aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-07-18 10:58:45 +0200
committerRob Austein <sra@hactrn.net>2015-07-18 10:58:45 +0200
commit809f0c7e9a4c49aa52b77ec2ab58a970a3ade389 (patch)
tree238b49eaf0b923ad158ac4e3f9df112db369b7de
parentb96b3aeb4ac1fae68e77bb38a1553855b8ef16f7 (diff)
Add support for dynamic allocation of hash and HMAC state, for cases
where it's unavoidable.
-rw-r--r--hal.h3
-rw-r--r--hash.c84
2 files changed, 79 insertions, 8 deletions
diff --git a/hal.h b/hal.h
index 15ab8f9..7aeed42 100644
--- a/hal.h
+++ b/hal.h
@@ -567,6 +567,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 af461a6..45e2f59 100644
--- a/hash.c
+++ b/hash.c
@@ -89,8 +89,11 @@ typedef struct {
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
@@ -276,20 +279,47 @@ 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;
return HAL_OK;
}
/*
+ * 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.
*/
@@ -519,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
@@ -541,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
@@ -557,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.
@@ -567,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
@@ -588,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;
}
/*