From b6a6a351f893f5306634a6f8913df12ea574d2ed Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Fri, 27 May 2016 13:32:29 +0200 Subject: [PATCH] test/sm: extract aes_cmac implementation --- test/security_manager/Makefile | 9 +- test/security_manager/aes_cmac.c | 93 +++++++++++++++++++++ test/security_manager/aes_cmac.h | 10 +++ test/security_manager/aes_cmac_test.c | 113 +++----------------------- 4 files changed, 120 insertions(+), 105 deletions(-) create mode 100644 test/security_manager/aes_cmac.c create mode 100644 test/security_manager/aes_cmac.h diff --git a/test/security_manager/Makefile b/test/security_manager/Makefile index e81e57a6e..62618afec 100644 --- a/test/security_manager/Makefile +++ b/test/security_manager/Makefile @@ -41,17 +41,18 @@ all: security_manager aestest ectest aes_cmac_test security_manager: ${CORE_OBJ} ${COMMON_OBJ} security_manager.c ${CC} ${CORE_OBJ} ${COMMON_OBJ} security_manager.c ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} -o $@ -aestest: aestest.c rijndael.c - ${CC} ${CFLAGS} rijndael.c aestest.c -o $@ +aestest: aestest.o rijndael.o + ${CC} ${CFLAGS} $^ -o $@ -ectest: ectest.c ${MBEDTLS} rijndael.c +ectest: ectest.o ${MBEDTLS} rijndael.o gcc ${CFLAGS} $^ -o $@ -aes_cmac_test: aes_cmac_test.c rijndael.c +aes_cmac_test: aes_cmac_test.o aes_cmac.o rijndael.o gcc ${CFLAGS} $^ -o $@ test: all ./security_manager + ./aes_cmac_test ./aestest clean: diff --git a/test/security_manager/aes_cmac.c b/test/security_manager/aes_cmac.c new file mode 100644 index 000000000..e81cf154b --- /dev/null +++ b/test/security_manager/aes_cmac.c @@ -0,0 +1,93 @@ +#include "aes_cmac.h" +#include "rijndael.h" + +#include + +static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data){ + int i; + int carry = 0; + for (i=len-1; i >= 0 ; i--){ + int new_carry = data[i] >> 7; + data[i] = data[i] << 1 | carry; + carry = new_carry; + } +} + +void aes128_calc_cyphertext(const uint8_t key[16], const uint8_t plaintext[16], uint8_t cyphertext[16]){ + uint32_t rk[RKLENGTH(KEYBITS)]; + int nrounds = rijndaelSetupEncrypt(rk, &key[0], KEYBITS); + rijndaelEncrypt(rk, nrounds, plaintext, cyphertext); +} + +void aes_cmac_calc_subkeys(sm_key_t k0, sm_key_t k1, sm_key_t k2){ + memcpy(k1, k0, 16); + sm_shift_left_by_one_bit_inplace(16, k1); + if (k0[0] & 0x80){ + k1[15] ^= 0x87; + } + memcpy(k2, k1, 16); + sm_shift_left_by_one_bit_inplace(16, k2); + if (k1[0] & 0x80){ + k2[15] ^= 0x87; + } +} + +void aes_cmac(sm_key_t aes_cmac, const sm_key_t key, const uint8_t * data, int sm_cmac_message_len){ + sm_key_t k0, k1, k2, zero; + memset(zero, 0, 16); + + aes128_calc_cyphertext(key, zero, k0); + aes_cmac_calc_subkeys(k0, k1, k2); + + int sm_cmac_block_count = (sm_cmac_message_len + 15) / 16; + + // step 3: .. + if (sm_cmac_block_count==0){ + sm_cmac_block_count = 1; + } + + // step 4: set m_last + sm_key_t sm_cmac_m_last; + int sm_cmac_last_block_complete = sm_cmac_message_len != 0 && (sm_cmac_message_len & 0x0f) == 0; + int i; + if (sm_cmac_last_block_complete){ + for (i=0;i<16;i++){ + sm_cmac_m_last[i] = data[sm_cmac_message_len - 16 + i] ^ k1[i]; + } + } else { + int valid_octets_in_last_block = sm_cmac_message_len & 0x0f; + for (i=0;i<16;i++){ + if (i < valid_octets_in_last_block){ + sm_cmac_m_last[i] = data[(sm_cmac_message_len & 0xfff0) + i] ^ k2[i]; + continue; + } + if (i == valid_octets_in_last_block){ + sm_cmac_m_last[i] = 0x80 ^ k2[i]; + continue; + } + sm_cmac_m_last[i] = k2[i]; + } + } + + // printf("sm_cmac_start: len %u, block count %u\n", sm_cmac_message_len, sm_cmac_block_count); + // LOG_KEY(sm_cmac_m_last); + + // Step 5 + sm_key_t sm_cmac_x; + memset(sm_cmac_x, 0, 16); + + // Step 6 + sm_key_t sm_cmac_y; + for (int block = 0 ; block < sm_cmac_block_count-1 ; block++){ + for (i=0;i<16;i++){ + sm_cmac_y[i] = sm_cmac_x[i] ^ data[block * 16 + i]; + } + aes128_calc_cyphertext(key, sm_cmac_y, sm_cmac_x); + } + for (i=0;i<16;i++){ + sm_cmac_y[i] = sm_cmac_x[i] ^ sm_cmac_m_last[i]; + } + + // Step 7 + aes128_calc_cyphertext(key, sm_cmac_y, aes_cmac); +} \ No newline at end of file diff --git a/test/security_manager/aes_cmac.h b/test/security_manager/aes_cmac.h new file mode 100644 index 000000000..a5b781d92 --- /dev/null +++ b/test/security_manager/aes_cmac.h @@ -0,0 +1,10 @@ +#ifndef __AES_CMAC_H +#define __AES_CMAC_H + +#include +typedef uint8_t sm_key_t[16]; +void aes128_calc_cyphertext(const uint8_t key[16], const uint8_t plaintext[16], uint8_t cyphertext[16]); +void aes_cmac_calc_subkeys(sm_key_t k0, sm_key_t k1, sm_key_t k2); +void aes_cmac(sm_key_t aes_cmac, const sm_key_t key, const uint8_t * data, int sm_cmac_message_len); + +#endif diff --git a/test/security_manager/aes_cmac_test.c b/test/security_manager/aes_cmac_test.c index 479e4b020..86ddb75f4 100644 --- a/test/security_manager/aes_cmac_test.c +++ b/test/security_manager/aes_cmac_test.c @@ -1,13 +1,12 @@ -#include "rijndael.h" #include #include +#include "aes_cmac.h" // #include "btstack_util.h" typedef uint8_t sm_key24_t[3]; typedef uint8_t sm_key56_t[7]; -typedef uint8_t sm_key_t[16]; typedef uint8_t sm_key256_t[32]; static const char * key_string = "2b7e1516 28aed2a6 abf71588 09cf4f3c"; @@ -74,10 +73,19 @@ static void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){ buffer[pos++] = value; } +static void hexdump2(void *data, int size){ + if (size <= 0) return; + int i; + for (i=0; i= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; - if (c >= 'A' && c <= 'F') return c - 'F' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } @@ -96,108 +104,11 @@ static int parse_hex(uint8_t * buffer, const char * hex_string){ return len; } -static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data){ - int i; - int carry = 0; - for (i=len-1; i >= 0 ; i--){ - int new_carry = data[i] >> 7; - data[i] = data[i] << 1 | carry; - carry = new_carry; - } -} - -void aes128_calc_cyphertext(const uint8_t key[16], const uint8_t plaintext[16], uint8_t cyphertext[16]){ - uint32_t rk[RKLENGTH(KEYBITS)]; - int nrounds = rijndaelSetupEncrypt(rk, &key[0], KEYBITS); - rijndaelEncrypt(rk, nrounds, plaintext, cyphertext); -} - -static void hexdump2(void *data, int size){ - if (size <= 0) return; - int i; - for (i=0; i