/*
 * Embedded Linux library
 * Copyright (C) 2015  Intel Corporation
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <assert.h>
#include <alloca.h>
#include <stdio.h>

#include <ell/ell.h>

#include "ell/useful.h"

#define FIXED_STR  "The quick brown fox jumps over the lazy dog. " \
		   "Jackdaws love my big sphinx of quartz. "       \
		   "Pack my box with five dozen liquor jugs. "     \
		   "How razorback-jumping frogs can level six piqued gymnasts!"
#define FIXED_LEN  (strlen(FIXED_STR))

#define KEY_STR "This key has exactly _32_ bytes!"
#define KEY_LEN (strlen(KEY_STR))

static void test_unsupported(const void *data)
{
	struct l_cipher *cipher;

	cipher = l_cipher_new(42, KEY_STR, KEY_LEN);
	assert(!cipher);
}

static bool aes_precheck(const void *data)
{
	return l_cipher_is_supported(L_CIPHER_AES);
}

static void test_aes(const void *data)
{
	struct l_cipher *cipher;
	char buf[256];
	size_t real_len;
	int r;

	cipher = l_cipher_new(L_CIPHER_AES, KEY_STR, KEY_LEN);
	assert(cipher);

	memcpy(buf, FIXED_STR, FIXED_LEN);
	/* AES is a block cipher, so pad out to next 16-byte boundary */
	real_len = align_len(FIXED_LEN, 16);
	memset(buf + FIXED_LEN, 0, real_len - FIXED_LEN);

	assert(l_cipher_encrypt(cipher, buf, buf, real_len));

	r = memcmp(buf, FIXED_STR, FIXED_LEN);
	assert(r);

	assert(l_cipher_decrypt(cipher, buf, buf, real_len));

	r = memcmp(buf, FIXED_STR, FIXED_LEN);
	assert(!r);

	l_cipher_free(cipher);
}

static bool aes_ctr_precheck(const void *data)
{
	return l_cipher_is_supported(L_CIPHER_AES_CTR);
}

static void test_aes_ctr(const void *data)
{
	struct l_cipher *cipher;
	uint8_t iv[16] = { 0 };
	char buf[256];
	int r;

	cipher = l_cipher_new(L_CIPHER_AES_CTR, KEY_STR, KEY_LEN);
	assert(cipher);

	assert(l_cipher_set_iv(cipher, iv, sizeof(iv)));

	memcpy(buf, FIXED_STR, FIXED_LEN);
	assert(l_cipher_encrypt(cipher, buf, buf, FIXED_LEN));

	r = memcmp(buf, FIXED_STR, FIXED_LEN);
	assert(r);

	assert(l_cipher_set_iv(cipher, iv, sizeof(iv)));
	assert(l_cipher_decrypt(cipher, buf, buf, FIXED_LEN));

	r = memcmp(buf, FIXED_STR, FIXED_LEN);
	assert(!r);

	l_cipher_free(cipher);
}

struct cipher_test {
	enum l_cipher_type type;
	const char *key;
	const char *iv;
	const char *plaintext;
	const char *ciphertext;
};

static const struct cipher_test ecb_aes128_nist = {
	.type		= L_CIPHER_AES,
	.key		= "2B7E151628AED2A6ABF7158809CF4F3C",
	.plaintext	= "6BC1BEE22E409F96E93D7E117393172A"
			  "AE2D8A571E03AC9C9EB76FAC45AF8E51"
			  "30C81C46A35CE411E5FBC1191A0A52EF"
			  "F69F2445DF4F9B17AD2B417BE66C3710",
	.ciphertext	= "3AD77BB40D7A3660A89ECAF32466EF97"
			  "F5D3D58503B9699DE785895A96FDBAAF"
			  "43B1CD7F598ECE23881B00E3ED030688"
			  "7B0C785E27E8AD3F8223207104725DD4",
};

static const struct cipher_test ecb_aes192_nist = {
	.type		= L_CIPHER_AES,
	.key		= "8E73B0F7DA0E6452C810F32B809079E5"
			  "62F8EAD2522C6B7B",
	.plaintext	= "6BC1BEE22E409F96E93D7E117393172A"
			  "AE2D8A571E03AC9C9EB76FAC45AF8E51"
			  "30C81C46A35CE411E5FBC1191A0A52EF"
			  "F69F2445DF4F9B17AD2B417BE66C3710",
	.ciphertext	= "BD334F1D6E45F25FF712A214571FA5CC"
			  "974104846D0AD3AD7734ECB3ECEE4EEF"
			  "EF7AFD2270E2E60ADCE0BA2FACE6444E"
			  "9A4B41BA738D6C72FB16691603C18E0E",
};

static const struct cipher_test ecb_aes256_nist = {
	.type		= L_CIPHER_AES,
	.key		= "603DEB1015CA71BE2B73AEF0857D7781"
			  "1F352C073B6108D72D9810A30914DFF4",
	.plaintext	= "6BC1BEE22E409F96E93D7E117393172A"
			  "AE2D8A571E03AC9C9EB76FAC45AF8E51"
			  "30C81C46A35CE411E5FBC1191A0A52EF"
			  "F69F2445DF4F9B17AD2B417BE66C3710",
	.ciphertext	= "F3EED1BDB5D2A03C064B5A7E3DB181F8"
			  "591CCB10D410ED26DC5BA74A31362870"
			  "B6ED21B99CA6F4F9F153E7B1BEAFED1D"
			  "23304B7A39F9F3FF067D8D8F9E24ECC7",
};

static const struct cipher_test cbc_aes128_nist = {
	.type		= L_CIPHER_AES_CBC,
	.key		= "2B7E151628AED2A6ABF7158809CF4F3C",
	.iv		= "000102030405060708090A0B0C0D0E0F",
	.plaintext	= "6BC1BEE22E409F96E93D7E117393172A"
			  "AE2D8A571E03AC9C9EB76FAC45AF8E51"
			  "30C81C46A35CE411E5FBC1191A0A52EF"
			  "F69F2445DF4F9B17AD2B417BE66C3710",
	.ciphertext	= "7649ABAC8119B246CEE98E9B12E9197D"
			  "5086CB9B507219EE95DB113A917678B2"
			  "73BED6B8E3C1743B7116E69E22229516"
			  "3FF1CAA1681FAC09120ECA307586E1A7",
};

