Skip to content
Commits on Source (7)
# Makefile for ETSI TS 103 744
# Detect the operating system
UNAME_S := $(shell uname -s)
# Compiler and flags
CC := gcc
CFLAGS := -Wall
LDFLAGS := -lcrypto -loqs
# Directories
WORKSPACE := $(shell pwd)/quantumsafe
BUILD_DIR := $(WORKSPACE)/build
LIB_DIR := $(BUILD_DIR)/lib
SRC_DIR := $(shell pwd)
OBJ_DIR := $(shell pwd)/obj
BIN_DIR := $(shell pwd)/bin
# Source and object files
SRCS := $(wildcard $(SRC_DIR)/*.c)
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
# Target executable
TARGET := $(BIN_DIR)/etsi-hkex-test
# Dependencies
DEPS := openssl liboqs oqs-provider
# Phony targets
.PHONY: all update install setup openssl liboqs oqs-provider test-oqs update-ldconfig compile update-ldconfig clean
#
# Default target
all: update install setup openssl liboqs oqs-provider test-oqs compile run
# all: update install setup openssl liboqs oqs-provider test-oqs compile
# Update and install necessary packages (OS-specific)
update:
ifeq ($(UNAME_S),Linux)
sudo apt update
sudo apt -y install git build-essential perl cmake autoconf libtool zlib1g-dev
else ifeq ($(UNAME_S),Darwin)
brew update
brew install git cmake autoconf automake libtool
endif
# Setup workspace and build directory
setup:
mkdir -p $(LIB_DIR)
# Clone and build OpenSSL
openssl:
@if [ ! -d $(WORKSPACE)/openssl ]; then \
echo "Cloning and building OpenSSL..."; \
cd $(WORKSPACE) && \
git clone -b openssl-3.2 https://github.com/openssl/openssl && \
cd openssl && \
./Configure \
--prefix=$(BUILD_DIR) \
no-ssl no-tls1 no-tls1_1 no-afalgeng \
no-shared threads -lm && \
make && \
echo "OpenSSL cloned and built successfully."; \
else \
echo "OpenSSL directory already exists. Skipping clone and build."; \
fi
# Clone and build liboqs
liboqs:
@if [ ! -d $(WORKSPACE)/liboqs ]; then \
echo "Cloning and building liboqs..."; \
cd $(WORKSPACE) && \
git clone https://github.com/open-quantum-safe/liboqs && \
cd liboqs && \
git checkout 0.13.0-release && \
mkdir build && cd build && \
cmake \
-DBUILD_SHARED_LIBS=ON \
-DOQS_USE_OPENSSL=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DOQS_BUILD_ONLY_LIB=ON \
-DOQS_DIST_BUILD=ON \
.. && \
make && \
echo "liboqs cloned and built successfully."; \
else \
echo "liboqs directory already exists. Skipping clone and build."; \
fi
# Clone and build oqs-provider
oqs-provider:
@if [ ! -d $(WORKSPACE)/oqs-provider ]; then \
echo "Cloning and building oqs-provider..." ; \
cd $(WORKSPACE) && \
git clone https://github.com/open-quantum-safe/oqs-provider && \
cd oqs-provider && \
git checkout 0.7.0-release && \
liboqs_DIR=$(BUILD_DIR) cmake \
-DOPENSSL_ROOT_DIR=$(WORKSPACE)/openssl/ \
-DCMAKE_BUILD_TYPE=Release \
-S . \
-B $(BUILD_DIR) && \
sudo cmake --build $(BUILD_DIR) ; \
echo "oqs-provider cloned, built, and configured successfully."; \
else \
echo "oqs-provider directory already exists. Skipping clone and build."; \
fi
# Test OQS provider
test-oqs:
@echo "Testing OQS provider..."
@export OPENSSL_MODULES=$(BUILD_DIR)/lib && openssl list -kem-algorithms -provider oqsprovider
# Compile the project
compile:
@echo "Compiling the project..."
gcc -Wall -o etsi-hkex-test main.c crypto.c qshkex.c -lcrypto -loqs \
-I$(WORKSPACE)/liboqs/build/include/ \
-L$(BUILD_DIR)/lib
@echo "Compilation completed. Executable: etsi-hkex-test"
# Run the compiled program
run: compile
@echo "Running etsi-hkex-test..."
ifeq ($(UNAME_S),Linux)
@export OPENSSL_MODULES=$(BUILD_DIR)/lib && ./etsi-hkex-test
else ifeq ($(UNAME_S),Darwin)
@DYLD_LIBRARY_PATH=$(BUILD_DIR)/lib:$$DYLD_LIBRARY_PATH ./etsi-hkex-test
endif
# Clean up
clean:
rm -rf $(WORKSPACE)
rm -f etsi-hkex-test
......@@ -14,11 +14,20 @@
This is not intended for production use. It is intended to be a reference
implementation for test vectors for the specification.
git clone ssh://git.amazon.com/pkg/Etsi-hkex-test
git checkout
### Build instructions ###
This library requires OpenSSL version 1.1.1d libcrypto.
This library requires OpenSSL version 3.2.4-dev libcrypto.
gcc -Wall -o etsi-hkex-test main.c qshkex.c -lcrypto
To clone and build dependencies (openssl, liboqs, and oqs-provider), run:
make
To build and run etsi-hkex-test:
make run
Or:
gcc -Wall -o etsi-hkex-test main.c crypto.c qshkex.c -lcrypto -loqs
./etsi-hkex-test
### License ###
......
/*
This file implements ETSI TC CYBER QSC Quantum-safe Hybrid Key Exchanges
(Version 1.1.1)
This is not intended for production use. It is intended to be a reference
implementation for test vectors for the specification.
It uses OpenSSL version 3.4.0 libcrypto.
gcc -Wall -o etsi-hkex-test main.c crypto.c qshkex.c -lcrypto -loqs
./etsi-hkex-test
Copyright 2020 ETSI. All rights reserved
SPDX-License-Identifier: BSD-3-Clause
*/
#include "crypto.h"
#include "qshkex.h"
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/provider.h>
#include <openssl/err.h>
#include <oqs/oqs.h>
#include <oqs/rand.h>
// Custom deterministic RNG function
void deterministic_randombytes(unsigned char *random_array, size_t bytes_to_generate)
{
uint32_t out_len = SEED_LEN_BYTES;
ascii_hex_strings_to_uint8(random_array, &out_len, 1, deterministic_seed[current_seed_index]);
if (out_len != bytes_to_generate) {
return;
}
current_seed_index++;
}
int test_qhkex_derand_ecdh(const int curve, const char *priv_dataA, const char *peerB, uint8_t *pubA, size_t *PA1length, uint8_t *pubB, size_t *PB1length, uint8_t *ss, uint32_t *ss_len)
{
int rval = FAILURE;
BIGNUM *privA = NULL, *x = NULL;
EC_POINT *peer_pointB = NULL, *shared_secret_point = NULL, *pub_keyA = NULL;
EC_GROUP *groupA = NULL;
EVP_PKEY_CTX *ctxA = NULL;
EVP_PKEY *pkeyA = NULL, *pkeyB = NULL;
size_t field_len, ss_lenA;
uint8_t shared_secretA[X448_KEY_LEN_BYTES];
uint8_t hex_private_keyA[X448_KEY_LEN_BYTES];
uint8_t pubA_cpy[MAX_KEY_BYTE_LEN], pubB_cpy[MAX_KEY_BYTE_LEN];
uint8_t hex_exp_shared[MAX_KEY_BYTE_LEN];
do {
if (curve == EVP_PKEY_X25519 || curve == EVP_PKEY_X448) {
field_len = X25519_KEY_LEN_BYTES;
if (curve == EVP_PKEY_X448) {
field_len = X448_KEY_LEN_BYTES;
}
for (int i = 0; i < field_len; i++) {
sscanf(&priv_dataA[i * 2], "%2hhx", &hex_private_keyA[i]);
}
if (!(pkeyA = EVP_PKEY_new_raw_private_key(curve, NULL, hex_private_keyA, field_len))) {
break;
}
if (EVP_PKEY_get_raw_public_key(pkeyA, pubA, &field_len) <= 0) {
break;
}
*PA1length = field_len;
for (int i = 0; i < field_len; i++) {
sscanf(&peerB[i * 2], "%2hhx", &pubB[i]);
}
if(!(pkeyB = EVP_PKEY_new_raw_public_key(curve, NULL, pubB, field_len))) {
break;
}
*PB1length = field_len;
if (!(ctxA = EVP_PKEY_CTX_new(pkeyA, NULL))) {
break;
}
if (EVP_PKEY_derive_init(ctxA) <= 0) {
break;
}
if (EVP_PKEY_derive_set_peer(ctxA, pkeyB) <= 0) {
break;
}
ss_lenA = field_len;
if (EVP_PKEY_derive(ctxA, shared_secretA, &ss_lenA) <= 0) {
break;
}
memcpy(ss, shared_secretA, ss_lenA);
*ss_len = ss_lenA;
ascii_hex_strings_to_uint8(hex_exp_shared, (uint32_t *)&field_len, 1, strk1[current_seed_index/2]);
if (memcmp(ss, hex_exp_shared, field_len) != 0) {
break;
}
rval = SUCCESS;
} else {
if (BN_hex2bn(&privA, priv_dataA) <= 0) {
break;
}
if (!(groupA = EC_GROUP_new_by_curve_name(curve))) {
break;
}
if (!(pub_keyA = EC_POINT_new(groupA))) {
break;
}
if (!EC_POINT_mul(groupA, pub_keyA, privA, NULL, NULL, NULL)) {
break;
}
if (!EC_POINT_point2oct(groupA, pub_keyA, POINT_CONVERSION_UNCOMPRESSED, pubA_cpy, MAX_KEY_BUF_BYTES, NULL)) {
break;
}
if (!(peer_pointB = EC_POINT_hex2point(groupA, peerB, NULL, NULL))) {
break;
}
if (!EC_POINT_point2oct(groupA, peer_pointB, POINT_CONVERSION_UNCOMPRESSED, pubB_cpy, MAX_KEY_BUF_BYTES, NULL)) {
break;
}
if (!(shared_secret_point = EC_POINT_new(groupA))) {
break;
}
if (!EC_POINT_mul(groupA, shared_secret_point, NULL, peer_pointB, privA, NULL)) {
break;
}
if (!(x = BN_new())) {
break;
}
if (!EC_POINT_get_affine_coordinates(groupA, shared_secret_point, x, NULL, NULL)) {
break;
}
if (!(field_len = EC_GROUP_get_degree(groupA)/8)) {
break;
}
memcpy(pubA, pubA_cpy + 1, field_len*2);
*PA1length = field_len*2;
memcpy(pubB, pubB_cpy + 1, field_len*2);
*PB1length = field_len*2;
BN_bn2bin(x, ss);
*ss_len = field_len;
ascii_hex_strings_to_uint8(hex_exp_shared, (uint32_t *)&field_len, 1, strk1[current_seed_index/2]);
if (memcmp(ss, hex_exp_shared, field_len) != 0) {
break;
}
rval = SUCCESS;
}
} while (0);
if (privA) {
BN_free(privA);
}
if (x) {
BN_free(x);
}
if (peer_pointB) {
EC_POINT_free(peer_pointB);
}
if (shared_secret_point) {
EC_POINT_free(shared_secret_point);
}
if (pub_keyA) {
EC_POINT_free(pub_keyA);
}
if (groupA) {
EC_GROUP_free(groupA);
}
if (ctxA) {
EVP_PKEY_CTX_free(ctxA);
}
if (pkeyA) {
EVP_PKEY_free(pkeyA);
}
if (pkeyB) {
EVP_PKEY_free(pkeyB);
}
return rval;
}
int test_qhkex_derand_mlkem(const char * alg_name, uint8_t *pubA, size_t *PA2length, uint8_t *ctB, size_t *CTB2length, uint8_t *ss, uint32_t *ss_len)
{
int rval = FAILURE;
OQS_KEM *kem;
uint8_t sk[OQS_KEM_ml_kem_1024_length_secret_key], sharedB[OQS_KEM_ml_kem_1024_length_shared_secret], hex_exp_shared[OQS_KEM_ml_kem_1024_length_shared_secret];
do {
OQS_randombytes_custom_algorithm(deterministic_randombytes);
if (!(kem = OQS_KEM_new(alg_name))) {
break;
}
if (OQS_KEM_keypair(kem, pubA, sk) != OQS_SUCCESS) {
break;
}
*PA2length = kem->length_public_key;
if (OQS_KEM_encaps(kem, ctB, ss, pubA) != OQS_SUCCESS) {
break;
}
*CTB2length = kem->length_ciphertext;
if (OQS_KEM_decaps(kem, sharedB, ctB, sk) != OQS_SUCCESS) {
break;
}
*ss_len = OQS_KEM_ml_kem_1024_length_shared_secret;
ascii_hex_strings_to_uint8(hex_exp_shared, ss_len, 1, strk2[current_seed_index/2 - 1]);
if (memcmp(ss, sharedB, kem->length_shared_secret) != 0 ||
memcmp(ss, hex_exp_shared, kem->length_shared_secret) != 0) {
break;
}
rval = SUCCESS;
} while (0);
if (kem) {
OQS_KEM_free(kem);
}
return rval;
}
int test_qhkex_rand_ecdh(int curve, uint8_t *pubA, size_t *PA1length, uint8_t *pubB, size_t *PB1length, uint8_t *ss, uint32_t *ss_len)
{
int rval = FAILURE;
EVP_PKEY_CTX *ctxA = NULL, *ctxB = NULL;
EVP_PKEY *pkeyA = NULL, *pkeyB = NULL;
uint8_t ssB[MAX_KEY_BYTE_LEN];
size_t secret_lenA = 0, secret_lenB = 0;
size_t pubA_len = 0, pubB_len = 0;
do {
// Create entity A keys
if (curve == EVP_PKEY_X25519 || curve == EVP_PKEY_X448) {
if (!(ctxA = EVP_PKEY_CTX_new_id(curve, NULL))) {
break;
}
} else {
if (!(ctxA = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) {
break;
}
}
if (EVP_PKEY_keygen_init(ctxA) <= 0) {
break;
}
if (curve != EVP_PKEY_X25519 || curve != EVP_PKEY_X448) {
if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctxA, curve) <= 0) {
break;
}
}
if (EVP_PKEY_keygen(ctxA, &pkeyA) <= 0) {
break;
}
if (curve != EVP_PKEY_X25519 || curve != EVP_PKEY_X448) {
if (EVP_PKEY_get_octet_string_param(pkeyA, "pub", pubA, MAX_KEY_BYTE_LEN, &pubA_len) <=0 ) {
break;
}
} else {
if (EVP_PKEY_get_raw_public_key(pkeyA, pubA, &pubA_len) <= 0) {
break;
}
}
*PA1length = pubA_len;
// Create entity B keys
if (curve == EVP_PKEY_X25519 || curve == EVP_PKEY_X448) {
if (!(ctxB = EVP_PKEY_CTX_new_id(curve, NULL))) {
break;
}
} else {
if (!(ctxB = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) {
break;
}
}
if (EVP_PKEY_keygen_init(ctxB) <= 0) {
break;
}
if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctxB, curve) <= 0) {
break;
}
if (EVP_PKEY_keygen(ctxB, &pkeyB) <= 0) {
break;
}
if (curve != EVP_PKEY_X25519 || curve != EVP_PKEY_X448) {
if (EVP_PKEY_get_octet_string_param(pkeyB, "pub", pubB, MAX_KEY_BYTE_LEN, &pubB_len) <= 0) {
break;
}
} else {
if (EVP_PKEY_get_raw_public_key(pkeyB, pubB, &pubB_len) <= 0) {
break;
}
}
*PB1length = pubB_len;
// Derive entity A shared secret
ctxA = EVP_PKEY_CTX_new(pkeyA, NULL);
if (!ctxA) {
break;
}
if (EVP_PKEY_derive_init(ctxA) <= 0) {
break;
}
if (EVP_PKEY_derive_set_peer(ctxA, pkeyB) <= 0) {
break;
}
if (EVP_PKEY_derive(ctxA, NULL, &secret_lenA) <= 0) {
break;
}
if (EVP_PKEY_derive(ctxA, ss, &secret_lenA) <= 0) {
break;
}
// Derive entity B shared secret
ctxB = EVP_PKEY_CTX_new(pkeyB, NULL);
if (!ctxB) {
break;
}
if (EVP_PKEY_derive_init(ctxB) <= 0) {
break;
}
if (EVP_PKEY_derive_set_peer(ctxB, pkeyA) <= 0) {
break;
}
if (EVP_PKEY_derive(ctxB, NULL, &secret_lenB) <= 0) {
break;
}
if (EVP_PKEY_derive(ctxB, ssB, &secret_lenB) <= 0) {
break;
}
// Check if entities shared secrets match
if (memcmp(ss, ssB, secret_lenB) != 0 || (secret_lenA != secret_lenB)) {
break;
}
*ss_len = secret_lenA;
rval = SUCCESS;
} while (0);
if (ctxA) {
EVP_PKEY_CTX_free(ctxA);
}
if (ctxB) {
EVP_PKEY_CTX_free(ctxB);
}
if (pkeyA) {
EVP_PKEY_free(pkeyA);
}
if (pkeyB) {
EVP_PKEY_free(pkeyB);
}
return rval;
}
int test_qhkex_rand_mlkem(const char * kem, uint8_t *pubA, size_t *PA2length, uint8_t *ctB, size_t *CTB2length, uint8_t *ss, uint32_t *ss_len)
{
int rval = FAILURE;
size_t pubA_len = OQS_KEM_ml_kem_1024_length_public_key;
size_t ss_out_len = OQS_KEM_ml_kem_1024_length_shared_secret;
size_t ciphertext_len = OQS_KEM_ml_kem_1024_length_ciphertext;
uint8_t shared_secretB[OQS_KEM_ml_kem_1024_length_shared_secret];
EVP_PKEY_CTX *pkey_ctx = NULL, *encaps_ctx = NULL, *decaps_ctx = NULL;
EVP_PKEY *keypair = NULL;
OSSL_PROVIDER *oqs_provider = NULL;
OSSL_LIB_CTX *libctx = NULL;
do {
if (!(libctx = OSSL_LIB_CTX_new())) {
break;
}
if (!(oqs_provider = OSSL_PROVIDER_load(libctx, "oqsprovider"))) {
break;
}
if (!(pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, kem, NULL))) {
break;
}
if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) {
break;
}
if (EVP_PKEY_keygen(pkey_ctx, &keypair) <= 0) {
break;
}
if (EVP_PKEY_get_octet_string_param(keypair, "pub", pubA, OQS_KEM_ml_kem_1024_length_public_key, &pubA_len) <= 0) {
break;
}
*PA2length = pubA_len;
if (!(encaps_ctx = EVP_PKEY_CTX_new(keypair, NULL))) {
break;
}
if (EVP_PKEY_encapsulate_init(encaps_ctx, NULL) <= 0) {
break;
}
if (EVP_PKEY_encapsulate(encaps_ctx, NULL, &ciphertext_len, NULL, &ss_out_len) <= 0) {
break;
}
*CTB2length = ciphertext_len;
if (EVP_PKEY_encapsulate(encaps_ctx, ctB, &ciphertext_len, ss, &ss_out_len) <= 0) {
break;
}
if (!(decaps_ctx = EVP_PKEY_CTX_new(keypair, NULL))) {
break;
}
if (EVP_PKEY_decapsulate_init(decaps_ctx, NULL) <= 0) {
break;
}
if (EVP_PKEY_decapsulate(decaps_ctx, shared_secretB, &ss_out_len, ctB, ciphertext_len) <= 0) {
break;
}
if (memcmp(ss, shared_secretB, ss_out_len) != 0) {
break;
}
*ss_len = ss_out_len;
rval = SUCCESS;
} while (0);
if (pkey_ctx) {
EVP_PKEY_CTX_free(pkey_ctx);
}
if (encaps_ctx) {
EVP_PKEY_CTX_free(encaps_ctx);
}
if (decaps_ctx) {
EVP_PKEY_CTX_free(decaps_ctx);
}
if (keypair) {
EVP_PKEY_free(keypair);
}
if (oqs_provider) {
OSSL_PROVIDER_unload(oqs_provider);
}
if (libctx) {
OSSL_LIB_CTX_free(libctx);
}
return rval;
}
\ No newline at end of file
/*
Header file for a reference implementation of
ETSI TC CYBER QSC Quantum-safe Hybrid Key Exchanges (Version 1.1.1)
This is not intended for production use. It is intended to be a reference
implementation for test vectors for the specification.
Copyright 2020 ETSI. All rights reserved
SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _QS_H_CRYPTO_KEX_H_
#define _QS_H_CRYPTO_KEX_H_
#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include "qshkex.h"
#define SEED_LEN_BYTES 64
#define X25519_KEY_LEN_BYTES 32
#define X448_KEY_LEN_BYTES 56
#define MAX_KEY_BUF_BYTES 128
extern int current_seed_index;
extern const char *deterministic_seed[];
extern const char *strk1[];
extern const char *strk2[];
int test_qhkex_derand_ecdh(const int curve, const char *priv_dataA, const char *peerB,
uint8_t *pubA, size_t *PA1length, uint8_t *pubB, size_t *PB1length,
uint8_t *ss, uint32_t *ss_len);
int test_qhkex_derand_mlkem(const char * alg_name, uint8_t *pubA, size_t *PA2length,
uint8_t *ctB, size_t *CTB2length, uint8_t *ss, uint32_t *ss_len);
int test_qhkex_rand_ecdh(int curve, uint8_t *pubA, size_t *PA1length,
uint8_t *pubB, size_t *PB1length, uint8_t *ss, uint32_t *ss_len);
int test_qhkex_rand_mlkem(const char * kem, uint8_t *pubA, size_t *PA2length,
uint8_t *ctB, size_t *CTB2length, uint8_t *ss, uint32_t *ss_len);
#endif /*_QS_H_CRYPTO_KEX_H_*/
......@@ -15,477 +15,1297 @@
*/
#include "qshkex.h"
#include "crypto.h"
#define TEST_VECTOR_CNT 7
#define HASH_FUNCTIONS_CNT 2
#define MAX_LABEL_BYTE_LEN 64
#define MAX_KEY_BYTE_LEN 128
#define MAX_LABEL_LEN 32
#define MAX_MSG_BYTE_LEN 4096
#define CONCAT_CONTEXT_TEST_VECTOR "CONCATENATION TEST VECTOR 1"
#define CASCADE_CONTEXT_TEST_VECTOR "CASCADE TEST VECTOR 1"
const EVP_MD *(*evp_hash[TEST_VECTOR_CNT][HASH_FUNCTIONS_CNT])(void) = {
{EVP_sha256, EVP_sha3_256},
{EVP_sha384, EVP_sha3_384},
{EVP_sha384, EVP_sha3_384},
{EVP_sha512, EVP_sha3_512},
{EVP_sha256, EVP_sha3_256},
{EVP_sha384, EVP_sha3_384},
{EVP_sha512, EVP_sha3_512},
#define TEST_VECTOR_CNT 12
#define INFO_TEST_VECTOR "ETSI_QSHKE_TEST_VECTORS_V_1_2"
const char *cids_concatenate_hkdf[TEST_VECTOR_CNT] = {
"1111", // HKDFwSHA256, ECDH with P256, MLKEM512, CatKDF
"1711", // HKDFwSHA256, ECDH with Curve25519, MLKEM512, CatKDF
"1411", // HKDFwSHA256, ECDH with BP-P256, MLKEM512, CatKDF
"1121", // HKDFwSHA256, ECDH with P256, MLKEM768, CatKDF
"1721", // HKDFwSHA256, ECDH with Curve25519, MLKEM768, CatKDF
"1421", // HKDFwSHA256, ECDH with BP-P256, MLKEM768, CatKDF
"2221", // HKDFwSHA384, ECDH with P384, MLKEM768, CatKDF
"2821", // HKDFwSHA384, ECDH with Curve448, MLKEM768, CatKDF
"2521", // HKDFwSHA384, ECDH with BP-P384, MLKEM768, CatKDF
"2231", // HKDFwSHA384, ECDH with P384, MLKEM1024, CatKDF
"2831", // HKDFwSHA384, ECDH with Curve448, MLKEM1024, CatKDF
"2531" // HKDFwSHA384, ECDH with BP-P384, MLKEM1024, CatKDF
};
const char *cids_concatenate_hmac[TEST_VECTOR_CNT] = {
"4111", // HMACwSHA256, ECDH with P256, MLKEM512, CatKDF
"4711", // HMACwSHA256, ECDH with Curve25519, MLKEM512, CatKDF
"4411", // HMACwSHA256, ECDH with BP-P256, MLKEM512, CatKDF
"4121", // HMACwSHA256, ECDH with P256, MLKEM768, CatKDF
"4721", // HMACwSHA256, ECDH with Curve25519, MLKEM768, CatKDF
"4421", // HMACwSHA256, ECDH with BP-P256, MLKEM768, CatKDF
"5221", // HMACwSHA384, ECDH with P384, MLKEM768, CatKDF
"5821", // HMACwSHA384, ECDH with Curve448, MLKEM768, CatKDF
"5521", // HMACwSHA384, ECDH with BP-P384, MLKEM768, CatKDF
"5231", // HMACwSHA384, ECDH with P384, MLKEM1024, CatKDF
"5831", // HMACwSHA384, ECDH with Curve448, MLKEM1024, CatKDF
"5531" // HMACwSHA384, ECDH with BP-P384, MLKEM1024, CatKDF
};
const char *cids_concatenate_kmac[TEST_VECTOR_CNT] = {
"7111", // KMAC128, ECDH with P256, MLKEM512, CatKDF
"7711", // KMAC128, ECDH with Curve25519, MLKEM512, CatKDF
"7411", // KMAC128, ECDH with BP-P256, MLKEM512, CatKDF
"7121", // KMAC128, ECDH with P256, MLKEM768, CatKDF
"7721", // KMAC128, ECDH with Curve25519, MLKEM768, CatKDF
"7421", // KMAC128, ECDH with BP-P256, MLKEM768, CatKDF
"8221", // KMAC256, ECDH with P384, MLKEM768, CatKDF
"8821", // KMAC256, ECDH with Curve448, MLKEM768, CatKDF
"8521", // KMAC256, ECDH with BP-P384, MLKEM768, CatKDF
"8231", // KMAC256, ECDH with P384, MLKEM1024, CatKDF
"8831", // KMAC256, ECDH with Curve448, MLKEM1024, CatKDF
"8531" // KMAC256, ECDH with BP-P384, MLKEM1024, CatKDF
};
const char *cids_cascade_hkdf[TEST_VECTOR_CNT] = {
"1112", // HKDFwSHA256, ECDH with P256, MLKEM512, CasKDF
"1712", // HKDFwSHA256, ECDH with Curve25519, MLKEM512, CasKDF
"1412", // HKDFwSHA256, ECDH with BP-P256, MLKEM512, CasKDF
"1122", // HKDFwSHA256, ECDH with P256, MLKEM768, CasKDF
"1722", // HKDFwSHA256, ECDH with Curve25519, MLKEM768, CasKDF
"1422", // HKDFwSHA256, ECDH with BP-P256, MLKEM768, CasKDF
"2222", // HKDFwSHA384, ECDH with P384, MLKEM768, CasKDF
"2822", // HKDFwSHA384, ECDH with Curve448, MLKEM768, CasKDF
"2522", // HKDFwSHA384, ECDH with BP-P384, MLKEM768, CasKDF
"2232", // HKDFwSHA384, ECDH with P384, MLKEM1024, CasKDF
"2832", // HKDFwSHA384, ECDH with Curve448, MLKEM1024, CasKDF
"2532" // HKDFwSHA384, ECDH with BP-P384, MLKEM1024, CasKDF
};
const char *cids_cascade_hmac[TEST_VECTOR_CNT] = {
"4112", // HMACwSHA256, ECDH with P256, MLKEM512, CasKDF
"4712", // HMACwSHA256, ECDH with Curve25519, MLKEM512, CasKDF
"4412", // HMACwSHA256, ECDH with BP-P256, MLKEM512, CasKDF
"4122", // HMACwSHA256, ECDH with P256, MLKEM768, CasKDF
"4722", // HMACwSHA256, ECDH with Curve25519, MLKEM768, CasKDF
"4422", // HMACwSHA256, ECDH with BP-P256, MLKEM768, CasKDF
"5222", // HMACwSHA384, ECDH with P384, MLKEM768, CasKDF
"5822", // HMACwSHA384, ECDH with Curve448, MLKEM768, CasKDF
"5522", // HMACwSHA384, ECDH with BP-P384, MLKEM768, CasKDF
"5232", // HMACwSHA384, ECDH with P384, MLKEM1024, CasKDF
"5832", // HMACwSHA384, ECDH with Curve448, MLKEM1024, CasKDF
"5532" // HMACwSHA384, ECDH with BP-P384, MLKEM1024, CasKDF
};
const char *cids_cascade_kmac[TEST_VECTOR_CNT] = {
"7112", // KMAC128, ECDH with P256, MLKEM512, CasKDF
"7712", // KMAC128, ECDH with Curve25519, MLKEM512, CasKDF
"7412", // KMAC128, ECDH with BP-P256, MLKEM512, CasKDF
"7122", // KMAC128, ECDH with P256, MLKEM768, CasKDF
"7722", // KMAC128, ECDH with Curve25519, MLKEM768, CasKDF
"7422", // KMAC128, ECDH with BP-P256, MLKEM768, CasKDF
"8222", // KMAC256, ECDH with P384, MLKEM768, CasKDF
"8822", // KMAC256, ECDH with Curve448, MLKEM768, CasKDF
"8522", // KMAC256, ECDH with BP-P384, MLKEM768, CasKDF
"8232", // KMAC256, ECDH with P384, MLKEM1024, CasKDF
"8832", // KMAC256, ECDH with Curve448, MLKEM1024, CasKDF
"8532" // KMAC256, ECDH with BP-P384, MLKEM1024, CasKDF
};
const EVP_MD *(*evp_hash[TEST_VECTOR_CNT])(void) = {
EVP_sha256,
EVP_sha256,
EVP_sha256,
EVP_sha256,
EVP_sha256,
EVP_sha256,
EVP_sha384,
EVP_sha384,
EVP_sha384,
EVP_sha384,
EVP_sha384,
EVP_sha384};
const uint32_t key_length[TEST_VECTOR_CNT] = {16, 24, 24, 32, 16, 24, 32};
const char *kmac[TEST_VECTOR_CNT] = {
SN_kmac128,
SN_kmac128,
SN_kmac128,
SN_kmac128,
SN_kmac128,
SN_kmac128,
SN_kmac256,
SN_kmac256,
SN_kmac256,
SN_kmac256,
SN_kmac256,
SN_kmac256};
const int curves[TEST_VECTOR_CNT] = {
NID_X9_62_prime256v1,
EVP_PKEY_X25519,
NID_brainpoolP256r1,
NID_X9_62_prime256v1,
EVP_PKEY_X25519,
NID_brainpoolP256r1,
NID_secp384r1,
EVP_PKEY_X448,
NID_brainpoolP384r1,
NID_secp384r1,
EVP_PKEY_X448,
NID_brainpoolP384r1};
const char *kems[TEST_VECTOR_CNT] = {
"mlkem512",
"mlkem512",
"mlkem512",
"mlkem768",
"mlkem768",
"mlkem768",
"mlkem768",
"mlkem768",
"mlkem768",
"mlkem1024",
"mlkem1024",
"mlkem1024"};
const char *kems_derand[TEST_VECTOR_CNT] = {
"ML-KEM-512",
"ML-KEM-512",
"ML-KEM-512",
"ML-KEM-768",
"ML-KEM-768",
"ML-KEM-768",
"ML-KEM-768",
"ML-KEM-768",
"ML-KEM-768",
"ML-KEM-1024",
"ML-KEM-1024",
"ML-KEM-1024"};
int current_seed_index;
const uint32_t key_length[TEST_VECTOR_CNT] = {16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24};
// 64 bytes
const char strPSK[] = {
"00000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000"};
// Label should be of same length agreed
/* Label contribution from A */
const char *strLA1[] = {
"0102030405060708090A0B0C0D0E0F10",
"1102030405060708090A0B0C0D0E0F100102030405060708",
"2102030405060708090A0B0C0D0E0F100102030405060709",
"3102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F10",
"10102030405060708090A0B0C0D0E0F1",
"21102030405060708090A0B0C0D0E0F10010203040506070",
"33102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F1"};
"0102030405060708090A0B0C0D0E0F10102030405060708090A0B0C0D0E0F101",
"0102030405060708090A0B0C0D0E0F12102030405060708090A0B0C0D0E0F122",
"20102030405060708090A0B0C0D0E0F10102030405060708090A0B0C0D0E0F13",
"10102030405060708090A0B0C0D0E0F10102030405060708090A0B0C0D0E0F14",
"0102030405060708090A0B0C0D0E0F1101020304050607081020304050607085",
"1102030405060708090A0B0C0D0E0F1001020304050607081020304050607086",
"2102030405060708090A0B0C0D0E0F100102030405060709102030405060708090A0B0C0D0E0F1001020304050607097",
"3102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F13102030405060708090A0B0C0D0E0F108",
"21102030405060708090A0B0C0D0E0F100102030405060711102030405060708090A0B0C0D0E0F100102030405060719",
"33102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F13102030405060708090A0B0C0D0E0F1A",
"21102030405060708090A0B0C0D0E0F100102030405060701102030405060708090A0B0C0D0E0F10010203040506070B",
"43102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F13102030405060708090A0B0C0D0E0F1C"};
const char *strLA2[] = {
"4102030405060708090A0B0C0D0E0F11",
"5102030405060708090A0B0C0D0E0F110102030405060708",
"6102030405060708090A0B0C0D0E0F110102030405060709",
"7102030405060708090A0B0C0D0E0F110102030405060708090A0B0C0D0E0F11",
"14102030405060708090A0B0C0D0E0F1",
"25102030405060708090A0B0C0D0E0F11010203040506070",
"3102030405060708090A0B0C0D0E0F110102030405060708090A0B0C0D0E0F11"};
"4102030405060708090A0B0C0D0E0F11102030405060708090A0B0C0D0E0F11D",
"4102030405060708090A0B0C0D0E0F12102030405060708090A0B0C0D0E0F12E",
"14102030405060708090A0B0C0D0E0F24102030405060708090A0B0C0D0E0F2F",
"3102030405060708090A0B0C0D0E0F110102030405060708090A0B0C0D0E0F30",
"14102030405060708090A0B0C0D0E0F14102030405060708090A0B0C0D0E0F11",
"5102030405060708090A0B0C0D0E0F1101020304050607081020304050607082",
"5102030405060708090A0B0C0D0E0F110102030405060709102030405060708090A0B0C0D0E0F1101020304050607093",
"6102030405060708090A0B0C0D0E0F110102030405060709102030405060708090A0B0C0D0E0F1101020304050607094",
"7102030405060708090A0B0C0D0E0F110102030405060708090A0B0C0D0E0F223102030405060708090A0B0C0D0E0F15",
"35102030405060708090A0B0C0D0E0F110102030405060705102030405060708090A0B0C0D0E0F110102030405060706",
"25102030405060708090A0B0C0D0E0F110102030405060705102030405060708090A0B0C0D0E0F110102030405060707",
"4102030405060708090A0B0C0D0E0F130102030405060708090A0B0C0D0E0F43102030405060708090A0B0C0D0E0F138"};
const char *strPA1[] = {
/* ECDH (NIST P-256, NIST P-384, NIST P-521) public keys from NIST CAVP SP
/* ECDH (NIST P-256, NIST P-384) public keys from NIST CAVP SP
* 800-56A ECCCDH Primitive Test Vectors.
* http://csrc.nist.gov/groups/STM/cavp/documents/components
* /ecccdhtestvectors.zip
* ECDH (Curve25519 and Curve448) public keys from IETF RFC 7748
* https://datatracker.ietf.org/doc/html/rfc7748#page-4
* ECDH (BP-P256 and BP-P384) public keys from IETF RFC 8734
* https://www.rfc-editor.org/rfc/rfc8734.txt
*/
"119F2F047902782AB0C9E27A54AFF5EB9B964829CA99C06B02DDBA95B0A3F6D08F52B72666\
4CAC366FC98AC7A012B2682CBD962E5ACB544671D41B9445704D1D",
4CAC366FC98AC7A012B2682CBD962E5ACB544671D41B9445704D1D", // NIST P-256
"8520F0098930A754748B7DDCB43EF75A0DBF3A0D26381AF4EBA4A98EAA9B4E6A", // Curve25519
"44106E913F92BC02A1705D9953A8414DB95E1AAA49E81D9E85F929A8E3100BE58AB4846F11\
CACCB73CE49CBDD120F5A900A69FD32C272223F789EF10EB089BDC", // BP-P256
"EAD218590119E8876B29146FF89CA61770C4EDBBF97D38CE385ED281D8A6B23028AF61281F\
D35E2FA7002523ACC85A429CB06EE6648325389F59EDFCE1405141", // NIST P-256
"8520F0098930A754748B7DDCB43EF75A0DBF3A0D26381AF4EBA4A98EAA9B4E6A", // Curve25519
"44106E913F92BC02A1705D9953A8414DB95E1AAA49E81D9E85F929A8E3100BE58AB4846F11\
CACCB73CE49CBDD120F5A900A69FD32C272223F789EF10EB089BDC", // BP-P256
"9803807F2F6D2FD966CDD0290BD410C0190352FBEC7FF6247DE1302DF86F25D34FE4A97BEF\
60CFF548355C015DBB3E5FBA26CA69EC2F5B5D9DAD20CC9DA711383A9DBE34EA3FA5A2AF75B4650\
2629AD54DD8B7D73A8ABB06A3A3BE47D650CC99",
"EA4018F5A307C379180BF6A62FD2CECEEBEEB7D4DF063A66FB838AA35243419791F7E2C9D4\
803C9319AA0EB03C416B6668835A91484F05EF028284DF6436FB88FFEBABCDD69AB0133E6735A1B\
CFB37203D10D340A8328A7B68770CA75878A1A6",
"00602F9D0CF9E526B29E22381C203C48A886C2B0673033366314F1FFBCBA240BA42F4EF38A\
76174635F91E6B4ED34275EB01C8467D05CA80315BF1A7BBD945F550A501B7C85F26F5D4B2D7355\
CF6B02117659943762B6D1DB5AB4F1DBC44CE7B2946EB6C7DE342962893FD387D1B73D7A8672D1F\
236961170B7EB3579953EE5CDC88CD2D",
"EAD218590119E8876B29146FF89CA61770C4EDBBF97D38CE385ED281D8A6B23028AF61281F\
D35E2FA7002523ACC85A429CB06EE6648325389F59EDFCE1405141",
"FCFCEA085E8CF74D0DCED1620BA8423694F903A219BBF901B0B59D6AC81BAAD316A242BA32\
BDE85CB248119B852FAB66972E3C68C7AB402C5836F2A16ED451A33120A7750A6039F3FF15388EE\
622B7065F7122BF6D51AEFBC29B37B03404581B",
"00D45615ED5D37FDE699610A62CD43BA76BEDD8F85ED31005FE00D6450FBBD101291ABD96D\
4945A8B57BC73B3FE9F4671105309EC9B6879D0551D930DAC8BA45D25501425332844E592B440C0\
027972AD1526431C06732DF19CD46A242172D4DD67C2C8C99DFC22E49949A56CF90C6473635CE82\
F25B33682FB19BC33BD910ED8CE3A7FA"};
2629AD54DD8B7D73A8ABB06A3A3BE47D650CC99", // NIST P-384
"9B08F7CC31B7E3E67D22D5AEA121074A273BD2B83DE09C63FAA73D2C22C5D9BBC836647241\
D953D40C5B12DA88120D53177F80E532C41FA0", // Curve448
"68B665DD91C195800650CDD363C625F4E742E8134667B767B1B476793588F885AB698C852D\
4A6E77A252D6380FCAF06855BC91A39C9EC01DEE36017B7D673A931236D2F1F5C83942D049E3FA2\
0607493E0D038FF2FD30C2AB67D15C85F7FAA59", // BP-P384
"9803807F2F6D2FD966CDD0290BD410C0190352FBEC7FF6247DE1302DF86F25D34FE4A97BEF\
60CFF548355C015DBB3E5FBA26CA69EC2F5B5D9DAD20CC9DA711383A9DBE34EA3FA5A2AF75B4650\
2629AD54DD8B7D73A8ABB06A3A3BE47D650CC99", // NIST P-384
"9B08F7CC31B7E3E67D22D5AEA121074A273BD2B83DE09C63FAA73D2C22C5D9BBC836647241\
D953D40C5B12DA88120D53177F80E532C41FA0", // Curve448
"68B665DD91C195800650CDD363C625F4E742E8134667B767B1B476793588F885AB698C852D\
4A6E77A252D6380FCAF06855BC91A39C9EC01DEE36017B7D673A931236D2F1F5C83942D049E3FA2\
0607493E0D038FF2FD30C2AB67D15C85F7FAA59"}; // BP-P384
const char *strPA2[] = {
/* SIKE (sikep434, sikep503, sikep610, sikep751) public keys from Round 3 KATs,
* https://csrc.nist.gov/CSRC/media/Projects/post-quantum-cryptography
* /documents/round-3/submissions/SIKE-Round3.zip
*/
"4484D7AADB44B40CC180DC568B2C142A60E6E2863F5988614A6215254B2F5F6F79B48F329A\
D1A2DED20B7ABAB10F7DBF59C3E20B59A700093060D2A44ACDC0083A53CF0808E0B3A827C45176B\
EE0DC6EC7CC16461E38461C12451BB95191407C1E942BB50D4C7B25A49C644B630159E6C4036538\
38E689FBF4A7ADEA693ED0657BA4A724786AF7953F7BA6E15F9BBF9F5007FB711569E72ACAB05D3\
463A458536CAB647F00C205D27D5311B2A5113D4B26548000DB237515931A040804E769361F94FF\
0167C78353D2630A1E6F595A1F80E87F6A5BCD679D7A64C5006F6191D4ADEFA1EA67F6388B7017D\
453F4FE2DFE80CCC709000B52175BFC3ADE52ECCB0CEBE1654F89D39131C357EACB61E5F13C80AB\
0165B7714D6BE6DF65F8DE73FF47B7F3304639F0903653ECCFA252F6E2104C4ABAD3C33AF24FD0E\
56F58DB92CC66859766035419AB2DF600",
"05279D27FF7E3A38ABB05DCFE23B5831C030D832D3EAE35FE06A6538597532D22A0F4012FB\
2263E160495F8291B58D9DF8A8947C7CF3E6735520BB2D094912408829851AC4B85AA922069F2AA\
A0A4827DFA4730E9CF05485CBEE411C3D5169DD4953746B6A2E6574957EF920596B1612BE62A883\
740B5A0C157117AE1C3A07E4CE8CCCE7E9E88FE7C20A507FF019AE0893F34303E173D291F6CB7EC\
B4C3901FF34A48DE40771F5BAD72DA2B4C1CFD0A61F33E39327A8DA60F5640D4C2E71EF9C7297A4\
E9BC50493E3BA65D3664610A6D61035CB6600378D017D1E1810ACD113252D60F5915749C2B5CFB4\
452C40C86F1F40C63297DCCA900686F2D2266F9444539D9BA13B1F52FB2FC3BD4F3EDAA6EB707AA\
FCA5261EA271ED961B2ED195D5E3B0299179251866CE0EAA31C5C90B7999A8D63BA2DE84A8AFA19\
F11F2DC0CACA39B982CE053F71D269931D9EE26BCE592A8EA818553BC8F8D244F62FB4F5E5386E3\
EFF5CD231401C9EC2BA57FF42DC3B3791357A53E1E31394008",
"671B24769304DD18C97AF0C5DE741C53E0B45A9E18C7A13A15C1758125E41605587E450F84\
52A2BF98B51C2AF6B0503CB8E01F8553C36079EBFADF4948FFA063ABF4866E7AB9B9D4C9A07CA40\
0C613607E6DB9BB6E7EB8ECA78894C7C8CE9E231B33179B2946C5C5BE1C783FA6AEA218F5EC4B4E\
6F914E5ED3724C5D7B79403F68438A40775E964C1B2C7D22E11A6C07474EB5D4CFF75965B400167\
E069FA9908A562DBABF5E30FED46BBA0A208ED4E50764CF320FB8556F07C7F6268084476A47D83B\
085DC77EB3CD30A2B5EE1E5829738077D52A0D7A4149EE9C1A70269BC047B4BE7E5B28007DEF74A\
4D813853396708A3A8498CC862F54015B79047014639EB8CA3BB786B27A2CFAF31E6BB9CCB152BE\
B3232465206973668597AA35EE1940A316F71241FA40D1AC233931E1967E79AAA600AA6D83FEC62\
80A63924E7375F22F7A47E1DE483FEA17E0DACBAEDBB13D58C0DC9BC21F2DC9525D46E4210AC5D8\
8567E4F23304EA5BE08D89D57A0246EA21C0CD28C096366D7F3C8D98F5A1FB00FE2F3A183E53A7E\
8B6C19E9BF979E8D20C703C957D6F06A142BE86A0A09B05ED40953BBD7A15E92098633941730DEB\
5BC1C5F5154E8BCA38E035580E101E6EE858D91BD8462B906EB2004C6E01",
"E1A758EC0D418BFE86D8077B5BB169133C06C1F2A067D8B202D9D058FFC51F63FD26155A65\
77C74BA7F1A27E7BA51982517B923615DEB00BE408920A07831DF5978CFDDD0BF690A264353A4A1\
6B666F90586D7F89A193CE09375D389C1379A7A528581C3ACB002CD2DC4F0FD672568FF9050BA83\
65C7FEFC5E6ED089B921DE6804091A0744DE3EB14D426A3F7DA215C50312617C1C2697243980D06\
056F2CCE88AE7AE73C7343C0B7104C9F2870A94FED744CF6E94630514B6CEAB0E64733BB6FA67B9\
31E5D8206010475CBE8BC587248D65D89D8CD9C8BBFA93E8B5F9EB9130773DED665D52ABBD91C4C\
8C255F73C0FC82501AE33330E9F308DE7177CBF83E4E26E334D7CB09019E638147FC58ED372AF66\
0F14C194BC80E9666325C98E0F80877271D4A6BF514F603703D8A697874CD50A34D92F5AAEA8463\
3CCF96801BD517BF425DEE4A32AAF06684052473EA14643C3D535440FB2240A988D09F297C5A388\
CB3DE60ED943F124034B90EFF611221F80F78EC124956338A105F6636B063D7E48BFBD5D614310F\
B97D86F122E4AE6F9DDF4977A93ED7D0CE2A94E346A1A03D3219CF21907B85A5BCDC713F93A4406\
A22E03B1655A66E1F6741A2F953E6FE0868B2614BABEF1943BBBCB1B66D3E7017E533EA84F29124\
0B56AB33EF1DC3F3DE99DBF9E8BE51A0076E462BCDD825EA96D7F63C99177C305C257B31461F4C2\
3D43115F0220409E8880BBB2468586D03461E807BE824B693874911B2B52AF06FDBDC47F5A01597\
29641A7C950AB9E03F2DC045135",
/* KYBER (kyber512, kyber768, kyber1024) public from Round 3 KATs,
* https://csrc.nist.gov/CSRC/media/Projects/post-quantum-cryptography
* /documents/round-3/submissions/Kyber-Round3.zip
*/
"115ACE0E64677CBB7DCFC93C16D3A305F67615A488D711AA56698C5663AB7AC9CE66D547C0\
595F98A43F4650BBE08C364D976789117D34F6AE51AC063CB55C6CA32558227DFEF807D19C30DE4\
14424097F6AA236A1053B4A07A76BE372A5C6B6002791EBE0AFDAF54E1CA237FF545BA68343E745\
C04AD1639DBC590346B6B9569B56DBBFE53151913066E5C85527DC9468110A136A411497C227DCB\
8C9B25570B7A0E42AADA6709F23208F5D496EBAB7843F6483BF0C0C73A40296EC2C6440001394C9\
9CA173D5C775B7F415D02A5A26A07407918587C41169F2B7178755ACC27FC8B19C4C4B3FCD41053\
F2C74C8A10A8321241B2802432875AE808B9EF1365C7B8A52902F1317BA2FB0269F47930672107B\
4726FEF64547394D3320C8F120B3C2F4725B0305FAB88CC7981FCB09A76A1CBF7F179F43BB0A4C8\
B0590857F1E69708466C7F8607391E7BC5268BFD3D7A1DFFCB4ECA2A1C9B597593013D5FC4202EC\
2B74E57AB76BBCF3632BBAF97CDC418A6F16392838CA9BF45DDF023777B7561833C105190F94F30\
2C59B531900BBC816361FAA5B3380CA3A893104CA7388B185671B3E5FE3790E9A626EC46D9B0B33\
C7A419AF7B32B6859894F575D82AC5456B5490A7AF8FE61046360589ECBA7244236F4123116B617\
4AA179249A49195B356C72FC6641F0251812EAA98570B046699070E0819DC2713F469137DFC6A3D\
7B92B298995EE780369153AC366B06D7249CD09E1B3378FB04399CECB8650581D637C79AE67D6F2\
CAF6ABACF598159A7792CB3C971D1499D2373AD20F63F03BB59ED137384AC61A7155143B8CA4932\
612EC915E4CA346A9BCE5DD60417C6B2A89B1CC435643F875BDC5A7E5B3481CF919EA09172FEBC4\
6D4FC3FB0CB9591704EE2DBB61844B2F3314A06BB6C6D34005E485CE667BDC7D098586928D2D913\
40F00419EA401351A240A0B041058BEFB0C2FD32645B7A2DF8F5CBFD873327C978D7B351A280884\
38837024C52B9C295CD713646FB5D6C0CCFB470734AC2B2BC8123C2C13DF6938E92455A862639FE\
B8A64B85163E32707E037B38D8AC3922B45187BB65EAFD465FC64A0C5F8F3F9003489415899D59A\
543D8208C54A3166529B53922",
"A72C2D9C843EE9F8313ECC7F86D6294D59159D9A879A542E260922ADF999051CC45200C9FF\
DB60449C49465979272367C083A7D6267A3ED7A7FD47957C219327F7CA73A4007E1627F00B11CC8\
0573C15AEE6640FB8562DFA6B240CA0AD351AC4AC155B96C14C8AB13DD262CDFD51C4BB5572FD61\
6553D17BDD430ACBEA3E95F0B698D66990AB51E5D03783A8B3D278A5720454CF9695CFDCA08485B\
A099C51CD92A7EA7587C1D15C28E609A81852601B0604010679AA482D51261EC36E36B871967621\
7FD74C54786488F4B4969C05A8BA27CA3A77CCE73B965923CA554E422B9B61F4754641608AC16C9\
B8587A32C1C5DD788F88B36B717A46965635DEB67F45B129B99070909C93EB80B42C2B3F3F70343\
A7CF37E8520E7BCFC416ACA4F18C7981262BA2BFC756AE03278F0EC66DC2057696824BA6769865A\
601D7148EF6F54E5AF5686AA2906F994CE38A5E0B938F239007003022C03392DF3401B1E4A3A7EB\
C6161449F73374C8B0140369343D9295FDF511845C4A46EBAAB6CA5492F6800B98C0CC803653A4B\
1D6E6AAED1932BACC5FEFAA818BA502859BA5494C5F5402C8536A9C4C1888150617F80098F6B2A9\
9C39BC5DC7CF3B5900A21329AB59053ABAA64ED163E859A8B3B3CA3359B750CCC3E710C7AC43C81\
91CB5D68870C06391C0CB8AEC72B897AC6BE7FBAACC676ED66314C83630E89448C88A1DF04ACEB2\
3ABF2E409EF333C622289C18A2134E650C45257E47475FA33AA537A5A8F7680214716C50D470E32\
84963CA64F54677AEC54B5272162BF52BC8142E1D4183FC017454A6B5A496831759064024745978\
CBD51A6CEDC8955DE4CC6D363670A47466E82BE5C23603A17BF22ACDB7CC984AF08C87E14E27753\
CF587A8EC3447E62C649E887A67C36C9CE98721B697213275646B194F36758673A8ED11284455AF\
C7A8529F69C97A3C2D7B8C636C0BA55614B768E624E712930F776169B01715725351BC74B47395E\
D52B25A1313C95164814C34C979CBDFAB85954662CAB485E75087A98CC74BB82CA2D1B5BF280323\
8480638C40E90B43C7460E7AA917F010151FAB1169987B372ABB59271F7006C24E60236B84B9DDD\
600623704254617FB498D89E58B0368BCB2103E79353EB587860C1422E476162E425BC2381DB82C\
6592737E1DD602864B0167A71EC1F223305C02FE25052AF2B3B5A55A0D7A2022D9A798DC0C5874A\
98702AAF4054C5D80338A5248B5B7BD09C53B5E2A084B047D277A861B1A73BB51488DE04EF573C8\
5230A0470B73175C9FA50594F66A5F50B4150054C93B68186F8B5CBC49316C8548A642B2B36A1D4\
54C7489AC33B2D2CE6668096782A2C1E0866D21A65E16B585E7AF8618BDF3184C19868785089172\
77B93E10706B1614972B2A94C7310FE9C708C231A1A8AC8D9314A529A97F469BF64962D82064844\
3099A076D55D4CEA824A58304844F99497C10A25148618A315D72CA857D1B04D575B94F85C01D19\
BEF211BF0AA3362E7041FD16596D808E867B44C4C00D1CDA3418967717F147D0EB21B42AAEE74AC\
35D0B92414B958531AADF463EC6305AE5ECAF79174002F26DDECC813BF32672E8529D95A4E730A7\
AB4A3E8F8A8AF979A665EAFD465FC64A0C5F8F3F9003489415899D59A543D8208C54A3166529B53\
922",
"D22302CBD3399FACC630991FC8F28BDB4354762541527678BCF61F65C241146C426D23B9BF\
AA6B7DF18C97F20C1B6125BF874B1D89475852C448215DB0EB7737F91480E8CEBD9A0871574F5AB\
62D9020175EC6927CA0B54C09818E42CF92A383172422C7DC1831D63B0C295DE75159DB8034E9E0\
7F7B0B910C3C1E5FB66B3DC523F1FA6EB4910CB89A6C17562C83AB4C18D0CD7E0796592A372AA40\
9B1C557347CCACDC4644A119064D06DD474929D1C6FB4D686E5491CE4BC89A30BB4B8C41BCE5157\
DFC1360823B1AB618C14B10F98C25067398EA7018C278A4B3DF31334D603B2044EF187CD9BC6CE4\
2725BD962C264983E9E18155A8B9C47143D70460A26A56FE7658C1F150348C6087EF758AD167887\
860A007A5FC37358D43B5EBEE820ACEA474F0AC07B76802866199C61231D5C747C93774D2C1E0C1\
C67E6C81B82752173E125BAF39B4FD19A4F453DC57976B1D97FE6996992BBB65B7CB25D077BBAA6\
A13322899AF659CF1B3558C1B5001154B625809ED89AEEBB89E6EA7D67F723D045AB05715C42355\
DA6A5C8DD39C8ABE3037751A01ED1C7374919F3121B5A52C53D1487316769F80721DEEAAAD3C90F\
76E7AE9E12BA92B32B5FD457E3C752C2650DFB885771CB77AC3C785A8C562E6A1C63C2A55EA47CF\
8B90EB8225C123C346452566235B2F31823A33521E087937A345D8D663EEAA05658917BBAA008C2\
E335F8850A90A326D0E66432F44CEB8289E4ECB2D12958E984072ECACB88E1348FF0B55654ACBA5\
B54971CBAEBA88EC4B91A94C37192FA982BECB9F3DA421603B61A51BC8E36CBD053851C77B1B926\
B17A272AA9023246B02B3ED47F66A00BD5684823634E7CE58CF8F306E35B1E5322824D904801F0A\
2FA7C2BC9C252B0A56B7BA2AB0F636021745A70A9A43E2B0A8D615970B65309624B5184BCC30B91\
1679AEDD76025FE3908FD67897B0CF4BE5A6F5413D7DD98564B23E42A93E4AA8821CD45054C643E\
DC1158DB6B3DEB13FB5A51EBD1A8A78B87225A7338E101104C4A220D9BDEDD48C85A1C2DAE781A8\
0C40E13B87EAC73A764201C9B760CCFB1AE392699C7039D27C39362B27B8FC6F07A8A3D4410F154\
7C48A9997F62C61074452EF1515F8A649EBCA9437205A4E8A61606B41DAF6834D671F4D852C0C9C\
4096611648C6A3170678B1537CC1828D93580C9E5849A9653175ACB753F2BE7437BE45F6C603E48\
5F2EC301BB42B6C37C225D7495A584AE231890AB5C8C35C268CF4BBB0213C096019319561A8A694\
7637AA40D006B415BB2CFA2237E0890B6A3BC134ABF8F6585E108D15940F91F4BF5B0C818055B21\
DEA6E63B553988C47F4B94E7CF800A493B4734705EDC56A4B6021C629500675876804CF0B951F03\
8A5C7FE58E89774EF2992FD7C63099D352A7D21560B788B405709861817E59A96B3A3A83CBA803B\
16934331071905BBEC6532900155D8AC88CB32E4E21A3BD3A03FDEC325A51CD2773964E6784FCF1\
853737AA64EB67564727272661ABF84313A57A44B123C65509CFB7A6F6641CDCC3B57FE628C7B81\
92DB44FFBF5796A8613B1FA126F6076883C783DC24E2A4464C40B3A41CA70AE87620866CF4FCB2B\
D204BF5C283812BA056AC0C345E379C4BA24D750901279BB2F3A16F612BFADB35703332C7C136F6\
8EAB6755C66B6A4AD1AABA7B768A58ACAACC10A459A1CC8EF29377BC200E4D315A30A6BCC3256F9\
734D06E9779CAA5442A9A16069081377C76E75154368072DC446ED6C8B8E622A21E383CF9BA1FB4\
34E2ECC81E7B78CEE986B8FF798AB18CF9634543546284EDA2A26B47F05B735BCDB1202220076DC\
8B4E4B9F853533C8F6C7FF38817BA49712835785F17F14CA01D0C1C1E98810FE0B36E5B427157B9\
418449CEDD641A4293C85C32700102ACEC22EBAD98ED160A5F027BD4CDA57F1F3720A12C134654D\
D5E73F829676495390D0E7929D6034E9C55F7D55BA658BC587988E8AF94960F6CFB8D5AF7A00215\
35A6E25E437D49A780698BE22AC9953949F571B85A685725F8207A2B0AE849B601AB91B159B3DF4\
A154C2041E776070AFC42969322380917C97510799F3149131477E16663D3174C7C1CAEA788535C\
6C005A64F2868631B31B66E205FD38C1D84542D0F1B578F58C9BF5A0FAEAB6AB6494893053165EA\
FD465FC64A0C5F8F3F9003489415899D59A543D8208C54A3166529B53922"};
/* FIPS203 ML-KEM (ML-KEM512, ML-KEM768, ML-KEM1024) public keys
* https://github.com/post-quantum-cryptography/KAT
* Tests are used by AWS-LC https://raw.githubusercontent.com/aws/
* aws-lc/refs/heads/main/crypto/fipsmodule/ml_kem/kat/mlkem512.txt
* NIST ACVP test vectors https://github.com/usnistgov/ACVP-Server
* do not provide matching tests for ML-KEM.KeyGen() and ML-KEM.Encaps()/Decaps()
*/
// ML-KEM-512
"80B70100831D7EE168F47392483119F93863ECB0BC605312D35728876B00F5F57AF4C85EDA\
97281D574390BC7256193668DC98625354AB52B9BCE781C5771CC26099F6FBACBEE1784D1948877\
31F097C87E082CBEAC57D30B7B9A293872C841466F2244CC65FF4BA653D6751DFA22051D5533699\
42C31C29F91307AF573292D697A8C31612E07B5335CF08329FD246BF2A32200A8CB0C4B03B9D09C\
5BA1C3919539E9229C696924348282F696B1525E5603806B4DB618B3DC8630CB286E4311721BC50\
31F257AA925BF80960445AA8D8E69788E99DA95C1D10CC3BE858528DB0CFEA003C74693780A65A3\
6E62843B3BE15406543D22D83507C87B2786792C80FA5628454A310394DDA4C2AB59493850257D6\
D3BC107186D9062707F354E81A1A10FCB763D31A4EC409AA243ED2E59BB189855EB1656266BB375\
00785EA08CD88C222A8C53A8777CAB42C9C238A00D59369425026E99D2AE6040AF6709029CA8789\
C897B329FBA748D69C8A7148C95ABB0C71787C58F12F21F2213E389242AA7FBD320C12AC42C6116\
06CB8C1D1B4625886A145A535BD65BD0D996B330C1657D61A87E90417003225759820A3BBEC505C\
DAF11193229AAE173CD12BAD22A7A30A76A9FA7636C3D5AA48E1784012A012F14168B7853D2A16F\
90CA02CC33B2006C08F26C15FCA29612CC792E1CF02E1321A75A810891986667D4148AF36E65E1A\
592589029617734C315C0E39B7518C8660CDC265D0C813EF20A043317FAE5B8E40546EECF71D6C0\
54FA66B49401309BEF30FD51A5519755DA9104689B26F0839154C847BEF2365943C0249483AAD9A\
7367C980A3D1CE46D2008A15275CA3BCA4834E6F9A3036C0CD80BA228D34B9780244D5C0CBE907C\
6FB43824A9C0746471639CB86188C60C3B253215CC91692BCD1493D6A444D536446E02968138001\
CC287E0E518F3AA25D8C3B95B3C35C59F4819D484976029AF05A263C35336B261F77B2CDC29389F\
084C04CBB370C48562B5B50771C0FB816908E198DD6D53F76E48BF042C2B1F82A3A40B8DAF51F46\
D76FA4BCC9D3C894FF850C0FAA32E0AC33901A4C79139F5F20417EC1A190607044F18BB824CF350\
C78AB3DDF3C2C86CA5543F715",
"DEE78922BB8DA2F4764DCA45F8EA4C1F530A1C571D3AD1924B589698CB2719E069FD943C14\
52C5D168B2B357B265831C019CB3557A0BF7187E4D108BF770C74DB40389CC718F3BC11CE3ABA84\
366AB245194B941F81B7AE702419BB98D73BA003783306C7B3A3677A543A0100C3175E8C020CA26\
6512909C3550C4F65C0EA3E24A47237D9A4A0B5AE588F983311FAA36E891AF8EA1B308C83179246\
154C765AC5B5A15456E193308002837D14354E066A34A4409AFBB15085AADC9E22B8DB5583D45B0\
A4AC72474A2AB94B792E531AB0CB882C13A4139A71FFA3783B537178F34E111B6C3F120A76D4CDC\
EC461843035ACD285ED627D8BD2B0B997CCCEB4ADAE3615A73BBA0A7C7BB9B13358BB51FF8A574D\
86B5000272CD270A0A1B24BB917506701C2F441FC5B79DD451CB3CACC740127BD411604BDAC464D\
A1A2F83918C5B2FB6E5284C972B93357A837828B1132632BB6F7BFBBEC3D947BD403D86990066DB\
6553722434C7C0E3992F009BB238F7A6B3E5251EDA943A7703FBA289AA2053A857796C2CB945494\
C0BA791A9E3CBFA800D8988C8121997D975B3D03595ADD64A3EACB8BA36A4D8B3BFDC11B7D56239\
087C90F352C0EEC40857F089CCFA7C9A683A1DE3CD8FF28B22153DDE231E5F74805D683EB8C346B\
A16C7FE68064B2059C8738E5AC19B64D4343F5C9D8BF9780302B0676C202A21292CC15FC1589A69\
838AD1EA3D0C3706F8E1B011F61299A56EC2515051FB94734B308AF3C35E45ABFADC128FE69838A\
A37080514D6C3748C916BD655080A1035FF1A763E450B56864CC232AFEE53919FF889A820A7A655\
8631B88F7318C033800F307C19B2D0A8B65882D8770979A5701AC602F71B72A26B82525AA67D77C\
75EB6871DC019B465583A250DB4704906187E8DFB3B70726988F9C52C12266C6391D4926CB79978\
007CA46EF60882806FFD59C64ED70333989AAC5186990440B89C3CD1363BE404706DBB63A5A007A\
0FAC261A0288F916FAF0AA4E944552F10801A3A5DDE263398015CC35227BD1711356251AA935A89\
BC2E3D2C08E1C9A8C1E4416F303BB73B314858CA4C210C959283FC865B027768C5D6047FD36DBCB\
C4EDF3EA5CC6A50CB052BCD31",
"F5E24E4E14B6653665CA0289A3728CBBA228FE116726C1251E9992A9F0060934645B262324\
ACB5C6B57D26E39226E22CF0C33F7FF5A4D979234F2B7949F566DB66C35B273DC9778A64F2BCFE9\
14C0D81527D418A112579E5D08B1C429587323425D7A78351453457CD868345AFA16218332002C9\
5D8406C14938C039693D6C1216AFB9983099031109BE0193A1B6E12436103FDD084A7B84380ACC3\
5817831C0558D4F8082BA58B9174841A840C2964853656C2327F7952132C6DD129DBF5023CE1B3A\
92F7736FC19528B71D21A27C3D7B7451D5A8FC02A786F75545D2451549BC95DBBB87724F72D2ADF\
1D619B1B94386C14C37128C2C1C60F4C02B28CC536C508A370BA9A2F4618CF1C64F355684F25A6E\
E99D3F89CE0136B47D7B26F0E6A60CC94FC4573834172A3EFB84C9FB66401B76C90007E8F7B19B5\
13292138B79147A364680DBCB211762358CD32A3C44720DF6BA22DC8D3019C0C4803F2A567D9EBC\
6A5BC012D1F634719891DA1324EAF228379264B3DA955DAA3A2FB8836894C8E80006782141257C2\
54D905A238A6B41AC3C76CB87EA342728EA6E48BC66816842FF2455E85C67F8C48874F469BDA56F\
DD83A57DD4076798A3D854CE40BCC6B349A198FC6FA4713C94794946E249201779709AB7510459E\
2FA325BB3C816B2AF3D9CAF36FA5C217379CFEB797A9080FE23374FA02F047C775CB4602B7859F7\
D79C0AF73F11B42847915B3D3246E1044031F61BAAD987F3C6CC93280B23C8390E48A2108092C7B\
419BAE13AE50067813A99B5DA80E58005C6965FFE453AE573501B242124515257C406278C2F7F39\
4574894445C612E4114F0A60404CDA976FA63B9A285781E0AB3D77AD2B002F1C885EF746610243B\
751AB4BCEA388027C41063B01679136087364CFDB1392FAABB9E20A5177B94BF5A393B7BDD83A7D\
82343173B8781B44334484354B7179B225AABEE99F230795D1FB248AA5615E85C0ADB49B7F51047\
12B86D4034D457975D41B7C88C0664E091E47E9798303C3901583C13606EED7883A537AC0E14706\
8B8C4AC056FBA108FF1083A9186EC05B338627A8DCE43E5C41410CD6BB35A330D20B77BB3A9034B\
4E3C443BBEB41B6691F11AB11",
// ML-KEM-768
"533145987CB33CD2C8F5AC8A73C03A97FB31D2B89D02B1576CFC77BC97656FC040FCC75697\
50459EE753EBD69839692B375A0F53165B191CA8C6185B85626282C0A4AD63B36B6A289F661D505\
850832248D6F39084695C028B979835848931874E037EDF33CD9F1521E2B478BF0C37D859572AB0\
8C20F7687749032949AB7457B66C1206C08A78C58633BA008E8770224700B84758B22B290E9ED01\
F750439B00B97729960940817D3BA0CE7F10EB6A0C8EBD975C85A6299A6CE486132292189F9DCC1\
3F275918704192A417E7B305834323C354213195BAD0A5AA30A3980B028A1E116E97E74ED8D053A\
2FA51E00068BCD69D325246E93A30AD493D28099AF143016BE454413256A5DA144C9985C70664EE\
12013DF167E228B921EA3BAC494B5D5140581A4D7E7080B4C284A6DAA955366EAE3217541A0B110\
9313F7A1AE9305D55B45CB6A5B2F3321A10DB137E92306A3B2A25FC1999495F7A732D7CD83BE092\
3050A5562A036699F92427CB71C0CA201D958F7A3171740AB477188DB276A52E576703493E289C1\
4BF896D5A827586492D23B605CDC6932A4ABF902A219F88B12D0479C91B4EE6C586A4A2061FC22D\
66264772359B569456111574D84606CBA28292C37A40B81F5A113BB9E72871E14184270FE2A87C3\
3BA7D01E95A578950D098C48A584428BAC781BA938F13BB80F4790EC36F1A394FEC97AB80054F60\
A90DA86ABE7D84799A604233A5A495294D13805B6CF3505DB833E9F223D102AAA9E666580B088E1\
CBABC4CB52725CB768B5E990B89411AA652E06A2BDB937B185EB924C59AF6BA9BE2BA09409DB5C2\
62D751731461A89AAC05ADACC320B6AFC5C4A5FDBB2F56B2483D11779C7117707B121D0B36362B2\
BF8D4B28F6948F5EB1D5E41B1C8A5053D581019C36AC87988803CB934027909DC4C5BD1AE2EF451\
D9F7945209C0E9E60AF43C50DC98646F3BB13BE6491E91930D9AA1AA315FB3B1A067579565D170C\
4E888E9042751106B72A60470A69992508E8CE3101A602A22DA7FB1A744F09488E704481F649DAB\
6158E5306F573009EC63ACF11B549D280033343FC9750BB927B931B94F9C5475A2B803AF36CC3CC\
30521EA2A86040E03E7CF90B36D2E370856285AE4523367482E68473CA500200F75C8C423C8AB93\
C7BFE74DF253AF97114A3FEAC1DDD34E06747C6B386990428100A99351BA14A3C19B1A7A6DA5A71\
5F6A698E9FC330C13B98D61A2A85AC0E0896CC8032490B93FEB284703F21E6D16307D7886F94875\
2FE55CEE7291C06AA7BBB79146C644AEA7C2765C5EFA535B729158EB51BC2D4C389B970B3008696\
6D858D51B78EF3829F9290DAF241C6D370425D83DDD61153DD2AC0FD206120434AD6792D60B2F08\
4A2950AAC250B4001F309EA45B09D9DB440D6A2C9BB3B140569C51C985A2B0BE03ABA918C2311B1\
1069FC9A0C762CCA59C1BDAE47C0406AF0CC7BBB1821C0F8733563ABBE896525E1156F7D593F55C\
39922B6B79E462CE587189247FA045CB19FA7256B960D0B25B7B364ECE250D43E19313C798CE424\
634DC358A0914FAF33EA2B06EAA748947C6C150E54D7BD3A4C4873B117266145833FF04CAA96424\
AB678B49BA94D6619F01BBC62961850CF25765C7627910EF8E79F9B3749086AABF75407D7AC4274\
8BC",
"06F51174F03C2FE07CC31B0659B87EBF124237811B88B980BC277F8C050B265CBEE1A4AE71\
45CB9253281BBC291F2808E065855FD91C7D14122C589FB21B45FD3B7FBB6562FD53006B565189E\
C983C7A0D4C21596EF3795AE22ECAD71F75395558B55220662BB66C389ED9AB6B784476E1788F34\
B28B59A4C6F71F9F6A49DA80C4D3107DB2C306968B5600E18285F8BFA293677F699FD2D2820DE49\
0F530818D6667686A765FCC0009484D71629C1F148104B462325AC55EF34DD5C7098441A06757CA\
35C8ADFDAB6D36333310241F9970B1B123478DCBB75AE6CA39BB84FFCB23A593C24BC54E74B4086\
165BB4B10AE39F45447AA4EA5F55762386B11051B84B0A688C12C73336FC87164B7FBC7F0B07D2A\
51BB05560606D5558666CC322963AD3CA2BC1293260A94707770C030B2BC9C00477A8D5FF673796\
1480D48109F66075DA9C8AB516F70A78DA9E444AB65798A2565965A68AD9146FD9267D2A80C4352\
A0A988157522046620A63D9BA7BBCCAFD50A61384453F8545845B25E7A05745C4B26EF7211200A9\
16241047FDABB66936BB7351C04F5CD06A10AE3C459B74BB0CD85044BF8B6BF2B33294014B9D685\
17CB1A9813230BA08813807A2DFCC6A739B6AC79575F19BAB96A7CDED404D0E52508214AD43763A\
0A048FC36785B2C718F75B3432769C1D2A6240336A82B39D865739AF78E94A92BD7B4703210297F\
B82E0BE57B97384DB5B24FFA5486C982AF48642D967222A28C6F83E5AD6A59CA486733808BA3BD8\
6A780E59888011965A351CA949B0D6C72FB3BA0F867834D166819C252D9600207C88997318B2D20\
4AC3619247A01829484F12BCA2E8F16AAC677C9E8AC209F9BCCF019BBDA66E8F073DFBD934E08CA\
15BE77576029654E049C1C20B1B123E5F0B50135628CD2C96A5D0B1EEF48FBE08AC4685247721B1\
28F71DC748452B94A458F39B337BC2305CCC505BB18BF6ABE3EC2C825799B95C13A1F6411CD3B03\
1F3CEC3D99AFC1A28F2019C1BD129A2EA35F06415C8B717337957CAA964E794881257073FF5C12C\
3C62034861C343B7F70B9D475CCC10EA5889910E04CA7EAF0B762DB56962EC40CA47CEB4D228600\
595CF22421148CF02B4CFCE76AD27701F925C01C71C5405534ED54B0100C280DD861D89E967BED4\
829C568BB76CA500342803835F7983179CDA15899033F797951031138A83669AB4CCB4630058088\
AA0845FAF7B0761B405AE866C426711EB152889D175E7B20DA03126B7419A766416A68AAC0FBC35\
5DA07D6E6339BC0539CEB55711F633B8C7392627497821CB9D7174C4E655B5928BF722C84B8233A\
0993B6DE02D7364443EA4C73A754B8190243DF936184819E1B8AB6F0B0BFBAC6C47E66DDF11757B\
E55E0787ADC112C63E644D1B904877764D856ABE78B583600CBB2119CB916C689D4543F4D553CAC\
33AD19B245B4948EF0BA3E7D1151179B9FB2941F3674E5F8771677737C435B2383119A3E7543411\
4439506E1B9145FF16B1458879A1039962434151619B77915D033A3FAB7385FE861E4A25B125A20\
5C3F1B16972470B2791534B5FB8731B20C03684CCBEB97A1FA4417655BB485C347519710522C357\
D50C43FC2644098533FE549C825F5DC8CA82A0DD908891BB4F92EAAB51CBE036CD6FB59A749269A\
0A3",
"0F6512622B9E8923C5FFBCAAC1401FB3F50D8B0C561AC1BB175634DA089374308CEB287074\
44B126E6438C4270CD735AED70CD0BDC6B975C480F6C5C5436C263BB604B33B750827792A95BA3A\
79CA3D9B8174C1BE945AB2BC86580A6778CD11471ABAEF93607B56C887CB12BAA5B3C9A264386C3\
712EB80F596274192465F18B4862F9A1C666BA71939EDFD67BBF94B35D663D60501308A03B11E47\
C50A979BB81A2D1310354911AD830691AB5126352418736C76DC7ACB304277806466B4116E1F13E\
319C4B82E4ABD6C23161458BF0A9C4D3CC3C22F513E6B759C4C73E046055C666518D35BA2BFAC25\
53B45D2E75BD0916DCD146803F2B9D904C33BD4A2F10AA0AE6230AF55BD985955BC742BACF81387\
153D0E9C39759707AA4A5FFE0C6655931ED5CB25BE896F2DD74E6F4055C4A4714D084420800FC0B\
613AD51ACA78B210F062102D88BE45CC56BEC037916A375525C3AE4AF54681C7A90942C8249E8A0\
5F4CA0673CD92C4767B2F26A68C53A0AEDE9C488547FD9B90355F641EB4B359CBA25F9654F9A67B\
CF5B6CFDAB4A637636AEC1ABACDC7C7FE0C1D187172E1F2A1E7B5193B6831ED51BECAB244D62A72\
A5AB022A331992941AEA849CC661018F4A8CE01A4725F4BECDF225983A2404A24CD6A44B0E7156E\
6A96702D2736ED790908516FB555D2E31B966E2660CB1C766831C583C153F81A6758B0BE4820437\
7B343E821F2C032BE18314AD24C110DB1656CB8452CC85C4E44879DC61BB083BFCD44A5A304A66C\
992FB7BBCCD0A83A10943B0A4B8D5CC17C30433EA842F942062ACA3690806B43D6B80590B6088EA\
81CDD36E9C40839D90AF4DEBC50CA06B716BBE4A732305DC5510A55F8E385509EB1532770775523\
1C4733A8EB9CE80D395A7613E8627A206A9A9CF57B388A780CEEBC55EB549D4338695355F6B1C98\
0BD71F2D40CF710C20B468412EC65C3F48799DB74453108C26C609A6E0643D104B65BAA6C0E416E\
0102D8D261C12E40C3A02A08EEC44C90B99028774C66663A8E5470C715514B4BB4BA2A5C71B424A\
9929E893248B66B6FCF97646691180254DAF9490BCE53E88057554B15C7D7B8358FA2879112E761\
A030FF02EFBDCA46E5808A9B75D0A69C4AFB609BA94698181710606885C176232C92AAAE283FCE1\
520414552A90ACAD9421E4D87EA4171E28B8260A3061DCC50EFFD48B60DB28EE501D33732A82635\
40F33B9803549D1D936B258863BCA134B156C6D4285B763BD52D807FD7425AFC5334E5961800807\
9034138EF057246B3A10BBA27117850124BE41353791B67F3B5A5DAE0C9446925A8D4936723982A\
B43399298026EC9129404031478A148C7290FB100A999BE95582326D35E06294C2AFC531083942B\
C0B91759B9B53B920F164A53C22D279747107B62A15703798CA4702B5B4EE323424C4DC8FB1E2A7\
5B21791A8F5C878BDA55657C8ACA47A14C082384A62CF88E483F071063AE33931D8627EBA8A08A1\
6B08B72DE6F7AB453917CD9145FA4B4FA34AB1A601C4B09136AB91734DEA5CD21C657393857B84A\
B6CE5693D0A0D8DA853224B301AACA554464450C08187FAA12F9925A0E222D596AB0767A6352B96\
1CBA921F0A8C03E4AB0118D65330DB1FC759D3204C7E89A3D5BA296A717BDFF283B2F5B17334A36\
C6E",
// ML-KEM-768
"533145987CB33CD2C8F5AC8A73C03A97FB31D2B89D02B1576CFC77BC97656FC040FCC75697\
50459EE753EBD69839692B375A0F53165B191CA8C6185B85626282C0A4AD63B36B6A289F661D505\
850832248D6F39084695C028B979835848931874E037EDF33CD9F1521E2B478BF0C37D859572AB0\
8C20F7687749032949AB7457B66C1206C08A78C58633BA008E8770224700B84758B22B290E9ED01\
F750439B00B97729960940817D3BA0CE7F10EB6A0C8EBD975C85A6299A6CE486132292189F9DCC1\
3F275918704192A417E7B305834323C354213195BAD0A5AA30A3980B028A1E116E97E74ED8D053A\
2FA51E00068BCD69D325246E93A30AD493D28099AF143016BE454413256A5DA144C9985C70664EE\
12013DF167E228B921EA3BAC494B5D5140581A4D7E7080B4C284A6DAA955366EAE3217541A0B110\
9313F7A1AE9305D55B45CB6A5B2F3321A10DB137E92306A3B2A25FC1999495F7A732D7CD83BE092\
3050A5562A036699F92427CB71C0CA201D958F7A3171740AB477188DB276A52E576703493E289C1\
4BF896D5A827586492D23B605CDC6932A4ABF902A219F88B12D0479C91B4EE6C586A4A2061FC22D\
66264772359B569456111574D84606CBA28292C37A40B81F5A113BB9E72871E14184270FE2A87C3\
3BA7D01E95A578950D098C48A584428BAC781BA938F13BB80F4790EC36F1A394FEC97AB80054F60\
A90DA86ABE7D84799A604233A5A495294D13805B6CF3505DB833E9F223D102AAA9E666580B088E1\
CBABC4CB52725CB768B5E990B89411AA652E06A2BDB937B185EB924C59AF6BA9BE2BA09409DB5C2\
62D751731461A89AAC05ADACC320B6AFC5C4A5FDBB2F56B2483D11779C7117707B121D0B36362B2\
BF8D4B28F6948F5EB1D5E41B1C8A5053D581019C36AC87988803CB934027909DC4C5BD1AE2EF451\
D9F7945209C0E9E60AF43C50DC98646F3BB13BE6491E91930D9AA1AA315FB3B1A067579565D170C\
4E888E9042751106B72A60470A69992508E8CE3101A602A22DA7FB1A744F09488E704481F649DAB\
6158E5306F573009EC63ACF11B549D280033343FC9750BB927B931B94F9C5475A2B803AF36CC3CC\
30521EA2A86040E03E7CF90B36D2E370856285AE4523367482E68473CA500200F75C8C423C8AB93\
C7BFE74DF253AF97114A3FEAC1DDD34E06747C6B386990428100A99351BA14A3C19B1A7A6DA5A71\
5F6A698E9FC330C13B98D61A2A85AC0E0896CC8032490B93FEB284703F21E6D16307D7886F94875\
2FE55CEE7291C06AA7BBB79146C644AEA7C2765C5EFA535B729158EB51BC2D4C389B970B3008696\
6D858D51B78EF3829F9290DAF241C6D370425D83DDD61153DD2AC0FD206120434AD6792D60B2F08\
4A2950AAC250B4001F309EA45B09D9DB440D6A2C9BB3B140569C51C985A2B0BE03ABA918C2311B1\
1069FC9A0C762CCA59C1BDAE47C0406AF0CC7BBB1821C0F8733563ABBE896525E1156F7D593F55C\
39922B6B79E462CE587189247FA045CB19FA7256B960D0B25B7B364ECE250D43E19313C798CE424\
634DC358A0914FAF33EA2B06EAA748947C6C150E54D7BD3A4C4873B117266145833FF04CAA96424\
AB678B49BA94D6619F01BBC62961850CF25765C7627910EF8E79F9B3749086AABF75407D7AC4274\
8BC",
"06F51174F03C2FE07CC31B0659B87EBF124237811B88B980BC277F8C050B265CBEE1A4AE71\
45CB9253281BBC291F2808E065855FD91C7D14122C589FB21B45FD3B7FBB6562FD53006B565189E\
C983C7A0D4C21596EF3795AE22ECAD71F75395558B55220662BB66C389ED9AB6B784476E1788F34\
B28B59A4C6F71F9F6A49DA80C4D3107DB2C306968B5600E18285F8BFA293677F699FD2D2820DE49\
0F530818D6667686A765FCC0009484D71629C1F148104B462325AC55EF34DD5C7098441A06757CA\
35C8ADFDAB6D36333310241F9970B1B123478DCBB75AE6CA39BB84FFCB23A593C24BC54E74B4086\
165BB4B10AE39F45447AA4EA5F55762386B11051B84B0A688C12C73336FC87164B7FBC7F0B07D2A\
51BB05560606D5558666CC322963AD3CA2BC1293260A94707770C030B2BC9C00477A8D5FF673796\
1480D48109F66075DA9C8AB516F70A78DA9E444AB65798A2565965A68AD9146FD9267D2A80C4352\
A0A988157522046620A63D9BA7BBCCAFD50A61384453F8545845B25E7A05745C4B26EF7211200A9\
16241047FDABB66936BB7351C04F5CD06A10AE3C459B74BB0CD85044BF8B6BF2B33294014B9D685\
17CB1A9813230BA08813807A2DFCC6A739B6AC79575F19BAB96A7CDED404D0E52508214AD43763A\
0A048FC36785B2C718F75B3432769C1D2A6240336A82B39D865739AF78E94A92BD7B4703210297F\
B82E0BE57B97384DB5B24FFA5486C982AF48642D967222A28C6F83E5AD6A59CA486733808BA3BD8\
6A780E59888011965A351CA949B0D6C72FB3BA0F867834D166819C252D9600207C88997318B2D20\
4AC3619247A01829484F12BCA2E8F16AAC677C9E8AC209F9BCCF019BBDA66E8F073DFBD934E08CA\
15BE77576029654E049C1C20B1B123E5F0B50135628CD2C96A5D0B1EEF48FBE08AC4685247721B1\
28F71DC748452B94A458F39B337BC2305CCC505BB18BF6ABE3EC2C825799B95C13A1F6411CD3B03\
1F3CEC3D99AFC1A28F2019C1BD129A2EA35F06415C8B717337957CAA964E794881257073FF5C12C\
3C62034861C343B7F70B9D475CCC10EA5889910E04CA7EAF0B762DB56962EC40CA47CEB4D228600\
595CF22421148CF02B4CFCE76AD27701F925C01C71C5405534ED54B0100C280DD861D89E967BED4\
829C568BB76CA500342803835F7983179CDA15899033F797951031138A83669AB4CCB4630058088\
AA0845FAF7B0761B405AE866C426711EB152889D175E7B20DA03126B7419A766416A68AAC0FBC35\
5DA07D6E6339BC0539CEB55711F633B8C7392627497821CB9D7174C4E655B5928BF722C84B8233A\
0993B6DE02D7364443EA4C73A754B8190243DF936184819E1B8AB6F0B0BFBAC6C47E66DDF11757B\
E55E0787ADC112C63E644D1B904877764D856ABE78B583600CBB2119CB916C689D4543F4D553CAC\
33AD19B245B4948EF0BA3E7D1151179B9FB2941F3674E5F8771677737C435B2383119A3E7543411\
4439506E1B9145FF16B1458879A1039962434151619B77915D033A3FAB7385FE861E4A25B125A20\
5C3F1B16972470B2791534B5FB8731B20C03684CCBEB97A1FA4417655BB485C347519710522C357\
D50C43FC2644098533FE549C825F5DC8CA82A0DD908891BB4F92EAAB51CBE036CD6FB59A749269A\
0A3",
"0F6512622B9E8923C5FFBCAAC1401FB3F50D8B0C561AC1BB175634DA089374308CEB287074\
44B126E6438C4270CD735AED70CD0BDC6B975C480F6C5C5436C263BB604B33B750827792A95BA3A\
79CA3D9B8174C1BE945AB2BC86580A6778CD11471ABAEF93607B56C887CB12BAA5B3C9A264386C3\
712EB80F596274192465F18B4862F9A1C666BA71939EDFD67BBF94B35D663D60501308A03B11E47\
C50A979BB81A2D1310354911AD830691AB5126352418736C76DC7ACB304277806466B4116E1F13E\
319C4B82E4ABD6C23161458BF0A9C4D3CC3C22F513E6B759C4C73E046055C666518D35BA2BFAC25\
53B45D2E75BD0916DCD146803F2B9D904C33BD4A2F10AA0AE6230AF55BD985955BC742BACF81387\
153D0E9C39759707AA4A5FFE0C6655931ED5CB25BE896F2DD74E6F4055C4A4714D084420800FC0B\
613AD51ACA78B210F062102D88BE45CC56BEC037916A375525C3AE4AF54681C7A90942C8249E8A0\
5F4CA0673CD92C4767B2F26A68C53A0AEDE9C488547FD9B90355F641EB4B359CBA25F9654F9A67B\
CF5B6CFDAB4A637636AEC1ABACDC7C7FE0C1D187172E1F2A1E7B5193B6831ED51BECAB244D62A72\
A5AB022A331992941AEA849CC661018F4A8CE01A4725F4BECDF225983A2404A24CD6A44B0E7156E\
6A96702D2736ED790908516FB555D2E31B966E2660CB1C766831C583C153F81A6758B0BE4820437\
7B343E821F2C032BE18314AD24C110DB1656CB8452CC85C4E44879DC61BB083BFCD44A5A304A66C\
992FB7BBCCD0A83A10943B0A4B8D5CC17C30433EA842F942062ACA3690806B43D6B80590B6088EA\
81CDD36E9C40839D90AF4DEBC50CA06B716BBE4A732305DC5510A55F8E385509EB1532770775523\
1C4733A8EB9CE80D395A7613E8627A206A9A9CF57B388A780CEEBC55EB549D4338695355F6B1C98\
0BD71F2D40CF710C20B468412EC65C3F48799DB74453108C26C609A6E0643D104B65BAA6C0E416E\
0102D8D261C12E40C3A02A08EEC44C90B99028774C66663A8E5470C715514B4BB4BA2A5C71B424A\
9929E893248B66B6FCF97646691180254DAF9490BCE53E88057554B15C7D7B8358FA2879112E761\
A030FF02EFBDCA46E5808A9B75D0A69C4AFB609BA94698181710606885C176232C92AAAE283FCE1\
520414552A90ACAD9421E4D87EA4171E28B8260A3061DCC50EFFD48B60DB28EE501D33732A82635\
40F33B9803549D1D936B258863BCA134B156C6D4285B763BD52D807FD7425AFC5334E5961800807\
9034138EF057246B3A10BBA27117850124BE41353791B67F3B5A5DAE0C9446925A8D4936723982A\
B43399298026EC9129404031478A148C7290FB100A999BE95582326D35E06294C2AFC531083942B\
C0B91759B9B53B920F164A53C22D279747107B62A15703798CA4702B5B4EE323424C4DC8FB1E2A7\
5B21791A8F5C878BDA55657C8ACA47A14C082384A62CF88E483F071063AE33931D8627EBA8A08A1\
6B08B72DE6F7AB453917CD9145FA4B4FA34AB1A601C4B09136AB91734DEA5CD21C657393857B84A\
B6CE5693D0A0D8DA853224B301AACA554464450C08187FAA12F9925A0E222D596AB0767A6352B96\
1CBA921F0A8C03E4AB0118D65330DB1FC759D3204C7E89A3D5BA296A717BDFF283B2F5B17334A36\
C6E",
// ML-KEM-1024
"E2F26491D9370C69C5866B0AA4E5951B2C9602C74B7AE4C27436B130F209DD4915ABBC14F0\
C154A67369C8504461595310B43BDC10A577F35EDDC16154F587BAA0C37F663739C8AFF34533C56\
947E4A637155619AD471162E9BFD6D18AB91B6F639B231865840A032E2B617E9A307301D0C27D97\
7C4A2C7D5E1006FA15329D550E1E27B116A400084BAC35E03698F2035BFB249DCC5224FC3C3B783\
4B0B0BC7C09B6D48A3AE649CB3B95A131479E609715357A30CBB0C19781A9BB819D55E4385AE7CA\
53B58CE699084DD96CE2361F47E97E82401F845909BB67707F8B876324BA3C35C712E313D476591\
47BCDA125349E7767396492E6CA09B3DB2AE2F035769C8F200B4874435098774AFA97B6D60164B7\
97665428850EF70B51A65924865DCBC4243B9CBD6CC07489772F8F64260BD666EFA2768F3800D82\
81A4C97B1E3AC8382A62F4C24B65A17322B75C7A63B74724C1DFBBAB7C9B532AE44B020E675412C\
768210793FE464D8AAC738780281710AFE3BA5EE1A7E4F15458DC27D0EC3B3EE8B41065456BC757\
67F713BFDCA6222543619C705474C922025351334C71A595F38B31427B40980571A6804A1974B3F\
C21B6EA52BC074187576A3B062C3712DD69D99683BE6800A1196739FC32E52606B8CC4CB10838AF\
8733B3F638D03C3423DA7CD5BA971B66C8FA3EA6B60D5B04AE14E7F8C4A66C01BEFDB4520E62138\
D76667595CE06828BFE31735D73D2228AD88F02545155C85435E4D62264C665B05503E93A7881F1\
8AC11FA12B293056B695AD275BA41C45ADEDB34D2BCCF8E2C715417A41994270F52C155936363A8\
0850BA70B2EC53404B7470CB3FDA8B117B138B81B195A51A72ACF50A1CA07F59E420F41B5618203\
36827415C27B093794124C38B68709E7C2B5C8A11ABCEE6C7A6096EE2545E0F58594AB57AA86CCC\
3AE33B94E4BA475403471549253896404715E110933290ABEE2C03E301BDBA737D280079362C8FE\
30143F5171C4349042B421CD5A1565824C21E6A4694F92EDA35A178383ACD854597308A2DC68290\
B56006DC4C2B6BCB6184835771950B6A590A3B0888578DD9E1135F857FB836A6373C914A429E9BF\
62A5DC855B954A8B8E606187425E6922DFD975477D32479F0B226F7BD0D0952A6C7AD07D31E4F8B\
803BB5B3A8071F98895A0773C40D902CCB4B6A6AF24E550A2BF547BF03C00A7236AC7FA82CD31AC\
7D4A8212DB1AE417006BBF73FE3FA9C155557A449C51EB56C60824105A33EE6E175A51191F1C440\
F711CB670994D3FBA08AE608BA598FC39B80338C96E25B4FF41B945C56C17BAA946A18AE275288F\
51571B0F34D67A74127957F0DD979E362B5AD7AB53E5C100D422A0C1400A0AC5ACCA081A07C195B\
75139477BEBC313DD0E76ACDE0AB1186C18F3AA52D87A2F70C1A6673AC7E1A6DB24B52D2AA1C961\
78B75DB0AD53AA9DB8A09FFD77D8AB6447EC1429AC85D1BFC361E1BA35A10715A1153434B3E5D07\
0C1BC7A72A4B7D54521213D429D0D30668037E8B2465B03C7EA170B0428AAF2E0A2A26EB432DB45\
FC642A20AE06D8A39282BB9246743A77BBB12ED43648FE06236F3B1805C5B0373760DCC5225424A\
D3E38971671E8E083B922A52E300225171147CEB7F9E9A1B6D155F6987950C62B9456C7E3178CC5\
B9022A25B25A42C057CD05876936602947467C88255A848EE048256AC2FF7D56E4A250F9CD476E9\
91449FAA568E8B432901B394CB6EC54836E62C38CD2B3C62D732EE7812DC987A6E8CC5E3D60D4C8\
56B39B703E7AC2F799A2918DBB343F79C0AE7787438692E780B6444C2B5D8BE2AC06157B65101F7\
7DF8905BC19915A9D2548A096E79999B45773CDFE18F2AF6461DF2AC82A92F241C450886569C03C\
9713A457784AFDD0A7B24DB43D3565B25A57E0F766C6CDAC4778A8B5F7074260394E608000EFBB2\
6DA17282E908921AB37019B019CB16593B9F9296735DB96123B4A3196CBD9A5596D2E6155BB357F\
1355DE4159076B8611CF07851331C55C835F33967DB045D855B5CC9243E1D16BEF176B9F20165F0\
A1C073BC8427132618F86C3D731F8A3736AEEB7AA537624A56296273C3C057C1F0213E912A870D6\
72F84FA193DCC520A514A2900C4C075C9CE0125E11A69ED86024C423B068B529E4BA2D7234C72BD\
4A09ABB09E4DD7F3C4789027DE5891D7108547F31B006276DD01180C1CFA",
"CC8196E5F1B1BA054644D0B27D952BF3E7AED0D611CB428641432DA8601AAC66ACB6FC3BD5\
907D2EF7CEB1344A17E656B46558ED53A993472BD5976994356803767F656CC550E04E3F4A256D9\
4244CD7C8F881233F31C54A805696E5BCB4380BFEF6442A06A98789A54D38B25EB7088145A6A781\
1D3A083DB4BA245F851D9357B48216B9F3C9CBFE610088F70CB3A018465B7FAC4744975729C4703\
AA5189B1F88C284E258FAE81EF93C3F41C5B3141CBC1E5432DF767B471BA378B95C2EA717424594\
1E9227250AA8027B810D8290229742CFD284C137183F6950E372A4B8B03CE8C89B9C471203542ED\
360474DD663F0A0BA9D804D8C339753AC5B2D2B8EDF33BBA96649F7336A42732917C902723A7B68\
10658B95BEB31540555600C0B0BBEC1823A273A405C6070990BB80F66ADB58BC1B502603E91B6AD\
A6AF4780A65D49BC9655EC0B2A919AA2C98C11AA72A0FFA50742CA4907357335C897EDCF25006B8\
CCB580041FE0061BD2160AD1B42B2A10E2E98E745294D333B6FD5159DE66557096B4BA3A96019B1\
8D6EAA92A0B6589F579F0998053B8C639A0134241A56DE420FBB82F99B1B3A5292D83BB83396A0E\
9C5B2CF97145670C6F34DA6E9C0CA3C0C51B20B561C1B85A1F42B7AF8320D3196D18F3A353A942E\
C676E9DA68B23638FFAF80FFDD55F87885F73C76256358787945217F56634217C91731DBB1382ED\
765452CA80133A2952B3155165BF26E2550435644D8628EFA974E45B1EEC12CE14C54E76826538C\
610D76662B6B0251A12CD5B3004610A12B8276A84CA76AECC9E14E524F05B75D445920647C33235\
8CD779ABF3F97AE54963D8A235EAF0AC94C99FC322A7650890B904B91385CDB4B716F6067ABB353\
BE5557FC54461A74C415F81ABEFA227004768846192D5E832C8284763285BAE3A1FE0C3C94488A4\
FA932465E1C3CC6A5A7F6B780FAB431B078E226A237518874747605090B5F3C83B24FA84F555954\
0C0969C00D0B370A6C1F51E3C4038B401C93FF46BECAB9AD9408DE62A3486E3BAC30A0D3D4B2108\
2B1123110B196BB294F6509BFC698F520C5D427036AA8D3598B9DAD641ABF8AAFD2574AB741B149\
03D693851DB705309DBB9C21855FDEB35DA3078AA51629E9537771C877A5C914CB05D8E0633539A\
CF93ECC0018C4E6AC40BB4C959BFF0450CEB97E24838A9DCBD8037B0047C8EAFAA4483AA3573EA8\
1E56C2A21D17B302095D14CBFD9C0490F68857C90780C2A1294E08CED2B9CF3BA47D025B99F1C1C\
E37C4B470529462CA1B1F5547AE01D44400D30B2A4809984E4B53519E604A4086A62CA6BC21C3F2\
3631D4E188614E72F5E50B976BB7B8320B897433E9D05BEA780280E547DF5537863A761575C8179\
C49025811578D55ADAE48B88F7A975DC4FB0B4B9C46C020F02303B68987816B2B0792380AC04C8A\
411A2B226EE91C4B1A45177A83A3AA633252B410F60C7C532C783F15891F51E9DD319CD6C4A5995\
944BC0695A160F2979C967017598957A2463BC7C943A2D852E410148F32C8C88054900AB0C1DC82\
F8A316EEDB966078A72E3537B5D969A3F26B93FA3927F774681413E3DE47EF9A5C1F581C2FE4034\
5A3B783F98CDB9926DF7E93A0EEC4B3201733D1607E5E67366C1CB08DBB1E5AA6DEE3231F150627\
76C1174C722ABEC857E23A8B21C559FF915E1D67B56AB52E2290276AA5577557EDD5731F0C0A52D\
2806756CC1FACA5A26F38ED656482A1733226237D4CC910FFA275E77CE60F6637B7C7C4B2921FD5\
3778383C7C50494F3435310A36D75C75A8404237CC05CC0F96F20BA333690029DA033175A16BB59\
473E913EB9974A033A01D29AA46BF9667E87A98B05809FA8471827C2C88B873A29A3776A7A51911\
B291C02D1C1C2F6DA5915C11A181518F32334215796A350306E1BA29EC5CFFDA5C312149523D0A8\
7D5B5D6B678C11E6C7DD354E51558BD779A814D77BEF6C9DA50412DDA32CA2A7A337B87124562C0\
F2C81B652735EEB491D155A9777CC7F4C4884ECC29106587DB923A8E50428748547D391E2F282CC\
4039ECFC5DC902265247381CA73BF948A77916A62AB347C4200CDAF62C30F3AB8036441343A903E\
6128E1A2803561176F3AE0D3050B0FCBBEF041DEFC72A9A43AB8CF918B8952EB9433CEDF82D01D9\
F00E44E9B7FA173E2DD8B12BEE781BED3E220007DFD751280B76563610C3",
"9945C4E2DB5B86E311B3450249742A0FCA203D514B68B7898E2599B095123370A302934C27\
F79C169565F4267BCEEBC67F39CC5881807D68A3EC61A07B3081B2069BDEB27402430AAAB193619\
C8562D486B21AC8CDF1C571F4CEC0CC991A99058EA3C6007A8A118A385F86A9A8C811A952CAAA5C\
5B78CC76D553B39C518415EA568AE5AB26353163D94EFCF9005A045269E50EC0C2006BF15896308\
77AD66B623B52AE4924C8716E32C6833BA65BDE5A86CE4ACDBF3721C7908A32E09981674B446B2B\
1C2AB9B637B8105C143B29B85E55BB7A36A03DE3395765866EA65BC0E4960088B6D617903CBC14A\
C12CCEDF8305F0622F83A848F9313F53C504FD8B6EABA4D8420C5B1400224D165A5BA521955CF93\
C22FD358C88D385C9B349410B50115ABC22BB83010DB0A2A6B227E986E9EE0ABC7C471A719A7EBC\
7B84D011053BB42538662F7249DF53B422146016997AEFC43398118A82585AF1E700B65198FEEAA\
2C001A3AD9372F4C9A12A3C3525AE2C38256661229CB567A0C2AB214702CC7FDE1785A41597E496\
9100BC2153BC7EA153582225EC109AFE2BA851E926BBFA3103DF4A2E72A1AD732365A697E93F900\
38296DE5925C719423C413C33553AFD8105BC9C7CDAB690544EA5700ECC2F592C4063085C2375F0\
CC9BB3A5BB057E243DA632AFAB9916AC78DD45ACB5204368E47B20313475253B0A2C152809734E0\
9ABCABB6934041CA3A8B5A03FCBB29116D4E456E89A0769BEA053E9A888261145D0911E042724A4\
1B35D154F3A266E9A389783804F4E239F80868C1EC459A2F2C8F5E44EA240B2CEBA3DA2DA93B1A6\
711DE01009A67E14985416C48830BB56CA6371EA007F87BA3177F558E3383798579F1F873769C05\
3BFA8CB6FC4C53030839B1343D2C367E2F422BC1C7C00EC392F94C17D4524CD98B071B09693A73B\
2DC909C8AB26F4A12A8C46C1FDB11A9D6428930351874BB49B919E7D245AA2F14EF183B47917B39\
FC6B3F8C664A217A11BB1C256D896F5FA68F6250029D49D797163DB011F5067A1C4158A71F8C52A\
02C4BBFC67621B4A1CA8914D673E25B0C587D1887C638C438459B141849CA906D0B363484A7A1E5\
778DE74659F05A327470E960948FEB01F66DA1442E1516CFAA42D6BBD5FB6C2F5EB49E50CB7A0D3\
1462013F65571E6DEB53FA65890D394474D33E1C0B022FF4129E8671AE275B6492886FA94E02401\
7211BBE60638124A76E9F49234E210380B46B3D686A24713E4F9C47D82BC4501084CC3932DCA5BC\
1AD02C5426272DB0880443726C4193C2337119F66112C1997E97C6D602562412C9C3A23C0723118\
F7A4E1383A91A4B7151A0454007066532440E93CD76C6B24163406AD276A9E693F085ACE935CEB3\
DBA7A3E49F66615D05D47A4AC12972E8BCDEE754BAA0C7652612745A5889518062F46FD00086AEE\
62731E5557A631D7D19A420398F2E66A08179949F2A9CD7325289252FA714C9FD3CCBB3AC8BC2C5\
31CB677845749E6BC911CE416708760E8F281F69231BA0893F10A4B4D7AB8FF78387F2DB6D66A9A\
0F324A1073738553C901D8C3BDE6C7E704159B7F0949210BCC35BCD8E7C1CE92AC8B50564BAE5AF\
6982174789CDA0F9CFFEE1A3F9C36DF035122642CEEA535CD860C4634B981DD2CBD3B960A587891\
9ABB9893A2837A0A59AFA98D5D858FF9937FE46248D8003BA1CBF6AAA0BA39876EDEB36FAC726F4\
052155A85C006389550CCF4BDC20C2363A9D5726EE58806AA878FE7B2F1488953E500013A96441F\
643DF095195C844487C37B05B70AFAC550A67CEB69659E38A19DD02716CD42406369CDF75C60563\
27ABA4CCEFF301CFC2290A7458593B599D4549AAABC4973C735AA94F308002CF10B4AFC84B9F445\
E1A127852DB05ACA68B8CD850EC768A8BC0CF62560246643BDFC08698C3BCB1F1A5771569F4BA95\
1746845043781CE969B775B08F997DC37AC866C13ACB153957F47BE0338B286717C348455D85424\
F93CBD4329EEC94A533539A7BA06103FB7079739FE0E08BF8CC4F7D2BBA6A89B100E219EB7C5899\
E94FDC2CAA385CCFE9E0703AB87317C5C57D2C5DE31722BA1841D7B204FDCB6D66180B43CBB7D94\
B91D6F48EB478A95EDC71D371B55ACB1616C220965B4BF2B907420B4B4663374DC682E1188A4119\
33B533F8692AB637028C5D029DCB7A310A3BD6377BB6FE262D26CD38474C"};
/* Label contribution from B */
const char *strLB1[] = {
"0202030405060708090A0B0C0D0E0F10",
"1202030405060708090A0B0C0D0E0F100202030405060708",
"2202030405060708090A0B0C0D0E0F100202030405060709",
"3202030405060708090A0B0C0D0E0F100202030405060708090A0B0C0D0E0F10",
"10202030405060708090A0B0C0D0E0F1",
"21202030405060708090A0B0C0D0E0F10020203040506070",
"33202030405060708090A0B0C0D0E0F100202030405060708090A0B0C0D0E0F1"};
"202030405060708090A0B0C0D0E0F10C02030405060708090A0B0C0D0E0F10C8",
"202030405060708090A0B0C0D0E0F10D02030405060708090A0B0C0D0E0F10D9",
"0202030405060708090A0B0C0D0E0F18202030405060708090A0B0C0D0E0F18A",
"0202030405060708090A0B0C0D0E0F14202030405060708090A0B0C0D0E0F14B",
"202030405060708090A0B0C0D0E0F100202030405060708E020304050607080C",
"202030405060708090A0B0C0D0E0F100202030405060708F020304050607080D",
"202030405060708090A0B0C0D0E0F100202030405060709F02030405060708090A0B0C0D0E0F100202030405060709FE",
"202030405060708090A0B0C0D0E0F100202030405060708090A0B0C0D0E0F10F02030405060708090A0B0C0D0E0F100F",
"1202030405060708090A0B0C0D0E0F10020203040506070A202030405060708090A0B0C0D0E0F10020203040506070A0",
"3202030405060708090A0B0C0D0E0F100202030405060708090A0B0C0D0E0F19202030405060708090A0B0C0D0E0F101",
"1202030405060708090A0B0C0D0E0F10020203040506070F202030405060708090A0B0C0D0E0F10020203040506070F2",
"3202030405060708090A0B0C0D0E0F100202030405060708090A0B0C0D0E0F1F202030405060708090A0B0C0D0E0F103"};
const char *strLB2[] = {
"4202030405060708090A0B0C0D0E0F11",
"5202030405060708090A0B0C0D0E0F110202030405060708",
"6202030405060708090A0B0C0D0E0F110202030405060709",
"7202030405060708090A0B0C0D0E0F110202030405060708090A0B0C0D0E0F11",
"84202030405060708090A0B0C0D0E0F1",
"95202030405060708090A0B0C0D0E0F11020203040506070",
"A7202030405060708090A0B0C0D0E0F110202030405060708090A0B0C0D0E0F1"};
"202030405060708090A0B0C0D0E0F11A02030405060708090A0B0C0D0E0F11A4",
"202030405060708090A0B0C0D0E0F11B02030405060708090A0B0C0D0E0F11B5",
"4202030405060708090A0B0C0D0E0F1A202030405060708090A0B0C0D0E0F1A6",
"4202030405060708090A0B0C0D0E0F1F202030405060708090A0B0C0D0E0F1F7",
"202030405060708090A0B0C0D0E0F110202030405060708A0203040506070808",
"202030405060708090A0B0C0D0E0F110202030405060708C0203040506070809",
"202030405060708090A0B0C0D0E0F110202030405060709A02030405060708090A0B0C0D0E0F110202030405060709AA",
"202030405060708090A0B0C0D0E0F110202030405060708090A0B0C0D0E0F11C02030405060708090A0B0C0D0E0F110B",
"5202030405060708090A0B0C0D0E0F11020203040506070A202030405060708090A0B0C0D0E0F11020203040506070AC",
"7202030405060708090A0B0C0D0E0F110202030405060708090A0B0C0D0E0F1B202030405060708090A0B0C0D0E0F11D",
"5202030405060708090A0B0C0D0E0F11020203040506070E202030405060708090A0B0C0D0E0F11020203040506070EE",
"7202030405060708090A0B0C0D0E0F110202030405060708090A0B0C0D0E0F1A202030405060708090A0B0C0D0E0F11F"};
const char *strPB1[] = {
/* ECDH (NIST P-256, NIST P-384, NIST P-521) public keys from NIST CAVP SP
/* ECDH (NIST P-256, NIST P-384) public keys from NIST CAVP SP
* 800-56A ECCCDH Primitive Test Vectors.
* http://csrc.nist.gov/groups/STM/cavp/documents/components/ecccdhtestvectors.zip
* http://csrc.nist.gov/groups/STM/cavp/documents/components
* /ecccdhtestvectors.zip
* ECDH (Curve25519 and Curve448) public keys from IETF RFC 7748
* https://datatracker.ietf.org/doc/html/rfc7748#page-4
* ECDH (BP-P256 and BP-P384) public keys from IETF RFC 8734
* https://www.rfc-editor.org/rfc/rfc8734.txt
*/
"809F04289C64348C01515EB03D5CE7AC1A8CB9498F5CAA50197E58D43A86A7AEB29D84E811\
197F25EBA8F5194092CB6FF440E26D4421011372461F579271CDA3",
197F25EBA8F5194092CB6FF440E26D4421011372461F579271CDA3", // NIST P-256
"DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B4F", // Curve25519
"8D2D688C6CF93E1160AD04CC4429117DC2C41825E1E9FCA0ADDD34E6F1B39F7B990C575208\
12BE512641E47034832106BC7D3E8DD0E4C7F1136D7006547CEC6A", // BP-P256
"700C48F77F56584C5CC632CA65640DB91B6BACCE3A4DF6B42CE7CC838833D287DB71E509E3\
FD9B060DDB20BA5C51DCC5948D46FBF640DFE0441782CAB85FA4AC", // NIST P-256
"DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B4F", // Curve25519
"8D2D688C6CF93E1160AD04CC4429117DC2C41825E1E9FCA0ADDD34E6F1B39F7B990C575208\
12BE512641E47034832106BC7D3E8DD0E4C7F1136D7006547CEC6A", // BP-P256
"A7C76B970C3B5FE8B05D2838AE04AB47697B9EAF52E764592EFDA27FE7513272734466B400\
091ADBF2D68C58E0C50066AC68F19F2E1CB879AED43A9969B91A0839C4C38A49749B661EFEDF243\
451915ED0905A32B060992B468C64766FC8437A",
"30F43FCF2B6B00DE53F624F1543090681839717D53C7C955D1D69EFAF0349B7363ACB44724\
0101CBB3AF6641CE4B88E025E46C0C54F0162A77EFCC27B6EA792002AE2BA82714299C860857A68\
153AB62E525EC0530D81B5AA15897981E858757",
"00685A48E86C79F0F0875F7BC18D25EB5FC8C0B07E5DA4F4370F3A9490340854334B1E1B87\
FA395464C60626124A4E70D0F785601D37C09870EBF176666877A2046D01BA52C56FC8776D9E8F5\
DB4F0CC27636D0B741BBE05400697942E80B739884A83BDE99E0F6716939E632BC8986FA18DCCD4\
43A348B6C3E522497955A4F3C302F676",
"700C48F77F56584C5CC632CA65640DB91B6BACCE3A4DF6B42CE7CC838833D287DB71E509E3\
FD9B060DDB20BA5C51DCC5948D46FBF640DFE0441782CAB85FA4AC",
"1AEFBFA2C6C8C855A1A216774550B79A24CDA37607BB1F7CC906650EE4B3816D68F6A9C75D\
A6E4242CEBFB6652F65180419D28B723EBADB7658FCEBB9AD9B7ADEA674F1DA3DC6B6397B55DA0F\
61A3EDDACB4ACDB14441CB214B04A0844C02FA3",
"01DF277C152108349BC34D539EE0CF06B24F5D3500677B4445453CCC21409453AAFB8A72A0\
BE9EBE54D12270AA51B3AB7F316AA5E74A951C5E53F74CD95FC29AEE7A013D52F33A9F3C14384D1\
587FA8ABE7AED74BC33749AD9C570B471776422C7D4505D9B0A96B3BFAC041E4C6A6990AE7F700E\
5B4A6640229112DEAFA0CD8BB0D089B0"};
451915ED0905A32B060992B468C64766FC8437A", // NIST P-384
"3EB7A829B0CD20F5BCFC0B599B6FECCF6DA4627107BDB0D4F345B43027D8B972FC3E34FB42\
32A13CA706DCB57AEC3DAE07BDC1C67BF33609", // Curve448
"4D44326F269A597A5B58BBA565DA5556ED7FD9A8A9EB76C25F46DB69D19DC8CE6AD18E404B\
15738B2086DF37E71D1EB462D692136DE56CBE93BF5FA3188EF58BC8A3A0EC6C1E151A21038A42E\
9185329B5B275903D192F8D4E1F32FE9CC78C48", // BP-P256
"A7C76B970C3B5FE8B05D2838AE04AB47697B9EAF52E764592EFDA27FE7513272734466B400\
091ADBF2D68C58E0C50066AC68F19F2E1CB879AED43A9969B91A0839C4C38A49749B661EFEDF243\
451915ED0905A32B060992B468C64766FC8437A", // NIST P-384
"3EB7A829B0CD20F5BCFC0B599B6FECCF6DA4627107BDB0D4F345B43027D8B972FC3E34FB42\
32A13CA706DCB57AEC3DAE07BDC1C67BF33609", // Curve448
"4D44326F269A597A5B58BBA565DA5556ED7FD9A8A9EB76C25F46DB69D19DC8CE6AD18E404B\
15738B2086DF37E71D1EB462D692136DE56CBE93BF5FA3188EF58BC8A3A0EC6C1E151A21038A42E\
9185329B5B275903D192F8D4E1F32FE9CC78C48"}; // BP-P384
const char *strPB2[] = {
/* SIKE (sikep434, sikep503, sikep610 and sikep751) ciphertexts - Round 2 KATs,
* https://csrc.nist.gov/CSRC/media/Projects/Post-Quantum-Cryptography/documents
* /round-2/submissions/SIKE-Round2.zip
*/
"0FDEB26DBD96E0CD272283CA5BDD1435BC9A7F9AB7FC24F83CA926DEED038AE4E47F39F988\
6E0BD7EEBEAACD12AB435CC92AA3383B2C01E6B9E02BC3BEF9C6C2719014562A96A0F3E784E3FA4\
4E5C62ED8CEA79E1108B6FECD5BF8836BF2DAE9FEB1863C4C8B3429220E2797F601FB4B8EBAFDD4\
F17355508D259CA60721D167F6E5480B5133E824F76D3240E97F31325DBB9A53E9A3EEE2E071273\
4825615A027857E2000D4D00E11988499A738452C93DA895BFA0E10294895CCF25E3C261CBE38F5\
D7E19ABE4E322094CB8DEC5BF7484902BABDE33CC69595F6013B20AABA9698C1DEA2BC6F65D5751\
9294E6FEEA3B549599D480948374D2D21B643573C276E1A5B0745301F648D7982AB46A306563996\
0182BF365819EFC0D4E61E87D2820DBC0E849E99E875B21501D1CA7588A1D458CD70C7DF793D499\
3B9B1679886CAE8013A8DD854F010A100C9933FA642DC0AEA9985786ED36B98D3",
"100692A8BD30F01BE8AC6B1AF8D93A060D3821B2587F4038D64B72426A194BEDE63CA60B75\
A5C3C15532CE307115AA9D77AC232E14D99C1E1AFEF1EB2D6321AE342F990023466E683A2568D59\
A14325C2C6C272029741D8E36976D1804059BC06B802F3A495EA50D0DBBA93FD263F4CF30BDB5F7\
83BA6A0775715B05F700C85B316F7AA1A1624973885941DBFF91316BF47AC698E11D6B2418F5533\
79D67A00F784B8643FB8A94029584391D488775EB4414A5E6E8122B0F282D900F3D05775F1DD994\
FB232ED826106203CD3433967F60FF925DF9E86CB376CAB5FD90B132E425682741F6AF078E75792\
CB4CE085D44993CFB6A4ED5AA3541640A0A67687922B92382CAC47C6AD358011A269CC7C17CE651\
CA2E2393F7DFE19D7054FEF69610A353D676B1F076549510590D406AD13F4A3292CCF206DBDAE47\
F08D448CC006449F27C1FB54E9C9E6F16ED2F3D120DD5AA2620D76690F00E31904C601310C76A84\
3A58E1AEB9C5F515FCEC482C08205FDE99A89E64485EBBD43EEFE2E24D18EEE8F20DF6E113C6667\
512E28396862C98F5C0",
"FB75E7D835313132AC0B29D8732F1F62E6DD10BBF30375B4A50C7B153431BAE6259E1C5526\
C07164E87EDC70E4F0D8331D73285661D1F639D216372D05B4583C1302932B03FF184D115D0B250\
297FF26AE81DFA0DE01A1DFB237C8008B22285A289C06BF4BC89C0BD77576932A14B1FEB9CE6D7F\
8816D710F1B043C8E58DCE1B32EF4EC8FB67E10CD23B6D4CC653DD8CD83B5F4DB0B5B741D30125C\
F842EE13EB940650E1E34E4666935B178F2351553F0822C8B354C70E47350E74A08F16D4F39F8AA\
80C3F4E0083C4BA1F31F5F1D04FD4CF835AEA688885E85509133FFE557A7892A0161AC01BBCC8A2\
7CE37E8CB9C1916A0F62BCF1E82C3F9213275B10CA272BFABCA2713CEEAECD0007C9FB6B562AFA2\
231FF7FD2C1D20D8ED28C11A840FEE931FE7A0E3BB925D88A852C2EE9BF606AD4000FA27643155A\
6FECAD9D4BABA8DE8F8D767AEC7A770D007ADB0D9F76E521DE6EF8D3567A32047688E2E8130AAF3\
EB594A366F3C534E335A3E9EDA326E60394CA10A44340CC78995742E48994002CEE1049870D14C2\
3C9FF2E5899DD7E3A1516D2F6E70B3DE1D79987379296E99EBCCAC43DA9A475CA3FE756D4649934\
BADA6DFA8C8F8BB21136172798BDA13E247B2F27874AFE13CCCA31F53D01A94B9520C3CBCDD1B1E\
B9BBBD6B83C76F64FC5D7C1DCF33A",
"66D24BC4630B2EE312F01B26EC1D3EC1F583795EC93B90FD9B5453E0BEDA2A70FB6181C9B9\
EA86A9866F1468E62CE853C6C65AA5D0E4535828B3A97E2D1D31DC4372E6A36DA7B0C4733574B91\
CCE215086C59B54F2364F61298004C8410B17658B4021CD36859C94210DE338869CACF0E2DC1141\
2FA5172E1663AAEBEF4B5EB0ED9175D6C86C5107DA92B8772342A2F44C93EFFE61F6C76AB8ABA19\
4E862543EDB707E9D2EE884995B1062FE2F60627D5C7673C7AC0D15B08C2F8510DC239463B1B32A\
D46873F6D1CB5A8579457386FD75700989BEED2CA547FE505C581B6B436AABC0F75AD6373A08CEC\
1504258A972C64EC4A1FEB86BFE32ACF3A73ECF815CBC883F39B42C6429A5875BD0BD6A94CEAD58\
7AF49AC8EFB43E1A447D2D8555CB0ADFBC9F335F1C599BC9FEAB3E4FE5F2D06D930A58C2FFEEDE0\
E2726EBD85EC890D1CB0E6870DD784AE30286F1A336D57FC41D2F2E2F89765C6A110853BB63E478\
A64D54A31A18FB4BA44FF58A3662F4D82D544BD9B0E94FC88ABC4E4D27D5F6084B5F2162B357A04\
A1A28C8938834ECC987E50C0A2CACA442850493CE16C047DF677097D3F7EA034BC3D25355042760\
03DBBEB12F1949C3D369E7EFBA09831E83D622AB2D9277F523946FBAB1DDE14015857EA47663C5C\
CF30BDF261CCBF31DBE2A560E96CE87FBA80B783350A42C837EB36B2F39A9FED1B649B8ECCE3D32\
35825F7C800834740546E0CF42C9C2C8B12495225F991B14547E5EEDB22858B26EE6E0AE13DBE3D\
50C6C1EF79C4B97DAD1B0239C4037C1AAC29EE1505E0E527EC81348900E7C216A1A1B34B8D2753A\
F2693647C412",
/* KYBER (kyber512, kyber768, kyber1024) ciphertexts from Round 3 KATs,
* https://csrc.nist.gov/CSRC/media/Projects/post-quantum-cryptography
* /documents/round-3/submissions/Kyber-Round3.zip
*/
"EDF24145E43B4F6DC6BF8332F54E02CAB02DBF3B5605DDC90A15C886AD3ED489462699E4AB\
ED44350BC3757E2696FBFB2534412E8DD201F1E4540A3970B055FE3B0BEC3A71F9E115B3F9F3910\
2065B1CCA8314DCC795E3C0E8FA98EE83CA6628457028A4D09E839E554862CF0B7BF56C5C0A829E\
8657947945FE9C22564FBAEBC1B3AF350D7955508A26D8A8EB547B8B1A2CF03CCA1AABCE6C34977\
83B6465BA0B6E7ACBA821195124AEF09E628382A1F914043BE7096E952CBC4FB4AFED1360904611\
7C011FD741EE286C83771690F0AEB50DA0D71285A179B215C6036DEB780F4D16769F72DE16FDADA\
C73BEFA5BEF8943197F44C59589DC9F4973DE1450BA1D0C3290D6B1D683F294E759C954ABE8A7DA\
5B1054FD6D21329B8E73D3756AFDA0DCB1FC8B1582D1F90CF275A102ABC6AC699DF0C5870E50A1F\
989E4E6241B60AAA2ECF9E8E33E0FFCF40FE831E8FDC2E83B52CA7AB6D93F146D29DCA53C7DA1DB\
4AC4F2DB39EA120D90FA60F4D437C6D00EF483BC94A3175CDA163FC1C2828BE4DBD6430507B584B\
B5177E171B8DDA9A4293C3200295C803A865D6D2166F66BA5401FB7A0E853168600A2948437E036\
E3BF19E12FD3F2A2B8B343F784248E8D685EB0AFDE6315338730E7A1001C27D8D2A76FA69D157BA\
1AC7AD56DA5A8C70FE4B5B8D786DC6FC0566BA8E1B8816334D32A3FB1CE7D4D5E4C332AF7B003D0\
91741A3D5C965292255DFF8ED2BBF1F9116BE50C17B8E548748AD4B2E957BBD1953482A2E1718CE\
C66CD2C81F572D552B7187885E6B8943D6431413C59EBB7E036048490BE5289E95B20A89E8B159F\
61A9A9886E147568F4C9021F362F02688A1C8C3BB0D24086880E55B6EDB43F3745D2C166DC1CB74\
3C76FE6BE523A893CC764D16435C37851252A81E2FFBA0F18971A3DEE37D4877CB928E36E523503\
7A6B2057897D518A5F0E348E3AB6D5B52DFC60757F3B41A4FEC7828F1DEEAF4587CCC8EADF647F4\
D203B2FAA05A649B582340CB4CACE57A30711BE752FACF0227D0A80C4128442DDC544BE805B9CFE\
8FE9B1237C80F96787CD9281CCF270C1AFC0670D",
"B52C56B92A4B7CE9E4CB7C5B1B163167A8A1675B2FDEF84A5B67CA15DB694C9F11BD027C30\
AE22EC921A1D911599AF0585E48D20DA70DF9F39E32EF95D4C8F44BFEFDAA5DA64F1054631D04D6\
D3CFD0A540DD7BA3886E4B5F13E878788604C95C096EAB3919F427521419A946C26CC041475D712\
4CDC01D0373E5B09C7A70603CFDB4FB3405023F2264DC3F983C4FC02A2D1B268F2208A1F6E2A620\
9BFF12F6F465F0B069C3A7F84F606D8A94064003D6EC114C8E808D3053884C1D5A142FBF20112EB\
360FDA3F0F28B172AE50F5E7D83801FB3F0064B687187074BD7FE30EDDAA334CF8FC04FA8CED899\
CEADE4B4F28B68372BAF98FF482A415B731155B75CEB976BE0EA0285BA01A27F1857A8FB377A3AE\
0C23B2AA9A079BFABFF0D5B2F1CD9B718BEA03C42F343A39B4F142D01AD8ACBB50E38853CF9A50C\
8B44C3CF671A4A9043B26DDBB24959AD6715C08521855C79A23B9C3D6471749C40725BDD5C2776D\
43AED20204BAA141EFB3304917474B7F9F7A4B08B1A93DAED98C67495359D37D67F7438BEE5E435\
85634B26C6B3810D7CDCBC0F6EB877A6087E68ACB8480D3A8CF6900447E49B417F15A53B607A0E2\
16B855970D37406870B4568722DA77A4084703816784E2F16BED18996532C5D8B7F5D214464E5F3\
F6E905867B0CE119E252A66713253544685D208E1723908A0CE97834652E08AE7BDC881A131B73C\
71E84D20D68FDEFF4F5D70CD1AF57B78E3491A9865942321800A203C05ED1FEEB5A28E584E19F65\
35E7F84E4A24F84A72DCAF5648B4A4235DD664464482F03176E888C28BFC6C1CB238CFFA35A321E\
71791D9EA8ED0878C61121BF8D2A4AB2C1A5E120BC40ABB1892D1715090A0EE48252CA297A99AA0\
E510CF26B1ADD06CA543E1C5D6BDCD3B9C585C8538045DB5C252EC3C8C3C954D9BE5907094A894E\
60EAB43538CFEE82E8FFC0791B0D0F43AC1627830A61D56DAD96C62958B0DE780B78BD47A604550\
DAB83FFF227C324049471F35248CFB849B25724FF704D5277AA352D550958BE3B237DFF473EC2AD\
BAEA48CA2658AEFCC77BBD4264AB374D70EAE5B964416CE8226A7E3255A0F8D7E2ADCA062BCD6D7\
8D60D1B32E11405BE54B66EF0FDDD567702A3BCCFEDE3C584701269ED14809F06F8968356BB9267\
FE86E514252E88BB5C30A7ECB3D0E621021EE0FBF7871B09342BF84F55C97EAF86C48189C7FF4DF\
389F077E2806E5FA73B3E9458A16C7E275F4F602275580EB7B7135FB537FA0CD95D6EA58C108CD8\
943D70C1643111F4F01CA8A8276A902666ED81B78D168B006F16AAA3D8E4CE4F4D0FB0997E41AEF\
FB5B3DAA838732F357349447F387776C793C0479DE9E99498CC356FDB0075A703F23C55D47B550E\
C89B02ADE89329086A50843456FEDC3788AC8D97233C54560467EE1D0F024B18428F0D73B30E19F\
5C63B9ABF11415BEA4D0170130BAABD33C05E6524E5FB5581B22B0433342248266D0F1053B245CC\
2462DC44D34965102482A8ED9E4E964D5683E5D45D0C8269",
"A6AF29D5F5B80BD130F518BADDD6C8F17545413D860FB3DE451979EBFA5E4E3112C7C0ADF9\
9824BB526F2C3550748ED0E134F0457A7C61F9F526F002BAADC03FC13E38131219513C3EDE06166\
1E74F603C4FCF7951C8E52C9C213B0D22D9293663D669A6B58ED8FCEFCF8249D7BB5298F5576144\
5B2B83CE7F005CB04248AEC8BDA22FD2D42AA766322014EA038CC32C55C8E4B9E28EC9119F52734\
1E4F66A035121073B85DE6706DA19E0838A9F33B719A68F039B664DC002659EABFC398679AA7009\
CE0CD01CDAFB6CD2A26FE4101672C98FF58F7C47D5BDA2906653B3A6F9651F7A121EA77EA74723F\
AE5B873F9BB7B664F0C8A93831EF9D51C7CC1EF44AC0E55A55CA76D137FE9B75F40509CEF156E5A\
D18F9FB999680008E547D55EECD5B4D1CB1D9F076CEC21501C7402509ECB77AFB2CB9A61340A8BD\
1514C6E71B4AA45E47EC37512271B911F8FB46C9082C9DF07204ABB5A50E6E3647A8AD4D8D5D7BF\
F19C8A509308BCFB895536D045CA2B97CB16A29BB7181CAD0509DDB91735028EBA8C31D74BD275E\
AA65B5340B3A43FBFE0B3061D6BAE7E75B7098CDABE91D4B31E36C9AA7A8298862AD63C8FD282E0\
3B460B3AB464CE0F27B1C3D11155ACAA011EB9E2AE3E6DDA07D6F491737CBCE9B05F9BC56BE20E8\
D326BA132C57FB235161144519CDF40560FBE279BDE411E112531F826D6AB10D4547350ADD2A9DE\
8D62C2AC82CABE6815646F4DC9742BB0C2A3F77EC7B46C6B537605FA31798CD89281221A33DFB97\
96E644305630332C2CB931408AB481A16D953F6BEAE3891D6D9AC1FAB38222D9271872D9D0CADB9\
1ABE9B4E265F75C6E5E829E146C3D8CE1E9D12E0D129801957F46B0D2DBE1F749B1D08E2345F623\
9A731342EB75B0CF1BF411749BC2CAF2810B788C6B7238B4D3DA2D6315CE9542E24404F145755A3\
0AB851E4445841BD33F716A586884888ECC6BC6498AA32919AE81D20C26973C2BD54582A0F6AD98\
ABFD2627E15690A727E69F581DD2A7127982A90E33E2D4A03FE339142C7E44C326AC46ED395A225\
D3033389917328B45316B1585A01B2C304B2944E903ABBB3EC5619441CFC8965A446DF75DEFA80C\
6E15ADBD506B7AB2DE12DDA9BC81441CFC89052E2E5808F7126C6FD3AC6AC8081258A84A09AE50F\
6CD7CC0F4AF336FD1D643E99079996268C2D32D909F22E3504F07FBB563196D4312FDDB9335D5C1\
D36E8C5EEA2278DBA23B94D193C947CC41CA993DC7DB1396340AD9C4FE687DD7B8D0C7A5120AE02\
04F2C665BD5F473D644C7FF26BFFBA7A36980830702128A7E661D677A092A36E7428A4139FB29B0\
095CC11086F447D2A9EF6C9B161F189C6299E084CB7AA00FAF787797BFB069FBC087FDE26252A16\
64F19C5A8A22EC5EE1AEB076357B7DC37E6B0F1520F958F7851BACB92C89FD114A72FEAC54652D4\
5B09E1AE7651ABD164BCD537D58FA39D3EC8ACDCDF98425005862FA59692DE162B77E6297C66233\
348408A8AB695CE2F2728DB9FBE27E958967EC5974767C5A66023074B4A71AFD264AD2890E970A1\
F31D6E3311B736F9F9488793DDC88F23458064254C82A1D9E59EAD2FCEC40B430687C4B7E289609\
26AFCACC9BD756A71088C78450E20A2E980AEDE9EBEDFE7FABD6ABFE96F934C4B02C01CA194D01B\
73C25D5997039D3FCD0F099521F70CAEE69110AC1FC5A99917AD752FC96ADFAD7186D0A7C9CFE56\
01C07514EA6448D661C57AA20242103C4276A070A489A4CB6BCA0F9ECC4379FB220215FD91F8101\
9D5B0AE619358B52468F272C178E3A74CF6775AA924FE329C3175D9E4C3E21AB9EC836EDC3ACAB2\
E3891EE8DEDA515D39AF9B8DDD0EE7B0164F805C3835F6D2BABDB30EAB4756E7EC7F829ECE01E8E\
ADFBBED12FC283B3D4C69F575E7F80417689FDFCFC7BE27EE3B8CDF57AAEBEC4A95B7E5BB585B85\
227F7C32BE30DB3E65E42E30DCF5A5FA073DBA399D942F2222ADB9B9898102AFE5432EDC7F04AE3\
4A8FEC2D81CB49A9A9B43814CE71D97F726E2B1E8F64B50E65DFB4816E12E82A3197484A4E9BBA4\
D2D69E3F19D0B75C21E2BFFE9FC0C98CF48A3AAF08D467F72687DF0178174B7897F734349B181EC\
A86A598A0C5E8C25946F24DC5572BD324A40458A788E5137F3C7A7C97FC9F12A3C463A8FE944910\
1CCE966D7C009323932998D56EF430C73BC24F5D95F737858DDC4F32C013"};
/* FIPS203 ML-KEM (ML-KEM512, ML-KEM768, ML-KEM1024) ciphertexts
* https://github.com/post-quantum-cryptography/KAT
* These tests are used by AWS-LC https://raw.githubusercontent.com/aws/
* aws-lc/refs/heads/main/crypto/fipsmodule/ml_kem/kat/mlkem512.txt
* NIST ACVP test vectors https://github.com/usnistgov/ACVP-Server
* do not have matching tests for ML-KEM.KeyGen() and ML-KEM.Enccaps()/Decaps()
*/
// ML-KEM-512
"917E59D1E182A29648A61955A154B304A842F458EBA593F3065FB7D744FBA24FA3A0D53885\
4E32844DB248D48100C389C4C4B3CA6C234F2F61A67932AEEE808DBFE98D896D1E9668820965C63\
43BBB4A4DE64B7A99FB53B5264E3199D587FFA5E0479F6B7386B23CB9C243FA6F5457FC97DBC96D\
CC039BD6C4E7E85A90B5C5232416434EA942CC71134BB9A2F4991E0595E3487FEABAC479CAB9510\
D57B86250EE7C96A67A9F2C6121F7DAA02C5CFA3B23B0C732C2B15694E1CCBAC82B787CF2118D08\
425CBBA121882217940C894CBE47AAE2541F5C6E0BD1BAAB31FD2B2ECB34B9E693F6FC0FDEEA906\
716D08818F51DF0C4694029E8C3234BE0B62471B2769D9AC4CEB947602380F3A497B2A01FF7B874\
6C1C7AE81983E016BD65C7CD1762C191857E41C2321981F6C7AA8D7AFAAA9FA0B557EC1EC1285F8\
B4D6C788AFF159EA5862E814D0825C8834B7CA45DB7C8EDA3FA6A6A7B8A40519529BF74B6A0F80C\
484917F40C107D182BCE3E344FD36D1B377A982F6BF2361B8D662875C166DCCA73240B86DF5EE0F\
A4231B356F0CDD6B3170FF89113DB0B1B9DD264335783222CBE7BE844642B0B1988D18B268DA6F7\
8CC944F43B827143C4DC5EE1F0D658B87B9C00862F263D6F5798FC82E8BE079A1108DEFDD4C7863\
C3147E9BDF0FBC84DEBA215FDFB9CA4237A8419B26FDEFF63A7F95C442BCE67966EBE6B5F9AF1FD\
2A7CBED648EA7276DB742DAC3E470F6CC741D82E77E9C0DD019B5458177551975B59633BE67B35C\
0D430B725524DEAFDEBA6D3643C5C82EBB52479669C411BB56B397F8D37B8F7FA4CED0316546CAA\
EE419C0E7F1D96A0EC614C6C9C8E03E010031765121F1EB8FD549FDE046A50443EBAB9FEA2E78A2\
9F4964455928DB1F9E7820E533C5712989B3A3637EA00A1DE3E469A800C431D4DF243C1DC7D6A89\
BA7900D52B78BCC103474F9D2C2128025C3193C4D1A09F50905AD2DE7FE8E09F047E0E72E6DAB0E\
DF7E3B08ED1316ACF857254B6C1FBF64CE582F2990CCECF9505FD7E8517998AAF583BE1AA641E9B\
54DBB91CA9D0700913967FB0349201B5D679B32D",
"1C43DE770E9CD59846B6F81F9C61CCD837978E26D32C330D509D8E29D9E7FB1A4FBA52101E\
48880D80616E533AAC591FEBD393CBB1282DE153560D4373CB882C66D307329597910ED3FF10584\
0964A640BC762E6329B9F3BA41A9EC31E04C8C9EFEC9635E0A9B456F619F10658BED36A133CED0C\
230B3CFDD8073775D759492A7E3BE0CE27725EB7C2474C568D039243FE810B31DB2FCE8EE403730\
6A5A9BBEE1BA745C2B4FC1111659F5DE919941C89C8CC661ECAAAE3E9610EAC66CD4128E3D4BB5A\
BB38837D996DB7E5C31FD09222F22F854C25FAD8AE12DED3E337C3241468EEEBECDA5DD682E6E57\
F51AD352858D04048A4703ADC135263C47B3A5D6E6C595BA1EA0602BD34353E191BFDF36D56B205\
39748AD61C66C250E07F2E3C6D60894472FE7E677C353F70A175F04C60F69DD921E9B9249BD6291\
4405829AEFA052C929CF23ABA067A7EB7FED0C15F401EF5084A97A61CED6FBF8791487231C05FC2\
3A387C77C0316538AD09BE82B10EE8F8D6A9D979F63A2EC2364F0867306E9BF6E3C0388496BEC8A\
D161515B016E91B5AB4E4EE9C48F0DE4950AA496B3BAC3ABFA86B9CBE27A92AC8A817650B2C4C53\
6EDA1D2AB58195CD423E0F4AFB5BAE7101438821B89A99206BA5FDD9D06C39DFD6F06FBA8C71942\
13D0E86F80E4E5A24977EFAACF7EBC02B028CFC9673DE6C8A0CC6AE1E577350935C912CE1D56C67\
0875C4D6BED8750A9EFBB450791C3D560CE510213274F7D4B3B88AD9967034751068580A9DEDF0A\
B3CADBB2F3BBF3719CE73E938666F2A7FE82F10F08D325D203EC0B0585B582216B7FC05A7291481\
D1222791385B6416E807E697026BE218C519C1B215842AFA0E58F988F88F3D90CF6CF42187876BD\
BD7BE0B2C261B0DD36D16DDE6ED8354BD7432B66D10BCACCB69C8944778902FC36DC70F4E6385B9\
D59AECC6445CE4AD65BCC958E886A92A1D4D175CF354B4FEE8890EA4CE21F5E831F6905AE528DB3\
991834A2452F591C3EA88D7612A599A3014FC8E10B30D48398BB8991C0FF12A7356645032530D81\
8D8AA2500B2521A73E18591EC6EF422DAEED66D2",
"5533604256120D548065769413B82FB5ABD0014E7E9F10492FF15FD45DC782B2DC4C55325F\
CC57685F134FF7E123CF028FA7B45DCC717CF2D7B274D8F2A8B7D1ACD66353A56335F482EC3D045\
04D2E052DED28112AC7410FA8E47F0D7C5EB1D6A29E948781DB3863767B7EA87A591E0D7EA4130C\
1C9FA5E8142DABF7EE8C02191CDF1B8C804D38E2B6E4445CD8FD341A63EC0001B9D8829D4C8F5E5\
3DC6E8786DF67F4AC0BB9D188F064DA50C1FAB3965510A048EB6B4AA78A851C47B106429B30F8A9\
A3B54648C8B43DCF76190BBC8C66A6A36DF7B95AE3D9784ADD8758235B291C0A1DB1BA805412E8B\
92C1416FBE64C42DB123830ED1BD97E69E522E482E83325E9E88AD9403F7E86D88D535E391AE4CD\
330EE05892A114E4439B59B30602D9D98704AA55305FA1F85B23D7C3B0F30654C8B7CB4CE02985E\
6CBE9A87CF0E999A565413099FDFAF577845A407CD6C2EA5EDEDB04BA434D80E1132467088861D6\
5199818ED4BA3A095E066339F353394877E3BF7926288CDD37AC31CDB499B5EB8CA06859BEB5C66\
0730FA793CF11347FBFED73A82E1D2B229A09593279AD0445BC11B4F164D015EC5141DADC10D322\
C9283E5A641157DFE53BDA4C3CA7364699DF0BF794D4683FB1FDECE8E318DA3FF028B63AA7D9F50\
B58785378BE79FC7E8A2B1273A8D78774853357AEC523EF7D927644B07D3D0F2876BF0B55D4592E\
33A658C461C96C8B81CCC2B1D48C3929AD994D015AE6DC4C98A75416767C7BA160BF7491B4A0AAD\
B5E43A397F63CE1CF7F916479F763350C54DC296A22314B4F484C8C22E364FCE5A6CA6E150B8102\
1B44B5F49F914927896437213D0ABCAEA28062DB2854138D0E0BEC841E6BE8E039B8A0D762E60EC\
8B6416DFE7C7C8ED9B7415908B8DD9A698950697FA5FAA5B1926A54DE986A0093DA976C89EDBF83\
711A4BAABC2C21C74F2B7FE96AAA9EB082DD66E3408CD30002CDBD573D27F66A806EB0B3144C427\
E07EF7A3967F04F0A4336F55E8E12C63A6780251844802273AC901D4F6A556502DB496D4BB46109\
BE1F90B7EFA76D3403A3BBEC6A32E8E5CF4EDBA3",
// ML-KEM 768
"CC1160B24F3AB56D7E3EEF460A2AD73D0E5B50BC5FD6E06D74C80DF6295A5E7FED8664C9B8\
19ABB90BF1B2481CA3958EDE019E5A8D215E3C3B2FC662E6A6E5F4D6CD36C30C747745FCD8F8556\
0645EC010987B87A7B42E619F388FDBB9DF0B916A01AD0640A9B761A9353DE373033EC5E2D16B59\
DB508BA33259B9791691FE35B2F08AFF381BFC9A74E380DFAC915B6165ED8C276DC7112FD36B7C2\
1710AC6A2201179642BACA216C3D4C39EA74E75A370B9ADE85A2AD8B00EADCC4AE2B3819374FDCE\
01F4AF02535194B88933ECE5A9B90C1886EFBCF40B1505D4D2603F7FED815F3B101664A90B239FE\
598E90C09069E102C500912C71F53396EA1C9035682C9ECB1627193FDEE803078E4CAB436B6CACE\
8A861AD95B5F53E6C9757EEDD7FC9EA369089E82D2D32C95209460BD880C7D856DD8BD589E131C9\
91E1148B5E4139E7F4EE32B25DA676FCB279ED94D9B28B6C4843F07A93FADC1314869D2E271D90D\
993E4F5B654157BDBF45215D691AFAECC498E9ADB3A798029C2D68665878634E02B34006BA953DB\
444203C88C4523BEDCA14358E0B129BC712EAB69D1C253C490DD4E5F751FBA1B38BA200A3E73E78\
299306855237C6F72B15598B2EAB30224A22C2C7883C6BEDE636C4D1C06ED0B6793E4609969CF8A\
442614C8C547598C26CC848BC4593E24591FC85F624548A1D01EA5BE04892C5C12EC07F70C8CA51\
C4CCD1C9F061EE1BFE07112C2577552966EB25759E77882F1B5B327964E6269E36C1D5AC9C94B01\
D891E1B3AC2660C5D99E32364AB31015986352ABB20A228C358A548D1B413FF534550F2EE0C80E0\
741B7F90DC22E8D701A44514810820A5A1D5EE62173283F91DAB585615E36A520FD7540FF7E7B9D\
6F2FB616251F1D2B6A034AF6427E66D559D7E04F1C7C22FEFA5F3F7B256D7225D5F683FE2923875\
4D66E10687290675202CD15A32A7F71B5750A95BFCC183D2C26BF31D41225C04FBC123683FA911B\
994C5B9AE5172EE9847356C67302E7C405625543B7FA82D9BE737467F7C000F97FFBB647500DE9E\
E36A266F97AE83AB58D239533C8A2FB440E649ACDF6EFC8D98BAF10A1BFA0F7681EC9708BAB9D00\
A78FFF74AA4C7099D6DA69FBEE2B7C5EA7CEB04527D01CA2CCA8416181BA450C2519A8F383881FF\
439DEDCE45BF0117CAC0A612E52AD1A3B2F2D1C9917264DD131813F3D9F6D2D574D6CE9AA0943AA\
7E84C9BDEC515B6827921366794FE6B9058769ADCB3A14593CA49A866DC7AF5BCAF2A48BB06271B\
3948CC64572AE3A9D46A1209D3E70A02D50AC3CB0AA1B820F8EA25DA127931406AAFC9B00C0FD90\
C7597321586694E35EA291A88665A2FFBAE5C9BE45938E60027C6C6DEB384F873457B5B5C710765\
1AE0273DF8A23FDFF74A2A6BD67703854FA5E115712E84D6726F27370FDE6390B362142FCD93647\
BD2D7A3927DE5F5040F60E17C39D1248F6662CF441EE4B2470CD412050CE09EC31075001286F401\
A58FE6217000D6A9C8BA753C4CE9D1D8CF8B908614DF0A81",
"DB3D4F38A49CC5C1C7766573873F3926184923F570FCDBA6D7086BEA39601FADFEBABB2F9E\
D0EBD86A6468BE03D3B05713DE50B5E5D58FFDB5500F2AF7419682BC7857870D1E624C2B48A7E0D\
30A91F141F0764014FBED12A9F72C958EB53A7ED4A1682578B4348A05C183C790FF56D66B23BD60\
1FB372C771F52045E13CA2D6DAB80A165A2159B8F990B5BBF125883DEC0A2AF4A54C3F386DE4DF6\
EE96923E9BB2551753DDC6D1F00D7EE910835082C6260974D11FBA49951DB2E27B47362EC4EBF80\
4327AD968201EDB71BDC8C32887214FB2AAA842AABBE0A4E03FDC695B19610377B9BEA9D3710166\
74E977E9E45382D236365EFEDF566659F9936D9D14CA8595DDF121AE7ACC6056DD6FE1B58DC0F0B\
23CF5366D2488C4D6361B09875242B3A39374159CF3654ABD25F8B080BAE117A5F77D15031AD8B3\
50C6922FFD426EC9F9F80A1918FE722CB7A4B537210EF8A5538A52048BADCE3CAF5C46454EEAF41\
3819D57EFBA834D7017F9343B302679A0A28F532E93FE8C5B6AEC3C42C160A3FAD20FA2ABADD29C\
2564DB59FA25A11CA502D11421F7F080A616F9656942932E11BFDCC47B1D8EFFA81D724FFABF461\
3830631737EB7E52DA78A6B026DB1C4FB80BBF2D8F9393875330B2F9C1A124436028BF2624C1E64\
797ABE2E526967DD99BC21B555A5833A31ACE7969E3ECC64C1697DEC0B074108F6B17EFA2A51792\
3B435D8446043FB1A96B2EF3B3D3952F08657997D1D9169FFD14316185EC30457E0FAF7EBA2B5A0\
2A01993EC530BB9C44C091D2E9D9BC82951E577D76DC2757F2E04E822B6A29F840887A297202E73\
89A0999F9E69255DE0A33AEB8CD0B21B7F3B5AA7BFD864CF8FF4FFE78FFF166CAF1B805464D5E4B\
60EB0277E3BA4F3F3390640F5F16E0B784CC8A67940977B2F0202D37A74472161589A7B9E7721CC\
532904A17AFF8FA86ECDC46A410BD6F9309B2CC310D7941A02A5720CD64241B5C13C78A86010805\
AC74C3B81D83348C63C410451BD2052CE764DA83CF80B2654CB1D033F259DA36039E4DF1A5C4CE3\
F8613E28CFC2B25EAE2A21B425B44D0C998977B3ADF5156BFCA1E357EC3F6B5805B2CDC4D46A4C8\
3154AEF0F50D493BAB0BBCA130E92CA21AF8BDF817F7616B55C4C24C066EBF896F39A7BF50A2415\
61E578BDD931CB07EADD193986C455F8798AB97B8D732D37C796E09C1C7ABB978BF666CED961373\
198607AC355FCF6903B4F3047A1D97C344A2D8B73DB310769CCFB4AE3DA6C4E82DEB83BF4060722\
D9E5A9AFBD3E03B4517E3B7D563F31821D5D8EF7F06F0D92A9F401EA9BEFD52CA8DB331360E603C\
14A340B806155DE690CD2D92EE6A8EE53BCEED7EEB308D375518C851C109A03EE61960D6CD7CD1F\
DEE5CC2A401039A15EE4F97A73400801A090FBF09BE42119662D06C3FF8217FCFC2C70CDE6E1C2F\
9A396A2E08A3C22AE3CE90A5C97C9F69EBC1546898A047C9DCAD128003A90B29B62F7B093CC90C9\
CD38104C1A3CE62BEA6A3646EF7E3B9FB7C4C44E78FF650C",
"535C387DD4843B57BF015986D2BC366C08FA21A6A3A615A35D82FE8FEA39968C4F6807E2EB\
EE361208EF9AE25D6E3109A0360CC7802604343337268FF3D91E0F397A0A5BA525D9C93FE897537\
A2EEE5D261B6CAA466E4FE85071B9DE1A1A8B3E9C2FF9D5ACAC679D101592FD2DFED7E667AD5E0C\
7FEFC249FCE1431E674D1128E955040DFB6E47D2435B4EF99F1ED38FF688743AC8655BDBE4656AA\
4E6CCF626020558A99BE753C8974CEDBC9CCF494DF5885B2628FAE4BDE6D26346C2B37BEFA5F1B1\
F584EBDA4B38D4248D5A3C5BF1ABFD79BF9601F27F9BCECB40DE27B50A8B3FC8F6F9D4375FD5374\
1DA0385998FBC755550DCDBB92B746EAA7197B903043545AF0792822D1DC3F12E6A3EDAE3C6B9AC\
81CB24004DBC6C9A7CA934927482E5D13E88D5DDAE92CBD59FB9B1285B3737CD9194A2F33572EAF\
E02B02BE27B99F283861FC76CDB1239AC0335FC0DBC781A493AB4565BBE01685A58B13CFF22C995\
4693D118A82948982927B880C790A6420CDC07A5398268EEFAE2BE89B2CF2F13DA535E56D4A046F\
88C6C34683770ABEDEE2D19F0C24790F83E8A60B0545A75B2BF0ED1308968623519A4C2B12D7B53\
98FACF4E4963934B96E064144B05CFAB5A2AAB4AF2CF0D226DDBCBE1C2C46A7300B2AA0C69A6D0A\
0521E1CF3EA836B30F3FA0014141ACAFEDCA5A2332FD083EF19F196C19C273EEAE4EAAB0E67DC0A\
72910C1FB1BE49F9A71B86A42EADF61ECF08B013A89D1FBA22F74DB93224ECA79D8576B6C97525A\
3523C24C99B5206722DF4658F2EB8801D9BFDD89D3D87548073620A8920065CBA6D5B0384CCB70D\
74A6EA328B0FCA71BD4737CD823188AAAA9D0D4534629420214881D1C93FF778032C5FA2A8FDF3D\
5DCE1C56F8009182FF95FF201ABDC410AFCB031290D3B5710BC45C9F9426A9C41C1A322FF723FF6\
794179186196648AD7939730189A4C60FA579709E838FE82DFCA775B7CC678BCC14DAD3B15C112A\
1CF9F432DE281A32DCE0C02370F524B74DD21EFEC5E8A6AF2245E5A3385E8C2C98400FFC1310AC5\
A7946D929EDC9FF6ACCB89997EA6AC8B1823F008C93526E9053663E5E049B2445EA2009B9C77BC2\
7D7F99069F2BD9C226118BF510FB20CC9C5E9F08D68D9B3C2E95E594FDB50954AA371CE263F74BB\
ABFF660218162056C1C60EE679D574508432D793973C9B4B3432DF9A9E8ED784B3274ED00A2E414\
5609AFBC7DBF6A98CB706EE3A6803A04F19207556E70B55BD12A4D4F3DEE0503369A449EE031486\
7940ECB4ECAD36C8F9799ADC88F9554E4359AB1D270B58B590411AF89B277AE885773A8E9F3BE1C\
239324C68EE6BC45728209FD2BA20A01FA8D214F502C34FA4C1449C13B16627C1F8E26BE1313291\
9D657B8558A584E6575FA829D2096329E60549EE31EC47CD5FB63250F533C7EC30607C5DC61DA29\
83BEAAAC9CF2408ED2B31B1A91169EB3E59CA3366C24EA09676AB0A48DD3F403FE7B21802AB8140\
8DFB20FE364F13ABCB986D09FB45CE5F5FC472ACE2C93C66",
// ML-KEM 768
"CC1160B24F3AB56D7E3EEF460A2AD73D0E5B50BC5FD6E06D74C80DF6295A5E7FED8664C9B8\
19ABB90BF1B2481CA3958EDE019E5A8D215E3C3B2FC662E6A6E5F4D6CD36C30C747745FCD8F8556\
0645EC010987B87A7B42E619F388FDBB9DF0B916A01AD0640A9B761A9353DE373033EC5E2D16B59\
DB508BA33259B9791691FE35B2F08AFF381BFC9A74E380DFAC915B6165ED8C276DC7112FD36B7C2\
1710AC6A2201179642BACA216C3D4C39EA74E75A370B9ADE85A2AD8B00EADCC4AE2B3819374FDCE\
01F4AF02535194B88933ECE5A9B90C1886EFBCF40B1505D4D2603F7FED815F3B101664A90B239FE\
598E90C09069E102C500912C71F53396EA1C9035682C9ECB1627193FDEE803078E4CAB436B6CACE\
8A861AD95B5F53E6C9757EEDD7FC9EA369089E82D2D32C95209460BD880C7D856DD8BD589E131C9\
91E1148B5E4139E7F4EE32B25DA676FCB279ED94D9B28B6C4843F07A93FADC1314869D2E271D90D\
993E4F5B654157BDBF45215D691AFAECC498E9ADB3A798029C2D68665878634E02B34006BA953DB\
444203C88C4523BEDCA14358E0B129BC712EAB69D1C253C490DD4E5F751FBA1B38BA200A3E73E78\
299306855237C6F72B15598B2EAB30224A22C2C7883C6BEDE636C4D1C06ED0B6793E4609969CF8A\
442614C8C547598C26CC848BC4593E24591FC85F624548A1D01EA5BE04892C5C12EC07F70C8CA51\
C4CCD1C9F061EE1BFE07112C2577552966EB25759E77882F1B5B327964E6269E36C1D5AC9C94B01\
D891E1B3AC2660C5D99E32364AB31015986352ABB20A228C358A548D1B413FF534550F2EE0C80E0\
741B7F90DC22E8D701A44514810820A5A1D5EE62173283F91DAB585615E36A520FD7540FF7E7B9D\
6F2FB616251F1D2B6A034AF6427E66D559D7E04F1C7C22FEFA5F3F7B256D7225D5F683FE2923875\
4D66E10687290675202CD15A32A7F71B5750A95BFCC183D2C26BF31D41225C04FBC123683FA911B\
994C5B9AE5172EE9847356C67302E7C405625543B7FA82D9BE737467F7C000F97FFBB647500DE9E\
E36A266F97AE83AB58D239533C8A2FB440E649ACDF6EFC8D98BAF10A1BFA0F7681EC9708BAB9D00\
A78FFF74AA4C7099D6DA69FBEE2B7C5EA7CEB04527D01CA2CCA8416181BA450C2519A8F383881FF\
439DEDCE45BF0117CAC0A612E52AD1A3B2F2D1C9917264DD131813F3D9F6D2D574D6CE9AA0943AA\
7E84C9BDEC515B6827921366794FE6B9058769ADCB3A14593CA49A866DC7AF5BCAF2A48BB06271B\
3948CC64572AE3A9D46A1209D3E70A02D50AC3CB0AA1B820F8EA25DA127931406AAFC9B00C0FD90\
C7597321586694E35EA291A88665A2FFBAE5C9BE45938E60027C6C6DEB384F873457B5B5C710765\
1AE0273DF8A23FDFF74A2A6BD67703854FA5E115712E84D6726F27370FDE6390B362142FCD93647\
BD2D7A3927DE5F5040F60E17C39D1248F6662CF441EE4B2470CD412050CE09EC31075001286F401\
A58FE6217000D6A9C8BA753C4CE9D1D8CF8B908614DF0A81",
"DB3D4F38A49CC5C1C7766573873F3926184923F570FCDBA6D7086BEA39601FADFEBABB2F9E\
D0EBD86A6468BE03D3B05713DE50B5E5D58FFDB5500F2AF7419682BC7857870D1E624C2B48A7E0D\
30A91F141F0764014FBED12A9F72C958EB53A7ED4A1682578B4348A05C183C790FF56D66B23BD60\
1FB372C771F52045E13CA2D6DAB80A165A2159B8F990B5BBF125883DEC0A2AF4A54C3F386DE4DF6\
EE96923E9BB2551753DDC6D1F00D7EE910835082C6260974D11FBA49951DB2E27B47362EC4EBF80\
4327AD968201EDB71BDC8C32887214FB2AAA842AABBE0A4E03FDC695B19610377B9BEA9D3710166\
74E977E9E45382D236365EFEDF566659F9936D9D14CA8595DDF121AE7ACC6056DD6FE1B58DC0F0B\
23CF5366D2488C4D6361B09875242B3A39374159CF3654ABD25F8B080BAE117A5F77D15031AD8B3\
50C6922FFD426EC9F9F80A1918FE722CB7A4B537210EF8A5538A52048BADCE3CAF5C46454EEAF41\
3819D57EFBA834D7017F9343B302679A0A28F532E93FE8C5B6AEC3C42C160A3FAD20FA2ABADD29C\
2564DB59FA25A11CA502D11421F7F080A616F9656942932E11BFDCC47B1D8EFFA81D724FFABF461\
3830631737EB7E52DA78A6B026DB1C4FB80BBF2D8F9393875330B2F9C1A124436028BF2624C1E64\
797ABE2E526967DD99BC21B555A5833A31ACE7969E3ECC64C1697DEC0B074108F6B17EFA2A51792\
3B435D8446043FB1A96B2EF3B3D3952F08657997D1D9169FFD14316185EC30457E0FAF7EBA2B5A0\
2A01993EC530BB9C44C091D2E9D9BC82951E577D76DC2757F2E04E822B6A29F840887A297202E73\
89A0999F9E69255DE0A33AEB8CD0B21B7F3B5AA7BFD864CF8FF4FFE78FFF166CAF1B805464D5E4B\
60EB0277E3BA4F3F3390640F5F16E0B784CC8A67940977B2F0202D37A74472161589A7B9E7721CC\
532904A17AFF8FA86ECDC46A410BD6F9309B2CC310D7941A02A5720CD64241B5C13C78A86010805\
AC74C3B81D83348C63C410451BD2052CE764DA83CF80B2654CB1D033F259DA36039E4DF1A5C4CE3\
F8613E28CFC2B25EAE2A21B425B44D0C998977B3ADF5156BFCA1E357EC3F6B5805B2CDC4D46A4C8\
3154AEF0F50D493BAB0BBCA130E92CA21AF8BDF817F7616B55C4C24C066EBF896F39A7BF50A2415\
61E578BDD931CB07EADD193986C455F8798AB97B8D732D37C796E09C1C7ABB978BF666CED961373\
198607AC355FCF6903B4F3047A1D97C344A2D8B73DB310769CCFB4AE3DA6C4E82DEB83BF4060722\
D9E5A9AFBD3E03B4517E3B7D563F31821D5D8EF7F06F0D92A9F401EA9BEFD52CA8DB331360E603C\
14A340B806155DE690CD2D92EE6A8EE53BCEED7EEB308D375518C851C109A03EE61960D6CD7CD1F\
DEE5CC2A401039A15EE4F97A73400801A090FBF09BE42119662D06C3FF8217FCFC2C70CDE6E1C2F\
9A396A2E08A3C22AE3CE90A5C97C9F69EBC1546898A047C9DCAD128003A90B29B62F7B093CC90C9\
CD38104C1A3CE62BEA6A3646EF7E3B9FB7C4C44E78FF650C",
"535C387DD4843B57BF015986D2BC366C08FA21A6A3A615A35D82FE8FEA39968C4F6807E2EB\
EE361208EF9AE25D6E3109A0360CC7802604343337268FF3D91E0F397A0A5BA525D9C93FE897537\
A2EEE5D261B6CAA466E4FE85071B9DE1A1A8B3E9C2FF9D5ACAC679D101592FD2DFED7E667AD5E0C\
7FEFC249FCE1431E674D1128E955040DFB6E47D2435B4EF99F1ED38FF688743AC8655BDBE4656AA\
4E6CCF626020558A99BE753C8974CEDBC9CCF494DF5885B2628FAE4BDE6D26346C2B37BEFA5F1B1\
F584EBDA4B38D4248D5A3C5BF1ABFD79BF9601F27F9BCECB40DE27B50A8B3FC8F6F9D4375FD5374\
1DA0385998FBC755550DCDBB92B746EAA7197B903043545AF0792822D1DC3F12E6A3EDAE3C6B9AC\
81CB24004DBC6C9A7CA934927482E5D13E88D5DDAE92CBD59FB9B1285B3737CD9194A2F33572EAF\
E02B02BE27B99F283861FC76CDB1239AC0335FC0DBC781A493AB4565BBE01685A58B13CFF22C995\
4693D118A82948982927B880C790A6420CDC07A5398268EEFAE2BE89B2CF2F13DA535E56D4A046F\
88C6C34683770ABEDEE2D19F0C24790F83E8A60B0545A75B2BF0ED1308968623519A4C2B12D7B53\
98FACF4E4963934B96E064144B05CFAB5A2AAB4AF2CF0D226DDBCBE1C2C46A7300B2AA0C69A6D0A\
0521E1CF3EA836B30F3FA0014141ACAFEDCA5A2332FD083EF19F196C19C273EEAE4EAAB0E67DC0A\
72910C1FB1BE49F9A71B86A42EADF61ECF08B013A89D1FBA22F74DB93224ECA79D8576B6C97525A\
3523C24C99B5206722DF4658F2EB8801D9BFDD89D3D87548073620A8920065CBA6D5B0384CCB70D\
74A6EA328B0FCA71BD4737CD823188AAAA9D0D4534629420214881D1C93FF778032C5FA2A8FDF3D\
5DCE1C56F8009182FF95FF201ABDC410AFCB031290D3B5710BC45C9F9426A9C41C1A322FF723FF6\
794179186196648AD7939730189A4C60FA579709E838FE82DFCA775B7CC678BCC14DAD3B15C112A\
1CF9F432DE281A32DCE0C02370F524B74DD21EFEC5E8A6AF2245E5A3385E8C2C98400FFC1310AC5\
A7946D929EDC9FF6ACCB89997EA6AC8B1823F008C93526E9053663E5E049B2445EA2009B9C77BC2\
7D7F99069F2BD9C226118BF510FB20CC9C5E9F08D68D9B3C2E95E594FDB50954AA371CE263F74BB\
ABFF660218162056C1C60EE679D574508432D793973C9B4B3432DF9A9E8ED784B3274ED00A2E414\
5609AFBC7DBF6A98CB706EE3A6803A04F19207556E70B55BD12A4D4F3DEE0503369A449EE031486\
7940ECB4ECAD36C8F9799ADC88F9554E4359AB1D270B58B590411AF89B277AE885773A8E9F3BE1C\
239324C68EE6BC45728209FD2BA20A01FA8D214F502C34FA4C1449C13B16627C1F8E26BE1313291\
9D657B8558A584E6575FA829D2096329E60549EE31EC47CD5FB63250F533C7EC30607C5DC61DA29\
83BEAAAC9CF2408ED2B31B1A91169EB3E59CA3366C24EA09676AB0A48DD3F403FE7B21802AB8140\
8DFB20FE364F13ABCB986D09FB45CE5F5FC472ACE2C93C66",
// ML-KEM 1024
"7F69C89494C15BEC8C947DC8B743CFD1873ADDE5AF6645F7A8AE24054A7D0931045168298D\
A2084C7422DBFBE9E521393FDCE998C5A36B7504FBA632DAAE5A61107D0960B318A588D05DC8A65\
C3FCB8270D2CEE48D35C495C8609343C88FB4D118EE42060FA6AEE25C784ACBB24E5A16445BAA79\
78CD87AD8237E97432896B592BCA55E82E4B30A654DF55B2C0C89FA0C538FB32C739E21C0BD1D72\
B3E9C06CA06794AD1F36D95CFE3881620FB224A79EC0875663C1F187AA273806AF4DDEC68FA2A1B\
62DBD9BE5C849E146C3BECC30C3F8AFA8043881567F8B0A121CD1A5E4CE82E1D081B484D1531AC7\
51F803BA5F6AC86F43987E6584AF03A077784B797B62496984812C1703B38E4D2CE5BB05E0D0D9A\
EBF69B20DEEB30D049DFBFB866FE1A7B177CA97C0A6B3FA6F4F98079A29D3D83980F5AFD4F58DB4\
E11AE73BF94F77823247D406D3F2AF9A095FC097DF5AF9C34A3C566F0BC9879DCA62EFC055E05A4\
3EF554E9246618372DBA19044DFD6C5A5FDB858F46B50652F1FA1AE6EA6D27FA07658A8A8FB9B49\
36BCE7D3A1A54B02E2E4E9C75A62A5CDE9501A075FFD7B8E553BAC31245A43610AD857A9C902C77\
FFEB71CD35C934C61D4C984D6512B54DA034217A076C3EBE7F92D42F2BC76CC1723CF77A6844F54\
7CFCFB1B6BD1F8A827037D58C787EC5BC2D5D01786881EDE0A9BFB265109B83D78203B13F4E0D3C\
89E750C8DE284074B7971F1F45595D48FA2E88CDB72AD6BBB97E5E3B1D8E0ECCC29CDEA9EE62C29\
2075843AAEA9484FEAC18E87B91716893CC8F79D8432722DC9F1581BDA0F81446E677FAD05F6DAB\
03799FB3C011512B7340DBD8E2D53DE29A29937299D856D3EFE62F11B2BCE098532029147719010\
7AE93526B3E7F5F804CB530C9B1DE20783CC39E45C7A972935C18349312E900B25C4C0F1D10D51F\
712CC756CD9A9883C63D36C00DD67ACFF79E85BAB91A8A286F1F63FC398045361B91C02DF423DD8\
165850EDE70D3DC63B315451B06B7C72926E136D6B80C182EF4E49B359D2B88C91B01EF84DE222E\
A9BD81D95EABA7A1F04465EBC29481BF2845606745F95F0DBE07BB0C2B0FC760D1C77CAB0F7A186\
0C4AA8D27133D3A8F903542F1A89B0C6B52AA07BB55ECE46A3FA9455252A28649F6663E05D80CAF\
912B9836052EE92947178C40676060157005DBF2784B0287E216F012626DD7FE14D6BBDC20B1F9F\
FCCEDB95C61E3C0926940B2404C0228AB2153DC8097ED58C2B1CDA0561464CC572F2CECB10FF31E\
C4F3C29016861698D5A0F5D1FBABB20AE33A4CD0D25B8077B251BB6169E5F3E0DF72F0F1F5EE52F\
90992772D80B34BA88AAD0DDE27948D9992D2AD1EA58EDC45615738EC7AE7A5E1D765C081C64AE8\
F3BB06F0FC8A64402837618BF209878E4412C9588983C2E377233D0C8920C87A0823E5B51355CD1\
5D4DB4C071E956D3B9221BFC87A78B3CAC2FCCF2F7FD41240796D776B0C1033B42E902EE5B16705\
D0F2548FC80F3CBFA6BBF76F3E2948AD5EAA1197D1E3B046DD2FE1652CBAC9892D641BDB5915984\
0AC3E5811D887256C1920C16DD1EF4DDEBF61FD312F88E2ABF214248FEE41C14DDE538777B5592A\
3CA309DB8425A60C91141D8642F6481364393627FE6559D096ABF4C26D8F3595A22F8D0A3F96125\
8DD3F9387855AA9A5A8829A03D53635102542FDB9C99072F80A236B794032C4C29851BF8C297D70\
7522BF9BCC1697FE238064C1B5E8E7856D3F4F717CC18BEEA8371CC298DEC7695ED4D27542C06C8\
36D771DA487A78B390EA05E4C14CD5D5187C672E77472D18FD0CDF6991C9F84A46B6331B9CC5318\
122F3031A31AAE17FFDE3CE93961C06D1EC341F4FE0DCA70BE68CFB2C76F7E8DB6EEE20E66E83E0\
4CAC137D1EB731A291B68BDC99918B3EF6FC39516F6AE4F07EF9DFE0747701AA86CF78F567C3B3A\
A993D95249AE04AA4FEBA2B9C484D05652F1C22FCA8E94045BB3B867CB245A9B333F2C7639B305E\
033E1515FF4FCE8000B1039ECF555400D51DCF374997B9995DF673CCE2D071754C06C03B7D07696\
807700191C9ED579031FD5362D32FA2043B35A90D1171E68FA562DFEE5A1E4B9CE8EE3ABA0D55D4\
B24405794A63248F2C5AFAFB4AA94B91ED3D95EA7205AFBBA6B1735AAAF5F8DAACA081FE097B58D\
76E40FFE6F906FC58D92EBB1BD9504077D18F9397A7250EDA9E6E2920267",
"069BD50C6D7A5C549DD1F2C55A99BBAD9DFB566DEC63024011C97D19BDAA9D855D217686D8\
D7A6863B90696DBA7B8F8C40C30EDD5F2D622A119F274EA4BFA4EB5073751126E68C1F2FF5A69E7\
2C9A2414DDD7BE9F70815EFCC0F0D0B745217A65B6E5F3AA9CB634037804507E80A67949E81938B\
0017A7D65602708297695DB01DD3778154A5D644F5F294493503BD6D0DBE261E92C2EB19C8BC182\
9FB14B95C2532B5CCA04B3F84E696C3F0BE6118DB84AAA9415E34BBB80F134E40DE6CD27C61B689\
0C99D7B8F3E5F80E20BA96EE31781EFD25670B62CCB3F899C626BCB735BA855096EEEE45444D2B0\
C3281C3B9CA0F69564469DF843398E3FC83EA12DA069893ABB72236B28F8547F2B73F871B329855\
1FA263F60D17A3D46C4A3D9E854D7DB3316F724E088E85F5191C721E7E1BAF95F4F68EE61668B27\
0D0873977584F0E7D109078C8135D8775816402FA8F3C9071E0488A2EC4AF00398A8BA619B4C8B4\
BA1841CAF8E9FDE44A80D2F46417EF529BA33D4CDF69A8F5F8822C7DF18802C1865DF6E094E487F\
992B19AA2C770E1F1A63677A6DC7EDB1D19B5E4F4140ACD6AA79C2826EBAD4D29CE7A75C2500C3A\
96D5726CE038C05D5A89371D4221C42474558C95CCE44479AEB2FC7972ACF43A92B86FE284A03F0\
258588397492B13F0E186FB30531D66E566371218D2D90920E997420570EC77AE1B5ADD185B05C5\
732545A86D0D2959E30C4DBEECAD5114EED7524444290E0652A502AF1BF3F305DF79304FFEB69D3\
C21780262E398B002FEFB1BC849403C17E6E418B7BEE7137E8C4BA83A05F1451DFF70DAC548C26A\
DF5F0FAA2170388DE2D2D5F4A4201ADA19EAB0007D744119D18F948DCCCC5D1A455E87B39A4C6DC\
9EBA7965423C44625AA34ECB175F288DAA832390AA98508467C7A928CBC3177E9AEF32974697085\
CA8B9F4B028D1F7E0EBD0EC3E8C40781D399D041CCBD29DCD6357FA32641F9B24EB4D3F6F331CEF\
508A29771DA72DBE343D934B177625AB3D90D9A14986E6395E4E6FEDB7567016F0F9F14776D19BB\
DFBA46C083AA5E32CA62C8961499C0FFA9FD726331E426BD78CCDEE5F3C6BDA448C0A0A84BEF5E3\
ABBBB421840D45D9D22B462DCF23CBCCDF72D45680D81DDABA76AD63F997978C9204D2F3FD49F54\
FDB34377753ABF6BD1B96AAC1CCD90A13DE231F3529646FEB01715BE5F541BBDFC30BF6941E65B9\
0CCA98BE3F71522AB8193098929BAF22E85C4DC4F04A949DE89363D8080FB1131AD0BA0645FCAF5\
83E3854C53DE82E2711EA60BF90F72F97F3BFBE2C4DC6DEF6B1DC1ADC96C68484DE80AF9B9CAA66\
686754FEC89E16DD9C8FF6D91262558F2FAD3B60A90C5FB7B57C12629F70CCE9878FBD649797796\
9825F9B3AA45AB186DA85B5F30FD46127C911E5AFD2899D0BF291B106686EAB6A4EF6842E7A7674\
152A7F42D831FD467CD71B3E5E49A89396FC3ACF6B79D6F278DE1DA94AE8C56738CF41AA2307DDC\
156F88C9B6404AD4F7AB8826B4A7B109051662C665BA63D37B29650E2376CCF7A433C9426F5A327\
2448A3AC74773ABE0D9671EC234F3CA3FE174BEA73E32DB3EB7F16EEE38E8F5AD8826B6D5ACA161\
E463BF2694862B9E6238BB72EA8AA73058053615AE7AABDE2B57A69FA5433953C908E6543AB335D\
415B600CEC73FD2B71E197D820B7B3B80F6ED068FB78156889ACCEC02CFBB729A98DE42CA955F69\
E15EC64B33C70051E7E32FA30FAF76ABFDAFE06C01E8C2AC3AC4D4498FEA8D34B914ADEAF54C679\
971E05EDA66895FAD91CC754382C734EDD5D9E85C38A313971BC2FAAF8C562C272640CCADD0F3B3\
4D318AA06A8489DBCE598DE7A686566B4B989023A7A45672B2D0A0233F2C67BD81950DBB7677457\
8644959725381A402BCDCB0843546C3FF67AA433D02C22A7EAD87FB395C501B53C25B4E493A07A0\
77A64972A558D57239834CC2FEB31F49E7272B79122BEC47C5A1C870E89187A679615167DBBC20C\
93992A20AB79833681A103BBEF5C44F7326EBD0BB4AD367C1E0BB05DAFFE6BA5688F5635A857FBC\
5B4F7A8B2AF103894EF49692BF13EE91E4ED0A453965656B245EA879B303C27CA30FA70CC50733A\
205A5EFCAB769BD5442C3882FE5D2E71E8A80CE6867C5F501ADF0E053CB8963777A89BBA8A190FD\
C2F0803510244FC62834AE40215C90EA76F4860567077DD4B45EABB256BB",
"F82392974467D1DDDD19CE29EE8ECD1A03178815A53839E00B8F8A98D34B32615F3B9DC4BB\
F7E8C8025DACF7EBB01F90519A58939A8C576A1C302750CE2F7CD5C9A26410CE8F627CDA7FADB99\
FC85A2687EA4A209959E2D562343F1AEC5031B460596A69F5F5B16EA22A0D152F6B16D62D1A1C1F\
8167850217F8454E923A1A52B93D2DD36DA5C196498B69B94C34A74336B9CF27C545C878688F84E\
7F9863D52C87ABD3CA30ACA781896EB77432EAECE2C76027E6025B25017A0B02ED6C559E06A7F27\
E19CFAF39EE184A5C5FCF7137C58093466ED28B8A8F9C99B8823156C2DC6CEF755AF978B14FD1DC\
797CF73047DEED138562F468C940A3F266AFD6ADE448D96062BE6B407BE94F137B0A42FA5B124DD\
7AAEDEF4423776DD643C78148939A4F1DB5BC9CA7C270D9287D5B531EAC41FC4BE3A127C511959A\
CEB8931823B6D4FF7A5B4AEA6406B854D8B7C54D4A953D554DE0855214017D379F97440787B1076\
F71D54C7055256BE69B761BE5BC7F1F471592CFA2D7BAB779B8CCD3D13E208353BC7E48BC06D561\
F3151DE61E4C58087844E036B0C1804919E13648152CEA8ACD62736661E7EDED2C126873B10CD3E\
6AAE80C73714359E2ABEF4D708AC856AD64389E92FC9D60400410E51007B94487F6D7C7EFC2BD26\
4E315A27CFFF6B66E9F776D6A600EEE00B9278C411A7FD3151A3A8EDC4909E4B9AA4FEB143B836D\
CEA125166B3F6E969A71610B5011E94D1D2460D2A7F0D12AF9D449F791F8B54F5D3D635F473481A\
082D7A7E299CAEC87FCF9311C6D52B178EC71DBEFC38EB665B1460CCB54AB81C6592BBDCDBC3EF8\
408253FEFEE270D12EB65EC0F357364DB94AE6DEC859BCAFC18A717C7F0CF8EC3F459773DDFB2DF\
789572BB545BED09F60DA1DA0CFB1F6219242E6E719E4422475B6466094A211FECE1653C3978927\
25F93E148EB13F02502A20B8A8FB836493132EB4DDBAD06DC2240ECF1F1F8B8C1A99ED877E19345\
81B96906C0E917EDBF520BB68AC5E8561A643C54CCB385E6C760F6BD37C2AB7E79BECE3902B4BF7\
46313A236B81A70E7613C95A8E2ED3BFF41E7130B9A0C8A63717E703EF30AB8500ABFFD0F377FAA\
5436910FA8627B3C8E0BAB4226F73E542A35A2934EACA4A6E18342FC322A150BC99A68385F6D614\
21704950E717BD26FFE0D0526F825A8AB4E0562C581B0548C3B7E640C71C981B1D224608333AE70\
07159C199149E3632E43915CF04449AFBF5A5E0929B187279BA227B59B0C75F988B6994245053E3\
66B47ED3ED8C504DC060F2165B9C657CB767AEA6C14FD5CFE942C4D9189684F812DD3096A1FC4C4\
A3BB6EFA63F3629AEBF2494EA6E544CC18FD9C2700CDC3816BC76754EEEBA41D836E10280C081A4\
278F3F00ABA9571DED482F57096950C42BFEC563A154AAE0CBE8D57A9E5FD813BD021AA6F2412C6\
414539B9E7D5B3A89C8E3D3FE0295A2E6D473552D11171B51C93F35808A1F574BEFEB37C4282EEB\
95C506EFB0F982984A68422FDFA2AD0B570B57DB2138BD6CD25407828D4133DB6B91AF5E372EE71\
FB2C4FB57F20FC83B5A567031CA23BDD0C9AFFD8946CC13B16FC94D411EA021EF50ADED2D0A9A0E\
879F8AE48ADA145F1C7729A5C677793E865D16207D2F511EF000FBABE35EA6B4C9EB94A195D1A1A\
4C42269701D3A7172A1FCBA71B2686A83FC1B5E2771A463D2B852F464217391595FEA32023E1CC5\
A0C78529A4F989D62B0CCDDC33EE961614A71BD001497037E7E37B7CE00884E387D9314B8612A45\
BDA618C4875B5B7854F2B46B1231DD3644F1406BE71620F2EC7D98763012A1620C5E31E96C8626A\
BB4C76F6A8A5655E5D224AB314075F196DD349B2387FC307916DCB532894F87337BAF4197E168B4\
30280A63E9BFFFEF57F88E15799A42F5BAC68C2355760A4D3603F72760D30116F746CA56AE59E61\
1E3A0F4DCF179927301E77E149BAF8CA839F97C2C6CF61409285DF9D5BD947F3D7B97E7DFECCC5E\
ED111D821EB1E7DC5E71B9D74E5CC0640A89058CC4244183F0700E1A882A6175FFFFEA9A10B0650\
A5653F42E09B1DF35630914D98331B897F58A3352EDF8DDAECE3D97AE2D31C0E58D929A6CDF96B3\
B744A0BE91D3CD19339A93997329426536D7FD2081B620CD6B136C3823744AC3C2B133D5851AA89\
7C5EAEF909E06DBC1173F69D1DAB5121D0C95810C500428837FB3E40F34E"};
const char *strk1[] = {
/* ECDH (NIST P-256, NIST P-384 and NIST P-521) shared secrets from
* NIST CAVP SP 800-56A ECCCDH Primitive Test Vectors.
/* ECDH (NIST P-256, NIST P-384) shared secrets from NIST CAVP SP
* 800-56A ECCCDH Primitive Test Vectors.
* http://csrc.nist.gov/groups/STM/cavp/documents/components
* /ecccdhtestvectors.zip
* ECDH (Curve25519 and Curve448) shared secrets from IETF RFC 7748
* https://datatracker.ietf.org/doc/html/rfc7748#page-4
* ECDH (BP-P256 and BP-P384) shared secrets from IETF RFC 8734
* https://www.rfc-editor.org/rfc/rfc8734.txt
*/
"057D636096CB80B67A8C038C890E887D1ADFA4195E9B3CE241C8A778C59CDA67",
"4A5D9D5BA4CE2DE1728E3BF480350F25E07E21C947D19E3376F09B3C1E161742",
"89AFC39D41D3B327814B80940B042590F96556EC91E6AE7939BCE31F3A18BF2B",
"46FC62106420FF012E54A434FBDD2D25CCC5852060561E68040DD7778997BD7B",
"4A5D9D5BA4CE2DE1728E3BF480350F25E07E21C947D19E3376F09B3C1E161742",
"89AFC39D41D3B327814B80940B042590F96556EC91E6AE7939BCE31F3A18BF2B",
"5F9D29DC5E31A163060356213669C8CE132E22F57C9A04F40BA7FCEAD493B457E5621E766C\
40A2E3D4D6A04B25E533F1",
"A23742A2C267D7425FDA94B93F93BBCC24791AC51CD8FD501A238D40812F4CBFC59AAC9520\
D758CF789C76300C69D2FF",
"005FC70477C3E63BC3954BD0DF3EA0D1F41EE21746ED95FC5E1FDF90930D5E136672D72CC7\
70742D1711C3C3A4C334A0AD9759436A4D3C5BF6E74B9578FAC148C831",
"46FC62106420FF012E54A434FBDD2D25CCC5852060561E68040DD7778997BD7B",
"3D2E640F350805EED1FF43B40A72B2ABED0A518BCEBE8F2D15B111B6773223DA3C3489121D\
B173D414B5BD5AD7153435",
"000B3920AC830ADE812C8F96805DA2236E002ACBBF13596A9AB254D44D0E91B6255EBF1229\
F366FB5A05C5884EF46032C26D42189273CA4EFA4C3DB6BD12A6853759"};
"07FFF4181AC6CC95EC1C16A94A0F74D12DA232CE40A77552281D282BB60C0B56FD2464C335\
543936521C24403085D59A449A5037514A879D",
"0BD9D3A7EA0B3D519D09D8E48D0785FB744A6B355E6304BC51C229FBBCE239BBADF6403715\
C35D4FB2A5444F575D4F42",
"5F9D29DC5E31A163060356213669C8CE132E22F57C9A04F40BA7FCEAD493B457E5621E766C\
40A2E3D4D6A04B25E533F1",
"07FFF4181AC6CC95EC1C16A94A0F74D12DA232CE40A77552281D282BB60C0B56FD2464C335\
543936521C24403085D59A449A5037514A879D",
"0BD9D3A7EA0B3D519D09D8E48D0785FB744A6B355E6304BC51C229FBBCE239BBADF6403715\
C35D4FB2A5444F575D4F42"};
const char *strk2[] = {
/* SIKE (sikep434, sikep503, sikep610, sikep751) secrets keys from Round 3 KATs,
* https://csrc.nist.gov/CSRC/media/Projects/post-quantum-cryptography
* /documents/round-3/submissions/SIKE-Round3.zip
*/
"35F7F8FF388714DEDC41F139078CEDC9",
"AF1280151C2C59B4D4150B18BA7F71590523CEA83C9BDDDA",
"0A5CFC45865775D0CC10F89EFAD9FFD33A6C8A7AB868309D",
"FEE94595E8A05C50113C044D4D8558DA101035EBBF604AA41D0AAA75B8A7F786",
/* KYBER (kyber512, kyber768, kyber1024) secret keys from Round 3 KATs,
* https://csrc.nist.gov/CSRC/media/Projects/post-quantum-cryptography
* /documents/round-3/submissions/Kyber-Round3.zip
*/
"0A6925676F24B22C286F4C81A4224CEC506C9B257D480E02E3B49F44CAA3237F",
"914CB67FE5C38E73BF74181C0AC50428DEDF7750A98058F7D536708774535B29",
"B10F7394926AD3B49C5D62D5AEB531D5757538BCC0DA9E550D438F1B61BD7419"};
/* FIPS203 ML-KEM (ML-KEM512, ML-KEM768, ML-KEM1024) shared secrets
* https://github.com/post-quantum-cryptography/KAT
* These tests are used by AWS-LC https://raw.githubusercontent.com/aws/
* aws-lc/refs/heads/main/crypto/fipsmodule/ml_kem/kat/mlkem512.txt
* NIST ACVP test vectors https://github.com/usnistgov/ACVP-Server
* do not have matching tests for ML-KEM.KeyGen() and ML-KEM.Enccaps()/Decaps()
*/
// ML-KEM 512
"2B5C52EE72946331983BA050BE0F435055C0547901E03559B356517889EA27C5",
"63DFB842BF767F89717839642A9B92FCCF82BF46A9F39BA1A3292995F3F934DC",
"135B9748C6AA6D1AE9B5420C72679FF65CAE622B8A7DF54CD7650131B5FD77F8",
// ML-KEM 768
"D71BD5A07C158C130283EF854516D290A46ADE09A63831C7B83B8FD0724C8FB0",
"E3E4F4E9D4F5C9AE03836BB9266C50B033285ACE9BC56F73817CE19679D1429A",
"73DCE41A9BFCC57EBEBA4A9F161800F3ABF1C38600F3EFA9A32EB8108819676F",
// ML-KEM 768
"D71BD5A07C158C130283EF854516D290A46ADE09A63831C7B83B8FD0724C8FB0",
"E3E4F4E9D4F5C9AE03836BB9266C50B033285ACE9BC56F73817CE19679D1429A",
"73DCE41A9BFCC57EBEBA4A9F161800F3ABF1C38600F3EFA9A32EB8108819676F",
// ML-KEM 1024
"8E012F050FCDE79D0913E1654A7D939A835A4A57943E13AC0FA2541EB3245BA9",
"F36ACE28D4F9F75AFE8FD34FF02AD6C402AF33567C5B33F91E5777CA74F8C840",
"9CC4ABFC04234C2FD68362D14C2EA03342B0D777A7BE4222594F768AA8DDCBB6"};
const char *strSA_ECC[] = {
/* ECDH (NIST P-256, NIST P-384) private keys for derandomized tests
* from NIST CAVP SP 800-56A ECCCDH Primitive Test Vectors.
* http://csrc.nist.gov/groups/STM/cavp/documents/components
* /ecccdhtestvectors.zip
* ECDH (Curve25519 and Curve448) shared secrets from IETF RFC 7748
* https://datatracker.ietf.org/doc/html/rfc7748#page-4
* ECDH (BP-P256 and BP-P384) shared secrets from IETF RFC 8734
* https://www.rfc-editor.org/rfc/rfc8734.txt
*/
"38F65D6DCE47676044D58CE5139582D568F64BB16098D179DBAB07741DD5CAF5",
"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
"81DB1EE100150FF2EA338D708271BE38300CB54241D79950F77B063039804F1D",
"7D7DC5F71EB29DDAF80D6214632EEAE03D9058AF1FB6D22ED80BADB62BC1A534",
"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
"81DB1EE100150FF2EA338D708271BE38300CB54241D79950F77B063039804F1D",
"3CC3122A68F0D95027AD38C067916BA0EB8C38894D22E1B15618B6818A661774AD463B205D\
A88CF699AB4D43C9CF98A1",
"9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BAF574A9419744\
897391006382A6F127AB1D9AC2D8C0A598726B",
"1E20F5E048A5886F1F157C74E91BDE2B98C8B52D58E5003D57053FC4B0BD65D6F15EB5D1EE\
1610DF870795143627D042",
"3CC3122A68F0D95027AD38C067916BA0EB8C38894D22E1B15618B6818A661774AD463B205D\
A88CF699AB4D43C9CF98A1",
"9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BAF574A9419744\
897391006382A6F127AB1D9AC2D8C0A598726B",
"1E20F5E048A5886F1F157C74E91BDE2B98C8B52D58E5003D57053FC4B0BD65D6F15EB5D1EE\
1610DF870795143627D042"};
const char *strPB_ECC[] = {
/* ECDH (NIST P-256, NIST P-384) peer public keys for derandomized tests
* from NIST CAVP SP 800-56A ECCCDH Primitive Test Vectors.
* http://csrc.nist.gov/groups/STM/cavp/documents/components
* /ecccdhtestvectors.zip
* ECDH (Curve25519 and Curve448) shared secrets from IETF RFC 7748
* https://datatracker.ietf.org/doc/html/rfc7748#page-4
* ECDH (BP-P256 and BP-P384) shared secrets from IETF RFC 8734
* https://www.rfc-editor.org/rfc/rfc8734.txt
*/
"04809F04289C64348C01515EB03D5CE7AC1A8CB9498F5CAA50197E58D43A86A7AEB29D84E8\
11197F25EBA8F5194092CB6FF440E26D4421011372461F579271CDA3",
"DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B4F",
"048D2D688C6CF93E1160AD04CC4429117DC2C41825E1E9FCA0ADDD34E6F1B39F7B990C5752\
0812BE512641E47034832106BC7D3E8DD0E4C7F1136D7006547CEC6A",
"04700C48F77F56584C5CC632CA65640DB91B6BACCE3A4DF6B42CE7CC838833D287DB71E509\
E3FD9B060DDB20BA5C51DCC5948D46FBF640DFE0441782CAB85FA4AC",
"DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B4F",
"048D2D688C6CF93E1160AD04CC4429117DC2C41825E1E9FCA0ADDD34E6F1B39F7B990C5752\
0812BE512641E47034832106BC7D3E8DD0E4C7F1136D7006547CEC6A",
"04A7C76B970C3B5FE8B05D2838AE04AB47697B9EAF52E764592EFDA27FE7513272734466B4\
00091ADBF2D68C58E0C50066AC68F19F2E1CB879AED43A9969B91A0839C4C38A49749B661EFEDF2\
43451915ED0905A32B060992B468C64766FC8437A",
"3EB7A829B0CD20F5BCFC0B599B6FECCF6DA4627107BDB0D4F345B43027D8B972FC3E34FB42\
32A13CA706DCB57AEC3DAE07BDC1C67BF33609",
"044D44326F269A597A5B58BBA565DA5556ED7FD9A8A9EB76C25F46DB69D19DC8CE6AD18E40\
4B15738B2086DF37E71D1EB462D692136DE56CBE93BF5FA3188EF58BC8A3A0EC6C1E151A21038A4\
2E9185329B5B275903D192F8D4E1F32FE9CC78C48",
"04A7C76B970C3B5FE8B05D2838AE04AB47697B9EAF52E764592EFDA27FE7513272734466B4\
00091ADBF2D68C58E0C50066AC68F19F2E1CB879AED43A9969B91A0839C4C38A49749B661EFEDF2\
43451915ED0905A32B060992B468C64766FC8437A",
"3EB7A829B0CD20F5BCFC0B599B6FECCF6DA4627107BDB0D4F345B43027D8B972FC3E34FB42\
32A13CA706DCB57AEC3DAE07BDC1C67BF33609",
"044D44326F269A597A5B58BBA565DA5556ED7FD9A8A9EB76C25F46DB69D19DC8CE6AD18E40\
4B15738B2086DF37E71D1EB462D692136DE56CBE93BF5FA3188EF58BC8A3A0EC6C1E151A21038A4\
2E9185329B5B275903D192F8D4E1F32FE9CC78C48"};
const char *deterministic_seed[] = {
/* FIPS203 ML-KEM (ML-KEM512, ML-KEM768, ML-KEM1024) keypair and encaps coins
* for derandomized tests https://github.com/post-quantum-cryptography/KAT
* These tests are used by AWS-LC https://raw.githubusercontent.com/aws/
* aws-lc/refs/heads/main/crypto/fipsmodule/ml_kem/kat/mlkem512.txt
* NIST ACVP test vectors https://github.com/usnistgov/ACVP-Server
* do not have matching tests for ML-KEM.KeyGen() and ML-KEM.Enccaps()/Decaps()
*/
"6DBBC4375136DF3B07F7C70E639E223E177E7FD53B161B3F4D57791794F12624F696484048\
EC21F96CF50A56D0759C448F3779752F0383D37449690694CF7A68",
"20A7B7E10F70496CC38220B944DEF699BF14D14E55CF4C90A12C1B33FC80FFFF",
"D69CFC64F84D4F33E4C54E166B7FF9283A394986A539B23987A10F39D2D9689B6DE62E3465\
A55C9C78A07D265BE8540B3E58B0801A124D07FF12B438D5202EA0",
"0121CB32ACD1871135CB34E29C1A0E26CCC001B939EAFAACC28F13F1938DBF91",
"63470357110828F25B23EDC80ED280ECD398A9F53251C3332754DE2AF0B15E901EAAE6BB91\
B27CD748C402C4111140D5A942CF3C95FF7977F88D2EF515BB26D0",
"34B961AF5D6254AF72C0D50E70DD9B4991150CCC09192AA46F1953D5C29A33EC",
"89B0C4B23019AF3498A27DA290892D981DD59FA08993BC05DA21E1D72503664CB585D4EB01\
085111A172A87688D0032E3381A9E9A35FDD6EF2F8AEB3B40EB5CE",
"0F4A070A0116194E267437545569D94AA5B2E4400645D5DE88C504B9DBB1455E",
"8D45A2AB49D8C20D4AB5680E5C9D9D0CC9CA8228484946F9AFCE5B8DF6F39D19A9F93C7B79\
1356B66AFCCEB745A548C7F6B185E4F45EC1FF1A22ACDD96E7A6D8",
"B3DBB0BF61A5230DC0AB9F1D21D5C16566FF9AD805A5E1EB7B2D6913D4CD5607",
"1FD893BD47ED681C7C11C9D00BE9EAFD9DB79AE7E934B03AA6DA99E019A28A5385DA83B471\
29711A63C2C2F6A5BCB701237B2B0B66814EEC9FCC1C560992A596",
"EF938DBDDEC94C01A845C7F1192C402F33C10F1F0176128AF219D6A0243900E6",
"89B0C4B23019AF3498A27DA290892D981DD59FA08993BC05DA21E1D72503664CB585D4EB01\
085111A172A87688D0032E3381A9E9A35FDD6EF2F8AEB3B40EB5CE",
"0F4A070A0116194E267437545569D94AA5B2E4400645D5DE88C504B9DBB1455E",
"8D45A2AB49D8C20D4AB5680E5C9D9D0CC9CA8228484946F9AFCE5B8DF6F39D19A9F93C7B79\
1356B66AFCCEB745A548C7F6B185E4F45EC1FF1A22ACDD96E7A6D8",
"B3DBB0BF61A5230DC0AB9F1D21D5C16566FF9AD805A5E1EB7B2D6913D4CD5607",
"1FD893BD47ED681C7C11C9D00BE9EAFD9DB79AE7E934B03AA6DA99E019A28A5385DA83B471\
29711A63C2C2F6A5BCB701237B2B0B66814EEC9FCC1C560992A596",
"EF938DBDDEC94C01A845C7F1192C402F33C10F1F0176128AF219D6A0243900E6",
"7838C35785AFF8B54BE30841ED41A87F420AEE847452A4561CDACCFF5B38DFC0F7ECFC9143\
EE45E44F5E98FD9CA1455340EC5DB4FB098534365EBBFBCC57D34D",
"9BF84A7839F40FAA71B35FCB695C5F41A9443BD94041A042A72C701F0D1D5DF9",
"859C3E3B13F3CBF5CB860BAD2FC6393A78390B0165800661A8F1A7436787C669DAA360ECBB\
51BCB33F5D36F92FFFE77C2DE7ED43D281DCB5FD68CFA0CE19DF2E",
"D38CEF643F9C6D2F6A4BA6A784AC1D81B32A073E531F79919912D4DB70B53075",
"23CA80A61C0201F08D6B9BFAE101FA573FAC5581EA3E54DAAAD3AD7A00BE5716AD10AD3409\
A90C4B24AB0DA526F289209ABCB1F05C86C7E4437A144C91E1C867",
"81C5839B15D7335676DBEEE048F6BCA56C4976331B5DF39A212BBC2A450F4143"};
/* Derived key_material */
const char *strkmcat[] = {
"5C366F23281D33EB85CAB026D3D9A35A",
"A808667CC0275AEB4A646E442F13E8D0",
"F79E08982B3D2B7C2D0B27F921CCF71C0E3EE98877DA225A",
"6D3F348DAB7EB85F043288112862AD16A10A70F65E73F171",
"933C64D06F5F3FB02D74530BCB093072682FAFDD64D42933",
"05C6E23AF74E3A8E1B1AA9F599C517468B86AB2068591AF8",
"4DB991EEDA686DDA8CB5F128C16267CC7516643FE5EBD8C6176405C9AB4600FA",
"270EF22EEDE80D0100872E307388027E8E12AE331AB81A27D6D166F7241B7BAF",
"1ACFDC16EEC7C8A669EC6007A4CAAB1A",
"9B8DD1A341ADFB821E32980DA418A114",
"1529723880E3E1777F73F8D89724D323572E56858D3DD732",
"7A954FCF3DE3C845B65E1D6F3CCD6186BD2F10FF83525B7A",
"6A4D002A9B310D6E73D87BF36224E2F41EDD8F75CFF448D59493D65D61C07D8B",
"203F634CFF7D7EC462281A65706E50342F025B7145E03A976640137C89F919A1"};
const char *strkmcas[] = {
"C1EF63BE6F26F6EBE2078C940AC47E59",
"5C0D6EE9B187EEE46C22EB3C3F36349A",
"CA58B87E512FCAEF2B11B1A1A8550FB4B1C1E2ACF7C364D5",
"007B8F4E6C95851C3598F59484D75A2A6FCFC931B42D74E4",
"DBC55D5F607CF981CB9774E920288ED030C3A13CADD4E594",
"944DC1D2AD91B40E3B3B6D2B19981D8571E27A0C49EE4767",
"109654A3D902FC17C83AD709D436E10FDA9A901CF6A1BDF9A02CB087171A8732",
"70D1D1AF1A736B6C648B7410F728D0AC689E2D8CD54F8B1DDA410CAD566F5CFE",
"A324764EEA9EBA338F0596D6D64DFA55",
"07930E42BCA7B1C60F530DA08A1C85F1",
"45F0EA18A6B22D94139BAF38F3C932277B48B4113A6B4E27",
"220D8F8C87FC3CD29FB1E9D24E5C6FAE4A6E42E085EB2D5F",
"EC38A129393864C9A949365155FD6A6943E30459DB80304EFEB83047B903D117",
"C2D57FA0CF6175F31581634849703060E203346823D091C182B5520F3714A487"};
const char *strkmcat_hkdf[] = {
"370705EB882B5629F955D01A5FFCA748",
"36C6BDE2BE72B35F3A51CA8EF72489E9",
"3DDF171F7569D9174DEDBD48893D328C",
"99B5DC7F166C3158043BC626DD0C4498",
"701675524E4986A391AFEFBB604AA63D",
"740CB65DD232C9D7804092733D2D7361",
"9E721A4AC9E7BB18562920725032BCA75947882E9E96D418",
"C3C3D576335BF6D31522B3A72A00765981CE67B99FCBE85D",
"833A314FE8BD6326B5B1FD51DD4CBA2ACE5C5F80C9B8D544",
"C65CD95DE189F21CD5726B2D595919461FCF3238DA50D538",
"C2B0B1967FC9C3A75B1D77F32B19EDEE39CBE94796A13536",
"B1E57722B3FB93C71EFCA4C8826C6C5C8BD491827B70A613"};
const char *strkmcas_hkdf[] = {
"6CB6C62AA34F1E4C23943663B4D48840",
"F1029D322632B91BA97FA308929E61D5",
"2025D7CC500F4C7759A7201A34A9E205",
"B4D24420223C495C2E12A50FD93C05B9",
"2D490429EE1F9F17CB05AE44691CCD09",
"4DF6A0FB71249E97C098BFF8F68C9760",
"33FB725B966F6C2D990B98265B467F6BB611ACF6AD284AA4",
"E22BDF8A0F358DC7AA80BB142FF0FD328DF575352D010950",
"A540725E733D8CCE09BC084385DDD8F03A9B4AF92AD7CF08",
"4AD2FA93C1E58F1DE44D5A6C5ED216F2E931E28A4C44662C",
"EF002D66B13574A50565FD949FA697B1E4E638D422C98080",
"ED94D90E304126A86A4BCD030236A306E2E6BA1824E8D90F"};
const char *strkmcat_hmac[] = {
"E5D337DF2D77ECE50E2DAA9E65F73D77",
"8EEC8502D551A1E46408D5673C8CB98F",
"B450CB239F23CCD820C0D4994D260234",
"3F0EC466248B91B18FA82A557C12E0E4",
"56617E0EC39843C6E41935F02A5D7FFD",
"1B57FF0AAA460D55099195DA71A9E23D",
"E26CB07AF36999973DE321AE13DB977C0EF37B18A430FC5F",
"C5AADE55D5BCE6EA33E971EF6A80F32EEECC418F490D1457",
"8C9700BE1498879F3AA886CCBDB513D91E4B73FDDF9ECEAD",
"7335508D7C14D92D98C3E8319773DC2B591245A7E926FAB0",
"A4E26D3B2EACC8E708DFA571CEEE057D2DF870A65F3C4E75",
"D0F6CBD16C466F331BD8E1716679673A5D73AADD221659ED"};
const char *strkmcas_hmac[] = {
"D696D1E075EA3B435D773C15B50F2A28",
"42B4C5C1162F0E47E004456310D3E460",
"85AB7C8DC9C922368C1F6FF48BE81ECD",
"7E12FBC4071218FA9D7B3DC21A651EA3",
"37A9900F776007E7FBE40A5486322855",
"3530F7B3284AFDEC9571E4F967C8025C",
"E157B71E03BB2D72D6709AEA3DDF8D6A86A248DCC9691B75",
"887AEC133D7D1B967A913F766AB9A61A78506652EBFEDEC9",
"B723BF81451D5A97CF6D9BB58421A94F588BCDD30EBC3710",
"9EFD0C9771DF02CF0EF9E031B3B872E4951D3CCB51B2DC02",
"1BE6EC5DF5765602EC08BC90205F5801B48FCF6797B5B340",
"5F6AC454E255DEDF959D9A92379C05837872343EE6A26E0A"};
const char * strkmcat_kmac[] = {
"E0C0450A61C8D41399EC6E977B01A9B8",
"EA6284682CBD30A9E3B0F8E12D82C3FC",
"7B8C1993F70989F49CDA53EE425104FC",
"1154D484AAB6231EE566F303C68B1EE1",
"1B697069B3382C389E30ED03D59D2BAA",
"4AD0977C7B13CC303F80AF94CEF4F794",
"2E2AAD04AAEC48A1E63CB71CD0809B371337BDA451284320",
"396256789FF63394A529C19C675ED76D153E6B26260434BF",
"A4E152F60978ED019D81925026B34AD38BF3AE585871A834",
"D031355CD04CB5641B2427F03EBDE1316317C40202BCA698",
"A0034BE961F28D59F51A2F19EF46C73E178E64B1FF40A830",
"D42F58186B93D75205FAACB4C12E2137432D810332C0E463"};
const char * strkmcas_kmac[] = {
"C259F87E2ED94BB7B14A7B1671B7331F",
"ED5DA8596698221195B037DD33E3D48D",
"BBCAAACFB0C2D5A118C6065DDAD69D9A",
"A21B0F3D7546FFD4C2A7058AC9AE4D5B",
"BF7487D94D53B67C9F73A40293481833",
"2E36C5A9C64F3B12C5E990F4863A6E5E",
"3375C5D5743B7FD5296D2B637BE9A7F99205513399DBFA70",
"140A796FF48D8676B0827DEC83270A947C08A02D1A2BE6E7",
"F8D21D6F3A76A53E9E01273BE568FE838FA091309041BEA1",
"C1A533E56B5E65CB1389CD027FA16C7F1EFA213E5431BEAF",
"E43B62DBA135BAA51C3A75B55330FE2525AF33C12EA8158B",
"B991336BDE64ACE280989E26C8FEB6E772A662B3FF0567AB"};
/*
* print_array( ) - this function is intended only for use within this
* application.
......@@ -507,7 +1327,8 @@ void print_array(const char *label, const uint8_t *array, const uint32_t alength
return;
}
/* Helper functions to loads a set of ascii hex strings to an internal
/*
* Helper functions to loads a set of ascii hex strings to an internal
* buffers. For example, if called with (array, alength, 3, "0ABC", "0132",
* "015AF4"), it wiill set array = { 0x0A, 0xBC, 0x01, 0x32, 0x01, 0x5A, 0xF4},
* and *alength = 6
......@@ -550,15 +1371,65 @@ void ascii_hex_strings_to_uint8(uint8_t *array, uint32_t *alength, const uint32_
va_end(args);
return;
}
/* Testing harness for concatenation KDF with two exchanges */
int test_hkex_concatenate()
/*
* Message Formatting function as recommended in Annex C.1
*/
void message_formatting_function(uint8_t *array, uint32_t *alength, const uint32_t scount, ...)
{
const char *pos;
uint32_t str_length, remaining_length, i, j, length;
uint8_t * ptr;
va_list args;
if ((array == NULL) || (alength == NULL)) {
exit(0);
}
ptr = array;
remaining_length = *alength;
*alength = 0;
va_start(args, scount);
for (i = 0; i < scount; i++) {
if ((pos = va_arg(args, const char *)) == NULL) {
va_end(args);
exit(0);
}
str_length = (uint32_t)strlen(pos);
if (str_length % 2) {
va_end(args);
exit(0);
}
if (remaining_length < str_length / 2) {
va_end(args);
exit(0);
}
if (i != 0){
length = htonl(str_length);
memcpy(ptr, &length, 4);
ptr += 4;
*alength = *alength + ((str_length + 8) / 2 );
}
else {
*alength = *alength + ((str_length) / 2 );
}
for (j = 0; j < ((str_length) / 2); j++) {
sscanf(pos, "%2hhx", ptr++);
pos += 2;
}
remaining_length -= (str_length ) / 2;
}
va_end(args);
return;
}
/* Testing harness for concatenation KDF (HMAC) with two exchanges */
int test_hkex_concatenate_hkdf()
{
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], key_material[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llength, klength, kmlength, k1length;
uint32_t k2length, r, j;
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, klength, kmlength, k1length, k2length, r;
const EVP_MD *md_type;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
......@@ -566,29 +1437,117 @@ int test_hkex_concatenate()
ascii_hex_strings_to_uint8(k1, &k1length, 1, strk1[r]);
k2length = sizeof(k2);
ascii_hex_strings_to_uint8(k2, &k2length, 1, strk2[r]);
for (j = 0; j < HASH_FUNCTIONS_CNT; j++) {
md_type = (*evp_hash[r][j])();
/* MA = LA1 || PA1 || PA2
md_type = (*evp_hash[r])();
printf("\nCatKDF as HKDF/HMAC with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_concatenate_hkdf[r]);
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
ascii_hex_strings_to_uint8(MA, &alength, 3, strLA1[r], strPA1[r], strPA2[r]);
/* MB = LB1 || PB1 || PB2
message_formatting_function(MA, &alength, 4, cids_concatenate_hkdf[r], strLA1[r], strPA1[r], strPA2[r]);
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
ascii_hex_strings_to_uint8(MB, &blength, 3, strLB1[r], strPB1[r], strPB2[r]);
/* label = LA || LB */
llength = sizeof(label);
ascii_hex_strings_to_uint8(label, &llength, 2, strLA1[r], strLB1[r]);
message_formatting_function(MB, &blength, 4, cids_concatenate_hkdf[r], strLB1[r], strPB1[r], strPB2[r]);
/* label = LA ^ LB */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
klength = key_length[r];
if (hkex_concat(md_type, key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)CONCAT_CONTEXT_TEST_VECTOR,
(uint32_t)strlen(CONCAT_CONTEXT_TEST_VECTOR), label, llength)) {
if (hkex_concat_hkdf(md_type, key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA = %s\n", strLA1[r]);
printf("PA1 = %s\n", strPA1[r]);
printf("PA2 = %s\n", strPA2[r]);
printf("LB = %s\n", strLB1[r]);
printf("PB1 = %s\n", strPB1[r]);
printf("PB2 = %s\n", strPB2[r]);
printf("k1 = %s\n", strk1[r]);
printf("k2 = %s\n", strk2[r]);
printf("info = \"%s\"\n", INFO_TEST_VECTOR);
print_array("label = LA ^ LB = ", label, llengthA);
printf("MA = cid || len(LA)|| LA || len(PA1) || PA1 || len(PA2) || PA2\n");
printf("MB = cid || len(LB)|| LB || len(PB1) || PB1 || len(PB2) || PB2\n\n");
print_array("key material = ", key_material, klength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcat[j + HASH_FUNCTIONS_CNT * r]);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcat_hkdf[r]);
if (memcmp(km, key_material, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for concatenation KDF (HMAC) with two exchanges */
int test_hkex_concatenate_hmac()
{
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], key_material[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, klength, kmlength, k1length;
uint32_t k2length, r;
const EVP_MD *md_type;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
k1length = sizeof(k1);
ascii_hex_strings_to_uint8(k1, &k1length, 1, strk1[r]);
k2length = sizeof(k2);
ascii_hex_strings_to_uint8(k2, &k2length, 1, strk2[r]);
md_type = (*evp_hash[r])();
printf("\nCatKDF as HMAC with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_concatenate_hmac[r]);
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 4, cids_concatenate_hmac[r], strLA1[r], strPA1[r], strPA2[r]);
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 4, cids_concatenate_hmac[r], strLB1[r], strPB1[r], strPB2[r]);
/* label = LA ^ LB */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
klength = key_length[r];
if (hkex_concat_hmac(md_type, key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA = %s\n", strLA1[r]);
printf("PA1 = %s\n", strPA1[r]);
printf("PA2 = %s\n", strPA2[r]);
......@@ -597,29 +1556,105 @@ int test_hkex_concatenate()
printf("PB2 = %s\n", strPB2[r]);
printf("k1 = %s\n", strk1[r]);
printf("k2 = %s\n", strk2[r]);
printf("context = %s\n", CONCAT_CONTEXT_TEST_VECTOR);
printf("label = LA || LB\n");
printf("MA = LA || PA1 || PA2\n");
printf("MB = LB || PB1 || PB2\n\n");
printf("info = \"%s\"\n", INFO_TEST_VECTOR);
print_array("label = LA ^ LB = ", label, llengthA);
printf("MA = cid || len(LA)|| LA || len(PA1) || PA1 || len(PA2) || PA2\n");
printf("MB = cid || len(LB)|| LB || len(PB1) || PB1 || len(PB2) || PB2\n\n");
print_array("key material = ", key_material, klength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcat_hmac[r]);
if (memcmp(km, key_material, key_length[r]) != 0) {
printf("Test vector %d failed\n", j + r * HASH_FUNCTIONS_CNT);
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for concatenation KDF (KMAC) with two exchanges */
int test_hkex_concatenate_kmac()
{
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], key_material[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, klength, kmlength, k1length;
uint32_t k2length, r;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
printf("\nCatKDF as %s, ECDH with %s, and %s \n\n", kmac[r], OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_concatenate_kmac[r]);
k1length = sizeof(k1);
ascii_hex_strings_to_uint8(k1, &k1length, 1, strk1[r]);
k2length = sizeof(k2);
ascii_hex_strings_to_uint8(k2, &k2length, 1, strk2[r]);
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 4, cids_concatenate_kmac[r], strLA1[r], strPA1[r], strPA2[r]);
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 4, cids_concatenate_kmac[r], strLB1[r], strPB1[r], strPB2[r]);
/* label = LA ^ LB */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
klength = key_length[r];
if (hkex_concat_kmac(kmac[r], key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA = %s\n", strLA1[r]);
printf("PA1 = %s\n", strPA1[r]);
printf("PA2 = %s\n", strPA2[r]);
printf("LB = %s\n", strLB1[r]);
printf("PB1 = %s\n", strPB1[r]);
printf("PB2 = %s\n", strPB2[r]);
printf("k1 = %s\n", strk1[r]);
printf("k2 = %s\n", strk2[r]);
printf("info = \"%s\"\n", INFO_TEST_VECTOR);
printf("label = LA ^ LB\n");
printf("MA = cid || len(LA)|| LA || len(PA1) || PA1 || len(PA2) || PA2\n");
printf("MB = cid || len(LB)|| LB || len(PB1) || PB1 || len(PB1) || PB2\n\n");
print_array("key material = ", key_material, klength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcat_kmac[r]);
if (memcmp(km, key_material, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for the cascade KDF using two rounds */
int test_hkex_cascade()
/* Testing harness for the cascade KDF (HKDF) using two rounds */
int test_hkex_cascade_hkdf()
{
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], round_secret[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], chain_secret1[MAX_KEY_BYTE_LEN];
uint8_t chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llength, clength, rlength, kmlength;
uint32_t k1length, k2length, r, j;
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint8_t chain_secret1[MAX_KEY_BYTE_LEN], chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, clength, rlength, kmlength;
uint32_t k1length, k2length, r;
const EVP_MD *md_type;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
......@@ -627,57 +1662,85 @@ int test_hkex_cascade()
ascii_hex_strings_to_uint8(k1, &k1length, 1, strk1[r]);
k2length = sizeof(k2);
ascii_hex_strings_to_uint8(k2, &k2length, 1, strk2[r]);
for (j = 0; j < HASH_FUNCTIONS_CNT; j++) {
md_type = (*evp_hash[r][j])();
/* MAi = LAi || PAi
md_type = (*evp_hash[r])();
printf("\nCasKDF as HKDF with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_cascade_hkdf[r]);
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
ascii_hex_strings_to_uint8(MA, &alength, 2, strLA1[r], strPA1[r]);
/* MBi = LBi || PBi
message_formatting_function(MA, &alength, 3, cids_cascade_hkdf[r], strLA1[r], strPA1[r]);
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
ascii_hex_strings_to_uint8(MB, &blength, 2, strLB1[r], strPB1[r]);
/* labeli = LAi || LBi */
llength = sizeof(label);
ascii_hex_strings_to_uint8(label, &llength, 2, strLA1[r], strLB1[r]);
message_formatting_function(MB, &blength, 3, cids_cascade_hkdf[r], strLB1[r], strPB1[r]);
/* label = LA1 ^ LB1 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
rlength = key_length[r];
clength = EVP_MD_size(md_type);
if (hkex_cascade(md_type, chain_secret1, clength, round_secret, rlength, NULL, 0, k1, k1length, MA, alength,
MB, blength, (uint8_t *)CASCADE_CONTEXT_TEST_VECTOR,
(uint32_t)strlen(CASCADE_CONTEXT_TEST_VECTOR), label, llength)) {
const uint8_t chain_secret0[] = {}; // OpenSSL3.x does not allow NULL pointer HMAC input
if (hkex_cascade_hkdf(md_type, chain_secret1, clength, round_secret, rlength, chain_secret0, 0, k1, k1length, MA, alength,
MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA1 = %s\n", strLA1[r]);
printf("PA1 = %s\n", strPA1[r]);
printf("LB1 = %s\n", strLB1[r]);
printf("PB1 = %s\n", strPB1[r]);
printf("previous_chain_secret = psk = <NULL>\n");
printf("k1 = %s\n", strk1[r]);
printf("context = %s\n", CASCADE_CONTEXT_TEST_VECTOR);
printf("label = LA1 || LB1\n");
printf("MA = LA1 || PA1\n");
printf("MB = LB1 || PB1\n\n");
printf("info1 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label1 = LA1 ^ LB1\n");
printf("MA1 = cid || len(LA1) || LA1 || len(PA1) || PA1\n");
printf("MB1 = cid || len(LB1) || LB1 || len(PB1) || PB1\n");
print_array("chain_secret1 = ", chain_secret1, clength);
print_array("key_material1 = ", round_secret, rlength);
/* MA = LA2 || PA2
/* MA = cid || len(LA2) || LA2 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
ascii_hex_strings_to_uint8(MA, &alength, 2, strLA2[r], strPA2[r]);
/* MB = LB1 || PB1
message_formatting_function(MA, &alength, 3, cids_cascade_hkdf[r], strLA2[r], strPA2[r]);
/* MB = cid || len(LB2) || LB2 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
ascii_hex_strings_to_uint8(MB, &blength, 2, strLB2[r], strPB2[r]);
/* label = LA2 || LB2 */
llength = sizeof(label);
ascii_hex_strings_to_uint8(label, &llength, 2, strLA2[r], strLB2[r]);
if (hkex_cascade(md_type, chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)CASCADE_CONTEXT_TEST_VECTOR,
(uint32_t)strlen(CASCADE_CONTEXT_TEST_VECTOR), label, llength)) {
message_formatting_function(MB, &blength, 3, cids_cascade_hkdf[r], strLB2[r], strPB2[r]);
/* label = LA2 ^ LB2 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA2[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB2[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
if (hkex_cascade_hkdf(md_type, chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA2 = %s\n", strLA2[r]);
......@@ -685,33 +1748,1815 @@ int test_hkex_cascade()
printf("LB2 = %s\n", strLB2[r]);
printf("PB2 = %s\n", strPB2[r]);
print_array("previous_chain_secret = ", chain_secret1, clength);
printf("k2 = %s\n", strk1[r]);
printf("context = %s\n", CASCADE_CONTEXT_TEST_VECTOR);
printf("label = LA2 || LB2\n");
printf("MA2 = LA2 || PA2\n");
printf("MB2 = LB2 || PB2\n\n");
printf("k2 = %s\n", strk2[r]);
printf("info2 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label2 = LA2 ^ LB2\n");
printf("MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2\n");
printf("MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2\n\n");
print_array("chain_secret2 = ", chain_secret1, clength);
print_array("chain_secret2 = ", chain_secret2, clength);
print_array("key_material2 = ", round_secret, rlength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcas[j + HASH_FUNCTIONS_CNT * r]);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcas_hkdf[r]);
if (memcmp(km, round_secret, key_length[r]) != 0) {
printf("Test vector %d failed\n", j + r * HASH_FUNCTIONS_CNT);
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
}
return SUCCESS;
}
int main(void)
/* Testing harness for the cascade KDF (HMAC) using two rounds */
int test_hkex_cascade_hmac()
{
if (test_hkex_concatenate()) {
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], round_secret[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint8_t chain_secret1[MAX_KEY_BYTE_LEN], chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, clength, rlength, kmlength;
uint32_t k1length, k2length, r;
const EVP_MD *md_type;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
k1length = sizeof(k1);
ascii_hex_strings_to_uint8(k1, &k1length, 1, strk1[r]);
k2length = sizeof(k2);
ascii_hex_strings_to_uint8(k2, &k2length, 1, strk2[r]);
md_type = (*evp_hash[r])();
printf("\nCasKDF as HMAC/HMAC with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_cascade_hmac[r]);
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 3, cids_cascade_hmac[r], strLA1[r], strPA1[r]);
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 3, cids_cascade_hmac[r], strLB1[r], strPB1[r]);
/* label = LA1 ^ LB1 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
rlength = key_length[r];
clength = EVP_MD_size(md_type);
const uint8_t chain_secret0[] = {}; // OpenSSL3.x does not allow NULL pointer HMAC input
if (hkex_cascade_hmac(md_type, chain_secret1, clength, round_secret, rlength, chain_secret0, 0, k1, k1length, MA, alength,
MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
if (test_hkex_cascade()) {
printf("LA1 = %s\n", strLA1[r]);
printf("PA1 = %s\n", strPA1[r]);
printf("LB1 = %s\n", strLB1[r]);
printf("PB1 = %s\n", strPB1[r]);
printf("previous_chain_secret = psk = <NULL>\n");
printf("k1 = %s\n", strk1[r]);
printf("info1 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label1 = LA1 ^ LB1\n");
printf("MA1 = cid || len(LA1) || LA1 || len(PA1) || PA1\n");
printf("MB1 = cid || len(LB1) || LB1 || len(PB1) || PB1\n");
print_array("chain_secret1 = ", chain_secret1, clength);
print_array("key_material1 = ", round_secret, rlength);
/* MA = cid || len(LA2) || LA2 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 3, cids_cascade_hmac[r], strLA2[r], strPA2[r]);
/* MB = cid || len(LB2) || LB2 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 3, cids_cascade_hmac[r], strLB2[r], strPB2[r]);
/* label = LA2 ^ LB2 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA2[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB2[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
if (hkex_cascade_hmac(md_type, chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA2 = %s\n", strLA2[r]);
printf("PA2 = %s\n", strPA2[r]);
printf("LB2 = %s\n", strLB2[r]);
printf("PB2 = %s\n", strPB2[r]);
print_array("previous_chain_secret = ", chain_secret1, clength);
printf("k2 = %s\n", strk2[r]);
printf("info2 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label2 = LA2 ^ LB2\n");
printf("MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2\n");
printf("MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2\n");
print_array("chain_secret2 = ", chain_secret2, clength);
print_array("key_material2 = ", round_secret, rlength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcas_hmac[r]);
if (memcmp(km, round_secret, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for the cascade KDF (KMAC) using two rounds */
int test_hkex_cascade_kmac()
{
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], round_secret[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint8_t chain_secret0[MAX_KEY_BYTE_LEN], chain_secret1[MAX_KEY_BYTE_LEN], chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, cs0length, clength, rlength, kmlength;
uint32_t k1length, k2length, r;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
printf("\nKDF as %s, ECDH with %s, and %s \n\n", kmac[r], OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_cascade_kmac[r]);
k1length = sizeof(k1);
ascii_hex_strings_to_uint8(k1, &k1length, 1, strk1[r]);
k2length = sizeof(k2);
ascii_hex_strings_to_uint8(k2, &k2length, 1, strk2[r]);
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 3, cids_cascade_kmac[r], strLA1[r], strPA1[r]);
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 3, cids_cascade_kmac[r], strLB1[r], strPB1[r]);
/* label = LA1 ^ LB1 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
rlength = key_length[r];
clength = KMAC128_OUT_BYTE_LENGTH;
if (memcmp(kmac[r], SN_kmac256, strlen(SN_kmac256)) == 0) {
clength = KMAC256_OUT_BYTE_LENGTH;
}
// OpenSSL3.x does not allow KMAC secret length < 4B
cs0length = sizeof(strPSK);
ascii_hex_strings_to_uint8(chain_secret0, &cs0length, 1, strPSK);
cs0length = clength;
if (hkex_cascade_kmac(kmac[r], chain_secret1, clength, round_secret, rlength, chain_secret0, cs0length, k1, k1length, MA, alength,
MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA1 = %s\n", strLA1[r]);
printf("PA1 = %s\n", strPA1[r]);
printf("LB1 = %s\n", strLB1[r]);
printf("PB1 = %s\n", strPB1[r]);
printf("previous_chain_secret = psk = <NULL>\n");
printf("k1 = %s\n", strk1[r]);
printf("info1 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label1 = LA1 ^ LB1\n");
printf("MA1 = cid || len(LA1) || LA1 || len(PA1) || PA1\n");
printf("MB1 = cid || len(LB1) || LB1 || len(PB1) || PB1\n\n");
print_array("chain_secret1 = ", chain_secret1, clength);
print_array("key_material1 = ", round_secret, rlength);
/* MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 3, cids_cascade_kmac[r], strLA2[r], strPA2[r]);
/* MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 3, cids_cascade_kmac[r], strLB2[r], strPB2[r]);
/* label = LA2 ^ LB2 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA2[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB2[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
if (hkex_cascade_kmac(kmac[r], chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA2 = %s\n", strLA2[r]);
printf("PA2 = %s\n", strPA2[r]);
printf("LB2 = %s\n", strLB2[r]);
printf("PB2 = %s\n", strPB2[r]);
print_array("previous_chain_secret = ", chain_secret1, clength);
printf("k2 = %s\n", strk2[r]);
printf("info2 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label2 = LA2 ^ LB2\n");
printf("MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2\n");
printf("MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2\n\n");
print_array("chain_secret2 = ", chain_secret2, clength);
print_array("key_material2 = ", round_secret, rlength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcas_kmac[r]);
if (memcmp(km, round_secret, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for concatenation KDF (HKDF) with derandomized ECC and PQ algorithms */
int test_hkex_concatenate_hkdf_derand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], key_material[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, klength, kmlength, k1length, k2length, r;
const EVP_MD *md_type;
current_seed_index = 0;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
md_type = (*evp_hash[r])();
printf("\nDerandomized CatKDF as HKDF/HMAC with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_concatenate_hkdf[r]);
if (test_qhkex_derand_ecdh(curves[r], strSA_ECC[r], strPB_ECC[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_derand_mlkem(kems_derand[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_concatenate_hkdf[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_concatenate_hkdf[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA ^ LB */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
klength = key_length[r];
if (hkex_concat_hkdf(md_type, key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC , PA_ECC_length);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("k1 = ", k1, k1length);
print_array("k2 = ", k2, k2length);
printf("info = \"%s\"\n", INFO_TEST_VECTOR);
print_array("label = LA ^ LB = ", label, llengthA);
printf("MA = cid || len(LA)|| LA || len(PA1) || PA1 || len(PA2) || PA2\n");
printf("MB = cid || len(LB)|| LB || len(PB1) || PB1 || len(PB2) || PB2\n\n");
print_array("key material = ", key_material, klength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcat_hkdf[r]);
if (memcmp(km, key_material, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for concatenation KDF (HMAC) with derandomized ECC and PQ algorithms */
int test_hkex_concatenate_hmac_derand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], key_material[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, klength, kmlength, k1length;
uint32_t k2length, r;
const EVP_MD *md_type;
current_seed_index = 0;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
md_type = (*evp_hash[r])();
printf("\nDerandomized CatKDF as HMAC with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_concatenate_hmac[r]);
if (test_qhkex_derand_ecdh(curves[r], strSA_ECC[r], strPB_ECC[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_derand_mlkem(kems_derand[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_concatenate_hmac[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MA = cid || len(LB1) || LB1 || len(PB1) || PB1 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_concatenate_hmac[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA ^ LB */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
klength = key_length[r];
if (hkex_concat_hmac(md_type, key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC , PA_ECC_length);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("k1 = ", k1, k1length);
print_array("k2 = ", k2, k2length);
printf("info = \"%s\"\n", INFO_TEST_VECTOR);
print_array("label = LA ^ LB = ", label, llengthA);
printf("MA = cid || len(LA)|| LA || len(PA1) || PA1 || len(PA2) || PA2\n");
printf("MB = cid || len(LB)|| LB || len(PB1) || PB1 || len(PB2) || PB2\n\n");
print_array("key material = ", key_material, klength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcat_hmac[r]);
if (memcmp(km, key_material, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for concatenation KDF (KMAC) with derandomized ECC and PQ algorithms */
int test_hkex_concatenate_kmac_derand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], key_material[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, klength, kmlength, k1length;
uint32_t k2length, r;
current_seed_index = 0;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
printf("\nDerandomized CatKDF as %s, ECDH with %s, and %s \n\n", kmac[r], OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_concatenate_kmac[r]);
if (test_qhkex_derand_ecdh(curves[r], strSA_ECC[r], strPB_ECC[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_derand_mlkem(kems_derand[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_concatenate_kmac[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MA = cid || len(LB1) || LB1 || len(PB1) || PB1 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_concatenate_kmac[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA ^ LB */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
klength = key_length[r];
if (hkex_concat_kmac(kmac[r], key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC , PA_ECC_length);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("k1 = ", k1, k1length);
print_array("k2 = ", k2, k2length);
printf("info = \"%s\"\n", INFO_TEST_VECTOR);
print_array("label = LA ^ LB = ", label, llengthA);
printf("MA = cid || len(LA)|| LA || len(PA1) || PA1 || len(PA2) || PA2\n");
printf("MB = cid || len(LB)|| LB || len(PB1) || PB1 || len(PB2) || PB2\n\n");
print_array("key material = ", key_material, klength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcat_kmac[r]);
if (memcmp(km, key_material, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for the cascade KDF (HKDF) with derandomized ECC and PQ algorithms */
int test_hkex_cascade_hkdf_derand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], round_secret[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint8_t chain_secret1[MAX_KEY_BYTE_LEN], chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, clength, rlength, kmlength;
uint32_t k1length, k2length, r;
const EVP_MD *md_type;
current_seed_index = 0;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
md_type = (*evp_hash[r])();
printf("\nDerandomized CasKDF as HKDF with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_cascade_hkdf[r]);
if (test_qhkex_derand_ecdh(curves[r], strSA_ECC[r], strPB_ECC[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_derand_mlkem(kems_derand[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_hkdf[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_hkdf[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
/* label = LA1 ^ LB1 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
rlength = key_length[r];
clength = EVP_MD_size(md_type);
const uint8_t chain_secret0[] = {}; // OpenSSL3.x does not allow NULL pointer HMAC input
if (hkex_cascade_hkdf(md_type, chain_secret1, clength, round_secret, rlength, chain_secret0, 0, k1, k1length, MA, alength,
MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA1 = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC, PA_ECC_length);
printf("LB1 = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
printf("previous_chain_secret = psk = <NULL>\n");
print_array("k1 = ", k1, k1length);
printf("info1 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label1 = LA1 ^ LB1\n");
printf("MA1 = cid || len(LA1) || LA1 || len(PA1) || PA1\n");
printf("MB1 = cid || len(LB1) || LB1 || len(PB1) || PB1\n");
print_array("chain_secret1 = ", chain_secret1, clength);
print_array("key_material1 = ", round_secret, rlength);
/* MA = cid || len(LA2) || LA2 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_hkdf[r], strLA2[r]);
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MB = cid || len(LB2) || LB2 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_hkdf[r], strLB2[r]);
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA2 ^ LB2 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA2[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB2[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
if (hkex_cascade_hkdf(md_type, chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA2 = %s\n", strLA2[r]);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB2 = %s\n", strLB2[r]);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("previous_chain_secret = ", chain_secret1, clength);
print_array("k2 = ", k2, k2length);
printf("info2 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label2 = LA2 ^ LB2\n");
printf("MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2\n");
printf("MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2\n\n");
print_array("chain_secret2 = ", chain_secret2, clength);
print_array("key_material2 = ", round_secret, rlength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcas_hkdf[r]);
if (memcmp(km, round_secret, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for the cascade KDF (HMAC) with derandomized ECC and PQ algorithms */
int test_hkex_cascade_hmac_derand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], round_secret[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint8_t chain_secret1[MAX_KEY_BYTE_LEN], chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, clength, rlength, kmlength;
uint32_t k1length, k2length, r;
const EVP_MD *md_type;
current_seed_index = 0;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
md_type = (*evp_hash[r])();
printf("\nDerandomized CasKDF as HMAC/HMAC with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_cascade_hmac[r]);
if (test_qhkex_derand_ecdh(curves[r], strSA_ECC[r], strPB_ECC[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_derand_mlkem(kems_derand[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_hmac[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_hmac[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
/* label = LA1 ^ LB1 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
rlength = key_length[r];
clength = EVP_MD_size(md_type);
const uint8_t chain_secret0[] = {}; // OpenSSL3.x does not allow NULL pointer HMAC input
if (hkex_cascade_hmac(md_type, chain_secret1, clength, round_secret, rlength, chain_secret0, 0, k1, k1length, MA, alength,
MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA1 = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC, PA_ECC_length);
printf("LB1 = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
printf("previous_chain_secret = psk = <NULL>\n");
print_array("k1 = ", k1, k1length);
printf("info1 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label1 = LA1 ^ LB1\n");
printf("MA1 = cid || len(LA1) || LA1 || len(PA1) || PA1\n");
printf("MB1 = cid || len(LB1) || LB1 || len(PB1) || PB1\n");
print_array("chain_secret1 = ", chain_secret1, clength);
print_array("key_material1 = ", round_secret, rlength);
/* MA = cid || len(LA2) || LA2 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_hmac[r], strLA2[r]);
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MB = cid || len(LB2) || LB2 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_hmac[r], strLB2[r]);
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA2 ^ LB2 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA2[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB2[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
if (hkex_cascade_hmac(md_type, chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA2 = %s\n", strLA2[r]);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB2 = %s\n", strLB2[r]);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("previous_chain_secret = ", chain_secret1, clength);
print_array("k2 = ", k2, k2length);
printf("info2 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label2 = LA2 ^ LB2\n");
printf("MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2\n");
printf("MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2\n");
print_array("chain_secret2 = ", chain_secret2, clength);
print_array("key_material2 = ", round_secret, rlength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcas_hmac[r]);
if (memcmp(km, round_secret, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for the cascade KDF (KMAC) with derandomized ECC and PQ algorithms */
int test_hkex_cascade_kmac_derand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t km[MAX_KEY_BYTE_LEN], round_secret[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint8_t chain_secret0[MAX_KEY_BYTE_LEN], chain_secret1[MAX_KEY_BYTE_LEN], chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, cs0length, clength, rlength, kmlength;
uint32_t k1length, k2length, r;
current_seed_index = 0;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
printf("\nDerandomized KDF as %s, ECDH with %s, and %s \n\n", kmac[r], OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_cascade_kmac[r]);
if (test_qhkex_derand_ecdh(curves[r], strSA_ECC[r], strPB_ECC[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_derand_mlkem(kems_derand[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_kmac[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_kmac[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
/* label = LA1 ^ LB1 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
rlength = key_length[r];
clength = KMAC128_OUT_BYTE_LENGTH;
if (memcmp(kmac[r], SN_kmac256, strlen(SN_kmac256)) == 0) {
clength = KMAC256_OUT_BYTE_LENGTH;
}
// OpenSSL3.x does not allow KMAC secret length < 4B
cs0length = sizeof(strPSK);
ascii_hex_strings_to_uint8(chain_secret0, &cs0length, 1, strPSK);
cs0length = clength;
if (hkex_cascade_kmac(kmac[r], chain_secret1, clength, round_secret, rlength, chain_secret0, cs0length, k1, k1length, MA, alength,
MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA1 = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC, PA_ECC_length);
printf("LB1 = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
printf("previous_chain_secret = psk = <NULL>\n");
print_array("k1 = ", k1, k1length);
printf("info1 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label1 = LA1 ^ LB1\n");
printf("MA1 = cid || len(LA1) || LA1 || len(PA1) || PA1\n");
printf("MB1 = cid || len(LB1) || LB1 || len(PB1) || PB1\n");
print_array("chain_secret1 = ", chain_secret1, clength);
print_array("key_material1 = ", round_secret, rlength);
/* MA = cid || len(LA2) || LA2 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_kmac[r], strLA2[r]);
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MB = cid || len(LB2) || LB2 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_kmac[r], strLB2[r]);
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA2 ^ LB2 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA2[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB2[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
if (hkex_cascade_kmac(kmac[r], chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA2 = %s\n", strLA2[r]);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB2 = %s\n", strLB2[r]);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("previous_chain_secret = ", chain_secret1, clength);
print_array("k2 = ", k2, k2length);
printf("info2 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label2 = LA2 ^ LB2\n");
printf("MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2\n");
printf("MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2\n");
print_array("chain_secret2 = ", chain_secret2, clength);
print_array("key_material2 = ", round_secret, rlength);
kmlength = sizeof(km);
ascii_hex_strings_to_uint8(km, &kmlength, 1, strkmcas_kmac[r]);
if (memcmp(km, round_secret, key_length[r]) != 0) {
printf("Test vector %u failed\n", r);
return FAILURE;
}
}
return SUCCESS;
}
/* Testing harness for concatenation KDF (HKDF) with randomized ECC and PQ algorithms */
int test_hkex_concatenate_hkdf_rand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t key_material[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, klength, k1length, k2length, r;
const EVP_MD *md_type;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
md_type = (*evp_hash[r])();
printf("\nRandomized CatKDF as HKDF/HMAC with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_concatenate_hkdf[r]);
if (test_qhkex_rand_ecdh(curves[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_rand_mlkem(kems[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_concatenate_hkdf[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_concatenate_hkdf[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA ^ LB */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
klength = key_length[r];
if (hkex_concat_hkdf(md_type, key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC , PA_ECC_length);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("k1 = ", k1, k1length);
print_array("k2 = ", k2, k2length);
printf("info = \"%s\"\n", INFO_TEST_VECTOR);
print_array("label = LA ^ LB = ", label, llengthA);
printf("MA = cid || len(LA)|| LA || len(PA1) || PA1 || len(PA2) || PA2\n");
printf("MB = cid || len(LB)|| LB || len(PB1) || PB1 || len(PB2) || PB2\n\n");
print_array("key material = ", key_material, klength);
}
return SUCCESS;
}
/* Testing harness for concatenation KDF (HMAC) with randomized ECC and PQ algorithms */
int test_hkex_concatenate_hmac_rand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t key_material[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, klength, k1length;
uint32_t k2length, r;
const EVP_MD *md_type;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
md_type = (*evp_hash[r])();
printf("\nRandomized CatKDF as HMAC with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_concatenate_hmac[r]);
if (test_qhkex_rand_ecdh(curves[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_rand_mlkem(kems[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_concatenate_hmac[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MA = cid || len(LB1) || LB1 || len(PB1) || PB1 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_concatenate_hmac[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA ^ LB */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
klength = key_length[r];
if (hkex_concat_hmac(md_type, key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC , PA_ECC_length);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("k1 = ", k1, k1length);
print_array("k2 = ", k2, k2length);
printf("info = \"%s\"\n", INFO_TEST_VECTOR);
print_array("label = LA ^ LB = ", label, llengthA);
printf("MA = cid || len(LA)|| LA || len(PA1) || PA1 || len(PA2) || PA2\n");
printf("MB = cid || len(LB)|| LB || len(PB1) || PB1 || len(PB2) || PB2\n\n");
print_array("key material = ", key_material, klength);
}
return SUCCESS;
}
/* Testing harness for concatenation KDF (KMAC) with randomized ECC and PQ algorithms */
int test_hkex_concatenate_kmac_rand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t key_material[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, klength, k1length;
uint32_t k2length, r;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
printf("\nRandomized CatKDF as %s, ECDH with %s, and %s \n\n", kmac[r], OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_concatenate_kmac[r]);
if (test_qhkex_rand_ecdh(curves[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_rand_mlkem(kems[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_concatenate_kmac[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MA = cid || len(LB1) || LB1 || len(PB1) || PB1 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_concatenate_kmac[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA ^ LB */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
klength = key_length[r];
if (hkex_concat_kmac(kmac[r], key_material, klength, NULL, 0, k1, k1length, k2, k2length, MA, alength, MB,
blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC , PA_ECC_length);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("k1 = ", k1, k1length);
print_array("k2 = ", k2, k2length);
printf("info = \"%s\"\n", INFO_TEST_VECTOR);
print_array("label = LA ^ LB = ", label, llengthA);
printf("MA = cid || len(LA)|| LA || len(PA1) || PA1 || len(PA2) || PA2\n");
printf("MB = cid || len(LB)|| LB || len(PB1) || PB1 || len(PB2) || PB2\n\n");
print_array("key material = ", key_material, klength);
}
return SUCCESS;
}
/* Testing harness for the cascade KDF (HKDF) with randomized ECC and PQ algorithms */
int test_hkex_cascade_hkdf_rand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t round_secret[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint8_t chain_secret1[MAX_KEY_BYTE_LEN], chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, clength, rlength;
uint32_t k1length, k2length, r;
const EVP_MD *md_type;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
md_type = (*evp_hash[r])();
printf("\nRandomized CasKDF as HKDF with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_cascade_hkdf[r]);
if (test_qhkex_rand_ecdh(curves[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_rand_mlkem(kems[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_hkdf[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_hkdf[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
/* label = LA1 ^ LB1 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
rlength = key_length[r];
clength = EVP_MD_size(md_type);
const uint8_t chain_secret0[] = {}; // OpenSSL3.x does not allow NULL pointer HMAC input
if (hkex_cascade_hkdf(md_type, chain_secret1, clength, round_secret, rlength, chain_secret0, 0, k1, k1length, MA, alength,
MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA1 = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC, PA_ECC_length);
printf("LB1 = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
printf("previous_chain_secret = psk = <NULL>\n");
print_array("k1 = ", k1, k1length);
printf("info1 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label1 = LA1 ^ LB1\n");
printf("MA1 = cid || len(LA1) || LA1 || len(PA1) || PA1\n");
printf("MB1 = cid || len(LB1) || LB1 || len(PB1) || PB1\n");
print_array("chain_secret1 = ", chain_secret1, clength);
print_array("key_material1 = ", round_secret, rlength);
/* MA = cid || len(LA2) || LA2 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_hkdf[r], strLA2[r]);
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MB = cid || len(LB2) || LB2 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_hkdf[r], strLB2[r]);
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA2 ^ LB2 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA2[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB2[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
if (hkex_cascade_hkdf(md_type, chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA2 = %s\n", strLA2[r]);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB2 = %s\n", strLB2[r]);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("previous_chain_secret = ", chain_secret1, clength);
print_array("k2 = ", k2, k2length);
printf("info2 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label2 = LA2 ^ LB2\n");
printf("MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2\n");
printf("MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2\n\n");
print_array("chain_secret2 = ", chain_secret2, clength);
print_array("key_material2 = ", round_secret, rlength);
}
return SUCCESS;
}
/* Testing harness for the cascade KDF (HMAC) with randomized ECC and PQ algorithms */
int test_hkex_cascade_hmac_rand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t round_secret[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint8_t chain_secret1[MAX_KEY_BYTE_LEN], chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, clength, rlength;
uint32_t k1length, k2length, r;
const EVP_MD *md_type;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
md_type = (*evp_hash[r])();
printf("\nRandomized CasKDF as HMAC/HMAC with %s, ECDH with %s, and %s \n\n", EVP_MD_name(md_type), OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_cascade_hmac[r]);
if (test_qhkex_rand_ecdh(curves[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_rand_mlkem(kems[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_hmac[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_hmac[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
/* label = LA1 ^ LB1 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
rlength = key_length[r];
clength = EVP_MD_size(md_type);
const uint8_t chain_secret0[] = {}; // OpenSSL3.x does not allow NULL pointer HMAC input
if (hkex_cascade_hmac(md_type, chain_secret1, clength, round_secret, rlength, chain_secret0, 0, k1, k1length, MA, alength,
MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA1 = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC, PA_ECC_length);
printf("LB1 = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
printf("previous_chain_secret = psk = <NULL>\n");
print_array("k1 = ", k1, k1length);
printf("info1 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label1 = LA1 ^ LB1\n");
printf("MA1 = cid || len(LA1) || LA1 || len(PA1) || PA1\n");
printf("MB1 = cid || len(LB1) || LB1 || len(PB1) || PB1\n");
print_array("chain_secret1 = ", chain_secret1, clength);
print_array("key_material1 = ", round_secret, rlength);
/* MA = cid || len(LA2) || LA2 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_hmac[r], strLA2[r]);
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MB = cid || len(LB2) || LB2 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_hmac[r], strLB2[r]);
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA2 ^ LB2 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA2[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB2[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
if (hkex_cascade_hmac(md_type, chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA2 = %s\n", strLA2[r]);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB2 = %s\n", strLB2[r]);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("previous_chain_secret = ", chain_secret1, clength);
print_array("k2 = ", k2, k2length);
printf("info2 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label2 = LA2 ^ LB2\n");
printf("MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2\n");
printf("MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2\n");
print_array("chain_secret2 = ", chain_secret2, clength);
print_array("key_material2 = ", round_secret, rlength);
}
return SUCCESS;
}
/* Testing harness for the cascade KDF (KMAC) with randomized ECC and PQ algorithms */
int test_hkex_cascade_kmac_rand()
{
uint8_t PA_ECC[MAX_KEY_BYTE_LEN], PB_ECC[MAX_KEY_BYTE_LEN];
uint8_t PA_PQ[MAX_MSG_BYTE_LEN], CTB_PQ[MAX_MSG_BYTE_LEN];
size_t length;
size_t PA_ECC_length, PB_ECC_length, PA_PQ_length, CTB_PQ_length;
uint8_t k1[MAX_KEY_BYTE_LEN], k2[MAX_KEY_BYTE_LEN];
uint8_t round_secret[MAX_KEY_BYTE_LEN];
uint8_t MA[MAX_MSG_BYTE_LEN], MB[MAX_MSG_BYTE_LEN];
uint8_t label[MAX_LABEL_BYTE_LEN], labelA[MAX_LABEL_BYTE_LEN], labelB[MAX_LABEL_BYTE_LEN];
uint8_t chain_secret0[MAX_KEY_BYTE_LEN], chain_secret1[MAX_KEY_BYTE_LEN], chain_secret2[MAX_KEY_BYTE_LEN];
uint32_t alength, blength, llengthA, llengthB, cs0length, clength, rlength;
uint32_t k1length, k2length, r;
for (r = 0; r < TEST_VECTOR_CNT; r++) {
printf("\nRandomized KDF as %s, ECDH with %s, and %s \n\n", kmac[r], OBJ_nid2sn(curves[r]), kems[r]);
printf("CID %s \n", cids_cascade_kmac[r]);
if (test_qhkex_rand_ecdh(curves[r], PA_ECC, &PA_ECC_length, PB_ECC, &PB_ECC_length, k1, &k1length)) {
return FAILURE;
}
if (test_qhkex_rand_mlkem(kems[r], PA_PQ, &PA_PQ_length, CTB_PQ, &CTB_PQ_length, k2, &k2length)) {
return FAILURE;
}
/* MA = cid || len(LA1) || LA1 || len(PA1) || PA1
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_kmac[r], strLA1[r]);
length = htonl(PA_ECC_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_ECC, PA_ECC_length);
alength += PA_ECC_length;
/* MB = cid || len(LB1) || LB1 || len(PB1) || PB1
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_kmac[r], strLB1[r]);
length = htonl(PB_ECC_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, PB_ECC, PB_ECC_length);
blength += PB_ECC_length;
/* label = LA1 ^ LB1 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA1[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB1[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
rlength = key_length[r];
clength = KMAC128_OUT_BYTE_LENGTH;
if (memcmp(kmac[r], SN_kmac256, strlen(SN_kmac256)) == 0) {
clength = KMAC256_OUT_BYTE_LENGTH;
}
// OpenSSL3.x does not allow KMAC secret length < 4B
cs0length = sizeof(strPSK);
ascii_hex_strings_to_uint8(chain_secret0, &cs0length, 1, strPSK);
cs0length = clength;
if (hkex_cascade_kmac(kmac[r], chain_secret1, clength, round_secret, rlength, chain_secret0, cs0length, k1, k1length, MA, alength,
MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA1 = %s\n", strLA1[r]);
print_array("PA1 = ", PA_ECC, PA_ECC_length);
printf("LB1 = %s\n", strLB1[r]);
print_array("PB1 = ", PB_ECC, PB_ECC_length);
printf("previous_chain_secret = psk = <NULL>\n");
print_array("k1 = ", k1, k1length);
printf("info1 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label1 = LA1 ^ LB1\n");
printf("MA1 = cid || len(LA1) || LA1 || len(PA1) || PA1\n");
printf("MB1 = cid || len(LB1) || LB1 || len(PB1) || PB1\n");
print_array("chain_secret1 = ", chain_secret1, clength);
print_array("key_material1 = ", round_secret, rlength);
/* MA = cid || len(LA2) || LA2 || len(PA2) || PA2
NOTE: for test vector purposes ONLY not a suggested message format
*/
alength = sizeof(MA);
message_formatting_function(MA, &alength, 2, cids_cascade_kmac[r], strLA2[r]);
length = htonl(PA_PQ_length*2);
my_memcpy(MA + alength, &length, sizeof(uint32_t));
alength += sizeof(uint32_t);
my_memcpy(MA + alength, PA_PQ, PA_PQ_length);
alength += PA_PQ_length;
/* MB = cid || len(LB2) || LB2 || len(PB2) || PB2
NOTE: for test vector purposes ONLY not a suggested message format
*/
blength = sizeof(MB);
message_formatting_function(MB, &blength, 2, cids_cascade_kmac[r], strLB2[r]);
length = htonl(CTB_PQ_length*2);
my_memcpy(MB + blength, &length, sizeof(uint32_t));
blength += sizeof(uint32_t);
my_memcpy(MB + blength, CTB_PQ, CTB_PQ_length);
blength += CTB_PQ_length;
/* label = LA2 ^ LB2 */
llengthA = sizeof(labelA);
ascii_hex_strings_to_uint8(labelA, &llengthA, 1, strLA2[r]);
llengthB = sizeof(labelB);
ascii_hex_strings_to_uint8(labelB, &llengthB, 1, strLB2[r]);
if (llengthA != llengthB) {
return FAILURE;
}
for (int i = 0; i < llengthA; i++) {
label[i] = labelA[i] ^ labelB[i];
}
if (hkex_cascade_kmac(kmac[r], chain_secret2, clength, round_secret, rlength, chain_secret1, clength, k2,
k2length, MA, alength, MB, blength, (uint8_t *)INFO_TEST_VECTOR,
(uint32_t)strlen(INFO_TEST_VECTOR), label, llengthA)) {
return FAILURE;
}
printf("LA2 = %s\n", strLA2[r]);
print_array("PA2 = ", PA_PQ, PA_PQ_length);
printf("LB2 = %s\n", strLB2[r]);
print_array("PB2 = ", CTB_PQ, CTB_PQ_length);
print_array("previous_chain_secret = ", chain_secret1, clength);
print_array("k2 = ", k2, k2length);
printf("info2 = \"%s\"\n", INFO_TEST_VECTOR);
printf("label2 = LA2 ^ LB2\n");
printf("MA2 = cid || len(LA2) || LA2 || len(PA2) || PA2\n");
printf("MB2 = cid || len(LB2) || LB2 || len(PB2) || PB2\n");
print_array("chain_secret2 = ", chain_secret2, clength);
print_array("key_material2 = ", round_secret, rlength);
}
return SUCCESS;
}
int main(void)
{
if (test_hkex_concatenate_hkdf()) {
return FAILURE;
}
if (test_hkex_concatenate_hmac()) {
return FAILURE;
}
if (test_hkex_concatenate_kmac()) {
return FAILURE;
}
if (test_hkex_cascade_hkdf()) {
return FAILURE;
}
if (test_hkex_cascade_hmac()) {
return FAILURE;
}
if (test_hkex_cascade_kmac()) {
return FAILURE;
}
// Derandomized CatKDF
if (test_hkex_concatenate_hkdf_derand()) {
return FAILURE;
}
if (test_hkex_concatenate_hmac_derand()) {
return FAILURE;
}
if (test_hkex_concatenate_kmac_derand()) {
return FAILURE;
}
// Derandomized CasKDF
if (test_hkex_cascade_hkdf_derand()) {
return FAILURE;
}
if (test_hkex_cascade_hmac_derand()) {
return FAILURE;
}
if (test_hkex_cascade_kmac_derand()) {
return FAILURE;
}
//Randomized CatKDF
if (test_hkex_concatenate_hkdf_rand()) {
return FAILURE;
}
if (test_hkex_concatenate_hmac_rand()) {
return FAILURE;
}
if (test_hkex_concatenate_kmac_rand()) {
return FAILURE;
}
// Randomized CasKDF
if (test_hkex_cascade_hkdf_rand()) {
return FAILURE;
}
if (test_hkex_cascade_hmac_rand()) {
return FAILURE;
}
if (test_hkex_cascade_kmac_rand()) {
return FAILURE;
}
printf("All tests passed\n");
return SUCCESS;
}
......@@ -15,18 +15,60 @@
*/
#include "qshkex.h"
#include <openssl/crypto.h>
/* Memory helper functions to handle null values */
static inline void *my_memcpy(void *dst, const void *src, size_t byte_len)
void *my_memcpy(void *dst, const void *src, size_t byte_len)
{
if (src == NULL || dst == NULL) {
return dst;
}
return memcpy(dst, src, byte_len);
}
/* Implements KDF concatenate-based formatting function, see Section 7.2.2 */
/* Input: const uint8_t * arg1, arg2, arg3 */
/* Input: const uint32_t a1length, a2length, a3length */
/* Output: uint8_t *kdf_context, uint32_t *clength */
/* Functionality: kdf_context = arg1 || a1length || arg2 || a2length || arg3 || a3length */
int cb_f(uint8_t *kdf_context, uint32_t *clength, const uint8_t *arg1,
const uint32_t a1length, const uint8_t *arg2, const uint32_t a2length, const uint8_t *arg3,
const uint32_t a3length)
{
int rval = FAILURE;
uint32_t length;
/* Implements the kdf context formatting function f, see Section 7.2 */
int f_function(const EVP_MD *md_type, uint8_t *kdf_context, uint32_t *clength, const uint8_t *arg1,
do {
if ((kdf_context == NULL) || (clength == NULL)) {
break;
}
if (((a1length) && (arg1 == NULL)) || ((a2length) && (arg2 == NULL)) || ((a3length) && (arg3 == NULL))) {
break;
}
length = htonl(a1length);
my_memcpy(kdf_context, &length, sizeof(uint32_t));
my_memcpy(kdf_context + sizeof(uint32_t), arg1, a1length);
length = htonl(a2length);
my_memcpy(kdf_context + sizeof(uint32_t) + a1length, &length, sizeof(uint32_t));
my_memcpy(kdf_context + 2 * sizeof(uint32_t) + a1length, arg2, a2length);
length = htonl(a3length);
my_memcpy(kdf_context + 2 * sizeof(uint32_t) + a1length + a2length, &length, sizeof(uint32_t));
my_memcpy(kdf_context + 3 * sizeof(uint32_t) + a1length + a2length, arg3, a3length);
*clength = a1length + a2length + a3length + 3 * sizeof(uint32_t);
rval = SUCCESS;
} while (0);
return rval;
}
/* Implements KDF concatenate-and-hash-based formatting function, see Section 7.2.3 */
/* Input: const uint8_t * arg1, arg2, arg3 */
/* Input: const uint32_t a1length, a2length, a3length */
/* Input: const EVP_MD *md_type */
/* Output: uint8_t *kdf_context, uint32_t *clength */
/* Functionality: kdf_context = hash(arg1 || a1length || arg2 || a2length || arg3 || a3length) */
int cahb_f(const EVP_MD *md_type, uint8_t *kdf_context, uint32_t *clength, const uint8_t *arg1,
const uint32_t a1length, const uint8_t *arg2, const uint32_t a2length, const uint8_t *arg3,
const uint32_t a3length)
{
......@@ -41,6 +83,7 @@ int f_function(const EVP_MD *md_type, uint8_t *kdf_context, uint32_t *clength, c
if (((a1length) && (arg1 == NULL)) || ((a2length) && (arg2 == NULL)) || ((a3length) && (arg3 == NULL))) {
break;
}
if ((mdctx = EVP_MD_CTX_new()) == NULL) {
break;
}
......@@ -78,7 +121,160 @@ int f_function(const EVP_MD *md_type, uint8_t *kdf_context, uint32_t *clength, c
}
return rval;
}
/* Implements the HMAC prf function from Section 7.3.2 */
/* Implements HKDF KDF function from Section 7.4.2 */
/* Input: const EVP_MD *md_type */
/* Input: const uint8_t *secret, *label, *context */
/* Input: const uint32_t slength, llength, clength */
/* Output: uint8_t *key_material, uint32_t *klength */
/* Functionality: key_material = HKDF(secret, label, context, length) */
int kdf_hkdf(const EVP_MD *md_type, uint8_t *key_material, uint32_t *klength, const uint8_t *secret, const uint32_t slength,
const uint8_t *label, const uint32_t llength, const uint8_t *context, const uint32_t clength)
{
int rval = FAILURE;
EVP_PKEY_CTX *pctx = NULL;
size_t keylen;
do {
if ((md_type == NULL) || (key_material == NULL) || (klength == NULL) || (secret == NULL)) {
break;
}
if (((llength) && (label == NULL)) || ((clength) && (context == NULL))) {
break;
}
if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL)) == NULL) {
break;
}
if (EVP_PKEY_derive_init(pctx) != 1) {
break;
}
if (EVP_PKEY_CTX_set_hkdf_md(pctx, md_type) != 1) {
break;
}
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, label, (int)llength) != 1) {
break;
}
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, (int)slength) != 1) {
break;
}
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, context, (int)clength) != 1) {
break;
}
keylen = *klength;
if (EVP_PKEY_derive(pctx, key_material, &keylen) != 1) {
break;
}
*klength = (uint32_t)keylen;
rval = SUCCESS;
} while (0);
if (pctx) {
EVP_PKEY_CTX_free(pctx);
}
return rval;
}
/* Implements HMAC KDF function from Section 7.4.3 */
/* Input: const EVP_MD *md_type */
/* Input: const uint8_t *secret, *label, *context */
/* Input: const uint32_t slength, llength, clength */
/* Output: uint8_t *key_material, uint32_t *klength */
/* Functionality: key_material = HMAC(label, secret || context) */
int kdf_hmac(const EVP_MD *md_type, uint8_t *key_material, uint32_t *klength, const uint8_t *secret, const uint32_t slength,
const uint8_t *label, const uint32_t llength, const uint8_t *context, const uint32_t clength)
{
int rval = FAILURE;
size_t keylen;
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM params[6], *p = params;
do {
if ((key_material == NULL) || (klength == NULL) || (secret == NULL)) {
break;
}
if (((llength) && (label == NULL)) || ((clength) && (context == NULL))) {
break;
}
kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
*p++ = OSSL_PARAM_construct_utf8_string("mac", (char *)"HMAC", strlen("HMAC"));
*p++ = OSSL_PARAM_construct_utf8_string("digest", (char *) EVP_MD_name(md_type), 0);
*p++ = OSSL_PARAM_construct_octet_string("secret", (void *)secret, slength);
*p++ = OSSL_PARAM_construct_octet_string("salt", (void *)label, llength);
*p++ = OSSL_PARAM_construct_octet_string("info", (void *)context, clength);
*p = OSSL_PARAM_construct_end();
keylen = *klength;
if (EVP_KDF_derive(kctx, key_material, keylen, params) <= 0) {
break;
}
*klength = keylen;
rval = SUCCESS;
} while (0);
if (kdf) {
EVP_KDF_free(kdf);
}
if (kctx) {
EVP_KDF_CTX_free(kctx);
}
return rval;
}
/* Implements KMAC KDF function from Section 7.4.4 */
/* Input: const char *kmac */
/* Input: const uint8_t *secret, *label, *context */
/* Input: const uint32_t slength, llength, clength */
/* Output: uint8_t *key_material, uint32_t *klength */
/* Functionality: key_material = KMAC#(label, counter || secret || context, length * 8, "KDF") */
/* Functionality: key_material = SSKDF_kmac(secret, label, context, length) */
int kdf_kmac(const char *kmac, uint8_t *key_material, uint32_t *klength, const uint8_t *secret, const uint32_t slength,
const uint8_t *label, const uint32_t llength, const uint8_t *context, const uint32_t clength)
{
int rval = FAILURE;
size_t keylen;
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM params[5], *p = params;
do {
if ((key_material == NULL) || (klength == NULL) || (secret == NULL)) {
break;
}
if (((llength) && (label == NULL)) || ((clength) && (context == NULL))) {
break;
}
kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
*p++ = OSSL_PARAM_construct_utf8_string("mac", (char *)kmac, strlen(kmac));
*p++ = OSSL_PARAM_construct_octet_string("secret", (void *)secret, slength);
*p++ = OSSL_PARAM_construct_octet_string("salt", (void *)label, llength);
*p++ = OSSL_PARAM_construct_octet_string("info", (void *)context, clength);
*p = OSSL_PARAM_construct_end();
keylen = *klength;
if (EVP_KDF_derive(kctx, key_material, keylen, params) <= 0) {
break;
}
*klength = keylen;
rval = SUCCESS;
} while (0);
if (kdf) {
EVP_KDF_free(kdf);
}
if (kctx) {
EVP_KDF_CTX_free(kctx);
}
return rval;
}
/* Implements HMAC PRF function from Section 7.3.2 */
/* Input: const EVP_MD *md_type */
/* Input: const uint8_t *secret, *ki, *MAi, *MBi */
/* Input: const uint8_t slength, const uint32_t kilength, mailength, mbilength */
/* Output: uint8_t *output, uint32_t *olength */
/* Functionality: context = cahb_f(ki, MAi, MBi) */
/* Functionality: output = HMAC(secret, context) */
int prf_hmac(const EVP_MD *md_type, uint8_t *output, uint32_t *olength, const uint8_t *secret, const uint8_t slength,
const uint8_t *ki, const uint32_t kilength, const uint8_t *MAi, const uint32_t mailength,
const uint8_t *MBi, const uint32_t mbilength)
......@@ -87,8 +283,10 @@ int prf_hmac(const EVP_MD *md_type, uint8_t *output, uint32_t *olength, const ui
uint32_t clength = MAX_DIGEST_BYTE_LEN;
uint8_t context[MAX_DIGEST_BYTE_LEN];
size_t outlen = MAX_DIGEST_BYTE_LEN;
EVP_MD_CTX *mdctx = NULL;
EVP_PKEY * pkey = NULL;
EVP_MAC_CTX *ctx = NULL;
EVP_MAC *mac = NULL;
OSSL_PARAM params[2], *p = params;
do {
if ((md_type == NULL) || (output == NULL) || (olength == NULL)) {
......@@ -100,86 +298,150 @@ int prf_hmac(const EVP_MD *md_type, uint8_t *output, uint32_t *olength, const ui
if (((mailength) && (MAi == NULL)) || ((mbilength) && (MBi == NULL))) {
break;
}
if (f_function(md_type, context, &clength, ki, kilength, MAi, mailength, MBi, mbilength)) {
if (cahb_f(md_type, context, &clength, ki, kilength, MAi, mailength, MBi, mbilength)) {
break;
}
if ((mdctx = EVP_MD_CTX_new()) == NULL) {
// Use EVP_MAC struct to allow zero length secret |slength|
if ((mac = EVP_MAC_fetch(NULL, "HMAC", NULL)) == NULL) {
break;
}
if ((pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, secret, slength)) == NULL) {
if ((ctx = EVP_MAC_CTX_new(mac)) == NULL) {
break;
}
if (EVP_DigestSignInit(mdctx, NULL, md_type, NULL, pkey) != 1) {
*p++ = OSSL_PARAM_construct_utf8_string("digest", (char *) EVP_MD_name(md_type), 0);
*p = OSSL_PARAM_construct_end();
if (!EVP_MAC_init(ctx, secret, slength, params)) {
break;
}
if (EVP_DigestSignUpdate(mdctx, context, clength) != 1) {
if (!EVP_MAC_update(ctx, context, clength)) {
break;
}
outlen = *olength;
if (EVP_DigestSignFinal(mdctx, output, &outlen) != 1) {
if (!EVP_MAC_final(ctx, output, (size_t*) olength, outlen)) {
break;
}
*olength = (uint32_t)outlen;
rval = SUCCESS;
} while (0);
if (mdctx) {
EVP_MD_CTX_free(mdctx);
if (mac) {
EVP_MAC_free(mac);
}
if (pkey) {
EVP_PKEY_free(pkey);
if (ctx) {
EVP_MAC_CTX_free(ctx);
}
return rval;
}
/* Implements the HMAC KDF function from Section 7.4.2 */
int kdf(const EVP_MD *md_type, uint8_t *key_material, uint32_t *klength, const uint8_t *secret, const uint32_t slength,
const uint8_t *label, const uint32_t llength, const uint8_t *context, const uint32_t clength)
/* Implements KMAC PRF function from Section 7.3.3 */
/* Input: const char *kmac */
/* Input: const uint8_t *secret, *ki, *MAi, *MBi */
/* Input: const uint8_t slength, const uint32_t kilength, mailength, mbilength */
/* Output: uint8_t *output, uint32_t *olength */
/* Functionality: context = cb_f(ki, MAi, MBi) */
/* Functionality: output = KMAC#(secret, context, 256/512, NULL) */
int prf_kmac(const char *kmac, uint8_t *output, uint32_t *olength, const uint8_t *secret, const uint8_t slength,
const uint8_t *ki, const uint32_t kilength, const uint8_t *MAi, const uint32_t mailength,
const uint8_t *MBi, const uint32_t mbilength)
{
int rval = FAILURE;
EVP_PKEY_CTX *pctx = NULL;
size_t keylen;
uint32_t clength = MAX_DIGEST_BYTE_LEN;
uint8_t context[MAX_BUFFER_SIZE];
size_t outlen = MAX_DIGEST_BYTE_LEN;
EVP_MAC_CTX *ctx = NULL;
EVP_MAC *mac = NULL;
OSSL_PARAM params[5], *p = params;
do {
if ((md_type == NULL) || (key_material == NULL) || (klength == NULL) || (secret == NULL)) {
if ((kmac == NULL) || (output == NULL) || (olength == NULL)) {
break;
}
if (((llength) && (label == NULL)) || ((clength) && (context == NULL))) {
if (((slength) && (secret == NULL)) || ((kilength) && (ki == NULL))) {
break;
}
if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL)) == NULL) {
if (((mailength) && (MAi == NULL)) || ((mbilength) && (MBi == NULL))) {
break;
}
if (EVP_PKEY_derive_init(pctx) != 1) {
if (cb_f(context, &clength, ki, kilength, MAi, mailength, MBi, mbilength)) {
break;
}
if (EVP_PKEY_CTX_set_hkdf_md(pctx, md_type) != 1) {
mac = EVP_MAC_fetch(NULL, kmac, NULL);
if (!(ctx = EVP_MAC_CTX_new(mac))) {
break;
}
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, label, (int)llength) != 1) {
outlen = *olength;
*p++ = OSSL_PARAM_construct_int("size", (int *)olength);
*p = OSSL_PARAM_construct_end();
if (!EVP_MAC_init(ctx, secret, slength, params)) {
break;
}
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, (int)slength) != 1) {
if (!EVP_MAC_update(ctx, context, clength)){
break;
}
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, context, (int)clength) != 1) {
if (!EVP_MAC_final(ctx, output, (size_t*)olength, outlen)){
break;
}
keylen = *klength;
if (EVP_PKEY_derive(pctx, key_material, &keylen) != 1) {
rval = SUCCESS;
} while (0);
if (mac) {
EVP_MAC_free(mac);
}
if (ctx) {
EVP_MAC_CTX_free(ctx);
}
return rval;
}
/* Implements function CatKDF from Section 8.2 using HKDF KDF as described in Section 7.4.2 */
/* Input: const EVP_MD *md_type */
/* Input: uint8_t *psk, *k1, *k2, *MA, *MB, *info, *label */
/* Input: const uint32_t klength, plength, k1length, k2length, malength, mblength, clength, llength */
/* Output: uint8_t *key_material */
int hkex_concat_hkdf(const EVP_MD *md_type, uint8_t *key_material, const uint32_t klength, const uint8_t *psk,
const uint32_t plength, const uint8_t *k1, const uint32_t k1length, const uint8_t *k2,
const uint32_t k2length, const uint8_t *MA, const uint32_t malength, const uint8_t *MB,
const uint32_t mblength, const uint8_t *info, const uint32_t ilength, const uint8_t *label,
const uint32_t llength)
{
int rval = FAILURE;
uint8_t secrets[MAX_SECRETS_BYTE_LEN];
uint8_t kdf_context[MAX_DIGEST_BYTE_LEN];
uint32_t kmlength, slength, kdfclength;
uint64_t total_size;
do {
if ((md_type == NULL) || (key_material == NULL) || (k1 == NULL) || (k2 == NULL) || (MA == NULL) ||
(MB == NULL)) {
break;
}
if (((llength) && (label == NULL)) || ((ilength) && (info == NULL)) || ((plength) && (psk == NULL))) {
break;
}
total_size = plength + k1length + k2length;
if (total_size > MAX_SECRETS_BYTE_LEN) {
break;
}
kdfclength = MAX_DIGEST_BYTE_LEN;
if (cahb_f(md_type, kdf_context, &kdfclength, info, ilength, MA, malength, MB, mblength)) {
break;
}
my_memcpy(secrets, psk, plength);
my_memcpy(secrets + plength, k1, k1length);
my_memcpy(secrets + plength + k1length, k2, k2length);
slength = plength + k1length + k2length;
kmlength = klength;
if (kdf_hkdf(md_type, key_material, &kmlength, secrets, slength, label, llength, kdf_context, kdfclength)) {
break;
}
*klength = (uint32_t)keylen;
rval = SUCCESS;
} while (0);
if (pctx) {
EVP_PKEY_CTX_free(pctx);
}
return rval;
}
/* Implements the function Concatenation KDF from Section 8.2 */
int hkex_concat(const EVP_MD *md_type, uint8_t *key_material, const uint32_t klength, const uint8_t *psk,
/* Implements function CatKDF from Section 8.2 using HMAC KDF as described in Section 7.4.3 */
/* Input: const EVP_MD *md_type */
/* Input: uint8_t *psk, *k1, *k2, *MA, *MB, *info, *label */
/* Input: const uint32_t klength, plength, k1length, k2length, malength, mblength, clength, llength */
/* Output: uint8_t *key_material */
int hkex_concat_hmac(const EVP_MD *md_type, uint8_t *key_material, const uint32_t klength, const uint8_t *psk,
const uint32_t plength, const uint8_t *k1, const uint32_t k1length, const uint8_t *k2,
const uint32_t k2length, const uint8_t *MA, const uint32_t malength, const uint8_t *MB,
const uint32_t mblength, const uint8_t *context, const uint32_t clength, const uint8_t *label,
const uint32_t mblength, const uint8_t *info, const uint32_t ilength, const uint8_t *label,
const uint32_t llength)
{
int rval = FAILURE;
......@@ -192,7 +454,7 @@ int hkex_concat(const EVP_MD *md_type, uint8_t *key_material, const uint32_t kle
(MB == NULL)) {
break;
}
if (((llength) && (label == NULL)) || ((clength) && (context == NULL)) || ((plength) && (psk == NULL))) {
if (((llength) && (label == NULL)) || ((ilength) && (info == NULL)) || ((plength) && (psk == NULL))) {
break;
}
total_size = plength + k1length + k2length;
......@@ -200,26 +462,74 @@ int hkex_concat(const EVP_MD *md_type, uint8_t *key_material, const uint32_t kle
break;
}
kdfclength = MAX_DIGEST_BYTE_LEN;
if (f_function(md_type, kdf_context, &kdfclength, context, clength, MA, malength, MB, mblength)) {
if (cahb_f(md_type, kdf_context, &kdfclength, info, ilength, MA, malength, MB, mblength)) {
break;
}
my_memcpy(secrets, psk, plength);
my_memcpy(secrets + plength, k1, k1length);
my_memcpy(secrets + plength + k1length, k2, k2length);
slength = plength + k1length + k2length;
kmlength = klength;
if (kdf(md_type, key_material, &kmlength, secrets, slength, label, llength, kdf_context, kdfclength)) {
if (kdf_hmac(md_type, key_material, &kmlength, secrets, slength, label, llength, kdf_context, kdfclength)) {
break;
}
rval = SUCCESS;
} while (0);
return rval;
}
/* Implements the one round of the function Cascading KDF from Section 8.3 */
int hkex_cascade(const EVP_MD *md_type, uint8_t *chain_secret, const uint32_t cslength, uint8_t *key_material,
/* Implements function CatKDF from Section 8.2 using KMAC KDF as described in Section 7.4.4 */
/* Input: const char *kmac */
/* Input: uint8_t *psk, *k1, *k2, *MA, *MB, *info, *label */
/* Input: const uint32_t klength, plength, k1length, k2length, malength, mblength, ilength, llength */
/* Output: uint8_t *key_material */
int hkex_concat_kmac(const char *kmac, uint8_t *key_material, const uint32_t klength, const uint8_t *psk,
const uint32_t plength, const uint8_t *k1, const uint32_t k1length, const uint8_t *k2,
const uint32_t k2length, const uint8_t *MA, const uint32_t malength, const uint8_t *MB,
const uint32_t mblength, const uint8_t *info, const uint32_t ilength, const uint8_t *label,
const uint32_t llength)
{
int rval = FAILURE;
uint8_t secrets[MAX_SECRETS_BYTE_LEN];
uint8_t kdf_context[MAX_BUFFER_SIZE];
uint32_t kmlength, slength, kdfclength;
uint64_t total_size;
do {
if ((key_material == NULL) || (k1 == NULL) || (k2 == NULL) || (MA == NULL) ||
(MB == NULL)) {
break;
}
if (((llength) && (label == NULL)) || ((ilength) && (info == NULL)) || ((plength) && (psk == NULL))) {
break;
}
total_size = plength + k1length + k2length;
if (total_size > MAX_SECRETS_BYTE_LEN) {
break;
}
if (cb_f(kdf_context, &kdfclength, info, ilength, MA, malength, MB, mblength)) {
break;
}
my_memcpy(secrets, psk, plength);
my_memcpy(secrets + plength, k1, k1length);
my_memcpy(secrets + plength + k1length, k2, k2length);
slength = plength + k1length + k2length;
kmlength = klength;
if (kdf_kmac(kmac, key_material, &kmlength, secrets, slength, label, llength, kdf_context, kdfclength)) {
break;
}
rval = SUCCESS;
} while (0);
return rval;
}
/* Implements function CasKDF from Section 8.3 using HKDF KDF and HMAC PRF as described in Sections 7.4.2 and 7.3.2 */
/* Input: const EVP_MD *md_type */
/* Input: uint8_t *previous_chain_secret, *ki, *MAi, *MBi, infoi, *labeli */
/* Input: const uint32_t cslength, klength, pcslength, kilength, mailength, mbilength, iilength, lilength */
/* Output: uint8_t *chain_secret, *key_material */
int hkex_cascade_hkdf(const EVP_MD *md_type, uint8_t *chain_secret, const uint32_t cslength, uint8_t *key_material,
const uint32_t klength, const uint8_t *previous_chain_secret, const uint32_t pcslength,
const uint8_t *ki, const uint32_t kilength, const uint8_t *MAi, const uint32_t mailength,
const uint8_t *MBi, const uint32_t mbilength, const uint8_t *contexti, const uint32_t cilength,
const uint8_t *MBi, const uint32_t mbilength, const uint8_t *infoi, const uint32_t iilength,
const uint8_t *labeli, const uint32_t lilength)
{
int rval = FAILURE;
......@@ -233,7 +543,7 @@ int hkex_cascade(const EVP_MD *md_type, uint8_t *chain_secret, const uint32_t cs
(MBi == NULL)) {
break;
}
if (((pcslength) && (previous_chain_secret == NULL)) || ((cilength) && (contexti == NULL)) ||
if (((pcslength) && (previous_chain_secret == NULL)) || ((iilength) && (infoi == NULL)) ||
((lilength) && (labeli == NULL))) {
break;
}
......@@ -249,7 +559,111 @@ int hkex_cascade(const EVP_MD *md_type, uint8_t *chain_secret, const uint32_t cs
break;
}
olength = (uint32_t)osize;
if (kdf(md_type, output, &olength, rsecret, rlength, labeli, lilength, contexti, cilength)) {
if (kdf_hkdf(md_type, output, &olength, rsecret, rlength, labeli, lilength, infoi, iilength)) {
break;
}
if (olength != (uint32_t)osize) {
break;
}
my_memcpy(chain_secret, output, cslength);
my_memcpy(key_material, output + cslength, klength);
OPENSSL_cleanse(output, sizeof(output));
rval = SUCCESS;
} while (0);
return rval;
}
/* Implements function CasKDF from Section 8.3 using HMAC KDF and HMAC PRF as described in Sections 7.4.3 and 7.3.2 */
/* Input: const EVP_MD *md_type */
/* Input: uint8_t *previous_chain_secret, *ki, *MAi, *MBi, infoi, *labeli */
/* Input: const uint32_t cslength, klength, pcslength, kilength, mailength, mbilength, iilength, lilength */
/* Output: uint8_t *chain_secret, *key_material */
int hkex_cascade_hmac(const EVP_MD *md_type, uint8_t *chain_secret, const uint32_t cslength, uint8_t *key_material,
const uint32_t klength, const uint8_t *previous_chain_secret, const uint32_t pcslength,
const uint8_t *ki, const uint32_t kilength, const uint8_t *MAi, const uint32_t mailength,
const uint8_t *MBi, const uint32_t mbilength, const uint8_t *infoi, const uint32_t iilength,
const uint8_t *labeli, const uint32_t lilength)
{
int rval = FAILURE;
uint8_t rsecret[MAX_DIGEST_BYTE_LEN];
uint8_t output[MAX_KEY_MATERIAL_BYTE_LEN + MAX_DIGEST_BYTE_LEN];
uint32_t olength, rlength = MAX_DIGEST_BYTE_LEN;
uint64_t osize;
do {
if ((md_type == NULL) || (chain_secret == NULL) || (key_material == NULL) || (ki == NULL) || (MAi == NULL) ||
(MBi == NULL)) {
break;
}
if (((pcslength) && (previous_chain_secret == NULL)) || ((iilength) && (infoi == NULL)) ||
((lilength) && (labeli == NULL))) {
break;
}
if ((cslength > MAX_DIGEST_BYTE_LEN) || (klength > MAX_KEY_MATERIAL_BYTE_LEN)) {
break;
}
osize = cslength + klength;
if (osize > sizeof(output)) {
break;
}
if (prf_hmac(md_type, rsecret, &rlength, previous_chain_secret, pcslength, ki, kilength, MAi, mailength, MBi,
mbilength)) {
break;
}
olength = (uint32_t)osize;
if (kdf_hmac(md_type, output, &olength, rsecret, rlength, labeli, lilength, infoi, iilength)) {
break;
}
if (olength != (uint32_t)osize) {
break;
}
my_memcpy(chain_secret, output, cslength);
my_memcpy(key_material, output + cslength, klength);
OPENSSL_cleanse(output, sizeof(output));
rval = SUCCESS;
} while (0);
return rval;
}
/* Implements function CasKDF from Section 8.3 using KMAC KDF and KMAC PRF as described in Sections 7.4.4 and 7.3.3 */
/* Input: const char *kmac */
/* Input: uint8_t *previous_chain_secret, *ki, *MAi, *MBi, infoi, *labeli */
/* Input: const uint32_t cslength, klength, pcslength, kilength, mailength, mbilength, iilength, lilength */
/* Output: uint8_t *chain_secret, *key_material */
int hkex_cascade_kmac(const char *kmac, uint8_t *chain_secret, const uint32_t cslength, uint8_t *key_material,
const uint32_t klength, const uint8_t *previous_chain_secret, const uint32_t pcslength,
const uint8_t *ki, const uint32_t kilength, const uint8_t *MAi, const uint32_t mailength,
const uint8_t *MBi, const uint32_t mbilength, const uint8_t *infoi, const uint32_t iilength,
const uint8_t *labeli, const uint32_t lilength)
{
int rval = FAILURE;
uint8_t rsecret[MAX_DIGEST_BYTE_LEN];
uint8_t output[MAX_KEY_MATERIAL_BYTE_LEN + MAX_DIGEST_BYTE_LEN];
uint32_t olength;
uint32_t rlength;
uint64_t osize;
do {
if ((kmac == NULL) || (chain_secret == NULL) || (key_material == NULL) || (ki == NULL) || (MAi == NULL) ||
(MBi == NULL)) {
break;
}
if (((pcslength) && (previous_chain_secret == NULL)) || ((iilength) && (infoi == NULL)) ||
((lilength) && (labeli == NULL))) {
break;
}
if ((cslength > MAX_DIGEST_BYTE_LEN) || (klength > MAX_KEY_MATERIAL_BYTE_LEN)) {
break;
}
osize = cslength + klength;
if (osize > sizeof(output)) {
break;
}
rlength = cslength;
if (prf_kmac(kmac, rsecret, &rlength, previous_chain_secret, pcslength, ki, kilength, MAi, mailength, MBi,
mbilength)) {
break;
}
olength = (uint32_t)osize;
if (kdf_kmac(kmac, output, &olength, rsecret, rlength, labeli, lilength, infoi, iilength)) {
break;
}
if (olength != (uint32_t)osize) {
......
......@@ -26,18 +26,52 @@
#define MAX_SECRETS_BYTE_LEN 256
#define MAX_KEY_MATERIAL_BYTE_LEN 128
#define MAX_BUFFER_SIZE 4096
#define MAX_LABEL_BYTE_LEN 64
#define MAX_KEY_BYTE_LEN 128
#define MAX_LABEL_LEN 32
#define KMAC128_OUT_BYTE_LENGTH 32
#define KMAC256_OUT_BYTE_LENGTH 48
#define MAX_MSG_BYTE_LEN 8192
void print_array(const char *label, const uint8_t *array, const uint32_t alength);
void ascii_hex_strings_to_uint8(uint8_t *array, uint32_t *alength, const uint32_t scount, ...);
void *my_memcpy(void *dst, const void *src, size_t byte_len);
int hkex_concat_hkdf(const EVP_MD *md_type, uint8_t *key_material, const uint32_t klength, const uint8_t *psk,
const uint32_t plength, const uint8_t *k1, const uint32_t k1length, const uint8_t *k2,
const uint32_t k2length, const uint8_t *MA, const uint32_t malength, const uint8_t *MB,
const uint32_t mblength, const uint8_t *info, const uint32_t ilength, const uint8_t *label,
const uint32_t llength);
int hkex_concat_hmac(const EVP_MD *md_type, uint8_t *key_material, const uint32_t klength, const uint8_t *psk,
const uint32_t plength, const uint8_t *k1, const uint32_t k1length, const uint8_t *k2,
const uint32_t k2length, const uint8_t *MA, const uint32_t malength, const uint8_t *MB,
const uint32_t mblength, const uint8_t *info, const uint32_t ilength, const uint8_t *label,
const uint32_t llength);
int hkex_concat(const EVP_MD *md_type, uint8_t *key_material, const uint32_t klength, const uint8_t *psk,
int hkex_concat_kmac(const char *kmac, uint8_t *key_material, const uint32_t klength, const uint8_t *psk,
const uint32_t plength, const uint8_t *k1, const uint32_t k1length, const uint8_t *k2,
const uint32_t k2length, const uint8_t *MA, const uint32_t malength, const uint8_t *MB,
const uint32_t mblength, const uint8_t *context, const uint32_t clength, const uint8_t *label,
const uint32_t mblength, const uint8_t *info, const uint32_t ilength, const uint8_t *label,
const uint32_t llength);
int hkex_cascade(const EVP_MD *md_type, uint8_t *chain_secret, const uint32_t cslength, uint8_t *key_material,
int hkex_cascade_hkdf(const EVP_MD *md_type, uint8_t *chain_secret, const uint32_t cslength, uint8_t *key_material,
const uint32_t klength, const uint8_t *previous_chain_secret, const uint32_t pcslength,
const uint8_t *ki, const uint32_t kilength, const uint8_t *MAi, const uint32_t mailength,
const uint8_t *MBi, const uint32_t mbilength, const uint8_t *infoi, const uint32_t iilength,
const uint8_t *labeli, const uint32_t lilength);
int hkex_cascade_hmac(const EVP_MD *md_type, uint8_t *chain_secret, const uint32_t cslength, uint8_t *key_material,
const uint32_t klength, const uint8_t *previous_chain_secret, const uint32_t pcslength,
const uint8_t *ki, const uint32_t kilength, const uint8_t *MAi, const uint32_t mailength,
const uint8_t *MBi, const uint32_t mbilength, const uint8_t *infoi, const uint32_t iilength,
const uint8_t *labeli, const uint32_t lilength);
int hkex_cascade_kmac(const char *kmac, uint8_t *chain_secret, const uint32_t cslength, uint8_t *key_material,
const uint32_t klength, const uint8_t *previous_chain_secret, const uint32_t pcslength,
const uint8_t *ki, const uint32_t kilength, const uint8_t *MAi, const uint32_t mailength,
const uint8_t *MBi, const uint32_t mbilength, const uint8_t *contexti, const uint32_t cilength,
const uint8_t *MBi, const uint32_t mbilength, const uint8_t *infoi, const uint32_t iilength,
const uint8_t *labeli, const uint32_t lilength);
#endif /*_QS_H_KEX_H_*/