Merge tag 'libcrypto-tests-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux

Pull crypto library test updates from Eric Biggers:

 - Add comprehensive KUnit test suites for the new AES-GCM and AES-CCM
   library APIs

 - Add FIPS self-tests for all the AES encryption modes. This is needed
   for parity with the traditional crypto API

 - Fix a couple more issues in the IRQ test helper

* tag 'libcrypto-tests-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux:
  lib/crypto: aes-cmac: Use __cleanup() instead of memzero_explicit()
  kunit: irq: Unregister on-stack timer and work from debugobjects
  kunit: irq: Continue increasing hrtimer interval for longer
  lib/crypto: tests: Add KUnit test suite for AES-GCM
  lib/crypto: tests: Add KUnit test suite for AES-CCM
  lib/crypto: tests: Add aead-test-template.h
  lib/crypto: tests: Use per-test-case buffers in hash tests
  lib/crypto: tests: Create test-utils.h
  lib/crypto: aes: Add FIPS self-tests for GCM and CCM
  lib/crypto: aes: Add FIPS self-tests for unauthenticated modes
  lib/crypto: fips: Split fips.h into fips-aes.h and fips-sha.h
This commit is contained in:
Linus Torvalds
2026-08-17 19:29:41 -07:00
35 changed files with 2738 additions and 397 deletions

View File

