Commit 15c64c47 authored by David Howells's avatar David Howells Committed by Eric Biggers
Browse files

lib/crypto: tests: Add SHA3 kunit tests



Add a SHA3 kunit test suite, providing the following:

 (*) A simple test of each of SHA3-224, SHA3-256, SHA3-384, SHA3-512,
     SHAKE128 and SHAKE256.

 (*) NIST 0- and 1600-bit test vectors for SHAKE128 and SHAKE256.

 (*) Output tiling (multiple squeezing) tests for SHAKE256.

 (*) Standard hash template test for SHA3-256.  To make this possible,
     gen-hash-testvecs.py is modified to support sha3-256.

 (*) Standard benchmark test for SHA3-256.

[EB: dropped some unnecessary changes to gen-hash-testvecs.py, moved
     addition of Testing section in doc file into this commit, and
     other small cleanups]

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Reviewed-by: default avatarArd Biesheuvel <ardb@kernel.org>
Tested-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Link: https://lore.kernel.org/r/20251026055032.1413733-6-ebiggers@kernel.org


Signed-off-by: default avatarEric Biggers <ebiggers@kernel.org>
parent 6401fd33
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -107,6 +107,17 @@ Once all the desired output has been extracted, zeroize the context::
	void shake_zeroize_ctx(struct shake_ctx *ctx);


Testing
=======

To test the SHA-3 code, use sha3_kunit (CONFIG_CRYPTO_LIB_SHA3_KUNIT_TEST).

Since the SHA-3 algorithms are FIPS-approved, when the kernel is booted in FIPS
mode the SHA-3 library also performs a simple self-test.  This is purely to meet
a FIPS requirement.  Normal testing done by kernel developers and integrators
should use the much more comprehensive KUnit test suite instead.


References
==========

+11 −0
Original line number Diff line number Diff line
@@ -81,6 +81,17 @@ config CRYPTO_LIB_SHA512_KUNIT_TEST
	  KUnit tests for the SHA-384 and SHA-512 cryptographic hash functions
	  and their corresponding HMACs.

config CRYPTO_LIB_SHA3_KUNIT_TEST
	tristate "KUnit tests for SHA-3" if !KUNIT_ALL_TESTS
	depends on KUNIT
	default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS
	select CRYPTO_LIB_BENCHMARK_VISIBLE
	select CRYPTO_LIB_SHA3
	help
	  KUnit tests for the SHA3 cryptographic hash and XOF functions,
	  including SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128 and
	  SHAKE256.

config CRYPTO_LIB_BENCHMARK_VISIBLE
	bool

+1 −0
Original line number Diff line number Diff line
@@ -8,3 +8,4 @@ obj-$(CONFIG_CRYPTO_LIB_POLY1305_KUNIT_TEST) += poly1305_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA1_KUNIT_TEST) += sha1_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA256_KUNIT_TEST) += sha224_kunit.o sha256_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA512_KUNIT_TEST) += sha384_kunit.o sha512_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA3_KUNIT_TEST) += sha3_kunit.o
+231 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* This file was generated by: ./scripts/crypto/gen-hash-testvecs.py sha3-256 */

