diff options
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 226 |
1 files changed, 119 insertions, 107 deletions
@@ -4,7 +4,7 @@ * HAL interface to Cryptech hash cores. * * Authors: Joachim Strömbergson, Paul Selkirk, Rob Austein - * Copyright (c) 2014-2016, NORDUnet A/S + * Copyright (c) 2014-2018, NORDUnet A/S * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -119,10 +119,12 @@ struct hal_hash_state { size_t block_used; /* How much of the block we've used */ unsigned block_count; /* Blocks sent */ unsigned flags; + hal_core_lru_t pomace; /* Private data for hal_core_alloc() */ }; -#define STATE_FLAG_STATE_ALLOCATED 0x1 /* State buffer dynamically allocated */ +#define STATE_FLAG_STATE_ALLOCATED 0x1 /* State buffer in use */ #define STATE_FLAG_SOFTWARE_CORE 0x2 /* Use software rather than hardware core */ +#define STATE_FLAG_FREE_CORE 0x4 /* Free core after use */ /* * HMAC state. Right now this just holds the key block and a hash @@ -330,7 +332,7 @@ static inline hal_hmac_state_t *alloc_static_hmac_state(void) * This is only used by the software hash cores, but it's simpler to define it unconditionally. */ -static inline void swytebop(void *out_, const void * const in_, const size_t n, const size_t w) +static inline hal_error_t swytebop(void *out_, const void * const in_, const size_t n, const size_t w) { const uint8_t order[] = { 0x01, 0x02, 0x03, 0x04 }; @@ -338,23 +340,24 @@ static inline void swytebop(void *out_, const void * const in_, const size_t n, uint8_t *out = out_; /* w must be a power of two */ - assert(in != out && in != NULL && out != NULL && w && !(w & (w - 1))); + hal_assert(in != out && in != NULL && out != NULL && w && !(w & (w - 1))); switch (* (uint32_t *) order) { case 0x01020304: memcpy(out, in, n); - return; + break; case 0x04030201: for (size_t i = 0; i < n; i += w) for (size_t j = 0; j < w && i + j < n; j++) out[i + j] = in[i + w - j - 1]; - return; + break; default: - assert((* (uint32_t *) order) == 0x01020304 || (* (uint32_t *) order) == 0x04030201); + hal_assert((* (uint32_t *) order) == 0x01020304 || (* (uint32_t *) order) == 0x04030201); } + return HAL_OK; } /* @@ -364,28 +367,37 @@ static inline void swytebop(void *out_, const void * const in_, const size_t n, static inline hal_error_t check_core(hal_core_t **core, const hal_hash_descriptor_t * const descriptor, - unsigned *flags) + unsigned *flags, + hal_core_lru_t *pomace) { - assert(descriptor != NULL && descriptor->driver != NULL); + if (core == NULL || descriptor == NULL || descriptor->driver == NULL || flags == NULL) + return HAL_ERROR_IMPOSSIBLE; -#if HAL_ONLY_USE_SOFTWARE_HASH_CORES hal_error_t err = HAL_ERROR_CORE_NOT_FOUND; -#else - hal_error_t err = hal_core_alloc(descriptor->core_name, core); -#endif -#if HAL_ENABLE_SOFTWARE_HASH_CORES - if ((err == HAL_ERROR_CORE_NOT_FOUND || err == HAL_ERROR_CORE_BUSY) && - descriptor->driver->sw_core) { +#if !HAL_ONLY_USE_SOFTWARE_HASH_CORES + + if (*core != NULL) + return HAL_OK; - *core = NULL; + if ((err = hal_core_alloc(descriptor->core_name, core, pomace)) == HAL_OK) { + *flags |= STATE_FLAG_FREE_CORE; + return HAL_OK; + } + +#endif - if (flags != NULL) - *flags |= STATE_FLAG_SOFTWARE_CORE; + if (*core != NULL) + return HAL_ERROR_IMPOSSIBLE; - err = HAL_OK; +#if HAL_ENABLE_SOFTWARE_HASH_CORES + + if (descriptor->driver->sw_core && err == HAL_ERROR_CORE_NOT_FOUND) { + *flags |= STATE_FLAG_SOFTWARE_CORE; + return HAL_OK; } -#endif /* HAL_ENABLE_SOFTWARE_HASH_CORES */ + +#endif return err; } @@ -414,6 +426,7 @@ hal_error_t hal_hash_initialize(hal_core_t *core, { const hal_hash_driver_t * const driver = check_driver(descriptor); hal_hash_state_t *state = state_buffer; + hal_core_lru_t pomace = 0; unsigned flags = 0; hal_error_t err; @@ -423,18 +436,15 @@ hal_error_t hal_hash_initialize(hal_core_t *core, if (state_buffer != NULL && state_length < descriptor->hash_state_length) return HAL_ERROR_BAD_ARGUMENTS; - if ((err = check_core(&core, descriptor, &flags)) != HAL_OK) + if ((err = check_core(&core, descriptor, &flags, &pomace)) != HAL_OK) return err; -#if ! HAL_ONLY_USE_SOFTWARE_HASH_CORES - /* - * If we're using a Verilog core that can save/restore state, then we - * free it after every operation, so that it can possibly be used by - * another client. - */ - if (descriptor->can_restore_state) - hal_core_free(core); -#endif + if ((flags & STATE_FLAG_FREE_CORE) != 0) + hal_core_free(core); + + /* A dynamically allocated core that can't restore state isn't going to work. */ + if (!state->descriptor->can_restore_state && (flags & STATE_FLAG_FREE_CORE) != 0) + return HAL_ERROR_BAD_ARGUMENTS; if (state_buffer == NULL && (state = alloc_static_hash_state()) == NULL) return HAL_ERROR_ALLOCATION_FAILURE; @@ -444,6 +454,7 @@ hal_error_t hal_hash_initialize(hal_core_t *core, state->driver = driver; state->core = core; state->flags = flags | STATE_FLAG_STATE_ALLOCATED; + state->pomace = pomace; *state_ = state; @@ -451,21 +462,17 @@ hal_error_t hal_hash_initialize(hal_core_t *core, } /* - * Clean up hash state. No-op unless memory was dynamically allocated. + * Clean up hash state. */ -void hal_hash_cleanup(hal_hash_state_t **state_) +void hal_hash_cleanup(hal_hash_state_t **state) { - if (state_ == NULL) + if (state == NULL || *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); - memset(state, 0, state->descriptor->hash_state_length); - *state_ = NULL; + *state = NULL; } #if ! HAL_ONLY_USE_SOFTWARE_HASH_CORES @@ -482,7 +489,7 @@ static hal_error_t hash_read_digest(const hal_core_t *core, { hal_error_t err; - assert(digest != NULL && digest_length % 4 == 0); + hal_assert(digest != NULL && digest_length % 4 == 0); if ((err = hal_io_wait_valid(core)) != HAL_OK) return err; @@ -501,7 +508,7 @@ static hal_error_t hash_write_digest(const hal_core_t *core, { hal_error_t err; - assert(digest != NULL && digest_length % 4 == 0); + hal_assert(digest != NULL && digest_length % 4 == 0); if ((err = hal_io_wait_ready(core)) != HAL_OK) return err; @@ -517,14 +524,14 @@ static hal_error_t hash_write_digest(const hal_core_t *core, 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); + hal_assert(state != NULL && state->descriptor != NULL && state->driver != NULL); + hal_assert(state->descriptor->block_length % 4 == 0); - assert(state->descriptor->digest_length <= sizeof(state->core_state) || - !state->descriptor->can_restore_state); + hal_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"); + hal_log(HAL_LOG_DEBUG, "[ %s ]\n", state->block_count == 0 ? "init" : "next"); #if HAL_ENABLE_SOFTWARE_HASH_CORES if ((state->flags & STATE_FLAG_SOFTWARE_CORE) != 0) @@ -585,22 +592,25 @@ hal_error_t hal_hash_update(hal_hash_state_t *state, /* Opaque state if (data_buffer_length == 0) return HAL_OK; - assert(state->descriptor != NULL && state->driver != NULL); - assert(state->descriptor->block_length <= sizeof(state->block)); + hal_assert(state->descriptor != NULL && state->driver != NULL); + hal_assert(state->descriptor->block_length <= sizeof(state->block)); -#if ! HAL_ONLY_USE_SOFTWARE_HASH_CORES - if (((state->flags & STATE_FLAG_SOFTWARE_CORE) == 0) && - state->descriptor->can_restore_state && - (err = hal_core_alloc(state->descriptor->core_name, &state->core)) != HAL_OK) + if ((state->flags & STATE_FLAG_FREE_CORE) != 0) { + err = hal_core_alloc(state->descriptor->core_name, &state->core, &state->pomace); + if (err == HAL_ERROR_CORE_REASSIGNED) { + state->core = NULL; + err = hal_core_alloc(state->descriptor->core_name, &state->core, &state->pomace); + } + if (err != HAL_OK) return err; -#endif + } while ((n = state->descriptor->block_length - state->block_used) <= data_buffer_length) { /* * We have enough data for another complete block. */ if (debug) - fprintf(stderr, "[ Full block, data_buffer_length %lu, used %lu, n %lu, msg_length %llu ]\n", + hal_log(HAL_LOG_DEBUG, "[ Full block, data_buffer_length %lu, used %lu, n %lu, msg_length %llu ]\n", (unsigned long) data_buffer_length, (unsigned long) state->block_used, (unsigned long) n, (unsigned long long)state->msg_length_low); memcpy(state->block + state->block_used, p, n); if ((state->msg_length_low += n) < n) @@ -618,9 +628,9 @@ hal_error_t hal_hash_update(hal_hash_state_t *state, /* Opaque state * Data left over, but not enough for a full block, stash it. */ if (debug) - fprintf(stderr, "[ Partial block, data_buffer_length %lu, used %lu, n %lu, msg_length %llu ]\n", + hal_log(HAL_LOG_DEBUG, "[ Partial block, data_buffer_length %lu, used %lu, n %lu, msg_length %llu ]\n", (unsigned long) data_buffer_length, (unsigned long) state->block_used, (unsigned long) n, (unsigned long long)state->msg_length_low); - assert(data_buffer_length < n); + hal_assert(data_buffer_length < n); memcpy(state->block + state->block_used, p, data_buffer_length); if ((state->msg_length_low += data_buffer_length) < data_buffer_length) state->msg_length_high++; @@ -628,10 +638,8 @@ hal_error_t hal_hash_update(hal_hash_state_t *state, /* Opaque state } out: -#if ! HAL_ONLY_USE_SOFTWARE_HASH_CORES - if (state->descriptor->can_restore_state) + if ((state->flags & STATE_FLAG_FREE_CORE) != 0) hal_core_free(state->core); -#endif return err; } @@ -652,19 +660,22 @@ hal_error_t hal_hash_finalize(hal_hash_state_t *state, /* Opaqu if (state == NULL || digest_buffer == NULL) return HAL_ERROR_BAD_ARGUMENTS; - assert(state->descriptor != NULL && state->driver != NULL); + hal_assert(state->descriptor != NULL && state->driver != NULL); if (digest_buffer_length < state->descriptor->digest_length) return HAL_ERROR_BAD_ARGUMENTS; - assert(state->descriptor->block_length <= sizeof(state->block)); + hal_assert(state->descriptor->block_length <= sizeof(state->block)); -#if ! HAL_ONLY_USE_SOFTWARE_HASH_CORES - if (((state->flags & STATE_FLAG_SOFTWARE_CORE) == 0) && - state->descriptor->can_restore_state && - (err = hal_core_alloc(state->descriptor->core_name, &state->core)) != HAL_OK) + if ((state->flags & STATE_FLAG_FREE_CORE) != 0) { + err = hal_core_alloc(state->descriptor->core_name, &state->core, &state->pomace); + if (err == HAL_ERROR_CORE_REASSIGNED) { + state->core = NULL; + err = hal_core_alloc(state->descriptor->core_name, &state->core, &state->pomace); + } + if (err != HAL_OK) return err; -#endif + } /* * Add padding, then pull result from the core @@ -674,13 +685,13 @@ hal_error_t hal_hash_finalize(hal_hash_state_t *state, /* Opaqu bit_length_high = (state->msg_length_high << 3) | (state->msg_length_low >> 61); /* Initial pad byte */ - assert(state->block_used < state->descriptor->block_length); + hal_assert(state->block_used < state->descriptor->block_length); state->block[state->block_used++] = 0x80; /* If not enough room for bit count, zero and push current block */ if ((n = state->descriptor->block_length - state->block_used) < state->driver->length_length) { if (debug) - fprintf(stderr, "[ Overflow block, used %lu, n %lu, msg_length %llu ]\n", + hal_log(HAL_LOG_DEBUG, "[ Overflow block, used %lu, n %lu, msg_length %llu ]\n", (unsigned long) state->block_used, (unsigned long) n, (unsigned long long)state->msg_length_low); if (n > 0) memset(state->block + state->block_used, 0, n); @@ -692,11 +703,11 @@ hal_error_t hal_hash_finalize(hal_hash_state_t *state, /* Opaqu /* Pad final block */ n = state->descriptor->block_length - state->block_used; - assert(n >= state->driver->length_length); + hal_assert(n >= state->driver->length_length); if (n > 0) memset(state->block + state->block_used, 0, n); if (debug) - fprintf(stderr, "[ Final block, used %lu, n %lu, msg_length %llu ]\n", + hal_log(HAL_LOG_DEBUG, "[ Final block, used %lu, n %lu, msg_length %llu ]\n", (unsigned long) state->block_used, (unsigned long) n, (unsigned long long)state->msg_length_low); p = state->block + state->descriptor->block_length; for (i = 0; (bit_length_low || bit_length_high) && i < state->driver->length_length; i++) { @@ -715,10 +726,9 @@ hal_error_t hal_hash_finalize(hal_hash_state_t *state, /* Opaqu /* All data pushed to core, now we just need to read back the result */ #if HAL_ENABLE_SOFTWARE_HASH_CORES - if ((state->flags & STATE_FLAG_SOFTWARE_CORE) != 0) { - swytebop(digest_buffer, state->core_state, state->descriptor->digest_length, state->driver->sw_word_size); - return HAL_OK; - } + if ((state->flags & STATE_FLAG_SOFTWARE_CORE) != 0) + return swytebop(digest_buffer, state->core_state, state->descriptor->digest_length, + state->driver->sw_word_size); #endif #if ! HAL_ONLY_USE_SOFTWARE_HASH_CORES if ((state->flags & STATE_FLAG_SOFTWARE_CORE) == 0) @@ -726,9 +736,8 @@ hal_error_t hal_hash_finalize(hal_hash_state_t *state, /* Opaqu #endif out: -#if ! HAL_ONLY_USE_SOFTWARE_HASH_CORES - hal_core_free(state->core); -#endif + if ((state->flags & STATE_FLAG_FREE_CORE) != 0) + hal_core_free(state->core); return err; } @@ -758,7 +767,7 @@ hal_error_t hal_hmac_initialize(hal_core_t *core, hal_hash_state_t *h = &state->hash_state; - assert(descriptor->block_length <= sizeof(state->keybuf)); + hal_assert(descriptor->block_length <= sizeof(state->keybuf)); #if 0 /* @@ -828,26 +837,17 @@ hal_error_t hal_hmac_initialize(hal_core_t *core, } /* - * Clean up HMAC state. No-op unless memory was dynamically allocated. + * Clean up HMAC state. */ -void hal_hmac_cleanup(hal_hmac_state_t **state_) +void hal_hmac_cleanup(hal_hmac_state_t **state) { - if (state_ == NULL) - return; - - hal_hmac_state_t *state = *state_; - - if (state == NULL) + if (state == NULL || *state == NULL) return; - hal_hash_state_t *h = &state->hash_state; + memset(*state, 0, (*state)->hash_state.descriptor->hmac_state_length); - if ((h->flags & STATE_FLAG_STATE_ALLOCATED) == 0) - return; - - memset(state, 0, h->descriptor->hmac_state_length); - *state_ = NULL; + *state = NULL; } /* @@ -878,15 +878,19 @@ hal_error_t hal_hmac_finalize(hal_hmac_state_t *state, uint8_t d[HAL_MAX_HASH_DIGEST_LENGTH]; hal_error_t err; - assert(descriptor != NULL && descriptor->digest_length <= sizeof(d)); + hal_assert(descriptor != NULL && descriptor->digest_length <= sizeof(d)); /* * Finish up inner hash and extract digest, then perform outer hash * to get HMAC. Key was prepared for this in hal_hmac_initialize(). + * + * For silly reasons, reusing the core value from the hash state + * block here would require nontrivial refactoring, so for the + * moment pass NULL and let the core allocator deal. Fix someday. */ if ((err = hal_hash_finalize(h, d, sizeof(d))) != HAL_OK || - (err = hal_hash_initialize(h->core, descriptor, &h, &state->hash_state, + (err = hal_hash_initialize(NULL, descriptor, &h, &state->hash_state, sizeof(state->hash_state))) != HAL_OK || (err = hal_hash_update(h, state->keybuf, descriptor->block_length)) != HAL_OK || (err = hal_hash_update(h, d, descriptor->digest_length)) != HAL_OK || @@ -971,12 +975,12 @@ static const uint64_t sha512_K[80] = { * confusing enough without adding a lot of unnecessary C macro baggage). */ -static inline uint32_t rot_l_32(uint32_t x, unsigned n) { assert(n < 32); return ((x << n) | (x >> (32 - n))); } -static inline uint32_t rot_r_32(uint32_t x, unsigned n) { assert(n < 32); return ((x >> n) | (x << (32 - n))); } -static inline uint32_t lsh_r_32(uint32_t x, unsigned n) { assert(n < 32); return (x >> n); } +static inline uint32_t rot_l_32(uint32_t x, unsigned n) { return ((x << n) | (x >> (32 - n))); } +static inline uint32_t rot_r_32(uint32_t x, unsigned n) { return ((x >> n) | (x << (32 - n))); } +static inline uint32_t lsh_r_32(uint32_t x, unsigned n) { return (x >> n); } -static inline uint64_t rot_r_64(uint64_t x, unsigned n) { assert(n < 64); return ((x >> n) | (x << (64 - n))); } -static inline uint64_t lsh_r_64(uint64_t x, unsigned n) { assert(n < 64); return (x >> n); } +static inline uint64_t rot_r_64(uint64_t x, unsigned n) { return ((x >> n) | (x << (64 - n))); } +static inline uint64_t lsh_r_64(uint64_t x, unsigned n) { return (x >> n); } static inline uint32_t Choose_32( uint32_t x, uint32_t y, uint32_t z) { return (z ^ (x & (y ^ z))); } static inline uint32_t Majority_32(uint32_t x, uint32_t y, uint32_t z) { return ((x & y) | (z & (x | y))); } @@ -999,8 +1003,8 @@ static inline uint64_t Gamma1_64(uint64_t x) { return rot_r_64(x, 19) ^ rot_r_64 * Offset into hash state. In theory, this should works out to compile-time constants after optimization. */ -static inline int sha1_pos(int i, int j) { assert(i >= 0 && j >= 0 && j < 5); return (5 + j - (i % 5)) % 5; } -static inline int sha2_pos(int i, int j) { assert(i >= 0 && j >= 0 && j < 8); return (8 + j - (i % 8)) % 8; } +static inline int sha1_pos(int i, int j) { return (5 + j - (i % 5)) % 5; } +static inline int sha2_pos(int i, int j) { return (8 + j - (i % 8)) % 8; } /* * Software implementation of SHA-1 block algorithm. @@ -1009,6 +1013,7 @@ static inline int sha2_pos(int i, int j) { assert(i >= 0 && j >= 0 && j < 8); re static hal_error_t sw_hash_core_sha1(hal_hash_state_t *state) { static const uint32_t iv[5] = {0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL, 0xc3d2e1f0UL}; + hal_error_t err; if (state == NULL) return HAL_ERROR_BAD_ARGUMENTS; @@ -1020,7 +1025,8 @@ static hal_error_t sw_hash_core_sha1(hal_hash_state_t *state) memcpy(S, H, sizeof(S)); - swytebop(W, state->block, 16 * sizeof(*W), sizeof(*W)); + if ((err = swytebop(W, state->block, 16 * sizeof(*W), sizeof(*W))) != HAL_OK) + return err; for (int i = 16; i < 80; i++) W[i] = rot_l_32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); @@ -1035,7 +1041,7 @@ static hal_error_t sw_hash_core_sha1(hal_hash_state_t *state) else f = Parity_32( S[b], S[c], S[d]), k = 0xCA62C1D6UL; if (debug) - fprintf(stderr, + hal_log(HAL_LOG_DEBUG, "[Round %02d < a = 0x%08x, b = 0x%08x, c = 0x%08x, d = 0x%08x, e = 0x%08x, f = 0x%08x, k = 0x%08x, w = 0x%08x]\n", i, (unsigned)S[a], (unsigned)S[b], (unsigned)S[c], (unsigned)S[d], (unsigned)S[e], (unsigned)f, (unsigned)k, (unsigned)W[i]); @@ -1043,7 +1049,7 @@ static hal_error_t sw_hash_core_sha1(hal_hash_state_t *state) S[b] = rot_l_32(S[b], 30); if (debug) - fprintf(stderr, "[Round %02d > a = 0x%08x, b = 0x%08x, c = 0x%08x, d = 0x%08x, e = 0x%08x]\n", + hal_log(HAL_LOG_DEBUG, "[Round %02d > a = 0x%08x, b = 0x%08x, c = 0x%08x, d = 0x%08x, e = 0x%08x]\n", i, (unsigned)S[a], (unsigned)S[b], (unsigned)S[c], (unsigned)S[d], (unsigned)S[e]); } @@ -1066,6 +1072,8 @@ static hal_error_t sw_hash_core_sha256(hal_hash_state_t *state) static const uint32_t sha256_iv[8] = {0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL}; + hal_error_t err; + if (state == NULL) return HAL_ERROR_BAD_ARGUMENTS; @@ -1081,7 +1089,8 @@ static hal_error_t sw_hash_core_sha256(hal_hash_state_t *state) memcpy(S, H, sizeof(S)); - swytebop(W, state->block, 16 * sizeof(*W), sizeof(*W)); + if ((err = swytebop(W, state->block, 16 * sizeof(*W), sizeof(*W))) != HAL_OK) + return err; for (int i = 16; i < 64; i++) W[i] = Gamma1_32(W[i - 2]) + W[i - 7] + Gamma0_32(W[i - 15]) + W[i - 16]; @@ -1123,6 +1132,8 @@ static hal_error_t sw_hash_core_sha512(hal_hash_state_t *state) sha512_256_iv[8] = {0x22312194FC2BF72CULL, 0x9F555FA3C84C64C2ULL, 0x2393B86B6F53B151ULL, 0x963877195940EABDULL, 0x96283EE2A88EFFE3ULL, 0xBE5E1E2553863992ULL, 0x2B0199FC2C85B8AAULL, 0x0EB72DDC81C52CA2ULL}; + hal_error_t err; + if (state == NULL) return HAL_ERROR_BAD_ARGUMENTS; @@ -1140,7 +1151,8 @@ static hal_error_t sw_hash_core_sha512(hal_hash_state_t *state) memcpy(S, H, sizeof(S)); - swytebop(W, state->block, 16 * sizeof(*W), sizeof(*W)); + if ((err = swytebop(W, state->block, 16 * sizeof(*W), sizeof(*W))) != HAL_OK) + return err; for (int i = 16; i < 80; i++) W[i] = Gamma1_64(W[i - 2]) + W[i - 7] + Gamma0_64(W[i - 15]) + W[i - 16]; |