From 401965f1e9f74b43c88477d2ff6ac4d6c62ab5a8 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Tue, 28 Apr 2020 12:11:49 -0400 Subject: The new keywrap core now talks directly to the MKM, so I split the code that talks to that core out of aes_keywrap.c. The HSM will now be built with just the keywrap core, with no user access to aes or mkmif. --- Makefile | 2 +- aes_keywrap.c | 193 ++++------------------- hal.h | 22 ++- keywrap.c | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ks.c | 19 +-- rpc_pkey.c | 4 +- verilog_constants.h | 9 +- 7 files changed, 500 insertions(+), 185 deletions(-) create mode 100644 keywrap.c diff --git a/Makefile b/Makefile index 3e0f515..57b7d18 100644 --- a/Makefile +++ b/Makefile @@ -99,7 +99,7 @@ OBJ += rpc_api.o rpc_hash.o uuid.o rpc_pkcs1.o crc32.o locks.o logging.o # Object files to build when we're on a platform with direct access # to our hardware (Verilog) cores. -CORE_OBJ = core.o csprng.o pbkdf2.o aes_keywrap.o modexp.o mkmif.o ${IO_OBJ} +CORE_OBJ = core.o csprng.o pbkdf2.o aes_keywrap.o keywrap.o modexp.o mkmif.o ${IO_OBJ} # I/O bus to the FPGA # diff --git a/aes_keywrap.c b/aes_keywrap.c index 3a5ce2e..8680588 100644 --- a/aes_keywrap.c +++ b/aes_keywrap.c @@ -50,44 +50,6 @@ #include "hal.h" #include "hal_internal.h" -/* - * Enable use of the keywrap core, if present. - */ - -static enum { - unknown = -1, - aes_core = 0, - keywrap_core = 1 -} which_core = unknown; - -static char *core_name[] = { - AES_CORE_NAME, - KEYWRAP_NAME -}; - -static inline hal_error_t init_aes_keywrap(void) -{ - if (which_core != unknown) - return HAL_OK; - else if (hal_core_find(KEYWRAP_NAME, NULL) != NULL) - return (which_core = keywrap_core), HAL_OK; - else if (hal_core_find(AES_CORE_NAME, NULL) != NULL) - return (which_core = aes_core), HAL_OK; - else - return HAL_ERROR_CORE_NOT_FOUND; -} - -hal_error_t hal_aes_use_keywrap_core(int onoff) -{ - if (onoff && hal_core_find(KEYWRAP_NAME, NULL) != NULL) - return (which_core = keywrap_core), HAL_OK; - else if (!onoff && hal_core_find(AES_CORE_NAME, NULL) != NULL) - return (which_core = aes_core), HAL_OK; - else - return HAL_ERROR_CORE_NOT_FOUND; -} - - /* * 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. @@ -102,8 +64,6 @@ 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; @@ -155,57 +115,6 @@ 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 from 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 @@ -265,24 +174,8 @@ 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 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) - which_core = keywrap_core; - else if (memcmp(info->name, AES_CORE_NAME, 8) == 0) - which_core = aes_core; - else - /* I have no idea what this is */ - return HAL_ERROR_BAD_ARGUMENTS; - } - else { - if ((err = init_aes_keywrap()) != HAL_OK || - (err = hal_core_alloc(core_name[which_core], &core, NULL)) != HAL_OK) - return err; - } + 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) goto out; @@ -308,26 +201,21 @@ hal_error_t hal_aes_keywrap(hal_core_t *core, if ((err = hal_io_wait_ready(core)) != HAL_OK) goto out; - if (which_core == keywrap_core) { - err = do_keywrap_core(core, C, n); + if (n == 1) { + if ((err = do_block(core, C, C + 8)) != HAL_OK) + goto out; } - else { - 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; - } + 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; } } } @@ -360,24 +248,8 @@ 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 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) - which_core = keywrap_core; - else if (memcmp(info->name, AES_CORE_NAME, 8) == 0) - which_core = aes_core; - else - /* I have no idea what this is */ - return HAL_ERROR_BAD_ARGUMENTS; - } - else { - if ((err = init_aes_keywrap()) != HAL_OK || - (err = hal_core_alloc(core_name[which_core], &core, NULL)) != HAL_OK) - return err; - } + 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) goto out; @@ -391,26 +263,21 @@ hal_error_t hal_aes_keyunwrap(hal_core_t *core, if ((err = hal_io_wait_ready(core)) != HAL_OK) goto out; - if (which_core == keywrap_core) { - err = do_keywrap_core(core, Q, n); + if (n == 1) { + if ((err = do_block(core, Q, Q + 8)) != HAL_OK) + goto out; } - else { - 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; - } + 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; } } } diff --git a/hal.h b/hal.h index a03c891..6ed8c9d 100644 --- a/hal.h +++ b/hal.h @@ -380,8 +380,6 @@ extern const hal_hash_descriptor_t *hal_hmac_get_descriptor(const hal_hmac_state * AES key wrap functions. */ -extern hal_error_t 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, @@ -394,6 +392,26 @@ extern hal_error_t hal_aes_keyunwrap(hal_core_t *core, extern size_t hal_aes_keywrap_ciphertext_length(const size_t plaintext_length); +/* + * New keywrap functions + */ + +extern hal_error_t hal_keywrap_mkm_status(hal_core_t *core); + +extern hal_error_t hal_keywrap_mkm_write(hal_core_t *core, const uint8_t *K, const size_t K_len); + +extern hal_error_t hal_keywrap_mkm_erase(hal_core_t *core, const size_t K_len); + +extern hal_error_t hal_keywrap_wrap(hal_core_t *core, + const uint8_t *kek, const size_t kek_length, + const uint8_t *plaintext, const size_t plaintext_length, + uint8_t *cyphertext, size_t *ciphertext_length); + +extern hal_error_t hal_keywrap_unwrap(hal_core_t *core, + const uint8_t *kek, const size_t kek_length, + const uint8_t *ciphertext, const size_t ciphertext_length, + uint8_t *plaintext, size_t *plaintext_length); + /* * PBKDF2 function. Uses HMAC with the specified digest algorithm as * the pseudo-random function (PRF). diff --git a/keywrap.c b/keywrap.c new file mode 100644 index 0000000..ccf7ea8 --- /dev/null +++ b/keywrap.c @@ -0,0 +1,436 @@ +/* + * keywrap.c + * --------- + * Implementation of RFC 5649 over Cryptech keywrap core. + * + * Authors: Rob Austein + * 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 + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 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 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is derived from aes_keywrap.c, and still shares some code + * with it, but the keywrap core has evolved to the point where it is no + * longer comfortable trying to support both cores in one driver. + */ + +#include +#include + +#include "hal.h" +#include "hal_internal.h" + +typedef union { + uint8_t b[4]; + uint32_t w; +} byteword_t; + +/* + * Match uninitialized flash for the "not set" value. + * Leave some bits at 1 for the "set" value to allow + * for adding more values later, if needed. + */ +#define MKM_STATUS_NOT_SET 0xffffffff +#define MKM_STATUS_SET 0x0000ffff +#define MKM_STATUS_ERASED 0x00000000 + +static hal_error_t mkm_status = HAL_ERROR_IMPOSSIBLE; + + +static inline hal_error_t hal_io_cmd_read(const hal_core_t *core) +{ + const uint8_t buf[4] = { 0, 0, 0, KEYWRAP_CTRL_READ }; + return hal_io_write(core, ADDR_CTRL, buf, sizeof(buf)); +} + +static inline hal_error_t hal_io_cmd_write(const hal_core_t *core) +{ + const uint8_t buf[4] = { 0, 0, 0, KEYWRAP_CTRL_WRITE }; + return hal_io_write(core, ADDR_CTRL, buf, sizeof(buf)); +} + + +/* + * Check the MKM status + */ + +hal_error_t hal_keywrap_mkm_status(hal_core_t *core) +{ + const int free_core = core == NULL; + uint8_t config[4] = { 0, 0, 0, 0 }; + byteword_t status; + hal_error_t err; + + if (free_core && (err = hal_core_alloc(KEYWRAP_NAME, &core, NULL)) != HAL_OK) + return err; + + if ((err = hal_io_write(core, KEYWRAP_ADDR_CONFIG, config, sizeof(config))) == HAL_OK && + (err = hal_io_cmd_read(core)) == HAL_OK && + (err = hal_io_wait_ready(core)) == HAL_OK) + err = hal_io_read(core, KEYWRAP_ADDR_MSTATUS, status.b, 4); + + if (free_core) + hal_core_free(core); + + if (err != HAL_OK) + return err; + + switch (htonl(status.w)) { + case MKM_STATUS_SET: return mkm_status = HAL_OK; + case MKM_STATUS_NOT_SET: return mkm_status = HAL_ERROR_MASTERKEY_NOT_SET; + default: return mkm_status = HAL_ERROR_MASTERKEY_FAIL; + } +} + +hal_error_t hal_keywrap_mkm_write(hal_core_t *core, const uint8_t *K, const size_t K_len) +{ + const int free_core = core == NULL; + uint8_t config[4] = { 0, 0, 0, 0 }; + byteword_t status; + hal_error_t err; + + if (K == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + if (K_len != KEK_LENGTH) + return HAL_ERROR_MASTERKEY_BAD_LENGTH; + + status.w = htonl(MKM_STATUS_NOT_SET); + for (size_t i = 0; i < K_len; ++i) { + if (K[i] != 0) { + status.w = htonl(MKM_STATUS_SET); + break; + } + } + + if (free_core && (err = hal_core_alloc(KEYWRAP_NAME, &core, NULL)) != HAL_OK) + return err; + + /* first write the key */ + config[3] |= KEYWRAP_CONFIG_MKS; + if ((err = hal_io_write(core, KEYWRAP_ADDR_KEY0, K, K_len)) != HAL_OK || + (err = hal_io_write(core, KEYWRAP_ADDR_CONFIG, config, sizeof(config))) != HAL_OK || + (err = hal_io_cmd_write(core)) != HAL_OK || + (err = hal_io_wait_ready(core)) != HAL_OK) + goto out; + + /* then write the status */ + config[3] &= ~KEYWRAP_CONFIG_MKS; + if ((err = hal_io_write(core, KEYWRAP_ADDR_MSTATUS, status.b, 4)) != HAL_OK || + (err = hal_io_write(core, KEYWRAP_ADDR_CONFIG, config, sizeof(config))) != HAL_OK || + (err = hal_io_cmd_write(core)) != HAL_OK || + (err = hal_io_wait_ready(core)) != HAL_OK) + goto out; + +out: + if (free_core) + hal_core_free(core); + + return err; +} + +hal_error_t hal_keywrap_mkm_erase(hal_core_t *core, const size_t K_len) +{ + uint8_t buf[KEK_LENGTH] = { 0 }; + + return hal_keywrap_mkm_write(core, buf, sizeof(buf)); +} + +/* + * 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. + */ + +static size_t hal_keywrap_ciphertext_length(const size_t plaintext_length) +{ + return (plaintext_length + 15) & ~7; +} + +/* + * Check the KEK, then load it into the AES core. + * Note that our AES core only supports 128 and 256 bit keys. + */ + +typedef enum { KEK_encrypting, KEK_decrypting } kek_action_t; + +static hal_error_t load_kek(hal_core_t *core, const uint8_t *K, const size_t K_len, const kek_action_t action) +{ + uint8_t config[4] = { 0 }; + hal_error_t err; + + if (K != NULL) { + /* user-provided KEK, for key export/import */ + config[3] |= KEYWRAP_CONFIG_MKK; + + if ((err = hal_io_write(core, AES_ADDR_KEY0, K, K_len)) != HAL_OK) + return err; + + switch (K_len) { + case bitsToBytes(128): + config[3] &= ~KEYWRAP_CONFIG_KEYLEN; + break; + case bitsToBytes(256): + config[3] |= KEYWRAP_CONFIG_KEYLEN; + break; + case bitsToBytes(192): + return HAL_ERROR_UNSUPPORTED_KEY; + default: + return HAL_ERROR_BAD_ARGUMENTS; + } + } + + else { + /* read the MKM KEK into the keywrap core */ + if (mkm_status != HAL_OK && + (err = hal_keywrap_mkm_status(core)) != HAL_OK) + return err; + + config[3] &= ~KEYWRAP_CONFIG_MKS; + if ((err = hal_io_write(core, KEYWRAP_ADDR_CONFIG, config, sizeof(config))) != HAL_OK || + (err = hal_io_cmd_read(core)) != HAL_OK || + (err = hal_io_wait_ready(core)) != HAL_OK) + return err; + + config[3] &= ~KEYWRAP_CONFIG_MKK; + config[3] |= KEYWRAP_CONFIG_KEYLEN; /* XXX hardwire to 256-bits for now */ + } + + switch (action) { + case KEK_encrypting: + config[3] |= KEYWRAP_CONFIG_ENCDEC; + break; + case KEK_decrypting: + config[3] &= ~KEYWRAP_CONFIG_ENCDEC; + break; + default: + return HAL_ERROR_BAD_ARGUMENTS; + } + + /* + * Load the KEK and tell the core to expand it. + */ + + if ((err = hal_io_write(core, KEYWRAP_ADDR_CONFIG, config, sizeof(config))) != HAL_OK || + (err = hal_io_init(core)) != HAL_OK) + return err; + + return HAL_OK; +} + + +/* + * Wrap/unwrap n 64-bit blocks of plaintext. + * The wrapped/unwrapped key is returned in the same buffer. + */ + +static hal_error_t do_wrap_unwrap(hal_core_t *core, uint8_t * const C, const size_t n) +{ + 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 from R_DATA */ + if ((err = hal_io_read(core, KEYWRAP_ADDR_R_DATA, C + 8, 8 * n)) != HAL_OK) + return err; + + return HAL_OK; +} + + +/* + * Wrap plaintext Q using KEK K, placing result in C. + * + * Q and C can overlap. For encrypt-in-place, use Q = C + 8 (that is, + * leave 8 empty bytes before the plaintext). + * + * Use hal_keywrap_ciphertext_length() to calculate the correct + * buffer size. + */ + +hal_error_t hal_keywrap_wrap(hal_core_t *core, + const uint8_t *K, const size_t K_len, + const uint8_t * const Q, + const size_t Q_len, + uint8_t *C, + size_t *C_len) +{ + const size_t calculated_C_len = hal_keywrap_ciphertext_length(Q_len); + const int free_core = (core == NULL); + hal_error_t err; + size_t n; + + 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 (free_core && (err = hal_core_alloc(KEYWRAP_NAME, &core, NULL)) != HAL_OK) + return err; + + if ((err = load_kek(core, K, K_len, KEK_encrypting)) != HAL_OK) + goto out; + + *C_len = calculated_C_len; + + if (C + 8 != Q) + memmove(C + 8, Q, Q_len); + if (Q_len % 8 != 0) + memset(C + 8 + Q_len, 0, 8 - (Q_len % 8)); + C[0] = 0xA6; + C[1] = 0x59; + C[2] = 0x59; + C[3] = 0xA6; + C[4] = (Q_len >> 24) & 0xFF; + C[5] = (Q_len >> 16) & 0xFF; + C[6] = (Q_len >> 8) & 0xFF; + C[7] = (Q_len >> 0) & 0xFF; + + n = calculated_C_len/8 - 1; + + /* Make sure the key expansion has completed. */ + if ((err = hal_io_wait_ready(core)) != HAL_OK) + goto out; + + err = do_wrap_unwrap(core, C, n); + +out: + if (free_core) + hal_core_free(core); + return err; +} + + +/* + * Unwrap ciphertext C using KEK K, placing result in Q. + * + * Q should be the same size as C. Q and C can overlap. + */ + +hal_error_t hal_keywrap_unwrap(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; + + 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(KEYWRAP_NAME, &core, NULL)) != HAL_OK) + return err; + + if ((err = load_kek(core, K, K_len, KEK_decrypting)) != HAL_OK) + goto out; + + n = (C_len / 8) - 1; + + if (Q != C) + memmove(Q, C, C_len); + + /* Make sure the key expansion has completed. */ + if ((err = hal_io_wait_ready(core)) != HAL_OK) + goto out; + + if ((err = do_wrap_unwrap(core, Q, n)) != HAL_OK) + goto out; + + if (Q[0] != 0xA6 || Q[1] != 0x59 || Q[2] != 0x59 || Q[3] != 0xA6) { + err = HAL_ERROR_KEYWRAP_BAD_MAGIC; + goto out; + } + + m = (((((Q[4] << 8) + Q[5]) << 8) + Q[6]) << 8) + Q[7]; + + if (m <= 8 * (n - 1) || m > 8 * n) { + err = HAL_ERROR_KEYWRAP_BAD_LENGTH; + goto out; + } + + if (m % 8 != 0) + for (size_t i = m + 8; i < 8 * (n + 1); i++) + if (Q[i] != 0x00) { + err = HAL_ERROR_KEYWRAP_BAD_PADDING; + goto out; + } + + *Q_len = m; + + memmove(Q, Q + 8, m); + +out: + if (free_core) + hal_core_free(core); + return err; +} + +/* + * "Any programmer who fails to comply with the standard naming, formatting, + * or commenting conventions should be shot. If it so happens that it is + * inconvenient to shoot him, then he is to be politely requested to recode + * his program in adherence to the above standard." + * -- Michael Spier, Digital Equipment Corporation + * + * Local variables: + * indent-tabs-mode: nil + * End: + */ diff --git a/ks.c b/ks.c index 72bb0fe..5f81132 100644 --- a/ks.c +++ b/ks.c @@ -538,9 +538,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)); @@ -554,12 +551,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_keywrap_wrap(NULL, NULL, 0, der, der_len, k->der, &k->der_len); } /* @@ -660,19 +652,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_keywrap_unwrap(NULL, NULL, 0, der, k_der_len, der, der_len); } return err; diff --git a/rpc_pkey.c b/rpc_pkey.c index 84e506d..4f5decd 100644 --- a/rpc_pkey.c +++ b/rpc_pkey.c @@ -1358,7 +1358,7 @@ static hal_error_t pkey_local_export(const hal_pkey_handle_t pkey_handle, goto fail; *pkcs8_len = pkcs8_max; - if ((err = hal_aes_keywrap(NULL, kek, KEK_LENGTH, pkcs8, len, pkcs8, pkcs8_len)) != HAL_OK) + if ((err = hal_keywrap_wrap(NULL, kek, KEK_LENGTH, pkcs8, len, pkcs8, pkcs8_len)) != HAL_OK) goto fail; if ((err = hal_asn1_encode_pkcs8_encryptedprivatekeyinfo(hal_asn1_oid_aesKeyWrap, @@ -1460,7 +1460,7 @@ static hal_error_t pkey_local_import(const hal_client_handle_t client, } der_len = sizeof(der); - if ((err = hal_aes_keyunwrap(NULL, kek, sizeof(kek), data, data_len, der, &der_len)) != HAL_OK) + if ((err = hal_keywrap_unwrap(NULL, kek, sizeof(kek), data, data_len, der, &der_len)) != HAL_OK) goto fail; hal_key_type_t type; diff --git a/verilog_constants.h b/verilog_constants.h index 9ed84d4..4588c20 100644 --- a/verilog_constants.h +++ b/verilog_constants.h @@ -344,12 +344,17 @@ #define MKMIF_ADDR_EMEM_DATA (0x20) /* - * AES Keywrap core + * AES Keywrap core, with Master Key Memory Interface */ +#define KEYWRAP_CTRL_READ (4) +#define KEYWRAP_CTRL_WRITE (8) + #define KEYWRAP_ADDR_CONFIG (0x0a) #define KEYWRAP_CONFIG_ENCDEC (1) #define KEYWRAP_CONFIG_KEYLEN (2) +#define KEYWRAP_CONFIG_MKS (4) +#define KEYWRAP_CONFIG_MKK (8) #define KEYWRAP_ADDR_RLEN (0x0c) #define KEYWRAP_ADDR_A0 (0x0e) @@ -364,6 +369,8 @@ #define KEYWRAP_ADDR_KEY6 (0x16) #define KEYWRAP_ADDR_KEY7 (0x17) +#define KEYWRAP_ADDR_MSTATUS (0x20) + #define KEYWRAP_ADDR_R_DATA (0x800) #define KEYWRAP_LEN_R_DATA (0x800) -- cgit v1.2.3