static const struct cipher_test cbc_aes192_nist = {
	.type		= L_CIPHER_AES_CBC,
	.key		= "8E73B0F7DA0E6452C810F32B809079E5"
			  "62F8EAD2522C6B7B",
	.iv		= "000102030405060708090A0B0C0D0E0F",
	.plaintext	= "6BC1BEE22E409F96E93D7E117393172A"
			  "AE2D8A571E03AC9C9EB76FAC45AF8E51"
			  "30C81C46A35CE411E5FBC1191A0A52EF"
			  "F69F2445DF4F9B17AD2B417BE66C3710",
	.ciphertext	= "4F021DB243BC633D7178183A9FA071E8"
			  "B4D9ADA9AD7DEDF4E5E738763F69145A"
			  "571B242012FB7AE07FA9BAAC3DF102E0"
			  "08B0E27988598881D920A9E64F5615CD",
};

static const struct cipher_test cbc_aes256_nist = {
	.type		= L_CIPHER_AES_CBC,
	.key		= "603DEB1015CA71BE2B73AEF0857D7781"
			  "1F352C073B6108D72D9810A30914DFF4",
	.iv		= "000102030405060708090A0B0C0D0E0F",
	.plaintext	= "6BC1BEE22E409F96E93D7E117393172A"
			  "AE2D8A571E03AC9C9EB76FAC45AF8E51"
			  "30C81C46A35CE411E5FBC1191A0A52EF"
			  "F69F2445DF4F9B17AD2B417BE66C3710",
	.ciphertext	= "F58C4C04D6E5F1BA779EABFB5F7BFBD6"
			  "9CFC4E967EDB808D679F777BC6702C7D"
			  "39F23369A9D9BACFA530E26304231461"
			  "B2EB05E2C39BE9FCDA6C19078C6A9D1B",
};

static const struct cipher_test ctr_aes128_nist = {
	.type		= L_CIPHER_AES_CTR,
	.key		= "2B7E151628AED2A6ABF7158809CF4F3C",
	.iv		= "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF",
	.plaintext	= "6BC1BEE22E409F96E93D7E117393172A"
			  "AE2D8A571E03AC9C9EB76FAC45AF8E51"
			  "30C81C46A35CE411E5FBC1191A0A52EF"
			  "F69F2445DF4F9B17AD2B417BE66C3710",
	.ciphertext	= "874D6191B620E3261BEF6864990DB6CE"
			  "9806F66B7970FDFF8617187BB9FFFDFF"
			  "5AE4DF3EDBD5D35E5B4F09020DB03EAB"
			  "1E031DDA2FBE03D1792170A0F3009CEE",
};

static const struct cipher_test ctr_aes192_nist = {
	.type		= L_CIPHER_AES_CTR,
	.key		= "8E73B0F7DA0E6452C810F32B809079E5"
			  "62F8EAD2522C6B7B",
	.iv		= "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF",
	.plaintext	= "6BC1BEE22E409F96E93D7E117393172A"
			  "AE2D8A571E03AC9C9EB76FAC45AF8E51"
			  "30C81C46A35CE411E5FBC1191A0A52EF"
			  "F69F2445DF4F9B17AD2B417BE66C3710",
	.ciphertext	= "1ABC932417521CA24F2B0459FE7E6E0B"
			  "090339EC0AA6FAEFD5CCC2C6F4CE8E94"
			  "1E36B26BD1EBC670D1BD1D665620ABF7"
			  "4F78A7F6D29809585A97DAEC58C6B050",
};

static const struct cipher_test ctr_aes256_nist = {
	.type		= L_CIPHER_AES_CTR,
	.key		= "603DEB1015CA71BE2B73AEF0857D7781"
			  "1F352C073B6108D72D9810A30914DFF4",
	.iv		= "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF",
	.plaintext	= "6BC1BEE22E409F96E93D7E117393172A"
			  "AE2D8A571E03AC9C9EB76FAC45AF8E51"
			  "30C81C46A35CE411E5FBC1191A0A52EF"
			  "F69F2445DF4F9B17AD2B417BE66C3710",
	.ciphertext	= "601EC313775789A5B7A7F504BBF3D228"
			  "F443E3CA4D62B59ACA84E990CACAF5C5"
			  "2B0930DAA23DE94CE87017BA2D84988D"
			  "DFC9C58DB67AADA613C2DD08457941A6",
};

static bool cipher_precheck(const void *data)
{
	const struct cipher_test *test = data;

	return l_cipher_is_supported(test->type);
}

static void test_encrypt(const void *data)
{
	const struct cipher_test *test = data;
	unsigned char *key;
	size_t key_len;
	struct l_cipher *cipher;
	unsigned char *plaintext;
	size_t plaintext_len;
	unsigned char *ciphertext;
	unsigned char *expected;
	size_t expected_len;
	bool result;

	key = l_util_from_hexstring(test->key, &key_len);
	assert(key);

	cipher = l_cipher_new(test->type, key, key_len);
	assert(cipher);

	if (test->iv) {
		unsigned char *iv;
		size_t iv_len;

		iv = l_util_from_hexstring(test->iv, &iv_len);
		assert(iv);

		result = l_cipher_set_iv(cipher, iv, iv_len);
		assert(result);

		l_free(iv);
	}

	plaintext = l_util_from_hexstring(test->plaintext, &plaintext_len);
	assert(plaintext);

	ciphertext = l_malloc(plaintext_len);

	result = l_cipher_encrypt(cipher, plaintext, ciphertext, plaintext_len);
	assert(result);

	expected = l_util_from_hexstring(test->ciphertext, &expected_len);
	assert(expected);
	assert(expected_len == plaintext_len);
	assert(!memcmp(ciphertext, expected, expected_len));

	l_free(expected);
	l_free(ciphertext);
	l_free(plaintext);
	l_cipher_free(cipher);
	l_free(key);
}

static void test_decrypt(const void *data)
{
	const struct cipher_test *test = data;
	unsigned char *key;
	size_t key_len;
	struct l_cipher *cipher;
	unsigned char *ciphertext;
	size_t ciphertext_len;
	unsigned char *plaintext;
	unsigned char *expected;
	size_t expected_len;
	bool result;

	key = l_util_from_hexstring(test->key, &key_len);
	assert(key);

	cipher = l_cipher_new(test->type, key, key_len);
	assert(cipher);

	if (test->iv) {
		unsigned char *iv;
		size_t iv_len;

		iv = l_util_from_hexstring(test->iv, &iv_len);
		assert(iv);

		result = l_cipher_set_iv(cipher, iv, iv_len);
		assert(result);

		l_free(iv);
	}

	ciphertext = l_util_from_hexstring(test->ciphertext, &ciphertext_len);
	assert(ciphertext);

	plaintext = l_malloc(ciphertext_len);

	result = l_cipher_decrypt(cipher, ciphertext, plaintext, ciphertext_len);
	assert(result);

	expected = l_util_from_hexstring(test->plaintext, &expected_len);
	assert(expected);
	assert(expected_len == ciphertext_len);
	assert(!memcmp(plaintext, expected, expected_len));

	l_free(expected);
	l_free(plaintext);
	l_free(ciphertext);
	l_cipher_free(cipher);
	l_free(key);
}

