From 9bf6075da2640dc57d5a9de5825a249cb3f827c3 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Tue, 5 Feb 2019 13:11:19 -0500 Subject: Track Joachim's latest keywrap core - KEK remains in the AES core until it times out or is explicitly zeroed out. --- aes_keywrap.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++------ hal.h | 9 +++++ ks.c | 19 ++-------- verilog_constants.h | 4 ++ 4 files changed, 109 insertions(+), 27 deletions(-) diff --git a/aes_keywrap.c b/aes_keywrap.c index a3e223f..63e0cf7 100644 --- a/aes_keywrap.c +++ b/aes_keywrap.c @@ -53,7 +53,7 @@ * Enable use of the experimental keywrap core, if present. */ -static int use_keywrap_core = 0; +static int use_keywrap_core = 1; int hal_aes_use_keywrap_core(int onoff) { @@ -82,17 +82,102 @@ size_t hal_aes_keywrap_ciphertext_length(const size_t plaintext_length) typedef enum { KEK_encrypting, KEK_decrypting } kek_action_t; +static unsigned _kek_load = 0, _kek_skip = 0; + +hal_error_t hal_aes_keywrap_get_stats(unsigned *load, unsigned *skip) +{ + if (load == NULL || skip == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + *load = _kek_load; + *skip = _kek_skip; + + return HAL_OK; +} + +void hal_aes_keywrap_reset_stats(void) +{ + _kek_load = _kek_skip = 0; +} + +hal_error_t hal_aes_keywrap_zero(hal_core_t *core) +{ + const int free_core = (core == NULL); + hal_error_t err; + + if (core == NULL && + (err = hal_core_alloc(KEYWRAP_NAME, &core, NULL)) != HAL_OK) + return err; + + uint8_t buf[4] = { 0, 0, 0, KEYWRAP_CTRL_ZERO }; + err = hal_io_write(core, ADDR_CTRL, buf, sizeof(buf)); + + if (free_core) + hal_core_free(core); + return err; +} + +hal_error_t hal_aes_keywrap_set_timeout(hal_core_t *core, uint32_t cycles) +{ + const int free_core = (core == NULL); + hal_error_t err; + + if (core == NULL && + (err = hal_core_alloc(KEYWRAP_NAME, &core, NULL)) != HAL_OK) + return err; + + union { + uint32_t word; + uint8_t bytes[4]; + } buf; + buf.word = htonl(cycles); + err = hal_io_write(core, KEYWRAP_ADDR_TIMEOUT, buf.bytes, sizeof(buf)); + + if (free_core) + hal_core_free(core); + return err; +} + +static inline int is_kek_loaded(const hal_core_t *core) +{ + uint8_t buf[4]; + + if (hal_io_read(core, ADDR_STATUS, buf, sizeof(buf)) == HAL_OK) + return (buf[3] & KEYWRAP_STATUS_LOADED); + + return 0; +} + static hal_error_t load_kek(const hal_core_t *core, const uint8_t *K, const size_t K_len, const kek_action_t action) { + static size_t kek_len = 0; uint8_t config[4]; hal_error_t err; - if (K == NULL) - return HAL_ERROR_BAD_ARGUMENTS; + if (K != NULL) { + kek_len = K_len; + if ((err = hal_io_write(core, AES_ADDR_KEY0, K, K_len)) != HAL_OK) + return err; + } + else if (!use_keywrap_core || !is_kek_loaded(core)) { + ++_kek_load; + uint8_t kek[KEK_LENGTH]; + + if ((err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek))) == HAL_OK) + err = hal_io_write(core, AES_ADDR_KEY0, kek, kek_len); + + memset(kek, 0, sizeof(kek)); + + if (err != HAL_OK) + return err; + } + else { + ++_kek_skip; + } memset(config, 0, sizeof(config)); - switch (K_len) { + switch (kek_len) { case bitsToBytes(128): config[3] &= ~AES_CONFIG_KEYLEN; break; @@ -120,8 +205,7 @@ static hal_error_t load_kek(const hal_core_t *core, const uint8_t *K, const size * Load the KEK and tell the core to expand it. */ - if ((err = hal_io_write(core, AES_ADDR_KEY0, K, K_len)) != HAL_OK || - (err = hal_io_write(core, AES_ADDR_CONFIG, config, sizeof(config))) != HAL_OK || + if ((err = hal_io_write(core, AES_ADDR_CONFIG, config, sizeof(config))) != HAL_OK || (err = hal_io_init(core)) != HAL_OK) return err; @@ -136,10 +220,6 @@ static hal_error_t load_kek(const hal_core_t *core, const uint8_t *K, const size static hal_error_t do_keywrap_core(const hal_core_t *core, uint8_t * const C, const size_t n) { -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - hal_error_t err; hal_assert(core != NULL && C != NULL && n > 0); @@ -246,7 +326,9 @@ hal_error_t hal_aes_keywrap(hal_core_t *core, const hal_core_info_t *info = hal_core_info(core); if (memcmp(info->name, KEYWRAP_NAME, 8) == 0) use_keywrap_core = 1; - else if (memcmp(info->name, AES_CORE_NAME, 8) != 0) + else if (memcmp(info->name, AES_CORE_NAME, 8) == 0) + use_keywrap_core = 0; + else /* I have no idea what this is */ return HAL_ERROR_BAD_ARGUMENTS; } diff --git a/hal.h b/hal.h index 9986de7..ce8ee2f 100644 --- a/hal.h +++ b/hal.h @@ -366,8 +366,17 @@ extern const hal_hash_descriptor_t *hal_hmac_get_descriptor(const hal_hmac_state * AES key wrap functions. */ + extern int hal_aes_use_keywrap_core(int onoff); +extern hal_error_t hal_aes_keywrap_get_stats(unsigned *load, unsigned *skip); + +extern void hal_aes_keywrap_reset_stats(void); + +extern hal_error_t hal_aes_keywrap_zero(hal_core_t *core); + +extern hal_error_t hal_aes_keywrap_set_timeout(hal_core_t *core, uint32_t cycles); + extern hal_error_t hal_aes_keywrap(hal_core_t *core, const uint8_t *kek, const size_t kek_length, const uint8_t *plaintext, const size_t plaintext_length, diff --git a/ks.c b/ks.c index a682cd2..51ea303 100644 --- a/ks.c +++ b/ks.c @@ -536,9 +536,6 @@ static hal_error_t construct_key_block(hal_ks_block_t *block, return HAL_ERROR_IMPOSSIBLE; hal_ks_key_block_t *k = &block->key; - hal_error_t err = HAL_OK; - uint8_t kek[KEK_LENGTH]; - size_t kek_len; memset(block, 0xFF, sizeof(*block)); @@ -552,12 +549,7 @@ static hal_error_t construct_key_block(hal_ks_block_t *block, k->der_len = SIZEOF_KS_KEY_BLOCK_DER; k->attributes_len = 0; - if ((err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek))) == HAL_OK) - err = hal_aes_keywrap(NULL, kek, kek_len, der, der_len, k->der, &k->der_len); - - memset(kek, 0, sizeof(kek)); - - return err; + return hal_aes_keywrap(NULL, NULL, 0, der, der_len, k->der, &k->der_len); } /* @@ -658,19 +650,14 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks, if (der != NULL) { - uint8_t kek[KEK_LENGTH]; - size_t kek_len, der_len_; - hal_error_t err; + size_t der_len_; if (der_len == NULL) der_len = &der_len_; *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, der, k_der_len, der, der_len); - - memset(kek, 0, sizeof(kek)); + err = hal_aes_keyunwrap(NULL, NULL, 0, der, k_der_len, der, der_len); } return err; diff --git a/verilog_constants.h b/verilog_constants.h index 8735b12..f058737 100644 --- a/verilog_constants.h +++ b/verilog_constants.h @@ -303,10 +303,14 @@ * AES Keywrap core */ +#define KEYWRAP_CTRL_ZERO (4) +#define KEYWRAP_STATUS_LOADED (4) + #define KEYWRAP_ADDR_CONFIG (0x0a) #define KEYWRAP_CONFIG_ENCDEC (1) #define KEYWRAP_CONFIG_KEYLEN (2) +#define KEYWRAP_ADDR_TIMEOUT (0x0b) #define KEYWRAP_ADDR_RLEN (0x0c) #define KEYWRAP_ADDR_A0 (0x0e) #define KEYWRAP_ADDR_A1 (0x0f) -- cgit v1.2.3 From e529855f7e15a14fed0ee16c9af1b55d7c55c660 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Wed, 13 Feb 2019 16:05:42 -0500 Subject: If a KEK is given to keywrap/unwrap, zero it out of the keywrap core after use. The key-export mechanism unwraps the key with the KEK from Master Key Memory, then re-wraps it with a random KEK. If that random KEK stays in the keywrap core, it will cause problems for all subsequent wrap/unwrap operations. --- aes_keywrap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aes_keywrap.c b/aes_keywrap.c index 63e0cf7..1ee857b 100644 --- a/aes_keywrap.c +++ b/aes_keywrap.c @@ -383,6 +383,8 @@ hal_error_t hal_aes_keywrap(hal_core_t *core, } out: + if (K != NULL) + hal_aes_keywrap_zero(core); if (free_core) hal_core_free(core); return err; @@ -483,6 +485,8 @@ hal_error_t hal_aes_keyunwrap(hal_core_t *core, memmove(Q, Q + 8, m); out: + if (K != NULL) + hal_aes_keywrap_zero(core); if (free_core) hal_core_free(core); return err; -- cgit v1.2.3