static const struct {
	size_t data_len;
	u8 digest[SHA3_256_DIGEST_SIZE];
} hash_testvecs[] = {
	{
		.data_len = 0,
		.digest = {
			0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66,
			0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62,
			0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa,
			0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a,
		},
	},
	{
		.data_len = 1,
		.digest = {
			0x11, 0x03, 0xe7, 0x84, 0x51, 0x50, 0x86, 0x35,
			0x71, 0x8a, 0x70, 0xe3, 0xc4, 0x26, 0x7b, 0x21,
			0x02, 0x13, 0xa0, 0x81, 0xe8, 0xe6, 0x14, 0x25,
			0x07, 0x34, 0xe5, 0xc5, 0x40, 0x06, 0xf2, 0x8b,
		},
	},
	{
		.data_len = 2,
		.digest = {
			0x2f, 0x6f, 0x6d, 0x47, 0x48, 0x52, 0x11, 0xb9,
			0xe4, 0x3d, 0xc8, 0x71, 0xcf, 0xb2, 0xee, 0xae,
			0x5b, 0xf4, 0x12, 0x84, 0x5b, 0x1c, 0xec, 0x6c,
			0xc1, 0x66, 0x88, 0xaa, 0xc3, 0x40, 0xbd, 0x7e,
		},
	},
	{
		.data_len = 3,
		.digest = {
			0xec, 0x02, 0xe8, 0x81, 0x4f, 0x84, 0x41, 0x69,
			0x06, 0xd8, 0xdc, 0x1d, 0x01, 0x78, 0xd7, 0xcb,
			0x39, 0xdf, 0xd3, 0x12, 0x1c, 0x99, 0xfd, 0xf3,
			0x5c, 0x83, 0xc9, 0xc2, 0x7a, 0x7b, 0x6a, 0x05,
		},
	},
	{
		.data_len = 16,
		.digest = {
			0xff, 0x6f, 0xc3, 0x41, 0xc3, 0x5f, 0x34, 0x6d,
			0xa7, 0xdf, 0x3e, 0xc2, 0x8b, 0x29, 0xb6, 0xf1,
			0xf8, 0x67, 0xfd, 0xcd, 0xb1, 0x9f, 0x38, 0x08,
			0x1d, 0x8d, 0xd9, 0xc2, 0x43, 0x66, 0x18, 0x6c,
		},
	},
	{
		.data_len = 32,
		.digest = {
			0xe4, 0xb1, 0x06, 0x17, 0xf8, 0x8b, 0x91, 0x95,
			0xe7, 0x57, 0x66, 0xac, 0x08, 0xb2, 0x03, 0x3e,
			0xf7, 0x84, 0x1f, 0xe3, 0x25, 0xa3, 0x11, 0xd2,
			0x11, 0xa4, 0x78, 0x74, 0x2a, 0x43, 0x20, 0xa5,
		},
	},
	{
		.data_len = 48,
		.digest = {
			0xeb, 0x57, 0x5f, 0x20, 0xa3, 0x6b, 0xc7, 0xb4,
			0x66, 0x2a, 0xa0, 0x30, 0x3b, 0x52, 0x00, 0xc9,
			0xce, 0x6a, 0xd8, 0x1e, 0xbe, 0xed, 0xa1, 0xd1,
			0xbe, 0x63, 0xc7, 0xe1, 0xe2, 0x66, 0x67, 0x0c,
		},
	},
	{
		.data_len = 49,
		.digest = {
			0xf0, 0x67, 0xad, 0x66, 0xbe, 0xec, 0x5a, 0xfd,
			0x29, 0xd2, 0x4f, 0x1d, 0xb2, 0x24, 0xb8, 0x90,
			0x05, 0x28, 0x0e, 0x66, 0x67, 0x74, 0x2d, 0xee,
			0x66, 0x25, 0x11, 0xd1, 0x76, 0xa2, 0xfc, 0x3a,
		},
	},
	{
		.data_len = 63,
		.digest = {
			0x57, 0x56, 0x21, 0xb3, 0x2d, 0x2d, 0xe1, 0x9d,
			0xbf, 0x2c, 0x82, 0xa8, 0xad, 0x7e, 0x6c, 0x46,
			0xfb, 0x30, 0xeb, 0xce, 0xcf, 0xed, 0x2d, 0x65,
			0xe7, 0xe4, 0x96, 0x69, 0xe0, 0x48, 0xd2, 0xb6,
		},
	},
	{
		.data_len = 64,
		.digest = {
			0x7b, 0xba, 0x67, 0x15, 0xe5, 0x21, 0xc4, 0x69,
			0xd3, 0xef, 0x5c, 0x97, 0x9f, 0x5b, 0xba, 0x9c,
			0xfa, 0x55, 0x64, 0xec, 0xb5, 0x37, 0x53, 0x1b,
			0x3f, 0x4c, 0x0a, 0xed, 0x51, 0x98, 0x2b, 0x52,
		},
	},
	{
		.data_len = 65,
		.digest = {
			0x44, 0xb6, 0x6b, 0x83, 0x09, 0x83, 0x55, 0x83,
			0xde, 0x1f, 0xcc, 0x33, 0xef, 0xdc, 0x05, 0xbb,
			0x3b, 0x63, 0x76, 0x45, 0xe4, 0x8e, 0x14, 0x7a,
			0x2d, 0xae, 0x90, 0xce, 0x68, 0xc3, 0xa4, 0xf2,
		},
	},
	{
		.data_len = 127,
		.digest = {
			0x50, 0x3e, 0x99, 0x4e, 0x28, 0x2b, 0xc9, 0xf4,
			0xf5, 0xeb, 0x2b, 0x16, 0x04, 0x2d, 0xf5, 0xbe,
			0xc0, 0x91, 0x41, 0x2a, 0x8e, 0x69, 0x5e, 0x39,
			0x53, 0x2c, 0xc1, 0x18, 0xa5, 0xeb, 0xd8, 0xda,
		},
	},
	{
		.data_len = 128,
		.digest = {
			0x90, 0x0b, 0xa6, 0x92, 0x84, 0x30, 0xaf, 0xee,
			0x38, 0x59, 0x83, 0x83, 0xe9, 0xfe, 0xab, 0x86,
			0x79, 0x1b, 0xcd, 0xe7, 0x0a, 0x0f, 0x58, 0x53,
			0x36, 0xab, 0x12, 0xe1, 0x5c, 0x97, 0xc1, 0xfb,
		},
	},
	{
		.data_len = 129,
		.digest = {
			0x2b, 0x52, 0x1e, 0x54, 0xbe, 0x38, 0x4c, 0x3e,
			0x73, 0x37, 0x18, 0xf5, 0x25, 0x2c, 0xc8, 0xc7,
			0xda, 0x7e, 0xb6, 0x47, 0x9d, 0xf4, 0x46, 0xce,
			0xfa, 0x80, 0x20, 0x6b, 0xbd, 0xfd, 0x2a, 0xd8,
		},
	},
	{
		.data_len = 256,
		.digest = {
			0x45, 0xf0, 0xf5, 0x9b, 0xd9, 0x91, 0x26, 0xd5,
			0x91, 0x3b, 0xf8, 0x87, 0x8b, 0x34, 0x02, 0x31,
			0x64, 0xab, 0xf4, 0x1c, 0x6e, 0x34, 0x72, 0xdf,
			0x32, 0x6d, 0xe5, 0xd2, 0x67, 0x5e, 0x86, 0x93,
		},
	},
	{
		.data_len = 511,
		.digest = {
			0xb3, 0xaf, 0x71, 0x64, 0xfa, 0xd4, 0xf1, 0x07,
			0x38, 0xef, 0x04, 0x8e, 0x89, 0xf4, 0x02, 0xd2,
			0xa5, 0xaf, 0x3b, 0xf5, 0x67, 0x56, 0xcf, 0xa9,
			0x8e, 0x43, 0xf5, 0xb5, 0xe3, 0x91, 0x8e, 0xe7,
		},
	},
	{
		.data_len = 513,
		.digest = {
			0x51, 0xac, 0x0a, 0x65, 0xb7, 0x96, 0x20, 0xcf,
			0x88, 0xf6, 0x97, 0x35, 0x89, 0x0d, 0x31, 0x0f,
			0xbe, 0x17, 0xbe, 0x62, 0x03, 0x67, 0xc0, 0xee,
			0x4f, 0xc1, 0xe3, 0x7f, 0x6f, 0xab, 0xac, 0xb4,
		},
	},
	{
		.data_len = 1000,
		.digest = {
			0x7e, 0xea, 0xa8, 0xd7, 0xde, 0x20, 0x1b, 0x58,
			0x24, 0xd8, 0x26, 0x40, 0x36, 0x5f, 0x3f, 0xaa,
			0xe5, 0x5a, 0xea, 0x98, 0x58, 0xd4, 0xd6, 0xfc,
			0x20, 0x4c, 0x5c, 0x4f, 0xaf, 0x56, 0xc7, 0xc3,
		},
	},
	{
		.data_len = 3333,
		.digest = {
			0x61, 0xb1, 0xb1, 0x3e, 0x0e, 0x7e, 0x90, 0x3d,
			0x31, 0x54, 0xbd, 0xc9, 0x0d, 0x53, 0x62, 0xf1,
			0xcd, 0x18, 0x80, 0xf9, 0x91, 0x75, 0x41, 0xb3,
			0x51, 0x39, 0x57, 0xa7, 0xa8, 0x1e, 0xfb, 0xc9,
		},
	},
	{
		.data_len = 4096,
		.digest = {
			0xab, 0x29, 0xda, 0x10, 0xc4, 0x11, 0x2d, 0x5c,
			0xd1, 0xce, 0x1c, 0x95, 0xfa, 0xc6, 0xc7, 0xb0,
			0x1b, 0xd1, 0xdc, 0x6f, 0xa0, 0x9d, 0x1b, 0x23,
			0xfb, 0x6e, 0x90, 0x97, 0xd0, 0x75, 0x44, 0x7a,
		},
	},
	{
		.data_len = 4128,
		.digest = {
			0x02, 0x45, 0x95, 0xf4, 0x19, 0xb5, 0x93, 0x29,
			0x90, 0xf2, 0x63, 0x3f, 0x89, 0xe8, 0xa5, 0x31,
			0x76, 0xf2, 0x89, 0x79, 0x66, 0xd3, 0x96, 0xdf,
			0x33, 0xd1, 0xa6, 0x17, 0x73, 0xb1, 0xd0, 0x45,
		},
	},
	{
		.data_len = 4160,
		.digest = {
			0xd1, 0x8e, 0x22, 0xea, 0x44, 0x87, 0x6e, 0x9d,
			0xfb, 0x36, 0x02, 0x20, 0x63, 0xb7, 0x69, 0x45,
			0x25, 0x41, 0x69, 0xe0, 0x9b, 0x87, 0xcf, 0xa3,
			0x51, 0xbb, 0xfc, 0x8d, 0xf7, 0x29, 0xa7, 0xea,
		},
	},
	{
		.data_len = 4224,
		.digest = {
			0x11, 0x86, 0x7d, 0x84, 0xf9, 0x8c, 0x6e, 0xc4,
			0x64, 0x36, 0xc6, 0xf3, 0x42, 0x92, 0x31, 0x2b,
			0x1e, 0x12, 0xe6, 0x4d, 0xbe, 0xfa, 0x77, 0x3f,
			0x89, 0x41, 0x33, 0x58, 0x1c, 0x98, 0x16, 0x0a,
		},
	},
	{
		.data_len = 16384,
		.digest = {
			0xb2, 0xba, 0x0c, 0x8c, 0x9d, 0xbb, 0x1e, 0xb0,
			0x03, 0xb5, 0xdf, 0x4f, 0xf5, 0x35, 0xdb, 0xec,
			0x60, 0xf2, 0x5b, 0xb6, 0xd0, 0x49, 0xd3, 0xed,
			0x55, 0xc0, 0x7a, 0xd7, 0xaf, 0xa1, 0xea, 0x53,
		},
	},
};