struct aead_test_vector {
	enum l_aead_cipher_type type;
	char *aad;
	char *plaintext;
	char *key;
	char *nonce;
	char *ciphertext;
	char *tag;
};

static const struct aead_test_vector ccm_long_nonce = {
	.type = L_AEAD_CIPHER_AES_CCM,
	.aad =
	"333b6b8fda49c6e671bad05c7e2cafa88bd47f9b0aef1a358bc87d04f26f6c82",
	.plaintext =
	"1293201eb30ddd693b2eb23c1e6c20d5add2202afc71679ca2eba14f73b77bcd",
	.key = "fa536cf6c309d45c1baaa658f674758d",
	.nonce = "e0c5241bf0014ca88511d73a30",
	.ciphertext =
	"2e54ebaa38da9a2b03a1147495565c31d07e793b01fd28b2adeacac6f76ae84e",
	.tag = "e0a03b982c5afc8a937373d7d2b0e7a3"
};

static const struct aead_test_vector ccm_short_nonce = {
	.type = L_AEAD_CIPHER_AES_CCM,
	.plaintext =
	"a3b3fdf26d213f83c5f656b00f77253b68959c188767d584914887602c787595",
	.aad =
	"fcc20524894b4603fefb8029eff485a513ce4753d0d3a27c3a2c69088fa7fab7",
	.key = "7d84efac51291e868c7b7702181a3936",
	.nonce = "1bb3e62620462a",
	.ciphertext =
	"3222192ee773cef4a87175b73b3875320f18b7e016d17d52fb01f0f6ca10bb5f",
	.tag = "ee007aafe91135c39855ebf3db96d7ff"
};

static const struct aead_test_vector ccm_no_aad = {
	.type = L_AEAD_CIPHER_AES_CCM,
	.plaintext =
	"90795fffab99cffdeee5cadafe448ea4df74c480f9d7e1e481ee49adeee2732a",
	.key = "7b3da7d5ef41b5eef19cf8fb4ca19519",
	.nonce = "96722de7516afb",
	.ciphertext =
	"9160dd0e0a8ddd13bf4acb0c6f3cf4794c5459d36a378cfb4a31e6b00840d78a",
	.tag = "efd1dc938802cd845a16f32a60eabd0f"
};

/* https://tools.ietf.org/html/draft-mcgrew-gcm-test-01 */

static const struct aead_test_vector gcm_test1 = {
	.type = L_AEAD_CIPHER_AES_GCM,
	.aad = "000043218765432100000000",
	.plaintext =
	"45000048699a000080114db7c0a80102c0a801010a9bf15638d3010000010000"
	"00000000045f736970045f756470037369700963796265726369747902646b00"
	"0021000101020201",
	/* 128-bit key */
	.key = "4c80cdefbb5d10da906ac73c3613a634",
	.nonce = "2e443b684956ed7e3b244cfe",
	.ciphertext =
	"fecf537e729d5b07dc30df528dd22b768d1b98736696a6fd348509fa13ceac34"
	"cfa2436f14a3f3cf65925bf1f4a13c5d15b21e1884f5ff6247aeabb786b93bce"
	"61bc17d768fd9732",
	.tag = "459018148f6cbe722fd04796562dfdb4",
};

static const struct aead_test_vector gcm_test2 = {
	.type = L_AEAD_CIPHER_AES_GCM,
	.aad = "0000a5f80000000a",
	.plaintext =
	"45000028a4ad4000400678800a01038f0a010612802306b8cb712602dd6bb03e"
	"501016d075680001",
	/* 192-bit key */
	.key = "feffe9928665731c6d6a8f9467308308feffe9928665731c",
	.nonce = "cafebabefacedbaddecaf888",
	.ciphertext =
	"a5b1f8066029aea40e598b8122de02420938b3ab33f828e687b8858b5bfbdbd0"
	"315b27452144cc77",
	.tag = "95457b9652037f5318027b5b4cd7a636",
};

static const struct aead_test_vector gcm_test3 = {
	.type = L_AEAD_CIPHER_AES_GCM,
	.aad = "4a2cbfe300000002",
	.plaintext =
	"4500003069a6400080062690c0a801029389155e0a9e008b2dc57ee000000000"
	"7002400020bf0000020405b40101040201020201",
	/* 256-bit key */
	.key =
	"abbccddef00112233445566778899aababbccddef00112233445566778899aab",
	.nonce = "112233440102030405060708",
	.ciphertext =
	"ff425c9b724599df7a3bcd510194e00d6a78107f1b0b1cbf06efae9d65a5d763"
	"748a637985771d347f0545659f14e99def842d8e",
	.tag = "b335f4eecfdbf831824b4c4915956c96",
};

static const struct aead_test_vector gcm_test4 = {
	.type = L_AEAD_CIPHER_AES_GCM,
	.aad = "0000000000000001",
	.plaintext =
	"4500003c99c500008001cb7a40679318010101010800075c0200440061626364"
	"65666768696a6b6c6d6e6f707172737475767761626364656667686901020201",
	.key = "00000000000000000000000000000000",
	.nonce = "000000000000000000000000",
	.ciphertext =
	"4688daf2f973a392732909c331d56d60f694abaa414b5e7ff5fdcdfff5e9a284"
	"456476492719ffb64de7d9dca1e1d894bc3bd57873ed4d181d19d4d5c8c18af3",
	.tag = "f821d496eeb096e98ad2b69e4799c71d",
};

static const struct aead_test_vector gcm_test5 = {
	.type = L_AEAD_CIPHER_AES_GCM,
	.aad = "335467aeffffffff",
	.plaintext = "01020201",
	.key = "7d773d00c144c525ac619d18c84a3f47",
	.nonce = "d966426743457e9182443bc6",
	.ciphertext = "437f866b",
	.tag = "cb3f699fe9b0822bac961c4504bef270",
};

