From 4cd624bde7dba165ec11591fe1618efb494119f9 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Fri, 17 Jan 2020 09:18:24 +0100 Subject: [PATCH 01/14] sys/crypto: add ccms --- sys/crypto/modes/ccm.c | 100 ++++++++++++++++++++++---- sys/include/crypto/modes/ccm.h | 19 +---- sys/include/crypto/modes/ccm_common.h | 50 +++++++++++++ sys/include/crypto/modes/ccms.h | 89 +++++++++++++++++++++++ 4 files changed, 228 insertions(+), 30 deletions(-) create mode 100644 sys/include/crypto/modes/ccm_common.h create mode 100644 sys/include/crypto/modes/ccms.h diff --git a/sys/crypto/modes/ccm.c b/sys/crypto/modes/ccm.c index 3f5a42882041..c026859e31a1 100644 --- a/sys/crypto/modes/ccm.c +++ b/sys/crypto/modes/ccm.c @@ -11,7 +11,7 @@ * @{ * * @file - * @brief Crypto mode - counter with CBC-MAC + * @brief Crypto mode - counter with CBC-MAC (CMS) and CMS* * * @author Nico von Geyso * @@ -43,6 +43,11 @@ static int ccm_compute_cbc_mac(cipher_t *cipher, const uint8_t iv[16], block_size = cipher_get_block_size(cipher); memmove(mac, iv, 16); offset = 0; + + if(length == 0) { + return 0; + } + do { uint8_t block_size_input = (length - offset > block_size) ? block_size : length - offset; @@ -76,7 +81,8 @@ static int ccm_create_mac_iv(cipher_t *cipher, uint8_t auth_data_len, uint8_t M, /* set flags in B[0] - bit format: 7 6 5..3 2..0 Reserved Adata M_ L_ */ - M_ = (M - 2) / 2; + M_ = M == 0 ? 0 : (M - 2) / 2; + L_ = L - 1; X1[0] = 64 * (auth_data_len > 0) + 8 * M_ + L_; @@ -168,7 +174,17 @@ static inline int _fits_in_nbytes(size_t value, uint8_t num_bytes) } -int cipher_encrypt_ccm(cipher_t *cipher, +static int _validate_mac_length_ccm(uint8_t mac_length) +{ + return (mac_length % 2 != 0 || mac_length < 4 || mac_length > 16); +} + +static int _validate_mac_length_ccms(uint8_t mac_length) +{ + return (mac_length % 2 != 0 || mac_length > 16); +} + +int _cipher_encrypt_ccm(cipher_t *cipher, const uint8_t *auth_data, uint32_t auth_data_len, uint8_t mac_length, uint8_t length_encoding, const uint8_t *nonce, size_t nonce_len, @@ -179,10 +195,6 @@ int cipher_encrypt_ccm(cipher_t *cipher, uint8_t nonce_counter[16] = { 0 }, mac_iv[16] = { 0 }, mac[16] = { 0 }, stream_block[16] = { 0 }, zero_block[16] = { 0 }, block_size; - if (mac_length % 2 != 0 || mac_length < 4 || mac_length > 16) { - return CCM_ERR_INVALID_MAC_LENGTH; - } - if (length_encoding < 2 || length_encoding > 8 || !_fits_in_nbytes(input_len, length_encoding)) { return CCM_ERR_INVALID_LENGTH_ENCODING; @@ -234,7 +246,7 @@ int cipher_encrypt_ccm(cipher_t *cipher, } -int cipher_decrypt_ccm(cipher_t *cipher, +int _cipher_decrypt_ccm(cipher_t *cipher, const uint8_t *auth_data, uint32_t auth_data_len, uint8_t mac_length, uint8_t length_encoding, const uint8_t *nonce, size_t nonce_len, @@ -248,10 +260,6 @@ int cipher_decrypt_ccm(cipher_t *cipher, block_size; size_t plain_len; - if (mac_length % 2 != 0 || mac_length < 4 || mac_length > 16) { - return CCM_ERR_INVALID_MAC_LENGTH; - } - if (length_encoding < 2 || length_encoding > 8 || !_fits_in_nbytes(input_len, length_encoding)) { return CCM_ERR_INVALID_LENGTH_ENCODING; @@ -305,3 +313,71 @@ int cipher_decrypt_ccm(cipher_t *cipher, return plain_len; } + +int cipher_decrypt_ccm(cipher_t *cipher, + const uint8_t *auth_data, uint32_t auth_data_len, + uint8_t mac_length, uint8_t length_encoding, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *input, size_t input_len, + uint8_t *plain) +{ + if(_validate_mac_length_ccm(mac_length)){ + return CCM_ERR_INVALID_MAC_LENGTH; + } + else { + return _cipher_decrypt_ccm(cipher, auth_data, auth_data_len, mac_length, + length_encoding, nonce, nonce_len, input, + input_len, plain); + } +} + +int cipher_decrypt_ccms(cipher_t *cipher, + const uint8_t *auth_data, uint32_t auth_data_len, + uint8_t mac_length, uint8_t length_encoding, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *input, size_t input_len, + uint8_t *plain) +{ + if(_validate_mac_length_ccms(mac_length)){ + return CCM_ERR_INVALID_MAC_LENGTH; + } + else { + return _cipher_decrypt_ccm(cipher, auth_data, auth_data_len, mac_length, + length_encoding, nonce, nonce_len, input, + input_len, plain); + } +} + +int cipher_encrypt_ccm(cipher_t *cipher, + const uint8_t *auth_data, uint32_t auth_data_len, + uint8_t mac_length, uint8_t length_encoding, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *input, size_t input_len, + uint8_t *output) +{ + if(_validate_mac_length_ccm(mac_length)) { + return CCM_ERR_INVALID_MAC_LENGTH; + } + else { + return _cipher_encrypt_ccm(cipher, auth_data, auth_data_len, mac_length, + length_encoding, nonce, nonce_len, input, + input_len, output); + } +} + +int cipher_encrypt_ccms(cipher_t *cipher, + const uint8_t *auth_data, uint32_t auth_data_len, + uint8_t mac_length, uint8_t length_encoding, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *input, size_t input_len, + uint8_t *output) +{ + if(_validate_mac_length_ccms(mac_length)) { + return CCM_ERR_INVALID_MAC_LENGTH; + } + else { + return _cipher_encrypt_ccm(cipher, auth_data, auth_data_len, mac_length, + length_encoding, nonce, nonce_len, input, + input_len, output); + } +} diff --git a/sys/include/crypto/modes/ccm.h b/sys/include/crypto/modes/ccm.h index 4c81593ae724..d5a554814bfb 100644 --- a/sys/include/crypto/modes/ccm.h +++ b/sys/include/crypto/modes/ccm.h @@ -20,29 +20,12 @@ #ifndef CRYPTO_MODES_CCM_H #define CRYPTO_MODES_CCM_H -#include "crypto/ciphers.h" +#include "ccm_common.h" #ifdef __cplusplus extern "C" { #endif -/** - * @name CCM error codes - * @{ - */ -#define CCM_ERR_INVALID_NONCE_LENGTH (-2) -#define CCM_ERR_INVALID_CBC_MAC (-3) -#define CCM_ERR_INVALID_DATA_LENGTH (-3) -#define CCM_ERR_INVALID_LENGTH_ENCODING (-4) -#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. * diff --git a/sys/include/crypto/modes/ccm_common.h b/sys/include/crypto/modes/ccm_common.h new file mode 100644 index 000000000000..fd54ad599d86 --- /dev/null +++ b/sys/include/crypto/modes/ccm_common.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup sys_crypto + * @{ + * + * @file ccm.h + * @brief Common header definitions for CBC-MAC (CCM) and CCM* (CCMS) + * + * @author Freie Universitaet Berlin, Computer Systems & Telematics + * @author Nico von Geyso + */ + +#ifndef CRYPTO_MODES_CCM_COMMON_H +#define CRYPTO_MODES_CCM_COMMON_H + +#include "crypto/ciphers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name CCM error codes + * @{ + */ +#define CCM_ERR_INVALID_NONCE_LENGTH (-2) +#define CCM_ERR_INVALID_CBC_MAC (-3) +#define CCM_ERR_INVALID_DATA_LENGTH (-3) +#define CCM_ERR_INVALID_LENGTH_ENCODING (-4) +#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 + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTO_MODES_CCM_H */ +/** @} */ diff --git a/sys/include/crypto/modes/ccms.h b/sys/include/crypto/modes/ccms.h new file mode 100644 index 000000000000..f4b2a8343bf0 --- /dev/null +++ b/sys/include/crypto/modes/ccms.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2020 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup sys_crypto + * @{ + * + * @file ccms.h + * @brief Counter with CCM* mode of operation for block ciphers + * + * @author Francisco Molina + */ + +#ifndef CRYPTO_MODES_CCMS_H +#define CRYPTO_MODES_CCMS_H + +#include "ccm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Encrypt and authenticate data of arbitrary length in ccms mode. + * + * @param cipher Already initialized cipher struct + * @param auth_data Additional data to authenticate in MAC + * @param auth_data_len Length of additional data, max (2^16 - 2^8) + * @param mac_length length of the appended MAC (between 0 and 16 - only + * even values) + * @param length_encoding maximal supported length of plaintext + * (2^(8*length_enc)), implementation supports (2^32) + * @param nonce Nounce for ctr mode encryption + * @param nonce_len Length of the nonce in octets + * (maximum: 15-length_encoding) + * @param input pointer to input data to encrypt + * @param input_len length of the input data, max 2^32 + * @param output pointer to allocated memory for encrypted data. It + * has to be of size data_len + mac_length. + * @return Length of encrypted data on a successful encryption + * @return A negative error code if something went wrong + */ +int cipher_encrypt_ccms(cipher_t *cipher, + const uint8_t *auth_data, uint32_t auth_data_len, + uint8_t mac_length, uint8_t length_encoding, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *input, size_t input_len, + uint8_t *output); + + +/** + * @brief Decrypt data of arbitrary length in ccms mode. + * + * @param cipher Already initialized cipher struct + * @param auth_data Additional data to authenticate in MAC + * @param auth_data_len Length of additional data, max (2^16 - 2^8) + * @param mac_length length of the appended MAC (between 0 and 16 - only + * even values) + * @param length_encoding maximal supported length of plaintext + * (2^(8*length_enc)), implementation supports (2^32) + * @param nonce Nounce for ctr mode encryption + * @param nonce_len Length of the nonce in octets + * (maximum: 15-length_encoding) + * @param input pointer to input data to decrypt + * @param input_len length of the input data, max 2^32 + * @param output pointer to allocated memory for decrypted data. It + * has to be of size data_len - mac_length. + * + * @return Length of the decrypted data on a successful decryption + * @return A negative error code if something went wrong + */ +int cipher_decrypt_ccms(cipher_t *cipher, + const uint8_t *auth_data, uint32_t auth_data_len, + uint8_t mac_length, uint8_t length_encoding, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *input, size_t input_len, + uint8_t *output); + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTO_MODES_CCMS_H */ +/** @} */ From 0032f6ba2debf23bb91d014a7254296a4ad177d8 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Fri, 17 Jan 2020 09:19:42 +0100 Subject: [PATCH 02/14] tests/sys_crypto: add ccms test --- tests/sys_crypto/main.c | 1 + tests/sys_crypto/tests-crypto-modes-ccms.c | 318 +++++++++++++++++++++ tests/sys_crypto/tests-crypto.h | 1 + 3 files changed, 320 insertions(+) create mode 100644 tests/sys_crypto/tests-crypto-modes-ccms.c diff --git a/tests/sys_crypto/main.c b/tests/sys_crypto/main.c index 9cf320889e97..b1127183daf7 100644 --- a/tests/sys_crypto/main.c +++ b/tests/sys_crypto/main.c @@ -19,6 +19,7 @@ int main(void) TESTS_RUN(tests_crypto_aes_tests()); TESTS_RUN(tests_crypto_cipher_tests()); TESTS_RUN(tests_crypto_modes_ccm_tests()); + TESTS_RUN(tests_crypto_modes_ccms_tests()); TESTS_RUN(tests_crypto_modes_ocb_tests()); TESTS_RUN(tests_crypto_modes_ecb_tests()); TESTS_RUN(tests_crypto_modes_cbc_tests()); diff --git a/tests/sys_crypto/tests-crypto-modes-ccms.c b/tests/sys_crypto/tests-crypto-modes-ccms.c new file mode 100644 index 000000000000..d0030bb481d1 --- /dev/null +++ b/tests/sys_crypto/tests-crypto-modes-ccms.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2015 Nico von Geyso + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include + +#include +#include +#include + +#include "embUnit.h" +#include "crypto/ciphers.h" +#include "crypto/modes/ccms.h" +#include "tests-crypto.h" + +static const size_t nonce_and_len_encoding_size = 15; + +/* IEEE 0537r2 */ +static const uint8_t TEST_IEEE_0537R2_1_KEY[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF +}; +static const uint8_t TEST_IEEE_0537R2_1_KEY_LEN = 16; +static const uint8_t TEST_IEEE_0537R2_1_NONCE[] = { + 0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, 0x02 +}; +static const uint8_t TEST_IEEE_0537R2_1_NONCE_LEN = 13; +static const uint8_t TEST_IEEE_0537R2_1_MAC_LEN = 8; +static const uint8_t TEST_IEEE_0537R2_1_INPUT[] = { + /* AAD */ + 0x08, 0xD0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x02, 0x05, 0x00, + 0x00, 0x00, 0x55, 0xCF, 0x00, 0x00, 0x51, 0x52, + 0x53, 0x54, + /* PLAINTEXT */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const size_t TEST_IEEE_0537R2_1_INPUT_LEN = 0; +static const size_t TEST_IEEE_0537R2_1_ADATA_LEN = 26; +static const uint8_t TEST_IEEE_0537R2_1_EXPECTED[] = { + /* AAD */ + 0x08, 0xD0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x02, 0x05, 0x00, + 0x00, 0x00, 0x55, 0xCF, 0x00, 0x00, 0x51, 0x52, + 0x53, 0x54, + /* MAC */ + 0x22, 0x3B, 0xC1, 0xEC, 0x84, 0x1A, 0xB5, 0x53, +}; +static const size_t TEST_IEEE_0537R2_1_EXPECTED_LEN = 34; + +/* IEEE 0537r2 */ +static const uint8_t TEST_IEEE_0537R2_2_KEY[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF +}; +static const uint8_t TEST_IEEE_0537R2_2_KEY_LEN = 16; +static const uint8_t TEST_IEEE_0537R2_2_NONCE[] = { + 0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, 0x04 +}; +static const uint8_t TEST_IEEE_0537R2_2_NONCE_LEN = 13; +static const uint8_t TEST_IEEE_0537R2_2_MAC_LEN = 0; +static const uint8_t TEST_IEEE_0537R2_2_INPUT[] = { + /* AAD */ + 0x69, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x04, 0x05, 0x00, + 0x00, 0x00, + /* PLAINTEXT */ + 0x61, 0x62, 0x63, 0x64 +}; +static const size_t TEST_IEEE_0537R2_2_INPUT_LEN = 4; +static const size_t TEST_IEEE_0537R2_2_ADATA_LEN = 26; +static const uint8_t TEST_IEEE_0537R2_2_EXPECTED[] = { + /* AAD */ + 0x69, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x04, 0x05, 0x00, + 0x00, 0x00, + /* CIPHERTEXT */ + 0xD4, 0x3E, 0x02, 0x2B, +}; +static const size_t TEST_IEEE_0537R2_2_EXPECTED_LEN = 30; + +/* IEEE 0537r2 */ +static const uint8_t TEST_IEEE_0537R2_3_KEY[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF +}; +static const uint8_t TEST_IEEE_0537R2_3_KEY_LEN = 16; +static const uint8_t TEST_IEEE_0537R2_3_NONCE[] = { + 0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, 0x06 +}; +static const uint8_t TEST_IEEE_0537R2_3_NONCE_LEN = 13; +static const uint8_t TEST_IEEE_0537R2_3_MAC_LEN = 8; +static const uint8_t TEST_IEEE_0537R2_3_INPUT[] = { + /* AAD */ + 0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xDE, 0xAC, 0xFF, 0xFF, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x06, + 0x05, 0x00, 0x00, 0x00, 0x01, + /* PLAINTEXT */ + 0xCE +}; +static const size_t TEST_IEEE_0537R2_3_INPUT_LEN = 1; +static const size_t TEST_IEEE_0537R2_3_ADATA_LEN = 29; +static const uint8_t TEST_IEEE_0537R2_3_EXPECTED[] = { + /* AAD */ + 0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xDE, 0xAC, 0xFF, 0xFF, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x06, + 0x05, 0x00, 0x00, 0x00, 0x01, + /* CIPHERTEXT */ + 0xD8, + /* MAC */ + 0x4F, 0xDE, 0x52, 0x90, 0x61, 0xF9, 0xC6, 0xF1 +}; +static const size_t TEST_IEEE_0537R2_3_EXPECTED_LEN = 38; + +/* Share test buffer output */ +static uint8_t data[512]; + +static void test_encrypt_op(const uint8_t *key, uint8_t key_len, + const uint8_t *adata, size_t adata_len, + const uint8_t *nonce, uint8_t nonce_len, + const uint8_t *plain, size_t plain_len, + const uint8_t *output_expected, + size_t output_expected_len, + uint8_t mac_length) +{ + cipher_t cipher; + int len, err, cmp; + size_t len_encoding = nonce_and_len_encoding_size - nonce_len; + + TEST_ASSERT_MESSAGE(sizeof(data) >= output_expected_len, + "Output buffer too small"); + + err = cipher_init(&cipher, CIPHER_AES_128, key, key_len); + TEST_ASSERT_EQUAL_INT(1, err); + + len = cipher_encrypt_ccms(&cipher, adata, adata_len, + mac_length, len_encoding, + nonce, nonce_len, plain, plain_len, data); + TEST_ASSERT_MESSAGE(len >= 0, "Encryption failed"); + + 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, + const uint8_t *adata, size_t adata_len, + const uint8_t *nonce, uint8_t nonce_len, + const uint8_t *encrypted, size_t encrypted_len, + const uint8_t *output_expected, + size_t output_expected_len, + uint8_t mac_length) +{ + cipher_t cipher; + int len, err, cmp; + size_t len_encoding = nonce_and_len_encoding_size - nonce_len; + + TEST_ASSERT_MESSAGE(sizeof(data) >= output_expected_len, + "Output buffer too small"); + + err = cipher_init(&cipher, CIPHER_AES_128, key, key_len); + TEST_ASSERT_EQUAL_INT(1, err); + + len = cipher_decrypt_ccms(&cipher, adata, adata_len, + mac_length, len_encoding, + nonce, nonce_len, encrypted, encrypted_len, data); + TEST_ASSERT_MESSAGE(len >= 0, "Decryption failed"); + + TEST_ASSERT_EQUAL_INT(output_expected_len, len); + cmp = compare(output_expected, data, len); + TEST_ASSERT_MESSAGE(1 == cmp, "wrong ciphertext"); + +} + +#define do_test_encrypt_op(name) do { \ + test_encrypt_op(TEST_ ## name ## _KEY, TEST_ ## name ## _KEY_LEN, \ + TEST_ ## name ## _INPUT, TEST_ ## name ## _ADATA_LEN, \ + TEST_ ## name ## _NONCE, TEST_ ## name ## _NONCE_LEN, \ + \ + TEST_ ## name ## _INPUT + TEST_ ## name ## _ADATA_LEN, \ + TEST_ ## name ## _INPUT_LEN, \ + \ + TEST_ ## name ## _EXPECTED + TEST_ ## name ## _ADATA_LEN, \ + TEST_ ## name ## _EXPECTED_LEN - TEST_ ## name ## _ADATA_LEN, \ + \ + TEST_ ## name ## _MAC_LEN \ + ); \ +} while (0) + + +static void test_crypto_modes_ccms_encrypt(void) +{ + do_test_encrypt_op(IEEE_0537R2_1); + do_test_encrypt_op(IEEE_0537R2_2); + do_test_encrypt_op(IEEE_0537R2_3); +} + +#define do_test_decrypt_op(name) do { \ + test_decrypt_op(TEST_ ## name ## _KEY, TEST_ ## name ## _KEY_LEN, \ + TEST_ ## name ## _INPUT, TEST_ ## name ## _ADATA_LEN, \ + TEST_ ## name ## _NONCE, TEST_ ## name ## _NONCE_LEN, \ + \ + TEST_ ## name ## _EXPECTED + TEST_ ## name ## _ADATA_LEN, \ + TEST_ ## name ## _EXPECTED_LEN - TEST_ ## name ## _ADATA_LEN, \ + \ + TEST_ ## name ## _INPUT + TEST_ ## name ## _ADATA_LEN, \ + TEST_ ## name ## _INPUT_LEN, \ + \ + TEST_ ## name ## _MAC_LEN \ + ); \ +} while (0) + +static void test_crypto_modes_ccms_decrypt(void) +{ + do_test_decrypt_op(IEEE_0537R2_1); + do_test_decrypt_op(IEEE_0537R2_2); + do_test_decrypt_op(IEEE_0537R2_3); +} + + +typedef int (*func_ccms_t)(cipher_t *, const uint8_t *, uint32_t, + uint8_t, uint8_t, const uint8_t *, size_t, + const uint8_t *, size_t, uint8_t *); + +static int _test_ccms_len(func_ccms_t func, uint8_t len_encoding, + const uint8_t *input, size_t input_len, + size_t adata_len) +{ + int ret; + cipher_t cipher; + uint8_t mac_length = 8; + uint8_t nonce[15] = { 0 }; + uint8_t key[16] = { 0 }; + + uint8_t nonce_len = nonce_and_len_encoding_size - len_encoding; + + cipher_init(&cipher, CIPHER_AES_128, key, 16); + + ret = func(&cipher, NULL, adata_len, mac_length, len_encoding, + nonce, nonce_len, input, input_len, data); + return ret; +} + + +/* Test length checking in ccm functions. */ +static void test_crypto_modes_ccms_check_len(void) +{ + int ret; + +/* Using length_encoding above UINT16_MAX doesn't work on 8/16 bit + architectures, SIZE_MAX is equal to UINT16_MAX there */ +#if SIZE_MAX > UINT16_MAX + /* Just 1 to big to fit */ + ret = _test_ccms_len(cipher_encrypt_ccms, 2, NULL, 1 << 16, 0); + TEST_ASSERT_EQUAL_INT(CCM_ERR_INVALID_LENGTH_ENCODING, ret); + ret = _test_ccms_len(cipher_decrypt_ccms, 2, NULL, 1 << 16, 0); + TEST_ASSERT_EQUAL_INT(CCM_ERR_INVALID_LENGTH_ENCODING, ret); + + /* adata_len should not change the result (was wrong in previous implem) */ + ret = _test_ccms_len(cipher_encrypt_ccms, 2, NULL, 1 << 16, 65535); + TEST_ASSERT_EQUAL_INT(CCM_ERR_INVALID_LENGTH_ENCODING, ret); + ret = _test_ccms_len(cipher_decrypt_ccms, 2, NULL, 1 << 16, 65535); + TEST_ASSERT_EQUAL_INT(CCM_ERR_INVALID_LENGTH_ENCODING, ret); +#endif + + /* Invalid length when length_encoding < 2 */ + ret = _test_ccms_len(cipher_encrypt_ccms, 1, NULL, 8, 0); + 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_ccms_len(cipher_encrypt_ccms, 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_ccms_len(cipher_decrypt_ccms, 8, einput, 16, 0); + TEST_ASSERT_MESSAGE(ret > 0, "Decryption : failed with valid input_len"); + + /* ccm library does not support auth_data_len > 0xFEFF */ + ret = _test_ccms_len(cipher_encrypt_ccms, 2, NULL, 0, 0xFEFF + 1); + TEST_ASSERT_EQUAL_INT(-1, ret); +} + + +Test *tests_crypto_modes_ccms_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_crypto_modes_ccms_encrypt), + new_TestFixture(test_crypto_modes_ccms_decrypt), + new_TestFixture(test_crypto_modes_ccms_check_len), + }; + + EMB_UNIT_TESTCALLER(crypto_modes_ccms_tests, NULL, NULL, fixtures); + + return (Test *)&crypto_modes_ccms_tests; +} diff --git a/tests/sys_crypto/tests-crypto.h b/tests/sys_crypto/tests-crypto.h index eddf2d73bafe..c6ac6c96cb79 100644 --- a/tests/sys_crypto/tests-crypto.h +++ b/tests/sys_crypto/tests-crypto.h @@ -59,6 +59,7 @@ static inline int compare(const uint8_t *a, const uint8_t *b, uint8_t len) Test* tests_crypto_aes_tests(void); Test* tests_crypto_cipher_tests(void); Test* tests_crypto_modes_ccm_tests(void); +Test* tests_crypto_modes_ccms_tests(void); Test* tests_crypto_modes_ocb_tests(void); Test* tests_crypto_modes_ecb_tests(void); Test* tests_crypto_modes_cbc_tests(void); From acd0a7fdfffc2faa5c33f142c9372309132069a4 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Tue, 31 Mar 2020 10:12:59 +0200 Subject: [PATCH 03/14] fixup! tests/sys_crypto: add ccms test Fix naming --- sys/crypto/modes/ccm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/crypto/modes/ccm.c b/sys/crypto/modes/ccm.c index c026859e31a1..0731f1e99c63 100644 --- a/sys/crypto/modes/ccm.c +++ b/sys/crypto/modes/ccm.c @@ -11,7 +11,7 @@ * @{ * * @file - * @brief Crypto mode - counter with CBC-MAC (CMS) and CMS* + * @brief Crypto mode - counter with CBC-MAC (CCM) and CCM* * * @author Nico von Geyso * From ec8fccde9b3e1c05991eb818453a093ea61bc0f2 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Tue, 31 Mar 2020 10:14:01 +0200 Subject: [PATCH 04/14] fixup! fixup! tests/sys_crypto: add ccms test Fix and and comment on valid mac_length --- sys/crypto/modes/ccm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/crypto/modes/ccm.c b/sys/crypto/modes/ccm.c index 0731f1e99c63..7e9fbb01b573 100644 --- a/sys/crypto/modes/ccm.c +++ b/sys/crypto/modes/ccm.c @@ -173,15 +173,16 @@ static inline int _fits_in_nbytes(size_t value, uint8_t num_bytes) return (value >> shift) <= 1; } - +/* Valid mac_length are are 4, 6, 8 ... 16 octets */ static int _validate_mac_length_ccm(uint8_t mac_length) { return (mac_length % 2 != 0 || mac_length < 4 || mac_length > 16); } +/* Valid mac_length are are 0, 4, 6, 8 ... 16 octets */ static int _validate_mac_length_ccms(uint8_t mac_length) { - return (mac_length % 2 != 0 || mac_length > 16); + return (mac_length % 2 != 0 || mac_length == 2 || mac_length > 16); } int _cipher_encrypt_ccm(cipher_t *cipher, From e8e53a4ebfa511abb4de52b525bae4656dbdfa35 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Tue, 31 Mar 2020 10:35:20 +0200 Subject: [PATCH 05/14] fixup! fixup! fixup! tests/sys_crypto: add ccms test --- sys/crypto/modes/ccm.c | 4 ++-- sys/include/crypto/modes/ccms.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/crypto/modes/ccm.c b/sys/crypto/modes/ccm.c index 7e9fbb01b573..f5c6a5e839f0 100644 --- a/sys/crypto/modes/ccm.c +++ b/sys/crypto/modes/ccm.c @@ -173,13 +173,13 @@ static inline int _fits_in_nbytes(size_t value, uint8_t num_bytes) return (value >> shift) <= 1; } -/* Valid mac_length are are 4, 6, 8 ... 16 octets */ +/* Valid mac_length are 4, 6, 8 ... 16 octets */ static int _validate_mac_length_ccm(uint8_t mac_length) { return (mac_length % 2 != 0 || mac_length < 4 || mac_length > 16); } -/* Valid mac_length are are 0, 4, 6, 8 ... 16 octets */ +/* Valid mac_length are 0, 4, 6, 8 ... 16 octets */ static int _validate_mac_length_ccms(uint8_t mac_length) { return (mac_length % 2 != 0 || mac_length == 2 || mac_length > 16); diff --git a/sys/include/crypto/modes/ccms.h b/sys/include/crypto/modes/ccms.h index f4b2a8343bf0..992fe7308b92 100644 --- a/sys/include/crypto/modes/ccms.h +++ b/sys/include/crypto/modes/ccms.h @@ -32,7 +32,7 @@ extern "C" { * @param auth_data Additional data to authenticate in MAC * @param auth_data_len Length of additional data, max (2^16 - 2^8) * @param mac_length length of the appended MAC (between 0 and 16 - only - * even values) + * even values, 2 excluded) * @param length_encoding maximal supported length of plaintext * (2^(8*length_enc)), implementation supports (2^32) * @param nonce Nounce for ctr mode encryption From 1aad0fb0a8f94ed4eb7ae853a4342f15ad39dc02 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Tue, 31 Mar 2020 10:51:43 +0200 Subject: [PATCH 06/14] fixup! fixup! fixup! fixup! tests/sys_crypto: add ccms test More code comments --- sys/crypto/modes/ccm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/crypto/modes/ccm.c b/sys/crypto/modes/ccm.c index f5c6a5e839f0..935661b9ec84 100644 --- a/sys/crypto/modes/ccm.c +++ b/sys/crypto/modes/ccm.c @@ -81,6 +81,7 @@ static int ccm_create_mac_iv(cipher_t *cipher, uint8_t auth_data_len, uint8_t M, /* set flags in B[0] - bit format: 7 6 5..3 2..0 Reserved Adata M_ L_ */ + /* valid M values include 0 for CCMS */ M_ = M == 0 ? 0 : (M - 2) / 2; L_ = L - 1; From 3b4aca6e8e31c945b5079baea94a4556428f2568 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Tue, 31 Mar 2020 10:52:22 +0200 Subject: [PATCH 07/14] squash! fixup! fixup! fixup! fixup! tests/sys_crypto: add ccms test Returning 0 on an empty message is actually also a fix for ccm, so should be its own commit. --- sys/crypto/modes/ccm.c | 1 + tests/sys_crypto/tests-crypto-modes-ccm.c | 31 +++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/sys/crypto/modes/ccm.c b/sys/crypto/modes/ccm.c index 935661b9ec84..782fc71e16ab 100644 --- a/sys/crypto/modes/ccm.c +++ b/sys/crypto/modes/ccm.c @@ -44,6 +44,7 @@ static int ccm_compute_cbc_mac(cipher_t *cipher, const uint8_t iv[16], memmove(mac, iv, 16); offset = 0; + /* no input message */ if(length == 0) { return 0; } diff --git a/tests/sys_crypto/tests-crypto-modes-ccm.c b/tests/sys_crypto/tests-crypto-modes-ccm.c index 70b6afcbbcda..a62cbe1af082 100644 --- a/tests/sys_crypto/tests-crypto-modes-ccm.c +++ b/tests/sys_crypto/tests-crypto-modes-ccm.c @@ -826,6 +826,32 @@ 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 */ +/* tcId" : 1 */ +static const uint8_t TEST_WYCHEPROOF_1_KEY[] = { + 0xbe, 0xdc, 0xfb, 0x5a, 0x01, 0x1e, 0xbc, 0x84, + 0x60, 0x0f, 0xcb, 0x29, 0x6c, 0x15, 0xaf, 0x0d +}; +static const size_t TEST_WYCHEPROOF_1_KEY_LEN = 16; +static const uint8_t TEST_WYCHEPROOF_1_NONCE[] = { + 0x43, 0x8a, 0x54, 0x7a, 0x94, 0xea, 0x88, 0xdc, + 0xe4, 0x6c, 0x6c, 0x85 +}; +static const size_t TEST_WYCHEPROOF_1_NONCE_LEN = 12; +static const size_t TEST_WYCHEPROOF_1_MAC_LEN = 16; +static const uint8_t TEST_WYCHEPROOF_1_INPUT[] = { + /* PLAINTEXT */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const size_t TEST_WYCHEPROOF_1_INPUT_LEN = 0; +static const size_t TEST_WYCHEPROOF_1_ADATA_LEN = 0; +static const uint8_t TEST_WYCHEPROOF_1_EXPECTED[] = { + /* MAC */ + 0x25, 0xd1, 0xa3, 0x84, 0x95, 0xa7, 0xde, 0xa4, + 0x5b, 0xda, 0x04, 0x97, 0x05, 0x62, 0x7d, 0x10 +}; +static const size_t TEST_WYCHEPROOF_1_EXPECTED_LEN = 16; + +/* tcId" : 28 */ static const uint8_t TEST_WYCHEPROOF_28_KEY[] = { 0x20, 0xbb, 0xf7, 0x4c, 0x1e, 0x63, 0x98, 0x2c, 0x47, 0x2c, 0x47, 0x43, 0x56, 0x9e, 0x4c, 0x84, @@ -864,7 +890,6 @@ static const uint8_t TEST_WYCHEPROOF_28_EXPECTED[] = { }; static const size_t TEST_WYCHEPROOF_28_EXPECTED_LEN = 63; - /* Manually created test vectors */ /* This is neccessary, because no test vectors are published with input length > 256 */ /* Data has been verified against BouncyCastle (.NET Core) and pycryptodome */ @@ -1113,7 +1138,7 @@ static void test_decrypt_op(const uint8_t *key, uint8_t key_len, len = cipher_decrypt_ccm(&cipher, adata, adata_len, mac_length, len_encoding, nonce, nonce_len, encrypted, encrypted_len, data); - TEST_ASSERT_MESSAGE(len > 0, "Decryption failed"); + TEST_ASSERT_MESSAGE(len >= 0, "Decryption failed"); TEST_ASSERT_EQUAL_INT(output_expected_len, len); cmp = compare(output_expected, data, len); @@ -1168,6 +1193,7 @@ static void test_crypto_modes_ccm_encrypt(void) do_test_encrypt_op(NIST_2); do_test_encrypt_op(NIST_3); + do_test_encrypt_op(WYCHEPROOF_1); do_test_encrypt_op(WYCHEPROOF_28); do_test_encrypt_op(MANUAL_01); @@ -1220,6 +1246,7 @@ static void test_crypto_modes_ccm_decrypt(void) do_test_decrypt_op(NIST_2); do_test_decrypt_op(NIST_3); + do_test_decrypt_op(WYCHEPROOF_1); do_test_decrypt_op(WYCHEPROOF_28); do_test_decrypt_op(MANUAL_01); From fcf6095ebad3b1fbaf9f65a48ca04c85fb1f78aa Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 9 Apr 2020 10:53:47 +0200 Subject: [PATCH 08/14] fixup! fixup! fixup! fixup! fixup! tests/sys_crypto: add ccms test Add long plain text and aad tests --- tests/sys_crypto/tests-crypto-modes-ccms.c | 200 +++++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/tests/sys_crypto/tests-crypto-modes-ccms.c b/tests/sys_crypto/tests-crypto-modes-ccms.c index d0030bb481d1..fa5de5f5848f 100644 --- a/tests/sys_crypto/tests-crypto-modes-ccms.c +++ b/tests/sys_crypto/tests-crypto-modes-ccms.c @@ -123,6 +123,200 @@ static const uint8_t TEST_IEEE_0537R2_3_EXPECTED[] = { }; static const size_t TEST_IEEE_0537R2_3_EXPECTED_LEN = 38; +/* Manually created test vectors */ +/* This is necessary, because no test vectors are published with input length > 256 */ +/* Data has been verified against pycryptodome */ + +static const uint8_t TEST_MANUAL_01_KEY[] = { + 0x43, 0xDF, 0x83, 0x6A, 0x96, 0x35, 0xCC, 0x2A, + 0x72, 0x8B, 0x38, 0xEE, 0x7E, 0x9C, 0x83, 0x04, +}; +static const size_t TEST_MANUAL_01_KEY_LEN = 16; +static const uint8_t TEST_MANUAL_01_NONCE[] = { + 0x0F, 0xDB, 0xEE, 0xDC, 0xC4, 0x78, 0x01, 0x31, + 0xD9, 0xA0, 0xF7, +}; +static const size_t TEST_MANUAL_01_NONCE_LEN = 11; +static const size_t TEST_MANUAL_01_MAC_LEN = 16; +static const uint8_t TEST_MANUAL_01_INPUT[] = { + /* AAD */ + 0x04, 0xEB, 0xED, 0x59, 0x3E, 0x86, 0x38, 0x8A, + /* PLAINTEXT */ + 0x27, 0xD3, 0x77, 0x53, 0xEE, 0xA0, 0x1C, 0xA9, + 0x6D, 0x03, 0x84, 0x01, 0x76, 0xE2, 0x9A, 0x3A, + 0x5C, 0x7B, 0x5C, 0xE8, 0x97, 0x8F, 0x29, 0x34, + 0x78, 0x91, 0x5C, 0xCA, 0xAE, 0xE7, 0x0E, 0xB1, + 0x15, 0x9D, 0xE4, 0xBB, 0xB4, 0xAF, 0x9F, 0xF9, + 0xE1, 0x08, 0x78, 0xBB, 0x1D, 0x0D, 0x40, 0xEA, + 0x63, 0xC3, 0x86, 0x93, 0xD2, 0x22, 0xC3, 0x49, + 0x23, 0xF5, 0x7E, 0x64, 0x0A, 0x31, 0xE5, 0xE0, + 0x99, 0xCC, 0x5D, 0x04, 0x34, 0x07, 0xB2, 0xC5, + 0xAD, 0x05, 0x96, 0x03, 0xA7, 0x6B, 0x9B, 0x14, + 0x98, 0xE7, 0xB9, 0x72, 0xC9, 0x24, 0xF1, 0x21, + 0x18, 0x90, 0xE8, 0x87, 0x42, 0x31, 0x18, 0xC6, + 0x47, 0x0C, 0x92, 0x2C, 0x6B, 0x61, 0x79, 0x71, + 0x8F, 0xA6, 0x09, 0x03, 0xEF, 0x9A, 0x9C, 0x66, + 0x71, 0xF4, 0x13, 0x52, 0x5D, 0x79, 0x01, 0x5B, + 0x93, 0x6F, 0x46, 0x57, 0x04, 0xAB, 0xE0, 0x6A, + 0x11, 0xDC, 0x2B, 0x5B, 0x2E, 0x1B, 0xC9, 0xB7, + 0x9D, 0x49, 0x16, 0xDA, 0x56, 0x5F, 0x0E, 0xFD, + 0x05, 0xCB, 0x15, 0x1A, 0x62, 0x63, 0xC2, 0xC2, + 0xBA, 0x4A, 0x87, 0xE0, 0x7A, 0x2B, 0xBB, 0x6A, + 0x49, 0x92, 0xBC, 0x66, 0x78, 0xFA, 0x7F, 0xFD, + 0x8D, 0xB1, 0x9D, 0x68, 0x1C, 0x61, 0x73, 0x73, + 0x25, 0xCD, 0xE7, 0x51, 0x93, 0x2F, 0x94, 0xCA, + 0xCC, 0x97, 0x7E, 0xDF, 0x7D, 0x5B, 0xB9, 0x1A, + 0x4A, 0x48, 0x6B, 0x69, 0x59, 0xC7, 0x92, 0xDE, + 0xB3, 0xAD, 0xAA, 0xED, 0xC6, 0xA9, 0xEF, 0xBA, + 0x65, 0x19, 0x91, 0xCC, 0x62, 0x57, 0x60, 0xB2, + 0xD0, 0x8B, 0x55, 0x5C, 0x59, 0x96, 0x70, 0x81, + 0xFD, 0x2B, 0xB0, 0x70, 0x1C, 0xA5, 0x0A, 0x74, + 0xF0, 0xDB, 0xCA, 0x3F, 0x1C, 0xBC, 0x44, 0xC6, + 0x82, 0xE5, 0x62, 0x9B, 0x28, 0x76, 0xB7, 0x58, + 0x7F, 0xD0, 0xE8, 0xF0, 0x2B, 0x16, 0x71, 0x03, +}; +static const size_t TEST_MANUAL_01_INPUT_LEN = 256; +static const size_t TEST_MANUAL_01_ADATA_LEN = 8; +static const uint8_t TEST_MANUAL_01_EXPECTED[] = { + /* AAD */ + 0x04, 0xEB, 0xED, 0x59, 0x3E, 0x86, 0x38, 0x8A, + /* CIPHERTEXT */ + 0x56, 0x5C, 0x45, 0xCB, 0xFA, 0x76, 0x94, 0x98, + 0xE8, 0xF6, 0xA0, 0x6C, 0x9C, 0x74, 0x64, 0xA2, + 0x8D, 0x6C, 0xB1, 0xAC, 0x73, 0x6F, 0xA7, 0xC1, + 0x3A, 0x7C, 0x04, 0x0D, 0x72, 0x07, 0xFB, 0x7D, + 0x0F, 0x61, 0x06, 0x66, 0xAA, 0x62, 0x54, 0xD6, + 0x29, 0x56, 0x4A, 0xB5, 0x4F, 0x41, 0x90, 0x25, + 0xB6, 0x4A, 0x7E, 0xD1, 0x8F, 0x1A, 0xFE, 0x31, + 0xB9, 0xE4, 0x69, 0x47, 0x26, 0x8C, 0x05, 0x11, + 0xB8, 0x5E, 0x28, 0x38, 0x61, 0xDD, 0x04, 0x3B, + 0xE4, 0xF8, 0x74, 0x77, 0x90, 0xFE, 0x17, 0xF8, + 0x93, 0x6A, 0x8E, 0x8F, 0xDB, 0x81, 0x35, 0x6E, + 0x44, 0x8D, 0xF6, 0x5C, 0x4B, 0xD5, 0xFD, 0x95, + 0x2A, 0x7F, 0x59, 0xEB, 0x78, 0x29, 0x75, 0x2F, + 0x57, 0x45, 0x6E, 0x2C, 0xAF, 0x74, 0xD1, 0x39, + 0x8C, 0x60, 0x87, 0x3D, 0x86, 0xB2, 0x57, 0x92, + 0xD7, 0xDF, 0x09, 0xDB, 0x31, 0xE0, 0x93, 0x10, + 0x72, 0xD8, 0x7D, 0xC3, 0xD9, 0x27, 0xE9, 0x14, + 0x4A, 0x88, 0xFE, 0xE4, 0x06, 0x60, 0xB4, 0x7A, + 0x1D, 0x0D, 0xB6, 0x8D, 0x8C, 0x80, 0x94, 0xF7, + 0xF6, 0x69, 0xE0, 0x47, 0xD8, 0x6B, 0xA8, 0x0D, + 0x51, 0x86, 0x6A, 0x84, 0x37, 0xCD, 0x1D, 0x16, + 0x99, 0xDC, 0xB9, 0xA9, 0x81, 0x3E, 0xC2, 0xBD, + 0x14, 0x77, 0x2C, 0x3B, 0x42, 0xAC, 0xDD, 0x88, + 0xF6, 0x7C, 0xC2, 0xAB, 0x0D, 0x85, 0x9D, 0x96, + 0x5D, 0xE7, 0x70, 0x94, 0x70, 0xDB, 0x2F, 0x61, + 0x1F, 0x1C, 0xAD, 0x74, 0xEF, 0x33, 0xCA, 0x00, + 0xBC, 0x61, 0xF4, 0x03, 0x05, 0x98, 0x2E, 0x9C, + 0x9E, 0x13, 0x1B, 0xA1, 0x7E, 0x79, 0xEE, 0x49, + 0x3E, 0x4F, 0xC0, 0xF5, 0x3A, 0xD2, 0x03, 0x82, + 0x4B, 0x7E, 0xA3, 0xE2, 0x93, 0x62, 0xC8, 0xF0, + 0x28, 0x11, 0xC3, 0xAD, 0xF8, 0x53, 0x70, 0xAA, + 0xCA, 0xB7, 0x9E, 0xFB, 0xF1, 0x08, 0x9A, 0x7D, + /* MAC */ + 0xB9, 0x8E, 0xC7, 0xDD, 0x33, 0x19, 0x92, 0x29, + 0x9D, 0x21, 0xAD, 0xC8, 0xBB, 0x5B, 0x4C, 0x02, + +}; +static const size_t TEST_MANUAL_01_EXPECTED_LEN = 280; + +static const uint8_t TEST_MANUAL_02_KEY[] = { + 0x32, 0xDA, 0x53, 0x3B, 0x4D, 0xBF, 0x6D, 0x12, + 0xBD, 0xAF, 0xEE, 0xB9, 0x53, 0x8F, 0x20, 0x2F +}; +static const size_t TEST_MANUAL_02_KEY_LEN = 16; +static const uint8_t TEST_MANUAL_02_NONCE[] = { + 0x01, 0xF0, 0x4F, 0x88, 0x73, 0xEA, 0x67, 0x5D, + 0x98, 0xA4, 0x3A, 0x4E, 0x06 +}; +static const size_t TEST_MANUAL_02_NONCE_LEN = 13; +static const size_t TEST_MANUAL_02_MAC_LEN = 16; +static const uint8_t TEST_MANUAL_02_INPUT[] = { + /* AAD */ + 0x69, 0x0A, 0xD6, 0xDE, 0x26, 0x61, 0x68, 0x1E, + 0x8F, 0x02, 0xB1, 0x67, 0x10, 0x37, 0x2E, 0xB9, + 0x99, 0x2E, 0xA9, 0x7A, 0xB1, 0x97, 0x6A, 0x7C, + 0x2B, 0x2B, 0x15, 0xB0, 0x85, 0x00, 0xB3, 0x07, + 0xE5, 0xD6, 0xC7, 0x50, 0x1F, 0xFF, 0x91, 0xB7, + 0x1E, 0x07, 0xD7, 0x01, 0x04, 0xC3, 0x5F, 0xBA, + 0xFE, 0x9D, 0x62, 0xDC, 0xA1, 0x90, 0x05, 0x70, + 0x3F, 0xF8, 0x96, 0xEA, 0x42, 0x91, 0x12, 0xAE, + 0xDE, 0xB6, 0xC9, 0xA5, 0xC5, 0xBC, 0x9F, 0x7D, + 0xF1, 0xD1, 0xFA, 0xE0, 0x80, 0x49, 0xEC, 0x1F, + 0x72, 0xF0, 0x50, 0xE6, 0x75, 0x8C, 0x72, 0xC7, + 0x58, 0x4C, 0xEB, 0x89, 0xDC, 0x86, 0xE7, 0x91, + 0x12, 0xB4, 0x2D, 0x00, 0x52, 0xB9, 0x6E, 0x5B, + 0xA1, 0x55, 0xE9, 0xB2, 0x12, 0x40, 0xC8, 0x7B, + 0xDD, 0x30, 0x9A, 0xB8, 0xF6, 0xD8, 0x8D, 0xE8, + 0x16, 0xC9, 0xDD, 0xFD, 0xE6, 0xB9, 0x5A, 0xF7, + 0xEE, 0x61, 0x7F, 0x37, 0x9F, 0x52, 0x35, 0xA8, + 0x6A, 0x99, 0x32, 0x2A, 0x33, 0xE5, 0xFB, 0x94, + 0x70, 0xEB, 0x9D, 0x19, 0xC4, 0x2E, 0x73, 0x38, + 0x60, 0x98, 0xC5, 0x0B, 0x10, 0xA7, 0xD5, 0xD4, + 0x23, 0x85, 0x8F, 0x92, 0x33, 0x4F, 0xF5, 0x51, + 0x43, 0x15, 0x8B, 0x00, 0xA7, 0x5E, 0xA5, 0x9F, + 0xFE, 0xA0, 0xDC, 0x10, 0x7C, 0x3D, 0x7B, 0xFC, + 0x1F, 0x56, 0x4B, 0x21, 0x40, 0xF8, 0xEF, 0xE2, + 0xFA, 0xEB, 0x58, 0x79, 0x78, 0xBF, 0x30, 0x5A, + 0x1C, 0x6E, 0x90, 0x07, 0x7D, 0x84, 0x64, 0x26, + 0xB4, 0x54, 0x3E, 0xFD, 0x4A, 0xA9, 0x16, 0xFD, + 0xA7, 0x23, 0x26, 0xEF, 0x04, 0xEE, 0xBE, 0xDB, + 0xDF, 0x27, 0x6D, 0xCF, 0xF1, 0x5D, 0xC1, 0xB8, + 0xEE, 0xDB, 0x30, 0x51, 0xC5, 0x7F, 0xE9, 0xF4, + 0x05, 0x36, 0x6A, 0x51, 0xC8, 0x1E, 0xD4, 0x52, + 0x9C, 0xD2, 0x04, 0xEB, 0xED, 0x59, 0x3E, 0x86, + 0x38, 0x8A, + /* PLAINTEXT */ + 0x34, 0xCB, 0x14, 0xF8, 0x41, 0xEF, 0x56, 0x49, + 0x57, 0x79, 0xD4, 0x6B, 0x21, 0x97, 0x87, 0x24 +}; +static const size_t TEST_MANUAL_02_INPUT_LEN = 16; +static const size_t TEST_MANUAL_02_ADATA_LEN = 258; +static const uint8_t TEST_MANUAL_02_EXPECTED[] = { + /* AAD */ + 0x69, 0x0A, 0xD6, 0xDE, 0x26, 0x61, 0x68, 0x1E, + 0x8F, 0x02, 0xB1, 0x67, 0x10, 0x37, 0x2E, 0xB9, + 0x99, 0x2E, 0xA9, 0x7A, 0xB1, 0x97, 0x6A, 0x7C, + 0x2B, 0x2B, 0x15, 0xB0, 0x85, 0x00, 0xB3, 0x07, + 0xE5, 0xD6, 0xC7, 0x50, 0x1F, 0xFF, 0x91, 0xB7, + 0x1E, 0x07, 0xD7, 0x01, 0x04, 0xC3, 0x5F, 0xBA, + 0xFE, 0x9D, 0x62, 0xDC, 0xA1, 0x90, 0x05, 0x70, + 0x3F, 0xF8, 0x96, 0xEA, 0x42, 0x91, 0x12, 0xAE, + 0xDE, 0xB6, 0xC9, 0xA5, 0xC5, 0xBC, 0x9F, 0x7D, + 0xF1, 0xD1, 0xFA, 0xE0, 0x80, 0x49, 0xEC, 0x1F, + 0x72, 0xF0, 0x50, 0xE6, 0x75, 0x8C, 0x72, 0xC7, + 0x58, 0x4C, 0xEB, 0x89, 0xDC, 0x86, 0xE7, 0x91, + 0x12, 0xB4, 0x2D, 0x00, 0x52, 0xB9, 0x6E, 0x5B, + 0xA1, 0x55, 0xE9, 0xB2, 0x12, 0x40, 0xC8, 0x7B, + 0xDD, 0x30, 0x9A, 0xB8, 0xF6, 0xD8, 0x8D, 0xE8, + 0x16, 0xC9, 0xDD, 0xFD, 0xE6, 0xB9, 0x5A, 0xF7, + 0xEE, 0x61, 0x7F, 0x37, 0x9F, 0x52, 0x35, 0xA8, + 0x6A, 0x99, 0x32, 0x2A, 0x33, 0xE5, 0xFB, 0x94, + 0x70, 0xEB, 0x9D, 0x19, 0xC4, 0x2E, 0x73, 0x38, + 0x60, 0x98, 0xC5, 0x0B, 0x10, 0xA7, 0xD5, 0xD4, + 0x23, 0x85, 0x8F, 0x92, 0x33, 0x4F, 0xF5, 0x51, + 0x43, 0x15, 0x8B, 0x00, 0xA7, 0x5E, 0xA5, 0x9F, + 0xFE, 0xA0, 0xDC, 0x10, 0x7C, 0x3D, 0x7B, 0xFC, + 0x1F, 0x56, 0x4B, 0x21, 0x40, 0xF8, 0xEF, 0xE2, + 0xFA, 0xEB, 0x58, 0x79, 0x78, 0xBF, 0x30, 0x5A, + 0x1C, 0x6E, 0x90, 0x07, 0x7D, 0x84, 0x64, 0x26, + 0xB4, 0x54, 0x3E, 0xFD, 0x4A, 0xA9, 0x16, 0xFD, + 0xA7, 0x23, 0x26, 0xEF, 0x04, 0xEE, 0xBE, 0xDB, + 0xDF, 0x27, 0x6D, 0xCF, 0xF1, 0x5D, 0xC1, 0xB8, + 0xEE, 0xDB, 0x30, 0x51, 0xC5, 0x7F, 0xE9, 0xF4, + 0x05, 0x36, 0x6A, 0x51, 0xC8, 0x1E, 0xD4, 0x52, + 0x9C, 0xD2, 0x04, 0xEB, 0xED, 0x59, 0x3E, 0x86, + 0x38, 0x8A, + /* CIPHERTEXT */ + 0xC0, 0x12, 0x0C, 0x23, 0x29, 0xAF, 0x50, 0x92, + 0xB4, 0xAA, 0x25, 0x4F, 0xB9, 0x4F, 0xE5, 0xB6, + /* MAC */ + 0x2C, 0xCA, 0x46, 0x8C, 0x63, 0x49, 0xBA, 0x5D, + 0xAB, 0x80, 0x8B, 0xD1, 0xA9, 0xF2, 0x05, 0x71, + +}; +static const size_t TEST_MANUAL_02_EXPECTED_LEN = 290; + /* Share test buffer output */ static uint8_t data[512]; @@ -204,6 +398,9 @@ static void test_crypto_modes_ccms_encrypt(void) do_test_encrypt_op(IEEE_0537R2_1); do_test_encrypt_op(IEEE_0537R2_2); do_test_encrypt_op(IEEE_0537R2_3); + + do_test_encrypt_op(MANUAL_01); + do_test_encrypt_op(MANUAL_02); } #define do_test_decrypt_op(name) do { \ @@ -226,6 +423,9 @@ static void test_crypto_modes_ccms_decrypt(void) do_test_decrypt_op(IEEE_0537R2_1); do_test_decrypt_op(IEEE_0537R2_2); do_test_decrypt_op(IEEE_0537R2_3); + + do_test_decrypt_op(MANUAL_01); + do_test_decrypt_op(MANUAL_02); } From 258cf23676d119d0a101fe981d733fb66432fd5a Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 9 Apr 2020 11:33:06 +0200 Subject: [PATCH 09/14] fixup! fixup! fixup! fixup! fixup! fixup! tests/sys_crypto: add ccms test Fix ccm to ccms --- tests/sys_crypto/tests-crypto-modes-ccms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sys_crypto/tests-crypto-modes-ccms.c b/tests/sys_crypto/tests-crypto-modes-ccms.c index fa5de5f5848f..c1d7c40bcb43 100644 --- a/tests/sys_crypto/tests-crypto-modes-ccms.c +++ b/tests/sys_crypto/tests-crypto-modes-ccms.c @@ -453,7 +453,7 @@ static int _test_ccms_len(func_ccms_t func, uint8_t len_encoding, } -/* Test length checking in ccm functions. */ +/* Test length checking in ccms functions. */ static void test_crypto_modes_ccms_check_len(void) { int ret; @@ -498,7 +498,7 @@ static void test_crypto_modes_ccms_check_len(void) ret = _test_ccms_len(cipher_decrypt_ccms, 8, einput, 16, 0); TEST_ASSERT_MESSAGE(ret > 0, "Decryption : failed with valid input_len"); - /* ccm library does not support auth_data_len > 0xFEFF */ + /* ccms library does not support auth_data_len > 0xFEFF */ ret = _test_ccms_len(cipher_encrypt_ccms, 2, NULL, 0, 0xFEFF + 1); TEST_ASSERT_EQUAL_INT(-1, ret); } From b11172bdc10e710f1ac8b475b51eb11272ad832a Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 9 Apr 2020 11:44:17 +0200 Subject: [PATCH 10/14] fixup! fixup! fixup! tests/sys_crypto: add ccms test _valid_mac_length_% return 1 if valid, 0 otherwise --- sys/crypto/modes/ccm.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/sys/crypto/modes/ccm.c b/sys/crypto/modes/ccm.c index 782fc71e16ab..88129fbb68e3 100644 --- a/sys/crypto/modes/ccm.c +++ b/sys/crypto/modes/ccm.c @@ -176,15 +176,16 @@ static inline int _fits_in_nbytes(size_t value, uint8_t num_bytes) } /* Valid mac_length are 4, 6, 8 ... 16 octets */ -static int _validate_mac_length_ccm(uint8_t mac_length) +static bool _valid_mac_length_ccm(uint8_t mac_length) { - return (mac_length % 2 != 0 || mac_length < 4 || mac_length > 16); + return (mac_length % 2 == 0 && mac_length >= 4 && mac_length <= 16); } /* Valid mac_length are 0, 4, 6, 8 ... 16 octets */ -static int _validate_mac_length_ccms(uint8_t mac_length) +static bool _valid_mac_length_ccms(uint8_t mac_length) { - return (mac_length % 2 != 0 || mac_length == 2 || mac_length > 16); + return (mac_length == 0) || \ + (mac_length % 2 == 0 && mac_length >=4 && mac_length <= 16); } int _cipher_encrypt_ccm(cipher_t *cipher, @@ -324,14 +325,14 @@ int cipher_decrypt_ccm(cipher_t *cipher, const uint8_t *input, size_t input_len, uint8_t *plain) { - if(_validate_mac_length_ccm(mac_length)){ - return CCM_ERR_INVALID_MAC_LENGTH; - } - else { + if(_valid_mac_length_ccm(mac_length)){ return _cipher_decrypt_ccm(cipher, auth_data, auth_data_len, mac_length, length_encoding, nonce, nonce_len, input, input_len, plain); } + else { + return CCM_ERR_INVALID_MAC_LENGTH; + } } int cipher_decrypt_ccms(cipher_t *cipher, @@ -341,14 +342,14 @@ int cipher_decrypt_ccms(cipher_t *cipher, const uint8_t *input, size_t input_len, uint8_t *plain) { - if(_validate_mac_length_ccms(mac_length)){ - return CCM_ERR_INVALID_MAC_LENGTH; - } - else { + if(_valid_mac_length_ccms(mac_length)){ return _cipher_decrypt_ccm(cipher, auth_data, auth_data_len, mac_length, length_encoding, nonce, nonce_len, input, input_len, plain); } + else { + return CCM_ERR_INVALID_MAC_LENGTH; + } } int cipher_encrypt_ccm(cipher_t *cipher, @@ -358,14 +359,14 @@ int cipher_encrypt_ccm(cipher_t *cipher, const uint8_t *input, size_t input_len, uint8_t *output) { - if(_validate_mac_length_ccm(mac_length)) { - return CCM_ERR_INVALID_MAC_LENGTH; - } - else { + if(_valid_mac_length_ccm(mac_length)) { return _cipher_encrypt_ccm(cipher, auth_data, auth_data_len, mac_length, length_encoding, nonce, nonce_len, input, input_len, output); } + else { + return CCM_ERR_INVALID_MAC_LENGTH; + } } int cipher_encrypt_ccms(cipher_t *cipher, @@ -375,12 +376,12 @@ int cipher_encrypt_ccms(cipher_t *cipher, const uint8_t *input, size_t input_len, uint8_t *output) { - if(_validate_mac_length_ccms(mac_length)) { - return CCM_ERR_INVALID_MAC_LENGTH; - } - else { + if(_valid_mac_length_ccms(mac_length)) { return _cipher_encrypt_ccm(cipher, auth_data, auth_data_len, mac_length, length_encoding, nonce, nonce_len, input, input_len, output); } + else { + return CCM_ERR_INVALID_MAC_LENGTH; + } } From 1f2698c929002a8e17ce64d9d34ff104d85b5f9a Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 9 Apr 2020 12:02:22 +0200 Subject: [PATCH 11/14] fixup! sys/crypto: add ccms Skip MAC computation when M=0 --- sys/crypto/modes/ccm.c | 51 ++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/sys/crypto/modes/ccm.c b/sys/crypto/modes/ccm.c index 88129fbb68e3..d058814b8bb3 100644 --- a/sys/crypto/modes/ccm.c +++ b/sys/crypto/modes/ccm.c @@ -82,8 +82,7 @@ static int ccm_create_mac_iv(cipher_t *cipher, uint8_t auth_data_len, uint8_t M, /* set flags in B[0] - bit format: 7 6 5..3 2..0 Reserved Adata M_ L_ */ - /* valid M values include 0 for CCMS */ - M_ = M == 0 ? 0 : (M - 2) / 2; + M_ = (M - 2) / 2; L_ = L - 1; X1[0] = 64 * (auth_data_len > 0) + 8 * M_ + L_; @@ -207,15 +206,22 @@ 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; - } - /* MAC calculation (T) with additional data and plaintext */ - len = ccm_compute_adata_mac(cipher, auth_data, auth_data_len, mac_iv); - if (len < 0) { - return len; + /* The value M = 0 (mac_length = 0) corresponds to disabling authenticity, + since then the authentication field is the empty string, this is only + possible in ccms, in ccm mac_lenth !=0 would have been checked by + _valid_mac_length_ccm() */ + if (mac_length != 0) { + 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; + } + + /* MAC calculation (T) with additional data and plaintext */ + len = ccm_compute_adata_mac(cipher, auth_data, auth_data_len, mac_iv); + if (len < 0) { + return len; + } } len = ccm_compute_cbc_mac(cipher, mac_iv, input, input_len, mac); @@ -290,17 +296,24 @@ int _cipher_decrypt_ccm(cipher_t *cipher, return len; } - /* Create B0, encrypt it (X1) and use it as mac_iv */ - if (ccm_create_mac_iv(cipher, auth_data_len, mac_length, length_encoding, - nonce, nonce_len, plain_len, mac_iv) < 0) { - return CCM_ERR_INVALID_DATA_LENGTH; - } + /* The value M = 0 (mac_length = 0) corresponds to disabling authenticity, + since then the authentication field is the empty string, this is only + possible in ccms, in ccm mac_lenth !=0 would have been checked by + _valid_mac_length_ccm() */ + if (mac_length != 0) { + /* Create B0, encrypt it (X1) and use it as mac_iv */ + if (ccm_create_mac_iv(cipher, auth_data_len, mac_length, length_encoding, + nonce, nonce_len, plain_len, mac_iv) < 0) { + return CCM_ERR_INVALID_DATA_LENGTH; + } - /* MAC calculation (T) with additional data and plaintext */ - len = ccm_compute_adata_mac(cipher, auth_data, auth_data_len, mac_iv); - if (len < 0) { - return len; + /* MAC calculation (T) with additional data and plaintext */ + len = ccm_compute_adata_mac(cipher, auth_data, auth_data_len, mac_iv); + if (len < 0) { + return len; + } } + len = ccm_compute_cbc_mac(cipher, mac_iv, plain, plain_len, mac); if (len < 0) { return len; From 00c6a82817baa4a6b7bf0e776bcf5b3a09878c86 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 9 Apr 2020 12:10:50 +0200 Subject: [PATCH 12/14] fixup! squash! fixup! fixup! fixup! fixup! tests/sys_crypto: add ccms test change doc to make explicit that plaintext=0 is allowed --- sys/include/crypto/modes/ccm.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sys/include/crypto/modes/ccm.h b/sys/include/crypto/modes/ccm.h index d5a554814bfb..1e11207e00e2 100644 --- a/sys/include/crypto/modes/ccm.h +++ b/sys/include/crypto/modes/ccm.h @@ -40,10 +40,12 @@ extern "C" { * @param nonce_len Length of the nonce in octets * (maximum: 15-length_encoding) * @param input pointer to input data to encrypt - * @param input_len length of the input data, max 2^32 + * @param input_len length of the input data, [0, 2^32] * @param output pointer to allocated memory for encrypted data. It * has to be of size data_len + mac_length. - * @return Length of encrypted data on a successful encryption + * + * @return Length of encrypted data on a successful encryption, + * can be 0 if input_len=0 (no plaintext) * @return A negative error code if something went wrong */ int cipher_encrypt_ccm(cipher_t *cipher, @@ -68,11 +70,12 @@ int cipher_encrypt_ccm(cipher_t *cipher, * @param nonce_len Length of the nonce in octets * (maximum: 15-length_encoding) * @param input pointer to input data to decrypt - * @param input_len length of the input data, max 2^32 + * @param input_len length of the input data, [0, 2^32] * @param output pointer to allocated memory for decrypted data. It * has to be of size data_len - mac_length. * - * @return Length of the decrypted data on a successful decryption + * @return Length of the decrypted data on a successful decryption, + * can be 0 if only auth_data and MAC is present. * @return A negative error code if something went wrong */ int cipher_decrypt_ccm(cipher_t *cipher, From 3b2665e7ad7c217f6f1fe282a8f795c739e3348d Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 9 Apr 2020 12:11:37 +0200 Subject: [PATCH 13/14] fixup! fixup! sys/crypto: add ccms Explicit plaintext length in header --- sys/include/crypto/modes/ccms.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sys/include/crypto/modes/ccms.h b/sys/include/crypto/modes/ccms.h index 992fe7308b92..27f866871ae1 100644 --- a/sys/include/crypto/modes/ccms.h +++ b/sys/include/crypto/modes/ccms.h @@ -39,10 +39,12 @@ extern "C" { * @param nonce_len Length of the nonce in octets * (maximum: 15-length_encoding) * @param input pointer to input data to encrypt - * @param input_len length of the input data, max 2^32 + * @param input_len length of the input data, [0, 2^32] * @param output pointer to allocated memory for encrypted data. It * has to be of size data_len + mac_length. - * @return Length of encrypted data on a successful encryption + * + * @return Length of encrypted data on a successful encryption, + * can be 0 if input_len=0 (no plaintext) * @return A negative error code if something went wrong */ int cipher_encrypt_ccms(cipher_t *cipher, @@ -67,11 +69,12 @@ int cipher_encrypt_ccms(cipher_t *cipher, * @param nonce_len Length of the nonce in octets * (maximum: 15-length_encoding) * @param input pointer to input data to decrypt - * @param input_len length of the input data, max 2^32 + * @param input_len length of the input data, [0, 2^32] * @param output pointer to allocated memory for decrypted data. It * has to be of size data_len - mac_length. * - * @return Length of the decrypted data on a successful decryption + * @return Length of the decrypted data on a successful decryption, + * can be 0 if only auth_data and MAC is present. * @return A negative error code if something went wrong */ int cipher_decrypt_ccms(cipher_t *cipher, From 7978ef5d10a9c4b24be145a5fce2c83ee488893c Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 9 Apr 2020 12:39:32 +0200 Subject: [PATCH 14/14] fixup! fixup! fixup! sys/crypto: add ccms Add implemenation disclaimer. --- sys/include/crypto/modes/ccms.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sys/include/crypto/modes/ccms.h b/sys/include/crypto/modes/ccms.h index 27f866871ae1..b09a00be968d 100644 --- a/sys/include/crypto/modes/ccms.h +++ b/sys/include/crypto/modes/ccms.h @@ -13,6 +13,19 @@ * @file ccms.h * @brief Counter with CCM* mode of operation for block ciphers * + * CCM* coincides with CCM for messages that require authentication and possibly + * encryption, but it also support messages only requiring encryption. This is + * advantageuos in cases where you would want a single mechanism to provide for + * confidentiality and authenticity. + * + * CCM* also specifices that the nonce shall encode the potential values for M + * in a way that one could uniquely determine M from the nonce N. But, it does + * not specify how this encoding should be implemented, and leaves this to the + * application. This is currently not implemented. + * + * @note Allthough CCM* support only encrypting data, it is not recommended + * if only generic encryption is needed. + * * @author Francisco Molina */