Files
wolfssl/tests/api/test_frodokem.c
T
Sean Parkinson 607d7cfdb3 FrodoKEM: Initial implementation
Supports Fast C code, small C code, small stack and assembly for x86_64, Aarch64, Aarch32, Thumb2.
2026-07-17 22:38:55 +10:00

1499 lines
57 KiB
C

/* test_frodokem.c
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <tests/unit.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#ifdef WOLFSSL_HAVE_FRODOKEM
#include <wolfssl/wolfcrypt/wc_frodokem.h>
#include <wolfssl/wolfcrypt/hash.h>
#include <wolfssl/wolfcrypt/sha256.h>
#endif
#include <wolfssl/wolfcrypt/types.h>
#include <tests/api/api.h>
#include <tests/api/test_frodokem.h>
#ifdef WOLFSSL_HAVE_FRODOKEM
/* The set of compiled-in key types, used to drive the functional tests. */
static const int frodokem_types[] = {
#ifdef WOLFSSL_FRODOKEM_SHAKE
#ifdef WOLFSSL_WC_FRODOKEM_640
WC_FRODOKEM_640_SHAKE,
#endif
#ifdef WOLFSSL_WC_FRODOKEM_976
WC_FRODOKEM_976_SHAKE,
#endif
#ifdef WOLFSSL_WC_FRODOKEM_1344
WC_FRODOKEM_1344_SHAKE,
#endif
#endif /* WOLFSSL_FRODOKEM_SHAKE */
#ifdef WOLFSSL_FRODOKEM_AES
#ifdef WOLFSSL_WC_FRODOKEM_640
WC_FRODOKEM_640_AES,
#endif
#ifdef WOLFSSL_WC_FRODOKEM_976
WC_FRODOKEM_976_AES,
#endif
#ifdef WOLFSSL_WC_FRODOKEM_1344
WC_FRODOKEM_1344_AES,
#endif
#endif /* WOLFSSL_FRODOKEM_AES */
#ifdef WOLFSSL_FRODOKEM_EPHEMERAL
#ifdef WOLFSSL_FRODOKEM_SHAKE
#ifdef WOLFSSL_WC_FRODOKEM_640
WC_EFRODOKEM_640_SHAKE,
#endif
#ifdef WOLFSSL_WC_FRODOKEM_976
WC_EFRODOKEM_976_SHAKE,
#endif
#ifdef WOLFSSL_WC_FRODOKEM_1344
WC_EFRODOKEM_1344_SHAKE,
#endif
#endif /* WOLFSSL_FRODOKEM_SHAKE */
#ifdef WOLFSSL_FRODOKEM_AES
#ifdef WOLFSSL_WC_FRODOKEM_640
WC_EFRODOKEM_640_AES,
#endif
#ifdef WOLFSSL_WC_FRODOKEM_976
WC_EFRODOKEM_976_AES,
#endif
#ifdef WOLFSSL_WC_FRODOKEM_1344
WC_EFRODOKEM_1344_AES,
#endif
#endif /* WOLFSSL_FRODOKEM_AES */
#endif /* WOLFSSL_FRODOKEM_EPHEMERAL */
0 /* sentinel so the array is never empty */
};
#define FRODOKEM_TYPE_CNT \
((int)(sizeof(frodokem_types) / sizeof(frodokem_types[0])) - 1)
/* The KAT data is only used by the make-key/encapsulate/decapsulate KAT tests,
* all of which need key generation to reconstruct the key. */
#if !defined(NO_SHA256) && !defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY)
/* Known-answer test data derived from the official FrodoKEM and eFrodoKEM
* KAT vectors (PQCkemKAT_*.rsp, count 0), for both the SHAKE and AES matrix A
* generation variants. To keep the data compact the public key, secret key and
* ciphertext are stored as SHA-256 digests; the shared secret is stored in
* full. The seed randomness (kr = s || seedSE || z for key generation, er =
* u || salt for encapsulation) is what the NIST AES-CTR DRBG produces for KAT
* count 0. */
#if defined(WOLFSSL_WC_FRODOKEM_640) && defined(WOLFSSL_FRODOKEM_SHAKE)
static const byte frodokem_kr_640_SHAKE[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,
};
static const byte frodokem_er_640_SHAKE[] = {
0xeb,0x4a,0x7c,0x66,0xef,0x4e,0xba,0x2d,0xdb,0x38,0xc8,0x8d,
0x8b,0xc7,0x06,0xb1,0xd6,0x39,0x00,0x21,0x98,0x17,0x2a,0x7b,
0x19,0x42,0xec,0xa8,0xf6,0xc0,0x01,0xba,0x26,0x20,0x2b,0xee,
0x59,0xac,0x27,0x54,0x84,0xea,0x76,0x7d,0x41,0xd8,0xd3,0x57,
};
static const byte frodokem_hpk_640_SHAKE[] = {
0x10,0xe6,0x3e,0xfe,0x34,0x0a,0x73,0xd4,0x6d,0x78,0xf7,0x68,
0xcf,0xea,0x23,0x5d,0x0d,0x7d,0xa1,0xe9,0xc6,0x36,0xd6,0xed,
0xc3,0x2d,0x2a,0x4e,0xd4,0xb1,0x3c,0xdc,
};
static const byte frodokem_hsk_640_SHAKE[] = {
0x23,0x3a,0x52,0xe7,0x3b,0xf5,0xf1,0x6d,0xaa,0xd0,0x03,0xdd,
0x15,0xce,0xa2,0x8e,0x30,0xdb,0xe6,0x42,0x61,0x58,0xbe,0x48,
0x67,0x95,0x6a,0xff,0x03,0xd1,0x26,0x91,
};
static const byte frodokem_hct_640_SHAKE[] = {
0x27,0x11,0xc7,0xe8,0x63,0xc9,0xd8,0x1c,0x08,0x18,0x2b,0x3e,
0xe1,0xe1,0xc9,0x53,0xcb,0xff,0xb1,0x5d,0xd5,0x0b,0xff,0x88,
0x25,0xc6,0xc2,0xa7,0x1a,0x4f,0xd0,0x1d,
};
static const byte frodokem_ss_640_SHAKE[] = {
0x2e,0xd4,0x2c,0xe7,0xd5,0xdb,0xfb,0x11,0x5f,0x2e,0x2b,0xdc,
0xb6,0x50,0xb3,0xfa,
};
#define FKAT_640_SHAKE \
{ WC_FRODOKEM_640_SHAKE, \
frodokem_kr_640_SHAKE, \
(word32)sizeof(frodokem_kr_640_SHAKE), \
frodokem_er_640_SHAKE, \
(word32)sizeof(frodokem_er_640_SHAKE), \
frodokem_hpk_640_SHAKE, \
frodokem_hsk_640_SHAKE, \
frodokem_hct_640_SHAKE, \
frodokem_ss_640_SHAKE, \
(word32)sizeof(frodokem_ss_640_SHAKE) },
#else
#define FKAT_640_SHAKE
#endif
#if defined(WOLFSSL_WC_FRODOKEM_976) && defined(WOLFSSL_FRODOKEM_SHAKE)
static const byte frodokem_kr_976_SHAKE[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,0x3e,0x78,0x4c,0xcb,0x7e,0xbc,0xdc,0xfd,
0x45,0x54,0x2b,0x7f,0x6a,0xf7,0x78,0x74,0x2e,0x0f,0x44,0x79,
0x17,0x50,0x84,0xaa,
};
static const byte frodokem_er_976_SHAKE[] = {
0xee,0x71,0x67,0x62,0xc1,0x5e,0x3b,0x72,0xaa,0x76,0x50,0xa6,
0x3b,0x9a,0x51,0x00,0x40,0xb0,0x3c,0x0f,0xe7,0x04,0x75,0xc0,
0x46,0x3b,0xbc,0x45,0xa0,0xba,0x5b,0x79,0x80,0xdd,0x46,0xee,
0xf8,0x2f,0xb0,0x62,0x03,0x50,0x77,0xd0,0x42,0xf3,0x06,0xbb,
0x63,0x91,0x04,0x0e,0x0d,0xd9,0x65,0xf1,0xfd,0xa9,0xd1,0x83,
0xca,0x9f,0xcc,0xb4,0x8f,0xc0,0x10,0xb1,0x84,0xab,0x00,0x33,
};
static const byte frodokem_hpk_976_SHAKE[] = {
0x75,0xed,0x58,0xdd,0x9c,0xb2,0x50,0x1a,0xf1,0x3e,0x56,0xbb,
0xd8,0x57,0x9b,0x73,0x17,0x99,0x8d,0x82,0x8c,0xa2,0x93,0xe3,
0x98,0x09,0xf4,0x00,0x44,0x04,0xe7,0x89,
};
static const byte frodokem_hsk_976_SHAKE[] = {
0x2e,0x79,0x47,0x64,0xc6,0xa3,0xe7,0xc1,0xa1,0x6f,0x00,0xa3,
0xc3,0x45,0x59,0x1f,0xea,0x97,0x7c,0x21,0x3c,0x87,0x32,0xad,
0x37,0x1a,0xb9,0x60,0x3e,0x5d,0x63,0xa9,
};
static const byte frodokem_hct_976_SHAKE[] = {
0x6e,0x35,0x8f,0x98,0xcf,0x02,0xec,0xbf,0x38,0xb8,0xdf,0x50,
0x61,0x49,0x1d,0xec,0x1e,0xae,0x05,0x2e,0xa6,0x80,0x65,0x61,
0xc3,0xa4,0xaa,0x5e,0xd2,0x15,0xf7,0xa3,
};
static const byte frodokem_ss_976_SHAKE[] = {
0x5b,0x6e,0x5a,0x69,0xa3,0xd5,0xf8,0xe7,0x5e,0xea,0x3a,0x6e,
0x95,0x59,0x5e,0xd0,0x27,0x8d,0xa5,0x5b,0x8b,0x37,0x31,0x42,
};
#define FKAT_976_SHAKE \
{ WC_FRODOKEM_976_SHAKE, \
frodokem_kr_976_SHAKE, \
(word32)sizeof(frodokem_kr_976_SHAKE), \
frodokem_er_976_SHAKE, \
(word32)sizeof(frodokem_er_976_SHAKE), \
frodokem_hpk_976_SHAKE, \
frodokem_hsk_976_SHAKE, \
frodokem_hct_976_SHAKE, \
frodokem_ss_976_SHAKE, \
(word32)sizeof(frodokem_ss_976_SHAKE) },
#else
#define FKAT_976_SHAKE
#endif
#if defined(WOLFSSL_WC_FRODOKEM_1344) && defined(WOLFSSL_FRODOKEM_SHAKE)
static const byte frodokem_kr_1344_SHAKE[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,0x3e,0x78,0x4c,0xcb,0x7e,0xbc,0xdc,0xfd,
0x45,0x54,0x2b,0x7f,0x6a,0xf7,0x78,0x74,0x2e,0x0f,0x44,0x79,
0x17,0x50,0x84,0xaa,0x48,0x8b,0x3b,0x74,0x34,0x06,0x78,0xaa,
0x38,0xe2,0x2e,0x96,0x28,0xb0,0xa1,0x61,0xfd,0xeb,0x0b,0xd2,
0x52,0x17,0x3b,0x9c,
};
static const byte frodokem_er_1344_SHAKE[] = {
0x9f,0x08,0x58,0x76,0x87,0xff,0x66,0x76,0x5c,0x67,0x1d,0xe7,
0x3e,0x91,0x8d,0x28,0x23,0xca,0x57,0x3f,0xf4,0xe7,0xa3,0x1a,
0x91,0x60,0x32,0x40,0x26,0xe5,0x40,0xea,0xcb,0x3a,0x04,0xe0,
0xd5,0x4c,0x75,0xde,0xb9,0x70,0x5b,0xfd,0xfb,0xdf,0x93,0x5a,
0x75,0x28,0x80,0x2e,0xe6,0xe5,0xb0,0xc6,0xa7,0x3b,0x2b,0x76,
0x1d,0x9b,0xd0,0x84,0x8a,0x6e,0x4c,0xf3,0xfc,0x4c,0xa8,0x4f,
0x14,0xe0,0x33,0x1a,0xf3,0x5b,0xfe,0xf4,0x1e,0x42,0xb1,0x3a,
0x6d,0xae,0x6d,0xf9,0x37,0xf7,0x38,0xc1,0x85,0x7b,0xa1,0xca,
};
static const byte frodokem_hpk_1344_SHAKE[] = {
0x97,0x4d,0x55,0x14,0xfb,0x13,0x11,0x4b,0xb6,0x67,0x52,0x7e,
0x84,0x09,0x0b,0x6d,0xe0,0xdf,0xee,0xa0,0x14,0x35,0xc6,0x0a,
0x3e,0xdc,0x57,0x0d,0x33,0x1a,0x5b,0xd6,
};
static const byte frodokem_hsk_1344_SHAKE[] = {
0x02,0xd4,0xf7,0x10,0x96,0xb3,0x6f,0x46,0xa9,0x03,0xf7,0x7f,
0xcc,0x9b,0x77,0x64,0x36,0x6d,0x9a,0x8f,0x84,0xf0,0x6c,0x9f,
0x86,0xc4,0x64,0xcf,0x69,0x52,0x6d,0x8f,
};
static const byte frodokem_hct_1344_SHAKE[] = {
0xaa,0x07,0x79,0x97,0x59,0xe8,0x7a,0xd1,0xd0,0x80,0xb2,0xd1,
0xeb,0x31,0xd1,0x1e,0x3e,0xf9,0x3e,0x66,0x5d,0xf9,0xa8,0xba,
0xe5,0x02,0x7f,0x4e,0x40,0xfc,0x7a,0x46,
};
static const byte frodokem_ss_1344_SHAKE[] = {
0x8d,0x20,0xf9,0x71,0x46,0x4d,0xf1,0x9e,0x05,0x61,0xbd,0xd3,
0x85,0xaf,0xd0,0xe2,0xef,0x0c,0xe2,0x12,0xef,0xd4,0x5a,0x63,
0x2f,0x5d,0x2c,0x64,0xf3,0xd6,0x6a,0xac,
};
#define FKAT_1344_SHAKE \
{ WC_FRODOKEM_1344_SHAKE, \
frodokem_kr_1344_SHAKE, \
(word32)sizeof(frodokem_kr_1344_SHAKE), \
frodokem_er_1344_SHAKE, \
(word32)sizeof(frodokem_er_1344_SHAKE), \
frodokem_hpk_1344_SHAKE, \
frodokem_hsk_1344_SHAKE, \
frodokem_hct_1344_SHAKE, \
frodokem_ss_1344_SHAKE, \
(word32)sizeof(frodokem_ss_1344_SHAKE) },
#else
#define FKAT_1344_SHAKE
#endif
#if defined(WOLFSSL_WC_FRODOKEM_640) && defined(WOLFSSL_FRODOKEM_AES)
static const byte frodokem_kr_640_AES[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,
};
static const byte frodokem_er_640_AES[] = {
0xeb,0x4a,0x7c,0x66,0xef,0x4e,0xba,0x2d,0xdb,0x38,0xc8,0x8d,
0x8b,0xc7,0x06,0xb1,0xd6,0x39,0x00,0x21,0x98,0x17,0x2a,0x7b,
0x19,0x42,0xec,0xa8,0xf6,0xc0,0x01,0xba,0x26,0x20,0x2b,0xee,
0x59,0xac,0x27,0x54,0x84,0xea,0x76,0x7d,0x41,0xd8,0xd3,0x57,
};
static const byte frodokem_hpk_640_AES[] = {
0x44,0x19,0xf4,0xf1,0x4c,0x33,0x63,0x55,0x11,0x86,0xb9,0x93,
0x82,0xbf,0x3e,0x62,0xac,0x23,0x82,0xb7,0xb5,0xd4,0xca,0x70,
0x39,0x2d,0xda,0x58,0x69,0xc8,0xbd,0xa1,
};
static const byte frodokem_hsk_640_AES[] = {
0x1e,0xfb,0x89,0xe5,0xfc,0x52,0xd2,0xbb,0xab,0x4a,0xdb,0xbb,
0x65,0xda,0xfb,0x49,0x73,0xd8,0xbf,0x09,0x7f,0x86,0x7e,0xf8,
0x6d,0xbe,0xa2,0xfd,0x51,0xe5,0xe3,0xea,
};
static const byte frodokem_hct_640_AES[] = {
0x56,0xd2,0xbd,0xd0,0xc6,0xe9,0x2b,0xc3,0x65,0xf2,0x86,0xbe,
0x75,0x7e,0x46,0xa0,0xe0,0x40,0xc8,0x75,0xef,0x50,0x20,0xbb,
0xbf,0xab,0xee,0x00,0x28,0x52,0xe7,0xe4,
};
static const byte frodokem_ss_640_AES[] = {
0xee,0x5b,0xa8,0xce,0xbb,0x0b,0x41,0xe9,0x03,0x0c,0xa1,0xfb,
0xc3,0xbe,0xad,0xb9,
};
#define FKAT_640_AES \
{ WC_FRODOKEM_640_AES, \
frodokem_kr_640_AES, \
(word32)sizeof(frodokem_kr_640_AES), \
frodokem_er_640_AES, \
(word32)sizeof(frodokem_er_640_AES), \
frodokem_hpk_640_AES, \
frodokem_hsk_640_AES, \
frodokem_hct_640_AES, \
frodokem_ss_640_AES, \
(word32)sizeof(frodokem_ss_640_AES) },
#else
#define FKAT_640_AES
#endif
#if defined(WOLFSSL_WC_FRODOKEM_976) && defined(WOLFSSL_FRODOKEM_AES)
static const byte frodokem_kr_976_AES[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,0x3e,0x78,0x4c,0xcb,0x7e,0xbc,0xdc,0xfd,
0x45,0x54,0x2b,0x7f,0x6a,0xf7,0x78,0x74,0x2e,0x0f,0x44,0x79,
0x17,0x50,0x84,0xaa,
};
static const byte frodokem_er_976_AES[] = {
0xee,0x71,0x67,0x62,0xc1,0x5e,0x3b,0x72,0xaa,0x76,0x50,0xa6,
0x3b,0x9a,0x51,0x00,0x40,0xb0,0x3c,0x0f,0xe7,0x04,0x75,0xc0,
0x46,0x3b,0xbc,0x45,0xa0,0xba,0x5b,0x79,0x80,0xdd,0x46,0xee,
0xf8,0x2f,0xb0,0x62,0x03,0x50,0x77,0xd0,0x42,0xf3,0x06,0xbb,
0x63,0x91,0x04,0x0e,0x0d,0xd9,0x65,0xf1,0xfd,0xa9,0xd1,0x83,
0xca,0x9f,0xcc,0xb4,0x8f,0xc0,0x10,0xb1,0x84,0xab,0x00,0x33,
};
static const byte frodokem_hpk_976_AES[] = {
0x47,0x7d,0x38,0x49,0x0e,0x9c,0xf9,0x67,0xdd,0x03,0x8a,0xf6,
0xb9,0x34,0xd0,0x75,0x12,0x7c,0x0d,0x05,0x15,0x9d,0xe0,0x4f,
0xc9,0x37,0xb6,0x16,0x5b,0x3d,0xf2,0x1d,
};
static const byte frodokem_hsk_976_AES[] = {
0x01,0x6e,0xbc,0x6e,0x61,0xcd,0xcf,0x75,0xac,0xf2,0x17,0xe3,
0x7b,0xc9,0x2c,0xb5,0x57,0x7f,0x61,0xd1,0x4f,0x2c,0x83,0x8b,
0xd1,0xa2,0x67,0x5a,0x4d,0x34,0x26,0xe8,
};
static const byte frodokem_hct_976_AES[] = {
0x64,0x1f,0xa3,0x00,0x89,0xd3,0x97,0x82,0x8c,0xa9,0xd1,0xc0,
0xf2,0x80,0x7b,0xeb,0xe8,0x70,0xa3,0xbd,0xc7,0xdc,0x5b,0xa8,
0x86,0x6c,0x54,0x3e,0xbf,0x47,0xbc,0x98,
};
static const byte frodokem_ss_976_AES[] = {
0xd9,0x38,0x8d,0x1b,0x0f,0x97,0xc5,0xdb,0x5f,0x9b,0x4a,0x7e,
0x99,0x42,0x7c,0xfe,0x90,0xe3,0xe1,0x0c,0x5c,0x56,0x9d,0x02,
};
#define FKAT_976_AES \
{ WC_FRODOKEM_976_AES, \
frodokem_kr_976_AES, \
(word32)sizeof(frodokem_kr_976_AES), \
frodokem_er_976_AES, \
(word32)sizeof(frodokem_er_976_AES), \
frodokem_hpk_976_AES, \
frodokem_hsk_976_AES, \
frodokem_hct_976_AES, \
frodokem_ss_976_AES, \
(word32)sizeof(frodokem_ss_976_AES) },
#else
#define FKAT_976_AES
#endif
#if defined(WOLFSSL_WC_FRODOKEM_1344) && defined(WOLFSSL_FRODOKEM_AES)
static const byte frodokem_kr_1344_AES[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,0x3e,0x78,0x4c,0xcb,0x7e,0xbc,0xdc,0xfd,
0x45,0x54,0x2b,0x7f,0x6a,0xf7,0x78,0x74,0x2e,0x0f,0x44,0x79,
0x17,0x50,0x84,0xaa,0x48,0x8b,0x3b,0x74,0x34,0x06,0x78,0xaa,
0x38,0xe2,0x2e,0x96,0x28,0xb0,0xa1,0x61,0xfd,0xeb,0x0b,0xd2,
0x52,0x17,0x3b,0x9c,
};
static const byte frodokem_er_1344_AES[] = {
0x9f,0x08,0x58,0x76,0x87,0xff,0x66,0x76,0x5c,0x67,0x1d,0xe7,
0x3e,0x91,0x8d,0x28,0x23,0xca,0x57,0x3f,0xf4,0xe7,0xa3,0x1a,
0x91,0x60,0x32,0x40,0x26,0xe5,0x40,0xea,0xcb,0x3a,0x04,0xe0,
0xd5,0x4c,0x75,0xde,0xb9,0x70,0x5b,0xfd,0xfb,0xdf,0x93,0x5a,
0x75,0x28,0x80,0x2e,0xe6,0xe5,0xb0,0xc6,0xa7,0x3b,0x2b,0x76,
0x1d,0x9b,0xd0,0x84,0x8a,0x6e,0x4c,0xf3,0xfc,0x4c,0xa8,0x4f,
0x14,0xe0,0x33,0x1a,0xf3,0x5b,0xfe,0xf4,0x1e,0x42,0xb1,0x3a,
0x6d,0xae,0x6d,0xf9,0x37,0xf7,0x38,0xc1,0x85,0x7b,0xa1,0xca,
};
static const byte frodokem_hpk_1344_AES[] = {
0xe2,0x83,0xbf,0xd5,0x9b,0xcc,0xa4,0xda,0x53,0x80,0xbc,0xa9,
0xe4,0x3c,0x0d,0xfc,0xc3,0xb3,0xb2,0xb4,0xd3,0xf3,0xa0,0x2c,
0x64,0x2e,0x0d,0x43,0x92,0x03,0xee,0x81,
};
static const byte frodokem_hsk_1344_AES[] = {
0xee,0x4a,0x33,0x60,0x94,0x5b,0x71,0x8f,0xb1,0x04,0x74,0xe9,
0xc6,0x64,0xe2,0xc3,0x9b,0xd7,0x7d,0xfd,0x6b,0xfe,0xba,0x73,
0x3c,0x10,0xd2,0x69,0x50,0xf4,0x62,0xce,
};
static const byte frodokem_hct_1344_AES[] = {
0x4a,0x37,0x7d,0xba,0x12,0xe3,0x78,0xeb,0x9a,0x82,0x32,0x02,
0x81,0xc9,0xe8,0x61,0x08,0xd8,0x31,0xb2,0xde,0xba,0xe1,0xe1,
0x9c,0xc5,0x19,0x5f,0xe8,0x6d,0x73,0x20,
};
static const byte frodokem_ss_1344_AES[] = {
0x37,0x69,0x55,0x16,0x12,0x73,0xfc,0x66,0x7f,0x3f,0xea,0xe5,
0xec,0x98,0x68,0x18,0x20,0xdb,0xd7,0x59,0x97,0x1b,0xb0,0xa2,
0xd2,0xbe,0xc4,0x51,0x0f,0x55,0x7e,0x83,
};
#define FKAT_1344_AES \
{ WC_FRODOKEM_1344_AES, \
frodokem_kr_1344_AES, \
(word32)sizeof(frodokem_kr_1344_AES), \
frodokem_er_1344_AES, \
(word32)sizeof(frodokem_er_1344_AES), \
frodokem_hpk_1344_AES, \
frodokem_hsk_1344_AES, \
frodokem_hct_1344_AES, \
frodokem_ss_1344_AES, \
(word32)sizeof(frodokem_ss_1344_AES) },
#else
#define FKAT_1344_AES
#endif
#if defined(WOLFSSL_WC_FRODOKEM_640) && defined(WOLFSSL_FRODOKEM_SHAKE) && \
defined(WOLFSSL_FRODOKEM_EPHEMERAL)
static const byte frodokem_kr_E640_SHAKE[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
};
static const byte frodokem_er_E640_SHAKE[] = {
0x33,0xb3,0xc0,0x75,0x07,0xe4,0x20,0x17,0x48,0x49,0x4d,0x83,
0x2b,0x6e,0xe2,0xa6,
};
static const byte frodokem_hpk_E640_SHAKE[] = {
0x49,0xa3,0x03,0x46,0x0f,0x09,0x77,0x33,0x9c,0xbd,0x2c,0x1b,
0x5a,0xa0,0xe7,0xaf,0x44,0xc5,0x02,0x49,0x17,0xf5,0xf7,0xac,
0xed,0x47,0x25,0xe9,0xd4,0xa2,0xc6,0x14,
};
static const byte frodokem_hsk_E640_SHAKE[] = {
0x85,0xd0,0xe3,0x16,0x3f,0x8c,0xae,0xbe,0xe1,0xb5,0x48,0x37,
0xa4,0x70,0xe6,0xb0,0x49,0x83,0x78,0x4e,0x3c,0x3d,0x2b,0x2f,
0x03,0x6b,0x7f,0x95,0x87,0x55,0x08,0xaa,
};
static const byte frodokem_hct_E640_SHAKE[] = {
0x88,0xba,0x53,0x7b,0x53,0x6d,0x89,0xfd,0x0b,0x84,0xf8,0x60,
0x4a,0x60,0x40,0xa9,0xdd,0x96,0x11,0x4e,0xe6,0xad,0x43,0x23,
0x5c,0x95,0x1e,0xdf,0x42,0x6c,0x68,0x0d,
};
static const byte frodokem_ss_E640_SHAKE[] = {
0x72,0x97,0x80,0xfc,0x51,0x65,0x7e,0x21,0x35,0x7f,0x03,0xa3,
0x38,0x11,0x65,0x69,
};
#define FKAT_E640_SHAKE \
{ WC_EFRODOKEM_640_SHAKE, \
frodokem_kr_E640_SHAKE, \
(word32)sizeof(frodokem_kr_E640_SHAKE), \
frodokem_er_E640_SHAKE, \
(word32)sizeof(frodokem_er_E640_SHAKE), \
frodokem_hpk_E640_SHAKE, \
frodokem_hsk_E640_SHAKE, \
frodokem_hct_E640_SHAKE, \
frodokem_ss_E640_SHAKE, \
(word32)sizeof(frodokem_ss_E640_SHAKE) },
#else
#define FKAT_E640_SHAKE
#endif
#if defined(WOLFSSL_WC_FRODOKEM_976) && defined(WOLFSSL_FRODOKEM_SHAKE) && \
defined(WOLFSSL_FRODOKEM_EPHEMERAL)
static const byte frodokem_kr_E976_SHAKE[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,
};
static const byte frodokem_er_E976_SHAKE[] = {
0xeb,0x4a,0x7c,0x66,0xef,0x4e,0xba,0x2d,0xdb,0x38,0xc8,0x8d,
0x8b,0xc7,0x06,0xb1,0xd6,0x39,0x00,0x21,0x98,0x17,0x2a,0x7b,
};
static const byte frodokem_hpk_E976_SHAKE[] = {
0x94,0x9c,0xe7,0x6a,0xae,0x38,0xde,0xcd,0x41,0xe2,0x32,0x06,
0x23,0x62,0xad,0xb8,0x92,0x46,0xba,0xce,0xfe,0x22,0x1f,0x80,
0x32,0x5d,0x45,0x49,0x02,0x63,0x1c,0xe4,
};
static const byte frodokem_hsk_E976_SHAKE[] = {
0x3d,0x5a,0x3a,0x15,0x0f,0xee,0xd6,0x4a,0x86,0x1f,0x7e,0x87,
0xd4,0xee,0x83,0xb1,0x35,0xc8,0xb1,0xbe,0x43,0x9e,0x14,0x21,
0xc4,0x19,0xbf,0x86,0xac,0x15,0xdc,0x50,
};
static const byte frodokem_hct_E976_SHAKE[] = {
0xdf,0x84,0x22,0xbf,0xda,0xe4,0xe3,0x13,0x55,0x22,0x54,0xd4,
0xc2,0x91,0xeb,0x17,0xf0,0xc6,0x0d,0x5c,0x46,0x01,0x3a,0x26,
0x79,0x21,0x45,0xa4,0xc4,0x6f,0x4b,0x0e,
};
static const byte frodokem_ss_E976_SHAKE[] = {
0xa9,0x81,0x65,0x53,0x9a,0x4a,0xad,0x97,0x90,0x23,0xd6,0x7b,
0x43,0x5d,0x31,0x6f,0x00,0x7c,0x86,0xee,0xaf,0xdb,0x63,0xc7,
};
#define FKAT_E976_SHAKE \
{ WC_EFRODOKEM_976_SHAKE, \
frodokem_kr_E976_SHAKE, \
(word32)sizeof(frodokem_kr_E976_SHAKE), \
frodokem_er_E976_SHAKE, \
(word32)sizeof(frodokem_er_E976_SHAKE), \
frodokem_hpk_E976_SHAKE, \
frodokem_hsk_E976_SHAKE, \
frodokem_hct_E976_SHAKE, \
frodokem_ss_E976_SHAKE, \
(word32)sizeof(frodokem_ss_E976_SHAKE) },
#else
#define FKAT_E976_SHAKE
#endif
#if defined(WOLFSSL_WC_FRODOKEM_1344) && defined(WOLFSSL_FRODOKEM_SHAKE) && \
defined(WOLFSSL_FRODOKEM_EPHEMERAL)
static const byte frodokem_kr_E1344_SHAKE[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,0x3e,0x78,0x4c,0xcb,0x7e,0xbc,0xdc,0xfd,
0x45,0x54,0x2b,0x7f,0x6a,0xf7,0x78,0x74,
};
static const byte frodokem_er_E1344_SHAKE[] = {
0x8b,0xf0,0xf4,0x59,0xf0,0xfb,0x3e,0xa8,0xd3,0x27,0x64,0xc2,
0x59,0xae,0x63,0x11,0x78,0x97,0x6b,0xaf,0x36,0x83,0xd3,0x33,
0x83,0x18,0x8a,0x65,0xa4,0xc2,0x44,0x9b,
};
static const byte frodokem_hpk_E1344_SHAKE[] = {
0x45,0x4d,0x55,0x2f,0x3c,0x25,0xaa,0xf0,0xe5,0xac,0xc1,0xa4,
0xfc,0x43,0x10,0x98,0xb9,0x0c,0xe3,0x99,0x3e,0x86,0x42,0x68,
0xa2,0x79,0x5a,0xe7,0xff,0x3c,0xe5,0xca,
};
static const byte frodokem_hsk_E1344_SHAKE[] = {
0xbe,0x73,0xb2,0x19,0x69,0x05,0x4a,0x4f,0xd4,0x45,0x25,0x08,
0x23,0xbe,0xd8,0xec,0x91,0xe6,0xa2,0x52,0x1b,0xce,0x0a,0xd0,
0x97,0x49,0xdd,0x1e,0x6c,0xb8,0xd6,0x6f,
};
static const byte frodokem_hct_E1344_SHAKE[] = {
0x2c,0x76,0xc5,0x40,0xee,0xba,0x95,0x1c,0x7e,0x16,0x68,0x99,
0x3d,0x13,0xa3,0xe3,0xcc,0xfd,0xc8,0xbc,0xba,0x29,0x44,0x68,
0x54,0x80,0xc2,0xb8,0x82,0x50,0xcc,0xf9,
};
static const byte frodokem_ss_E1344_SHAKE[] = {
0x6d,0x69,0xdf,0x1a,0x90,0x96,0x8e,0xab,0xad,0xa6,0x9c,0xd3,
0x0e,0xc6,0x81,0x3a,0x44,0x06,0x30,0x9d,0xac,0x17,0x44,0x29,
0xa0,0x12,0x08,0x52,0xbf,0x82,0x64,0x60,
};
#define FKAT_E1344_SHAKE \
{ WC_EFRODOKEM_1344_SHAKE, \
frodokem_kr_E1344_SHAKE, \
(word32)sizeof(frodokem_kr_E1344_SHAKE), \
frodokem_er_E1344_SHAKE, \
(word32)sizeof(frodokem_er_E1344_SHAKE), \
frodokem_hpk_E1344_SHAKE, \
frodokem_hsk_E1344_SHAKE, \
frodokem_hct_E1344_SHAKE, \
frodokem_ss_E1344_SHAKE, \
(word32)sizeof(frodokem_ss_E1344_SHAKE) },
#else
#define FKAT_E1344_SHAKE
#endif
#if defined(WOLFSSL_WC_FRODOKEM_640) && defined(WOLFSSL_FRODOKEM_AES) && \
defined(WOLFSSL_FRODOKEM_EPHEMERAL)
static const byte frodokem_kr_E640_AES[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
};
static const byte frodokem_er_E640_AES[] = {
0x33,0xb3,0xc0,0x75,0x07,0xe4,0x20,0x17,0x48,0x49,0x4d,0x83,
0x2b,0x6e,0xe2,0xa6,
};
static const byte frodokem_hpk_E640_AES[] = {
0x3d,0x9e,0xc6,0x83,0x5b,0x6e,0x15,0xd8,0x15,0xc2,0xf8,0x45,
0x48,0x42,0x79,0xa7,0xcc,0x4b,0xf3,0xcc,0xc7,0x7d,0x00,0x29,
0xd3,0xb6,0x95,0x47,0x34,0x19,0xf3,0x29,
};
static const byte frodokem_hsk_E640_AES[] = {
0x80,0x96,0xbd,0x18,0x6c,0xf9,0x9d,0xfa,0x98,0x9a,0x78,0xe2,
0x95,0xe9,0x58,0xcc,0x83,0x39,0xaf,0x24,0x5d,0x7b,0xe3,0x8d,
0x88,0x70,0x4f,0x32,0x9a,0x00,0xba,0x66,
};
static const byte frodokem_hct_E640_AES[] = {
0xa2,0xdb,0xb4,0xa4,0xbc,0x4b,0x72,0x92,0xf3,0x68,0xe7,0x1a,
0x34,0x51,0xad,0x8d,0xcd,0x10,0x12,0x32,0x68,0x0c,0x24,0xa6,
0x92,0xcc,0xe8,0xca,0xd4,0x03,0x48,0xea,
};
static const byte frodokem_ss_E640_AES[] = {
0x9f,0x54,0x37,0x7d,0x45,0x20,0x90,0xf3,0x63,0x1e,0x45,0xb9,
0x39,0x9a,0x28,0x92,
};
#define FKAT_E640_AES \
{ WC_EFRODOKEM_640_AES, \
frodokem_kr_E640_AES, \
(word32)sizeof(frodokem_kr_E640_AES), \
frodokem_er_E640_AES, \
(word32)sizeof(frodokem_er_E640_AES), \
frodokem_hpk_E640_AES, \
frodokem_hsk_E640_AES, \
frodokem_hct_E640_AES, \
frodokem_ss_E640_AES, \
(word32)sizeof(frodokem_ss_E640_AES) },
#else
#define FKAT_E640_AES
#endif
#if defined(WOLFSSL_WC_FRODOKEM_976) && defined(WOLFSSL_FRODOKEM_AES) && \
defined(WOLFSSL_FRODOKEM_EPHEMERAL)
static const byte frodokem_kr_E976_AES[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,
};
static const byte frodokem_er_E976_AES[] = {
0xeb,0x4a,0x7c,0x66,0xef,0x4e,0xba,0x2d,0xdb,0x38,0xc8,0x8d,
0x8b,0xc7,0x06,0xb1,0xd6,0x39,0x00,0x21,0x98,0x17,0x2a,0x7b,
};
static const byte frodokem_hpk_E976_AES[] = {
0xc6,0xc9,0x25,0x07,0xc1,0xf4,0x8c,0x20,0x89,0x76,0x8d,0xe0,
0x14,0x22,0xa5,0x9c,0x2b,0xb8,0x5c,0xe5,0x6e,0x09,0x56,0x5c,
0x5f,0x07,0xa9,0x0f,0x84,0x9c,0x45,0xc0,
};
static const byte frodokem_hsk_E976_AES[] = {
0x07,0x74,0x6e,0x26,0x0b,0x4c,0x11,0x01,0x15,0x58,0xa9,0xb5,
0x5e,0x1c,0x27,0xa3,0x76,0x0a,0x3b,0x98,0x0e,0x76,0xab,0x22,
0x19,0xaf,0x01,0x85,0x41,0xff,0x00,0x45,
};
static const byte frodokem_hct_E976_AES[] = {
0x16,0x05,0x08,0xa0,0xd9,0x3e,0x28,0xcd,0xd7,0xd7,0xf3,0xac,
0x31,0x66,0x79,0x20,0x4e,0x24,0xf7,0x7d,0x57,0x1d,0x6d,0x31,
0x8f,0x41,0x41,0xf2,0x51,0x87,0xfd,0xc2,
};
static const byte frodokem_ss_E976_AES[] = {
0x59,0x4d,0xe8,0x44,0x73,0xb3,0x40,0x8e,0x35,0xf6,0xc4,0xd1,
0xf2,0xf2,0xec,0x3b,0x56,0xd2,0xdd,0xa9,0x6f,0xa2,0x34,0x96,
};
#define FKAT_E976_AES \
{ WC_EFRODOKEM_976_AES, \
frodokem_kr_E976_AES, \
(word32)sizeof(frodokem_kr_E976_AES), \
frodokem_er_E976_AES, \
(word32)sizeof(frodokem_er_E976_AES), \
frodokem_hpk_E976_AES, \
frodokem_hsk_E976_AES, \
frodokem_hct_E976_AES, \
frodokem_ss_E976_AES, \
(word32)sizeof(frodokem_ss_E976_AES) },
#else
#define FKAT_E976_AES
#endif
#if defined(WOLFSSL_WC_FRODOKEM_1344) && defined(WOLFSSL_FRODOKEM_AES) && \
defined(WOLFSSL_FRODOKEM_EPHEMERAL)
static const byte frodokem_kr_E1344_AES[] = {
0x7c,0x99,0x35,0xa0,0xb0,0x76,0x94,0xaa,0x0c,0x6d,0x10,0xe4,
0xdb,0x6b,0x1a,0xdd,0x2f,0xd8,0x1a,0x25,0xcc,0xb1,0x48,0x03,
0x2d,0xcd,0x73,0x99,0x36,0x73,0x7f,0x2d,0xb5,0x05,0xd7,0xcf,
0xad,0x1b,0x49,0x74,0x99,0x32,0x3c,0x86,0x86,0x32,0x5e,0x47,
0x92,0xf2,0x67,0xaa,0xfa,0x3f,0x87,0xca,0x60,0xd0,0x1c,0xb5,
0x4f,0x29,0x20,0x2a,0x3e,0x78,0x4c,0xcb,0x7e,0xbc,0xdc,0xfd,
0x45,0x54,0x2b,0x7f,0x6a,0xf7,0x78,0x74,
};
static const byte frodokem_er_E1344_AES[] = {
0x8b,0xf0,0xf4,0x59,0xf0,0xfb,0x3e,0xa8,0xd3,0x27,0x64,0xc2,
0x59,0xae,0x63,0x11,0x78,0x97,0x6b,0xaf,0x36,0x83,0xd3,0x33,
0x83,0x18,0x8a,0x65,0xa4,0xc2,0x44,0x9b,
};
static const byte frodokem_hpk_E1344_AES[] = {
0xf4,0xc8,0x3f,0xd6,0xbd,0xbd,0xd1,0x49,0x30,0x7f,0x72,0xd6,
0x7b,0xdd,0x83,0xaa,0x49,0xcd,0xa6,0xde,0xa6,0x9b,0xf3,0x64,
0xe7,0xef,0x27,0x76,0xc3,0xb7,0x21,0xff,
};
static const byte frodokem_hsk_E1344_AES[] = {
0xe4,0x99,0x44,0x64,0x5a,0xa1,0x19,0xb7,0x53,0xe1,0xdd,0x48,
0x68,0xb4,0x19,0xc4,0x21,0xe9,0x04,0x61,0xde,0x23,0xbb,0xdc,
0xd5,0x5e,0xa2,0x8c,0xa8,0xd1,0x59,0xf9,
};
static const byte frodokem_hct_E1344_AES[] = {
0x25,0x27,0xe2,0xb6,0x22,0xec,0xa7,0x6d,0xc8,0xea,0x48,0x9d,
0x51,0x6c,0x68,0x5c,0x4c,0x67,0x75,0x11,0x27,0xfd,0x3f,0x49,
0x25,0xc6,0x91,0x55,0x60,0xe9,0xe8,0x43,
};
static const byte frodokem_ss_E1344_AES[] = {
0xb2,0x43,0xfe,0x6d,0x7c,0x9b,0x38,0x29,0x25,0x2d,0x5a,0xec,
0x09,0x0a,0x47,0x09,0xf5,0xe3,0x96,0xfd,0xef,0xe4,0xef,0x1a,
0xa4,0xae,0x6c,0x94,0x98,0xcb,0xce,0x15,
};
#define FKAT_E1344_AES \
{ WC_EFRODOKEM_1344_AES, \
frodokem_kr_E1344_AES, \
(word32)sizeof(frodokem_kr_E1344_AES), \
frodokem_er_E1344_AES, \
(word32)sizeof(frodokem_er_E1344_AES), \
frodokem_hpk_E1344_AES, \
frodokem_hsk_E1344_AES, \
frodokem_hct_E1344_AES, \
frodokem_ss_E1344_AES, \
(word32)sizeof(frodokem_ss_E1344_AES) },
#else
#define FKAT_E1344_AES
#endif
/* One known-answer entry per compiled parameter set / variant. */
typedef struct FrodoKemKat {
int type;
const byte* kr;
word32 krLen;
const byte* er;
word32 erLen;
const byte* hpk;
const byte* hsk;
const byte* hct;
const byte* ss;
word32 ssLen;
} FrodoKemKat;
static const FrodoKemKat frodokem_kats[] = {
FKAT_640_SHAKE FKAT_976_SHAKE FKAT_1344_SHAKE
FKAT_640_AES FKAT_976_AES FKAT_1344_AES
FKAT_E640_SHAKE FKAT_E976_SHAKE FKAT_E1344_SHAKE
FKAT_E640_AES FKAT_E976_AES FKAT_E1344_AES
};
#define FRODOKEM_KAT_CNT \
((int)(sizeof(frodokem_kats) / sizeof(frodokem_kats[0])))
#endif /* !NO_SHA256 && !WOLFSSL_FRODOKEM_NO_MAKE_KEY */
#endif /* WOLFSSL_HAVE_FRODOKEM */
/* KAT: key generation. Regenerate each key from fixed randomness and check the
* encoded public and private keys against the expected SHA-256 digests. */
int test_wc_frodokem_make_key_kats(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(NO_SHA256) && \
!defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY)
int i;
FrodoKemKey* key = NULL;
byte* buf = NULL;
byte hash[WC_SHA256_DIGEST_SIZE];
word32 pkLen = 0;
word32 skLen = 0;
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
buf = (byte*)XMALLOC(FRODOKEM_MAX_PRIVATE_KEY_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(buf);
for (i = 0; (i < FRODOKEM_KAT_CNT) && EXPECT_SUCCESS(); i++) {
const FrodoKemKat* k = &frodokem_kats[i];
ExpectIntEQ(wc_FrodoKemKey_Init(key, k->type, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_MakeKeyWithRandom(key, k->kr,
(int)k->krLen), 0);
ExpectIntEQ(wc_FrodoKemKey_PublicKeySize(key, &pkLen), 0);
ExpectIntEQ(wc_FrodoKemKey_EncodePublicKey(key, buf, pkLen), 0);
ExpectIntEQ(wc_Sha256Hash(buf, pkLen, hash), 0);
ExpectIntEQ(XMEMCMP(hash, k->hpk, WC_SHA256_DIGEST_SIZE), 0);
ExpectIntEQ(wc_FrodoKemKey_PrivateKeySize(key, &skLen), 0);
ExpectIntEQ(wc_FrodoKemKey_EncodePrivateKey(key, buf, skLen), 0);
ExpectIntEQ(wc_Sha256Hash(buf, skLen, hash), 0);
ExpectIntEQ(XMEMCMP(hash, k->hsk, WC_SHA256_DIGEST_SIZE), 0);
wc_FrodoKemKey_Free(key);
}
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* KAT: encapsulation. Recreate the key, encapsulate with fixed randomness and
* check the ciphertext digest and shared secret against expected values. */
int test_wc_frodokem_encapsulate_kats(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(NO_SHA256) && \
!defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY) && \
!defined(WOLFSSL_FRODOKEM_NO_ENCAPSULATE)
int i;
FrodoKemKey* key = NULL;
byte* ct = NULL;
byte hash[WC_SHA256_DIGEST_SIZE];
byte ss[FRODOKEM_MAX_LENSEC];
word32 ctLen = 0;
word32 ssLen = 0;
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
ct = (byte*)XMALLOC(FRODOKEM_MAX_CIPHER_TEXT_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(ct);
for (i = 0; (i < FRODOKEM_KAT_CNT) && EXPECT_SUCCESS(); i++) {
const FrodoKemKat* k = &frodokem_kats[i];
ExpectIntEQ(wc_FrodoKemKey_Init(key, k->type, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_MakeKeyWithRandom(key, k->kr,
(int)k->krLen), 0);
ExpectIntEQ(wc_FrodoKemKey_CipherTextSize(key, &ctLen), 0);
ExpectIntEQ(wc_FrodoKemKey_SharedSecretSize(key, &ssLen), 0);
ExpectIntEQ(wc_FrodoKemKey_EncapsulateWithRandom(key, ct, ss, k->er,
(int)k->erLen), 0);
ExpectIntEQ(wc_Sha256Hash(ct, ctLen, hash), 0);
ExpectIntEQ(XMEMCMP(hash, k->hct, WC_SHA256_DIGEST_SIZE), 0);
ExpectIntEQ(XMEMCMP(ss, k->ss, ssLen), 0);
wc_FrodoKemKey_Free(key);
}
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* KAT: decapsulation. Recreate the key and ciphertext, decapsulate and check
* the recovered shared secret against the expected value. */
int test_wc_frodokem_decapsulate_kats(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(NO_SHA256) && \
!defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY) && \
!defined(WOLFSSL_FRODOKEM_NO_ENCAPSULATE) && \
!defined(WOLFSSL_FRODOKEM_NO_DECAPSULATE)
int i;
FrodoKemKey* key = NULL;
byte* ct = NULL;
byte ss[FRODOKEM_MAX_LENSEC];
byte ssDec[FRODOKEM_MAX_LENSEC];
word32 ctLen = 0;
word32 ssLen = 0;
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
ct = (byte*)XMALLOC(FRODOKEM_MAX_CIPHER_TEXT_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(ct);
for (i = 0; (i < FRODOKEM_KAT_CNT) && EXPECT_SUCCESS(); i++) {
const FrodoKemKat* k = &frodokem_kats[i];
ExpectIntEQ(wc_FrodoKemKey_Init(key, k->type, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_MakeKeyWithRandom(key, k->kr,
(int)k->krLen), 0);
ExpectIntEQ(wc_FrodoKemKey_CipherTextSize(key, &ctLen), 0);
ExpectIntEQ(wc_FrodoKemKey_SharedSecretSize(key, &ssLen), 0);
ExpectIntEQ(wc_FrodoKemKey_EncapsulateWithRandom(key, ct, ss, k->er,
(int)k->erLen), 0);
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(key, ssDec, ct, ctLen), 0);
ExpectIntEQ(XMEMCMP(ssDec, k->ss, ssLen), 0);
wc_FrodoKemKey_Free(key);
}
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* Full RNG-based round trip for every compiled variant: the decapsulated
* shared secret must equal the encapsulated one. */
int test_wc_frodokem_roundtrip(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(WC_NO_RNG) && \
!defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY) && \
!defined(WOLFSSL_FRODOKEM_NO_ENCAPSULATE) && \
!defined(WOLFSSL_FRODOKEM_NO_DECAPSULATE)
int i;
FrodoKemKey* key = NULL;
WC_RNG rng;
byte* ct = NULL;
byte ss[FRODOKEM_MAX_LENSEC];
byte ssDec[FRODOKEM_MAX_LENSEC];
word32 ctLen = 0;
word32 ssLen = 0;
int rngInit = 0;
XMEMSET(&rng, 0, sizeof(rng));
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
ct = (byte*)XMALLOC(FRODOKEM_MAX_CIPHER_TEXT_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(ct);
ExpectIntEQ(wc_InitRng(&rng), 0);
if (EXPECT_SUCCESS()) {
rngInit = 1;
}
for (i = 0; (i < FRODOKEM_TYPE_CNT) && EXPECT_SUCCESS(); i++) {
ExpectIntEQ(wc_FrodoKemKey_Init(key, frodokem_types[i], NULL,
INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_CipherTextSize(key, &ctLen), 0);
ExpectIntEQ(wc_FrodoKemKey_SharedSecretSize(key, &ssLen), 0);
ExpectIntEQ(wc_FrodoKemKey_MakeKey(key, &rng), 0);
ExpectIntEQ(wc_FrodoKemKey_Encapsulate(key, ct, ss, &rng), 0);
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(key, ssDec, ct, ctLen), 0);
ExpectIntEQ(XMEMCMP(ss, ssDec, ssLen), 0);
wc_FrodoKemKey_Free(key);
}
if (rngInit) {
DoExpectIntEQ(wc_FreeRng(&rng), 0);
}
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* Encode then decode the public and private keys and confirm the decoded key
* pair still produces matching shared secrets. */
int test_wc_frodokem_encode_decode(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(WC_NO_RNG) && \
!defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY) && \
!defined(WOLFSSL_FRODOKEM_NO_ENCAPSULATE) && \
!defined(WOLFSSL_FRODOKEM_NO_DECAPSULATE)
int i;
FrodoKemKey* key = NULL;
FrodoKemKey* pubKey = NULL;
FrodoKemKey* privKey = NULL;
WC_RNG rng;
byte* pkBuf = NULL;
byte* skBuf = NULL;
byte* ct = NULL;
byte ss[FRODOKEM_MAX_LENSEC];
byte ssDec[FRODOKEM_MAX_LENSEC];
word32 pkLen = 0;
word32 skLen = 0;
word32 ctLen = 0;
word32 ssLen = 0;
int rngInit = 0;
XMEMSET(&rng, 0, sizeof(rng));
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
pubKey = (FrodoKemKey*)XMALLOC(sizeof(*pubKey), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(pubKey);
privKey = (FrodoKemKey*)XMALLOC(sizeof(*privKey), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(privKey);
pkBuf = (byte*)XMALLOC(FRODOKEM_MAX_PUBLIC_KEY_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(pkBuf);
skBuf = (byte*)XMALLOC(FRODOKEM_MAX_PRIVATE_KEY_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(skBuf);
ct = (byte*)XMALLOC(FRODOKEM_MAX_CIPHER_TEXT_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(ct);
ExpectIntEQ(wc_InitRng(&rng), 0);
if (EXPECT_SUCCESS()) {
rngInit = 1;
}
for (i = 0; (i < FRODOKEM_TYPE_CNT) && EXPECT_SUCCESS(); i++) {
int type = frodokem_types[i];
ExpectIntEQ(wc_FrodoKemKey_Init(key, type, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_Init(pubKey, type, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_Init(privKey, type, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_PublicKeySize(key, &pkLen), 0);
ExpectIntEQ(wc_FrodoKemKey_PrivateKeySize(key, &skLen), 0);
ExpectIntEQ(wc_FrodoKemKey_CipherTextSize(key, &ctLen), 0);
ExpectIntEQ(wc_FrodoKemKey_SharedSecretSize(key, &ssLen), 0);
ExpectIntEQ(wc_FrodoKemKey_MakeKey(key, &rng), 0);
ExpectIntEQ(wc_FrodoKemKey_EncodePublicKey(key, pkBuf, pkLen), 0);
ExpectIntEQ(wc_FrodoKemKey_EncodePrivateKey(key, skBuf, skLen), 0);
ExpectIntEQ(wc_FrodoKemKey_DecodePublicKey(pubKey, pkBuf, pkLen), 0);
ExpectIntEQ(wc_FrodoKemKey_DecodePrivateKey(privKey, skBuf, skLen), 0);
/* Encapsulate to the decoded public key, decapsulate with the decoded
* private key. */
ExpectIntEQ(wc_FrodoKemKey_Encapsulate(pubKey, ct, ss, &rng), 0);
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(privKey, ssDec, ct, ctLen), 0);
ExpectIntEQ(XMEMCMP(ss, ssDec, ssLen), 0);
wc_FrodoKemKey_Free(privKey);
wc_FrodoKemKey_Free(pubKey);
wc_FrodoKemKey_Free(key);
}
if (rngInit) {
DoExpectIntEQ(wc_FreeRng(&rng), 0);
}
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(skBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(pkBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* A modified ciphertext must decapsulate (implicit rejection) to a shared
* secret different from the one produced for the valid ciphertext. */
int test_wc_frodokem_decap_implicit_reject(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(WC_NO_RNG) && \
!defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY) && \
!defined(WOLFSSL_FRODOKEM_NO_ENCAPSULATE) && \
!defined(WOLFSSL_FRODOKEM_NO_DECAPSULATE)
int i;
FrodoKemKey* key = NULL;
WC_RNG rng;
byte* ct = NULL;
byte ss[FRODOKEM_MAX_LENSEC];
byte ssDec[FRODOKEM_MAX_LENSEC];
byte ssDec2[FRODOKEM_MAX_LENSEC];
byte exp[FRODOKEM_MAX_LENSEC];
wc_Shake sh;
word32 ctLen = 0;
word32 ssLen = 0;
int rngInit = 0;
XMEMSET(&rng, 0, sizeof(rng));
XMEMSET(&sh, 0, sizeof(sh));
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
ct = (byte*)XMALLOC(FRODOKEM_MAX_CIPHER_TEXT_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(ct);
ExpectIntEQ(wc_InitRng(&rng), 0);
if (EXPECT_SUCCESS()) {
rngInit = 1;
}
/* Every compiled variant: a modified ciphertext must decapsulate to an
* implicit-rejection secret, deterministically. */
for (i = 0; (i < FRODOKEM_TYPE_CNT) && EXPECT_SUCCESS(); i++) {
ExpectIntEQ(wc_FrodoKemKey_Init(key, frodokem_types[i], NULL,
INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_CipherTextSize(key, &ctLen), 0);
ExpectIntEQ(wc_FrodoKemKey_SharedSecretSize(key, &ssLen), 0);
ExpectIntEQ(wc_FrodoKemKey_MakeKey(key, &rng), 0);
ExpectIntEQ(wc_FrodoKemKey_Encapsulate(key, ct, ss, &rng), 0);
/* Flip a bit in the ciphertext. */
if (EXPECT_SUCCESS()) {
ct[0] ^= 0xff;
}
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(key, ssDec, ct, ctLen), 0);
ExpectIntNE(XMEMCMP(ss, ssDec, ssLen), 0);
/* Implicit rejection is deterministic: decapsulating the same modified
* ciphertext again yields the same shared secret (the SHAKE(c' || s)
* value), not uninitialized/garbage data. */
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(key, ssDec2, ct, ctLen), 0);
ExpectIntEQ(XMEMCMP(ssDec, ssDec2, ssLen), 0);
/* Isolate the implicit-rejection property: the rejected secret must be
* SHAKE(c1 || c2 || salt || s) over the STORED rejection secret s (not
* k'). Recompute it (640 hashes with SHAKE128, 976/1344 with SHAKE256)
* and confirm it matches - a select that used k' would not. */
if ((frodokem_types[i] & FRODOKEM_BASE_MASK) == WC_FRODOKEM_640) {
ExpectIntEQ(wc_InitShake128(&sh, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_Shake128_Update(&sh, ct, ctLen), 0);
ExpectIntEQ(wc_Shake128_Update(&sh, key->s, ssLen), 0);
ExpectIntEQ(wc_Shake128_Final(&sh, exp, ssLen), 0);
wc_Shake128_Free(&sh);
}
else {
ExpectIntEQ(wc_InitShake256(&sh, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_Shake256_Update(&sh, ct, ctLen), 0);
ExpectIntEQ(wc_Shake256_Update(&sh, key->s, ssLen), 0);
ExpectIntEQ(wc_Shake256_Final(&sh, exp, ssLen), 0);
wc_Shake256_Free(&sh);
}
ExpectIntEQ(XMEMCMP(ssDec, exp, ssLen), 0);
wc_FrodoKemKey_Free(key);
}
if (rngInit) {
DoExpectIntEQ(wc_FreeRng(&rng), 0);
}
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* Decapsulating with a public-key-only object must fail. */
int test_wc_frodokem_decapsulate_pubonly_fails(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(WC_NO_RNG) && \
!defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY) && \
!defined(WOLFSSL_FRODOKEM_NO_ENCAPSULATE) && \
!defined(WOLFSSL_FRODOKEM_NO_DECAPSULATE)
int i;
FrodoKemKey* key = NULL;
FrodoKemKey* pubKey = NULL;
WC_RNG rng;
byte* pkBuf = NULL;
byte* ct = NULL;
byte ss[FRODOKEM_MAX_LENSEC];
byte ssDec[FRODOKEM_MAX_LENSEC];
word32 pkLen = 0;
word32 ctLen = 0;
int rngInit = 0;
XMEMSET(&rng, 0, sizeof(rng));
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
pubKey = (FrodoKemKey*)XMALLOC(sizeof(*pubKey), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(pubKey);
pkBuf = (byte*)XMALLOC(FRODOKEM_MAX_PUBLIC_KEY_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(pkBuf);
ct = (byte*)XMALLOC(FRODOKEM_MAX_CIPHER_TEXT_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(ct);
ExpectIntEQ(wc_InitRng(&rng), 0);
if (EXPECT_SUCCESS()) {
rngInit = 1;
}
/* Every compiled variant: a public-key-only object cannot decapsulate. */
for (i = 0; (i < FRODOKEM_TYPE_CNT) && EXPECT_SUCCESS(); i++) {
ExpectIntEQ(wc_FrodoKemKey_Init(key, frodokem_types[i], NULL,
INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_Init(pubKey, frodokem_types[i], NULL,
INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_PublicKeySize(key, &pkLen), 0);
ExpectIntEQ(wc_FrodoKemKey_CipherTextSize(key, &ctLen), 0);
ExpectIntEQ(wc_FrodoKemKey_MakeKey(key, &rng), 0);
ExpectIntEQ(wc_FrodoKemKey_Encapsulate(key, ct, ss, &rng), 0);
ExpectIntEQ(wc_FrodoKemKey_EncodePublicKey(key, pkBuf, pkLen), 0);
ExpectIntEQ(wc_FrodoKemKey_DecodePublicKey(pubKey, pkBuf, pkLen), 0);
/* Public-key-only object cannot decapsulate. */
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(pubKey, ssDec, ct, ctLen),
WC_NO_ERR_TRACE(BAD_STATE_E));
wc_FrodoKemKey_Free(pubKey);
wc_FrodoKemKey_Free(key);
}
if (rngInit) {
DoExpectIntEQ(wc_FreeRng(&rng), 0);
}
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(pkBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* A private key whose embedded public-key hash does not match the public key
* must be rejected by decode. */
int test_wc_frodokem_decode_privkey_bad_pkh(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(WC_NO_RNG) && \
!defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY)
int i;
FrodoKemKey* key = NULL;
WC_RNG rng;
byte* sk = NULL;
word32 skLen = 0;
int rngInit = 0;
XMEMSET(&rng, 0, sizeof(rng));
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
sk = (byte*)XMALLOC(FRODOKEM_MAX_PRIVATE_KEY_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(sk);
ExpectIntEQ(wc_InitRng(&rng), 0);
if (EXPECT_SUCCESS()) {
rngInit = 1;
}
/* Every compiled variant: a corrupted embedded pkh is rejected. */
for (i = 0; (i < FRODOKEM_TYPE_CNT) && EXPECT_SUCCESS(); i++) {
ExpectIntEQ(wc_FrodoKemKey_Init(key, frodokem_types[i], NULL,
INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_PrivateKeySize(key, &skLen), 0);
ExpectIntEQ(wc_FrodoKemKey_MakeKey(key, &rng), 0);
ExpectIntEQ(wc_FrodoKemKey_EncodePrivateKey(key, sk, skLen), 0);
/* A correctly encoded private key decodes. */
ExpectIntEQ(wc_FrodoKemKey_DecodePrivateKey(key, sk, skLen), 0);
/* Corrupt the stored public-key hash (the final lenSec bytes). */
if (EXPECT_SUCCESS()) {
sk[skLen - 1] ^= 0xff;
}
ExpectIntEQ(wc_FrodoKemKey_DecodePrivateKey(key, sk, skLen),
WC_NO_ERR_TRACE(WC_KEY_MISMATCH_E));
wc_FrodoKemKey_Free(key);
}
if (rngInit) {
DoExpectIntEQ(wc_FreeRng(&rng), 0);
}
XFREE(sk, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* Bad-argument and bad-length handling. */
int test_wc_frodokem_bad_args(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM)
FrodoKemKey* key = NULL;
word32 len = 0;
word32 pkLen = 0;
word32 skLen = 0;
int type = frodokem_types[0];
byte small[8];
XMEMSET(small, 0, sizeof(small));
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
/* Constructor / destructor NULL handling. */
#ifndef WC_NO_CONSTRUCTORS
ExpectIntEQ(wc_FrodoKemKey_Delete(NULL, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#endif
ExpectIntEQ(wc_FrodoKemKey_Free(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* Init argument checks: NULL key, unknown type bits. */
ExpectIntEQ(wc_FrodoKemKey_Init(NULL, type, NULL, INVALID_DEVID),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_Init(key, -1, NULL, INVALID_DEVID),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* Size queries reject NULL key and NULL output. */
ExpectIntEQ(wc_FrodoKemKey_Init(key, type, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_PublicKeySize(NULL, &len),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_PublicKeySize(key, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_PrivateKeySize(NULL, &len),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_PrivateKeySize(key, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_CipherTextSize(NULL, &len),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_CipherTextSize(key, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_SharedSecretSize(NULL, &len),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_SharedSecretSize(key, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_PublicKeySize(key, &pkLen), 0);
ExpectIntEQ(wc_FrodoKemKey_PrivateKeySize(key, &skLen), 0);
/* Make key argument and length checks. */
#ifndef WOLFSSL_FRODOKEM_NO_MAKE_KEY
ExpectIntEQ(wc_FrodoKemKey_MakeKeyWithRandom(NULL, small, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_MakeKeyWithRandom(key, NULL, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_MakeKeyWithRandom(key, small, 1),
WC_NO_ERR_TRACE(BUFFER_E));
#ifndef WC_NO_RNG
ExpectIntEQ(wc_FrodoKemKey_MakeKey(NULL, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_MakeKey(key, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#endif
#endif /* !WOLFSSL_FRODOKEM_NO_MAKE_KEY */
/* Encapsulate argument checks. */
#ifndef WOLFSSL_FRODOKEM_NO_ENCAPSULATE
#ifndef WC_NO_RNG
ExpectIntEQ(wc_FrodoKemKey_Encapsulate(NULL, small, small, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#endif
ExpectIntEQ(wc_FrodoKemKey_EncapsulateWithRandom(NULL, small, small,
small, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* NULL ct / ss are rejected independently of key state. */
ExpectIntEQ(wc_FrodoKemKey_EncapsulateWithRandom(key, NULL, small,
small, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_EncapsulateWithRandom(key, small, NULL,
small, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#ifndef WC_NO_RNG
/* Encapsulate rejects a NULL rng in isolation (ct and ss valid). */
ExpectIntEQ(wc_FrodoKemKey_Encapsulate(key, small, small, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#endif
/* Encapsulate on a key with no public key set reports bad state. */
ExpectIntEQ(wc_FrodoKemKey_EncapsulateWithRandom(key, small, small,
small, 0), WC_NO_ERR_TRACE(BAD_STATE_E));
#endif /* !WOLFSSL_FRODOKEM_NO_ENCAPSULATE */
/* Decapsulate argument checks. */
#ifndef WOLFSSL_FRODOKEM_NO_DECAPSULATE
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(NULL, small, small, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* NULL ss / ct are rejected independently of key state and length. */
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(key, NULL, small, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(key, small, NULL, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#endif
/* Encode / decode NULL handling. */
ExpectIntEQ(wc_FrodoKemKey_EncodePublicKey(NULL, small, pkLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_EncodePublicKey(key, NULL, pkLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_EncodePrivateKey(NULL, small, skLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_EncodePrivateKey(key, NULL, skLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_DecodePublicKey(NULL, small, pkLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_DecodePublicKey(key, NULL, pkLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_DecodePrivateKey(NULL, small, skLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_FrodoKemKey_DecodePrivateKey(key, NULL, skLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* Encoding before any key material is set must report bad state. */
ExpectIntEQ(wc_FrodoKemKey_EncodePublicKey(key, small, pkLen),
WC_NO_ERR_TRACE(BAD_STATE_E));
ExpectIntEQ(wc_FrodoKemKey_EncodePrivateKey(key, small, skLen),
WC_NO_ERR_TRACE(BAD_STATE_E));
/* Wrong encoded lengths on decode must report a buffer error. */
ExpectIntEQ(wc_FrodoKemKey_DecodePublicKey(key, small, pkLen - 1),
WC_NO_ERR_TRACE(BUFFER_E));
ExpectIntEQ(wc_FrodoKemKey_DecodePrivateKey(key, small, skLen - 1),
WC_NO_ERR_TRACE(BUFFER_E));
wc_FrodoKemKey_Free(key);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* Encapsulate and decapsulate length checks on a fully made key. */
int test_wc_frodokem_op_len_checks(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(WC_NO_RNG) && \
!defined(WOLFSSL_FRODOKEM_NO_MAKE_KEY) && \
!defined(WOLFSSL_FRODOKEM_NO_ENCAPSULATE) && \
!defined(WOLFSSL_FRODOKEM_NO_DECAPSULATE)
FrodoKemKey* key = NULL;
WC_RNG rng;
byte* ct = NULL;
byte ss[FRODOKEM_MAX_LENSEC];
byte rnd[8];
word32 ctLen = 0;
int rngInit = 0;
int i = 0;
XMEMSET(&rng, 0, sizeof(rng));
XMEMSET(rnd, 0, sizeof(rnd));
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
ct = (byte*)XMALLOC(FRODOKEM_MAX_CIPHER_TEXT_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(ct);
ExpectIntEQ(wc_InitRng(&rng), 0);
if (EXPECT_SUCCESS()) {
rngInit = 1;
}
/* Repeat for every compiled variant: the bad-length thresholds differ
* across the parameter sets and the standard/ephemeral split (encapsulate
* checks lenSec + lenSalt, decapsulate checks ctSize), so a single variant
* would not exercise them all. */
for (i = 0; (i < FRODOKEM_TYPE_CNT) && EXPECT_SUCCESS(); i++) {
ExpectIntEQ(wc_FrodoKemKey_Init(key, frodokem_types[i], NULL,
INVALID_DEVID), 0);
ExpectIntEQ(wc_FrodoKemKey_CipherTextSize(key, &ctLen), 0);
ExpectIntEQ(wc_FrodoKemKey_MakeKey(key, &rng), 0);
/* Encapsulate with the wrong random length reports a buffer error (the
* public key is set, so this reaches the length check, not bad
* state). */
ExpectIntEQ(wc_FrodoKemKey_EncapsulateWithRandom(key, ct, ss, rnd, 1),
WC_NO_ERR_TRACE(BUFFER_E));
/* Decapsulate with the wrong ciphertext length reports a buffer
* error. */
ExpectIntEQ(wc_FrodoKemKey_Decapsulate(key, ss, ct, ctLen - 1),
WC_NO_ERR_TRACE(BUFFER_E));
wc_FrodoKemKey_Free(key);
}
if (rngInit) {
DoExpectIntEQ(wc_FreeRng(&rng), 0);
}
XFREE(ct, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
/* Constructor and destructor happy path. */
int test_wc_frodokem_new_delete(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM) && !defined(WC_NO_CONSTRUCTORS)
FrodoKemKey* key = NULL;
word32 pkLen = 0;
/* New allocates and initializes the object. */
key = wc_FrodoKemKey_New(frodokem_types[0], NULL, INVALID_DEVID);
ExpectNotNull(key);
/* Initialized: a size query on it succeeds and returns a non-zero size. */
ExpectIntEQ(wc_FrodoKemKey_PublicKeySize(key, &pkLen), 0);
ExpectIntGT(pkLen, 0);
/* Delete frees the object and clears the caller's pointer. */
ExpectIntEQ(wc_FrodoKemKey_Delete(key, &key), 0);
ExpectNull(key);
#endif
return EXPECT_RESULT();
}
/* A validly-formed type whose parameter set or A-generation method is not
* compiled in must report NOT_COMPILED_IN (an ill-formed type is
* BAD_FUNC_ARG). The compiled-variant list is the source of truth, so this
* exercises the not-compiled path in single-variant / method-restricted builds
* and is a self-consistent no-op when every variant is enabled. */
int test_wc_frodokem_not_compiled_in(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_FRODOKEM)
/* All twelve validly-formed variant types. These are bit combinations,
* always defined regardless of what is compiled in. */
static const int allTypes[] = {
WC_FRODOKEM_640_SHAKE, WC_FRODOKEM_976_SHAKE, WC_FRODOKEM_1344_SHAKE,
WC_FRODOKEM_640_AES, WC_FRODOKEM_976_AES, WC_FRODOKEM_1344_AES,
WC_EFRODOKEM_640_SHAKE, WC_EFRODOKEM_976_SHAKE, WC_EFRODOKEM_1344_SHAKE,
WC_EFRODOKEM_640_AES, WC_EFRODOKEM_976_AES, WC_EFRODOKEM_1344_AES
};
FrodoKemKey* key = NULL;
int i, j, compiled;
key = (FrodoKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
for (i = 0; (i < (int)(sizeof(allTypes) / sizeof(allTypes[0]))) &&
EXPECT_SUCCESS(); i++) {
/* Is this type one of the compiled-in variants? */
compiled = 0;
for (j = 0; j < FRODOKEM_TYPE_CNT; j++) {
if (frodokem_types[j] == allTypes[i]) {
compiled = 1;
break;
}
}
if (compiled) {
/* A compiled variant initializes. */
ExpectIntEQ(wc_FrodoKemKey_Init(key, allTypes[i], NULL,
INVALID_DEVID), 0);
wc_FrodoKemKey_Free(key);
}
else {
/* A valid but not-compiled variant reports NOT_COMPILED_IN. */
ExpectIntEQ(wc_FrodoKemKey_Init(key, allTypes[i], NULL,
INVALID_DEVID), WC_NO_ERR_TRACE(NOT_COMPILED_IN));
}
}
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}