static const struct aead_test_vector gcm_test6 = {
	.type = L_AEAD_CIPHER_AES_GCM,
	.aad =
	"0000432100000007000000000000000045000030da3a00008001df3bc0a80005"
	"c0a800010800c6cd020007006162636465666768696a6b6c6d6e6f7071727374"
	"01020201",
	.key = "4c80cdefbb5d10da906ac73c3613a634",
	.nonce = "22433c640000000000000000",
	.tag = "f2a9a836e155106aa8dcd618e4099aaa",
};

/* RFC 3610 - Packet Vector #1 */
static const struct aead_test_vector rfc3610_ccm_1 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "00000003020100A0A1A2A3A4A5",
	.aad		= "0001020304050607",
	.plaintext	= "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E",
	.ciphertext	= "588C979A61C663D2F066D0C2C0F989806D5F6B61DAC384",
	.tag		= "17E8D12CFDF926E0",
};

/* RFC 3610 - Packet Vector #2 */
static const struct aead_test_vector rfc3610_ccm_2 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "00000004030201A0A1A2A3A4A5",
	.aad		= "0001020304050607",
	.plaintext	= "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
	.ciphertext	= "72C91A36E135F8CF291CA894085C87E3CC15C439C9E43A3B",
	.tag		= "A091D56E10400916",
};

/* RFC 3610 - Packet Vector #3 */
static const struct aead_test_vector rfc3610_ccm_3 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "00000005040302A0A1A2A3A4A5",
	.aad		= "0001020304050607",
	.plaintext	= "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20",
	.ciphertext	= "51B1E5F44A197D1DA46B0F8E2D282AE871E838BB64DA859657",
	.tag		= "4ADAA76FBD9FB0C5",
};

/* RFC 3610 - Packet Vector #4 */
static const struct aead_test_vector rfc3610_ccm_4 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "00000006050403A0A1A2A3A4A5",
	.aad		= "000102030405060708090A0B",
	.plaintext	= "0C0D0E0F101112131415161718191A1B1C1D1E",
	.ciphertext	= "A28C6865939A9A79FAAA5C4C2A9D4A91CDAC8C",
	.tag		= "96C861B9C9E61EF1",
};

/* RFC 3610 - Packet Vector #5 */
static const struct aead_test_vector rfc3610_ccm_5 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "00000007060504A0A1A2A3A4A5",
	.aad		= "000102030405060708090A0B",
	.plaintext	= "0C0D0E0F101112131415161718191A1B1C1D1E1F",
	.ciphertext	= "DCF1FB7B5D9E23FB9D4E131253658AD86EBDCA3E",
	.tag		= "51E83F077D9C2D93",
};

/* RFC 3610 - Packet Vector #6 */
static const struct aead_test_vector rfc3610_ccm_6 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "00000008070605A0A1A2A3A4A5",
	.aad		= "000102030405060708090A0B",
	.plaintext	= "0C0D0E0F101112131415161718191A1B1C1D1E1F20",
	.ciphertext	= "6FC1B011F006568B5171A42D953D469B2570A4BD87",
	.tag		= "405A0443AC91CB94",
};

/* RFC 3610 - Packet Vector #7 */
static const struct aead_test_vector rfc3610_ccm_7 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "00000009080706A0A1A2A3A4A5",
	.aad		= "0001020304050607",
	.plaintext	= "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E",
	.ciphertext	= "0135D1B2C95F41D5D1D4FEC185D166B8094E999DFED96C",
	.tag		= "048C56602C97ACBB7490",
};

/* RFC 3610 - Packet Vector #8 */
static const struct aead_test_vector rfc3610_ccm_8 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "0000000A090807A0A1A2A3A4A5",
	.aad		= "0001020304050607",
	.plaintext	= "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
	.ciphertext	= "7B75399AC0831DD2F0BBD75879A2FD8F6CAE6B6CD9B7DB24",
	.tag		= "C17B4433F434963F34B4",
};

/* RFC 3610 - Packet Vector #9 */
static const struct aead_test_vector rfc3610_ccm_9 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "0000000B0A0908A0A1A2A3A4A5",
	.aad		= "0001020304050607",
	.plaintext	= "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20",
	.ciphertext	= "82531A60CC24945A4B8279181AB5C84DF21CE7F9B73F42E197",
	.tag		= "EA9C07E56B5EB17E5F4E",
};

/* RFC 3610 - Packet Vector #10 */
static const struct aead_test_vector rfc3610_ccm_10 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "0000000C0B0A09A0A1A2A3A4A5",
	.aad		= "000102030405060708090A0B",
	.plaintext	= "0C0D0E0F101112131415161718191A1B1C1D1E",
	.ciphertext	= "07342594157785152B074098330ABB141B947B",
	.tag		= "566AA9406B4D999988DD",
};

/* RFC 3610 - Packet Vector #11 */
static const struct aead_test_vector rfc3610_ccm_11 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "0000000D0C0B0AA0A1A2A3A4A5",
	.aad		= "000102030405060708090A0B",
	.plaintext	= "0C0D0E0F101112131415161718191A1B1C1D1E1F",
	.ciphertext	= "676BB20380B0E301E8AB79590A396DA78B834934",
	.tag		= "F53AA2E9107A8B6C022C",
};

/* RFC 3610 - Packet Vector #12 */
static const struct aead_test_vector rfc3610_ccm_12 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF",
	.nonce		= "0000000E0D0C0BA0A1A2A3A4A5",
	.aad		= "000102030405060708090A0B",
	.plaintext	= "0C0D0E0F101112131415161718191A1B1C1D1E1F20",
	.ciphertext	= "C0FFA0D6F05BDB67F24D43A4338D2AA4BED7B20E43",
	.tag		= "CD1AA31662E7AD65D6DB",
};

/* RFC 3610 - Packet Vector #13 */
static const struct aead_test_vector rfc3610_ccm_13 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "00412B4EA9CDBE3C9696766CFA",
	.aad		= "0BE1A88BACE018B1",
	.plaintext	= "08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C",
	.ciphertext	= "4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8",
	.tag		= "E78CF7CB0CDDD7B3",
};

/* RFC 3610 - Packet Vector #14 */
static const struct aead_test_vector rfc3610_ccm_14 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "0033568EF7B2633C9696766CFA",
	.aad		= "63018F76DC8A1BCB",
	.plaintext	= "9020EA6F91BDD85AFA0039BA4BAFF9BFB79C7028949CD0EC",
	.ciphertext	= "4CCB1E7CA981BEFAA0726C55D378061298C85C92814ABC33",
	.tag		= "C52EE81D7D77C08A",
};

