aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-09-08 13:13:48 -0400
committerRob Austein <sra@hactrn.net>2015-09-08 13:13:48 -0400
commit5106b886fe0d8af948bf28be2a571c247afc6020 (patch)
tree79c88af459e5e73d2ad38990ec19e37d0aeb32ce
parentc334ad5442340a6f6ba22d3d56970b7fe376df6b (diff)
parent809f0c7e9a4c49aa52b77ec2ab58a970a3ade389 (diff)
Merge branch 'state_access'
-rw-r--r--hal.h4
-rw-r--r--hash.c182
2 files changed, 146 insertions, 40 deletions
diff --git a/hal.h b/hal.h
index 4a31398..64377b4 100644
--- a/hal.h
+++ b/hal.h
@@ -511,6 +511,7 @@ typedef struct {
const uint8_t * const digest_algorithm_id;
size_t digest_algorithm_id_length;
const void *driver;
+ unsigned can_restore_state : 1;
} hal_hash_descriptor_t;
/*
@@ -560,6 +561,9 @@ extern hal_error_t hal_hmac_update(const hal_hmac_state_t state,
extern hal_error_t hal_hmac_finalize(const hal_hmac_state_t state,
uint8_t *hmac, const size_t length);
+extern void hal_hash_cleanup(hal_hash_state_t *state);
+
+extern void hal_hmac_cleanup(hal_hmac_state_t *state);
/*
* AES key wrap functions.
diff --git a/hash.c b/hash.c
index f48e079..45e2f59 100644
--- a/hash.c
+++ b/hash.c
@@ -76,7 +76,8 @@ typedef struct {
} driver_t;
/*
- * Hash state.
+ * Hash state. For now we assume that the only core state we need to
+ * save and restore is the current digest value.
*/
typedef struct {
@@ -84,11 +85,15 @@ typedef struct {
const driver_t *driver;
uint64_t msg_length_high; /* Total data hashed in this message */
uint64_t msg_length_low; /* (128 bits in SHA-512 cases) */
- uint8_t block[HAL_MAX_HASH_BLOCK_LENGTH]; /* Block we're accumulating */
+ uint8_t block[HAL_MAX_HASH_BLOCK_LENGTH], /* Block we're accumulating */
+ core_state[HAL_MAX_HASH_DIGEST_LENGTH]; /* Saved core state */
size_t block_used; /* How much of the block we've used */
unsigned block_count; /* Blocks sent */
+ unsigned flags;
} internal_hash_state_t;
+#define STATE_FLAG_STATE_ALLOCATED 0x1 /* State buffer dynamically allocated */
+
/*
* HMAC state. Right now this just holds the key block and a hash
* context; if and when we figure out how PCLSR the hash cores, we
@@ -185,42 +190,42 @@ const hal_hash_descriptor_t hal_hash_sha1[1] = {{
SHA1_BLOCK_LEN, SHA1_DIGEST_LEN,
sizeof(internal_hash_state_t), sizeof(internal_hmac_state_t),
dalgid_sha1, sizeof(dalgid_sha1),
- &sha1_driver
+ &sha1_driver, 0
}};
const hal_hash_descriptor_t hal_hash_sha256[1] = {{
SHA256_BLOCK_LEN, SHA256_DIGEST_LEN,
sizeof(internal_hash_state_t), sizeof(internal_hmac_state_t),
dalgid_sha256, sizeof(dalgid_sha256),
- &sha256_driver
+ &sha256_driver, 1
}};
const hal_hash_descriptor_t hal_hash_sha512_224[1] = {{
SHA512_BLOCK_LEN, SHA512_224_DIGEST_LEN,
sizeof(internal_hash_state_t), sizeof(internal_hmac_state_t),
dalgid_sha512_224, sizeof(dalgid_sha512_224),
- &sha512_224_driver
+ &sha512_224_driver, 0
}};
const hal_hash_descriptor_t hal_hash_sha512_256[1] = {{
SHA512_BLOCK_LEN, SHA512_256_DIGEST_LEN,
sizeof(internal_hash_state_t), sizeof(internal_hmac_state_t),
dalgid_sha512_256, sizeof(dalgid_sha512_256),
- &sha512_256_driver
+ &sha512_256_driver, 0
}};
const hal_hash_descriptor_t hal_hash_sha384[1] = {{
SHA512_BLOCK_LEN, SHA384_DIGEST_LEN,
sizeof(internal_hash_state_t), sizeof(internal_hmac_state_t),
dalgid_sha384, sizeof(dalgid_sha384),
- &sha384_driver
+ &sha384_driver, 0
}};
const hal_hash_descriptor_t hal_hash_sha512[1] = {{
SHA512_BLOCK_LEN, SHA512_DIGEST_LEN,
sizeof(internal_hash_state_t), sizeof(internal_hmac_state_t),
dalgid_sha512, sizeof(dalgid_sha512),
- &sha512_driver
+ &sha512_driver, 0
}};
/*
@@ -274,13 +279,21 @@ hal_error_t hal_hash_initialize(const hal_hash_descriptor_t * const descriptor,
const driver_t * const driver = check_driver(descriptor);
internal_hash_state_t *state = state_buffer;
- if (driver == NULL || state == NULL || opaque_state == NULL ||
- state_length < descriptor->hash_state_length)
+ if (driver == NULL || opaque_state == NULL)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ if (state_buffer != NULL && state_length < descriptor->hash_state_length)
return HAL_ERROR_BAD_ARGUMENTS;
+ if (state_buffer == NULL && (state = malloc(descriptor->hash_state_length)) == NULL)
+ return HAL_ERROR_ALLOCATION_FAILURE;
+
memset(state, 0, sizeof(*state));
state->descriptor = descriptor;
state->driver = driver;
+
+ if (state_buffer == NULL)
+ state->flags |= STATE_FLAG_STATE_ALLOCATED;
opaque_state->state = state;
@@ -288,10 +301,66 @@ hal_error_t hal_hash_initialize(const hal_hash_descriptor_t * const descriptor,
}
/*
+ * Clean up hash state. No-op unless memory was dynamically allocated.
+ */
+
+void hal_hash_cleanup(hal_hash_state_t *opaque_state)
+{
+ if (opaque_state == NULL)
+ return;
+
+ internal_hash_state_t *state = opaque_state->state;
+
+ if (state == NULL || (state->flags & STATE_FLAG_STATE_ALLOCATED) == 0)
+ return;
+
+ memset(state, 0, state->descriptor->hash_state_length);
+ free(state);
+ opaque_state->state = NULL;
+}
+
+/*
+ * Read hash result from core. At least for now, this also serves to
+ * read current hash state from core.
+ */
+
+static hal_error_t hash_read_digest(const driver_t * const driver,
+ uint8_t *digest,
+ const size_t digest_length)
+{
+ hal_error_t err;
+
+ assert(digest != NULL && digest_length % 4 == 0);
+
+ if ((err = hal_io_wait_valid(driver->status_addr)) != HAL_OK)
+ return err;
+
+ return hal_io_read(driver->digest_addr, digest, digest_length);
+}
+
+/*
+ * Write hash state back to core.
+ */
+
+static hal_error_t hash_write_digest(const driver_t * const driver,
+ const uint8_t * const digest,
+ const size_t digest_length)
+{
+ hal_error_t err;
+
+ assert(digest != NULL && digest_length % 4 == 0);
+
+ if ((err = hal_io_wait_ready(driver->status_addr)) != HAL_OK)
+ return err;
+
+ return hal_io_write(driver->digest_addr, digest, digest_length);
+}
+
+/*
* Send one block to a core.
*/
-static hal_error_t hash_write_block(const internal_hash_state_t * const state)
+static hal_error_t hash_write_block(internal_hash_state_t *state)
{
uint8_t ctrl_cmd[4];
hal_error_t err;
@@ -299,43 +368,38 @@ static hal_error_t hash_write_block(const internal_hash_state_t * const state)
assert(state != NULL && state->descriptor != NULL && state->driver != NULL);
assert(state->descriptor->block_length % 4 == 0);
+ assert(state->descriptor->digest_length <= sizeof(state->core_state) ||
+ !state->descriptor->can_restore_state);
+
if (debug)
fprintf(stderr, "[ %s ]\n", state->block_count == 0 ? "init" : "next");
- if ((err = hal_io_write(state->driver->block_addr, state->block, state->descriptor->block_length)) != HAL_OK)
+ if ((err = hal_io_wait_ready(state->driver->status_addr)) != HAL_OK)
+ return err;
+
+ if (state->descriptor->can_restore_state &&
+ state->block_count != 0 &&
+ (err = hash_write_digest(state->driver, state->core_state,
+ state->descriptor->digest_length)) != HAL_OK)
+ return err;
+
+ if ((err = hal_io_write(state->driver->block_addr, state->block,
+ state->descriptor->block_length)) != HAL_OK)
return err;
ctrl_cmd[0] = ctrl_cmd[1] = ctrl_cmd[2] = 0;
ctrl_cmd[3] = state->block_count == 0 ? CTRL_INIT : CTRL_NEXT;
ctrl_cmd[3] |= state->driver->ctrl_mode;
- /*
- * Not sure why we're waiting for ready here, but it's what the old
- * (read: tested) code did, so keep that behavior for now.
- */
-
if ((err = hal_io_write(state->driver->ctrl_addr, ctrl_cmd, sizeof(ctrl_cmd))) != HAL_OK)
return err;
- return hal_io_wait_valid(state->driver->status_addr);
-}
-
-/*
- * Read hash result from core.
- */
-
-static hal_error_t hash_read_digest(const driver_t * const driver,
- uint8_t *digest,
- const size_t digest_length)
-{
- hal_error_t err;
-
- assert(digest != NULL && digest_length % 4 == 0);
-
- if ((err = hal_io_wait_valid(driver->status_addr)) != HAL_OK)
+ if (state->descriptor->can_restore_state &&
+ (err = hash_read_digest(state->driver, state->core_state,
+ state->descriptor->digest_length)) != HAL_OK)
return err;
- return hal_io_read(driver->digest_addr, digest, digest_length);
+ return hal_io_wait_valid(state->driver->status_addr);
}
/*
@@ -485,15 +549,21 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
{
const driver_t * const driver = check_driver(descriptor);
internal_hmac_state_t *state = state_buffer;
- internal_hash_state_t *h = &state->hash_state;
hal_hash_state_t oh;
hal_error_t err;
int i;
- if (descriptor == NULL || driver == NULL || state == NULL || opaque_state == NULL ||
- state_length < descriptor->hmac_state_length)
+ if (driver == NULL || opaque_state == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
+ if (state_buffer != NULL && state_length < descriptor->hmac_state_length)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ if (state_buffer == NULL && (state = malloc(descriptor->hmac_state_length)) == NULL)
+ return HAL_ERROR_ALLOCATION_FAILURE;
+
+ internal_hash_state_t *h = &state->hash_state;
+
assert(descriptor->block_length <= sizeof(state->keybuf));
#if 0
@@ -507,7 +577,10 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
#endif
if ((err = hal_hash_initialize(descriptor, &oh, h, sizeof(*h))) != HAL_OK)
- return err;
+ goto fail;
+
+ if (state_buffer == NULL)
+ h->flags |= STATE_FLAG_STATE_ALLOCATED;
/*
* If the supplied HMAC key is longer than the hash block length, we
@@ -523,7 +596,7 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
else if ((err = hal_hash_update(oh, key, key_length)) != HAL_OK ||
(err = hal_hash_finalize(oh, state->keybuf, sizeof(state->keybuf))) != HAL_OK ||
(err = hal_hash_initialize(descriptor, &oh, h, sizeof(*h))) != HAL_OK)
- return err;
+ goto fail;
/*
* XOR the key with the IPAD value, then start the inner hash.
@@ -533,7 +606,7 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
state->keybuf[i] ^= HMAC_IPAD;
if ((err = hal_hash_update(oh, state->keybuf, descriptor->block_length)) != HAL_OK)
- return err;
+ goto fail;
/*
* Prepare the key for the final hash. Since we just XORed key with
@@ -554,6 +627,35 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
opaque_state->state = state;
return HAL_OK;
+
+ fail:
+ if (state_buffer == NULL)
+ free(state);
+ return err;
+}
+
+/*
+ * Clean up HMAC state. No-op unless memory was dynamically allocated.
+ */
+
+void hal_hmac_cleanup(hal_hmac_state_t *opaque_state)
+{
+ if (opaque_state == NULL)
+ return;
+
+ internal_hmac_state_t *state = opaque_state->state;
+
+ if (state == NULL)
+ return;
+
+ internal_hash_state_t *h = &state->hash_state;
+
+ if ((h->flags & STATE_FLAG_STATE_ALLOCATED) == 0)
+ return;
+
+ memset(state, 0, h->descriptor->hmac_state_length);
+ free(state);
+ opaque_state->state = NULL;
}
/*