static const u8 hash_testvec_consolidated[SHA3_256_DIGEST_SIZE] = {
	0x3b, 0x33, 0x67, 0xf8, 0xea, 0x92, 0x78, 0x62,
	0xdd, 0xbe, 0x72, 0x15, 0xbd, 0x6f, 0xfa, 0xe5,
	0x5e, 0xab, 0x9f, 0xb1, 0xe4, 0x23, 0x7c, 0x2c,
	0x80, 0xcf, 0x09, 0x75, 0xf8, 0xe2, 0xfa, 0x30,
};
+344 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 */
#include <crypto/sha3.h>
#include "sha3-testvecs.h"

#define HASH		sha3_256
#define HASH_CTX	sha3_ctx
#define HASH_SIZE	SHA3_256_DIGEST_SIZE
#define HASH_INIT	sha3_256_init
#define HASH_UPDATE	sha3_update
#define HASH_FINAL	sha3_final
#include "hash-test-template.h"

/*
 * Sample message and the output generated for various algorithms by passing it
 * into "openssl sha3-224" etc..
 */
static const u8 test_sha3_sample[] =
	"The quick red fox jumped over the lazy brown dog!\n"
	"The quick red fox jumped over the lazy brown dog!\n"
	"The quick red fox jumped over the lazy brown dog!\n"
	"The quick red fox jumped over the lazy brown dog!\n";