/* RFC 3610 - Packet Vector #15 */
static const struct aead_test_vector rfc3610_ccm_15 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "00103FE41336713C9696766CFA",
	.aad		= "AA6CFA36CAE86B40",
	.plaintext	= "B916E0EACC1C00D7DCEC68EC0B3BBB1A02DE8A2D1AA346132E",
	.ciphertext	= "B1D23A2220DDC0AC900D9AA03C61FCF4A559A4417767089708",
	.tag		= "A776796EDB723506",
};

/* RFC 3610 - Packet Vector #16 */
static const struct aead_test_vector rfc3610_ccm_16 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "00764C63B8058E3C9696766CFA",
	.aad		= "D0D0735C531E1BECF049C244",
	.plaintext	= "12DAAC5630EFA5396F770CE1A66B21F7B2101C",
	.ciphertext	= "14D253C3967B70609B7CBB7C49916028324526",
	.tag		= "9A6F49975BCADEAF",
};

/* RFC 3610 - Packet Vector #17 */
static const struct aead_test_vector rfc3610_ccm_17 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "00F8B678094E3B3C9696766CFA",
	.aad		= "77B60F011C03E1525899BCAE",
	.plaintext	= "E88B6A46C78D63E52EB8C546EFB5DE6F75E9CC0D",
	.ciphertext	= "5545FF1A085EE2EFBF52B2E04BEE1E2336C73E3F",
	.tag		= "762C0C7744FE7E3C",
};

/* RFC 3610 - Packet Vector #18 */
static const struct aead_test_vector rfc3610_ccm_18 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "00D560912D3F703C9696766CFA",
	.aad		= "CD9044D2B71FDB8120EA60C0",
	.plaintext	= "6435ACBAFB11A82E2F071D7CA4A5EBD93A803BA87F",
	.ciphertext	= "009769ECABDF48625594C59251E6035722675E04C8",
	.tag		= "47099E5AE0704551",
};

/* RFC 3610 - Packet Vector #19 */
static const struct aead_test_vector rfc3610_ccm_19 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "0042FFF8F1951C3C9696766CFA",
	.aad		= "D85BC7E69F944FB8",
	.plaintext	= "8A19B950BCF71A018E5E6701C91787659809D67DBEDD18",
	.ciphertext	= "BC218DAA947427B6DB386A99AC1AEF23ADE0B52939CB6A",
	.tag		= "637CF9BEC2408897C6BA",
};

/* RFC 3610 - Packet Vector #20 */
static const struct aead_test_vector rfc3610_ccm_20 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "00920F40E56CDC3C9696766CFA",
	.aad		= "74A0EBC9069F5B37",
	.plaintext	= "1761433C37C5A35FC1F39F406302EB907C6163BE38C98437",
	.ciphertext	= "5810E6FD25874022E80361A478E3E9CF484AB04F447EFFF6",
	.tag		= "F0A477CC2FC9BF548944",
};

/* RFC 3610 - Packet Vector #21 */
static const struct aead_test_vector rfc3610_ccm_21 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "0027CA0C7120BC3C9696766CFA",
	.aad		= "44A3AA3AAE6475CA",
	.plaintext	= "A434A8E58500C6E41530538862D686EA9E81301B5AE4226BFA",
	.ciphertext	= "F2BEED7BC5098E83FEB5B31608F8E29C38819A89C8E776F154",
	.tag		= "4D4151A4ED3A8B87B9CE",
};

/* RFC 3610 - Packet Vector #22 */
static const struct aead_test_vector rfc3610_ccm_22 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "005B8CCBCD9AF83C9696766CFA",
	.aad		= "EC46BB63B02520C33C49FD70",
	.plaintext	= "B96B49E21D621741632875DB7F6C9243D2D7C2",
	.ciphertext	= "31D750A09DA3ED7FDDD49A2032AABF17EC8EBF",
	.tag		= "7D22C8088C666BE5C197",
};

/* RFC 3610 - Packet Vector #23 */
static const struct aead_test_vector rfc3610_ccm_23 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "003EBE94044B9A3C9696766CFA",
	.aad		= "47A65AC78B3D594227E85E71",
	.plaintext	= "E2FCFBB880442C731BF95167C8FFD7895E337076",
	.ciphertext	= "E882F1DBD38CE3EDA7C23F04DD65071EB41342AC",
	.tag		= "DF7E00DCCEC7AE52987D",
};

/* RFC 3610 - Packet Vector #24 */
static const struct aead_test_vector rfc3610_ccm_24 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "D7828D13B2B0BDC325A76236DF93CC6B",
	.nonce		= "008D493B30AE8B3C9696766CFA",
	.aad		= "6E37A6EF546D955D34AB6059",
	.plaintext	= "ABF21C0B02FEB88F856DF4A37381BCE3CC128517D4",
	.ciphertext	= "F32905B88A641B04B9C9FFB58CC390900F3DA12AB1",
	.tag		= "6DCE9E82EFA16DA62059",
};

/* NIST CCM-AES128 - Example #1 */
static const struct aead_test_vector nist_ccm_aes128_1 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F",
	.nonce		= "10111213141516",
	.aad		= "0001020304050607",
	.plaintext	= "20212223",
	.ciphertext	= "7162015B",
	.tag		= "4DAC255D",
};

/* NIST CCM-AES128 - Example #2 */
static const struct aead_test_vector nist_ccm_aes128_2 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F",
	.nonce		= "1011121314151617",
	.aad		= "000102030405060708090A0B0C0D0E0F",
	.plaintext	= "202122232425262728292A2B2C2D2E2F",
	.ciphertext	= "D2A1F0E051EA5F62081A7792073D593D",
	.tag		= "1FC64FBFACCD",
};

/* NIST CCM-AES128 - Example #3 */
static const struct aead_test_vector nist_ccm_aes128_3 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F",
	.nonce		= "101112131415161718191A1B",
	.aad		= "000102030405060708090A0B0C0D0E0F"
			  "10111213",
	.plaintext	= "202122232425262728292A2B2C2D2E2F"
			  "3031323334353637",
	.ciphertext	= "E3B201A9F5B71A7A9B1CEAECCD97E70B"
			  "6176AAD9A4428AA5",
	.tag		= "484392FBC1B09951",
};

/* NIST CCM-AES128 - Example #4 */
static const struct aead_test_vector nist_ccm_aes128_4 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F",
	.nonce		= "10111213141516",
	.plaintext	= "202122232425262728292A2B2C2D2E2F"
			  "303132333435363738393A3B3C3D3E3F"
			  "404142434445464748494A4B4C4D4E4F"
			  "505152535455565758595A5B5C5D5E5F",
	.ciphertext	= "7162015BC051951E5918AEAF3C11F3D4"
			  "AC363F8D5B6AF3D369603B04F24CAE29"
			  "964E2F2BF9D31143F72527CE2DB402EA"
			  "B7660E4A10B08E82266517CDF60267F9",
	.tag		= "C66B655C",
};

