diff options
-rw-r--r-- | aes_keywrap.c | 19 | ||||
-rw-r--r-- | asn1.c | 21 | ||||
-rw-r--r-- | core.c | 233 | ||||
-rwxr-xr-x | cryptech_muxd | 12 | ||||
-rw-r--r-- | csprng.c | 8 | ||||
-rw-r--r-- | ecdsa.c | 71 | ||||
-rw-r--r-- | hal.h | 31 | ||||
-rw-r--r-- | hal_internal.h | 26 | ||||
-rw-r--r-- | hal_io_fmc.c | 35 | ||||
-rw-r--r-- | hash.c | 232 | ||||
-rw-r--r-- | ks.c | 19 | ||||
-rw-r--r-- | ks_attribute.c | 1 | ||||
-rw-r--r-- | ks_token.c | 1 | ||||
-rw-r--r-- | ks_volatile.c | 1 | ||||
-rw-r--r-- | locks.c | 31 | ||||
-rw-r--r-- | mkmif.c | 38 | ||||
-rw-r--r-- | modexp.c | 57 | ||||
-rw-r--r-- | pbkdf2.c | 9 | ||||
-rw-r--r-- | rpc_client.c | 8 | ||||
-rw-r--r-- | rpc_pkcs1.c | 8 | ||||
-rw-r--r-- | rpc_pkey.c | 55 | ||||
-rw-r--r-- | rpc_serial.c | 2 | ||||
-rw-r--r-- | rsa.c | 147 | ||||
-rw-r--r-- | slip.c | 2 | ||||
-rwxr-xr-x | tests/parallel-signatures.py | 57 | ||||
-rw-r--r-- | tests/test-rsa.c | 41 | ||||
-rw-r--r-- | uuid.c | 1 |
27 files changed, 660 insertions, 506 deletions
diff --git a/aes_keywrap.c b/aes_keywrap.c index 355cb0b..144ad68 100644 --- a/aes_keywrap.c +++ b/aes_keywrap.c @@ -45,7 +45,6 @@ #include <stdint.h> #include <string.h> -#include <assert.h> #include "hal.h" #include "hal_internal.h" @@ -132,7 +131,7 @@ static hal_error_t do_block(const hal_core_t *core, uint8_t *b1, uint8_t *b2) { hal_error_t err; - assert(b1 != NULL && b2 != NULL); + hal_assert(b1 != NULL && b2 != NULL); if ((err = hal_io_write(core, AES_ADDR_BLOCK0, b1, 8)) != HAL_OK || (err = hal_io_write(core, AES_ADDR_BLOCK2, b2, 8)) != HAL_OK || @@ -164,15 +163,16 @@ hal_error_t hal_aes_keywrap(hal_core_t *core, size_t *C_len) { const size_t calculated_C_len = hal_aes_keywrap_ciphertext_length(m); + const int free_core = core == NULL; hal_error_t err; size_t n; - assert(calculated_C_len % 8 == 0); + hal_assert(calculated_C_len % 8 == 0); if (Q == NULL || C == NULL || C_len == NULL || *C_len < calculated_C_len) return HAL_ERROR_BAD_ARGUMENTS; - if ((err = hal_core_alloc(AES_CORE_NAME, &core)) != HAL_OK) + if (free_core && (err = hal_core_alloc(AES_CORE_NAME, &core, NULL)) != HAL_OK) return err; if ((err = load_kek(core, K, K_len, KEK_encrypting)) != HAL_OK) @@ -215,7 +215,8 @@ hal_error_t hal_aes_keywrap(hal_core_t *core, } out: - hal_core_free(core); + if (free_core) + hal_core_free(core); return err; } @@ -226,13 +227,14 @@ out: * Q should be the same size as C. Q and C can overlap. */ -hal_error_t hal_aes_keyunwrap(hal_core_t * core, +hal_error_t hal_aes_keyunwrap(hal_core_t *core, const uint8_t *K, const size_t K_len, const uint8_t * const C, const size_t C_len, uint8_t *Q, size_t *Q_len) { + const int free_core = core == NULL; hal_error_t err; size_t n; size_t m; @@ -240,7 +242,7 @@ hal_error_t hal_aes_keyunwrap(hal_core_t * core, if (C == NULL || Q == NULL || C_len % 8 != 0 || C_len < 16 || Q_len == NULL || *Q_len < C_len) return HAL_ERROR_BAD_ARGUMENTS; - if ((err = hal_core_alloc(AES_CORE_NAME, &core)) != HAL_OK) + if (free_core && (err = hal_core_alloc(AES_CORE_NAME, &core, NULL)) != HAL_OK) return err; if ((err = load_kek(core, K, K_len, KEK_decrypting)) != HAL_OK) @@ -294,7 +296,8 @@ hal_error_t hal_aes_keyunwrap(hal_core_t * core, memmove(Q, Q + 8, m); out: - hal_core_free(core); + if (free_core) + hal_core_free(core); return err; } @@ -49,7 +49,6 @@ */ #include <stdint.h> -#include <assert.h> #include "hal.h" #include "hal_internal.h" @@ -197,7 +196,7 @@ hal_error_t hal_asn1_encode_integer(const fp_int * const bn, if (der == NULL || err != HAL_OK) return err; - assert(hlen + vlen <= der_max); + hal_assert(hlen + vlen <= der_max); der += hlen; if (leading_zero) @@ -240,7 +239,7 @@ hal_error_t hal_asn1_encode_uint32(const uint32_t n, if (der == NULL || err != HAL_OK) return err; - assert(hlen + vlen <= der_max); + hal_assert(hlen + vlen <= der_max); der += hlen; @@ -276,7 +275,7 @@ hal_error_t hal_asn1_encode_octet_string(const uint8_t * const data, const si if (der == NULL) return HAL_OK; - assert(hlen + data_len <= der_max); + hal_assert(hlen + data_len <= der_max); /* * Handle data early, in case it was staged into our output buffer. @@ -365,8 +364,8 @@ hal_error_t hal_asn1_encode_spki(const uint8_t * const alg_oid, const size_t a *d++ = 0x00; d += pubkey_len; /* pubkey handled early, above. */ - assert(d == der + hlen_spki + vlen); - assert(d <= der + der_max); + hal_assert(d == der + hlen_spki + vlen); + hal_assert(d <= der + der_max); return HAL_OK; } @@ -457,8 +456,8 @@ hal_error_t hal_asn1_encode_pkcs8_privatekeyinfo(const uint8_t * const alg_oid, d += hlen; d += privkey_len; /* privkey handled early, above. */ - assert(d == der_end); - assert(d <= der + der_max); + hal_assert(d == der_end); + hal_assert(d <= der + der_max); return HAL_OK; } @@ -525,8 +524,8 @@ hal_error_t hal_asn1_encode_pkcs8_encryptedprivatekeyinfo(const uint8_t * const d += data_len; /* data handled early, above. */ - assert(d == der + hlen_pkcs8 + vlen); - assert(d <= der + der_max); + hal_assert(d == der + hlen_pkcs8 + vlen); + hal_assert(d <= der + der_max); return HAL_OK; } @@ -542,7 +541,7 @@ hal_error_t hal_asn1_decode_header(const uint8_t tag, const uint8_t * const der, size_t der_max, size_t *hlen, size_t *vlen) { - assert(der != NULL && hlen != NULL && vlen != NULL); + hal_assert(der != NULL && hlen != NULL && vlen != NULL); if (der_max < 2 || der[0] != tag) return HAL_ERROR_ASN1_PARSE_FAILED; @@ -56,16 +56,15 @@ extern size_t strnlen(const char *, size_t); struct hal_core { hal_core_info_t info; - uint32_t busy; + int busy; + hal_core_lru_t lru; struct hal_core *next; }; -#ifndef HAL_STATIC_CORE_STATE_BLOCKS -#define HAL_STATIC_CORE_STATE_BLOCKS 0 -#endif - -#if HAL_STATIC_CORE_STATE_BLOCKS > 0 +#if defined(HAL_STATIC_CORE_STATE_BLOCKS) && HAL_STATIC_CORE_STATE_BLOCKS > 0 static hal_core_t core_table[HAL_STATIC_CORE_STATE_BLOCKS]; +#else +#error HAL_STATIC_CORE_STATE_BLOCKS must be defined as a positive integer #endif /* @@ -73,7 +72,7 @@ static hal_core_t core_table[HAL_STATIC_CORE_STATE_BLOCKS]; * bit nasty due to non-null-terminated fixed-length names. */ -static int name_matches(const hal_core_t *const core, const char * const name) +static inline int name_matches(const hal_core_t *const core, const char * const name) { return (core != NULL && name != NULL && *name != '\0' && strncmp(name, core->info.name, strnlen(name, sizeof(core->info.name))) == 0); @@ -92,39 +91,34 @@ static int name_matches(const hal_core_t *const core, const char * const name) #define CORE_MAX 0x10000 #define CORE_SIZE 0x100 -/* Extra space to leave after particular cores. Yummy. */ - -static const struct { const char *name; hal_addr_t extra; } gaps[] = { - { "csprng", 11 * CORE_SIZE }, /* empty slots after csprng */ - { "modexps6", 3 * CORE_SIZE }, /* ModexpS6 uses four slots */ - { "modexpa7", 7 * CORE_SIZE }, /* ModexpA7 uses eight slots */ -}; - static hal_core_t *head = NULL; +static hal_core_lru_t lru = 0; -static hal_core_t *probe_cores(void) +static inline hal_core_t *probe_cores(void) { + /* Extra space to leave after particular cores. Yummy. */ + static const struct { const char *name; hal_addr_t extra; } gaps[] = { + { "csprng", 11 * CORE_SIZE }, /* empty slots after csprng */ + { "modexps6", 3 * CORE_SIZE }, /* ModexpS6 uses four slots */ + { "modexpa7", 7 * CORE_SIZE }, /* ModexpA7 uses eight slots */ + }; + + if (offsetof(hal_core_t, info) != 0) + return NULL; /* Paranoia, see hal.h */ + if (head != NULL) return head; - hal_core_t *core = NULL; hal_core_t **tail = &head; hal_error_t err = HAL_OK; -#if HAL_STATIC_CORE_STATE_BLOCKS > 0 - int n = 0; -#endif + hal_addr_t addr; + int n; - for (hal_addr_t addr = CORE_MIN; addr < CORE_MAX; addr += CORE_SIZE) { - -#if HAL_STATIC_CORE_STATE_BLOCKS > 0 - core = &core_table[n]; -#else - if (core == NULL && (core = malloc(sizeof(hal_core_t))) == NULL) { - err = HAL_ERROR_ALLOCATION_FAILURE; - goto fail; - } -#endif + for (addr = CORE_MIN, n = 0; + addr < CORE_MAX && n < HAL_STATIC_CORE_STATE_BLOCKS; + addr += CORE_SIZE, n++) { + hal_core_t *core = &core_table[n]; memset(core, 0, sizeof(*core)); core->info.base = addr; @@ -144,48 +138,19 @@ static hal_core_t *probe_cores(void) *tail = core; tail = &core->next; - core = NULL; - -#if HAL_STATIC_CORE_STATE_BLOCKS > 0 - if (++n >= HAL_STATIC_CORE_STATE_BLOCKS) - break; -#endif } -#if HAL_STATIC_CORE_STATE_BLOCKS > 0 -#else - if (core != NULL) - free(core); -#endif - return head; fail: -#if HAL_STATIC_CORE_STATE_BLOCKS > 0 memset(core_table, 0, sizeof(core_table)); -#else - if (core != NULL) - free(core); - while ((core = head) != NULL) { - head = core->next; - free(core); - } -#endif return NULL; } void hal_core_reset_table(void) { -#if HAL_STATIC_CORE_STATE_BLOCKS > 0 - head = NULL; - memset(core_table, 0, sizeof(core_table)); -#else - while (head != NULL) { - hal_core_t *next = head->next; - free(head); - head = next; - } -#endif + head = NULL; + memset(core_table, 0, sizeof(core_table)); } hal_core_t * hal_core_iterate(hal_core_t *core) @@ -201,76 +166,133 @@ hal_core_t *hal_core_find(const char *name, hal_core_t *core) return NULL; } -static hal_error_t hal_core_alloc_no_wait(const char *name, hal_core_t **pcore) -{ - /* - * This used to allow name == NULL iff *core != NULL, but the - * semantics were fragile and in practice we always pass a name - * anyway, so simplify by requiring name != NULL, always. - */ +/* + * If caller specifies a non-NULL core value, we fail unless that core + * is available and has the right name and lru values. + * + * If caller specifies a NULL core value, we take any free core with + * the right name. + * + * Modification of lru field is handled by the jacket routines, to + * avoid premature updates. + */ - if (name == NULL || pcore == NULL) +static hal_error_t hal_core_alloc_no_wait(const char *name, hal_core_t **pcore, hal_core_lru_t *pomace) +{ + if (name == NULL || pcore == NULL || (*pcore != NULL && pomace == NULL)) return HAL_ERROR_BAD_ARGUMENTS; hal_error_t err = HAL_ERROR_CORE_NOT_FOUND; hal_core_t *core = *pcore; + hal_core_t *best = NULL; + uint32_t age = 0; + + hal_critical_section_start(); + /* + * User wants to reuse previous core, grab that core or or bust. + * Never return CORE_BUSY in this case, because busy implies + * somebody else has touched it. Checking the name in this case + * isn't strictly necessary, but it's cheap insurance. + */ if (core != NULL) { - /* if we can reallocate the same core, do it now */ - if (!core->busy) { - hal_critical_section_start(); + if (core->busy || core->lru != *pomace) + err = HAL_ERROR_CORE_REASSIGNED; + else if (!name_matches(core, name)) + err = HAL_ERROR_CORE_NOT_FOUND; + else { core->busy = 1; - hal_critical_section_end(); - return HAL_OK; + err = HAL_OK; } - /* else forget that core and fall through to search */ - *pcore = NULL; } - hal_critical_section_start(); - for (core = hal_core_find(name, NULL); core != NULL; core = hal_core_find(name, core)) { - if (core->busy) { - err = HAL_ERROR_CORE_BUSY; - continue; + /* + * User just wants a core with the right name, search for least recently used matching core. + */ + else { + for (core = hal_core_find(name, NULL); core != NULL; core = hal_core_find(name, core)) { + if (core->busy && err == HAL_ERROR_CORE_NOT_FOUND) { + err = HAL_ERROR_CORE_BUSY; + } + else if (!core->busy && (lru - core->lru) >= age) { + best = core; + age = (lru - core->lru); + } + } + if (best != NULL) { + *pcore = best; + best->busy = 1; + err = HAL_OK; } - err = HAL_OK; - *pcore = core; - core->busy = 1; - break; } + hal_critical_section_end(); return err; } -hal_error_t hal_core_alloc(const char *name, hal_core_t **pcore) +hal_error_t hal_core_alloc(const char *name, hal_core_t **pcore, hal_core_lru_t *pomace) { hal_error_t err; - while ((err = hal_core_alloc_no_wait(name, pcore)) == HAL_ERROR_CORE_BUSY) + while ((err = hal_core_alloc_no_wait(name, pcore, pomace)) == HAL_ERROR_CORE_BUSY) hal_task_yield(); - return err; + if (err != HAL_OK) + return err; + + (*pcore)->lru = ++lru; + + if (pomace != NULL) + *pomace = (*pcore)->lru; + + return HAL_OK; } -hal_error_t hal_core_alloc2(const char *name1, hal_core_t **pcore1, - const char *name2, hal_core_t **pcore2) +hal_error_t hal_core_alloc2(const char *name1, hal_core_t **pcore1, hal_core_lru_t *pomace1, + const char *name2, hal_core_t **pcore2, hal_core_lru_t *pomace2) { - hal_error_t err; + const int clear = pcore1 != NULL && *pcore1 == NULL; + + for (;;) { + + hal_error_t err = hal_core_alloc_no_wait(name1, pcore1, pomace1); + + switch (err) { + + case HAL_OK: + break; - while (1) { - if ((err = hal_core_alloc(name1, pcore1)) != HAL_OK) + case HAL_ERROR_CORE_BUSY: + hal_task_yield(); + continue; + + default: return err; + } + + if ((err = hal_core_alloc_no_wait(name2, pcore2, pomace2)) == HAL_OK) + break; - if ((err = hal_core_alloc_no_wait(name2, pcore2)) == HAL_OK) - return HAL_OK; - - hal_core_free(*pcore1); - /* hal_core_free does a yield, so we don't need to do another one */ + hal_core_free(*pcore1); /* hal_core_free does a yield, so we don't need to do another one */ + + if (clear) /* put *pcore1 back as we found it */ + *pcore1 = NULL; if (err != HAL_ERROR_CORE_BUSY) return err; } + + (*pcore1)->lru = ++lru; + (*pcore2)->lru = ++lru; + + if (pomace1 != NULL) + *pomace1 = (*pcore1)->lru; + + if (pomace2 != NULL) + *pomace2 = (*pcore2)->lru; + + return HAL_OK; } void hal_core_free(hal_core_t *core) @@ -283,21 +305,6 @@ void hal_core_free(hal_core_t *core) } } -hal_addr_t hal_core_base(const hal_core_t *core) -{ - return core == NULL ? 0 : core->info.base; -} - -const hal_core_info_t *hal_core_info(const hal_core_t *core) -{ - return core == NULL ? NULL : &core->info; -} - -int hal_core_busy(const hal_core_t *core) -{ - return (int)core->busy; -} - /* * Local variables: * indent-tabs-mode: nil diff --git a/cryptech_muxd b/cryptech_muxd index d306eaf..1aecb1e 100755 --- a/cryptech_muxd +++ b/cryptech_muxd @@ -419,6 +419,10 @@ def main(): default = os.getenv("CRYPTECH_RPC_CLIENT_SOCKET_NAME", "/tmp/.cryptech_muxd.rpc")) + parser.add_argument("--rpc-socket-mode", + help = "permission bits for RPC socket inode", + default = 0600, type = lambda s: int(s, 8)) + parser.add_argument("--cty-device", help = "CTY serial device name", default = os.getenv("CRYPTECH_CTY_CLIENT_SERIAL_DEVICE")) @@ -428,6 +432,10 @@ def main(): default = os.getenv("CRYPTECH_CTY_CLIENT_SOCKET_NAME", "/tmp/.cryptech_muxd.cty")) + parser.add_argument("--cty-socket-mode", + help = "permission bits for CTY socket inode", + default = 0600, type = lambda s: int(s, 8)) + args = parser.parse_args() if args.log_file is not None: @@ -454,7 +462,7 @@ def main(): logger.warn("No RPC device found") else: rpc_stream = RPCIOStream(device = args.rpc_device) - rpc_server = RPCServer(rpc_stream, args.rpc_socket) + rpc_server = RPCServer(rpc_stream, args.rpc_socket, args.rpc_socket_mode) futures.append(rpc_stream.rpc_output_loop()) futures.append(rpc_stream.logout_all()) @@ -462,7 +470,7 @@ def main(): logger.warn("No CTY device found") else: cty_stream = CTYIOStream(device = args.cty_device, console_log = console_log) - cty_server = CTYServer(cty_stream, args.cty_socket) + cty_server = CTYServer(cty_stream, args.cty_socket, args.cty_socket_mode) futures.append(cty_stream.cty_output_loop()) # Might want to use WaitIterator(dict(...)) here so we can @@ -46,9 +46,10 @@ hal_error_t hal_get_random(hal_core_t *core, void *buffer, const size_t length) { uint8_t temp[4], ior = 0, * const buf = buffer; - hal_error_t err; + const int free_core = core == NULL; + hal_error_t err = HAL_OK; - if ((err = hal_core_alloc(CSPRNG_NAME, &core)) != HAL_OK) + if (free_core && (err = hal_core_alloc(CSPRNG_NAME, &core, NULL)) != HAL_OK) return err; for (size_t i = 0; i < length; i += 4) { @@ -73,7 +74,8 @@ hal_error_t hal_get_random(hal_core_t *core, void *buffer, const size_t length) err = HAL_ERROR_CSPRNG_BROKEN; } - hal_core_free(core); + if (free_core) + hal_core_free(core); return err; } @@ -68,7 +68,6 @@ */ #include <stdint.h> -#include <assert.h> #include "hal.h" #include "hal_internal.h" @@ -354,8 +353,7 @@ static inline void ff_sqr(const ecdsa_curve_t * const curve, static inline int point_is_infinite(const ec_point_t * const P) { - assert(P != NULL); - return fp_iszero(P->z); + return P == NULL || fp_iszero(P->z); } /* @@ -367,9 +365,9 @@ static inline int point_is_infinite(const ec_point_t * const P) * infinity for that curve. */ -static inline void point_set_infinite(ec_point_t *P, const ecdsa_curve_t * const curve) +static inline hal_error_t point_set_infinite(ec_point_t *P, const ecdsa_curve_t * const curve) { - assert(P != NULL); + hal_assert(P != NULL); if (curve != NULL) { fp_copy(unconst_fp_int(curve->mu), P->x); @@ -382,6 +380,8 @@ static inline void point_set_infinite(ec_point_t *P, const ecdsa_curve_t * const fp_set(P->y, 1); fp_zero(P->z); } + + return HAL_OK; } /* @@ -403,7 +403,7 @@ static inline void point_copy(const ec_point_t * const P, ec_point_t *R) static inline hal_error_t point_to_montgomery(ec_point_t *P, const ecdsa_curve_t * const curve) { - assert(P != NULL && curve != NULL); + hal_assert(P != NULL && curve != NULL); if (fp_cmp_d(unconst_fp_int(P->z), 1) != FP_EQ) return HAL_ERROR_BAD_ARGUMENTS; @@ -431,7 +431,7 @@ static inline hal_error_t point_to_montgomery(ec_point_t *P, static inline hal_error_t point_to_affine(ec_point_t *P, const ecdsa_curve_t * const curve) { - assert(P != NULL && curve != NULL); + hal_assert(P != NULL && curve != NULL); if (point_is_infinite(P)) return HAL_ERROR_IMPOSSIBLE; @@ -475,11 +475,11 @@ static inline hal_error_t point_to_affine(ec_point_t *P, * http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html */ -static inline void point_double(const ec_point_t * const P, - ec_point_t *R, - const ecdsa_curve_t * const curve) +static inline hal_error_t point_double(const ec_point_t * const P, + ec_point_t *R, + const ecdsa_curve_t * const curve) { - assert(P != NULL && R != NULL && curve != NULL); + hal_assert(P != NULL && R != NULL && curve != NULL); const int was_infinite = point_is_infinite(P); @@ -520,9 +520,11 @@ static inline void point_double(const ec_point_t * const P, ff_add (curve, t2, t2, t2); ff_sub (curve, t1, t2, R->y); - assert(was_infinite == point_is_infinite(P)); + hal_assert(was_infinite == point_is_infinite(P)); fp_zero(alpha); fp_zero(beta); fp_zero(gamma); fp_zero(delta); fp_zero(t1); fp_zero(t2); + + return HAL_OK; } /** @@ -542,18 +544,18 @@ static inline void point_double(const ec_point_t * const P, * point doubling algorithm. */ -static inline void point_add(const ec_point_t * const P, - const ec_point_t * const Q, - ec_point_t *R, - const ecdsa_curve_t * const curve) +static inline hal_error_t point_add(const ec_point_t * const P, + const ec_point_t * const Q, + ec_point_t *R, + const ecdsa_curve_t * const curve) { - assert(P != NULL && Q != NULL && R != NULL && curve != NULL); + hal_assert(P != NULL && Q != NULL && R != NULL && curve != NULL); /* * Q must be affine in Montgomery form. */ - assert(fp_cmp(unconst_fp_int(Q->z), unconst_fp_int(curve->mu)) == FP_EQ); + hal_assert(fp_cmp(unconst_fp_int(Q->z), unconst_fp_int(curve->mu)) == FP_EQ); #warning What happens here if P and Q are not equal but map to the same point in affine space? @@ -640,6 +642,8 @@ static inline void point_add(const ec_point_t * const P, else if (result_is_infinite) point_set_infinite(R, curve); + + return HAL_OK; } /** @@ -658,7 +662,7 @@ static hal_error_t point_scalar_multiply(const fp_int * const k, ec_point_t *R, const ecdsa_curve_t * const curve) { - assert(k != NULL && P_ != NULL && R != NULL && curve != NULL); + hal_assert(k != NULL && P_ != NULL && R != NULL && curve != NULL); if (fp_iszero(k) || fp_cmp_d(unconst_fp_int(P_->z), 1) != FP_EQ) return HAL_ERROR_BAD_ARGUMENTS; @@ -787,7 +791,7 @@ static hal_error_t verilog_point_pick_random(const verilog_ecdsa_driver_t * cons fp_int *k, ec_point_t *P) { - assert(k != NULL && P != NULL); + hal_assert(k != NULL && P != NULL); const size_t len = fp_unsigned_bin_size(k); uint8_t b[driver->bytes]; @@ -798,7 +802,7 @@ static hal_error_t verilog_point_pick_random(const verilog_ecdsa_driver_t * cons if (len > sizeof(b)) return HAL_ERROR_RESULT_TOO_LONG; - if ((err = hal_core_alloc(driver->name, &core)) != HAL_OK) + if ((err = hal_core_alloc(driver->name, &core, NULL)) != HAL_OK) goto fail; #define check(_x_) do { if ((err = (_x_)) != HAL_OK) goto fail; } while (0) @@ -846,7 +850,7 @@ static hal_error_t point_pick_random(const ecdsa_curve_t * const curve, { hal_error_t err; - assert(curve != NULL && k != NULL && P != NULL); + hal_assert(curve != NULL && k != NULL && P != NULL); /* * Pick a random scalar corresponding to a point on the curve. Per @@ -933,7 +937,8 @@ static hal_error_t point_pick_random(const ecdsa_curve_t * const curve, static int point_is_on_curve(const ec_point_t * const P, const ecdsa_curve_t * const curve) { - assert(P != NULL && curve != NULL); + if (P == NULL || curve == NULL) + return 0; fp_int t1[1] = INIT_FP_INT; fp_int t2[1] = INIT_FP_INT; @@ -966,6 +971,8 @@ static int point_is_on_curve(const ec_point_t * const P, return fp_cmp(t1, unconst_fp_int(curve->b)) == FP_EQ; } +#warning hal_ecdsa_xxx() functions currently ignore core arguments, works but suboptimal, fix this + /* * Generate a new ECDSA key. */ @@ -1172,7 +1179,7 @@ hal_error_t hal_ecdsa_key_to_ecpoint(const hal_ecdsa_key_t * const key, const size_t q_len = fp_unsigned_bin_size(unconst_fp_int(curve->q)); const size_t Qx_len = fp_unsigned_bin_size(unconst_fp_int(key->Q->x)); const size_t Qy_len = fp_unsigned_bin_size(unconst_fp_int(key->Q->y)); - assert(q_len >= Qx_len && q_len >= Qy_len); + hal_assert(q_len >= Qx_len && q_len >= Qy_len); const size_t vlen = q_len * 2 + 1; size_t hlen; @@ -1185,7 +1192,7 @@ hal_error_t hal_ecdsa_key_to_ecpoint(const hal_ecdsa_key_t * const key, if (der == NULL || err != HAL_OK) return err; - assert(hlen + vlen <= der_max); + hal_assert(hlen + vlen <= der_max); uint8_t *d = der + hlen; memset(d, 0, vlen); @@ -1198,7 +1205,7 @@ hal_error_t hal_ecdsa_key_to_ecpoint(const hal_ecdsa_key_t * const key, fp_to_unsigned_bin(unconst_fp_int(key->Q->y), d + q_len - Qy_len); d += q_len; - assert(d <= der + der_max); + hal_assert(d <= der + der_max); return HAL_OK; } @@ -1291,7 +1298,7 @@ hal_error_t hal_ecdsa_private_key_to_der(const hal_ecdsa_key_t * const key, const size_t d_len = fp_unsigned_bin_size(unconst_fp_int(key->d)); const size_t Qx_len = fp_unsigned_bin_size(unconst_fp_int(key->Q->x)); const size_t Qy_len = fp_unsigned_bin_size(unconst_fp_int(key->Q->y)); - assert(q_len >= d_len && q_len >= Qx_len && q_len >= Qy_len); + hal_assert(q_len >= d_len && q_len >= Qx_len && q_len >= Qy_len); fp_int version[1] = INIT_FP_INT; fp_set(version, 1); @@ -1466,7 +1473,7 @@ hal_error_t hal_ecdsa_public_key_to_der(const hal_ecdsa_key_t * const key, const size_t Qx_len = fp_unsigned_bin_size(unconst_fp_int(key->Q->x)); const size_t Qy_len = fp_unsigned_bin_size(unconst_fp_int(key->Q->y)); const size_t ecpoint_len = q_len * 2 + 1; - assert(q_len >= Qx_len && q_len >= Qy_len); + hal_assert(q_len >= Qx_len && q_len >= Qy_len); if (der != NULL && ecpoint_len < der_max) { memset(der, 0, ecpoint_len); @@ -1480,7 +1487,7 @@ hal_error_t hal_ecdsa_public_key_to_der(const hal_ecdsa_key_t * const key, fp_to_unsigned_bin(unconst_fp_int(key->Q->y), d + q_len - Qy_len); d += q_len; - assert(d < der + der_max); + hal_assert(d < der + der_max); } return hal_asn1_encode_spki(hal_asn1_oid_ecPublicKey, hal_asn1_oid_ecPublicKey_len, @@ -1554,7 +1561,7 @@ static hal_error_t encode_signature_pkcs11(const ecdsa_curve_t * const curve, const fp_int * const r, const fp_int * const s, uint8_t *signature, size_t *signature_len, const size_t signature_max) { - assert(curve != NULL && r != NULL && s != NULL); + hal_assert(curve != NULL && r != NULL && s != NULL); const size_t n_len = fp_unsigned_bin_size(unconst_fp_int(curve->n)); const size_t r_len = fp_unsigned_bin_size(unconst_fp_int(r)); @@ -1589,7 +1596,7 @@ static hal_error_t decode_signature_pkcs11(const ecdsa_curve_t * const curve, fp_int *r, fp_int *s, const uint8_t * const signature, const size_t signature_len) { - assert(curve != NULL && r != NULL && s != NULL); + hal_assert(curve != NULL && r != NULL && s != NULL); if (signature == NULL || (signature_len & 1) != 0) return HAL_ERROR_BAD_ARGUMENTS; @@ -1695,7 +1702,7 @@ hal_error_t hal_ecdsa_verify(hal_core_t *core, const uint8_t * const hash, const size_t hash_len, const uint8_t * const signature, const size_t signature_len) { - assert(key != NULL && hash != NULL && signature != NULL); + hal_assert(key != NULL && hash != NULL && signature != NULL); const ecdsa_curve_t * const curve = get_curve(key->curve); @@ -161,6 +161,8 @@ DEFINE_HAL_ERROR(HAL_ERROR_KEYSTORE_WRONG_BLOCK_TYPE, "Wrong block type in keystore") \ DEFINE_HAL_ERROR(HAL_ERROR_RPC_PROTOCOL_ERROR, "RPC protocol error") \ DEFINE_HAL_ERROR(HAL_ERROR_NOT_IMPLEMENTED, "Not implemented") \ + DEFINE_HAL_ERROR(HAL_ERROR_CORE_REASSIGNED, "Core has been reassigned since last use") \ + DEFINE_HAL_ERROR(HAL_ERROR_ASSERTION_FAILED, "Assertion failed") \ DEFINE_HAL_ERROR(HAL_ERROR_HASHSIG_KEY_EXHAUSTED, "Key exhausted") \ DEFINE_HAL_ERROR(HAL_ERROR_NOT_READY, "Not ready for this operation") \ END_OF_HAL_ERROR_LIST @@ -214,6 +216,12 @@ extern hal_error_t hal_io_wait2(const hal_core_t *core1, const hal_core_t *core2 * insistence on discarding array bounds information makes * non-delimited character arrays problematic unless we wrap them in a * structure. + * + * For performance reasons, we promise that the hal_core_info_t will + * be the first element of hal_core_t, so that we can convert between + * them using inline functions without completely exposing hal_core_t. + * This is icky, but hal_core_base() gets called a lot during I/O, so + * it's worth a bit of ick to eliminate some function call overhead. */ typedef struct { @@ -222,16 +230,25 @@ typedef struct { hal_addr_t base; } hal_core_info_t; +typedef uint32_t hal_core_lru_t; + +static inline const hal_core_info_t *hal_core_info(const hal_core_t *core) +{ + return (const hal_core_info_t *) core; +} + +static inline hal_addr_t hal_core_base(const hal_core_t *core) +{ + return core == NULL ? 0 : hal_core_info(core)->base; +} + extern hal_core_t *hal_core_find(const char *name, hal_core_t *core); -extern const hal_core_info_t *hal_core_info(const hal_core_t *core); -extern hal_addr_t hal_core_base(const hal_core_t *core); -extern hal_core_t * hal_core_iterate(hal_core_t *core); +extern hal_core_t *hal_core_iterate(hal_core_t *core); extern void hal_core_reset_table(void); -extern hal_error_t hal_core_alloc(const char *name, hal_core_t **core); +extern hal_error_t hal_core_alloc(const char *name, hal_core_t **core, hal_core_lru_t *pomace); +extern hal_error_t hal_core_alloc2(const char *name1, hal_core_t **core1, hal_core_lru_t *pomace1, + const char *name2, hal_core_t **core2, hal_core_lru_t *pomace2); extern void hal_core_free(hal_core_t *core); -extern void hal_critical_section_start(void); -extern void hal_critical_section_end(void); -extern int hal_core_busy(const hal_core_t *core); /* * Slightly higher level public API, still working directly with cores. diff --git a/hal_internal.h b/hal_internal.h index b698611..94546c3 100644 --- a/hal_internal.h +++ b/hal_internal.h @@ -48,6 +48,19 @@ */ /* + * Assertions, using our logger rather than printf() and assuming a + * hal_error_t return value. + */ + +#define hal_assert(_whatever_) \ + do { \ + if (!(_whatever_)) { \ + hal_log(HAL_LOG_ERROR, "Assertion failed: %s", #_whatever_); \ + return HAL_ERROR_ASSERTION_FAILED; \ + } \ + } while (0) + +/* * htonl and htons are not available in arm-none-eabi headers or libc. */ #ifndef STM32F4XX @@ -152,6 +165,8 @@ extern void hal_critical_section_start(void); extern void hal_critical_section_end(void); extern void hal_ks_lock(void); extern void hal_ks_unlock(void); +extern void hal_rsa_bf_lock(void); +extern void hal_rsa_bf_unlock(void); extern void hal_task_yield(void); extern void hal_task_yield_maybe(void); @@ -529,15 +544,8 @@ typedef struct { int hint; /* - * This might be where we'd stash a (hal_core_t *) pointing to a - * core which has already been loaded with the key, if we were - * trying to be clever about using multiple signing cores. Moot - * point (ie, no way we could possibly test such a thing) as long as - * the FPGA is too small to hold more than one modexp core and ECDSA - * is entirely software, so skip it for now, but the implied - * semantics are interesting: a pkey handle starts to resemble an - * initialized signing core, and once all the cores are in use, one - * can't load another key without closing an existing pkey handle. + * This might be where we'd stash one or more (hal_core_t *) + * pointing to cores which have already been loaded with the key. */ } hal_pkey_slot_t; diff --git a/hal_io_fmc.c b/hal_io_fmc.c index 0d49f1e..8a32921 100644 --- a/hal_io_fmc.c +++ b/hal_io_fmc.c @@ -44,6 +44,15 @@ #include "hal.h" #include "hal_internal.h" +/* + * Even no-op debugging code shows up in profiling if it's in an inner + * loop which runs often enough, so we leave now this off by default + * at compile time. + */ +#ifndef HAL_IO_FMC_DEBUG +#define HAL_IO_FMC_DEBUG 0 +#endif + static int debug = 0; static int inited = 0; @@ -68,17 +77,24 @@ void hal_io_set_debug(int onoff) debug = onoff; } -static void dump(char *label, hal_addr_t offset, const uint8_t *buf, size_t len) +#if HAL_IO_FMC_DEBUG + +static inline void dump(const char *label, const hal_addr_t offset, const uint8_t * const buf, const size_t len) { if (debug) { - size_t i; - printf("%s %04x [", label, (unsigned int)offset); - for (i = 0; i < len; ++i) - printf(" %02x", buf[i]); - printf(" ]\n"); + char hex[len * 3 + 1]; + for (size_t i = 0; i < len; ++i) + sprintf(hex + 3 * i, " %02x", buf[i]); + hal_log(HAL_LOG_DEBUG, "%s %04x [%s ]", label, (unsigned int) offset, hex); } } +#else + +#define dump(...) + +#endif + hal_error_t hal_io_write(const hal_core_t *core, hal_addr_t offset, const uint8_t *buf, size_t len) { hal_error_t err; @@ -98,7 +114,7 @@ hal_error_t hal_io_write(const hal_core_t *core, hal_addr_t offset, const uint8_ for (; len > 0; offset += 4, buf += 4, len -= 4) { uint32_t val; val = htonl(*(uint32_t *)buf); - fmc_write_32(offset, &val); + fmc_write_32(offset, val); } return HAL_OK; @@ -108,7 +124,6 @@ hal_error_t hal_io_read(const hal_core_t *core, hal_addr_t offset, uint8_t *buf, { uint8_t *rbuf = buf; int rlen = len; - hal_addr_t orig_offset = offset; hal_error_t err; if (core == NULL) @@ -120,6 +135,8 @@ hal_error_t hal_io_read(const hal_core_t *core, hal_addr_t offset, uint8_t *buf, if ((err = init()) != HAL_OK) return err; + dump("read ", offset + hal_core_base(core), buf, len); + offset = fmc_offset(offset + hal_core_base(core)); for (; rlen > 0; offset += 4, rbuf += 4, rlen -= 4) { uint32_t val; @@ -127,8 +144,6 @@ hal_error_t hal_io_read(const hal_core_t *core, hal_addr_t offset, uint8_t *buf, *(uint32_t *)rbuf = ntohl(val); } - dump("read ", orig_offset + hal_core_base(core), buf, len); - return HAL_OK; } @@ -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 @@ -34,7 +34,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <assert.h> #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -81,6 +80,11 @@ static hal_error_t sw_hash_core_sha512(hal_hash_state_t *); #endif /* HAL_ENABLE_SOFTWARE_HASH_CORES */ +#if HAL_ONLY_USE_SOFTWARE_HASH_CORES +#define hal_core_alloc(x, y, z) HAL_ERROR_CORE_NOT_FOUND +#define hal_core_free(x) +#endif + /* * HMAC magic numbers. */ @@ -119,10 +123,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 +336,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 +344,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 +371,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; + + if ((err = hal_core_alloc(descriptor->core_name, core, pomace)) == HAL_OK) { + *flags |= STATE_FLAG_FREE_CORE; + return HAL_OK; + } + +#endif - *core = NULL; + if (*core != NULL) + return HAL_ERROR_IMPOSSIBLE; - if (flags != NULL) - *flags |= STATE_FLAG_SOFTWARE_CORE; +#if HAL_ENABLE_SOFTWARE_HASH_CORES - err = HAL_OK; + 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 +430,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 +440,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 (!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 +458,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 +466,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_; + memset(*state, 0, (*state)->descriptor->hash_state_length); - if (state == NULL || (state->flags & STATE_FLAG_STATE_ALLOCATED) == 0) - return; - - memset(state, 0, state->descriptor->hash_state_length); - *state_ = NULL; + *state = NULL; } #if ! HAL_ONLY_USE_SOFTWARE_HASH_CORES @@ -482,7 +493,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 +512,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 +528,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 +596,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 +632,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 +642,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 +664,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 +689,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 +707,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 +730,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 +740,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 +771,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 +841,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) + if (state == NULL || *state == NULL) return; - hal_hmac_state_t *state = *state_; + memset(*state, 0, (*state)->hash_state.descriptor->hmac_state_length); - 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); - *state_ = NULL; + *state = NULL; } /* @@ -878,15 +882,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 +979,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 +1007,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 +1017,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 +1029,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 +1045,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 +1053,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 +1076,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 +1093,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 +1136,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 +1155,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]; @@ -620,6 +620,7 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks, hal_error_t err = HAL_OK; hal_ks_block_t *block; + size_t k_der_len = 0; unsigned b; hal_ks_lock(); @@ -627,17 +628,18 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks, if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || (err = hal_ks_block_test_owner(ks, b, slot->client, slot->session)) != HAL_OK || (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) - goto done; + goto unlock; if (hal_ks_block_get_type(block) != HAL_KS_BLOCK_TYPE_KEY) { err = HAL_ERROR_KEYSTORE_WRONG_BLOCK_TYPE; /* HAL_ERROR_KEY_NOT_FOUND */ - goto done; + goto unlock; } hal_ks_cache_mark_used(ks, block, b); hal_ks_key_block_t *k = &block->key; + k_der_len = k->der_len; slot->type = k->type; slot->curve = k->curve; slot->flags = k->flags; @@ -645,6 +647,15 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks, if (der == NULL && der_len != NULL) *der_len = k->der_len; + if (der != NULL && k_der_len <= der_max) + memcpy(der, k->der, k_der_len); + + unlock: + hal_ks_unlock(); + + if (err != HAL_OK) + return err; + if (der != NULL) { uint8_t kek[KEK_LENGTH]; @@ -657,13 +668,11 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks, *der_len = der_max; if ((err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek))) == HAL_OK) - err = hal_aes_keyunwrap(NULL, kek, kek_len, k->der, k->der_len, der, der_len); + err = hal_aes_keyunwrap(NULL, kek, kek_len, der, k_der_len, der, der_len); memset(kek, 0, sizeof(kek)); } - done: - hal_ks_unlock(); return err; } diff --git a/ks_attribute.c b/ks_attribute.c index 1eefefb..9e66994 100644 --- a/ks_attribute.c +++ b/ks_attribute.c @@ -33,7 +33,6 @@ */ #include <string.h> -#include <assert.h> #include "hal.h" #include "hal_internal.h" @@ -44,7 +44,6 @@ #include <stddef.h> #include <string.h> -#include <assert.h> #include "hal.h" #include "hal_internal.h" diff --git a/ks_volatile.c b/ks_volatile.c index 75d7fcb..10fff9a 100644 --- a/ks_volatile.c +++ b/ks_volatile.c @@ -37,7 +37,6 @@ */ #include <string.h> -#include <assert.h> #include "hal.h" #include "hal_internal.h" @@ -77,29 +77,26 @@ * Critical sections -- disable preemption BRIEFLY. */ -WEAK_FUNCTION void hal_critical_section_start(void) -{ - return; -} - -WEAK_FUNCTION void hal_critical_section_end(void) -{ - return; -} +WEAK_FUNCTION void hal_critical_section_start(void) { return; } +WEAK_FUNCTION void hal_critical_section_end(void) { return; } /* * Keystore lock -- lock call blocks indefinitely. */ -WEAK_FUNCTION void hal_ks_lock(void) -{ - return; -} +WEAK_FUNCTION void hal_ks_lock(void) { return; } +WEAK_FUNCTION void hal_ks_unlock(void) { return; } -WEAK_FUNCTION void hal_ks_unlock(void) -{ - return; -} +/* + * RSA blinding cache lock -- lock call blocks indefinitely. + */ + +WEAK_FUNCTION void hal_rsa_bf_lock(void) { return; } +WEAK_FUNCTION void hal_rsa_bf_unlock(void) { return; } + +/* + * Non-preemptive task yield. + */ WEAK_FUNCTION void hal_task_yield(void) { @@ -45,63 +45,72 @@ typedef union { hal_error_t hal_mkmif_init(hal_core_t *core) { + const int free_core = core == NULL; byteword_t cmd; hal_error_t err; cmd.word = htonl(MKMIF_CTRL_CMD_INIT); - if ((err = hal_core_alloc(MKMIF_NAME, &core)) != HAL_OK) + if (free_core && (err = hal_core_alloc(MKMIF_NAME, &core, NULL)) != HAL_OK) return err; if ((err = hal_io_write(core, MKMIF_ADDR_CTRL, cmd.byte, 4)) == HAL_OK) err = hal_io_wait_ready(core); - hal_core_free(core); + if (free_core) + hal_core_free(core); return err; } hal_error_t hal_mkmif_set_clockspeed(hal_core_t *core, const uint32_t divisor) { + const int free_core = core == NULL; byteword_t data; hal_error_t err; data.word = htonl(divisor); - if ((err = hal_core_alloc(MKMIF_NAME, &core)) != HAL_OK) + if (free_core && (err = hal_core_alloc(MKMIF_NAME, &core, NULL)) != HAL_OK) return err; err = hal_io_write(core, MKMIF_ADDR_SCLK_DIV, data.byte, 4); - hal_core_free(core); + if (free_core) + hal_core_free(core); + return err; } hal_error_t hal_mkmif_get_clockspeed(hal_core_t *core, uint32_t *divisor) { + const int free_core = core == NULL; byteword_t data; hal_error_t err; - if ((err = hal_core_alloc(MKMIF_NAME, &core)) != HAL_OK) + if (free_core && (err = hal_core_alloc(MKMIF_NAME, &core, NULL)) != HAL_OK) return err; if ((err = hal_io_read(core, MKMIF_ADDR_SCLK_DIV, data.byte, 4)) == HAL_OK) *divisor = htonl(data.word); - hal_core_free(core); + if (free_core) + hal_core_free(core); + return err; } hal_error_t hal_mkmif_write(hal_core_t *core, uint32_t addr, const uint8_t *buf, size_t len) { + const int free_core = core == NULL; + hal_error_t err = HAL_OK; byteword_t cmd; - hal_error_t err; if (len % 4 != 0) return HAL_ERROR_IO_BAD_COUNT; cmd.word = htonl(MKMIF_CTRL_CMD_WRITE); - if ((err = hal_core_alloc(MKMIF_NAME, &core)) == HAL_OK) { + if (!free_core || (err = hal_core_alloc(MKMIF_NAME, &core, NULL)) == HAL_OK) { for (; len > 0; addr += 4, buf += 4, len -= 4) { byteword_t write_addr; write_addr.word = htonl((uint32_t)addr); @@ -113,7 +122,9 @@ hal_error_t hal_mkmif_write(hal_core_t *core, uint32_t addr, const uint8_t *buf, } } - hal_core_free(core); + if (free_core) + hal_core_free(core); + return err; } @@ -128,15 +139,16 @@ hal_error_t hal_mkmif_write_word(hal_core_t *core, uint32_t addr, const uint32_t hal_error_t hal_mkmif_read(hal_core_t *core, uint32_t addr, uint8_t *buf, size_t len) { + const int free_core = core == NULL; + hal_error_t err = HAL_OK; byteword_t cmd; - hal_error_t err; if (len % 4 != 0) return HAL_ERROR_IO_BAD_COUNT; cmd.word = htonl(MKMIF_CTRL_CMD_READ); - if ((err = hal_core_alloc(MKMIF_NAME, &core)) != HAL_OK) + if (free_core && (err = hal_core_alloc(MKMIF_NAME, &core, NULL)) != HAL_OK) return err; for (; len > 0; addr += 4, buf += 4, len -= 4) { @@ -149,7 +161,9 @@ hal_error_t hal_mkmif_read(hal_core_t *core, uint32_t addr, uint8_t *buf, size_t break; } - hal_core_free(core); + if (free_core) + hal_core_free(core); + return err; } @@ -265,7 +265,6 @@ static inline hal_error_t extract_result(hal_modexp_arg_t *a) { /* * Extract results from the main calculation and we're done. - * Hardly seems worth making this a separate function. */ return get_buffer(a->core, MODEXPA7_ADDR_RESULT, a->result, a->mod_len); @@ -282,16 +281,23 @@ hal_error_t hal_modexp(const int precalc, hal_modexp_arg_t *a) if ((err = check_args(a)) != HAL_OK) return err; - if ((err = hal_core_alloc(MODEXPA7_NAME, &a->core)) == HAL_OK && - (err = setup_precalc(precalc, a)) == HAL_OK && + const int free_core = a->core == NULL; + + if ((!free_core || + (err = hal_core_alloc(MODEXPA7_NAME, &a->core, NULL)) == HAL_OK) && + (err = setup_precalc(precalc, a)) == HAL_OK && (!precalc || - (err = hal_io_wait_ready(a->core)) == HAL_OK) && - (err = setup_calc(precalc, a)) == HAL_OK && - (err = hal_io_wait_valid(a->core)) == HAL_OK && - (err = extract_result(a)) == HAL_OK) + (err = hal_io_wait_ready(a->core)) == HAL_OK) && + (err = setup_calc(precalc, a)) == HAL_OK && + (err = hal_io_wait_valid(a->core)) == HAL_OK && + (err = extract_result(a)) == HAL_OK) err = HAL_OK; - hal_core_free(a->core); + if (free_core) { + hal_core_free(a->core); + a->core = NULL; + } + return err; } @@ -301,27 +307,38 @@ hal_error_t hal_modexp(const int precalc, hal_modexp_arg_t *a) hal_error_t hal_modexp2(const int precalc, hal_modexp_arg_t *a1, hal_modexp_arg_t *a2) { + int free_core = 0; hal_error_t err; if ((err = check_args(a1)) != HAL_OK || (err = check_args(a2)) != HAL_OK) return err; - if ((err = hal_core_alloc2(MODEXPA7_NAME, &a1->core, - MODEXPA7_NAME, &a2->core)) == HAL_OK && - (err = setup_precalc(precalc, a1)) == HAL_OK && - (err = setup_precalc(precalc, a2)) == HAL_OK && + if (a1->core == NULL && a2->core == NULL) + free_core = 1; + else if (a1->core == NULL || a2->core == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + if ((!free_core || + (err = hal_core_alloc2(MODEXPA7_NAME, &a1->core, NULL, + MODEXPA7_NAME, &a2->core, NULL)) == HAL_OK) && + (err = setup_precalc(precalc, a1)) == HAL_OK && + (err = setup_precalc(precalc, a2)) == HAL_OK && (!precalc || - (err = hal_io_wait_ready2(a1->core, a2->core)) == HAL_OK) && - (err = setup_calc(precalc, a1)) == HAL_OK && - (err = setup_calc(precalc, a2)) == HAL_OK && - (err = hal_io_wait_valid2(a1->core, a2->core)) == HAL_OK && - (err = extract_result(a1)) == HAL_OK && - (err = extract_result(a2)) == HAL_OK) + (err = hal_io_wait_ready2(a1->core, a2->core)) == HAL_OK) && + (err = setup_calc(precalc, a1)) == HAL_OK && + (err = setup_calc(precalc, a2)) == HAL_OK && + (err = hal_io_wait_valid2(a1->core, a2->core)) == HAL_OK && + (err = extract_result(a1)) == HAL_OK && + (err = extract_result(a2)) == HAL_OK) err = HAL_OK; - hal_core_free(a1->core); - hal_core_free(a2->core); + if (free_core) { + hal_core_free(a1->core); + hal_core_free(a2->core); + a1->core = a2->core = NULL; + } + return err; } @@ -34,7 +34,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <assert.h> #include <string.h> #include <stdint.h> @@ -53,7 +52,7 @@ static hal_error_t do_hmac(hal_core_t *core, const uint32_t block, uint8_t * mac, const size_t mac_len) { - assert(d != NULL && pw != NULL && data != NULL && mac != NULL); + hal_assert(d != NULL && pw != NULL && data != NULL && mac != NULL); uint8_t sb[d->hmac_state_length]; hal_hmac_state_t *s; @@ -96,9 +95,9 @@ hal_error_t hal_pbkdf2(hal_core_t *core, iterations_desired == 0) return HAL_ERROR_BAD_ARGUMENTS; - assert(sizeof(statebuf) >= descriptor->hmac_state_length); - assert(sizeof(result) >= descriptor->digest_length); - assert(sizeof(mac) >= descriptor->digest_length); + hal_assert(sizeof(statebuf) >= descriptor->hmac_state_length); + hal_assert(sizeof(result) >= descriptor->digest_length); + hal_assert(sizeof(mac) >= descriptor->digest_length); /* Output length check per RFC 2989 5.2. */ if ((uint64_t) derived_key_length > ((uint64_t) 0xFFFFFFFF) * descriptor->block_length) diff --git a/rpc_client.c b/rpc_client.c index 2fb8ae6..e97289e 100644 --- a/rpc_client.c +++ b/rpc_client.c @@ -33,8 +33,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <assert.h> - #include "hal.h" #include "hal_internal.h" #include "xdr_internal.h" @@ -46,7 +44,7 @@ #if HAL_RPC_CLIENT_DEBUG #include <stdio.h> -#define check(op) do { const hal_error_t _err_ = (op); if (_err_ != HAL_OK) { printf("%s returned %d (%s)\n", #op, _err_, hal_error_string(_err_)); return _err_; } } while (0) +#define check(op) do { const hal_error_t _err_ = (op); if (_err_ != HAL_OK) { hal_log(HAL_LOG_DEBUG, "%s returned %d (%s)", #op, _err_, hal_error_string(_err_)); return _err_; } } while (0) #else #define check(op) do { const hal_error_t _err_ = (op); if (_err_ != HAL_OK) { return _err_; } } while (0) #endif @@ -74,14 +72,14 @@ static hal_error_t read_matching_packet(const rpc_func_num_t expected_func, size_t ilen = inbuf_max; hal_error_t err; - assert(inbuf != NULL && iptr != NULL && ilimit != NULL); + hal_assert(inbuf != NULL && iptr != NULL && ilimit != NULL); do { if ((err = hal_rpc_recv(inbuf, &ilen)) != HAL_OK) return err; - assert(ilen <= inbuf_max); + hal_assert(ilen <= inbuf_max); *iptr = inbuf; *ilimit = inbuf + ilen; diff --git a/rpc_pkcs1.c b/rpc_pkcs1.c index 2dcf9dd..1cf5cfd 100644 --- a/rpc_pkcs1.c +++ b/rpc_pkcs1.c @@ -32,8 +32,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <assert.h> - #include "hal.h" #include "hal_internal.h" @@ -46,7 +44,7 @@ hal_error_t hal_rpc_pkcs1_construct_digestinfo(const hal_hash_handle_t handle, uint8_t *digest_info, size_t *digest_info_len, const size_t digest_info_max) { - assert(digest_info != NULL && digest_info_len != NULL); + hal_assert(digest_info != NULL && digest_info_len != NULL); hal_digest_algorithm_t alg; size_t len, alg_len; @@ -62,7 +60,7 @@ hal_error_t hal_rpc_pkcs1_construct_digestinfo(const hal_hash_handle_t handle, if (*digest_info_len >= digest_info_max) return HAL_ERROR_RESULT_TOO_LONG; - assert(*digest_info_len < 130); + hal_assert(*digest_info_len < 130); uint8_t *d = digest_info; @@ -76,7 +74,7 @@ hal_error_t hal_rpc_pkcs1_construct_digestinfo(const hal_hash_handle_t handle, *d++ = 0x04; /* OCTET STRING */ *d++ = (uint8_t) len; - assert(digest_info + *digest_info_len == d + len); + hal_assert(digest_info + *digest_info_len == d + len); return hal_rpc_hash_finalize(handle, d, len); } @@ -34,7 +34,6 @@ */ #include <string.h> -#include <assert.h> #include "hal.h" #include "hal_internal.h" @@ -74,8 +73,6 @@ static inline hal_pkey_slot_t *alloc_slot(const hal_key_flags_t flags) uint32_t glop = ++next_glop << 16; next_glop %= 0x7FFF; - assert((glop & HAL_PKEY_HANDLE_TOKEN_FLAG) == 0); - if ((flags & HAL_KEY_FLAG_TOKEN) != 0) glop |= HAL_PKEY_HANDLE_TOKEN_FLAG; @@ -225,7 +222,7 @@ static inline hal_error_t check_writable(const hal_client_handle_t client, static inline hal_error_t get_nonzero_random(uint8_t *buffer, size_t n) { - assert(buffer != NULL); + hal_assert(buffer != NULL); uint32_t word = 0; hal_error_t err; @@ -261,7 +258,7 @@ static hal_error_t pkcs1_5_pad(const uint8_t * const data, const size_t data_len uint8_t *block, const size_t block_len, const uint8_t type) { - assert(data != NULL && block != NULL && (type == 0x01 || type == 0x02)); + hal_assert(data != NULL && block != NULL && (type == 0x01 || type == 0x02)); hal_error_t err; @@ -331,7 +328,7 @@ static hal_error_t pkey_local_load(const hal_client_handle_t client, const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags) { - assert(pkey != NULL && name != NULL && der != NULL); + hal_assert(pkey != NULL && name != NULL && der != NULL); hal_curve_name_t curve; hal_pkey_slot_t *slot; @@ -375,7 +372,7 @@ static hal_error_t pkey_local_open(const hal_client_handle_t client, hal_pkey_handle_t *pkey, const hal_uuid_t * const name) { - assert(pkey != NULL && name != NULL); + hal_assert(pkey != NULL && name != NULL); hal_pkey_slot_t *slot; hal_error_t err; @@ -419,7 +416,7 @@ static hal_error_t pkey_local_generate_rsa(const hal_client_handle_t client, const uint8_t * const public_exponent, const size_t public_exponent_len, const hal_key_flags_t flags) { - assert(pkey != NULL && name != NULL && (key_length & 7) == 0); + hal_assert(pkey != NULL && name != NULL && (key_length & 7) == 0); uint8_t keybuf[hal_rsa_key_t_size]; hal_rsa_key_t *key = NULL; @@ -478,7 +475,7 @@ static hal_error_t pkey_local_generate_ec(const hal_client_handle_t client, const hal_curve_name_t curve, const hal_key_flags_t flags) { - assert(pkey != NULL && name != NULL); + hal_assert(pkey != NULL && name != NULL); uint8_t keybuf[hal_ecdsa_key_t_size]; hal_ecdsa_key_t *key = NULL; @@ -537,7 +534,7 @@ static hal_error_t pkey_local_generate_hashsig(const hal_client_handle_t client, const lmots_algorithm_t lmots_type, const hal_key_flags_t flags) { - assert(pkey != NULL && name != NULL); + hal_assert(pkey != NULL && name != NULL); hal_hashsig_key_t *key = NULL; hal_pkey_slot_t *slot; @@ -837,18 +834,18 @@ static hal_error_t pkey_local_sign_rsa(hal_pkey_slot_t *slot, uint8_t *keybuf, const size_t keybuf_len, const uint8_t * const der, const size_t der_len, const hal_hash_handle_t hash, - const uint8_t * input, size_t input_len, - uint8_t * signature, size_t *signature_len, const size_t signature_max) + const uint8_t *input, size_t input_len, + uint8_t *signature, size_t *signature_len, const size_t signature_max) { hal_rsa_key_t *key = NULL; hal_error_t err; - assert(signature != NULL && signature_len != NULL); - assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); + hal_assert(signature != NULL && signature_len != NULL); + hal_assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); if ((err = hal_rsa_private_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK || (err = hal_rsa_key_get_modulus(key, NULL, signature_len, 0)) != HAL_OK) - return err; + return err; if (*signature_len > signature_max) return HAL_ERROR_RESULT_TOO_LONG; @@ -859,7 +856,7 @@ static hal_error_t pkey_local_sign_rsa(hal_pkey_slot_t *slot, input = signature; } - if ((err = pkcs1_5_pad(input, input_len, signature, *signature_len, 0x01)) != HAL_OK || + if ((err = pkcs1_5_pad(input, input_len, signature, *signature_len, 0x01)) != HAL_OK || (err = hal_rsa_decrypt(NULL, NULL, key, signature, *signature_len, signature, *signature_len)) != HAL_OK) return err; @@ -886,8 +883,8 @@ static hal_error_t pkey_local_sign_ecdsa(hal_pkey_slot_t *slot, hal_ecdsa_key_t *key = NULL; hal_error_t err; - assert(signature != NULL && signature_len != NULL); - assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); + hal_assert(signature != NULL && signature_len != NULL); + hal_assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); if ((err = hal_ecdsa_private_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK) return err; @@ -924,8 +921,8 @@ static hal_error_t pkey_local_sign_hashsig(hal_pkey_slot_t *slot, hal_hashsig_key_t *key = NULL; hal_error_t err; - assert(signature != NULL && signature_len != NULL); - assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); + hal_assert(signature != NULL && signature_len != NULL); + hal_assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); if ((err = hal_hashsig_private_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK) return err; @@ -1022,8 +1019,8 @@ static hal_error_t pkey_local_verify_rsa(uint8_t *keybuf, const size_t keybuf_le hal_rsa_key_t *key = NULL; hal_error_t err; - assert(signature != NULL && signature_len > 0); - assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); + hal_assert(signature != NULL && signature_len > 0); + hal_assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); switch (type) { case HAL_KEY_TYPE_RSA_PRIVATE: @@ -1069,8 +1066,8 @@ static hal_error_t pkey_local_verify_ecdsa(uint8_t *keybuf, const size_t keybuf_ hal_ecdsa_key_t *key = NULL; hal_error_t err; - assert(signature != NULL && signature_len > 0); - assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); + hal_assert(signature != NULL && signature_len > 0); + hal_assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); switch (type) { case HAL_KEY_TYPE_EC_PRIVATE: @@ -1113,8 +1110,8 @@ static hal_error_t pkey_local_verify_hashsig(uint8_t *keybuf, const size_t keybu hal_hashsig_key_t *key = NULL; hal_error_t err; - assert(signature != NULL && signature_len > 0); - assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); + hal_assert(signature != NULL && signature_len > 0); + hal_assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0)); if ((err = hal_hashsig_public_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK) return err; @@ -1240,7 +1237,7 @@ static hal_error_t pkey_local_match(const hal_client_handle_t client, const unsigned result_max, const hal_uuid_t * const previous_uuid) { - assert(state != NULL && result_len != NULL); + hal_assert(state != NULL && result_len != NULL); static const hal_uuid_t uuid_zero[1] = {{{0}}}; const hal_uuid_t *prev = previous_uuid; @@ -1325,7 +1322,7 @@ static hal_error_t pkey_local_export(const hal_pkey_handle_t pkey_handle, uint8_t *pkcs8, size_t *pkcs8_len, const size_t pkcs8_max, uint8_t *kek, size_t *kek_len, const size_t kek_max) { - assert(pkcs8 != NULL && pkcs8_len != NULL && kek != NULL && kek_len != NULL && kek_max > KEK_LENGTH); + hal_assert(pkcs8 != NULL && pkcs8_len != NULL && kek != NULL && kek_len != NULL && kek_max > KEK_LENGTH); uint8_t rsabuf[hal_rsa_key_t_size]; hal_rsa_key_t *rsa = NULL; @@ -1422,7 +1419,7 @@ static hal_error_t pkey_local_import(const hal_client_handle_t client, const uint8_t * const kek_, const size_t kek_len, const hal_key_flags_t flags) { - assert(pkey != NULL && name != NULL && pkcs8 != NULL && kek_ != NULL && kek_len > 2); + hal_assert(pkey != NULL && name != NULL && pkcs8 != NULL && kek_ != NULL && kek_len > 2); uint8_t kek[KEK_LENGTH], rsabuf[hal_rsa_key_t_size], der[HAL_KS_WRAPPED_KEYSIZE], *d; size_t der_len, oid_len, data_len; diff --git a/rpc_serial.c b/rpc_serial.c index 0e0e6ff..bae8b83 100644 --- a/rpc_serial.c +++ b/rpc_serial.c @@ -92,7 +92,7 @@ hal_error_t hal_serial_init(const char * const device, const uint32_t speed) termios_speed = B921600; break; default: - fprintf(stderr, "invalid line speed %lu\n", (unsigned long) speed); + hal_log(HAL_LOG_ERROR, "invalid line speed %lu\n", (unsigned long) speed); return HAL_ERROR_RPC_TRANSPORT; } @@ -12,7 +12,7 @@ * St Denis's libtomcrypt code. * * Authors: Rob Austein - * Copyright (c) 2015, NORDUnet A/S + * Copyright (c) 2015-2018, NORDUnet A/S * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -102,6 +102,15 @@ #endif /* + * How big to make the blinding factors cache. + * Zero disables the cache entirely. + */ + +#ifndef HAL_RSA_BLINDING_CACHE_SIZE +#define HAL_RSA_BLINDING_CACHE_SIZE 2 +#endif + +/* * Whether we want debug output. */ @@ -123,6 +132,20 @@ void hal_rsa_set_blinding(const int onoff) blinding = onoff; } +#if HAL_RSA_BLINDING_CACHE_SIZE > 0 + +typedef struct { + unsigned lru; + fp_int n[1], bf[1], ubf[1]; +} bfc_slot_t; + +static struct { + unsigned lru; + bfc_slot_t slot[HAL_RSA_BLINDING_CACHE_SIZE]; +} bfc; + +#endif + /* * RSA key implementation. This structure type is private to this * module, anything else that needs to touch one of these just gets a @@ -215,7 +238,7 @@ static hal_error_t modexp(hal_core_t *core, const fp_int * const msg, const fp_int * const exp, const fp_int * const mod, - fp_int *res, + fp_int * res, uint8_t *coeff, const size_t coeff_len, uint8_t *mont, const size_t mont_len) { @@ -225,29 +248,29 @@ static hal_error_t modexp(hal_core_t *core, return HAL_ERROR_IMPOSSIBLE; const size_t msg_len = (fp_unsigned_bin_size(unconst_fp_int(msg)) + 3) & ~3; - const size_t exp_len = (fp_unsigned_bin_size(unconst_fp_int(exp)) + 3) & ~3; - const size_t mod_len = (fp_unsigned_bin_size(unconst_fp_int(mod)) + 3) & ~3; + const size_t exp_len = (fp_unsigned_bin_size(unconst_fp_int(exp)) + 3) & ~3; + const size_t mod_len = (fp_unsigned_bin_size(unconst_fp_int(mod)) + 3) & ~3; uint8_t msgbuf[msg_len]; uint8_t expbuf[exp_len]; uint8_t modbuf[mod_len]; uint8_t resbuf[mod_len]; - hal_modexp_arg_t args = { - .core = core, - .msg = msgbuf, .msg_len = sizeof(msgbuf), - .exp = expbuf, .exp_len = sizeof(expbuf), - .mod = modbuf, .mod_len = sizeof(modbuf), - .result = resbuf, .result_len = sizeof(resbuf), - .coeff = coeff, .coeff_len = coeff_len, - .mont = mont, .mont_len = mont_len - }; + hal_modexp_arg_t args = { + .core = core, + .msg = msgbuf, .msg_len = sizeof(msgbuf), + .exp = expbuf, .exp_len = sizeof(expbuf), + .mod = modbuf, .mod_len = sizeof(modbuf), + .result = resbuf, .result_len = sizeof(resbuf), + .coeff = coeff, .coeff_len = coeff_len, + .mont = mont, .mont_len = mont_len + }; if ((err = unpack_fp(msg, msgbuf, sizeof(msgbuf))) != HAL_OK || (err = unpack_fp(exp, expbuf, sizeof(expbuf))) != HAL_OK || (err = unpack_fp(mod, modbuf, sizeof(modbuf))) != HAL_OK || (err = hal_modexp(precalc, &args)) != HAL_OK) - goto fail; + goto fail; fp_read_unsigned_bin(res, resbuf, sizeof(resbuf)); @@ -283,34 +306,34 @@ static hal_error_t modexp2(const int precalc, return HAL_ERROR_IMPOSSIBLE; const size_t msg_len = (fp_unsigned_bin_size(unconst_fp_int(msg)) + 3) & ~3; - const size_t exp1_len = (fp_unsigned_bin_size(unconst_fp_int(exp1)) + 3) & ~3; - const size_t mod1_len = (fp_unsigned_bin_size(unconst_fp_int(mod1)) + 3) & ~3; - const size_t exp2_len = (fp_unsigned_bin_size(unconst_fp_int(exp2)) + 3) & ~3; - const size_t mod2_len = (fp_unsigned_bin_size(unconst_fp_int(mod2)) + 3) & ~3; + const size_t exp1_len = (fp_unsigned_bin_size(unconst_fp_int(exp1)) + 3) & ~3; + const size_t mod1_len = (fp_unsigned_bin_size(unconst_fp_int(mod1)) + 3) & ~3; + const size_t exp2_len = (fp_unsigned_bin_size(unconst_fp_int(exp2)) + 3) & ~3; + const size_t mod2_len = (fp_unsigned_bin_size(unconst_fp_int(mod2)) + 3) & ~3; uint8_t msgbuf[msg_len]; uint8_t expbuf1[exp1_len], modbuf1[mod1_len], resbuf1[mod1_len]; uint8_t expbuf2[exp2_len], modbuf2[mod2_len], resbuf2[mod2_len]; - hal_modexp_arg_t args1 = { - .core = core1, - .msg = msgbuf, .msg_len = sizeof(msgbuf), - .exp = expbuf1, .exp_len = sizeof(expbuf1), - .mod = modbuf1, .mod_len = sizeof(modbuf1), - .result = resbuf1, .result_len = sizeof(resbuf1), - .coeff = coeff1, .coeff_len = coeff1_len, - .mont = mont1, .mont_len = mont1_len - }; - - hal_modexp_arg_t args2 = { - .core = core2, - .msg = msgbuf, .msg_len = sizeof(msgbuf), - .exp = expbuf2, .exp_len = sizeof(expbuf2), - .mod = modbuf2, .mod_len = sizeof(modbuf2), - .result = resbuf2, .result_len = sizeof(resbuf2), - .coeff = coeff2, .coeff_len = coeff2_len, - .mont = mont2, .mont_len = mont2_len - }; + hal_modexp_arg_t args1 = { + .core = core1, + .msg = msgbuf, .msg_len = sizeof(msgbuf), + .exp = expbuf1, .exp_len = sizeof(expbuf1), + .mod = modbuf1, .mod_len = sizeof(modbuf1), + .result = resbuf1, .result_len = sizeof(resbuf1), + .coeff = coeff1, .coeff_len = coeff1_len, + .mont = mont1, .mont_len = mont1_len + }; + + hal_modexp_arg_t args2 = { + .core = core2, + .msg = msgbuf, .msg_len = sizeof(msgbuf), + .exp = expbuf2, .exp_len = sizeof(expbuf2), + .mod = modbuf2, .mod_len = sizeof(modbuf2), + .result = resbuf2, .result_len = sizeof(resbuf2), + .coeff = coeff2, .coeff_len = coeff2_len, + .mont = mont2, .mont_len = mont2_len + }; if ((err = unpack_fp(msg, msgbuf, sizeof(msgbuf))) != HAL_OK || (err = unpack_fp(exp1, expbuf1, sizeof(expbuf1))) != HAL_OK || @@ -318,7 +341,7 @@ static hal_error_t modexp2(const int precalc, (err = unpack_fp(exp2, expbuf2, sizeof(expbuf2))) != HAL_OK || (err = unpack_fp(mod2, modbuf2, sizeof(modbuf2))) != HAL_OK || (err = hal_modexp2(precalc, &args1, &args2)) != HAL_OK) - goto fail; + goto fail; fp_read_unsigned_bin(res1, resbuf1, sizeof(resbuf1)); fp_read_unsigned_bin(res2, resbuf2, sizeof(resbuf2)); @@ -415,12 +438,10 @@ int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) #endif /* HAL_RSA_SIGN_USE_MODEXP && HAL_RSA_KEYGEN_USE_MODEXP */ /* - * Create blinding factors. There are various schemes for amortizing - * the cost of this over multiple RSA operations, at present we don't - * try. Come back to this if it looks like a bottleneck. + * Create blinding factors. */ -static hal_error_t create_blinding_factors(hal_core_t *core, hal_rsa_key_t *key, fp_int *bf, fp_int *ubf) +static hal_error_t create_blinding_factors(hal_rsa_key_t *key, fp_int *bf, fp_int *ubf) { if (key == NULL || bf == NULL || ubf == NULL) return HAL_ERROR_IMPOSSIBLE; @@ -429,14 +450,39 @@ static hal_error_t create_blinding_factors(hal_core_t *core, hal_rsa_key_t *key, uint8_t rnd[fp_unsigned_bin_size(unconst_fp_int(key->n))]; hal_error_t err = HAL_OK; + hal_rsa_bf_lock(); + +#if HAL_RSA_BLINDING_CACHE_SIZE > 0 + unsigned best_delta = 0; + int best_index = 0; + + for (int i = 0; i < HAL_RSA_BLINDING_CACHE_SIZE; i++) { + bfc_slot_t *b = &bfc.slot[i]; + const unsigned delta = bfc.lru - b->lru; + if (delta > best_delta) { + best_delta = delta; + best_index = i; + } + if (fp_cmp_mag(b->n, key->n) == FP_EQ) { + if (fp_sqrmod(b->bf, key->n, b->bf) != FP_OKAY || + fp_sqrmod(b->ubf, key->n, b->ubf) != FP_OKAY) + continue; /* should never happen, but be safe */ + fp_copy(b->bf, bf); + fp_copy(b->ubf, ubf); + err = HAL_OK; + goto fail; + } + } +#endif + if ((err = hal_get_random(NULL, rnd, sizeof(rnd))) != HAL_OK) goto fail; fp_init(bf); - fp_read_unsigned_bin(bf, rnd, sizeof(rnd)); + fp_read_unsigned_bin(bf, rnd, sizeof(rnd)); fp_copy(bf, ubf); - if ((err = modexp(core, precalc, bf, key->e, key->n, bf, + if ((err = modexp(NULL, precalc, bf, key->e, key->n, bf, key->nC, sizeof(key->nC), key->nF, sizeof(key->nF))) != HAL_OK) goto fail; @@ -445,7 +491,18 @@ static hal_error_t create_blinding_factors(hal_core_t *core, hal_rsa_key_t *key, FP_CHECK(fp_invmod(ubf, unconst_fp_int(key->n), ubf)); +#if HAL_RSA_BLINDING_CACHE_SIZE > 0 + { + bfc_slot_t *b = &bfc.slot[best_index]; + fp_copy(key->n, b->n); + fp_copy(bf, b->bf); + fp_copy(ubf, b->ubf); + b->lru = ++bfc.lru; + } +#endif + fail: + hal_rsa_bf_unlock(); memset(rnd, 0, sizeof(rnd)); return err; } @@ -471,7 +528,7 @@ static hal_error_t rsa_crt(hal_core_t *core1, hal_core_t *core2, hal_rsa_key_t * * Handle blinding if requested. */ if (blinding) { - if ((err = create_blinding_factors(core1, key, bf, ubf)) != HAL_OK) + if ((err = create_blinding_factors(key, bf, ubf)) != HAL_OK) goto fail; FP_CHECK(fp_mulmod(msg, bf, unconst_fp_int(key->n), msg)); } @@ -48,7 +48,7 @@ #if HAL_SLIP_DEBUG #include <stdio.h> -#define check(op) do { const hal_error_t _err_ = (op); if (_err_ != HAL_OK) { printf("%s returned %d (%s)\n", #op, _err_, hal_error_string(_err_)); return _err_; } } while (0) +#define check(op) do { const hal_error_t _err_ = (op); if (_err_ != HAL_OK) { hal_log(HAL_LOG_DEBUG, "%s returned %d (%s)", #op, _err_, hal_error_string(_err_)); return _err_; } } while (0) #else #define check(op) do { const hal_error_t _err_ = (op); if (_err_ != HAL_OK) { return _err_; } } while (0) #endif diff --git a/tests/parallel-signatures.py b/tests/parallel-signatures.py index 006b753..8d98460 100755 --- a/tests/parallel-signatures.py +++ b/tests/parallel-signatures.py @@ -54,7 +54,6 @@ from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter from tornado.gen import Return, coroutine from tornado.ioloop import IOLoop from tornado.iostream import IOStream, StreamClosedError -from tornado.queues import Queue from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString from Crypto.Util.number import inverse @@ -197,55 +196,52 @@ def pkcs1_hash_and_pad(text): @coroutine -def worker(args, k, p, q, r, m): - while True: - n = yield q.get() +def client(args, k, p, q, r, m, v, h): + while q: + n = q.pop(0) logger.debug("Signing %s", n) - try: - t0 = datetime.datetime.now() - s = yield p.sign(data = m) - t1 = datetime.datetime.now() - if args.verify: - k.verify(s) - r.add(t0, t1) - except: - logger.exception("Signature failed") - finally: - q.task_done() + t0 = datetime.datetime.now() + s = yield p.sign(data = m) + t1 = datetime.datetime.now() + logger.debug("Signature %s: %s", n, ":".join("{:02x}".format(ord(b)) for b in s)) + if args.verify and not v.verify(h, s): + raise RuntimeError("RSA verification failed") + r.add(t0, t1) + @coroutine def main(): parser = ArgumentParser(description = __doc__, formatter_class = ArgumentDefaultsHelpFormatter) parser.add_argument("-i", "--iterations", default = 1000, type = int, help = "iterations") + parser.add_argument("-c", "--clients", default = 4, type = int, help = "client count") parser.add_argument("-k", "--key", choices = tuple(key_table), default = "rsa_2048", help = "key to test") parser.add_argument("-p", "--pin", default = "fnord", help = "user PIN") - parser.add_argument("-q", "--quiet", action = "store_true", help = "be less chatty") + parser.add_argument("-q", "--quiet", action = "store_true", help = "bark less") + parser.add_argument("-d", "--debug", action = "store_true", help = "bark more") parser.add_argument("-t", "--text", default = "Hamsters'R'Us", help = "plaintext to sign") parser.add_argument("-v", "--verify", action = "store_true", help = "verify signatures") - parser.add_argument("-w", "--workers", default = 4, type = int, help = "worker count") args = parser.parse_args() + if args.debug: + logging.getLogger().setLevel(logging.DEBUG) + k = key_table[args.key] - q = Queue() - - tbs = pkcs1_hash_and_pad(args.text) - der = k.exportKey(format = "DER", pkcs = 8) + d = k.exportKey(format = "DER", pkcs = 8) + h = SHA256(args.text) + v = PKCS115_SigScheme(k) + q = range(args.iterations) + m = pkcs1_hash_and_pad(args.text) + r = Result(args, args.key) - hsms = [HSM() for i in xrange(args.workers)] + hsms = [HSM() for i in xrange(args.clients)] for hsm in hsms: yield hsm.login(HAL_USER_NORMAL, args.pin) - pkeys = yield [hsm.pkey_load(der, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) for hsm in hsms] - - r = Result(args, args.key) - - for pkey in pkeys: - IOLoop.current().spawn_callback(worker, args, k, pkey, q, r, tbs) + pkeys = yield [hsm.pkey_load(d, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) for hsm in hsms] - yield [q.put(i) for i in xrange(args.iterations)] - yield q.join() + yield [client(args, k, pkey, q, r, m, v, h) for pkey in pkeys] yield [pkey.delete() for pkey in pkeys] @@ -296,6 +292,7 @@ class Result(object): "mean {0.mean} " "speedup {0.speedup} " "(n {0.n}, " + "c {0.args.clients} " "t0 {0.t0} " "t1 {0.t1})\n").format(self)) sys.stdout.flush() diff --git a/tests/test-rsa.c b/tests/test-rsa.c index 176ba03..853f90f 100644 --- a/tests/test-rsa.c +++ b/tests/test-rsa.c @@ -49,8 +49,7 @@ * Run one modexp test. */ -static int test_modexp(hal_core_t *core, - const char * const kind, +static int test_modexp(const char * const kind, const rsa_tc_t * const tc, const rsa_tc_bn_t * const msg, /* Input message */ const rsa_tc_bn_t * const exp, /* Exponent */ @@ -61,7 +60,6 @@ static int test_modexp(hal_core_t *core, printf("%s test for %lu-bit RSA key\n", kind, (unsigned long) tc->size); hal_modexp_arg_t args = { - .core = core, .msg = msg->val, .msg_len = msg->len, .exp = exp->val, .exp_len = exp->len, .mod = tc->n.val, .mod_len = tc->n.len, @@ -83,8 +81,7 @@ static int test_modexp(hal_core_t *core, * Run one RSA CRT test. */ -static int test_decrypt(hal_core_t *core, - const char * const kind, +static int test_decrypt(const char * const kind, const rsa_tc_t * const tc) { printf("%s test for %lu-bit RSA key\n", kind, (unsigned long) tc->size); @@ -107,7 +104,7 @@ static int test_decrypt(hal_core_t *core, uint8_t result[tc->n.len]; - if ((err = hal_rsa_decrypt(core, NULL, key, tc->m.val, tc->m.len, result, sizeof(result))) != HAL_OK) + if ((err = hal_rsa_decrypt(NULL, NULL, key, tc->m.val, tc->m.len, result, sizeof(result))) != HAL_OK) printf("RSA CRT failed: %s\n", hal_error_string(err)); const int mismatch = (err == HAL_OK && memcmp(result, tc->s.val, tc->s.len) != 0); @@ -124,8 +121,7 @@ static int test_decrypt(hal_core_t *core, * Run one RSA key generation + CRT test. */ -static int test_gen(hal_core_t *core, - const char * const kind, +static int test_gen(const char * const kind, const rsa_tc_t * const tc) { printf("%s test for %lu-bit RSA key\n", kind, (unsigned long) tc->size); @@ -138,7 +134,7 @@ static int test_gen(hal_core_t *core, const uint8_t f4[] = { 0x01, 0x00, 0x01 }; - if ((err = hal_rsa_key_gen(core, &key1, keybuf1, sizeof(keybuf1), bitsToBytes(tc->size), f4, sizeof(f4))) != HAL_OK) + if ((err = hal_rsa_key_gen(NULL, &key1, keybuf1, sizeof(keybuf1), bitsToBytes(tc->size), f4, sizeof(f4))) != HAL_OK) return printf("RSA key generation failed: %s\n", hal_error_string(err)), 0; size_t der_len = 0; @@ -174,7 +170,7 @@ static int test_gen(hal_core_t *core, uint8_t result[tc->n.len]; - if ((err = hal_rsa_decrypt(core, NULL, key1, tc->m.val, tc->m.len, result, sizeof(result))) != HAL_OK) + if ((err = hal_rsa_decrypt(NULL, NULL, key1, tc->m.val, tc->m.len, result, sizeof(result))) != HAL_OK) printf("RSA CRT failed: %s\n", hal_error_string(err)); snprintf(fn, sizeof(fn), "test-rsa-sig-%04lu.der", (unsigned long) tc->size); @@ -192,7 +188,7 @@ static int test_gen(hal_core_t *core, if (err != HAL_OK) /* Deferred failure from hal_rsa_decrypt(), above */ return 0; - if ((err = hal_rsa_encrypt(core, key1, result, sizeof(result), result, sizeof(result))) != HAL_OK) + if ((err = hal_rsa_encrypt(NULL, key1, result, sizeof(result), result, sizeof(result))) != HAL_OK) printf("First RSA signature check failed: %s\n", hal_error_string(err)); int mismatch = 0; @@ -239,7 +235,7 @@ static int test_gen(hal_core_t *core, * the public key passes the signature verification test below. */ - if ((err = hal_rsa_encrypt(core, key2, result, sizeof(result), result, sizeof(result))) != HAL_OK) + if ((err = hal_rsa_encrypt(NULL, key2, result, sizeof(result), result, sizeof(result))) != HAL_OK) return printf("Second RSA signature check failed: %s\n", hal_error_string(err)), 0; if (err == HAL_OK && memcmp(result, tc->m.val, tc->m.len) != 0) @@ -286,34 +282,31 @@ static void _time_check(const struct timeval t0, const int ok) * and try generating a signature with that. */ -static int test_rsa(hal_core_t *core, const rsa_tc_t * const tc) +static int test_rsa(const rsa_tc_t * const tc) { int ok = 1; /* RSA encryption */ - time_check(test_modexp(core, "Verification", tc, &tc->s, &tc->e, &tc->m)); + time_check(test_modexp("Verification", tc, &tc->s, &tc->e, &tc->m)); /* Brute force RSA decryption */ - time_check(test_modexp(core, "Signature (ModExp)", tc, &tc->m, &tc->d, &tc->s)); + time_check(test_modexp("Signature (ModExp)", tc, &tc->m, &tc->d, &tc->s)); /* RSA decyrption using CRT */ - time_check(test_decrypt(core, "Signature (CRT)", tc)); + time_check(test_decrypt("Signature (CRT)", tc)); /* Key generation and CRT -- not test vector, so writes key and sig to file */ - time_check(test_gen(core, "Generation and CRT", tc)); + time_check(test_gen("Generation and CRT", tc)); return ok; } int main(void) { - hal_core_t *core = hal_core_find(MODEXPS6_NAME, NULL); - if (core == NULL) - core = hal_core_find(MODEXPA7_NAME, NULL); - const hal_core_info_t *core_info = hal_core_info(core); + const hal_core_info_t *info = hal_core_info(hal_core_find(MODEXPA7_NAME, NULL)); - if (core_info != NULL) - printf("\"%8.8s\" \"%4.4s\"\n\n", core_info->name, core_info->version); + if (info != NULL) + printf("\"%8.8s\" \"%4.4s\"\n\n", info->name, info->version); /* * Run the test cases. @@ -324,7 +317,7 @@ int main(void) /* Normal test */ for (size_t i = 0; i < (sizeof(rsa_tc)/sizeof(*rsa_tc)); i++) - if (!test_rsa(core, &rsa_tc[i])) + if (!test_rsa(&rsa_tc[i])) return 1; return 0; @@ -33,7 +33,6 @@ */ #include <stdio.h> -#include <assert.h> #include "hal.h" #include "hal_internal.h" |