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:
commit
4c4cb8a14f
@ -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,
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user