/* NIST CCM-AES128 - Example #5 */
static const struct aead_test_vector nist_ccm_aes128_5 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F",
	.nonce		= "10111213141516",
	.aad		= "000102030405060708090A0B0C0D0E0F"
			  "101112131415161718191A1B1C1D1E1F"
			  "202122232425262728292A2B2C2D2E2F"
			  "303132333435363738393A3B3C3D3E3F",
	.tag		= "E84023F8",
};

/* NIST CCM-AES192 - Example #1 */
static const struct aead_test_vector nist_ccm_aes192_1 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "5051525354555657",
	.nonce		= "10111213141516",
	.aad		= "0001020304050607",
	.plaintext	= "20212223",
	.ciphertext	= "18EE1730",
	.tag		= "C8C326D5",
};

/* NIST CCM-AES192 - Example #2 */
static const struct aead_test_vector nist_ccm_aes192_2 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "5051525354555657",
	.nonce		= "1011121314151617",
	.aad		= "000102030405060708090A0B0C0D0E0F",
	.plaintext	= "202122232425262728292A2B2C2D2E2F",
	.ciphertext	= "2232B6E0924148AE7239BCBD1A0F7ECB",
	.tag		= "56E9CC28AA67",
};

/* NIST CCM-AES192 - Example #3 */
static const struct aead_test_vector nist_ccm_aes192_3 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "5051525354555657",
	.nonce		= "101112131415161718191A1B",
	.aad		= "000102030405060708090A0B0C0D0E0F"
			  "10111213",
	.plaintext	= "202122232425262728292A2B2C2D2E2F"
			  "3031323334353637",
	.ciphertext	= "8081316FD89624D62CE7637FB94995B6"
			  "631C50D61586DE01",
	.tag		= "42366952505F995A",
};

/* NIST CCM-AES192 - Example #4 */
static const struct aead_test_vector nist_ccm_aes192_4 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "5051525354555657",
	.nonce		= "10111213141516",
	.plaintext	= "202122232425262728292A2B2C2D2E2F"
			  "303132333435363738393A3B3C3D3E3F"
			  "404142434445464748494A4B4C4D4E4F"
			  "505152535455565758595A5B5C5D5E5F",
	.ciphertext	= "18EE1730F4490EA847A8E9C532C69F9C"
			  "0A539A585C1E7B6A5AF919F4819088A9"
			  "6ED632555098D3007E7D963C7BD013EB"
			  "307671D0FBC39A0DF4A26A9F4B9E4DAD",
	.tag		= "C9CE2FBC",
};

/* NIST CCM-AES192 - Example #5 */
static const struct aead_test_vector nist_ccm_aes192_5 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "5051525354555657",
	.nonce		= "10111213141516",
	.aad		= "000102030405060708090A0B0C0D0E0F"
			  "101112131415161718191A1B1C1D1E1F"
			  "202122232425262728292A2B2C2D2E2F"
			  "303132333435363738393A3B3C3D3E3F",
	.tag		= "F1FB2A57",
};

/* NIST CCM-AES256 - Example #1 */
static const struct aead_test_vector nist_ccm_aes256_1 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "505152535455565758595A5B5C5D5E5F",
	.nonce		= "10111213141516",
	.aad		= "0001020304050607",
	.plaintext	= "20212223",
	.ciphertext	= "8AB1A874",
	.tag		= "95FC0820",
};

/* NIST CCM-AES256 - Example #2 */
static const struct aead_test_vector nist_ccm_aes256_2 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "505152535455565758595A5B5C5D5E5F",
	.nonce		= "1011121314151617",
	.aad		= "000102030405060708090A0B0C0D0E0F",
	.plaintext	= "202122232425262728292A2B2C2D2E2F",
	.ciphertext	= "AF1785FC0F5EA7D0CFBA837246484497",
	.tag		= "94B826C8849E",
};

/* NIST CCM-AES256 - Example #3 */
static const struct aead_test_vector nist_ccm_aes256_3 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "505152535455565758595A5B5C5D5E5F",
	.nonce		= "101112131415161718191A1B",
	.aad		= "000102030405060708090A0B0C0D0E0F"
			  "10111213",
	.plaintext	= "202122232425262728292A2B2C2D2E2F"
			  "3031323334353637",
	.ciphertext	= "04F883AEB3BD0730EAF50BB6DE4FA221"
			  "2034E4E41B0E75E5",
	.tag		= "2B48C8766F7E7649",
};

/* NIST CCM-AES256 - Example #4 */
static const struct aead_test_vector nist_ccm_aes256_4 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "505152535455565758595A5B5C5D5E5F",
	.nonce		= "10111213141516",
	.plaintext	= "202122232425262728292A2B2C2D2E2F"
			  "303132333435363738393A3B3C3D3E3F"
			  "404142434445464748494A4B4C4D4E4F"
			  "505152535455565758595A5B5C5D5E5F",
	.ciphertext	= "8AB1A874F6853F2443A59500F78D1727"
			  "2D6D39DFA6D0E65107B10700C2CE9EE8"
			  "663D3E2A01C2E12C32E9377442231920"
			  "BE53278F4F60A972B709BB16932936BA",
	.tag		= "3FBD0FAE",
};

/* NIST CCM-AES256 - Example #5 */
static const struct aead_test_vector nist_ccm_aes256_5 = {
	.type		= L_AEAD_CIPHER_AES_CCM,
	.key		= "404142434445464748494A4B4C4D4E4F"
			  "505152535455565758595A5B5C5D5E5F",
	.nonce		= "10111213141516",
	.aad		= "000102030405060708090A0B0C0D0E0F"
			  "101112131415161718191A1B1C1D1E1F"
			  "202122232425262728292A2B2C2D2E2F"
			  "303132333435363738393A3B3C3D3E3F",
	.tag		= "A6CF8230",
};

static bool aead_cipher_precheck(const void *data)
{
	const struct aead_test_vector *tv = data;

	return l_aead_cipher_is_supported(tv->type);
}

