Skip to content

Commit

Permalink
Merge pull request #137 from LedgerHQ/enable-hw-aes-cbc-sdk
Browse files Browse the repository at this point in the history
Perform CBC mode in hardware
  • Loading branch information
srasoamiaramanana-ledger authored Jul 5, 2023
2 parents 2108082 + 14c8669 commit ee03223
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 41 deletions.
1 change: 0 additions & 1 deletion include/ox_aes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions lib_cxng/include/lcx_cipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 7 additions & 4 deletions lib_cxng/src/cx_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand All @@ -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;
Expand All @@ -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 = {
Expand Down
80 changes: 46 additions & 34 deletions lib_cxng/src/cx_cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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:
Expand Down Expand Up @@ -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;
}
Expand All @@ -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) {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit ee03223

Please sign in to comment.