[test] Add Project Wycheproof AES-GCM tests

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2026-09-01 14:24:51 +01:00
parent e49e1db1c2
commit 35bd9a8fd3
4 changed files with 7180 additions and 0 deletions
+134
View File
@@ -729,6 +729,139 @@ class HkdfSha512TestFile(HkdfTestFile):
LABEL: ClassVar = "HKDF-SHA512"
SRCFILE: ClassVar = "hkdf_sha512_test.json"
##############################################################################
#
# AEAD cipher tests
#
class AeadCipherTestFlag(Enum):
COUNTER_WRAP = "CounterWrap"
KTV = "Ktv"
LONG_IV = "LongIv"
MODIFIED_TAG = "ModifiedTag"
PSEUDORANDOM = "Pseudorandom"
SMALL_IV = "SmallIv"
SPECIAL_CASE = "SpecialCase"
ZERO_LENGTH_IV = "ZeroLengthIv"
@attrclass
class AeadCipherTestCase(TestCase):
"""An AEAD cipher test case"""
flags = set_field(AeadCipherTestFlag)
key = scalar_field(HexBytes, metadata={"stable": True})
iv = scalar_field(HexBytes, metadata={"stable": True})
aad = scalar_field(HexBytes, metadata={"stable": True})
msg = scalar_field(HexBytes, metadata={"stable": True})
ct = scalar_field(HexBytes)
tag = scalar_field(HexBytes)
@key.validator
def validate_key(self, attr, value):
"""Validate key size"""
self.validate_fixed(attr, value, (self.test_group.keySize // 8))
@iv.validator
def validate_iv(self, attr, value):
"""Validate IV size"""
self.validate_fixed(attr, value, (self.test_group.ivSize // 8))
@tag.validator
def validate_tag(self, attr, value):
"""Validate tag size"""
self.validate_fixed(attr, value, (self.test_group.tagSize // 8))
@property
def skip(self):
"""Reason for skipping test (if any)"""
if AeadCipherTestFlag.MODIFIED_TAG in self.flags:
# Our cipher abstraction covers only generating the tag,
# not comparing the tag to check for a match
return "modified tag"
@property
def key_failure(self):
"""Check if test case is expected to fail due to invalid key"""
return False
@property
def iv_failure(self):
"""Check if test case is expected to fail due to invalid IV"""
return False
def definition(self):
"""Generate source code for test definition"""
code = super().definition()
if not self.skip:
algorithm = "&%s_algorithm" % self.test_file.ALGORITHM
code += (
"CIPHER_TEST ( %s, %s,\n" % (self.test_name, algorithm) +
self.key.source("\tKEY") + ",\n" +
self.iv.source("\tIV") + ",\n" +
self.aad.source("\tADDITIONAL") + ",\n" +
self.msg.source("\tPLAINTEXT") + ",\n" +
self.ct.source("\tCIPHERTEXT") + ",\n" +
self.tag.source("\tAUTH") + " );\n"
)
return code
def invocation(self):
"""Generate source code for test invocation"""
code = super().invocation()
if self.key_failure:
code += "\tcipher_key_fail_ok ( &%s );\n" % self.test_name
elif self.iv_failure:
code += "\tcipher_iv_fail_ok ( &%s );\n" % self.test_name
elif self.failure:
raise ValueError("%d: unknown cipher failure reason" % self.tcId)
else:
code += "\tcipher_ok ( &%s );\n" % self.test_name
return code
@attrclass
class AeadCipherTestGroup(TestGroup):
"""An AEAD cipher test group"""
ivSize = scalar_field(int)
keySize = scalar_field(int)
tagSize = scalar_field(int)
tests = list_field(AeadCipherTestCase)
@attrclass
class AeadCipherTestFile(TestFile):
"""An AEAD cipher test file"""
SCHEMA: ClassVar = "aead_test_schema_v1.json"
testGroups = list_field(AeadCipherTestGroup)
##############################################################################
#
# GCM cipher tests
#
@attrclass
class GcmCipherTestCase(AeadCipherTestCase):
"""A GCM cipher test case"""
@property
def iv_failure(self):
"""Check if test case is expected to fail due to invalid IV"""
return AeadCipherTestFlag.ZERO_LENGTH_IV in self.flags
@attrclass
class GcmCipherTestGroup(AeadCipherTestGroup):
"""A GCM cipher test group"""
tests = list_field(GcmCipherTestCase)
@attrclass
class GcmCipherTestFile(AeadCipherTestFile):
"""A GCM cipher test file"""
testGroups = list_field(GcmCipherTestGroup)
@attrclass
class AesGcmCipherTestFile(GcmCipherTestFile):
"""An AES-GCM cipher test file"""
ALGORITHM: ClassVar = "aes_gcm"
LABEL: ClassVar = "AES-GCM"
SRCFILE: ClassVar = "aes_gcm_test.json"
##############################################################################
#
# Main program
@@ -756,6 +889,7 @@ def main():
# Read JSON inputs
classes = (
AesGcmCipherTestFile,
HkdfSha1TestFile,
HkdfSha256TestFile,
HkdfSha384TestFile,
File diff suppressed because it is too large Load Diff
+4
View File
@@ -52,6 +52,10 @@ FILE_LICENCE ( BSD2 );
/** Self-tests */
struct self_test wycheproof_test[] __self_test = {
{
.name = "wycheproof:aes-gcm",
.exec = wycheproof_aes_gcm_exec,
},
{
.name = "wycheproof:hkdf-sha1",
.exec = wycheproof_hkdf_sha1_exec,
+3
View File
@@ -10,16 +10,19 @@
FILE_LICENCE ( BSD2 );
#include <ipxe/crypto.h>
#include <ipxe/aes.h>
#include <ipxe/p256.h>
#include <ipxe/p384.h>
#include <ipxe/sha1.h>
#include <ipxe/sha256.h>
#include <ipxe/sha512.h>
#include <ipxe/x25519.h>
#include "cipher_test.h"
#include "exchange_test.h"
#include "hkdf_test.h"
#include "hmac_test.h"
extern void wycheproof_aes_gcm_exec ( void );
extern void wycheproof_hkdf_sha1_exec ( void );
extern void wycheproof_hkdf_sha256_exec ( void );
extern void wycheproof_hkdf_sha384_exec ( void );