static void test_aead(const void *data)
{
	const struct aead_test_vector *tv = data;
	struct l_aead_cipher *cipher;
	char *encbuf;
	size_t encbuflen;
	char *decbuf;
	size_t decbuflen;
	int r;
	bool success;

	size_t ptlen = 0;
	uint8_t *pt = NULL;
	size_t aadlen = 0;
	uint8_t *aad = NULL;
	size_t keylen;
	uint8_t *key = l_util_from_hexstring(tv->key, &keylen);
	size_t noncelen;
	uint8_t *nonce = l_util_from_hexstring(tv->nonce, &noncelen);
	size_t ctlen = 0;
	uint8_t *ct = NULL;
	size_t taglen;
	uint8_t *tag = l_util_from_hexstring(tv->tag, &taglen);

	if (tv->plaintext) {
		pt = l_util_from_hexstring(tv->plaintext, &ptlen);
		assert(pt);
	}

	if (tv->ciphertext) {
		ct = l_util_from_hexstring(tv->ciphertext, &ctlen);
		assert(ct);
	}

	if (tv->aad) {
		aad = l_util_from_hexstring(tv->aad, &aadlen);
		assert(aad);
	}

	assert(key);
	assert(nonce);
	assert(tag);

	decbuflen = ptlen;
	decbuf = alloca(decbuflen);
	memset(decbuf, 0, decbuflen);

	encbuflen = ctlen + taglen;
	encbuf = alloca(encbuflen);
	memset(encbuf, 0, encbuflen);

	cipher = l_aead_cipher_new(tv->type, key, keylen, taglen);
	assert(cipher);

	success = l_aead_cipher_encrypt(cipher, pt, ptlen, aad, aadlen,
					nonce, noncelen, encbuf, encbuflen);
	if (!success) {
		printf("# Some kernel versions before v4.9 have a known AEAD\n"
			"# bug. If the system running this test is using a\n"
			"# v4.8 or earlier kernel, a failure here is likely\n"
			"# due to that kernel bug.\n");
	}
	assert(success);

	assert(memcmp(encbuf, ct, ctlen) == 0);
	assert(memcmp(encbuf + ctlen, tag, taglen) == 0);

	success = l_aead_cipher_decrypt(cipher, encbuf, encbuflen, aad, aadlen,
					nonce, noncelen, decbuf, decbuflen);
	assert (success);

	r = memcmp(decbuf, pt, ptlen);
	assert(!r);

	l_aead_cipher_free(cipher);

	if (tv->plaintext)
		l_free(pt);

	l_free(key);
	l_free(aad);
	l_free(nonce);

	if (tv->ciphertext)
		l_free(ct);

	l_free(tag);
}

/* https://en.wikipedia.org/wiki/RC4 */
static const struct cipher_test arc4_test1 = {
	.type		= L_CIPHER_ARC4,
	.key		= "4B6579",			/* "Key" */
	.plaintext	= "506C61696E74657874",		/* "Plaintext" */
	.ciphertext	= "BBF316E8D940AF0AD3",
};

static const struct cipher_test arc4_test2 = {
	.type		= L_CIPHER_ARC4,
	.key		= "57696B69",			/* "Wiki" */
	.plaintext	= "7065646961",			/* "pedia" */
	.ciphertext	= "1021BF0420",
};

static const struct cipher_test arc4_test3 = {
	.type		= L_CIPHER_ARC4,
	.key		= "536563726574",		   /* "Secret" */
	.plaintext	= "41747461636B206174206461776E",  /* "Attack at .." */
	.ciphertext	= "45A01F645FC35B383552544B9BF5",
};

/* RFC2268 Section 5 (where Effective key length == 8 * Key length) */
static const struct cipher_test rc2_test1 = {
	.type		= L_CIPHER_RC2_CBC,
	.key		= "ffffffffffffffff",
	.plaintext	= "ffffffffffffffff",
	.ciphertext	= "278b27e42e2f0d49",
};

static const struct cipher_test rc2_test2 = {
	.type		= L_CIPHER_RC2_CBC,
	.key		= "3000000000000000",
	.plaintext	= "1000000000000001",
	.ciphertext	= "30649edf9be7d2c2",
};

static const struct cipher_test rc2_test3 = {
	.type		= L_CIPHER_RC2_CBC,
	.key		= "88bca90e90875a7f0f79c384627bafb2",
	.plaintext	= "0000000000000000",
	.ciphertext	= "2269552ab0f85ca6",
};

static const struct cipher_test des_test1 = {
	.type		= L_CIPHER_DES,
	.key		= "0E329232EA6D0D73",
	.plaintext	= "8787878787878787",
	.ciphertext	= "0000000000000000",
};

static const struct cipher_test des_test2 = {
	.type		= L_CIPHER_DES,
	.key		= "0E329232EA6D0D73",
	.plaintext	= "596F7572206C6970732061726520736D"
			  "6F6F74686572207468616E2076617365"
			  "6C696E650D0A0000",
	.ciphertext	= "C0999FDDE378D7ED727DA00BCA5A84EE"
			  "47F269A4D6438190D9D52F78F5358499"
			  "828AC9B453E0E653",
};

#define add_encrypt_test(name, data) l_test_add_data_func_precheck(name, \
					data, test_encrypt, cipher_precheck, 0)
#define add_decrypt_test(name, data) l_test_add_data_func_precheck(name, \
					data, test_decrypt, cipher_precheck, 0)

#define add_aead_test(name, data) l_test_add_data_func_precheck(name, data, \
					test_aead, aead_cipher_precheck, 0);

