1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/tests/sys_crypto/tests-crypto-modes-ocb.c
2019-10-08 20:58:52 +02:00

446 lines
14 KiB
C

/*
* Copyright (C) 2018 Mathias Tausig
*
* 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 "crypto/ciphers.h"
#include "crypto/modes/ocb.h"
#include "tests-crypto.h"
/* Test vectors from RFC 7253, Appendix A */
/* The key (K) has a fixed value, the tag length is
128 bits, and the nonce (N) increments.
K : 000102030405060708090A0B0C0D0E0F
*/
static uint8_t TEST_KEY[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
static uint8_t TEST_KEY_LEN = 16;
/* Test 1:
N: BBAA99887766554433221100
A:
P:
C: 785407BFFFC8AD9EDCC5520AC9111EE6
*/
static uint8_t *TEST_1_KEY = TEST_KEY;
static uint8_t TEST_1_NONCE[] = {
0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44,
0x33, 0x22, 0x11, 0x00,
};
static size_t TEST_1_NONCE_LEN = 12;
static uint8_t *TEST_1_INPUT;
static size_t TEST_1_INPUT_LEN = 0;
static uint8_t *TEST_1_ADATA;
static size_t TEST_1_ADATA_LEN = 0;
static uint8_t TEST_1_EXPECTED[] = {
0x78, 0x54, 0x07, 0xBF, 0xFF, 0xC8, 0xAD, 0x9E,
0xDC, 0xC5, 0x52, 0x0A, 0xC9, 0x11, 0x1E, 0xE6
};
static size_t TEST_1_EXPECTED_LEN = 16;
static uint8_t TEST_1_TAG_LEN = 16;
/* Test 2:
N: BBAA99887766554433221101
A: 0001020304050607
P: 0001020304050607
C: 6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009
*/
static uint8_t *TEST_2_KEY = TEST_KEY;
static uint8_t TEST_2_NONCE[] = {
0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44,
0x33, 0x22, 0x11, 0x01,
};
static size_t TEST_2_NONCE_LEN = 12;
static uint8_t TEST_2_INPUT[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
static size_t TEST_2_INPUT_LEN = sizeof(TEST_2_INPUT);
static uint8_t TEST_2_ADATA[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
static size_t TEST_2_ADATA_LEN = sizeof(TEST_2_ADATA);
static uint8_t TEST_2_EXPECTED[] = {
0x68, 0x20, 0xB3, 0x65, 0x7B, 0x6F, 0x61, 0x5A,
0x57, 0x25, 0xBD, 0xA0, 0xD3, 0xB4, 0xEB, 0x3A,
0x25, 0x7C, 0x9A, 0xF1, 0xF8, 0xF0, 0x30, 0x09
};
static size_t TEST_2_EXPECTED_LEN = sizeof(TEST_2_EXPECTED);
static uint8_t TEST_2_TAG_LEN = 16;
/* Test 3:
N: BBAA99887766554433221102
A: 0001020304050607
P:
C: 81017F8203F081277152FADE694A0A00
*/
static uint8_t *TEST_3_KEY = TEST_KEY;
static uint8_t TEST_3_NONCE[] = {
0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44,
0x33, 0x22, 0x11, 0x02,
};
static size_t TEST_3_NONCE_LEN = 12;
static uint8_t *TEST_3_INPUT;
static size_t TEST_3_INPUT_LEN = 0;
static uint8_t TEST_3_ADATA[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
static size_t TEST_3_ADATA_LEN = sizeof(TEST_2_ADATA);
static uint8_t TEST_3_EXPECTED[] = {
0x81, 0x01, 0x7F, 0x82, 0x03, 0xF0, 0x81, 0x27,
0x71, 0x52, 0xFA, 0xDE, 0x69, 0x4A, 0x0A, 0x00
};
static size_t TEST_3_EXPECTED_LEN = sizeof(TEST_3_EXPECTED);
static uint8_t TEST_3_TAG_LEN = 16;
/* Test 4:
N: BBAA99887766554433221103
A:
P: 0001020304050607
C: 45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9
*/
static uint8_t *TEST_4_KEY = TEST_KEY;
static uint8_t TEST_4_NONCE[] = {
0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44,
0x33, 0x22, 0x11, 0x03,
};
static size_t TEST_4_NONCE_LEN = 12;
static uint8_t TEST_4_INPUT[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
static size_t TEST_4_INPUT_LEN = sizeof(TEST_4_INPUT);
static uint8_t *TEST_4_ADATA;
static size_t TEST_4_ADATA_LEN = 0;
static uint8_t TEST_4_EXPECTED[] = {
0x45, 0xDD, 0x69, 0xF8, 0xF5, 0xAA, 0xE7, 0x24,
0x14, 0x05, 0x4C, 0xD1, 0xF3, 0x5D, 0x82, 0x76,
0x0B, 0x2C, 0xD0, 0x0D, 0x2F, 0x99, 0xBF, 0xA9
};
static size_t TEST_4_EXPECTED_LEN = sizeof(TEST_4_EXPECTED);
static uint8_t TEST_4_TAG_LEN = 16;
/* Test 16:
N: BBAA9988776655443322110F
A:
P: 000102030405060708090A0B0C0D0E0F1011121314151617
18191A1B1C1D1E1F2021222324252627
C: 4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15
A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95
A98CA5F3000B1479
*/
static uint8_t *TEST_16_KEY = TEST_KEY;
static uint8_t TEST_16_NONCE[] = {
0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44,
0x33, 0x22, 0x11, 0x0F,
};
static size_t TEST_16_NONCE_LEN = 12;
static uint8_t TEST_16_INPUT[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
};
static size_t TEST_16_INPUT_LEN = sizeof(TEST_16_INPUT);
static uint8_t *TEST_16_ADATA;
static size_t TEST_16_ADATA_LEN = 0;
static uint8_t TEST_16_EXPECTED[] = {
0x44, 0x12, 0x92, 0x34, 0x93, 0xC5, 0x7D, 0x5D,
0xE0, 0xD7, 0x00, 0xF7, 0x53, 0xCC, 0xE0, 0xD1,
0xD2, 0xD9, 0x50, 0x60, 0x12, 0x2E, 0x9F, 0x15,
0xA5, 0xDD, 0xBF, 0xC5, 0x78, 0x7E, 0x50, 0xB5,
0xCC, 0x55, 0xEE, 0x50, 0x7B, 0xCB, 0x08, 0x4E,
0x47, 0x9A, 0xD3, 0x63, 0xAC, 0x36, 0x6B, 0x95,
0xA9, 0x8C, 0xA5, 0xF3, 0x00, 0x0B, 0x14, 0x79
};
static size_t TEST_16_EXPECTED_LEN = sizeof(TEST_16_EXPECTED);
static uint8_t TEST_16_TAG_LEN = 16;
/* Test 17:
The next tuple shows a result with a tag length of 96 bits and a
different key.
K: 0F0E0D0C0B0A09080706050403020100
N: BBAA9988776655443322110D
A: 000102030405060708090A0B0C0D0E0F1011121314151617
18191A1B1C1D1E1F2021222324252627
P: 000102030405060708090A0B0C0D0E0F1011121314151617
18191A1B1C1D1E1F2021222324252627
C: 1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1
A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD
AC4F02AA
*/
static uint8_t TEST_17_KEY[] = {
0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
};
static uint8_t TEST_17_NONCE[] = {
0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44,
0x33, 0x22, 0x11, 0x0D,
};
static size_t TEST_17_NONCE_LEN = 12;
static uint8_t TEST_17_INPUT[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
};
static size_t TEST_17_INPUT_LEN = sizeof(TEST_17_INPUT);
static uint8_t TEST_17_ADATA[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
};
static size_t TEST_17_ADATA_LEN = sizeof(TEST_17_ADATA);
static uint8_t TEST_17_EXPECTED[] = {
0x17, 0x92, 0xA4, 0xE3, 0x1E, 0x07, 0x55, 0xFB,
0x03, 0xE3, 0x1B, 0x22, 0x11, 0x6E, 0x6C, 0x2D,
0xDF, 0x9E, 0xFD, 0x6E, 0x33, 0xD5, 0x36, 0xF1,
0xA0, 0x12, 0x4B, 0x0A, 0x55, 0xBA, 0xE8, 0x84,
0xED, 0x93, 0x48, 0x15, 0x29, 0xC7, 0x6B, 0x6A,
0xD0, 0xC5, 0x15, 0xF4, 0xD1, 0xCD, 0xD4, 0xFD,
0xAC, 0x4F, 0x02, 0xAA
};
static size_t TEST_17_EXPECTED_LEN = sizeof(TEST_17_EXPECTED);
static uint8_t TEST_17_TAG_LEN = 12;
/* Share test buffer output */
static uint8_t data[60];
static void test_encrypt_op(uint8_t *key, uint8_t key_len,
uint8_t *adata, size_t adata_len,
uint8_t *nonce, uint8_t nonce_len,
uint8_t *plain, size_t plain_len,
uint8_t *output_expected,
size_t output_expected_len,
uint8_t tag_length)
{
cipher_t cipher;
int len, err, cmp;
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_ocb(&cipher, adata, adata_len,
tag_length, 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");
}
#define do_test_encrypt_op(name) do { \
test_encrypt_op(TEST_ ## name ## _KEY, TEST_KEY_LEN, \
TEST_ ## name ## _ADATA, TEST_ ## name ## _ADATA_LEN, \
TEST_ ## name ## _NONCE, TEST_ ## name ## _NONCE_LEN, \
\
TEST_ ## name ## _INPUT, TEST_ ## name ## _INPUT_LEN, \
\
TEST_ ## name ## _EXPECTED, \
TEST_ ## name ## _EXPECTED_LEN, TEST_ ## name ## _TAG_LEN \
); \
} while (0)
static void test_crypto_modes_ocb_encrypt(void)
{
do_test_encrypt_op(1);
do_test_encrypt_op(2);
do_test_encrypt_op(3);
do_test_encrypt_op(4);
do_test_encrypt_op(16);
do_test_encrypt_op(17);
}
static void test_decrypt_op(uint8_t *key, uint8_t key_len,
uint8_t *adata, size_t adata_len,
uint8_t *nonce, uint8_t nonce_len,
uint8_t *encrypted, size_t encrypted_len,
uint8_t *output_expected,
size_t output_expected_len,
uint8_t tag_length)
{
cipher_t cipher;
int len, err, cmp;
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_ocb(&cipher, adata, adata_len,
tag_length, 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");
/* do some negative tests for the tag verification */
if (adata_len > 0) {
/* Drop one byte of auth data */
len = cipher_decrypt_ocb(&cipher, adata, adata_len - 1,
tag_length, nonce, nonce_len,
encrypted, encrypted_len, data);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_TAG, len);
/* Alter one byte of auth data */
adata[0] = adata[0] ^ 0x01;
len = cipher_decrypt_ocb(&cipher, adata, adata_len,
tag_length, nonce, nonce_len,
encrypted, encrypted_len, data);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_TAG, len);
adata[0] = adata[0] ^ 0x01;
}
/* Drop one byte of the nonce */
len = cipher_decrypt_ocb(&cipher, adata, adata_len,
tag_length, nonce, nonce_len - 1,
encrypted, encrypted_len, data);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_TAG, len);
/* Alter one byte of the nonce */
nonce[0] = nonce[0] ^ 0x01;
len = cipher_decrypt_ocb(&cipher, adata, adata_len,
tag_length, nonce, nonce_len,
encrypted, encrypted_len, data);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_TAG, len);
nonce[0] = nonce[0] ^ 0x01;
/* Alter one byte of the ciphertext */
encrypted[0] = encrypted[0] ^ 0x01;
len = cipher_decrypt_ocb(&cipher, adata, adata_len,
tag_length, nonce, nonce_len,
encrypted, encrypted_len, data);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_TAG, len);
encrypted[0] = encrypted[0] ^ 0x01;
/* Alter one byte of the tag */
encrypted[encrypted_len - 1] = encrypted[encrypted_len - 1] ^ 0x01;
len = cipher_decrypt_ocb(&cipher, adata, adata_len,
tag_length, nonce, nonce_len,
encrypted, encrypted_len, data);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_TAG, len);
encrypted[encrypted_len - 1] = encrypted[encrypted_len - 1] ^ 0x01;
}
#define do_test_decrypt_op(name) do { \
test_decrypt_op(TEST_ ## name ## _KEY, TEST_KEY_LEN, \
TEST_ ## name ## _ADATA, TEST_ ## name ## _ADATA_LEN, \
TEST_ ## name ## _NONCE, TEST_ ## name ## _NONCE_LEN, \
\
TEST_ ## name ## _EXPECTED, \
TEST_ ## name ## _EXPECTED_LEN, \
\
TEST_ ## name ## _INPUT, \
TEST_ ## name ## _INPUT_LEN, \
\
TEST_ ## name ## _TAG_LEN \
); \
} while (0)
static void test_crypto_modes_ocb_decrypt(void)
{
do_test_decrypt_op(1);
do_test_decrypt_op(2);
do_test_decrypt_op(3);
do_test_decrypt_op(4);
do_test_decrypt_op(16);
do_test_decrypt_op(17);
}
static void test_crypto_modes_ocb_bad_parameter_values(void)
{
uint8_t key[16], auth_data[1], nonce[16], input[16], output[32];
cipher_t cipher;
cipher_init(&cipher, CIPHER_AES_128, key, 16);
/* tag length must be positive */
int rv = cipher_encrypt_ocb(&cipher, auth_data, sizeof(auth_data), 0, nonce,
15, input, sizeof(input), output);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_TAG_LENGTH, rv);
/* tag length must be <= 16 */
rv = cipher_encrypt_ocb(&cipher, auth_data, sizeof(auth_data), 17, nonce,
15, input, sizeof(input), output);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_TAG_LENGTH, rv);
/* nonce must not be empty */
rv = cipher_encrypt_ocb(&cipher, auth_data, sizeof(auth_data), 16, nonce, 0,
input, sizeof(input), output);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_NONCE_LENGTH, rv);
/* nonce must be <=15 */
rv = cipher_encrypt_ocb(&cipher, auth_data, sizeof(auth_data), 16, nonce,
16, input, sizeof(input), output);
TEST_ASSERT_EQUAL_INT(OCB_ERR_INVALID_NONCE_LENGTH, rv);
}
Test *tests_crypto_modes_ocb_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(test_crypto_modes_ocb_encrypt),
new_TestFixture(test_crypto_modes_ocb_decrypt),
new_TestFixture(test_crypto_modes_ocb_bad_parameter_values),
};
EMB_UNIT_TESTCALLER(crypto_modes_ocb_tests, NULL, NULL, fixtures);
return (Test *)&crypto_modes_ocb_tests;
}