10 #define CX_MAX_BLOCK_SIZE 16
12 static cx_err_t cx_cipher_check_out_len(
cx_cipher_context_t *ctx,
size_t in_len,
size_t out_len)
15 if (out_len < in_len) {
16 return CX_INVALID_PARAMETER;
22 return CX_INVALID_PARAMETER;
26 if (out_len < in_len) {
27 return CX_INVALID_PARAMETER;
32 if (out_len < UPPER_ALIGN(in_len, 8,
size_t)) {
33 return CX_INVALID_PARAMETER;
37 if (out_len < UPPER_ALIGN(in_len + 7, 8,
size_t)) {
38 return CX_INVALID_PARAMETER;
50 return &cx_aes_128_info;
52 return &cx_aes_192_info;
54 return &cx_aes_256_info;
61 static cx_err_t get_no_padding(
uint8_t *input,
size_t in_len,
size_t *data_len)
63 if ((NULL == input) || (NULL == data_len)) {
64 return CX_INVALID_PARAMETER;
70 static void add_zeros_padding(
uint8_t *output,
size_t out_len,
size_t data_len)
74 for (i = data_len; i < out_len; i++) {
81 size_t padding_len = out_len - data_len;
84 output[data_len] = 0x80;
85 for (i = 1; i < padding_len; i++) {
86 output[data_len + i] = 0x00;
90 static cx_err_t get_zeros_padding(
uint8_t *input,
size_t in_len,
size_t *data_len)
92 if ((NULL == input) || (NULL == data_len)) {
93 return CX_INVALID_PARAMETER;
99 static inline uint32_t neq_zero(uint32_t x)
101 return (x | -x) >> 31;
104 static inline uint32_t conditional_choice(uint32_t a, uint32_t b, uint32_t cond)
107 return (a ^ b) ^ (b & (-cond));
110 static cx_err_t get_one_and_zeros_padding(
uint8_t *input,
size_t in_len,
size_t *data_len)
112 if ((NULL == input) || (NULL == data_len)) {
113 return CX_INVALID_PARAMETER;
125 for (i = in_len - 1; i >= 0; i--) {
126 uint32_t is_0x80 = neq_zero(input[i] ^ 0x80);
127 uint32_t is_zero = neq_zero(acc);
128 result[is_0x80 | is_zero] = 1;
129 padsize[is_0x80 | is_zero] = i;
132 *data_len = padsize[0];
133 uint32_t is_correct = neq_zero((uint32_t) result[0]);
134 return conditional_choice(CX_OK, CX_INVALID_PARAMETER, is_correct);
144 cx_err_t error = CX_INTERNAL_ERROR;
146 if (len % block_size) {
147 return CX_INVALID_PARAMETER_VALUE;
157 return CX_INVALID_PARAMETER_VALUE;
160 output += block_size;
177 cx_err_t error = CX_INTERNAL_ERROR;
179 if (len % block_size) {
180 return CX_INVALID_PARAMETER_VALUE;
185 output += block_size;
190 memcpy(output, block, block_size);
191 output += block_size;
197 memcpy(ctx->
sig, block, block_size);
204 static size_t cx_cipher_verify_block(
uint8_t *block,
uint8_t *block_ref,
size_t block_size)
206 return (memcmp(block, block_ref, block_size) == 0) ? block_size : 0;
212 return CX_INVALID_PARAMETER;
221 return CX_INVALID_PARAMETER;
225 return CX_INVALID_PARAMETER;
228 return CX_INVALID_PARAMETER;
239 return CX_INVALID_PARAMETER_VALUE;
247 return CX_INVALID_PARAMETER_VALUE;
260 if ((NULL == ctx) || (NULL == key) || (NULL == ctx->
cipher_info)) {
261 return CX_INVALID_PARAMETER;
264 return CX_INVALID_PARAMETER_SIZE;
268 return CX_INVALID_PARAMETER_VALUE;
272 op_mode = operation | ctx->
mode;
279 return CX_INVALID_PARAMETER;
284 if ((NULL == iv) && (0 != iv_len)) {
285 return CX_INVALID_PARAMETER_VALUE;
289 return CX_INVALID_PARAMETER_VALUE;
292 memcpy(ctx->
iv, iv, iv_len);
304 return CX_INVALID_PARAMETER;
320 return CX_INVALID_PARAMETER_VALUE;
332 cx_err_t error = CX_INTERNAL_ERROR;
334 if ((NULL == ctx) || (NULL == ctx->
cipher_info) || (NULL == out_len)) {
335 return CX_INVALID_PARAMETER;
339 return CX_INVALID_PARAMETER_VALUE;
342 CX_CHECK(cx_cipher_check_out_len(ctx, in_len, *out_len));
367 output += block_size;
369 *out_len += block_size;
372 in_len -= remain_len;
375 remain_len = in_len % block_size;
378 remain_len = block_size;
382 in_len -= remain_len;
386 CX_CHECK(ecb_func(ctx, ctx->
operation, in_len, input, output));
389 CX_CHECK(cbc_func(ctx, ctx->
operation, in_len, input, output));
405 return CX_INVALID_PARAMETER_VALUE;
413 cx_err_t error = CX_INTERNAL_ERROR;
414 if ((NULL == ctx) || (NULL == ctx->
cipher_info) || (NULL == out_len)) {
415 return CX_INVALID_PARAMETER;
463 error = CX_INVALID_PARAMETER_VALUE;
500 cx_err_t error = CX_INTERNAL_ERROR;
501 size_t finish_len = 0;
506 finish_len = *out_len;
510 *out_len += finish_len;
530 static void test_iso9797_method2_unpad(
void **state)
532 uint8_t buf1[8] = {0, 1, 2, 3, 4, 5, 6, 0x80};
533 size_t unpadded_size = 0;
535 assert_int_equal(get_one_and_zeros_padding(buf1, 8, &unpadded_size), CX_OK);
536 assert_int_equal(unpadded_size, 7);
538 uint8_t buf2[8] = {0, 1, 2, 3, 0x80, 0, 0, 0};
541 assert_int_equal(get_one_and_zeros_padding(buf2, 8, &unpadded_size), CX_OK);
542 assert_int_equal(unpadded_size, 4);
545 uint8_t buf3[8] = {0, 1, 2, 3, 4, 5, 6, 7};
547 assert_int_equal(get_one_and_zeros_padding(buf3, 8, &unpadded_size), CX_INVALID_PARAMETER);
549 uint8_t buf4[8] = {0, 1, 2, 3, 4, 5, 0x80, 7};
552 assert_int_equal(get_one_and_zeros_padding(buf4, 8, &unpadded_size), CX_INVALID_PARAMETER);
554 uint8_t buf5[8] = {0x80, 0, 0, 0, 0, 0, 0, 0};
557 assert_int_equal(get_one_and_zeros_padding(buf5, 8, &unpadded_size), CX_OK);
558 assert_int_equal(unpadded_size, 0);
561 static void test_iso9797_method2_pad(
void **state)
564 const uint8_t buf1_padded[8] = {0x80, 0, 0, 0, 0, 0, 0, 0};
567 assert_memory_equal(buf1, buf1_padded,
sizeof(buf1_padded));
569 uint8_t buf2[8] = {0xaa, 0xbb, 0xcc};
570 const uint8_t buf2_padded[8] = {0xaa, 0xbb, 0xcc, 0x80, 0, 0, 0, 0};
573 assert_memory_equal(buf2, buf2_padded,
sizeof(buf2_padded));
575 uint8_t buf3[16] = {0, 1, 2, 3, 4, 5, 6, 7};
576 const uint8_t buf3_padded[16] = {0, 1, 2, 3, 4, 5, 6, 7, 0x80, 0, 0, 0, 0, 0, 0, 0};
579 assert_memory_equal(buf3, buf3_padded,
sizeof(buf3_padded));
584 const struct CMUnitTest tests[] = {
585 cmocka_unit_test(test_iso9797_method2_pad),
586 cmocka_unit_test(test_iso9797_method2_unpad),
589 return cmocka_run_group_tests(tests, NULL, NULL);
void cx_cipher_reset(cx_cipher_context_t *ctx)
#define CX_MAX_BLOCK_SIZE
cx_err_t cx_cipher_setiv(cx_cipher_context_t *ctx, const uint8_t *iv, size_t iv_len)
Set the initialization vector.
void add_one_and_zeros_padding(uint8_t *output, size_t out_len, size_t data_len)
cx_err_t cx_cipher_mac(cx_cipher_context_t *ctx, uint8_t *output, size_t *out_len, size_t *finish_len)
cx_err_t cx_cipher_setup(cx_cipher_context_t *ctx, const cx_cipher_id_t type, uint32_t mode)
Initialize and fill the context structure given the cipher info.
cx_err_t cx_cipher_init(cx_cipher_context_t *ctx)
Initialize a cipher context as NONE.
cx_err_t cx_cipher_enc_dec(cx_cipher_context_t *ctx, const uint8_t *iv, size_t iv_len, const uint8_t *input, size_t in_len, uint8_t *output, size_t *out_len)
All-in-one encryption or decryption.
cx_err_t cx_cipher_update(cx_cipher_context_t *ctx, const uint8_t *input, size_t in_len, uint8_t *output, size_t *out_len)
Encrypt or decrypt with the given context.
cx_err_t cx_cipher_setkey(cx_cipher_context_t *ctx, const uint8_t *key, uint32_t key_bitlen, uint32_t operation)
Set the key to use.
cx_err_t cx_cipher_finish(cx_cipher_context_t *ctx, uint8_t *output, size_t *out_len)
Finalize the operation.
cx_err_t cx_cipher_set_padding(cx_cipher_context_t *ctx, uint32_t padding)
Set the padding type.
@ CX_CIPHER_AES_192
AES with a 192-bit key.
@ CX_CIPHER_AES_256
AES with a 256-bit key.
@ CX_CIPHER_AES_128
AES with a 128-bit key.
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(* ctx_reset)(void)
Reset.
cx_err_t(* setkey_func)(const cipher_key_t *ctx_key, uint32_t operation, const uint8_t *key, uint32_t key_bitlen)
Set key for encryption or decryption.
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.
uint32_t mode
Mode of operation: ECB, CBC, CTR.
size_t iv_size
Length of the initialization vector.
uint32_t operation
Operation: encryption or decryption.
uint8_t unprocessed_data[MAX_BLOCK_LENGTH]
Data to process.
void(* add_padding)(uint8_t *output, size_t out_len, size_t data_len)
Padding function.
uint32_t key_bitlen
Key size in bits.
const cipher_key_t * cipher_key
Cipher-specific context.
uint8_t iv[MAX_IV_LENGTH]
Initiaization vector.
cx_err_t(* get_padding)(uint8_t *input, size_t in_len, size_t *data_len)
Check the padding.
const cx_cipher_info_t * cipher_info
Cipher information.
size_t unprocessed_len
Length of data to process.
uint8_t sig[MAX_BLOCK_LENGTH]
Last block to be verified.
const cx_cipher_base_t * base
uint32_t iv_size
Initialization vector size.
uint32_t key_bitlen
Key size.
uint32_t block_size
Block size.