static const u8 test_sha3_224[8 + SHA3_224_DIGEST_SIZE + 8] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
	0xd6, 0xe8, 0xd8, 0x80, 0xfa, 0x42, 0x80, 0x70,
	0x7e, 0x7f, 0xd7, 0xd2, 0xd7, 0x7a, 0x35, 0x65,
	0xf0, 0x0b, 0x4f, 0x9f, 0x2a, 0x33, 0xca, 0x0a,
	0xef, 0xa6, 0x4c, 0xb8,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
};

static const u8 test_sha3_256[8 + SHA3_256_DIGEST_SIZE + 8] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
	0xdb, 0x3b, 0xb0, 0xb8, 0x8d, 0x15, 0x78, 0xe5,
	0x78, 0x76, 0x8e, 0x39, 0x7e, 0x89, 0x86, 0xb9,
	0x14, 0x3a, 0x1e, 0xe7, 0x96, 0x7c, 0xf3, 0x25,
	0x70, 0xbd, 0xc3, 0xa9, 0xae, 0x63, 0x71, 0x1d,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
};

static const u8 test_sha3_384[8 + SHA3_384_DIGEST_SIZE + 8] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
	0x2d, 0x4b, 0x29, 0x85, 0x19, 0x94, 0xaa, 0x31,
	0x9b, 0x04, 0x9d, 0x6e, 0x79, 0x66, 0xc7, 0x56,
	0x8a, 0x2e, 0x99, 0x84, 0x06, 0xcf, 0x10, 0x2d,
	0xec, 0xf0, 0x03, 0x04, 0x1f, 0xd5, 0x99, 0x63,
	0x2f, 0xc3, 0x2b, 0x0d, 0xd9, 0x45, 0xf7, 0xbb,
	0x0a, 0xc3, 0x46, 0xab, 0xfe, 0x4d, 0x94, 0xc2,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
};

