aboutsummaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c180
1 files changed, 141 insertions, 39 deletions
diff --git a/hash.c b/hash.c
index ce086f4..e06278d 100644
--- a/hash.c
+++ b/hash.c
@@ -76,7 +76,8 @@ struct hal_hash_driver {
};
/*
- * Hash state.
+ * Hash state. For now we assume that the only core state we need to
+ * save and restore is the current digest value.
*/
struct hal_hash_state {
@@ -84,11 +85,15 @@ struct hal_hash_state {
const hal_hash_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;
};
+#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(hal_hash_state_t), sizeof(hal_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(hal_hash_state_t), sizeof(hal_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(hal_hash_state_t), sizeof(hal_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(hal_hash_state_t), sizeof(hal_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(hal_hash_state_t), sizeof(hal_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(hal_hash_state_t), sizeof(hal_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 hal_hash_driver_t * const driver = check_driver(descriptor);
hal_hash_state_t *state = state_buffer;
- if (driver == NULL || state == NULL || state_ == NULL ||
- state_length < descriptor->hash_state_length)
+ if (driver == NULL || 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;
*state_ = state;
@@ -288,6 +301,62 @@ 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 **state_)
+{
+ if (state_ == NULL)
+ return;
+
+ hal_hash_state_t *state = *state_;
+
+ if (state == NULL || (state->flags & STATE_FLAG_STATE_ALLOCATED) == 0)
+ return;
+
+ memset(state, 0, state->descriptor->hash_state_length);
+ free(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 hal_hash_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 hal_hash_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.
*/
@@ -299,43 +368,38 @@ static hal_error_t hash_write_block(hal_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 hal_hash_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);
}
/*
@@ -483,14 +547,20 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
{
const hal_hash_driver_t * const driver = check_driver(descriptor);
hal_hmac_state_t *state = state_buffer;
- hal_hash_state_t *h = NULL;
hal_error_t err;
int i;
- if (descriptor == NULL || driver == NULL || state == NULL || state_ == NULL ||
- state_length < descriptor->hmac_state_length)
+ if (descriptor == NULL || driver == NULL || 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;
+
+ hal_hash_state_t *h = &state->hash_state;
+
assert(descriptor->block_length <= sizeof(state->keybuf));
#if 0
@@ -505,7 +575,10 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
if ((err = hal_hash_initialize(descriptor, &h, &state->hash_state,
sizeof(state->hash_state))) != 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
@@ -522,7 +595,7 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
(err = hal_hash_finalize(h, state->keybuf, sizeof(state->keybuf))) != HAL_OK ||
(err = hal_hash_initialize(descriptor, &h, &state->hash_state,
sizeof(state->hash_state))) != HAL_OK)
- return err;
+ goto fail;
/*
* XOR the key with the IPAD value, then start the inner hash.
@@ -532,7 +605,7 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
state->keybuf[i] ^= HMAC_IPAD;
if ((err = hal_hash_update(h, state->keybuf, descriptor->block_length)) != HAL_OK)
- return err;
+ goto fail;
/*
* Prepare the key for the final hash. Since we just XORed key with
@@ -553,6 +626,35 @@ hal_error_t hal_hmac_initialize(const hal_hash_descriptor_t * const descriptor,
*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 **state_)
+{
+ if (state_ == NULL)
+ return;
+
+ hal_hmac_state_t *state = *state_;
+
+ if (state == NULL)
+ return;
+
+ hal_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);
+ *state_ = NULL;
}
/*