btstack_crypto/aes-ccm: add support for Additional Authenticated Data (AAD)

This commit is contained in:
Matthias Ringwald 2019-01-12 12:32:45 +01:00
parent c342091bde
commit f88ad41f77
4 changed files with 222 additions and 8 deletions

View File

@ -341,7 +341,7 @@ static void btstack_crypto_ccm_setup_a_i(btstack_crypto_ccm_t * btstack_crypto_c
memcpy(&btstack_crypto_ccm_s[1], btstack_crypto_ccm->nonce, 13);
big_endian_store_16(btstack_crypto_ccm_s, 14, counter);
#ifdef DEBUG_CCM
printf("tstack_crypto_ccm_setup_a_%u\n", counter);
printf("ststack_crypto_ccm_setup_a_%u\n", counter);
printf("%16s: ", "ai");
printf_hexdump(btstack_crypto_ccm_s, 16);
#endif
@ -373,7 +373,8 @@ static void btstack_crypto_ccm_setup_a_i(btstack_crypto_ccm_t * btstack_crypto_c
static void btstack_crypto_ccm_setup_b_0(btstack_crypto_ccm_t * btstack_crypto_ccm, uint8_t * b0){
uint8_t m_prime = (btstack_crypto_ccm->auth_len - 2) / 2;
b0[0] = (m_prime << 3) | 1 ; // Adata = 0, M', L' = L - 1
uint8_t Adata = btstack_crypto_ccm->aad_len ? 1 : 0;
b0[0] = (Adata << 6) | (m_prime << 3) | 1 ; // Adata, M', L' = L - 1
memcpy(&b0[1], btstack_crypto_ccm->nonce, 13);
big_endian_store_16(b0, 14, btstack_crypto_ccm->message_len);
#ifdef DEBUG_CCM
@ -548,6 +549,55 @@ static void btstack_crypto_ccm_calc_xn(btstack_crypto_ccm_t * btstack_crypto_ccm
}
#endif
static void btstack_crypto_ccm_calc_aad_xn(btstack_crypto_ccm_t * btstack_crypto_ccm){
// store length
if (btstack_crypto_ccm->aad_offset == 0){
uint8_t len_buffer[2];
big_endian_store_16(len_buffer, 0, btstack_crypto_ccm->aad_len);
btstack_crypto_ccm->x_i[0] ^= len_buffer[0];
btstack_crypto_ccm->x_i[1] ^= len_buffer[1];
btstack_crypto_ccm->aad_remainder_len += 2;
btstack_crypto_ccm->aad_offset += 2;
}
// fill from input
uint16_t bytes_free = 16 - btstack_crypto_ccm->aad_remainder_len;
uint16_t bytes_to_copy = btstack_min(bytes_free, btstack_crypto_ccm->block_len);
printf("btstack_crypto_ccm_calc_aad_xn: bytes to copy %u\n", bytes_to_copy);
while (bytes_to_copy){
btstack_crypto_ccm->x_i[btstack_crypto_ccm->aad_remainder_len++] ^= *btstack_crypto_ccm->input++;
btstack_crypto_ccm->aad_offset++;
btstack_crypto_ccm->block_len--;
bytes_to_copy--;
bytes_free--;
}
// if last block, fill with zeros
printf("btstack_crypto_ccm_calc_aad_xn: aad_len %u, aad_offset %u. aad_remainder_len %u, bytes_free %u\n",
btstack_crypto_ccm->aad_len, btstack_crypto_ccm->aad_offset, btstack_crypto_ccm->aad_remainder_len, bytes_free);
if (btstack_crypto_ccm->aad_offset == (btstack_crypto_ccm->aad_len + 2)){
printf("btstack_crypto_ccm_calc_aad_xn: fill from %u, %u bytes\n", btstack_crypto_ccm->aad_remainder_len, bytes_free);
// memset(&btstack_crypto_ccm->b_i[btstack_crypto_ccm->aad_remainder_len], 0, bytes_free);
btstack_crypto_ccm->aad_remainder_len = 16;
}
// if not full, notify done
if (btstack_crypto_ccm->aad_remainder_len < 16){
btstack_crypto_done(&btstack_crypto_ccm->btstack_crypto);
return;
}
// encrypt block
#ifdef DEBUG_CCM
printf("%16s: ", "Xn XOR Bn (aad)");
printf_hexdump(btstack_crypto_ccm->x_i, 16);
#endif
btstack_crypto_ccm->aad_remainder_len = 0;
btstack_crypto_ccm->state = CCM_W4_AAD_XN;
btstack_crypto_aes128_start(btstack_crypto_ccm->key, btstack_crypto_ccm->x_i);
}
static void btstack_crypto_ccm_handle_s0(btstack_crypto_ccm_t * btstack_crypto_ccm, const uint8_t * data){
// data is little-endian, flip on the fly
int i;
@ -634,6 +684,7 @@ static void btstack_crypto_run(void){
}
break;
case BTSTACK_CRYPTO_CCM_DIGEST_BLOCK:
case BTSTACK_CRYPTO_CCM_ENCRYPT_BLOCK:
case BTSTACK_CRYPTO_CCM_DECRYPT_BLOCK:
#ifdef USE_BTSTACK_AES128
@ -642,6 +693,9 @@ static void btstack_crypto_run(void){
#else
btstack_crypto_ccm = (btstack_crypto_ccm_t *) btstack_crypto;
switch (btstack_crypto_ccm->state){
case CCM_CALCULATE_AAD_XN:
btstack_crypto_ccm_calc_aad_xn(btstack_crypto_ccm);
break;
case CCM_CALCULATE_X1:
btstack_crypto_ccm_calc_x1(btstack_crypto_ccm);
break;
@ -772,6 +826,36 @@ static void btstack_crypto_handle_encryption_result(const uint8_t * data){
reverse_128(data, result);
btstack_crypto_cmac_handle_encryption_result(btstack_crypto_cmac, result);
break;
case BTSTACK_CRYPTO_CCM_DIGEST_BLOCK:
btstack_crypto_ccm = (btstack_crypto_ccm_t*) btstack_linked_list_get_first_item(&btstack_crypto_operations);
switch (btstack_crypto_ccm->state){
case CCM_W4_X1:
reverse_128(data, btstack_crypto_ccm->x_i);
#ifdef DEBUG_CCM
printf("%16s: ", "X1");
printf_hexdump(btstack_crypto_ccm->x_i, 16);
#endif
btstack_crypto_ccm->aad_remainder_len = 0;
btstack_crypto_ccm->state = CCM_CALCULATE_AAD_XN;
break;
case CCM_W4_AAD_XN:
reverse_128(data, btstack_crypto_ccm->x_i);
#ifdef DEBUG_CCM
printf("%16s: ", "Xn+1 AAD");
printf_hexdump(btstack_crypto_ccm->x_i, 16);
#endif
// more aad?
if (btstack_crypto_ccm->aad_offset < (btstack_crypto_ccm->aad_len + 2)){
btstack_crypto_ccm->state = CCM_CALCULATE_AAD_XN;
} else {
// done
btstack_crypto_done(btstack_crypto);
}
break;
default:
break;
}
break;
case BTSTACK_CRYPTO_CCM_ENCRYPT_BLOCK:
btstack_crypto_ccm = (btstack_crypto_ccm_t*) btstack_linked_list_get_first_item(&btstack_crypto_operations);
switch (btstack_crypto_ccm->state){
@ -1058,15 +1142,28 @@ int btstack_crypto_ecc_p256_validate_public_key(const uint8_t * public_key){
}
#endif
void btstack_crypo_ccm_init(btstack_crypto_ccm_t * request, const uint8_t * key, const uint8_t * nonce, uint16_t message_len, uint8_t auth_len){
void btstack_crypo_ccm_init(btstack_crypto_ccm_t * request, const uint8_t * key, const uint8_t * nonce, uint16_t message_len, uint16_t additional_authenticated_data_len, uint8_t auth_len){
request->key = key;
request->nonce = nonce;
request->message_len = message_len;
request->aad_len = additional_authenticated_data_len;
request->aad_offset = 0;
request->auth_len = auth_len;
request->counter = 1;
request->state = CCM_CALCULATE_X1;
}
void btstack_crypo_ccm_digest(btstack_crypto_ccm_t * request, uint8_t * additional_authenticated_data, uint16_t additional_authenticated_data_len, void (* callback)(void * arg), void * callback_arg){
// not implemented yet
request->btstack_crypto.context_callback.callback = callback;
request->btstack_crypto.context_callback.context = callback_arg;
request->btstack_crypto.operation = BTSTACK_CRYPTO_CCM_DIGEST_BLOCK;
request->block_len = additional_authenticated_data_len;
request->input = additional_authenticated_data;
btstack_linked_list_add_tail(&btstack_crypto_operations, (btstack_linked_item_t*) request);
btstack_crypto_run();
}
void btstack_crypo_ccm_get_authentication_value(btstack_crypto_ccm_t * request, uint8_t * authentication_value){
memcpy(authentication_value, request->x_i, request->auth_len);
}
@ -1081,6 +1178,9 @@ void btstack_crypto_ccm_encrypt_block(btstack_crypto_ccm_t * request, uint16_t b
request->block_len = block_len;
request->input = plaintext;
request->output = ciphertext;
if (request->state != CCM_CALCULATE_X1){
request->state = CCM_CALCULATE_XN;
}
btstack_linked_list_add_tail(&btstack_crypto_operations, (btstack_linked_item_t*) request);
btstack_crypto_run();
}
@ -1092,6 +1192,9 @@ void btstack_crypto_ccm_decrypt_block(btstack_crypto_ccm_t * request, uint16_t b
request->block_len = block_len;
request->input = ciphertext;
request->output = plaintext;
if (request->state != CCM_CALCULATE_X1){
request->state = CCM_CALCULATE_SN;
}
btstack_linked_list_add_tail(&btstack_crypto_operations, (btstack_linked_item_t*) request);
btstack_crypto_run();
}

View File

@ -60,6 +60,7 @@ typedef enum {
BTSTACK_CRYPTO_CMAC_MESSAGE,
BTSTACK_CRYPTO_ECC_P256_GENERATE_KEY,
BTSTACK_CRYPTO_ECC_P256_CALCULATE_DHKEY,
BTSTACK_CRYPTO_CCM_DIGEST_BLOCK,
BTSTACK_CRYPTO_CCM_ENCRYPT_BLOCK,
BTSTACK_CRYPTO_CCM_DECRYPT_BLOCK,
} btstack_crypto_operation_t;
@ -102,6 +103,8 @@ typedef struct {
typedef enum {
CCM_CALCULATE_X1,
CCM_W4_X1,
CCM_CALCULATE_AAD_XN,
CCM_W4_AAD_XN,
CCM_CALCULATE_XN,
CCM_W4_XN,
CCM_CALCULATE_S0,
@ -118,10 +121,13 @@ typedef struct {
const uint8_t * input;
uint8_t * output;
uint8_t x_i[16];
uint16_t aad_offset;
uint16_t aad_len;
uint16_t message_len;
uint16_t block_len;
uint16_t counter;
uint16_t block_len;
uint8_t auth_len;
uint8_t aad_remainder_len;
} btstack_crypto_ccm_t;
/**
@ -220,9 +226,10 @@ int btstack_crypto_ecc_p256_validate_public_key(const uint8_t * public_key);
* @param nonce
* @param key
* @param message_len
* @param additional_authenticated_data_len must be smaller than 0xff00
* @param auth_len
*/
void btstack_crypo_ccm_init(btstack_crypto_ccm_t * request, const uint8_t * key, const uint8_t * nonce, uint16_t message_len, uint8_t auth_len);
void btstack_crypo_ccm_init(btstack_crypto_ccm_t * request, const uint8_t * key, const uint8_t * nonce, uint16_t message_len, uint16_t additional_authenticated_data_len, uint8_t auth_len);
/**
* Get authentication value after encrypt or decrypt operation
@ -231,6 +238,16 @@ void btstack_crypo_ccm_init(btstack_crypto_ccm_t * request, const uint8_t * key,
*/
void btstack_crypo_ccm_get_authentication_value(btstack_crypto_ccm_t * request, uint8_t * authentication_value);
/**
* Digest Additional Authentication Data - can be called multipled times up to total additional_authenticated_data_len specified in btstack_crypo_ccm_init
* @param request
* @param additional_authenticated_data
* @param additional_authenticated_data_len
* @param callback
* @param callback_arg
*/
void btstack_crypo_ccm_digest(btstack_crypto_ccm_t * request, uint8_t * additional_authenticated_data, uint16_t additional_authenticated_data_len, void (* callback)(void * arg), void * callback_arg);
/**
* Encrypt block - can be called multiple times. len must be a multiply of 16 for all but the last call
* @param request

View File

@ -115,6 +115,11 @@ int bt_mesh_ccm_decrypt(const u8_t key[16], u8_t nonce[13],
pmsg[i] = Xn[i];
}
#ifdef LOG_XN
printf("%16s: ", "Xn XOR bn");
printf_hexdump(pmsg, 16);
#endif
err = bt_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
@ -323,10 +328,21 @@ int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13],
aad_len -= 16;
i = 0;
#ifdef LOG_XN
printf("%16s: ", "Xn XOR bn (aad)");
printf_hexdump(pmsg, 16);
#endif
err = bt_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
#ifdef LOG_XN
printf("%16s: ", "Xn+1 AAD");
printf_hexdump(Xn, 16);
#endif
}
for (i = 0; i < aad_len; i++, j++) {
@ -337,10 +353,20 @@ int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13],
pmsg[i] = Xn[i];
}
#ifdef LOG_XN
printf("%16s: ", "Xn XOR bn (aad)");
printf_hexdump(pmsg, 16);
#endif
err = bt_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
#ifdef LOG_XN
printf("%16s: ", "Xn+1 AAD");
printf_hexdump(Xn, 16);
#endif
}
last_blk = msg_len % 16;

View File

@ -29,7 +29,73 @@ static void ccm_done(void * arg){
}
static void message_24(void){
static void message_24_upper_transport_encrypt(void){
printf("[+] Upper transport encrypt\n");
DEFINE_KEY(label_uuid, "f4a002c7fb1e4ca0a469a021de0db875");
DEFINE_KEY(app_key, "63964771734fbd76e3b40519d1d94a48");
uint8_t app_nonce[13];
parse_hex(app_nonce, "010007080d1234973612345677");
printf("%16s: ", "app_nonce"); printf_hexdump(app_nonce, 13);
uint8_t plaintext[8];
parse_hex(plaintext, "ea0a00576f726c64");
printf("%16s: ", "plaintext"); printf_hexdump(plaintext, sizeof(plaintext));
printf("Reference:\n");
uint8_t ciphertext[8+8];
bt_mesh_ccm_encrypt(app_key, app_nonce, plaintext, sizeof(plaintext), label_uuid, sizeof(label_uuid), ciphertext, 8);
printf("%16s: ", "ciphertext"); printf_hexdump(ciphertext, 8);
printf("%16s: ", "TransMIC"); printf_hexdump(&ciphertext[8], 8);
// btstack_crypto
printf("btstack_crypto:\n");
uint8_t trans_mic[8];
btstack_crypto_init();
btstack_crypto_ccm_t btstack_crypto_ccm;
btstack_crypo_ccm_init(&btstack_crypto_ccm, app_key, app_nonce, sizeof(plaintext), sizeof(label_uuid), sizeof(trans_mic));
btstack_crypo_ccm_digest(&btstack_crypto_ccm, label_uuid, 16, &ccm_done, NULL);
btstack_crypto_ccm_encrypt_block(&btstack_crypto_ccm, sizeof(plaintext), plaintext, ciphertext, &ccm_done, NULL);
btstack_crypo_ccm_get_authentication_value(&btstack_crypto_ccm, trans_mic);
printf("%16s: ", "ciphertext"); printf_hexdump(ciphertext, 8);
printf("%16s: ", "TransMIC"); printf_hexdump(trans_mic, 8);
}
static void message_24_upper_transport_decrypt(void){
printf("[+] Upper transport decrypt\n");
DEFINE_KEY(label_uuid, "f4a002c7fb1e4ca0a469a021de0db875");
DEFINE_KEY(app_key, "63964771734fbd76e3b40519d1d94a48");
uint8_t app_nonce[13];
parse_hex(app_nonce, "010007080d1234973612345677");
printf("%16s: ", "app_nonce"); printf_hexdump(app_nonce, 13);
uint8_t ciphertext[8];
parse_hex(ciphertext, "DE1547118463123E");
printf("%16s: ", "ciphertext"); printf_hexdump(ciphertext, sizeof(ciphertext));
printf("Reference:\n");
uint8_t plaintext[8+8];
bt_mesh_ccm_decrypt(app_key, app_nonce, ciphertext, sizeof(ciphertext), label_uuid, sizeof(label_uuid), plaintext, 8);
printf("%16s: ", "plaintext"); printf_hexdump(plaintext, 8);
printf("%16s: ", "TransMIC"); printf_hexdump(&plaintext[8], 8);
// btstack_crypto
printf("btstack_crypto:\n");
uint8_t trans_mic[8];
btstack_crypto_init();
btstack_crypto_ccm_t btstack_crypto_ccm;
btstack_crypo_ccm_init(&btstack_crypto_ccm, app_key, app_nonce, sizeof(ciphertext), sizeof(label_uuid), sizeof(trans_mic));
btstack_crypo_ccm_digest(&btstack_crypto_ccm, label_uuid, 16, &ccm_done, NULL);
btstack_crypto_ccm_decrypt_block(&btstack_crypto_ccm, sizeof(ciphertext), ciphertext, plaintext, &ccm_done, NULL);
btstack_crypo_ccm_get_authentication_value(&btstack_crypto_ccm, trans_mic);
printf("%16s: ", "plaintext"); printf_hexdump(plaintext, 8);
printf("%16s: ", "TransMIC"); printf_hexdump(trans_mic, 8);
}
static void message_24_lower_transport_segment_0(void){
printf("[+] Lower Transport Segment 0\n");
DEFINE_KEY(encryption_key, "0953fa93e7caac9638f58820220a398e");
uint8_t network_nonce[13];
@ -51,7 +117,7 @@ static void message_24(void){
uint8_t net_mic[4];
btstack_crypto_init();
btstack_crypto_ccm_t btstack_crypto_ccm;
btstack_crypo_ccm_init(&btstack_crypto_ccm, encryption_key, network_nonce, sizeof(plaintext), 4);
btstack_crypo_ccm_init(&btstack_crypto_ccm, encryption_key, network_nonce, sizeof(plaintext), 0, 4);
btstack_crypto_ccm_encrypt_block(&btstack_crypto_ccm, sizeof(plaintext), plaintext, ciphertext, &ccm_done, NULL);
btstack_crypo_ccm_get_authentication_value(&btstack_crypto_ccm, net_mic);
printf("%16s: ", "ciphertext"); printf_hexdump(ciphertext, 18);
@ -59,6 +125,8 @@ static void message_24(void){
}
int main(void){
message_24();
message_24_upper_transport_encrypt();
message_24_upper_transport_decrypt();
message_24_lower_transport_segment_0();
return 0;
}