static const u8 test_sha3_512[8 + SHA3_512_DIGEST_SIZE + 8] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
	0xdd, 0x71, 0x3b, 0x44, 0xb6, 0x6c, 0xd7, 0x78,
	0xe7, 0x93, 0xa1, 0x4c, 0xd7, 0x24, 0x16, 0xf1,
	0xfd, 0xa2, 0x82, 0x4e, 0xed, 0x59, 0xe9, 0x83,
	0x15, 0x38, 0x89, 0x7d, 0x39, 0x17, 0x0c, 0xb2,
	0xcf, 0x12, 0x80, 0x78, 0xa1, 0x78, 0x41, 0xeb,
	0xed, 0x21, 0x4c, 0xa4, 0x4a, 0x5f, 0x30, 0x1a,
	0x70, 0x98, 0x4f, 0x14, 0xa2, 0xd1, 0x64, 0x1b,
	0xc2, 0x0a, 0xff, 0x3b, 0xe8, 0x26, 0x41, 0x8f,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
};

static const u8 test_shake128[8 + SHAKE128_DEFAULT_SIZE + 8] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
	0x41, 0xd6, 0xb8, 0x9c, 0xf8, 0xe8, 0x54, 0xf2,
	0x5c, 0xde, 0x51, 0x12, 0xaf, 0x9e, 0x0d, 0x91,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
};

static const u8 test_shake256[8 + SHAKE256_DEFAULT_SIZE + 8] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
	0xab, 0x06, 0xd4, 0xf9, 0x8b, 0xfd, 0xb2, 0xc4,
	0xfe, 0xf1, 0xcc, 0xe2, 0x40, 0x45, 0xdd, 0x15,
	0xcb, 0xdd, 0x02, 0x8d, 0xb7, 0x9f, 0x1e, 0x67,
	0xd6, 0x7f, 0x98, 0x5e, 0x1b, 0x19, 0xf8, 0x01,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
};

