diff options
-rw-r--r-- | aes_keywrap.c | 176 | ||||
-rw-r--r-- | core.c | 1 | ||||
-rw-r--r-- | hal.h | 5 | ||||
-rw-r--r-- | verilog_constants.h | 25 |
4 files changed, 172 insertions, 35 deletions
diff --git a/aes_keywrap.c b/aes_keywrap.c index 144ad68..b849304 100644 --- a/aes_keywrap.c +++ b/aes_keywrap.c @@ -4,8 +4,9 @@ * Implementation of RFC 5649 over Cryptech AES core. * * Authors: Rob Austein - * Copyright (c) 2015-2017, NORDUnet A/S - * All rights reserved. + * Copyright (c) 2015-2018, NORDUnet A/S All rights reserved. + * Copyright: 2020, The Commons Conservancy Cryptech Project + * SPDX-License-Identifier: BSD-3-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -17,9 +18,9 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * - Neither the name of the NORDUnet nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. + * - Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -50,7 +51,21 @@ #include "hal_internal.h" /* + * Enable use of the experimental keywrap core, if present. + */ + +static int use_keywrap_core = 0; + +int hal_aes_use_keywrap_core(int onoff) +{ + use_keywrap_core = (onoff && hal_core_find(KEYWRAP_NAME, NULL) != NULL); + return use_keywrap_core; +} + + +/* * How long the ciphertext will be for a given plaintext length. + * This rounds up the length to a multiple of 8, and adds 8 for the IV. */ size_t hal_aes_keywrap_ciphertext_length(const size_t plaintext_length) @@ -62,6 +77,8 @@ size_t hal_aes_keywrap_ciphertext_length(const size_t plaintext_length) /* * Check the KEK, then load it into the AES core. * Note that our AES core only supports 128 and 256 bit keys. + * + * This should work without modification for the experimental keywrap core. */ typedef enum { KEK_encrypting, KEK_decrypting } kek_action_t; @@ -114,6 +131,57 @@ static hal_error_t load_kek(const hal_core_t *core, const uint8_t *K, const size /* + * Use the experimental keywrap core to wrap/unwrap n 64-bit blocks of plaintext. + * The wrapped/unwrapped key is returned in the same buffer. + */ + +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); + + /* n is the number of 64-bit (8-byte) blocks in the input. + * KEYWRAP_LEN_R_DATA is the number of 4-byte data registers in the core. + */ + if (n == 0 || n > KEYWRAP_LEN_R_DATA * 2) + return HAL_ERROR_BAD_ARGUMENTS; + + /* write the AIV to A */ + if ((err = hal_io_write(core, KEYWRAP_ADDR_A0, C, 8)) != HAL_OK) + return err; + + /* write the length to RLEN */ + uint32_t nn = htonl(n); + if ((err = hal_io_write(core, KEYWRAP_ADDR_RLEN, (const uint8_t *)&nn, 4)) != HAL_OK) + return err; + + /* write the data to R_DATA */ + if ((err = hal_io_write(core, KEYWRAP_ADDR_R_DATA, C + 8, 8 * n)) != HAL_OK) + return err; + + /* start the wrap/unwrap operation, and wait for it to complete */ + if ((err = hal_io_next(core)) != HAL_OK || + (err = hal_io_wait_ready(core)) != HAL_OK) + return err; + + /* read the A registers */ + if ((err = hal_io_read(core, KEYWRAP_ADDR_A0, C, 8)) != HAL_OK) + return err; + + /* read the data to R_DATA */ + if ((err = hal_io_read(core, KEYWRAP_ADDR_R_DATA, C + 8, 8 * n)) != HAL_OK) + return err; + + return HAL_OK; +} + + +/* * Process one block. Since AES Key Wrap always deals with 64-bit * half blocks and since the bus is going to break this up into 32-bit * words no matter what we do, we can eliminate a few gratuitous @@ -163,7 +231,7 @@ 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; + const int free_core = (core == NULL); hal_error_t err; size_t n; @@ -172,8 +240,22 @@ hal_error_t hal_aes_keywrap(hal_core_t *core, if (Q == NULL || C == NULL || C_len == NULL || *C_len < calculated_C_len) return HAL_ERROR_BAD_ARGUMENTS; - if (free_core && (err = hal_core_alloc(AES_CORE_NAME, &core, NULL)) != HAL_OK) - return err; + /* If we're passed a core, we should figure out which one it is. + * In practice, core is always NULL, so this is UNTESTED CODE. + */ + if (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) + /* I have no idea what this is */ + return HAL_ERROR_BAD_ARGUMENTS; + } + else { + const char *core_name = (use_keywrap_core ? KEYWRAP_NAME : AES_CORE_NAME); + if ((err = hal_core_alloc(core_name, &core, NULL)) != HAL_OK) + return err; + } if ((err = load_kek(core, K, K_len, KEK_encrypting)) != HAL_OK) goto out; @@ -195,21 +277,26 @@ hal_error_t hal_aes_keywrap(hal_core_t *core, n = calculated_C_len/8 - 1; - if (n == 1) { - if ((err = do_block(core, C, C + 8)) != HAL_OK) - goto out; + if (use_keywrap_core) { + err = do_keywrap_core(core, C, n); } - else { - for (size_t j = 0; j <= 5; j++) { - for (size_t i = 1; i <= n; i++) { - uint32_t t = n * j + i; - if ((err = do_block(core, C, C + i * 8)) != HAL_OK) + if (n == 1) { + if ((err = do_block(core, C, C + 8)) != HAL_OK) + goto out; + } + + else { + for (size_t j = 0; j <= 5; j++) { + for (size_t i = 1; i <= n; i++) { + uint32_t t = n * j + i; + if ((err = do_block(core, C, C + i * 8)) != HAL_OK) goto out; - C[7] ^= t & 0xFF; t >>= 8; - C[6] ^= t & 0xFF; t >>= 8; - C[5] ^= t & 0xFF; t >>= 8; - C[4] ^= t & 0xFF; + C[7] ^= t & 0xFF; t >>= 8; + C[6] ^= t & 0xFF; t >>= 8; + C[5] ^= t & 0xFF; t >>= 8; + C[4] ^= t & 0xFF; + } } } } @@ -242,8 +329,22 @@ 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 (free_core && (err = hal_core_alloc(AES_CORE_NAME, &core, NULL)) != HAL_OK) - return err; + /* If we're passed a core, we should figure out which one it is. + * In practice, core is always NULL, so this is UNTESTED CODE. + */ + if (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) + /* I have no idea what this is */ + return HAL_ERROR_BAD_ARGUMENTS; + } + else { + const char *core_name = (use_keywrap_core ? KEYWRAP_NAME : AES_CORE_NAME); + if ((err = hal_core_alloc(core_name, &core, NULL)) != HAL_OK) + return err; + } if ((err = load_kek(core, K, K_len, KEK_decrypting)) != HAL_OK) goto out; @@ -253,21 +354,26 @@ hal_error_t hal_aes_keyunwrap(hal_core_t *core, if (Q != C) memmove(Q, C, C_len); - if (n == 1) { - if ((err = do_block(core, Q, Q + 8)) != HAL_OK) - goto out; + if (use_keywrap_core) { + err = do_keywrap_core(core, Q, n); } - else { - for (long j = 5; j >= 0; j--) { - for (size_t i = n; i >= 1; i--) { - uint32_t t = n * j + i; - Q[7] ^= t & 0xFF; t >>= 8; - Q[6] ^= t & 0xFF; t >>= 8; - Q[5] ^= t & 0xFF; t >>= 8; - Q[4] ^= t & 0xFF; - if ((err = do_block(core, Q, Q + i * 8)) != HAL_OK) - goto out; + if (n == 1) { + if ((err = do_block(core, Q, Q + 8)) != HAL_OK) + goto out; + } + + else { + for (long j = 5; j >= 0; j--) { + for (size_t i = n; i >= 1; i--) { + uint32_t t = n * j + i; + Q[7] ^= t & 0xFF; t >>= 8; + Q[6] ^= t & 0xFF; t >>= 8; + Q[5] ^= t & 0xFF; t >>= 8; + Q[4] ^= t & 0xFF; + if ((err = do_block(core, Q, Q + i * 8)) != HAL_OK) + goto out; + } } } } @@ -104,6 +104,7 @@ static inline hal_core_t *probe_cores(void) { "modexps6", 3 * CORE_SIZE }, /* ModexpS6 uses four slots */ { "modexpa7", 7 * CORE_SIZE }, /* ModexpA7 uses eight slots */ { "modexpng", 15 * CORE_SIZE }, /* ModexpNG uses 16 slots */ + { "key wrap", 31 * CORE_SIZE }, /* keywrap uses 32 slots */ }; if (offsetof(hal_core_t, info) != 0) @@ -123,6 +123,9 @@ #define ECDSA384_NAME "ecdsa384" #define ECDSA384_VERSION "0.20" +#define KEYWRAP_NAME "key wrap" +#define KEYWRAP_VERSION "0.70" + /* * C API error codes. Defined in this form so we can keep the tokens * and error strings together. See errorstrings.c. @@ -377,6 +380,8 @@ 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(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/verilog_constants.h b/verilog_constants.h index bd31ee3..db75294 100644 --- a/verilog_constants.h +++ b/verilog_constants.h @@ -42,6 +42,7 @@ #ifndef _VERILOG_CONSTANTS_H_ #define _VERILOG_CONSTANTS_H_ + /* * Common to all cores. */ @@ -342,6 +343,30 @@ #define MKMIF_ADDR_EMEM_ADDR (0x10) #define MKMIF_ADDR_EMEM_DATA (0x20) +/* + * AES Keywrap core + */ + +#define KEYWRAP_ADDR_CONFIG (0x0a) +#define KEYWRAP_CONFIG_ENCDEC (1) +#define KEYWRAP_CONFIG_KEYLEN (2) + +#define KEYWRAP_ADDR_RLEN (0x0c) +#define KEYWRAP_ADDR_A0 (0x0e) +#define KEYWRAP_ADDR_A1 (0x0f) + +#define KEYWRAP_ADDR_KEY0 (0x10) +#define KEYWRAP_ADDR_KEY1 (0x11) +#define KEYWRAP_ADDR_KEY2 (0x12) +#define KEYWRAP_ADDR_KEY3 (0x13) +#define KEYWRAP_ADDR_KEY4 (0x14) +#define KEYWRAP_ADDR_KEY5 (0x15) +#define KEYWRAP_ADDR_KEY6 (0x16) +#define KEYWRAP_ADDR_KEY7 (0x17) + +#define KEYWRAP_ADDR_R_DATA (0x1000) +#define KEYWRAP_LEN_R_DATA (0x1000) + #endif /* _VERILOG_CONSTANTS_H_ */ /* |