From 14c86698cedcc51c0e76a2458092db41a4fecbfa Mon Sep 17 00:00:00 2001 From: sra Date: Tue, 3 Jan 2023 14:42:10 +0100 Subject: [PATCH] Perform CBC mode in hardware --- include/ox_aes.h | 1 - lib_cxng/include/lcx_cipher.h | 4 +- lib_cxng/src/cx_aes.c | 11 +++-- lib_cxng/src/cx_cipher.c | 80 ++++++++++++++++++++--------------- 4 files changed, 55 insertions(+), 41 deletions(-) diff --git a/include/ox_aes.h b/include/ox_aes.h index fa2c6cfde..ee4ef516a 100644 --- a/include/ox_aes.h +++ b/include/ox_aes.h @@ -112,5 +112,4 @@ SYSCALL void cx_aes_reset_hw(void); */ SYSCALL cx_err_t cx_aes_block_hw(const unsigned char *inblock PLENGTH(16), unsigned char *outblock PLENGTH(16)); - #endif diff --git a/lib_cxng/include/lcx_cipher.h b/lib_cxng/include/lcx_cipher.h index 559df0d7a..4ce7e375a 100644 --- a/lib_cxng/include/lcx_cipher.h +++ b/lib_cxng/include/lcx_cipher.h @@ -50,8 +50,8 @@ typedef struct { /** Base cipher information */ typedef struct { - cx_err_t (*enc_func)(const cipher_key_t *ctx_key, const uint8_t *in_block, uint8_t *out_block); ///< Encryption function - cx_err_t (*dec_func)(const cipher_key_t *ctx_key, const uint8_t *in_block, uint8_t *out_block); ///< Decryption function + cx_err_t (*enc_func)(const uint8_t *in_block, uint8_t *out_block); ///< Encryption function + cx_err_t (*dec_func)(const uint8_t *in_block, uint8_t *out_block); ///< Decryption function cx_err_t (*ctr_func)(const cipher_key_t *ctx_key, size_t len, size_t *nc_off, uint8_t *nonce_counter, uint8_t *stream_block, const uint8_t *input, uint8_t *output); ///< Encryption in CTR mode cx_err_t (*setkey_func)(const cipher_key_t *ctx_key, uint32_t operation, const uint8_t *key, diff --git a/lib_cxng/src/cx_aes.c b/lib_cxng/src/cx_aes.c index c73793032..6730183de 100644 --- a/lib_cxng/src/cx_aes.c +++ b/lib_cxng/src/cx_aes.c @@ -78,7 +78,9 @@ cx_err_t cx_aes_iv_no_throw(const cx_aes_key_t *key, ctx->key_bitlen = key->size * 8; ctx->operation = operation; ctx->cipher_key = (const cipher_key_t*)key; + operation |= mode & CX_MASK_CHAIN; CX_CHECK(cx_cipher_setup(ctx, type, mode & CX_MASK_CHAIN)); + CX_CHECK(cx_aes_set_key_hw(key, operation)); CX_CHECK(cx_cipher_set_padding(ctx, mode & CX_MASK_PAD)); CX_CHECK(cx_cipher_enc_dec(ctx, iv, iv_len, in, in_len, out, out_len)); @@ -96,10 +98,11 @@ cx_err_t aes_ctr(cx_aes_key_t *ctx_key, size_t len, size_t *nc_off, uint8_t *non uint8_t c; size_t n = *nc_off; cx_err_t error = CX_INVALID_PARAMETER; + UNUSED(ctx_key); while (len--) { if (n == 0) { - CX_CHECK(cx_aes_enc_block(ctx_key, nonce_counter, stream_block)); + CX_CHECK(cx_aes_block_hw(nonce_counter, stream_block)); for (int i = CX_AES_BLOCK_SIZE; i > 0; i--) { if (++nonce_counter[i - 1] != 0) { break; @@ -126,11 +129,11 @@ cx_err_t aes_setkey(cx_aes_key_t *ctx_key, uint32_t operation, const uint8_t *ke } static const cx_cipher_base_t aes_base = { - (cx_err_t (*) (const cipher_key_t *ctx_key, const uint8_t *inblock, uint8_t *outblock))cx_aes_enc_block, - (cx_err_t (*) (const cipher_key_t *ctx_key, const uint8_t *inblock, uint8_t *outblock))cx_aes_dec_block, + (cx_err_t (*) (const uint8_t *inblock, uint8_t *outblock))cx_aes_block_hw, + (cx_err_t (*) (const uint8_t *inblock, uint8_t *outblock))cx_aes_block_hw, (cx_err_t(*) (const cipher_key_t *ctx_key, size_t len, size_t *nc_off, uint8_t *nonce_counter, uint8_t *stream_block, const uint8_t *input, uint8_t *output))aes_ctr, (cx_err_t(*) (const cipher_key_t *ctx_key, uint32_t operation, const uint8_t *key, uint32_t key_bitlen))aes_setkey, - (cx_err_t(*)(void))cx_aes_reset_hw + (cx_err_t(*)(void))cx_aes_reset_hw, }; const cx_cipher_info_t cx_aes_128_info = { diff --git a/lib_cxng/src/cx_cipher.c b/lib_cxng/src/cx_cipher.c index 044b67dff..2d59005f3 100644 --- a/lib_cxng/src/cx_cipher.c +++ b/lib_cxng/src/cx_cipher.c @@ -134,9 +134,9 @@ static cx_err_t ecb_func(cx_cipher_context_t *ctx, uint32_t operation, size_t le } while (len > 0) { if (CX_ENCRYPT == operation) { - CX_CHECK(ctx->cipher_info->base->enc_func(ctx->cipher_key, input, output)); + CX_CHECK(ctx->cipher_info->base->enc_func(input, output)); } else if (CX_DECRYPT == operation) { - CX_CHECK(ctx->cipher_info->base->dec_func(ctx->cipher_key, input, output)); + CX_CHECK(ctx->cipher_info->base->dec_func(input, output)); } else { return CX_INVALID_PARAMETER_VALUE; @@ -151,11 +151,10 @@ static cx_err_t ecb_func(cx_cipher_context_t *ctx, uint32_t operation, size_t le return error; } -static cx_err_t cbc_func(cx_cipher_context_t *ctx, uint32_t operation, size_t len, uint8_t *iv, +static cx_err_t cbc_func(cx_cipher_context_t *ctx, uint32_t operation, size_t len, const uint8_t *input, uint8_t *output) { uint8_t block[CX_MAX_BLOCK_SIZE]; - uint8_t tmp[CX_MAX_BLOCK_SIZE]; uint32_t block_size = ctx->cipher_info->block_size; cx_err_t error = CX_INTERNAL_ERROR; @@ -164,27 +163,20 @@ static cx_err_t cbc_func(cx_cipher_context_t *ctx, uint32_t operation, size_t le } while (len > 0) { if (CX_DECRYPT == operation) { - CX_CHECK(ctx->cipher_info->base->dec_func(ctx->cipher_key, input, block)); - for (uint32_t i = 0; i < block_size; i++) { - tmp[i] = block[i] ^ iv[i]; - } - memcpy(iv, input, block_size); + CX_CHECK(ctx->cipher_info->base->dec_func(input, output)); + output += block_size; } else { - for (uint32_t i = 0; i < block_size; i++) { - block[i] = input[i] ^ iv[i]; + CX_CHECK(ctx->cipher_info->base->enc_func(input, block)); + if (CX_ENCRYPT == operation) { + memcpy(output, block, block_size); + output += block_size; } - CX_CHECK(ctx->cipher_info->base->enc_func(ctx->cipher_key, block, tmp)); - memcpy(iv, tmp, block_size); - } - if ((CX_ENCRYPT == operation) || (CX_DECRYPT == operation)) { - memcpy(output, tmp, block_size); - output += block_size; } input += block_size; len -= block_size; } - memcpy(ctx->sig, tmp, block_size); + memcpy(ctx->sig, block, block_size); error = CX_OK; end: @@ -239,6 +231,8 @@ cx_err_t cx_cipher_setup(cx_cipher_context_t *ctx, const cx_cipher_id_t type, ui } cx_err_t cx_cipher_setkey(cx_cipher_context_t *ctx, const uint8_t *key, uint32_t key_bitlen, uint32_t operation) { + uint32_t op_mode; + if ((NULL == ctx) || (NULL == key) || (NULL == ctx->cipher_info)) { return CX_INVALID_PARAMETER; } @@ -251,7 +245,8 @@ cx_err_t cx_cipher_setkey(cx_cipher_context_t *ctx, const uint8_t *key, uint32_t } ctx->key_bitlen = key_bitlen; ctx->operation = operation; - return ctx->cipher_info->base->setkey_func(ctx->cipher_key, operation, key, key_bitlen); + op_mode = operation | ctx->mode; + return ctx->cipher_info->base->setkey_func(ctx->cipher_key, op_mode, key, key_bitlen); } cx_err_t cx_cipher_setiv(cx_cipher_context_t *ctx, const uint8_t *iv, size_t iv_len) { @@ -271,6 +266,10 @@ cx_err_t cx_cipher_setiv(cx_cipher_context_t *ctx, const uint8_t *iv, size_t iv_ memcpy(ctx->iv, iv, iv_len); ctx->iv_size = iv_len; + + if (CX_CHAIN_CBC == ctx->mode) { + ctx->cipher_info->base->enc_func(ctx->iv, ctx->iv); + } return CX_OK; } @@ -328,7 +327,7 @@ cx_err_t cx_cipher_update(cx_cipher_context_t *ctx, const uint8_t *input, size_t if (CX_CHAIN_ECB == ctx->mode) { CX_CHECK(ecb_func(ctx, ctx->operation, block_size, ctx->unprocessed_data, output)); } else { - CX_CHECK(cbc_func(ctx, ctx->operation, block_size, ctx->iv, ctx->unprocessed_data, output)); + CX_CHECK(cbc_func(ctx, ctx->operation, block_size, ctx->unprocessed_data, output)); } if (ctx->operation != CX_SIGN) { output += block_size; @@ -340,7 +339,7 @@ cx_err_t cx_cipher_update(cx_cipher_context_t *ctx, const uint8_t *input, size_t } if (in_len != 0) { remain_len = in_len % block_size; - if ((remain_len == 0) && (ctx->operation == CX_DECRYPT)) { + if ((remain_len == 0) && (ctx->operation == CX_DECRYPT) && (ctx->add_padding != NULL)) { remain_len = block_size; } memcpy(ctx->unprocessed_data, &(input[in_len - remain_len]), remain_len); @@ -352,7 +351,7 @@ cx_err_t cx_cipher_update(cx_cipher_context_t *ctx, const uint8_t *input, size_t CX_CHECK(ecb_func(ctx, ctx->operation, in_len, input, output)); } else { - CX_CHECK(cbc_func(ctx, ctx->operation, in_len, ctx->iv, input, output)); + CX_CHECK(cbc_func(ctx, ctx->operation, in_len, input, output)); } } *out_len = in_len; @@ -379,41 +378,51 @@ cx_err_t cx_cipher_finish(cx_cipher_context_t *ctx, uint8_t *output, size_t *out *out_len = 0; switch (ctx->mode) { case CX_CHAIN_CTR: - return CX_OK; + error = CX_OK; + break; case CX_CHAIN_ECB: case CX_CHAIN_CBC: if ((CX_ENCRYPT == ctx->operation) || (CX_SIGN == ctx->operation) || (CX_VERIFY == ctx->operation)) { if (NULL == ctx->add_padding) { if (ctx->unprocessed_len != 0) { - return CX_INTERNAL_ERROR; + goto end; } - return CX_OK; + error = CX_OK; + goto end; } if ((add_zeros_padding == ctx->add_padding) && (ctx->unprocessed_len == 0)) { *out_len = 0; - return CX_OK; + error = CX_OK; + goto end; } ctx->add_padding(ctx->unprocessed_data, ctx->cipher_info->block_size, ctx->unprocessed_len); } + if (get_no_padding != ctx->get_padding) { + ctx->unprocessed_len = ctx->cipher_info->block_size; + } if (CX_CHAIN_ECB == ctx->mode) { - CX_CHECK(ecb_func(ctx, ctx->operation, ctx->cipher_info->block_size, ctx->unprocessed_data, output)); + CX_CHECK(ecb_func(ctx, ctx->operation, ctx->unprocessed_len, ctx->unprocessed_data, output)); } else { - CX_CHECK(cbc_func(ctx, ctx->operation, ctx->cipher_info->block_size, ctx->iv, + CX_CHECK(cbc_func(ctx, ctx->operation, ctx->unprocessed_len, ctx->unprocessed_data, output)); } - if (CX_DECRYPT == ctx->operation ) { - return ctx->get_padding(output, ctx->cipher_info->block_size, out_len); + if ((CX_DECRYPT == ctx->operation) && (NULL != ctx->get_padding)) { + error = ctx->get_padding(output, ctx->unprocessed_len, out_len); + goto end; } - *out_len = ctx->cipher_info->block_size; - return CX_OK; + *out_len = ctx->unprocessed_len; + error = CX_OK; + break; default: - return CX_INVALID_PARAMETER_VALUE; + error = CX_INVALID_PARAMETER_VALUE; + break; } end: + ctx->cipher_info->base->ctx_reset(); return error; } @@ -441,7 +450,10 @@ cx_err_t cx_cipher_enc_dec(cx_cipher_context_t *ctx, const uint8_t *iv, size_t i CX_CHECK(cx_cipher_setiv(ctx, iv, iv_len)); CX_CHECK(cx_cipher_update(ctx, input, in_len, output, out_len)); - CX_CHECK(cx_cipher_finish(ctx, output + *out_len, &finish_len)); + if (ctx->add_padding != NULL) { + finish_len = *out_len; + } + CX_CHECK(cx_cipher_finish(ctx, output + finish_len, &finish_len)); CX_CHECK(cx_cipher_mac(ctx, output, out_len, &finish_len)); *out_len += finish_len;