static void test_sha3_224_basic(struct kunit *test)
{
	u8 out[8 + SHA3_224_DIGEST_SIZE + 8];

	BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_224));

	memset(out, 0, sizeof(out));
	sha3_224(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8);

	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_224, sizeof(test_sha3_224),
			       "SHA3-224 gives wrong output");
}

static void test_sha3_256_basic(struct kunit *test)
{
	u8 out[8 + SHA3_256_DIGEST_SIZE + 8];

	BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_256));

	memset(out, 0, sizeof(out));
	sha3_256(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8);

	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_256, sizeof(test_sha3_256),
			       "SHA3-256 gives wrong output");
}

static void test_sha3_384_basic(struct kunit *test)
{
	u8 out[8 + SHA3_384_DIGEST_SIZE + 8];

	BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_384));

	memset(out, 0, sizeof(out));
	sha3_384(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8);

	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_384, sizeof(test_sha3_384),
			       "SHA3-384 gives wrong output");
}

static void test_sha3_512_basic(struct kunit *test)
{
	u8 out[8 + SHA3_512_DIGEST_SIZE + 8];

	BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_512));

	memset(out, 0, sizeof(out));
	sha3_512(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8);

	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_512, sizeof(test_sha3_512),
			       "SHA3-512 gives wrong output");
}

static void test_shake128_basic(struct kunit *test)
{
	u8 out[8 + SHAKE128_DEFAULT_SIZE + 8];

	BUILD_BUG_ON(sizeof(out) != sizeof(test_shake128));

	memset(out, 0, sizeof(out));
	shake128(test_sha3_sample, sizeof(test_sha3_sample) - 1,
		 out + 8, sizeof(out) - 16);

	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake128, sizeof(test_shake128),
			       "SHAKE128 gives wrong output");
}

static void test_shake256_basic(struct kunit *test)
{
	u8 out[8 + SHAKE256_DEFAULT_SIZE + 8];

	BUILD_BUG_ON(sizeof(out) != sizeof(test_shake256));

	memset(out, 0, sizeof(out));
	shake256(test_sha3_sample, sizeof(test_sha3_sample) - 1,
		 out + 8, sizeof(out) - 16);

	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256, sizeof(test_shake256),
			       "SHAKE256 gives wrong output");
}

/*
 * Usable NIST tests.
 *
 * From: https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values
 */
static const u8 test_nist_1600_sample[] = {
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3
};

static const u8 test_shake128_nist_0[] = {
	0x7f, 0x9c, 0x2b, 0xa4, 0xe8, 0x8f, 0x82, 0x7d,
	0x61, 0x60, 0x45, 0x50, 0x76, 0x05, 0x85, 0x3e
};

static const u8 test_shake128_nist_1600[] = {
	0x13, 0x1a, 0xb8, 0xd2, 0xb5, 0x94, 0x94, 0x6b,
	0x9c, 0x81, 0x33, 0x3f, 0x9b, 0xb6, 0xe0, 0xce,
};

static const u8 test_shake256_nist_0[] = {
	0x46, 0xb9, 0xdd, 0x2b, 0x0b, 0xa8, 0x8d, 0x13,
	0x23, 0x3b, 0x3f, 0xeb, 0x74, 0x3e, 0xeb, 0x24,
	0x3f, 0xcd, 0x52, 0xea, 0x62, 0xb8, 0x1b, 0x82,
	0xb5, 0x0c, 0x27, 0x64, 0x6e, 0xd5, 0x76, 0x2f
};

static const u8 test_shake256_nist_1600[] = {
	0xcd, 0x8a, 0x92, 0x0e, 0xd1, 0x41, 0xaa, 0x04,
	0x07, 0xa2, 0x2d, 0x59, 0x28, 0x86, 0x52, 0xe9,
	0xd9, 0xf1, 0xa7, 0xee, 0x0c, 0x1e, 0x7c, 0x1c,
	0xa6, 0x99, 0x42, 0x4d, 0xa8, 0x4a, 0x90, 0x4d,
};

