1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #12362 from mtausig/ccm_aadlen

Fix CCM mode when length of AAD is > 24
This commit is contained in:
Francisco 2020-01-07 22:26:24 +01:00 committed by GitHub
commit 4c4cb8a14f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 8 deletions

View File

@ -34,7 +34,7 @@ static inline int min(int a, int b)
}
}
int ccm_compute_cbc_mac(cipher_t *cipher, const uint8_t iv[16],
static int ccm_compute_cbc_mac(cipher_t *cipher, const uint8_t iv[16],
const uint8_t *input, size_t length, uint8_t *mac)
{
uint8_t offset, block_size, mac_enc[16] = { 0 };
@ -63,7 +63,7 @@ int ccm_compute_cbc_mac(cipher_t *cipher, const uint8_t iv[16],
}
int ccm_create_mac_iv(cipher_t *cipher, uint8_t auth_data_len, uint8_t M,
static int ccm_create_mac_iv(cipher_t *cipher, uint8_t auth_data_len, uint8_t M,
uint8_t L, const uint8_t *nonce, uint8_t nonce_len,
size_t plaintext_len, uint8_t X1[16])
{
@ -99,14 +99,14 @@ int ccm_create_mac_iv(cipher_t *cipher, uint8_t auth_data_len, uint8_t M,
return 0;
}
int ccm_compute_adata_mac(cipher_t *cipher, const uint8_t *auth_data,
static int ccm_compute_adata_mac(cipher_t *cipher, const uint8_t *auth_data,
uint32_t auth_data_len, uint8_t X1[16])
{
if (auth_data_len > 0) {
int len;
/* 16 octet block size + max. 10 len encoding */
uint8_t auth_data_encoded[26], len_encoding = 0;
/* Create a block with the encoded length. Block length is always 16 */
uint8_t auth_data_encoded[CCM_BLOCK_SIZE], len_encoding = 0;
/* If 0 < l(a) < (2^16 - 2^8), then the length field is encoded as two
* octets. (RFC3610 page 2)
@ -123,12 +123,32 @@ int ccm_compute_adata_mac(cipher_t *cipher, const uint8_t *auth_data,
return -1;
}
memcpy(auth_data_encoded + len_encoding, auth_data, auth_data_len);
uint8_t auth_data_len_in_encoded =
(auth_data_len >=
(uint32_t)CCM_BLOCK_SIZE -
len_encoding) ? ((uint32_t)CCM_BLOCK_SIZE -
len_encoding) :
auth_data_len;
memcpy(auth_data_encoded + len_encoding, auth_data,
auth_data_len_in_encoded);
/* Calculate the MAC over the first block of AAD + heading length encoding */
len = ccm_compute_cbc_mac(cipher, X1, auth_data_encoded,
auth_data_len + len_encoding, X1);
auth_data_len_in_encoded + len_encoding, X1);
if (len < 0) {
return -1;
}
/* Calculate the MAC for the remainder of the AAD (if there is one) */
if (auth_data_len_in_encoded < auth_data_len) {
len = ccm_compute_cbc_mac(cipher, X1,
auth_data + auth_data_len_in_encoded,
auth_data_len - auth_data_len_in_encoded,
X1);
if (len < 0) {
return -1;
}
}
}
return 0;
@ -169,6 +189,7 @@ int cipher_encrypt_ccm(cipher_t *cipher,
/* Create B0, encrypt it (X1) and use it as mac_iv */
block_size = cipher_get_block_size(cipher);
assert(block_size == CCM_BLOCK_SIZE);
if (ccm_create_mac_iv(cipher, auth_data_len, mac_length, length_encoding,
nonce, nonce_len, input_len, mac_iv) < 0) {
return CCM_ERR_INVALID_DATA_LENGTH;
@ -179,6 +200,7 @@ int cipher_encrypt_ccm(cipher_t *cipher,
if (len < 0) {
return len;
}
len = ccm_compute_cbc_mac(cipher, mac_iv, input, input_len, mac);
if (len < 0) {
return len;
@ -236,6 +258,7 @@ int cipher_decrypt_ccm(cipher_t *cipher,
/* Compute first stream block */
nonce_counter[0] = length_encoding - 1;
block_size = cipher_get_block_size(cipher);
assert(block_size == CCM_BLOCK_SIZE);
memcpy(&nonce_counter[1], nonce, min(nonce_len,
(size_t)15 - length_encoding));
len = cipher_encrypt_ctr(cipher, nonce_counter, block_size, zero_block,

View File

@ -37,6 +37,12 @@ extern "C" {
#define CCM_ERR_INVALID_MAC_LENGTH (-5)
/** @} */
/**
* @brief Block size required for the cipher. CCM is only defined for 128 bit ciphers.
*/
#define CCM_BLOCK_SIZE 16
/**
* @brief Encrypt and authenticate data of arbitrary length in ccm mode.
*

View File

@ -823,6 +823,47 @@ static const uint8_t TEST_NIST_3_EXPECTED[] = {
};
static const size_t TEST_NIST_3_EXPECTED_LEN = 52;
/* Tests from Project Wycheproof */
/* See https://github.com/google/wycheproof/blob/master/testvectors/aes_ccm_test.json */
static const uint8_t TEST_WYCHEPROOF_28_KEY[] = {
0x20, 0xbb, 0xf7, 0x4c, 0x1e, 0x63, 0x98, 0x2c,
0x47, 0x2c, 0x47, 0x43, 0x56, 0x9e, 0x4c, 0x84,
};
static const size_t TEST_WYCHEPROOF_28_KEY_LEN = 16;
static const uint8_t TEST_WYCHEPROOF_28_NONCE[] = {
0x45, 0x9f, 0xc7, 0xc0, 0x04, 0xbf, 0x46, 0x32,
0x3a, 0x02, 0xd8, 0x46,
};
static const size_t TEST_WYCHEPROOF_28_NONCE_LEN = 12;
static const size_t TEST_WYCHEPROOF_28_MAC_LEN = 16;
static const uint8_t TEST_WYCHEPROOF_28_INPUT[] = {
/* AAD */
0x4f, 0x22, 0x85, 0xce, 0x3d, 0xaf, 0xa5, 0x28,
0xc6, 0x94, 0xa5, 0x27, 0x2d, 0x3b, 0x7b, 0x92,
0x90, 0x97, 0xdb, 0x39, 0x87, 0x72, 0x65, 0x3b,
0xd9, 0xbb, 0xbd, 0xb3, 0xb2, 0xc8, 0xe1,
/* PLAINTEXT */
0x6d, 0xb5, 0x09, 0x92, 0xe8, 0xfb, 0xbe, 0xe1,
0x5d, 0x49, 0x79, 0xd3, 0xe3, 0x22, 0xda, 0xcd,
};
static const size_t TEST_WYCHEPROOF_28_INPUT_LEN = 16;
static const size_t TEST_WYCHEPROOF_28_ADATA_LEN = 31;
static const uint8_t TEST_WYCHEPROOF_28_EXPECTED[] = {
/* AAD */
0x4f, 0x22, 0x85, 0xce, 0x3d, 0xaf, 0xa5, 0x28,
0xc6, 0x94, 0xa5, 0x27, 0x2d, 0x3b, 0x7b, 0x92,
0x90, 0x97, 0xdb, 0x39, 0x87, 0x72, 0x65, 0x3b,
0xd9, 0xbb, 0xbd, 0xb3, 0xb2, 0xc8, 0xe1,
/* CIPHERTEXT */
0x87, 0x03, 0xe4, 0x46, 0x97, 0x13, 0x8c, 0x58,
0x53, 0x2d, 0x97, 0xee, 0x99, 0x23, 0x1d, 0x94,
/* MAC */
0xf1, 0x4c, 0x2f, 0x39, 0xa4, 0x87, 0x1a, 0x4a,
0x16, 0xc4, 0x2f, 0x6f, 0xe8, 0x78, 0xde, 0xef,
};
static const size_t TEST_WYCHEPROOF_28_EXPECTED_LEN = 63;
/* Share test buffer output */
static uint8_t data[60];
@ -852,7 +893,6 @@ static void test_encrypt_op(const uint8_t *key, uint8_t key_len,
TEST_ASSERT_EQUAL_INT(output_expected_len, len);
cmp = compare(output_expected, data, len);
TEST_ASSERT_MESSAGE(1 == cmp, "wrong ciphertext");
}
static void test_decrypt_op(const uint8_t *key, uint8_t key_len,
@ -930,6 +970,8 @@ static void test_crypto_modes_ccm_encrypt(void)
do_test_encrypt_op(NIST_1);
do_test_encrypt_op(NIST_2);
do_test_encrypt_op(NIST_3);
do_test_encrypt_op(WYCHEPROOF_28);
}
#define do_test_decrypt_op(name) do { \
@ -977,6 +1019,8 @@ static void test_crypto_modes_ccm_decrypt(void)
do_test_decrypt_op(NIST_1);
do_test_decrypt_op(NIST_2);
do_test_decrypt_op(NIST_3);
do_test_decrypt_op(WYCHEPROOF_28);
}