int main(int argc, char *argv[])
{
	l_test_init(&argc, &argv);

	l_test_add("unsupported", test_unsupported, NULL);

	l_test_add_func_precheck("aes", test_aes, aes_precheck, 0);
	l_test_add_func_precheck("aes_ctr", test_aes_ctr, aes_ctr_precheck, 0);

	add_aead_test("aes_ccm long nonce", &ccm_long_nonce);
	add_aead_test("aes_ccm short nonce", &ccm_short_nonce);
	add_aead_test("aes_ccm no AAD", &ccm_no_aad);

	add_aead_test("aes_gcm test 1", &gcm_test1);
	add_aead_test("aes_gcm test 2", &gcm_test2);
	add_aead_test("aes_gcm test 3", &gcm_test3);
	add_aead_test("aes_gcm test 4", &gcm_test4);
	add_aead_test("aes_gcm test 5", &gcm_test5);
	add_aead_test("aes_gcm test 6", &gcm_test6);

	add_aead_test("RFC3610 - Packet Vector #1", &rfc3610_ccm_1);
	add_aead_test("RFC3610 - Packet Vector #2", &rfc3610_ccm_2);
	add_aead_test("RFC3610 - Packet Vector #3", &rfc3610_ccm_3);
	add_aead_test("RFC3610 - Packet Vector #4", &rfc3610_ccm_4);
	add_aead_test("RFC3610 - Packet Vector #5", &rfc3610_ccm_5);
	add_aead_test("RFC3610 - Packet Vector #6", &rfc3610_ccm_6);
	add_aead_test("RFC3610 - Packet Vector #7", &rfc3610_ccm_7);
	add_aead_test("RFC3610 - Packet Vector #8", &rfc3610_ccm_8);
	add_aead_test("RFC3610 - Packet Vector #9", &rfc3610_ccm_9);
	add_aead_test("RFC3610 - Packet Vector #10", &rfc3610_ccm_10);
	add_aead_test("RFC3610 - Packet Vector #11", &rfc3610_ccm_11);
	add_aead_test("RFC3610 - Packet Vector #12", &rfc3610_ccm_12);
	add_aead_test("RFC3610 - Packet Vector #13", &rfc3610_ccm_13);
	add_aead_test("RFC3610 - Packet Vector #14", &rfc3610_ccm_14);
	add_aead_test("RFC3610 - Packet Vector #15", &rfc3610_ccm_15);
	add_aead_test("RFC3610 - Packet Vector #16", &rfc3610_ccm_16);
	add_aead_test("RFC3610 - Packet Vector #17", &rfc3610_ccm_17);
	add_aead_test("RFC3610 - Packet Vector #18", &rfc3610_ccm_18);
	add_aead_test("RFC3610 - Packet Vector #19", &rfc3610_ccm_19);
	add_aead_test("RFC3610 - Packet Vector #20", &rfc3610_ccm_20);
	add_aead_test("RFC3610 - Packet Vector #21", &rfc3610_ccm_21);
	add_aead_test("RFC3610 - Packet Vector #22", &rfc3610_ccm_22);
	add_aead_test("RFC3610 - Packet Vector #23", &rfc3610_ccm_23);
	add_aead_test("RFC3610 - Packet Vector #24", &rfc3610_ccm_24);

	add_aead_test("NIST CCM-AES128 - Example #1", &nist_ccm_aes128_1);
	add_aead_test("NIST CCM-AES128 - Example #2", &nist_ccm_aes128_2);
	add_aead_test("NIST CCM-AES128 - Example #3", &nist_ccm_aes128_3);
	add_aead_test("NIST CCM-AES128 - Example #4", &nist_ccm_aes128_4);
	add_aead_test("NIST CCM-AES128 - Example #5", &nist_ccm_aes128_5);
	add_aead_test("NIST CCM-AES192 - Example #1", &nist_ccm_aes192_1);
	add_aead_test("NIST CCM-AES192 - Example #2", &nist_ccm_aes192_2);
	add_aead_test("NIST CCM-AES192 - Example #3", &nist_ccm_aes192_3);
	add_aead_test("NIST CCM-AES192 - Example #4", &nist_ccm_aes192_4);
	add_aead_test("NIST CCM-AES192 - Example #5", &nist_ccm_aes192_5);
	add_aead_test("NIST CCM-AES256 - Example #1", &nist_ccm_aes256_1);
	add_aead_test("NIST CCM-AES256 - Example #2", &nist_ccm_aes256_2);
	add_aead_test("NIST CCM-AES256 - Example #3", &nist_ccm_aes256_3);
	add_aead_test("NIST CCM-AES256 - Example #4", &nist_ccm_aes256_4);
	add_aead_test("NIST CCM-AES256 - Example #5", &nist_ccm_aes256_5);

	add_encrypt_test("ARC4/encrypt/test 1", &arc4_test1);
	add_decrypt_test("ARC4/decrypt/test 1", &arc4_test1);
	add_encrypt_test("ARC4/encrypt/test 2", &arc4_test2);
	add_decrypt_test("ARC4/decrypt/test 2", &arc4_test2);
	add_encrypt_test("ARC4/encrypt/test 3", &arc4_test3);
	add_decrypt_test("ARC4/decrypt/test 3", &arc4_test3);

	add_encrypt_test("RC2/encrypt/test 1", &rc2_test1);
	add_decrypt_test("RC2/decrypt/test 1", &rc2_test1);
	add_encrypt_test("RC2/encrypt/test 2", &rc2_test2);
	add_decrypt_test("RC2/decrypt/test 2", &rc2_test2);
	add_encrypt_test("RC2/encrypt/test 3", &rc2_test3);
	add_decrypt_test("RC2/decrypt/test 3", &rc2_test3);

	add_encrypt_test("DES/encrypt/test 1", &des_test1);
	add_decrypt_test("DES/decrypt/test 1", &des_test1);
	add_encrypt_test("DES/encrypt/test 2", &des_test2);
	add_decrypt_test("DES/decrypt/test 2", &des_test2);

	add_encrypt_test("AES-128/encrypt/NIST", &ecb_aes128_nist);
	add_decrypt_test("AES-128/decrypt/NIST", &ecb_aes128_nist);
	add_encrypt_test("AES-192/encrypt/NIST", &ecb_aes192_nist);
	add_decrypt_test("AES-192/decrypt/NIST", &ecb_aes192_nist);
	add_encrypt_test("AES-256/encrypt/NIST", &ecb_aes256_nist);
	add_decrypt_test("AES-256/decrypt/NIST", &ecb_aes256_nist);
	add_encrypt_test("CBC-AES-128/encrypt/NIST", &cbc_aes128_nist);
	add_decrypt_test("CBS-AES-128/decrypt/NIST", &cbc_aes128_nist);
	add_encrypt_test("CBC-AES-192/encrypt/NIST", &cbc_aes192_nist);
	add_decrypt_test("CBS-AES-192/decrypt/NIST", &cbc_aes192_nist);
	add_encrypt_test("CBC-AES-256/encrypt/NIST", &cbc_aes256_nist);
	add_decrypt_test("CBS-AES-256/decrypt/NIST", &cbc_aes256_nist);
	add_encrypt_test("CTR-AES-128/encrypt/NIST", &ctr_aes128_nist);
	add_decrypt_test("CTR-AES-128/decrypt/NIST", &ctr_aes128_nist);
	add_encrypt_test("CTR-AES-192/encrypt/NIST", &ctr_aes192_nist);
	add_decrypt_test("CTR-AES-192/decrypt/NIST", &ctr_aes192_nist);
	add_encrypt_test("CTR-AES-256/encrypt/NIST", &ctr_aes256_nist);
	add_decrypt_test("CTR-AES-256/decrypt/NIST", &ctr_aes256_nist);

	return l_test_run();
}
