diff --git a/sys/crypto/modes/ccm.c b/sys/crypto/modes/ccm.c index 0442e8abe1fe84052f35cd67af01cb9c32f3342e..0df28fa4bd7312a4ec9eabe5f4514c3e5babb78e 100644 --- a/sys/crypto/modes/ccm.c +++ b/sys/crypto/modes/ccm.c @@ -132,8 +132,11 @@ int ccm_compute_adata_mac(cipher_t* cipher, uint8_t* auth_data, /* Check if 'value' can be stored in 'num_bytes' */ static inline int _fits_in_nbytes(size_t value, uint8_t num_bytes) { - uint32_t length_max = 1 << (8 * num_bytes); - return value < length_max; + /* Not allowed to shift more or equal than left operand width + * So we shift by maximum num bits of size_t -1 and compare to 1 + */ + unsigned shift = (8 * min(sizeof(size_t), num_bytes)) - 1; + return (value >> shift) <= 1; } diff --git a/tests/unittests/tests-crypto/tests-crypto-modes-ccm.c b/tests/unittests/tests-crypto/tests-crypto-modes-ccm.c index 81f1d7d654067b4d6eafc4c798717bc34e6815b2..1fe20e7972d9a238e5649e22c465183ff3c382bc 100644 --- a/tests/unittests/tests-crypto/tests-crypto-modes-ccm.c +++ b/tests/unittests/tests-crypto/tests-crypto-modes-ccm.c @@ -226,6 +226,26 @@ static void test_crypto_modes_ccm_check_len(void) TEST_ASSERT_EQUAL_INT(CCM_ERR_INVALID_LENGTH_ENCODING, ret); ret = _test_ccm_len(cipher_decrypt_ccm, 2, NULL, 1 << 16, 65535); TEST_ASSERT_EQUAL_INT(CCM_ERR_INVALID_LENGTH_ENCODING, ret); + + /* Valid length that were wrongly checked */ + /* Check should work with len_encoding >= 4, test with 8 */ + uint8_t input[8]; + ret = _test_ccm_len(cipher_encrypt_ccm, 8, input, 8, 0); + TEST_ASSERT_MESSAGE(ret > 0, "Encryption : failed with valid input_len"); + + /* einput is encrypted value for + * - 8 * 0 input + * - All 0 nonce and key + * - adata_len == 0 + * - mac_len == 8 and len_encoding = 8 + */ + uint8_t einput[16] = { + 0xa2, 0x46, 0x75, 0xfc, 0x5f, 0x1b, 0x01, 0x37, + 0x8a, 0x85, 0xd7, 0xf8, 0x42, 0x82, 0x6a, 0x63, + }; + + ret = _test_ccm_len(cipher_decrypt_ccm, 8, einput, 16, 0); + TEST_ASSERT_MESSAGE(ret > 0, "Decryption : failed with valid input_len"); }