static void test_shake128_nist(struct kunit *test)
{
	u8 out[SHAKE128_DEFAULT_SIZE];

	shake128("", 0, out, sizeof(out));
	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake128_nist_0, sizeof(out),
			       "SHAKE128 gives wrong output for NIST.0");

	shake128(test_nist_1600_sample, sizeof(test_nist_1600_sample),
		 out, sizeof(out));
	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake128_nist_1600, sizeof(out),
			       "SHAKE128 gives wrong output for NIST.1600");
}

static void test_shake256_nist(struct kunit *test)
{
	u8 out[SHAKE256_DEFAULT_SIZE];

	shake256("", 0, out, sizeof(out));
	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256_nist_0, sizeof(out),
			       "SHAKE256 gives wrong output for NIST.0");

	shake256(test_nist_1600_sample, sizeof(test_nist_1600_sample),
		 out, sizeof(out));
	KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256_nist_1600, sizeof(out),
			       "SHAKE256 gives wrong output for NIST.1600");
}

/*
 * Output tiling test of SHAKE256; equal output tiles barring the last.  A
 * series of squeezings of the same context should, if laid end-to-end, match a
 * single squeezing of the combined size.
 */
static void test_shake256_tiling(struct kunit *test)
{
	struct shake_ctx ctx;
	u8 out[8 + SHA3_512_DIGEST_SIZE + 8];

	for (int tile_size = 1; tile_size < SHAKE256_DEFAULT_SIZE; tile_size++) {
		int left = SHAKE256_DEFAULT_SIZE;
		u8 *p = out + 8;

		memset(out, 0, sizeof(out));
		shake256_init(&ctx);
		shake_update(&ctx, test_sha3_sample,
			     sizeof(test_sha3_sample) - 1);
		while (left > 0) {
			int part = umin(tile_size, left);

			shake_squeeze(&ctx, p, part);
			p += part;
			left -= part;
		}

		KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256, sizeof(test_shake256),
				       "SHAKE tile %u gives wrong output", tile_size);
	}
}

/*
 * Output tiling test of SHAKE256; output tiles getting gradually smaller and
 * then cycling round to medium sized ones.  A series of squeezings of the same
 * context should, if laid end-to-end, match a single squeezing of the combined
 * size.
 */
static void test_shake256_tiling2(struct kunit *test)
{
	struct shake_ctx ctx;
	u8 out[8 + SHA3_512_DIGEST_SIZE + 8];

	for (int first_tile_size = 3;
	     first_tile_size < SHAKE256_DEFAULT_SIZE;
	     first_tile_size++) {
		int tile_size = first_tile_size;
		int left = SHAKE256_DEFAULT_SIZE;
		u8 *p = out + 8;

		memset(out, 0, sizeof(out));
		shake256_init(&ctx);
		shake_update(&ctx, test_sha3_sample,
			     sizeof(test_sha3_sample) - 1);
		while (left > 0) {
			int part = umin(tile_size, left);

			shake_squeeze(&ctx, p, part);
			p += part;
			left -= part;
			tile_size--;
			if (tile_size < 1)
				tile_size = 5;
		}

		KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256, sizeof(test_shake256),
				       "SHAKE tile %u gives wrong output", tile_size);
	}
}

static struct kunit_case sha3_test_cases[] = {
	HASH_KUNIT_CASES,
	KUNIT_CASE(test_sha3_224_basic),
	KUNIT_CASE(test_sha3_256_basic),
	KUNIT_CASE(test_sha3_384_basic),
	KUNIT_CASE(test_sha3_512_basic),
	KUNIT_CASE(test_shake128_basic),
	KUNIT_CASE(test_shake256_basic),
	KUNIT_CASE(test_shake128_nist),
	KUNIT_CASE(test_shake256_nist),
	KUNIT_CASE(test_shake256_tiling),
	KUNIT_CASE(test_shake256_tiling2),
	KUNIT_CASE(benchmark_hash),
	{},
};

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);

MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3");
MODULE_LICENSE("GPL");
Loading