@@ -38,11 +38,13 @@ static enum hrtimer_restart kunit_irq_test_timer_func(struct hrtimer *timer)
softirq_calls = atomic_read(&state->softirq_func_calls);
/*
* If the timer is firing too often for the softirq or task to ever have
* a chance to run, increase the timer interval. This is needed on very
* slow systems.
* If the hrtimer is running much faster than the bh_work or the task,
* then it is firing too fast and might be starving those contexts as
* well as the actual system timer tick. Increase the interval.
*/
if (hardirq_calls >= 20 && (softirq_calls == 0 || task_calls == 0))
if (hardirq_calls >= 20 &&
(hardirq_calls / 2 > softirq_calls ||
hardirq_calls / 2 > task_calls))
state->interval = ktime_add_ns(state->interval, 250);
if (!state->func(state->test_specific_state))
@@ -135,6 +137,8 @@ static inline void kunit_run_irq_test(struct kunit *test, bool (*func)(void *),
/* Cancel the timer and work. */
hrtimer_cancel(&state.timer);
flush_work(&state.bh_work);
destroy_hrtimer_on_stack(&state.timer);
destroy_work_on_stack(&state.bh_work);
/* Sanity check: the timer and BH functions should have been run. */
KUNIT_EXPECT_GT_MSG(test, atomic_read(&state.hardirq_func_calls), 0,

View File

@@ -3,6 +3,8 @@ CONFIG_KUNIT=y
CONFIG_CRYPTO_LIB_ENABLE_ALL_FOR_KUNIT=y
CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST=y
CONFIG_CRYPTO_LIB_AES_CCM_KUNIT_TEST=y
CONFIG_CRYPTO_LIB_AES_GCM_KUNIT_TEST=y
CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST=y
CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST=y
CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST=y

View File

@@ -19,7 +19,7 @@
#include <linux/export.h>
#include <linux/module.h>
#include <linux/unaligned.h>
#include "fips.h"
#include "fips-aes.h"
static const u8 ____cacheline_aligned aes_sbox[] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
@@ -522,6 +522,26 @@ void aes_decrypt(const struct aes_key *key, u8 out[AES_BLOCK_SIZE],
}
EXPORT_SYMBOL(aes_decrypt);
/* FIPS cryptographic algorithm self-test for "bare" AES */
static void __init aes_fips_test(void)
{
struct aes_key key;
u8 data[AES_BLOCK_SIZE];
if (aes_preparekey(&key, fips_test_key, sizeof(fips_test_key)) != 0)
panic("aes: FIPS self-test failed (preparekey)\n");
aes_encrypt(&key, data, fips_test_data);
if (memcmp(fips_test_aes_ecb_ctext, data, sizeof(data)) != 0)
panic("aes: FIPS self-test failed (wrong ciphertext)\n");
aes_decrypt(&key, data, data);
if (memcmp(fips_test_data, data, sizeof(data)) != 0)
panic("aes: FIPS self-test failed (wrong plaintext)\n");
memzero_explicit(&key, sizeof(key));
}
#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_CBC_MACS)
#ifndef aes_cbcmac_blocks_arch
@@ -717,17 +737,10 @@ void aes_cbcmac_final(struct aes_cbcmac_ctx *ctx, u8 out[AES_BLOCK_SIZE])
}
EXPORT_SYMBOL_NS_GPL(aes_cbcmac_final, "CRYPTO_INTERNAL");
/*
* FIPS cryptographic algorithm self-test for AES-CMAC. As per the FIPS 140-3
* Implementation Guidance, a cryptographic algorithm self-test for at least one
* of AES-GCM, AES-CCM, AES-CMAC, or AES-GMAC is required if any of those modes
* is implemented. This fulfills that requirement via AES-CMAC.
*
* This is just for FIPS. The full tests are in the KUnit test suite.
*/
/* FIPS cryptographic algorithm self-test for AES-CMAC */
static void __init aes_cmac_fips_test(void)
{
struct aes_cmac_key key;
struct aes_cmac_key key __cleanup(aes_cmac_zeroize_key);
u8 mac[AES_BLOCK_SIZE];
if (aes_cmac_preparekey(&key, fips_test_key, sizeof(fips_test_key)) !=
@@ -736,7 +749,6 @@ static void __init aes_cmac_fips_test(void)
aes_cmac(&key, fips_test_data, sizeof(fips_test_data), mac);
if (memcmp(fips_test_aes_cmac_value, mac, sizeof(mac)) != 0)
panic("aes: CMAC FIPS self-test failed (wrong MAC)\n");
memzero_explicit(&key, sizeof(key));
}
#else /* CONFIG_CRYPTO_LIB_AES_CBC_MACS */
static inline void aes_cmac_fips_test(void)
@@ -797,7 +809,31 @@ void aes_ecb_decrypt(u8 *dst, const u8 *src, size_t len,
aes_decrypt(key, &dst[i], &src[i]);
}
EXPORT_SYMBOL_GPL(aes_ecb_decrypt);
#endif /* CONFIG_CRYPTO_LIB_AES_ECB */
/* FIPS cryptographic algorithm self-test for AES-ECB */
static void __init aes_ecb_fips_test(void)
{
struct aes_key key;
u8 data[sizeof(fips_test_data)];
if (aes_preparekey(&key, fips_test_key, sizeof(fips_test_key)) != 0)
panic("aes: ECB FIPS self-test failed (preparekey)\n");
aes_ecb_encrypt(data, fips_test_data, sizeof(data), &key);
if (memcmp(fips_test_aes_ecb_ctext, data, sizeof(data)) != 0)
panic("aes: ECB FIPS self-test failed (wrong ciphertext)\n");
aes_ecb_decrypt(data, data, sizeof(data), &key);
if (memcmp(fips_test_data, data, sizeof(data)) != 0)
panic("aes: ECB FIPS self-test failed (wrong plaintext)\n");
memzero_explicit(&key, sizeof(key));
}
#else /* CONFIG_CRYPTO_LIB_AES_ECB */
static inline void aes_ecb_fips_test(void)
{
}
#endif /* !CONFIG_CRYPTO_LIB_AES_ECB */
#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_CBC)
/*
@@ -983,7 +1019,66 @@ void aes_cbc_cts_decrypt(u8 *dst, const u8 *src, size_t len,
crypto_xor(pad, iv, AES_BLOCK_SIZE); /* P[n - 1] */
}
EXPORT_SYMBOL_GPL(aes_cbc_cts_decrypt);
#endif /* CONFIG_CRYPTO_LIB_AES_CBC */
/* FIPS cryptographic algorithm self-test for AES-CBC */
static void __init aes_cbc_fips_test(void)
{
struct aes_key key;
u8 iv[AES_BLOCK_SIZE];
u8 data[sizeof(fips_test_data)];
if (aes_preparekey(&key, fips_test_key, sizeof(fips_test_key)) != 0)
panic("aes: CBC FIPS self-test failed (preparekey)\n");
memcpy(iv, fips_test_iv, sizeof(iv));
aes_cbc_encrypt(data, fips_test_data, sizeof(data), iv, &key);
if (memcmp(fips_test_aes_cbc_ctext, data, sizeof(data)) != 0)
panic("aes: CBC FIPS self-test failed (wrong ciphertext)\n");
memcpy(iv, fips_test_iv, sizeof(iv));
aes_cbc_decrypt(data, data, sizeof(data), iv, &key);
if (memcmp(fips_test_data, data, sizeof(data)) != 0)
panic("aes: CBC FIPS self-test failed (wrong plaintext)\n");
memzero_explicit(&key, sizeof(key));
}
/* FIPS cryptographic algorithm self-test for AES-CBC-CTS */
static void __init aes_cbc_cts_fips_test(void)
{
struct aes_key key;
u8 iv[AES_BLOCK_SIZE];
const size_t data_len = 2 * AES_BLOCK_SIZE;
u8 ptext[2 * AES_BLOCK_SIZE];
u8 data[2 * AES_BLOCK_SIZE];
/* ptext = fips_test_data || fips_test_data */
memcpy(ptext, fips_test_data, AES_BLOCK_SIZE);
memcpy(&ptext[AES_BLOCK_SIZE], ptext, AES_BLOCK_SIZE);
if (aes_preparekey(&key, fips_test_key, sizeof(fips_test_key)) != 0)
panic("aes: CBC-CTS FIPS self-test failed (preparekey)\n");
memcpy(iv, fips_test_iv, sizeof(iv));
aes_cbc_cts_encrypt(data, ptext, data_len, iv, &key);
if (memcmp(fips_test_aes_cbc_cts_ctext, data, data_len) != 0)
panic("aes: CBC-CTS FIPS self-test failed (wrong ciphertext)\n");
memcpy(iv, fips_test_iv, sizeof(iv));
aes_cbc_cts_decrypt(data, data, data_len, iv, &key);
if (memcmp(ptext, data, data_len) != 0)
panic("aes: CBC-CTS FIPS self-test failed (wrong plaintext)\n");
memzero_explicit(&key, sizeof(key));
}
#else /* CONFIG_CRYPTO_LIB_AES_CBC */
static inline void aes_cbc_fips_test(void)
{
}
static inline void aes_cbc_cts_fips_test(void)
{
}
#endif /* !CONFIG_CRYPTO_LIB_AES_CBC */
#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_CTR)
/*
@@ -1078,7 +1173,34 @@ void aes_xctr(u8 *dst, const u8 *src, size_t len, u64 *ctr,
memzero_explicit(aes_input, sizeof(aes_input));
}
EXPORT_SYMBOL_GPL(aes_xctr);
#endif /* CONFIG_CRYPTO_LIB_AES_CTR */
/* FIPS cryptographic algorithm self-test for AES-CTR */
static void __init aes_ctr_fips_test(void)
{
struct aes_enckey key;
u8 ctr[AES_BLOCK_SIZE];
u8 data[sizeof(fips_test_data)];
if (aes_prepareenckey(&key, fips_test_key, sizeof(fips_test_key)) != 0)
panic("aes: CTR FIPS self-test failed (preparekey)\n");
memcpy(ctr, fips_test_iv, sizeof(ctr));
aes_ctr(data, fips_test_data, sizeof(data), ctr, &key);
if (memcmp(fips_test_aes_ctr_ctext, data, sizeof(data)) != 0)
panic("aes: CTR FIPS self-test failed (wrong ciphertext)\n");
memcpy(ctr, fips_test_iv, sizeof(ctr));
aes_ctr(data, data, sizeof(data), ctr, &key);
if (memcmp(fips_test_data, data, sizeof(data)) != 0)
panic("aes: CTR FIPS self-test failed (wrong plaintext)\n");
memzero_explicit(&key, sizeof(key));
}
#else /* CONFIG_CRYPTO_LIB_AES_CTR */
static inline void aes_ctr_fips_test(void)
{
}
#endif /* !CONFIG_CRYPTO_LIB_AES_CTR */
#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_XTS)
int aes_xts_preparekey(struct aes_xts_key *key, const u8 *in_key,
@@ -1307,7 +1429,36 @@ void aes_xts_decrypt(u8 *dst, const u8 *src, size_t len,
aes_xts_decrypt_nocts(dst, src, len, tweak, key, cont);
}
EXPORT_SYMBOL_GPL(aes_xts_decrypt);
#endif /* CONFIG_CRYPTO_LIB_AES_XTS */
/* FIPS cryptographic algorithm self-test for AES-XTS */
static void __init aes_xts_fips_test(void)
{
struct aes_xts_key *key __free(kfree_sensitive) = kmalloc_obj(*key);
u8 tweak[AES_BLOCK_SIZE];
u8 data[sizeof(fips_test_data)];
if (key == NULL)
panic("aes: XTS FIPS self-test failed (kmalloc)\n");
if (aes_xts_preparekey(key, fips_test_xts_key,
sizeof(fips_test_xts_key), 0) != 0)
panic("aes: XTS FIPS self-test failed (preparekey)\n");
memcpy(tweak, fips_test_iv, sizeof(tweak));
aes_xts_encrypt(data, fips_test_data, sizeof(data), tweak, key, false);
if (memcmp(fips_test_aes_xts_ctext, data, sizeof(data)) != 0)
panic("aes: XTS FIPS self-test failed (wrong ciphertext)\n");
memcpy(tweak, fips_test_iv, sizeof(tweak));
aes_xts_decrypt(data, data, sizeof(data), tweak, key, false);
if (memcmp(fips_test_data, data, sizeof(data)) != 0)
panic("aes: XTS FIPS self-test failed (wrong plaintext)\n");
}
#else /* CONFIG_CRYPTO_LIB_AES_XTS */
static inline void aes_xts_fips_test(void)
{
}
#endif /* !CONFIG_CRYPTO_LIB_AES_XTS */
#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_GCM)
/*
@@ -1586,7 +1737,37 @@ int aes_gcm_decrypt(u8 *dst, const u8 *src, size_t data_len, const u8 *authtag,
}
EXPORT_SYMBOL_GPL(aes_gcm_decrypt);
#endif /* CONFIG_CRYPTO_LIB_AES_GCM */
/* FIPS cryptographic algorithm self-test for AES-GCM */
static void __init aes_gcm_fips_test(void)
{
const size_t data_len = sizeof(fips_test_data);
u8 buf[sizeof(fips_test_data) + AES_BLOCK_SIZE];
struct aes_gcm_key key;
int err;
if (aes_gcm_preparekey(&key, fips_test_key, sizeof(fips_test_key),
AES_BLOCK_SIZE) != 0)
panic("aes: GCM FIPS self-test failed (preparekey)\n");
aes_gcm_encrypt(buf, fips_test_data, data_len, &buf[data_len],
fips_test_ad, sizeof(fips_test_ad), fips_test_iv, &key);
if (memcmp(fips_test_aes_gcm_ctext_and_tag, buf, sizeof(buf)) != 0)
panic("aes: GCM FIPS self-test failed (wrong ciphertext and/or tag)\n");
err = aes_gcm_decrypt(buf, buf, data_len, &buf[data_len], fips_test_ad,
sizeof(fips_test_ad), fips_test_iv, &key);
if (err != 0)
panic("aes: GCM FIPS self-test failed (decryption failed)\n");
if (memcmp(fips_test_data, buf, data_len) != 0)
panic("aes: GCM FIPS self-test failed (wrong plaintext)\n");
memzero_explicit(&key, sizeof(key));
}
#else /* CONFIG_CRYPTO_LIB_AES_GCM */
static inline void aes_gcm_fips_test(void)
{
}
#endif /* !CONFIG_CRYPTO_LIB_AES_GCM */
#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_CCM)
int aes_ccm_preparekey(struct aes_ccm_key *key, const u8 *in_key,
@@ -1898,15 +2079,60 @@ int aes_ccm_decrypt(u8 *dst, const u8 *src, size_t data_len, const u8 *authtag,
return err;
}
EXPORT_SYMBOL_GPL(aes_ccm_decrypt);
#endif /* CONFIG_CRYPTO_LIB_AES_CCM */
/* FIPS cryptographic algorithm self-test for AES-CCM */
static void __init aes_ccm_fips_test(void)
{
const size_t data_len = sizeof(fips_test_data);
const size_t nonce_len = 13;
u8 buf[sizeof(fips_test_data) + AES_BLOCK_SIZE];
struct aes_ccm_key key;
int err;
if (aes_ccm_preparekey(&key, fips_test_key, sizeof(fips_test_key),
AES_BLOCK_SIZE) != 0)
panic("aes: CCM FIPS self-test failed (preparekey)\n");
err = aes_ccm_encrypt(buf, fips_test_data, data_len, &buf[data_len],
fips_test_ad, sizeof(fips_test_ad), fips_test_iv,
nonce_len, &key);
if (err != 0)
panic("aes: CCM FIPS self-test failed (encryption failed)\n");
if (memcmp(fips_test_aes_ccm_ctext_and_tag, buf, sizeof(buf)) != 0)
panic("aes: CCM FIPS self-test failed (wrong ciphertext and/or tag)\n");
err = aes_ccm_decrypt(buf, buf, data_len, &buf[data_len], fips_test_ad,
sizeof(fips_test_ad), fips_test_iv, nonce_len,
&key);
if (err != 0)
panic("aes: CCM FIPS self-test failed (decryption failed)\n");
if (memcmp(fips_test_data, buf, data_len) != 0)
panic("aes: CCM FIPS self-test failed (wrong plaintext)\n");
memzero_explicit(&key, sizeof(key));
}
#else /* CONFIG_CRYPTO_LIB_AES_CCM */
static inline void aes_ccm_fips_test(void)
{
}
#endif /* !CONFIG_CRYPTO_LIB_AES_CCM */
static int __init aes_mod_init(void)
{
#ifdef aes_mod_init_arch
aes_mod_init_arch();
#endif
if (fips_enabled)
if (fips_enabled) {
aes_fips_test();
aes_cmac_fips_test();
aes_ecb_fips_test();
aes_cbc_fips_test();
aes_cbc_cts_fips_test();
aes_ctr_fips_test();
aes_xts_fips_test();
aes_gcm_fips_test();
aes_ccm_fips_test();
}
return 0;
}
subsys_initcall(aes_mod_init);

78
lib/crypto/fips-aes.h Normal file
View File

@@ -0,0 +1,78 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* This file was generated by: gen-fips-testvecs.py */
/* clang-format off */
#include <linux/fips.h>
static const u8 fips_test_data[] __initconst __maybe_unused = {
0x66, 0x69, 0x70, 0x73, 0x20, 0x74, 0x65, 0x73,
0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00,
};
static const u8 fips_test_ad[] __initconst __maybe_unused = {
0x66, 0x69, 0x70, 0x73, 0x20, 0x74, 0x65, 0x73,
0x74, 0x20, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00,
};
static const u8 fips_test_iv[] __initconst __maybe_unused = {
0x66, 0x69, 0x70, 0x73, 0x20, 0x74, 0x65, 0x73,
0x74, 0x20, 0x69, 0x76, 0x00, 0x00, 0x00, 0x00,
};
static const u8 fips_test_key[] __initconst __maybe_unused = {
0x66, 0x69, 0x70, 0x73, 0x20, 0x74, 0x65, 0x73,
0x74, 0x20, 0x6b, 0x65, 0x79, 0x00, 0x00, 0x00,
};
static const u8 fips_test_xts_key[] __initconst __maybe_unused = {
0x6b, 0x65, 0x79, 0x31, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6b, 0x65, 0x79, 0x32, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const u8 fips_test_aes_cmac_value[] __initconst __maybe_unused = {
0xc5, 0x88, 0x28, 0x55, 0xd7, 0x2c, 0x00, 0xb6,
0x6a, 0xa7, 0xfc, 0x82, 0x90, 0x81, 0xcf, 0x18,
};
static const u8 fips_test_aes_ecb_ctext[] __initconst __maybe_unused = {
0x47, 0x76, 0x48, 0xaf, 0x1b, 0xd8, 0x4c, 0xe6,
0xb5, 0xa7, 0x20, 0x8d, 0x64, 0x88, 0xbc, 0x3f,
};
static const u8 fips_test_aes_cbc_ctext[] __initconst __maybe_unused = {
0xc8, 0x7d, 0x7c, 0x25, 0xba, 0x15, 0xf7, 0xe1,
0x08, 0xa0, 0xd0, 0x7a, 0x20, 0x37, 0xaf, 0x5e,
};
static const u8 fips_test_aes_cbc_cts_ctext[] __initconst __maybe_unused = {
0x36, 0x8e, 0x37, 0xb4, 0x78, 0xe2, 0x88, 0x59,
0xd5, 0xe8, 0x17, 0x65, 0x5c, 0xa1, 0x25, 0xe6,
0xc8, 0x7d, 0x7c, 0x25, 0xba, 0x15, 0xf7, 0xe1,
0x08, 0xa0, 0xd0, 0x7a, 0x20, 0x37, 0xaf, 0x5e,
};
static const u8 fips_test_aes_ctr_ctext[] __initconst __maybe_unused = {
0x95, 0xf4, 0xf4, 0x7a, 0xc8, 0xa2, 0x53, 0x73,
0x53, 0x8f, 0x95, 0xfc, 0x18, 0xfe, 0x58, 0x2f,
};
static const u8 fips_test_aes_xts_ctext[] __initconst __maybe_unused = {
0xd4, 0x51, 0x7f, 0x01, 0x14, 0x91, 0x16, 0x29,
0x26, 0xbe, 0xec, 0x9b, 0x90, 0xed, 0x59, 0x30,
};
static const u8 fips_test_aes_gcm_ctext_and_tag[] __initconst __maybe_unused = {
0x12, 0x0c, 0x5d, 0x03, 0x32, 0x93, 0x13, 0x44,
0x06, 0x35, 0x26, 0x9d, 0xe0, 0xea, 0xbc, 0xe2,
0x30, 0xa9, 0xa4, 0x15, 0xc5, 0x3d, 0xb3, 0xf9,
0x30, 0x82, 0xdf, 0x9c, 0xd8, 0xc4, 0x3f, 0x2f,
};
static const u8 fips_test_aes_ccm_ctext_and_tag[] __initconst __maybe_unused = {
0x11, 0x8e, 0x01, 0xcb, 0xb5, 0x22, 0x6d, 0xb4,
0x66, 0x98, 0x97, 0x1d, 0x35, 0x53, 0x78, 0xdd,
0xd1, 0xc5, 0xff, 0xb6, 0x90, 0xcf, 0xb1, 0xf2,
0x87, 0x99, 0xd6, 0x1e, 0xd5, 0xd1, 0xed, 0x63,
};

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* This file was generated by: gen-fips-testvecs.py */
/* clang-format off */
#include <linux/fips.h>
@@ -43,8 +44,3 @@ static const u8 fips_test_sha3_256_value[] __initconst __maybe_unused = {
0xba, 0x9b, 0xb6, 0xaa, 0x32, 0xa7, 0x97, 0x00,
0x98, 0xdb, 0xff, 0xe7, 0xc6, 0xde, 0xb5, 0x82,
};
static const u8 fips_test_aes_cmac_value[] __initconst __maybe_unused = {
0xc5, 0x88, 0x28, 0x55, 0xd7, 0x2c, 0x00, 0xb6,
0x6a, 0xa7, 0xfc, 0x82, 0x90, 0x81, 0xcf, 0x18,
};

View File

@@ -12,7 +12,7 @@
#include <linux/string.h>
#include <linux/unaligned.h>
#include <linux/wordpart.h>
#include "fips.h"
#include "fips-sha.h"
static const struct sha1_block_state sha1_iv = {
.h = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },

View File

@@ -17,7 +17,7 @@
#include <linux/string.h>
#include <linux/unaligned.h>
#include <linux/wordpart.h>
#include "fips.h"
#include "fips-sha.h"
static const struct sha256_block_state sha224_iv = {
.h = {

View File

@@ -17,7 +17,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/unaligned.h>
#include "fips.h"
#include "fips-sha.h"
/*
* On some 32-bit architectures, such as h8300, GCC ends up using over 1 KB of

View File

@@ -17,7 +17,7 @@
#include <linux/string.h>
#include <linux/unaligned.h>
#include <linux/wordpart.h>
#include "fips.h"
#include "fips-sha.h"
static const struct sha512_block_state sha384_iv = {
.h = {

View File

@@ -9,6 +9,24 @@ config CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST
KUnit tests for the AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC message
authentication codes.
config CRYPTO_LIB_AES_CCM_KUNIT_TEST
tristate "KUnit tests for AES-CCM" if !KUNIT_ALL_TESTS
depends on KUNIT && CRYPTO_LIB_AES_CCM
default KUNIT_ALL_TESTS
select CRYPTO_LIB_BENCHMARK_VISIBLE
# This test uses BLAKE2s, but that's always built-in.
help
KUnit tests for the AES-CCM authenticated encryption algorithm.
config CRYPTO_LIB_AES_GCM_KUNIT_TEST
tristate "KUnit tests for AES-GCM" if !KUNIT_ALL_TESTS
depends on KUNIT && CRYPTO_LIB_AES_GCM
default KUNIT_ALL_TESTS
select CRYPTO_LIB_BENCHMARK_VISIBLE
# This test uses BLAKE2s, but that's always built-in.
help
KUnit tests for the AES-GCM authenticated encryption algorithm.
config CRYPTO_LIB_BLAKE2B_KUNIT_TEST
tristate "KUnit tests for BLAKE2b" if !KUNIT_ALL_TESTS
depends on KUNIT && CRYPTO_LIB_BLAKE2B

View File

@@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later
obj-$(CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST) += aes_cbc_macs_kunit.o
obj-$(CONFIG_CRYPTO_LIB_AES_CCM_KUNIT_TEST) += aes_ccm_kunit.o
obj-$(CONFIG_CRYPTO_LIB_AES_GCM_KUNIT_TEST) += aes_gcm_kunit.o
obj-$(CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST) += blake2b_kunit.o
obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o
obj-$(CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST) += chacha20poly1305_kunit.o

File diff suppressed because it is too large Load Diff

View File

@@ -34,18 +34,9 @@ static void aes_cmac_withtestkey(const u8 *data, size_t data_len,
static int aes_cbc_macs_suite_init(struct kunit_suite *suite)
{
u8 raw_key[AES_KEYSIZE_256];
int err;
rand_bytes_seeded_from_len(raw_key, sizeof(raw_key));
err = aes_cmac_preparekey(&test_key, raw_key, sizeof(raw_key));
if (err)
return err;
return hash_suite_init(suite);
}
static void aes_cbc_macs_suite_exit(struct kunit_suite *suite)
{
hash_suite_exit(suite);
return aes_cmac_preparekey(&test_key, raw_key, sizeof(raw_key));
}
/* Verify compatibility of the AES-CMAC implementation with RFC 4493. */
@@ -218,7 +209,6 @@ static struct kunit_suite aes_cbc_macs_test_suite = {
.name = "aes_cbc_macs",
.test_cases = aes_cbc_macs_test_cases,
.suite_init = aes_cbc_macs_suite_init,
.suite_exit = aes_cbc_macs_suite_exit,
};
kunit_test_suite(aes_cbc_macs_test_suite);

View File

@@ -0,0 +1,356 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* KUnit test suite for AES-CCM
*
* Copyright 2026 Google LLC
*/
#include <crypto/aes-ccm.h>
#include <crypto/blake2s.h>
#include "test-utils.h"
/* AES-CCM test vectors from external sources */
static const struct aes_ccm_testvec {
const char *name;
const char *key;
size_t key_len;
const char *nonce;
size_t nonce_len;
const char *ad;
size_t ad_len;
const char *ptext;
const char *ctext;
size_t data_len;
const char *tag;
size_t tag_len;
} aes_ccm_testvecs[] = {
{
.name = "RFC 3610 Packet Vector #1",
.key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
"\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
.key_len = 16,
.nonce = "\x00\x00\x00\x03\x02\x01\x00\xa0"
"\xa1\xa2\xa3\xa4\xa5",
.nonce_len = 13,
.ad = "\x00\x01\x02\x03\x04\x05\x06\x07",
.ad_len = 8,
.ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
"\x10\x11\x12\x13\x14\x15\x16\x17"
"\x18\x19\x1a\x1b\x1c\x1d\x1e",
.ctext = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2"
"\xf0\x66\xd0\xc2\xc0\xf9\x89\x80"
"\x6d\x5f\x6b\x61\xda\xc3\x84",
.data_len = 23,
.tag = "\x17\xe8\xd1\x2c\xfd\xf9\x26\xe0",
.tag_len = 8,
},
{
.name = "RFC 3610 Packet Vector #5",
.key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
"\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
.key_len = 16,
.nonce = "\x00\x00\x00\x07\x06\x05\x04\xa0"
"\xa1\xa2\xa3\xa4\xa5",
.nonce_len = 13,
.ad = "\x00\x01\x02\x03\x04\x05\x06\x07"
"\x08\x09\x0a\x0b",
.ad_len = 12,
.ptext = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
"\x14\x15\x16\x17\x18\x19\x1a\x1b"
"\x1c\x1d\x1e\x1f",
.ctext = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb"
"\x9d\x4e\x13\x12\x53\x65\x8a\xd8"
"\x6e\xbd\xca\x3e",
.data_len = 20,
.tag = "\x51\xe8\x3f\x07\x7d\x9c\x2d\x93",
.tag_len = 8,
},
{
.name = "RFC 3610 Packet Vector #9",
.key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
"\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
.key_len = 16,
.nonce = "\x00\x00\x00\x0b\x0a\x09\x08\xa0"
"\xa1\xa2\xa3\xa4\xa5",
.nonce_len = 13,
.ad = "\x00\x01\x02\x03\x04\x05\x06\x07",
.ad_len = 8,
.ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
"\x10\x11\x12\x13\x14\x15\x16\x17"
"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20",
.ctext = "\x82\x53\x1a\x60\xcc\x24\x94\x5a"
"\x4b\x82\x79\x18\x1a\xb5\xc8\x4d"
"\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1"
"\x97",
.data_len = 25,
.tag = "\xea\x9c\x07\xe5\x6b\x5e\xb1\x7e"
"\x5f\x4e",
.tag_len = 10,
},
{
.name = "NIST SP 800-38C Example 1",
.key = "\x40\x41\x42\x43\x44\x45\x46\x47"
"\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
.key_len = 16,
.nonce = "\x10\x11\x12\x13\x14\x15\x16",
.nonce_len = 7,
.ad = "\x00\x01\x02\x03\x04\x05\x06\x07",
.ad_len = 8,
.ptext = "\x20\x21\x22\x23",
.ctext = "\x71\x62\x01\x5b",
.data_len = 4,
.tag = "\x4d\xac\x25\x5d",
.tag_len = 4,
},
{
.name = "NIST SP 800-38C Example 2",
.key = "\x40\x41\x42\x43\x44\x45\x46\x47"
"\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
.key_len = 16,
.nonce = "\x10\x11\x12\x13\x14\x15\x16\x17",
.nonce_len = 8,
.ad = "\x00\x01\x02\x03\x04\x05\x06\x07"
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
.ad_len = 16,
.ptext = "\x20\x21\x22\x23\x24\x25\x26\x27"
"\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f",
.ctext = "\xd2\xa1\xf0\xe0\x51\xea\x5f\x62"
"\x08\x1a\x77\x92\x07\x3d\x59\x3d",
.data_len = 16,
.tag = "\x1f\xc6\x4f\xbf\xac\xcd",
.tag_len = 6,
},
{
.name = "NIST SP 800-38C Example 3",
.key = "\x40\x41\x42\x43\x44\x45\x46\x47"
"\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
.key_len = 16,
.nonce = "\x10\x11\x12\x13\x14\x15\x16\x17"
"\x18\x19\x1a\x1b",
.nonce_len = 12,
.ad = "\x00\x01\x02\x03\x04\x05\x06\x07"
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
"\x10\x11\x12\x13",
.ad_len = 20,
.ptext = "\x20\x21\x22\x23\x24\x25\x26\x27"
"\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
"\x30\x31\x32\x33\x34\x35\x36\x37",
.ctext = "\xe3\xb2\x01\xa9\xf5\xb7\x1a\x7a"
"\x9b\x1c\xea\xec\xcd\x97\xe7\x0b"
"\x61\x76\xaa\xd9\xa4\x42\x8a\xa5",
.data_len = 24,
.tag = "\x48\x43\x92\xfb\xc1\xb0\x99\x51",
.tag_len = 8,
},
};
static void test_aes_ccm_one_test_vector(struct kunit *test,
const struct aes_ccm_testvec *tv)
{
u8 *ctext = alloc_buf(test, tv->data_len);
u8 *decrypted = alloc_buf(test, tv->data_len);
u8 *tag = alloc_buf(test, tv->tag_len);
struct aes_ccm_key key;
int err;
err = aes_ccm_preparekey(&key, tv->key, tv->key_len, tv->tag_len);
KUNIT_ASSERT_EQ_MSG(test, 0, err, "Failed to prepare key for %s",
tv->name);
err = aes_ccm_encrypt(ctext, tv->ptext, tv->data_len, tag, tv->ad,
tv->ad_len, tv->nonce, tv->nonce_len, &key);
KUNIT_ASSERT_EQ_MSG(test, 0, err, "Encryption failed for %s", tv->name);
KUNIT_ASSERT_MEMEQ_MSG(test, tv->ctext, ctext, tv->data_len,
"Wrong ciphertext for %s", tv->name);
KUNIT_ASSERT_MEMEQ_MSG(test, tag, tv->tag, tv->tag_len,
"Wrong tag for %s", tv->name);
err = aes_ccm_decrypt(decrypted, ctext, tv->data_len, tag, tv->ad,
tv->ad_len, tv->nonce, tv->nonce_len, &key);
KUNIT_ASSERT_EQ_MSG(test, 0, err, "Decryption failed for %s", tv->name);
KUNIT_ASSERT_MEMEQ_MSG(test, tv->ptext, decrypted, tv->data_len,
"Wrong plaintext for %s", tv->name);
}
static void test_aes_ccm_test_vectors(struct kunit *test)
{
for (size_t i = 0; i < ARRAY_SIZE(aes_ccm_testvecs); i++)
test_aes_ccm_one_test_vector(test, &aes_ccm_testvecs[i]);
}
/*
* Test NIST SP 800-38C Example 4, which uses a deterministically-generated
* 65536-byte associated data string.
*/
static void test_aes_ccm_nist_sp800_38c_example4(struct kunit *test)
{
struct aes_ccm_testvec tv = {
.name = "NIST SP 800-38C Example 4",
.key_len = 16,
.nonce_len = 13,
.ad_len = 65536,
.ctext = "\x69\x91\x5d\xad\x1e\x84\xc6\x37"
"\x6a\x68\xc2\x96\x7e\x4d\xab\x61"
"\x5a\xe0\xfd\x1f\xae\xc4\x4c\xc4"
"\x84\x82\x85\x29\x46\x3c\xcf\x72",
.data_len = 32,
.tag = "\xb4\xac\x6b\xec\x93\xe8\x59\x8e"
"\x7f\x0d\xad\xbc\xea\x5b",
.tag_len = 14,
};
u8 *key, *nonce, *ad, *ptext;
key = alloc_buf(test, tv.key_len);
for (size_t i = 0; i < tv.key_len; i++)
key[i] = 0x40 + i;
nonce = alloc_guarded_buf(test, tv.nonce_len);
for (size_t i = 0; i < tv.nonce_len; i++)
nonce[i] = 0x10 + i;
ad = alloc_guarded_buf(test, tv.ad_len);
for (size_t i = 0; i < tv.ad_len; i++)
ad[i] = (u8)i;
ptext = alloc_guarded_buf(test, tv.data_len);
for (size_t i = 0; i < tv.data_len; i++)
ptext[i] = 0x20 + i;
tv.key = key;
tv.nonce = nonce;
tv.ad = ad;
tv.ptext = ptext;
test_aes_ccm_one_test_vector(test, &tv);
}
static const size_t aes_ccm_valid_key_lens[] = { 16, 24, 32 };
#define AEAD_MAX_KEY_LEN 32
#define AEAD_VALID_KEY_LENS aes_ccm_valid_key_lens
static const size_t aes_ccm_valid_nonce_lens[] = { 7, 8, 9, 10, 11, 12, 13 };
#define AEAD_MAX_NONCE_LEN 13
#define AEAD_VALID_NONCE_LENS aes_ccm_valid_nonce_lens
static const size_t aes_ccm_valid_tag_lens[] = { 4, 6, 8, 10, 12, 14, 16 };
#define AEAD_MAX_TAG_LEN 16
#define AEAD_VALID_TAG_LENS aes_ccm_valid_tag_lens
#define AEAD_KEY aes_ccm_key
#define AEAD_CTX aes_ccm_ctx
#define AEAD_PREPAREKEY aes_ccm_preparekey
#define AEAD_ENCRYPT aes_ccm_encrypt
#define AEAD_DECRYPT aes_ccm_decrypt
#define AEAD_INIT aes_ccm_init
#define AEAD_AUTH_UPDATE aes_ccm_auth_update
#define AEAD_ENCRYPT_UPDATE aes_ccm_encrypt_update
#define AEAD_DECRYPT_UPDATE aes_ccm_decrypt_update
#define AEAD_ENCRYPT_FINAL aes_ccm_encrypt_final
#define AEAD_DECRYPT_FINAL aes_ccm_decrypt_final
/* This value was generated by gen-aead-testvecs.py. */
static const u8 aes_ccm_monte_carlo_checksum[BLAKE2S_HASH_SIZE] = {
0x70, 0x1c, 0xde, 0xa4, 0xe2, 0x03, 0x50, 0xb2, 0xf5, 0x9e, 0x61,
0x66, 0xe4, 0xe5, 0x13, 0x1a, 0x00, 0x95, 0x34, 0x03, 0xb7, 0x61,
0x2c, 0xdb, 0xc3, 0x15, 0x36, 0x84, 0x93, 0x7f, 0xb4, 0x5b,
};
#define AEAD_MONTE_CARLO_CHECKSUM aes_ccm_monte_carlo_checksum
#include "aead-test-template.h"
/*
* Test that for each AES-CCM nonce length, the message length is validated
* against the correct corresponding maximum message length.
*/
static void test_aes_ccm_data_len_too_large(struct kunit *test)
{
static const struct {
size_t nonce_len;
u64 max_data_len;
} lens[] = {
/* clang-format off */
{ 7, 0xffffffffffffffff }, /* U64_MAX */
{ 8, 0xffffffffffffff },
{ 9, 0xffffffffffff },
{ 10, 0xffffffffff },
{ 11, 0xffffffff },
{ 12, 0xffffff },
{ 13, 0xffff },
/* clang-format on */
};
u8 nonce[13] = {};
u8 raw_key[AES_KEYSIZE_256] = {};
int err;
struct aes_ccm_key *key = alloc_buf(test, sizeof(*key));
struct aes_ccm_ctx ctx;
err = aes_ccm_preparekey(key, raw_key, sizeof(raw_key), 16);
KUNIT_ASSERT_EQ(test, 0, err);
for (size_t i = 0; i < ARRAY_SIZE(lens); i++) {
size_t nonce_len = lens[i].nonce_len;
u64 max_data_len = lens[i].max_data_len;
/* data_len <= max_data_len should be accepted. */
err = aes_ccm_init(&ctx, 0, 0, nonce, nonce_len, key);
KUNIT_ASSERT_EQ_MSG(
test, 0, err,
"data_len=0 wasn't accepted with nonce_len=%zu",
nonce_len);
err = aes_ccm_init(&ctx, max_data_len, 0, nonce, nonce_len,
key);
KUNIT_ASSERT_EQ_MSG(
test, 0, err,
"data_len=%llu wasn't accepted with nonce_len=%zu",
max_data_len, nonce_len);
/* data_len > max_data_len should be rejected. */
if (max_data_len == U64_MAX)
continue;
err = aes_ccm_init(&ctx, max_data_len + 1, 0, nonce, nonce_len,
key);
KUNIT_ASSERT_EQ_MSG(
test, -EOVERFLOW, err,
"data_len=%llu wasn't rejected with -EOVERFLOW with nonce_len=%zu (aes_ccm_init)",
max_data_len + 1, nonce_len);
if (max_data_len + 1 <= SIZE_MAX) {
err = aes_ccm_encrypt(NULL, NULL, max_data_len + 1,
NULL, NULL, 0, nonce, nonce_len,
key);
KUNIT_ASSERT_EQ_MSG(
test, -EOVERFLOW, err,
"data_len=%llu wasn't rejected with -EOVERFLOW with nonce_len=%zu (aes_ccm_encrypt)",
max_data_len + 1, nonce_len);
err = aes_ccm_decrypt(NULL, NULL, max_data_len + 1,
NULL, NULL, 0, nonce, nonce_len,
key);
KUNIT_ASSERT_EQ_MSG(
test, -EOVERFLOW, err,
"data_len=%llu wasn't rejected with -EOVERFLOW with nonce_len=%zu (aes_ccm_decrypt)",
max_data_len + 1, nonce_len);
}
err = aes_ccm_init(&ctx, U64_MAX, 0, nonce, nonce_len, key);
KUNIT_ASSERT_EQ_MSG(
test, -EOVERFLOW, err,
"data_len=U64_MAX wasn't rejected with -EOVERFLOW with nonce_len=%zu (aes_ccm_init)",
nonce_len);
}
}
static struct kunit_case aes_ccm_test_cases[] = {
KUNIT_CASE(test_aes_ccm_test_vectors),
KUNIT_CASE(test_aes_ccm_nist_sp800_38c_example4),
KUNIT_CASE(test_aes_ccm_data_len_too_large),
AEAD_KUNIT_CASES,
{},
};
static struct kunit_suite aes_ccm_test_suite = {
.name = "aes_ccm",
.test_cases = aes_ccm_test_cases,
};
kunit_test_suite(aes_ccm_test_suite);
MODULE_DESCRIPTION("KUnit tests and benchmark for AES-CCM");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,472 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* KUnit test suite for AES-GCM
*
* Copyright 2026 Google LLC
*/
#include <crypto/aes-gcm.h>
#include <crypto/blake2s.h>
#include "test-utils.h"
/* The kernel's AES-GCM implementation supports only 12-byte nonces. */
#define AES_GCM_NONCE_LEN 12
/*
* AES-GCM test vectors from the original paper "The Galois/Counter Mode of
* Operation (GCM)" by McGrew & Viega. Vectors with nonce lengths other than 12
* bytes are excluded.
*/
static const struct aes_gcm_testvec {
const char *name;
const char *key;
size_t key_len;
const char *nonce;
size_t nonce_len;
const char *ad;
size_t ad_len;
const char *ptext;
const char *ctext;
size_t data_len;
const char *tag;
size_t tag_len;
} aes_gcm_testvecs[] = {
/* AES-128 Test Vectors */
{
.name = "McGrew & Viega Test Case 1",
.key = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
.key_len = 16,
.nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00",
.nonce_len = 12,
.ptext = "",
.ctext = "",
.data_len = 0,
.ad = "",
.ad_len = 0,
.tag = "\x58\xe2\xfc\xce\xfa\x7e\x30\x61"
"\x36\x7f\x1d\x57\xa4\xe7\x45\x5a",
.tag_len = 16,
},
{
.name = "McGrew & Viega Test Case 2",
.key = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
.key_len = 16,
.nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00",
.nonce_len = 12,
.ptext = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
.ctext = "\x03\x88\xda\xce\x60\xb6\xa3\x92"
"\xf3\x28\xc2\xb9\x71\xb2\xfe\x78",
.data_len = 16,
.ad = "",
.ad_len = 0,
.tag = "\xab\x6e\x47\xd4\x2c\xec\x13\xbd"
"\xf5\x3a\x67\xb2\x12\x57\xbd\xdf",
.tag_len = 16,
},
{
.name = "McGrew & Viega Test Case 3",
.key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
"\x6d\x6a\x8f\x94\x67\x30\x83\x08",
.key_len = 16,
.nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
"\xde\xca\xf8\x88",
.nonce_len = 12,
.ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
.ctext = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
"\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
"\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
"\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
"\x21\xd5\x14\xb2\x54\x66\x93\x1c"
"\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
"\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
"\x3d\x58\xe0\x91\x47\x3f\x59\x85",
.data_len = 64,
.ad = "",
.ad_len = 0,
.tag = "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6"
"\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4",
.tag_len = 16,
},
{
.name = "McGrew & Viega Test Case 4",
.key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
"\x6d\x6a\x8f\x94\x67\x30\x83\x08",
.key_len = 16,
.nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
"\xde\xca\xf8\x88",
.nonce_len = 12,
.ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39",
.ctext = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
"\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
"\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
"\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
"\x21\xd5\x14\xb2\x54\x66\x93\x1c"
"\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
"\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
"\x3d\x58\xe0\x91",
.data_len = 60,
.ad = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
"\xfe\xed\xfa\xce\xde\xad\xbe\xef"
"\xab\xad\xda\xd2",
.ad_len = 20,
.tag = "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb"
"\x94\xfa\xe9\x5a\xe7\x12\x1a\x47",
.tag_len = 16,
},
/* AES-192 Test Vectors */
{
.name = "McGrew & Viega Test Case 7",
.key = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
.key_len = 24,
.nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00",
.nonce_len = 12,
.ptext = "",
.ctext = "",
.data_len = 0,
.ad = "",
.ad_len = 0,
.tag = "\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b"
"\xa0\x0e\xd1\xf3\x12\x57\x24\x35",
.tag_len = 16,
},
{
.name = "McGrew & Viega Test Case 8",
.key = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
.key_len = 24,
.nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00",
.nonce_len = 12,
.ptext = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
.ctext = "\x98\xe7\x24\x7c\x07\xf0\xfe\x41"
"\x1c\x26\x7e\x43\x84\xb0\xf6\x00",
.data_len = 16,
.ad = "",
.ad_len = 0,
.tag = "\x2f\xf5\x8d\x80\x03\x39\x27\xab"
"\x8e\xf4\xd4\x58\x75\x14\xf0\xfb",
.tag_len = 16,
},
{
.name = "McGrew & Viega Test Case 9",
.key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
"\x6d\x6a\x8f\x94\x67\x30\x83\x08"
"\xfe\xff\xe9\x92\x86\x65\x73\x1c",
.key_len = 24,
.nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
"\xde\xca\xf8\x88",
.nonce_len = 12,
.ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
.ctext = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
"\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
"\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
"\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
"\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
"\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
"\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
"\xcc\xda\x27\x10\xac\xad\xe2\x56",
.data_len = 64,
.ad = "",
.ad_len = 0,
.tag = "\x99\x24\xa7\xc8\x58\x73\x36\xbf"
"\xb1\x18\x02\x4d\xb8\x67\x4a\x14",
.tag_len = 16,
},
{
.name = "McGrew & Viega Test Case 10",
.key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
"\x6d\x6a\x8f\x94\x67\x30\x83\x08"
"\xfe\xff\xe9\x92\x86\x65\x73\x1c",
.key_len = 24,
.nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
"\xde\xca\xf8\x88",
.nonce_len = 12,
.ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39",
.ctext = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
"\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
"\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
"\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
"\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
"\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
"\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
"\xcc\xda\x27\x10",
.data_len = 60,
.ad = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
"\xfe\xed\xfa\xce\xde\xad\xbe\xef"
"\xab\xad\xda\xd2",
.ad_len = 20,
.tag = "\x25\x19\x49\x8e\x80\xf1\x47\x8f"
"\x37\xba\x55\xbd\x6d\x27\x61\x8c",
.tag_len = 16,
},
/* AES-256 Test Vectors */
{
.name = "McGrew & Viega Test Case 13",
.key = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
.key_len = 32,
.nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00",
.nonce_len = 12,
.ptext = "",
.ctext = "",
.data_len = 0,
.ad = "",
.ad_len = 0,
.tag = "\x53\x0f\x8a\xfb\xc7\x45\x36\xb9"
"\xa9\x63\xb4\xf1\xc4\xcb\x73\x8b",
.tag_len = 16,
},
{
.name = "McGrew & Viega Test Case 14",
.key = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
.key_len = 32,
.nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00",
.nonce_len = 12,
.ptext = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
.ctext = "\xce\xa7\x40\x3d\x4d\x60\x6b\x6e"
"\x07\x4e\xc5\xd3\xba\xf3\x9d\x18",
.data_len = 16,
.ad = "",
.ad_len = 0,
.tag = "\xd0\xd1\xc8\xa7\x99\x99\x6b\xf0"
"\x26\x5b\x98\xb5\xd4\x8a\xb9\x19",
.tag_len = 16,
},
{
.name = "McGrew & Viega Test Case 15",
.key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
"\x6d\x6a\x8f\x94\x67\x30\x83\x08"
"\xfe\xff\xe9\x92\x86\x65\x73\x1c"
"\x6d\x6a\x8f\x94\x67\x30\x83\x08",
.key_len = 32,
.nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
"\xde\xca\xf8\x88",
.nonce_len = 12,
.ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
.ctext = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
"\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
"\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
"\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
"\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
"\xa7\xb0\x8b\x10\x56\x82\x88\x38"
"\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
"\xbc\xc9\xf6\x62\x89\x80\x15\xad",
.data_len = 64,
.ad = "",
.ad_len = 0,
.tag = "\xb0\x94\xda\xc5\xd9\x34\x71\xbd"
"\xec\x1a\x50\x22\x70\xe3\xcc\x6c",
.tag_len = 16,
},
{
.name = "McGrew & Viega Test Case 16",
.key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
"\x6d\x6a\x8f\x94\x67\x30\x83\x08"
"\xfe\xff\xe9\x92\x86\x65\x73\x1c"
"\x6d\x6a\x8f\x94\x67\x30\x83\x08",
.key_len = 32,
.nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
"\xde\xca\xf8\x88",
.nonce_len = 12,
.ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
"\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
"\x1c\x3c\x0c\x95\x95\x68\x09\x53"
"\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39",
.ctext = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
"\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
"\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
"\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
"\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
"\xa7\xb0\x8b\x10\x56\x82\x88\x38"
"\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
"\xbc\xc9\xf6\x62",
.data_len = 60,
.ad = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
"\xfe\xed\xfa\xce\xde\xad\xbe\xef"
"\xab\xad\xda\xd2",
.ad_len = 20,
.tag = "\x76\xfc\x6e\xce\x0f\x4e\x17\x68"
"\xcd\xdf\x88\x53\xbb\x2d\x55\x1b",
.tag_len = 16,
},
};
static void test_aes_gcm_one_test_vector(struct kunit *test,
const struct aes_gcm_testvec *tv)
{
u8 *ctext = alloc_buf(test, tv->data_len);
u8 *decrypted = alloc_buf(test, tv->data_len);
u8 *tag = alloc_buf(test, tv->tag_len);
struct aes_gcm_key key;
int err;
KUNIT_ASSERT_EQ(test, AES_GCM_NONCE_LEN, tv->nonce_len);
err = aes_gcm_preparekey(&key, tv->key, tv->key_len, tv->tag_len);
KUNIT_ASSERT_EQ_MSG(test, 0, err, "Failed to prepare key for %s",
tv->name);
aes_gcm_encrypt(ctext, tv->ptext, tv->data_len, tag, tv->ad, tv->ad_len,
tv->nonce, &key);
KUNIT_ASSERT_MEMEQ_MSG(test, tv->ctext, ctext, tv->data_len,
"Wrong ciphertext for %s", tv->name);
KUNIT_ASSERT_MEMEQ_MSG(test, tag, tv->tag, tv->tag_len,
"Wrong tag for %s", tv->name);
err = aes_gcm_decrypt(decrypted, ctext, tv->data_len, tag, tv->ad,
tv->ad_len, tv->nonce, &key);
KUNIT_ASSERT_EQ_MSG(test, 0, err, "Decryption failed for %s", tv->name);
KUNIT_ASSERT_MEMEQ_MSG(test, tv->ptext, decrypted, tv->data_len,
"Wrong plaintext for %s", tv->name);
}
static void test_aes_gcm_test_vectors(struct kunit *test)
{
for (size_t i = 0; i < ARRAY_SIZE(aes_gcm_testvecs); i++)
test_aes_gcm_one_test_vector(test, &aes_gcm_testvecs[i]);
}
static int aes_gcm_init_test(struct aes_gcm_ctx *ctx, u64 data_len, u64 ad_len,
const u8 *nonce, size_t nonce_len,
const struct aes_gcm_key *key)
{
if (nonce_len != AES_GCM_NONCE_LEN)
return -EINVAL;
/*
* Ignore data_len and ad_len. Incremental AES-GCM doesn't need them at
* initialization time.
*/
aes_gcm_init(ctx, nonce, key);
return 0;
}
static int aes_gcm_encrypt_test(u8 *dst, const u8 *src, size_t data_len,
u8 *authtag, const u8 *ad, size_t ad_len,
const u8 *nonce, size_t nonce_len,
const struct aes_gcm_key *key)
{
if (nonce_len != AES_GCM_NONCE_LEN)
return -EINVAL;
/* aes_gcm_encrypt() returns void. */
aes_gcm_encrypt(dst, src, data_len, authtag, ad, ad_len, nonce, key);
return 0;
}
static int aes_gcm_decrypt_test(u8 *dst, const u8 *src, size_t data_len,
const u8 *authtag, const u8 *ad, size_t ad_len,
const u8 *nonce, size_t nonce_len,
const struct aes_gcm_key *key)
{
if (nonce_len != AES_GCM_NONCE_LEN)
return -EINVAL;
return aes_gcm_decrypt(dst, src, data_len, authtag, ad, ad_len, nonce,
key);
}
static const size_t aes_gcm_valid_key_lens[] = { 16, 24, 32 };
#define AEAD_MAX_KEY_LEN 32
#define AEAD_VALID_KEY_LENS aes_gcm_valid_key_lens
static const size_t aes_gcm_valid_nonce_lens[] = { AES_GCM_NONCE_LEN };
#define AEAD_MAX_NONCE_LEN AES_GCM_NONCE_LEN
#define AEAD_VALID_NONCE_LENS aes_gcm_valid_nonce_lens
static const size_t aes_gcm_valid_tag_lens[] = { 4, 8, 12, 13, 14, 15, 16 };
#define AEAD_MAX_TAG_LEN 16
#define AEAD_VALID_TAG_LENS aes_gcm_valid_tag_lens
#define AEAD_KEY aes_gcm_key
#define AEAD_CTX aes_gcm_ctx
#define AEAD_PREPAREKEY aes_gcm_preparekey
#define AEAD_ENCRYPT aes_gcm_encrypt_test
#define AEAD_DECRYPT aes_gcm_decrypt_test
#define AEAD_INIT aes_gcm_init_test
#define AEAD_AUTH_UPDATE aes_gcm_auth_update
#define AEAD_ENCRYPT_UPDATE aes_gcm_encrypt_update
#define AEAD_DECRYPT_UPDATE aes_gcm_decrypt_update
#define AEAD_ENCRYPT_FINAL aes_gcm_encrypt_final
#define AEAD_DECRYPT_FINAL aes_gcm_decrypt_final
/* This value was generated by gen-aead-testvecs.py. */
static const u8 aes_gcm_monte_carlo_checksum[BLAKE2S_HASH_SIZE] = {
0x6d, 0xd0, 0x6e, 0x6b, 0xde, 0x3e, 0x92, 0x9f, 0xae, 0x1f, 0xf1,
0x84, 0x99, 0x5a, 0x9e, 0x7b, 0xfe, 0x20, 0x9e, 0x22, 0x7c, 0x5f,
0x15, 0xb3, 0x59, 0x89, 0xd0, 0xb7, 0x74, 0x5d, 0xd2, 0xa5,
};
#define AEAD_MONTE_CARLO_CHECKSUM aes_gcm_monte_carlo_checksum
#include "aead-test-template.h"
static struct kunit_case aes_gcm_test_cases[] = {
KUNIT_CASE(test_aes_gcm_test_vectors),
AEAD_KUNIT_CASES,
{},
};
static struct kunit_suite aes_gcm_test_suite = {
.name = "aes_gcm",
.test_cases = aes_gcm_test_cases,
};
kunit_test_suite(aes_gcm_test_suite);
MODULE_DESCRIPTION("KUnit tests and benchmark for AES-GCM");
MODULE_LICENSE("GPL");

View File

@@ -41,9 +41,9 @@ static void blake2b_init_default(struct blake2b_ctx *ctx)
static void test_blake2b_all_key_and_hash_lens(struct kunit *test)
{
const size_t data_len = 100;
u8 *data = &test_buf[0];
u8 *key = data + data_len;
u8 *hash = key + BLAKE2B_KEY_SIZE;
u8 *data = alloc_buf(test, data_len);
u8 *key = alloc_buf(test, BLAKE2B_KEY_SIZE);
u8 *hash = alloc_buf(test, BLAKE2B_HASH_SIZE);
struct blake2b_ctx main_ctx;
u8 main_hash[BLAKE2B_HASH_SIZE];
@@ -68,11 +68,13 @@ static void test_blake2b_all_key_and_hash_lens(struct kunit *test)
static void test_blake2b_with_guarded_key_buf(struct kunit *test)
{
const size_t data_len = 100;
u8 *data = alloc_buf(test, data_len);
u8 *guarded_key_buf = alloc_guarded_buf(test, BLAKE2B_KEY_SIZE);
rand_bytes(test_buf, data_len);
rand_bytes(data, data_len);
for (int key_len = 0; key_len <= BLAKE2B_KEY_SIZE; key_len++) {
u8 key[BLAKE2B_KEY_SIZE];
u8 *guarded_key = &test_buf[TEST_BUF_LEN - key_len];
u8 *guarded_key = &guarded_key_buf[BLAKE2B_KEY_SIZE - key_len];
u8 hash1[BLAKE2B_HASH_SIZE];
u8 hash2[BLAKE2B_HASH_SIZE];
struct blake2b_ctx ctx;
@@ -80,14 +82,13 @@ static void test_blake2b_with_guarded_key_buf(struct kunit *test)
rand_bytes(key, key_len);
memcpy(guarded_key, key, key_len);
blake2b(key, key_len, test_buf, data_len,
hash1, BLAKE2B_HASH_SIZE);
blake2b(guarded_key, key_len, test_buf, data_len,
hash2, BLAKE2B_HASH_SIZE);
blake2b(key, key_len, data, data_len, hash1, BLAKE2B_HASH_SIZE);
blake2b(guarded_key, key_len, data, data_len, hash2,
BLAKE2B_HASH_SIZE);
KUNIT_ASSERT_MEMEQ(test, hash1, hash2, BLAKE2B_HASH_SIZE);
blake2b_init_key(&ctx, BLAKE2B_HASH_SIZE, guarded_key, key_len);
blake2b_update(&ctx, test_buf, data_len);
blake2b_update(&ctx, data, data_len);
blake2b_final(&ctx, hash2);
KUNIT_ASSERT_MEMEQ(test, hash1, hash2, BLAKE2B_HASH_SIZE);
}
@@ -100,14 +101,16 @@ static void test_blake2b_with_guarded_key_buf(struct kunit *test)
static void test_blake2b_with_guarded_out_buf(struct kunit *test)
{
const size_t data_len = 100;
u8 *data = alloc_buf(test, data_len);
u8 *out_buf = alloc_guarded_buf(test, BLAKE2B_HASH_SIZE);
rand_bytes(test_buf, data_len);
rand_bytes(data, data_len);
for (int out_len = 1; out_len <= BLAKE2B_HASH_SIZE; out_len++) {
u8 hash[BLAKE2B_HASH_SIZE];
u8 *guarded_hash = &test_buf[TEST_BUF_LEN - out_len];
u8 *guarded_hash = &out_buf[BLAKE2B_HASH_SIZE - out_len];
blake2b(NULL, 0, test_buf, data_len, hash, out_len);
blake2b(NULL, 0, test_buf, data_len, guarded_hash, out_len);
blake2b(NULL, 0, data, data_len, hash, out_len);
blake2b(NULL, 0, data, data_len, guarded_hash, out_len);
KUNIT_ASSERT_MEMEQ(test, hash, guarded_hash, out_len);
}
}
@@ -124,8 +127,6 @@ static struct kunit_case blake2b_test_cases[] = {
static struct kunit_suite blake2b_test_suite = {
.name = "blake2b",
.test_cases = blake2b_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(blake2b_test_suite);

View File

@@ -41,9 +41,9 @@ static void blake2s_init_default(struct blake2s_ctx *ctx)
static void test_blake2s_all_key_and_hash_lens(struct kunit *test)
{
const size_t data_len = 100;
u8 *data = &test_buf[0];
u8 *key = data + data_len;
u8 *hash = key + BLAKE2S_KEY_SIZE;
u8 *data = alloc_buf(test, data_len);
u8 *key = alloc_buf(test, BLAKE2S_KEY_SIZE);
u8 *hash = alloc_buf(test, BLAKE2S_HASH_SIZE);
struct blake2s_ctx main_ctx;
u8 main_hash[BLAKE2S_HASH_SIZE];
@@ -68,11 +68,13 @@ static void test_blake2s_all_key_and_hash_lens(struct kunit *test)
static void test_blake2s_with_guarded_key_buf(struct kunit *test)
{
const size_t data_len = 100;
u8 *data = alloc_buf(test, data_len);
u8 *guarded_key_buf = alloc_guarded_buf(test, BLAKE2S_KEY_SIZE);
rand_bytes(test_buf, data_len);
rand_bytes(data, data_len);
for (int key_len = 0; key_len <= BLAKE2S_KEY_SIZE; key_len++) {
u8 key[BLAKE2S_KEY_SIZE];
u8 *guarded_key = &test_buf[TEST_BUF_LEN - key_len];
u8 *guarded_key = &guarded_key_buf[BLAKE2S_KEY_SIZE - key_len];
u8 hash1[BLAKE2S_HASH_SIZE];
u8 hash2[BLAKE2S_HASH_SIZE];
struct blake2s_ctx ctx;
@@ -80,14 +82,13 @@ static void test_blake2s_with_guarded_key_buf(struct kunit *test)
rand_bytes(key, key_len);
memcpy(guarded_key, key, key_len);
blake2s(key, key_len, test_buf, data_len,
hash1, BLAKE2S_HASH_SIZE);
blake2s(guarded_key, key_len, test_buf, data_len,
hash2, BLAKE2S_HASH_SIZE);
blake2s(key, key_len, data, data_len, hash1, BLAKE2S_HASH_SIZE);
blake2s(guarded_key, key_len, data, data_len, hash2,
BLAKE2S_HASH_SIZE);
KUNIT_ASSERT_MEMEQ(test, hash1, hash2, BLAKE2S_HASH_SIZE);
blake2s_init_key(&ctx, BLAKE2S_HASH_SIZE, guarded_key, key_len);
blake2s_update(&ctx, test_buf, data_len);
blake2s_update(&ctx, data, data_len);
blake2s_final(&ctx, hash2);
KUNIT_ASSERT_MEMEQ(test, hash1, hash2, BLAKE2S_HASH_SIZE);
}
@@ -100,14 +101,16 @@ static void test_blake2s_with_guarded_key_buf(struct kunit *test)
static void test_blake2s_with_guarded_out_buf(struct kunit *test)
{
const size_t data_len = 100;
u8 *data = alloc_buf(test, data_len);
u8 *out_buf = alloc_guarded_buf(test, BLAKE2S_HASH_SIZE);
rand_bytes(test_buf, data_len);
rand_bytes(data, data_len);
for (int out_len = 1; out_len <= BLAKE2S_HASH_SIZE; out_len++) {
u8 hash[BLAKE2S_HASH_SIZE];
u8 *guarded_hash = &test_buf[TEST_BUF_LEN - out_len];
u8 *guarded_hash = &out_buf[BLAKE2S_HASH_SIZE - out_len];
blake2s(NULL, 0, test_buf, data_len, hash, out_len);
blake2s(NULL, 0, test_buf, data_len, guarded_hash, out_len);
blake2s(NULL, 0, data, data_len, hash, out_len);
blake2s(NULL, 0, data, data_len, guarded_hash, out_len);
KUNIT_ASSERT_MEMEQ(test, hash, guarded_hash, out_len);
}
}
@@ -124,8 +127,6 @@ static struct kunit_case blake2s_test_cases[] = {
static struct kunit_suite blake2s_test_suite = {
.name = "blake2s",
.test_cases = blake2s_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(blake2s_test_suite);

View File

@@ -11,7 +11,7 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include "test-utils.h"
struct chacha20poly1305_testvec {
const u8 *input, *output, *assoc, *nonce, *key;
@@ -8890,11 +8890,8 @@ static void test_chacha20poly1305(struct kunit *test)
bool ret;
struct scatterlist sg_src[3];
computed_output = kunit_kmalloc(test, MAXIMUM_TEST_BUFFER_LEN,
GFP_KERNEL);
input = kunit_kmalloc(test, MAXIMUM_TEST_BUFFER_LEN, GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, computed_output);
KUNIT_ASSERT_NOT_NULL(test, input);
computed_output = alloc_buf(test, MAXIMUM_TEST_BUFFER_LEN);
input = alloc_buf(test, MAXIMUM_TEST_BUFFER_LEN);
for (i = 0; i < ARRAY_SIZE(chacha20poly1305_enc_vectors); ++i) {
memset(computed_output, 0, MAXIMUM_TEST_BUFFER_LEN);

View File

@@ -39,17 +39,18 @@ static void ghash_withtestkey(const u8 *data, size_t len,
*/
static void test_ghash_allones_key_and_message(struct kunit *test)
{
const size_t max_len = 4096;
u8 *data = alloc_buf(test, max_len);
struct ghash_key key;
struct ghash_ctx hashofhashes_ctx;
u8 hash[GHASH_BLOCK_SIZE];
static_assert(TEST_BUF_LEN >= 4096);
memset(test_buf, 0xff, 4096);
memset(data, 0xff, max_len);
ghash_preparekey(&key, test_buf);
ghash_preparekey(&key, data);
ghash_init(&hashofhashes_ctx, &key);
for (size_t len = 0; len <= 4096; len += 16) {
ghash(&key, test_buf, len, hash);
for (size_t len = 0; len <= max_len; len += 16) {
ghash(&key, data, len, hash);
ghash_update(&hashofhashes_ctx, hash, sizeof(hash));
}
ghash_final(&hashofhashes_ctx, hash);
@@ -68,7 +69,7 @@ static void check_key_consistency(struct kunit *test,
const struct ghash_key *key1,
const struct ghash_key *key2)
{
u8 *data = test_buf;
u8 *data = alloc_buf(test, MAX_LEN_FOR_KEY_CHECK);
u8 hash1[GHASH_BLOCK_SIZE];
u8 hash2[GHASH_BLOCK_SIZE];
@@ -88,10 +89,10 @@ static void check_key_consistency(struct kunit *test,
static void test_ghash_with_guarded_key(struct kunit *test)
{
u8 raw_key[GHASH_BLOCK_SIZE];
u8 *guarded_raw_key = &test_buf[TEST_BUF_LEN - sizeof(raw_key)];
u8 *guarded_raw_key = alloc_guarded_buf(test, sizeof(raw_key));
struct ghash_key key1, key2;
struct ghash_key *guarded_key =
(struct ghash_key *)&test_buf[TEST_BUF_LEN - sizeof(key1)];
alloc_guarded_buf(test, sizeof(*guarded_key));
/* Prepare with regular buffers. */
rand_bytes(raw_key, sizeof(raw_key));
@@ -116,14 +117,14 @@ static void test_ghash_with_minimally_aligned_key(struct kunit *test)
{
u8 raw_key[GHASH_BLOCK_SIZE];
struct ghash_key key;
const size_t align = __alignof__(struct ghash_key);
u8 *key_buf = alloc_buf(test, sizeof(struct ghash_key) + 3 * align);
struct ghash_key *minaligned_key =
(struct ghash_key *)&test_buf[MAX_LEN_FOR_KEY_CHECK +
__alignof__(struct ghash_key)];
(struct ghash_key *)(PTR_ALIGN(key_buf, 2 * align) + align);
KUNIT_ASSERT_TRUE(test, IS_ALIGNED((uintptr_t)minaligned_key,
__alignof__(struct ghash_key)));
KUNIT_ASSERT_TRUE(test, !IS_ALIGNED((uintptr_t)minaligned_key,
2 * __alignof__(struct ghash_key)));
KUNIT_ASSERT_TRUE(test, IS_ALIGNED((uintptr_t)minaligned_key, align));
KUNIT_ASSERT_TRUE(test,
!IS_ALIGNED((uintptr_t)minaligned_key, 2 * align));
rand_bytes(raw_key, sizeof(raw_key));
ghash_preparekey(&key, raw_key);
@@ -164,12 +165,7 @@ static int ghash_suite_init(struct kunit_suite *suite)
rand_bytes_seeded_from_len(raw_key, sizeof(raw_key));
ghash_preparekey(&test_key, raw_key);
return hash_suite_init(suite);
}
static void ghash_suite_exit(struct kunit_suite *suite)
{
hash_suite_exit(suite);
return 0;
}
static struct kunit_case ghash_test_cases[] = {
@@ -186,7 +182,6 @@ static struct kunit_suite ghash_test_suite = {
.name = "ghash",
.test_cases = ghash_test_cases,
.suite_init = ghash_suite_init,
.suite_exit = ghash_suite_exit,
};
kunit_test_suite(ghash_test_suite);

View File

@@ -7,93 +7,7 @@
*/
#include <kunit/run-in-irq-context.h>
#include <kunit/test.h>
#include <linux/vmalloc.h>
/* test_buf is a guarded buffer, i.e. &test_buf[TEST_BUF_LEN] is not mapped. */
#define TEST_BUF_LEN 16384
static u8 *test_buf;
static u8 *orig_test_buf;
static u64 random_seed;
/*
* This is a simple linear congruential generator. It is used only for testing,
* which does not require cryptographically secure random numbers. A hard-coded
* algorithm is used instead of <linux/prandom.h> so that it matches the
* algorithm used by the test vector generation script. This allows the input
* data in random test vectors to be concisely stored as just the seed.
*/
static u32 rand32(void)
{
random_seed = (random_seed * 25214903917 + 11) & ((1ULL << 48) - 1);
return random_seed >> 16;
}
static void rand_bytes(u8 *out, size_t len)
{
for (size_t i = 0; i < len; i++)
out[i] = rand32();
}
static void rand_bytes_seeded_from_len(u8 *out, size_t len)
{
random_seed = len;
rand_bytes(out, len);
}
static bool rand_bool(void)
{
return rand32() % 2;
}
/* Generate a random length, preferring small lengths. */
static size_t rand_length(size_t max_len)
{
size_t len;
switch (rand32() % 3) {
case 0:
len = rand32() % 128;
break;
case 1:
len = rand32() % 3072;
break;
default:
len = rand32();
break;
}
return len % (max_len + 1);
}
static size_t rand_offset(size_t max_offset)
{
return min(rand32() % 128, max_offset);
}
static int hash_suite_init(struct kunit_suite *suite)
{
/*
* Allocate the test buffer using vmalloc() with a page-aligned length
* so that it is immediately followed by a guard page. This allows
* buffer overreads to be detected, even in assembly code.
*/
size_t alloc_len = round_up(TEST_BUF_LEN, PAGE_SIZE);
orig_test_buf = vmalloc(alloc_len);
if (!orig_test_buf)
return -ENOMEM;
test_buf = orig_test_buf + alloc_len - TEST_BUF_LEN;
return 0;
}
static void hash_suite_exit(struct kunit_suite *suite)
{
vfree(orig_test_buf);
orig_test_buf = NULL;
test_buf = NULL;
}
#include "test-utils.h"
/*
* Test the hash function against a list of test vectors.
@@ -104,14 +18,16 @@ static void hash_suite_exit(struct kunit_suite *suite)
*/
static void test_hash_test_vectors(struct kunit *test)
{
const size_t max_len = 16384;
u8 *data = alloc_buf(test, max_len);
for (size_t i = 0; i < ARRAY_SIZE(hash_testvecs); i++) {
size_t data_len = hash_testvecs[i].data_len;
u8 actual_hash[HASH_SIZE];
KUNIT_ASSERT_LE(test, data_len, TEST_BUF_LEN);
rand_bytes_seeded_from_len(test_buf, data_len);
HASH(test_buf, data_len, actual_hash);
KUNIT_ASSERT_LE(test, data_len, max_len);
rand_bytes_seeded_from_len(data, data_len);
HASH(data, data_len, actual_hash);
KUNIT_ASSERT_MEMEQ_MSG(
test, actual_hash, hash_testvecs[i].digest, HASH_SIZE,
"Wrong result with test vector %zu; data_len=%zu", i,
@@ -127,14 +43,15 @@ static void test_hash_test_vectors(struct kunit *test)
*/
static void test_hash_all_lens_up_to_4096(struct kunit *test)
{
const size_t max_len = 4096;
u8 *data = alloc_buf(test, max_len);
struct HASH_CTX ctx;
u8 hash[HASH_SIZE];
static_assert(TEST_BUF_LEN >= 4096);
rand_bytes_seeded_from_len(test_buf, 4096);
rand_bytes_seeded_from_len(data, max_len);
HASH_INIT(&ctx);
for (size_t len = 0; len <= 4096; len++) {
HASH(test_buf, len, hash);
for (size_t len = 0; len <= max_len; len++) {
HASH(data, len, hash);
HASH_UPDATE(&ctx, hash, HASH_SIZE);
}
HASH_FINAL(&ctx, hash);
@@ -147,6 +64,9 @@ static void test_hash_all_lens_up_to_4096(struct kunit *test)
*/
static void test_hash_incremental_updates(struct kunit *test)
{
const size_t max_len = 16384;
u8 *data = alloc_guarded_buf(test, max_len);
for (int i = 0; i < 1000; i++) {
size_t total_len, offset;
struct HASH_CTX ctx;
@@ -155,12 +75,12 @@ static void test_hash_incremental_updates(struct kunit *test)
size_t num_parts = 0;
size_t remaining_len, cur_offset;
total_len = rand_length(TEST_BUF_LEN);
offset = rand_offset(TEST_BUF_LEN - total_len);
rand_bytes(&test_buf[offset], total_len);
total_len = rand_length(max_len);
offset = rand_offset(max_len - total_len);
rand_bytes(&data[offset], total_len);
/* Compute the hash value in one shot. */
HASH(&test_buf[offset], total_len, hash1);
HASH(&data[offset], total_len, hash1);
/*
* Compute the hash value incrementally, using a randomly
@@ -172,13 +92,13 @@ static void test_hash_incremental_updates(struct kunit *test)
while (rand_bool()) {
size_t part_len = rand_length(remaining_len);
HASH_UPDATE(&ctx, &test_buf[cur_offset], part_len);
HASH_UPDATE(&ctx, &data[cur_offset], part_len);
num_parts++;
cur_offset += part_len;
remaining_len -= part_len;
}
if (remaining_len != 0 || rand_bool()) {
HASH_UPDATE(&ctx, &test_buf[cur_offset], remaining_len);
HASH_UPDATE(&ctx, &data[cur_offset], remaining_len);
num_parts++;
}
HASH_FINAL(&ctx, hash2);
@@ -197,11 +117,13 @@ static void test_hash_incremental_updates(struct kunit *test)
*/
static void test_hash_buffer_overruns(struct kunit *test)
{
const size_t max_tested_len = TEST_BUF_LEN - sizeof(struct HASH_CTX);
void *const buf_end = &test_buf[TEST_BUF_LEN];
const size_t buf_len = 16384;
u8 *buf = alloc_guarded_buf(test, buf_len);
void *const buf_end = &buf[buf_len];
const size_t max_tested_len = buf_len - sizeof(struct HASH_CTX);
struct HASH_CTX *guarded_ctx = buf_end - sizeof(*guarded_ctx);
rand_bytes(test_buf, TEST_BUF_LEN);
rand_bytes(buf, buf_len);
for (int i = 0; i < 100; i++) {
size_t len = rand_length(max_tested_len);
@@ -215,14 +137,14 @@ static void test_hash_buffer_overruns(struct kunit *test)
HASH_FINAL(&ctx, hash);
/* Check for overruns of the hash value buffer. */
HASH(test_buf, len, buf_end - HASH_SIZE);
HASH(buf, len, buf_end - HASH_SIZE);
HASH_INIT(&ctx);
HASH_UPDATE(&ctx, test_buf, len);
HASH_UPDATE(&ctx, buf, len);
HASH_FINAL(&ctx, buf_end - HASH_SIZE);
/* Check for overuns of the hash context. */
/* Check for overruns of the hash context. */
HASH_INIT(guarded_ctx);
HASH_UPDATE(guarded_ctx, test_buf, len);
HASH_UPDATE(guarded_ctx, buf, len);
HASH_FINAL(guarded_ctx, hash);
}
}
@@ -233,30 +155,32 @@ static void test_hash_buffer_overruns(struct kunit *test)
*/
static void test_hash_overlaps(struct kunit *test)
{
const size_t max_tested_len = TEST_BUF_LEN - HASH_SIZE;
const size_t buf_len = 16384;
u8 *buf = alloc_guarded_buf(test, buf_len);
const size_t max_tested_len = buf_len - HASH_SIZE;
struct HASH_CTX ctx;
u8 hash[HASH_SIZE];
rand_bytes(test_buf, TEST_BUF_LEN);
rand_bytes(buf, buf_len);
for (int i = 0; i < 100; i++) {
size_t len = rand_length(max_tested_len);
size_t offset = HASH_SIZE + rand_offset(max_tested_len - len);
bool left_end = rand_bool();
u8 *ovl_hash = left_end ? &test_buf[offset] :
&test_buf[offset + len - HASH_SIZE];
u8 *ovl_hash = left_end ? &buf[offset] :
&buf[offset + len - HASH_SIZE];
HASH(&test_buf[offset], len, hash);
HASH(&test_buf[offset], len, ovl_hash);
HASH(&buf[offset], len, hash);
HASH(&buf[offset], len, ovl_hash);
KUNIT_ASSERT_MEMEQ_MSG(
test, hash, ovl_hash, HASH_SIZE,
"Overlap test 1 failed with len=%zu offset=%zu left_end=%d",
len, offset, left_end);
/* Repeat the above test, but this time use init+update+final */
HASH(&test_buf[offset], len, hash);
HASH(&buf[offset], len, hash);
HASH_INIT(&ctx);
HASH_UPDATE(&ctx, &test_buf[offset], len);
HASH_UPDATE(&ctx, &buf[offset], len);
HASH_FINAL(&ctx, ovl_hash);
KUNIT_ASSERT_MEMEQ_MSG(
test, hash, ovl_hash, HASH_SIZE,
@@ -264,10 +188,10 @@ static void test_hash_overlaps(struct kunit *test)
len, offset, left_end);
/* Test modifying the source data after it was used. */
HASH(&test_buf[offset], len, hash);
HASH(&buf[offset], len, hash);
HASH_INIT(&ctx);
HASH_UPDATE(&ctx, &test_buf[offset], len);
rand_bytes(&test_buf[offset], len);
HASH_UPDATE(&ctx, &buf[offset], len);
rand_bytes(&buf[offset], len);
HASH_FINAL(&ctx, ovl_hash);
KUNIT_ASSERT_MEMEQ_MSG(
test, hash, ovl_hash, HASH_SIZE,
@@ -282,20 +206,22 @@ static void test_hash_overlaps(struct kunit *test)
*/
static void test_hash_alignment_consistency(struct kunit *test)
{
const size_t max_len = 16384;
u8 *data = alloc_guarded_buf(test, max_len);
u8 hash1[128 + HASH_SIZE];
u8 hash2[128 + HASH_SIZE];
for (int i = 0; i < 100; i++) {
size_t len = rand_length(TEST_BUF_LEN);
size_t data_offs1 = rand_offset(TEST_BUF_LEN - len);
size_t data_offs2 = rand_offset(TEST_BUF_LEN - len);
size_t len = rand_length(max_len);
size_t data_offs1 = rand_offset(max_len - len);
size_t data_offs2 = rand_offset(max_len - len);
size_t hash_offs1 = rand_offset(128);
size_t hash_offs2 = rand_offset(128);
rand_bytes(&test_buf[data_offs1], len);
HASH(&test_buf[data_offs1], len, &hash1[hash_offs1]);
memmove(&test_buf[data_offs2], &test_buf[data_offs1], len);
HASH(&test_buf[data_offs2], len, &hash2[hash_offs2]);
rand_bytes(&data[data_offs1], len);
HASH(&data[data_offs1], len, &hash1[hash_offs1]);
memmove(&data[data_offs2], &data[data_offs1], len);
HASH(&data[data_offs2], len, &hash2[hash_offs2]);
KUNIT_ASSERT_MEMEQ_MSG(
test, &hash1[hash_offs1], &hash2[hash_offs2], HASH_SIZE,
"Alignment consistency test failed with len=%zu data_offs=(%zu,%zu) hash_offs=(%zu,%zu)",
@@ -308,11 +234,14 @@ static void test_hash_ctx_zeroization(struct kunit *test)
{
static const u8 zeroes[sizeof(struct HASH_CTX)];
struct HASH_CTX ctx;
const size_t data_len = 128;
u8 *data = alloc_buf(test, data_len);
u8 hash[HASH_SIZE];
rand_bytes(test_buf, 128);
rand_bytes(data, data_len);
HASH_INIT(&ctx);
HASH_UPDATE(&ctx, test_buf, 128);
HASH_FINAL(&ctx, test_buf);
HASH_UPDATE(&ctx, data, data_len);
HASH_FINAL(&ctx, hash);
KUNIT_ASSERT_MEMEQ_MSG(test, &ctx, zeroes, sizeof(ctx),
"Hash context was not zeroized by finalization");
}
@@ -321,6 +250,7 @@ static void test_hash_ctx_zeroization(struct kunit *test)
#define IRQ_TEST_NUM_BUFFERS 3 /* matches max concurrency level */
struct hash_irq_test1_state {
u8 *data;
u8 expected_hashes[IRQ_TEST_NUM_BUFFERS][HASH_SIZE];
atomic_t seqno;
};
@@ -336,7 +266,8 @@ static bool hash_irq_test1_func(void *state_)
u32 i = (u32)atomic_inc_return(&state->seqno) % IRQ_TEST_NUM_BUFFERS;
u8 actual_hash[HASH_SIZE];
HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN, actual_hash);
HASH(&state->data[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN,
actual_hash);
return memcmp(actual_hash, state->expected_hashes[i], HASH_SIZE) == 0;
}
@@ -346,12 +277,14 @@ static bool hash_irq_test1_func(void *state_)
*/
static void test_hash_interrupt_context_1(struct kunit *test)
{
const size_t total_data_len = IRQ_TEST_NUM_BUFFERS * IRQ_TEST_DATA_LEN;
struct hash_irq_test1_state state = {};
/* Prepare some test messages and compute the expected hash of each. */
rand_bytes(test_buf, IRQ_TEST_NUM_BUFFERS * IRQ_TEST_DATA_LEN);
state.data = alloc_buf(test, total_data_len);
rand_bytes(state.data, total_data_len);
for (int i = 0; i < IRQ_TEST_NUM_BUFFERS; i++)
HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN,
HASH(&state.data[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN,
state.expected_hashes[i]);
kunit_run_irq_test(test, hash_irq_test1_func, 100000, &state);
@@ -365,6 +298,8 @@ struct hash_irq_test2_hash_ctx {
};
struct hash_irq_test2_state {
u8 *data;
size_t data_len;
struct hash_irq_test2_hash_ctx ctxs[IRQ_TEST_NUM_BUFFERS];
u8 expected_hash[HASH_SIZE];
u16 update_lens[32];
@@ -397,7 +332,7 @@ static bool hash_irq_test2_func(void *state_)
ctx->step++;
} else if (ctx->step < state->num_steps - 1) {
/* Update step */
HASH_UPDATE(&ctx->hash_ctx, &test_buf[ctx->offset],
HASH_UPDATE(&ctx->hash_ctx, &state->data[ctx->offset],
state->update_lens[ctx->step - 1]);
ctx->offset += state->update_lens[ctx->step - 1];
ctx->step++;
@@ -405,7 +340,7 @@ static bool hash_irq_test2_func(void *state_)
/* Final step */
u8 actual_hash[HASH_SIZE];
if (WARN_ON_ONCE(ctx->offset != TEST_BUF_LEN))
if (WARN_ON_ONCE(ctx->offset != state->data_len))
ret = false;
HASH_FINAL(&ctx->hash_ctx, actual_hash);
if (memcmp(actual_hash, state->expected_hash, HASH_SIZE) != 0)
@@ -426,20 +361,23 @@ static bool hash_irq_test2_func(void *state_)
*/
static void test_hash_interrupt_context_2(struct kunit *test)
{
const size_t data_len = 16384;
struct hash_irq_test2_state *state;
int remaining = TEST_BUF_LEN;
size_t remaining = data_len;
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, state);
state->data_len = data_len;
state->data = alloc_buf(test, data_len);
rand_bytes(test_buf, TEST_BUF_LEN);
HASH(test_buf, TEST_BUF_LEN, state->expected_hash);
rand_bytes(state->data, data_len);
HASH(state->data, data_len, state->expected_hash);
/*
* Generate a list of update lengths to use. Ensure that it contains
* multiple entries but is limited to a maximum length.
*/
static_assert(TEST_BUF_LEN / 4096 > 1);
KUNIT_ASSERT_GT(test, data_len / 4096, 1);
for (state->num_steps = 0;
state->num_steps < ARRAY_SIZE(state->update_lens) - 1 && remaining;
state->num_steps++) {
@@ -485,21 +423,23 @@ static void test_hash_interrupt_context_2(struct kunit *test)
*/
static void test_hmac(struct kunit *test)
{
const size_t max_data_len = 4096;
const size_t max_key_len = 293;
const size_t outer_key_len = 32;
u8 *data = alloc_guarded_buf(test, max_data_len);
u8 *raw_key = alloc_guarded_buf(test, max_key_len);
static const u8 zeroes[sizeof(struct HMAC_CTX)];
u8 *raw_key;
struct HMAC_KEY key;
struct HMAC_CTX ctx;
u8 mac[HASH_SIZE];
u8 mac2[HASH_SIZE];
static_assert(TEST_BUF_LEN >= 4096 + 293);
rand_bytes_seeded_from_len(test_buf, 4096);
raw_key = &test_buf[4096];
rand_bytes_seeded_from_len(data, max_data_len);
rand_bytes_seeded_from_len(raw_key, outer_key_len);
rand_bytes_seeded_from_len(raw_key, 32);
HMAC_PREPAREKEY(&key, raw_key, 32);
HMAC_PREPAREKEY(&key, raw_key, outer_key_len);
HMAC_INIT(&ctx, &key);
for (size_t data_len = 0; data_len <= 4096; data_len++) {
for (size_t data_len = 0; data_len <= max_data_len; data_len++) {
/*
* Cycle through key lengths as well. Somewhat arbitrarily go
* up to 293, which is somewhat larger than the largest hash
@@ -507,17 +447,17 @@ static void test_hmac(struct kunit *test)
* hashed down to one block); going higher would not be useful.
* To reduce correlation with data_len, use a prime number here.
*/
size_t key_len = data_len % 293;
size_t key_len = data_len % max_key_len;
HMAC_UPDATE(&ctx, test_buf, data_len);
HMAC_UPDATE(&ctx, data, data_len);
rand_bytes_seeded_from_len(raw_key, key_len);
HMAC_USINGRAWKEY(raw_key, key_len, test_buf, data_len, mac);
HMAC_USINGRAWKEY(raw_key, key_len, data, data_len, mac);
HMAC_UPDATE(&ctx, mac, HASH_SIZE);
/* Verify that HMAC() is consistent with HMAC_USINGRAWKEY(). */
HMAC_PREPAREKEY(&key, raw_key, key_len);
HMAC(&key, test_buf, data_len, mac2);
HMAC(&key, data, data_len, mac2);
KUNIT_ASSERT_MEMEQ_MSG(
test, mac, mac2, HASH_SIZE,
"HMAC gave different results with raw and prepared keys");
@@ -540,14 +480,17 @@ static void benchmark_hash(struct kunit *test)
1, 16, 64, 127, 128, 200, 256,
511, 512, 1024, 3173, 4096, 16384,
};
const size_t max_len = 16384;
u8 *data = alloc_buf(test, max_len);
u8 hash[HASH_SIZE];
if (!IS_ENABLED(CONFIG_CRYPTO_LIB_BENCHMARK))
kunit_skip(test, "not enabled");
/* Warm-up */
for (size_t i = 0; i < 10000000; i += TEST_BUF_LEN)
HASH(test_buf, TEST_BUF_LEN, hash);
memset(data, 0, max_len);
for (size_t i = 0; i < 10000000; i += max_len)
HASH(data, max_len, hash);
for (size_t i = 0; i < ARRAY_SIZE(lens_to_test); i++) {
size_t len = lens_to_test[i];
@@ -555,11 +498,11 @@ static void benchmark_hash(struct kunit *test)
size_t num_iters = 10000000 / (len + 128);
u64 t;
KUNIT_ASSERT_LE(test, len, TEST_BUF_LEN);
KUNIT_ASSERT_LE(test, len, max_len);
preempt_disable();
t = ktime_get_ns();
for (size_t j = 0; j < num_iters; j++)
HASH(test_buf, len, hash);
HASH(data, len, hash);
t = ktime_get_ns() - t;
preempt_enable();
kunit_info(test, "len=%zu: %llu MB/s", len,

View File

@@ -30,8 +30,6 @@ static struct kunit_case hash_test_cases[] = {
static struct kunit_suite hash_test_suite = {
.name = "md5",
.test_cases = hash_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(hash_test_suite);

View File

@@ -8,6 +8,7 @@
#include <kunit/test.h>
#include <linux/random.h>
#include <linux/unaligned.h>
#include "test-utils.h"
#define Q 8380417 /* The prime q = 2^23 - 2^13 + 1 */
@@ -60,14 +61,6 @@ static void do_mldsa_and_assert_success(struct kunit *test,
KUNIT_ASSERT_EQ(test, err, 0);
}
static u8 *kunit_kmemdup_or_fail(struct kunit *test, const u8 *src, size_t len)
{
u8 *dst = kunit_kmalloc(test, len, GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, dst);
return memcpy(dst, src, len);
}
/*
* Test that changing coefficients in a valid signature's z vector results in
* the following behavior from mldsa_verify():
@@ -83,7 +76,7 @@ static u8 *kunit_kmemdup_or_fail(struct kunit *test, const u8 *src, size_t len)
static void test_mldsa_z_range(struct kunit *test,
const struct mldsa_testvector *tv)
{
u8 *sig = kunit_kmemdup_or_fail(test, tv->sig, tv->sig_len);
u8 *sig = memdup_buf(test, tv->sig, tv->sig_len);
const int lambda = params[tv->alg].lambda;
const s32 gamma1 = params[tv->alg].gamma1;
const int beta = params[tv->alg].beta;
@@ -146,7 +139,7 @@ static void test_mldsa_bad_hints(struct kunit *test,
{
const int omega = params[tv->alg].omega;
const int k = params[tv->alg].k;
u8 *sig = kunit_kmemdup_or_fail(test, tv->sig, tv->sig_len);
u8 *sig = memdup_buf(test, tv->sig, tv->sig_len);
/* Pointer to the encoded hint vector in the signature */
u8 *hintvec = &sig[tv->sig_len - omega - k];
u8 h;
@@ -202,9 +195,9 @@ static void test_mldsa_mutation(struct kunit *test,
const int msg_len = tv->msg_len;
const int pk_len = tv->pk_len;
const int num_iter = 200;
u8 *sig = kunit_kmemdup_or_fail(test, tv->sig, sig_len);
u8 *msg = kunit_kmemdup_or_fail(test, tv->msg, msg_len);
u8 *pk = kunit_kmemdup_or_fail(test, tv->pk, pk_len);
u8 *sig = memdup_buf(test, tv->sig, sig_len);
u8 *msg = memdup_buf(test, tv->msg, msg_len);
u8 *pk = memdup_buf(test, tv->pk, pk_len);
/* Initially the signature is valid. */
do_mldsa_and_assert_success(test, tv);

View File

@@ -5,14 +5,13 @@
#include <crypto/nh.h>
#include <kunit/test.h>
#include "nh-testvecs.h"
#include "test-utils.h"
static void test_nh(struct kunit *test)
{
u32 *key = kunit_kmalloc(test, NH_KEY_BYTES, GFP_KERNEL);
u32 *key = memdup_buf(test, nh_test_key, NH_KEY_BYTES);
__le64 hash[NH_NUM_PASSES];
KUNIT_ASSERT_NOT_NULL(test, key);
memcpy(key, nh_test_key, NH_KEY_BYTES);
le32_to_cpu_array(key, NH_KEY_WORDS);
nh(key, nh_test_msg, 16, hash);

View File

@@ -46,12 +46,7 @@ static void poly1305_withtestkey(const u8 *data, size_t len,
static int poly1305_suite_init(struct kunit_suite *suite)
{
rand_bytes_seeded_from_len(test_key, POLY1305_KEY_SIZE);
return hash_suite_init(suite);
}
static void poly1305_suite_exit(struct kunit_suite *suite)
{
hash_suite_exit(suite);
return 0;
}
/*
@@ -81,19 +76,20 @@ static void poly1305_suite_exit(struct kunit_suite *suite)
*/
static void test_poly1305_allones_keys_and_message(struct kunit *test)
{
const size_t max_len = 4096;
u8 *data = alloc_buf(test, max_len);
struct poly1305_desc_ctx mac_ctx, macofmacs_ctx;
u8 mac[POLY1305_DIGEST_SIZE];
static_assert(TEST_BUF_LEN >= 4096);
memset(test_buf, 0xff, 4096);
memset(data, 0xff, max_len);
poly1305_init(&mac_ctx, test_buf);
poly1305_init(&macofmacs_ctx, test_buf);
poly1305_init(&mac_ctx, data);
poly1305_init(&macofmacs_ctx, data);
for (int i = 0; i < 32; i++) {
for (size_t len = 0; len <= 4096; len += 16) {
for (size_t len = 0; len <= max_len; len += 16) {
struct poly1305_desc_ctx tmp_ctx;
poly1305_update(&mac_ctx, test_buf, len);
poly1305_update(&mac_ctx, data, len);
tmp_ctx = mac_ctx;
poly1305_final(&tmp_ctx, mac);
poly1305_update(&macofmacs_ctx, mac,
@@ -157,7 +153,6 @@ static struct kunit_suite poly1305_test_suite = {
.name = "poly1305",
.test_cases = poly1305_test_cases,
.suite_init = poly1305_suite_init,
.suite_exit = poly1305_suite_exit,
};
kunit_test_suite(poly1305_test_suite);

View File

@@ -66,17 +66,18 @@ static void test_polyval_rfc8452_testvec(struct kunit *test)
*/
static void test_polyval_allones_key_and_message(struct kunit *test)
{
const size_t max_len = 4096;
u8 *data = alloc_buf(test, max_len);
struct polyval_key key;
struct polyval_ctx hashofhashes_ctx;
u8 hash[POLYVAL_BLOCK_SIZE];
static_assert(TEST_BUF_LEN >= 4096);
memset(test_buf, 0xff, 4096);
memset(data, 0xff, max_len);
polyval_preparekey(&key, test_buf);
polyval_preparekey(&key, data);
polyval_init(&hashofhashes_ctx, &key);
for (size_t len = 0; len <= 4096; len += 16) {
polyval(&key, test_buf, len, hash);
for (size_t len = 0; len <= max_len; len += 16) {
polyval(&key, data, len, hash);
polyval_update(&hashofhashes_ctx, hash, sizeof(hash));
}
polyval_final(&hashofhashes_ctx, hash);
@@ -95,7 +96,7 @@ static void check_key_consistency(struct kunit *test,
const struct polyval_key *key1,
const struct polyval_key *key2)
{
u8 *data = test_buf;
u8 *data = alloc_buf(test, MAX_LEN_FOR_KEY_CHECK);
u8 hash1[POLYVAL_BLOCK_SIZE];
u8 hash2[POLYVAL_BLOCK_SIZE];
@@ -115,10 +116,10 @@ static void check_key_consistency(struct kunit *test,
static void test_polyval_with_guarded_key(struct kunit *test)
{
u8 raw_key[POLYVAL_BLOCK_SIZE];
u8 *guarded_raw_key = &test_buf[TEST_BUF_LEN - sizeof(raw_key)];
u8 *guarded_raw_key = alloc_guarded_buf(test, sizeof(raw_key));
struct polyval_key key1, key2;
struct polyval_key *guarded_key =
(struct polyval_key *)&test_buf[TEST_BUF_LEN - sizeof(key1)];
alloc_guarded_buf(test, sizeof(*guarded_key));
/* Prepare with regular buffers. */
rand_bytes(raw_key, sizeof(raw_key));
@@ -137,21 +138,20 @@ static void test_polyval_with_guarded_key(struct kunit *test)
/*
* Test that polyval_key only needs to be aligned to
* __alignof__(struct polyval_key), i.e. 8 bytes. The assembly code may prefer
* 16-byte or higher alignment, but it musn't require it.
* 16-byte or higher alignment, but it mustn't require it.
*/
static void test_polyval_with_minimally_aligned_key(struct kunit *test)
{
u8 raw_key[POLYVAL_BLOCK_SIZE];
struct polyval_key key;
const size_t align = __alignof__(struct polyval_key);
u8 *key_buf = alloc_buf(test, sizeof(struct polyval_key) + 3 * align);
struct polyval_key *minaligned_key =
(struct polyval_key *)&test_buf[MAX_LEN_FOR_KEY_CHECK +
__alignof__(struct polyval_key)];
(struct polyval_key *)(PTR_ALIGN(key_buf, 2 * align) + align);
KUNIT_ASSERT_TRUE(test, IS_ALIGNED((uintptr_t)minaligned_key,
__alignof__(struct polyval_key)));
KUNIT_ASSERT_TRUE(test, IS_ALIGNED((uintptr_t)minaligned_key, align));
KUNIT_ASSERT_TRUE(test,
!IS_ALIGNED((uintptr_t)minaligned_key,
2 * __alignof__(struct polyval_key)));
!IS_ALIGNED((uintptr_t)minaligned_key, 2 * align));
rand_bytes(raw_key, sizeof(raw_key));
polyval_preparekey(&key, raw_key);
@@ -192,12 +192,7 @@ static int polyval_suite_init(struct kunit_suite *suite)
rand_bytes_seeded_from_len(raw_key, sizeof(raw_key));
polyval_preparekey(&test_key, raw_key);
return hash_suite_init(suite);
}
static void polyval_suite_exit(struct kunit_suite *suite)
{
hash_suite_exit(suite);
return 0;
}
static struct kunit_case polyval_test_cases[] = {
@@ -215,7 +210,6 @@ static struct kunit_suite polyval_test_suite = {
.name = "polyval",
.test_cases = polyval_test_cases,
.suite_init = polyval_suite_init,
.suite_exit = polyval_suite_exit,
};
kunit_test_suite(polyval_test_suite);

View File

@@ -30,8 +30,6 @@ static struct kunit_case hash_test_cases[] = {
static struct kunit_suite hash_test_suite = {
.name = "sha1",
.test_cases = hash_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(hash_test_suite);

View File

@@ -30,8 +30,6 @@ static struct kunit_case hash_test_cases[] = {
static struct kunit_suite hash_test_suite = {
.name = "sha224",
.test_cases = hash_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(hash_test_suite);

View File

@@ -4,6 +4,7 @@
*/
#include <crypto/sha2.h>
#include "sha256-testvecs.h"
#include "test-utils.h"
/* Generate the HASH_KUNIT_CASES using hash-test-template.h. */
#define HASH sha256
@@ -22,26 +23,6 @@
#define HMAC_USINGRAWKEY hmac_sha256_usingrawkey
#include "hash-test-template.h"
static void free_guarded_buf(void *buf)
{
vfree(buf);
}
/*
* Allocate a KUnit-managed buffer that has length @len bytes immediately
* followed by an unmapped page, and assert that the allocation succeeds.
*/
static void *alloc_guarded_buf(struct kunit *test, size_t len)
{
size_t full_len = round_up(len, PAGE_SIZE);
void *buf = vmalloc(full_len);
KUNIT_ASSERT_NOT_NULL(test, buf);
KUNIT_ASSERT_EQ(test, 0,
kunit_add_action_or_reset(test, free_guarded_buf, buf));
return buf + full_len - len;
}
/*
* Test for sha256_finup_2x(). Specifically, choose various data lengths and
* salt lengths, and for each one, verify that sha256_finup_2x() produces the
@@ -105,19 +86,20 @@ static void test_sha256_finup_2x(struct kunit *test)
static void test_sha256_finup_2x_defaultctx(struct kunit *test)
{
const size_t data_len = 128;
u8 *data = alloc_buf(test, 2 * data_len);
struct sha256_ctx ctx;
u8 hash1_a[SHA256_DIGEST_SIZE];
u8 hash2_a[SHA256_DIGEST_SIZE];
u8 hash1_b[SHA256_DIGEST_SIZE];
u8 hash2_b[SHA256_DIGEST_SIZE];
rand_bytes(test_buf, 2 * data_len);
rand_bytes(data, 2 * data_len);
sha256_init(&ctx);
sha256_finup_2x(&ctx, test_buf, &test_buf[data_len], data_len, hash1_a,
sha256_finup_2x(&ctx, data, &data[data_len], data_len, hash1_a,
hash2_a);
sha256_finup_2x(NULL, test_buf, &test_buf[data_len], data_len, hash1_b,
sha256_finup_2x(NULL, data, &data[data_len], data_len, hash1_b,
hash2_b);
KUNIT_ASSERT_MEMEQ(test, hash1_a, hash1_b, SHA256_DIGEST_SIZE);
@@ -131,18 +113,19 @@ static void test_sha256_finup_2x_defaultctx(struct kunit *test)
static void test_sha256_finup_2x_hugelen(struct kunit *test)
{
const size_t data_len = 4 * SHA256_BLOCK_SIZE;
u8 *data = alloc_buf(test, data_len);
struct sha256_ctx ctx = {};
u8 expected_hash[SHA256_DIGEST_SIZE];
u8 hash[SHA256_DIGEST_SIZE];
rand_bytes(test_buf, data_len);
rand_bytes(data, data_len);
for (size_t align = 0; align < SHA256_BLOCK_SIZE; align++) {
sha256_init(&ctx);
ctx.ctx.bytecount = 0x123456789abcd00 + align;
sha256_finup_2x(&ctx, test_buf, test_buf, data_len, hash, hash);
sha256_finup_2x(&ctx, data, data, data_len, hash, hash);
sha256_update(&ctx, test_buf, data_len);
sha256_update(&ctx, data, data_len);
sha256_final(&ctx, expected_hash);
KUNIT_ASSERT_MEMEQ(test, hash, expected_hash,
@@ -161,6 +144,7 @@ static void benchmark_sha256_finup_2x(struct kunit *test)
static const size_t salt_lens_to_test[] = { 0, 32, 64 };
const size_t data_len = 4096;
const size_t num_iters = 4096;
u8 *data = alloc_buf(test, data_len * 2);
struct sha256_ctx ctx;
u8 hash1[SHA256_DIGEST_SIZE];
u8 hash2[SHA256_DIGEST_SIZE];
@@ -170,12 +154,12 @@ static void benchmark_sha256_finup_2x(struct kunit *test)
if (!sha256_finup_2x_is_optimized())
kunit_skip(test, "not relevant");
rand_bytes(test_buf, data_len * 2);
rand_bytes(data, data_len * 2);
/* Warm-up */
for (size_t i = 0; i < num_iters; i++)
sha256_finup_2x(NULL, &test_buf[0], &test_buf[data_len],
data_len, hash1, hash2);
sha256_finup_2x(NULL, &data[0], &data[data_len], data_len,
hash1, hash2);
for (size_t i = 0; i < ARRAY_SIZE(salt_lens_to_test); i++) {
size_t salt_len = salt_lens_to_test[i];
@@ -186,12 +170,12 @@ static void benchmark_sha256_finup_2x(struct kunit *test)
* not measured; we're just interested in sha256_finup_2x().
*/
sha256_init(&ctx);
sha256_update(&ctx, test_buf, salt_len);
sha256_update(&ctx, data, salt_len);
preempt_disable();
t0 = ktime_get_ns();
for (size_t j = 0; j < num_iters; j++)
sha256_finup_2x(&ctx, &test_buf[0], &test_buf[data_len],
sha256_finup_2x(&ctx, &data[0], &data[data_len],
data_len, hash1, hash2);
t1 = ktime_get_ns();
preempt_enable();
@@ -215,8 +199,6 @@ static struct kunit_case hash_test_cases[] = {
static struct kunit_suite hash_test_suite = {
.name = "sha256",
.test_cases = hash_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(hash_test_suite);

View File

@@ -30,8 +30,6 @@ static struct kunit_case hash_test_cases[] = {
static struct kunit_suite hash_test_suite = {
.name = "sha384",
.test_cases = hash_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(hash_test_suite);

View File

@@ -273,12 +273,10 @@ static void test_shake_all_lens_up_to_4096(struct kunit *test)
{
struct sha3_ctx main_ctx;
const size_t max_len = 4096;
u8 *const in = test_buf;
u8 *const out = &test_buf[TEST_BUF_LEN - max_len];
u8 *const in = alloc_buf(test, max_len);
u8 *const out = alloc_buf(test, max_len);
u8 main_hash[SHA3_256_DIGEST_SIZE];
KUNIT_ASSERT_LE(test, 2 * max_len, TEST_BUF_LEN);
rand_bytes_seeded_from_len(in, max_len);
for (int alg = 0; alg < 2; alg++) {
sha3_256_init(&main_ctx);
@@ -309,12 +307,8 @@ static void test_shake_all_lens_up_to_4096(struct kunit *test)
static void test_shake_multiple_squeezes(struct kunit *test)
{
const size_t max_len = 512;
u8 *ref_out;
KUNIT_ASSERT_GE(test, TEST_BUF_LEN, 2 * max_len);
ref_out = kunit_kzalloc(test, max_len, GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, ref_out);
u8 *buf = alloc_buf(test, max_len);
u8 *ref_out = alloc_buf(test, max_len);
for (int i = 0; i < 2000; i++) {
const int alg = rand32() % 2;
@@ -322,8 +316,8 @@ static void test_shake_multiple_squeezes(struct kunit *test)
const size_t out_len = rand_length(max_len);
const size_t in_offs = rand_offset(max_len - in_len);
const size_t out_offs = rand_offset(max_len - out_len);
u8 *const in = &test_buf[in_offs];
u8 *const out = &test_buf[out_offs];
u8 *const in = &buf[in_offs];
u8 *const out = &buf[out_offs];
struct shake_ctx ctx;
size_t remaining_len, j, num_parts;
@@ -368,16 +362,12 @@ static void test_shake_multiple_squeezes(struct kunit *test)
static void test_shake_with_guarded_bufs(struct kunit *test)
{
const size_t max_len = 512;
u8 *reg_buf;
KUNIT_ASSERT_GE(test, TEST_BUF_LEN, max_len);
reg_buf = kunit_kzalloc(test, max_len, GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, reg_buf);
u8 *buf = alloc_guarded_buf(test, max_len);
u8 *reg_buf = alloc_buf(test, max_len);
for (int alg = 0; alg < 2; alg++) {
for (size_t len = 0; len <= max_len; len++) {
u8 *guarded_buf = &test_buf[TEST_BUF_LEN - len];
u8 *guarded_buf = &buf[max_len - len];
rand_bytes(reg_buf, len);
memcpy(guarded_buf, reg_buf, len);
@@ -413,8 +403,6 @@ static struct kunit_case sha3_test_cases[] = {
static struct kunit_suite sha3_test_suite = {
.name = "sha3",
.test_cases = sha3_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(sha3_test_suite);

View File

@@ -30,8 +30,6 @@ static struct kunit_case hash_test_cases[] = {
static struct kunit_suite hash_test_suite = {
.name = "sha512",
.test_cases = hash_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(hash_test_suite);

View File

@@ -22,8 +22,6 @@ static struct kunit_case sm3_test_cases[] = {
static struct kunit_suite sm3_test_suite = {
.name = "sm3",
.test_cases = sm3_test_cases,
.suite_init = hash_suite_init,
.suite_exit = hash_suite_exit,
};
kunit_test_suite(sm3_test_suite);

View File

@@ -0,0 +1,111 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Test utility functions shared by the crypto library tests.
*
* For now this is simply a header that's included into the KUnit test suites
* that need it. If this gets too large it could be made its own translation
* unit and libcrypto_test_utils module, but that seems overkill for now.
*/
#ifndef LIB_CRYPTO_TEST_UTILS_H
#define LIB_CRYPTO_TEST_UTILS_H
#include <kunit/test.h>
#include <linux/math.h>
#include <linux/minmax.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
static u64 random_seed;
static __maybe_unused void action_free_guarded_buf(void *buf)
{
vfree(buf);
}
/*
* Allocate a KUnit-managed buffer that has length @size bytes (> 0) immediately
* followed by an unmapped page, and assert that the allocation succeeds.
*/
static __maybe_unused void *alloc_guarded_buf(struct kunit *test, size_t size)
{
size_t full_size = round_up(size, PAGE_SIZE);
void *buf = vmalloc(full_size);
KUNIT_ASSERT_NOT_NULL(test, buf);
KUNIT_ASSERT_EQ(test, 0,
kunit_add_action_or_reset(test, action_free_guarded_buf,
buf));
return buf + full_size - size;
}
static __maybe_unused void *alloc_buf(struct kunit *test, size_t size)
{
void *buf = kunit_kmalloc(test, size, GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, buf);
return buf;
}
static __maybe_unused void *memdup_buf(struct kunit *test, const void *src,
size_t size)
{
void *dst = alloc_buf(test, size);
return memcpy(dst, src, size);
}
/*
* This is a simple linear congruential generator. It is used only for testing,
* which does not require cryptographically secure random numbers. A hard-coded
* algorithm is used instead of <linux/prandom.h> so that it matches the
* algorithm used by the test vector generation script. This allows the input
* data in random test vectors to be concisely stored as just the seed.
*/
static __maybe_unused u32 rand32(void)
{
random_seed = (random_seed * 25214903917 + 11) & ((1ULL << 48) - 1);
return random_seed >> 16;
}
static __maybe_unused void rand_bytes(u8 *out, size_t len)
{
for (size_t i = 0; i < len; i++)
out[i] = rand32();
}
static __maybe_unused void rand_bytes_seeded_from_len(u8 *out, size_t len)
{
random_seed = len;
rand_bytes(out, len);
}
static __maybe_unused bool rand_bool(void)
{
return rand32() % 2;
}
/* Generate a random length, preferring small lengths. */
static __maybe_unused size_t rand_length(size_t max_len)
{
size_t len;
switch (rand32() % 3) {
case 0:
len = rand32() % 128;
break;
case 1:
len = rand32() % 3072;
break;
default:
len = rand32();
break;
}
return len % (max_len + 1);
}
static __maybe_unused size_t rand_offset(size_t max_offset)
{
return min(rand32() % 128, max_offset);
}
#endif /* LIB_CRYPTO_TEST_UTILS_H */

View File

@@ -0,0 +1,69 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Script that generates known-good data used in the AEAD tests.
#
# Requires that python-cryptography be installed.
#
# Copyright 2026 Google LLC
import hashlib
import sys
import cryptography.hazmat.primitives.ciphers.aead
# Deterministically generate 'length' random bytes.
def rand_bytes(length):
seed = length
out = []
for _ in range(length):
seed = (seed * 25214903917 + 11) % 2**48
out.append((seed >> 16) % 256)
return bytes(out)
# Deterministically generate many different AEAD inputs using exactly the same
# method that the test uses; encrypt them using an independent implementation of
# the algorithm; compute the checksum of all the resulting (ciphertext, authtag)
# pairs concatenated to each other; and print the checksum as a C struct.
def gen_monte_carlo_checksum(alg):
blake2s = hashlib.blake2s()
for data_len in range(1025):
ad_len = data_len % 293
pt = rand_bytes(data_len)
ad = rand_bytes(ad_len)
if alg == "aes-ccm":
key_len = [16, 24, 32][data_len % 3]
key = rand_bytes(key_len)
nonce = rand_bytes([7, 8, 9, 10, 11, 12, 13][data_len % 7])
tag_len = [4, 6, 8, 10, 12, 14, 16][data_len % 7]
ccm = cryptography.hazmat.primitives.ciphers.aead.AESCCM(
key, tag_length=tag_len
)
ct_and_tag = ccm.encrypt(nonce, pt, ad)
elif alg == "aes-gcm":
key_len = [16, 24, 32][data_len % 3]
key = rand_bytes(key_len)
nonce = rand_bytes(12)
tag_len = [4, 8, 12, 13, 14, 15, 16][data_len % 7]
gcm = cryptography.hazmat.primitives.ciphers.aead.AESGCM(key)
# python-cryptography supports only 16-byte GCM tags. However, in
# GCM, shorter tags are simply truncated. Do that below.
ct_and_tag = gcm.encrypt(nonce, pt, ad)[: data_len + tag_len]
blake2s.update(ct_and_tag)
name = f"{alg.replace('-', '_')}_monte_carlo_checksum"
value = blake2s.digest()
print(f"static const u8 {name}[BLAKE2S_HASH_SIZE] = {{")
for i in range(0, len(value), 11):
line = "\t" + "".join(f"0x{b:02x}, " for b in value[i : i + 11])
print(f"{line.rstrip()}")
print("};")
if len(sys.argv) != 2 or sys.argv[1] not in ("aes-ccm", "aes-gcm"):
sys.stderr.write("Usage: gen-aead-testvecs.py [aes-ccm|aes-gcm]\n")
sys.exit(1)
gen_monte_carlo_checksum(sys.argv[1])

View File

@@ -1,46 +1,148 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Script that generates lib/crypto/fips.h
# Script that generates lib/crypto/fips-aes.h and lib/crypto/fips-sha.h
#
# Requires that python-cryptography be installed.
#
# Copyright 2025 Google LLC
import cryptography.hazmat.primitives.ciphers
import cryptography.hazmat.primitives.ciphers.aead
import cryptography.hazmat.primitives.cmac
import hashlib
import hmac
fips_test_data = b"fips test data\0\0"
fips_test_key = b"fips test key\0\0\0"
def print_static_u8_array_definition(name, value):
print('')
print(f'static const u8 {name}[] __initconst __maybe_unused = {{')
def print_static_u8_array_definition(file, name, value):
print("", file=file)
print(f"static const u8 {name}[] __initconst __maybe_unused = {{", file=file)
for i in range(0, len(value), 8):
line = '\t' + ''.join(f'0x{b:02x}, ' for b in value[i:i+8])
print(f'{line.rstrip()}')
print('};')
line = "\t" + "".join(f"0x{b:02x}, " for b in value[i : i + 8])
print(f"{line.rstrip()}", file=file)
print("};", file=file)
print('/* SPDX-License-Identifier: GPL-2.0-or-later */')
print(f'/* This file was generated by: gen-fips-testvecs.py */')
print()
print('#include <linux/fips.h>')
print_static_u8_array_definition("fips_test_data", fips_test_data)
print_static_u8_array_definition("fips_test_key", fips_test_key)
def print_header(file):
print("/* SPDX-License-Identifier: GPL-2.0-or-later */", file=file)
print("/* This file was generated by: gen-fips-testvecs.py */", file=file)
print("/* clang-format off */", file=file)
print("", file=file)
print("#include <linux/fips.h>", file=file)
for alg in 'sha1', 'sha256', 'sha512':
ctx = hmac.new(fips_test_key, digestmod=alg)
ctx.update(fips_test_data)
print_static_u8_array_definition(f'fips_test_hmac_{alg}_value', ctx.digest())
print_static_u8_array_definition(f'fips_test_sha3_256_value',
hashlib.sha3_256(fips_test_data).digest())
def gen_aes_test_data(file):
fips_test_data = b"fips test data\0\0"
fips_test_ad = b"fips test ad\0\0\0\0"
fips_test_iv = b"fips test iv\0\0\0\0"
fips_test_key = b"fips test key\0\0\0"
fips_test_xts_key = b"key1" + (b"\0" * 12) + b"key2" + (b"\0" * 12)
aes = cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_key)
aes_cmac = cryptography.hazmat.primitives.cmac.CMAC(aes)
aes_cmac.update(fips_test_data)
print_static_u8_array_definition('fips_test_aes_cmac_value',
aes_cmac.finalize())
print_header(file)
print_static_u8_array_definition(file, "fips_test_data", fips_test_data)
print_static_u8_array_definition(file, "fips_test_ad", fips_test_ad)
print_static_u8_array_definition(file, "fips_test_iv", fips_test_iv)
print_static_u8_array_definition(file, "fips_test_key", fips_test_key)
print_static_u8_array_definition(file, "fips_test_xts_key", fips_test_xts_key)
aes = cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_key)
# AES-CMAC
aes_cmac = cryptography.hazmat.primitives.cmac.CMAC(aes)
aes_cmac.update(fips_test_data)
print_static_u8_array_definition(
file, "fips_test_aes_cmac_value", aes_cmac.finalize()
)
# AES-ECB
cipher = cryptography.hazmat.primitives.ciphers.Cipher(
aes, cryptography.hazmat.primitives.ciphers.modes.ECB()
)
encryptor = cipher.encryptor()
ctext = encryptor.update(fips_test_data) + encryptor.finalize()
print_static_u8_array_definition(file, "fips_test_aes_ecb_ctext", ctext)
# AES-CBC
cipher = cryptography.hazmat.primitives.ciphers.Cipher(
aes, cryptography.hazmat.primitives.ciphers.modes.CBC(fips_test_iv)
)
encryptor = cipher.encryptor()
ctext = encryptor.update(fips_test_data) + encryptor.finalize()
print_static_u8_array_definition(file, "fips_test_aes_cbc_ctext", ctext)
# AES-CBC-CTS
cipher = cryptography.hazmat.primitives.ciphers.Cipher(
aes, cryptography.hazmat.primitives.ciphers.modes.CBC(fips_test_iv)
)
encryptor = cipher.encryptor()
ctext = encryptor.update(fips_test_data * 2) + encryptor.finalize()
ctext = ctext[16:32] + ctext[0:16]
print_static_u8_array_definition(file, "fips_test_aes_cbc_cts_ctext", ctext)
# AES-CTR
cipher = cryptography.hazmat.primitives.ciphers.Cipher(
aes, cryptography.hazmat.primitives.ciphers.modes.CTR(fips_test_iv)
)
encryptor = cipher.encryptor()
ctext = encryptor.update(fips_test_data) + encryptor.finalize()
print_static_u8_array_definition(file, "fips_test_aes_ctr_ctext", ctext)
# AES-XTS
cipher = cryptography.hazmat.primitives.ciphers.Cipher(
cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_xts_key),
cryptography.hazmat.primitives.ciphers.modes.XTS(fips_test_iv),
)
encryptor = cipher.encryptor()
ctext = encryptor.update(fips_test_data) + encryptor.finalize()
print_static_u8_array_definition(file, "fips_test_aes_xts_ctext", ctext)
# AES-GCM
cipher = cryptography.hazmat.primitives.ciphers.aead.AESGCM(fips_test_key)
ct_and_tag = cipher.encrypt(
nonce=fips_test_iv[:12], data=fips_test_data, associated_data=fips_test_ad
)
print_static_u8_array_definition(
file, "fips_test_aes_gcm_ctext_and_tag", ct_and_tag
)
# AES-CCM
cipher = cryptography.hazmat.primitives.ciphers.aead.AESCCM(
fips_test_key, tag_length=16
)
ct_and_tag = cipher.encrypt(
nonce=fips_test_iv[:13], data=fips_test_data, associated_data=fips_test_ad
)
print_static_u8_array_definition(
file, "fips_test_aes_ccm_ctext_and_tag", ct_and_tag
)
def gen_sha_test_data(file):
fips_test_data = b"fips test data\0\0"
fips_test_key = b"fips test key\0\0\0"
print_header(file)
print_static_u8_array_definition(file, "fips_test_data", fips_test_data)
print_static_u8_array_definition(file, "fips_test_key", fips_test_key)
for alg in "sha1", "sha256", "sha512":
ctx = hmac.new(fips_test_key, digestmod=alg)
ctx.update(fips_test_data)
print_static_u8_array_definition(
file, f"fips_test_hmac_{alg}_value", ctx.digest()
)
print_static_u8_array_definition(
file, "fips_test_sha3_256_value", hashlib.sha3_256(fips_test_data).digest()
)
filename = "lib/crypto/fips-aes.h"
with open(filename, "w") as file:
print(f"Generating {filename}")
gen_aes_test_data(file)
filename = "lib/crypto/fips-sha.h"
with open(filename, "w") as file:
print(f"Generating {filename}")
gen_sha_test_data(file)