Add SLH-DSA FIPS self tests

This requires a keygen test, as well as Sign/Verify tests for at least 1
sha2 algorithm and 1 shake related algorithm.

A pairwise consistency test has also been added to the key generation.

Note that self test datat for the signature is currently stored as a
sha256 digest in order to reduce the memory footprint.
(Since the signature size for sha2/shake using 128s = ~8K, and for 128f = ~17K)

Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25882)
This commit is contained in:
slontis 2024-11-21 12:15:24 +11:00 committed by Tomas Mraz
parent a25bcde26a
commit b8b67b1907
6 changed files with 359 additions and 200 deletions

View File

@ -53,6 +53,7 @@ extern "C" {
# define OSSL_SELF_TEST_DESC_PCT_DSA "DSA"
# define OSSL_SELF_TEST_DESC_PCT_ML_DSA "ML-DSA"
# define OSSL_SELF_TEST_DESC_PCT_ML_KEM "ML-KEM"
# define OSSL_SELF_TEST_DESC_PCT_SLH_DSA "SLH_DSA"
# define OSSL_SELF_TEST_DESC_CIPHER_AES_GCM "AES_GCM"
# define OSSL_SELF_TEST_DESC_CIPHER_AES_ECB "AES_ECB_Decrypt"
# define OSSL_SELF_TEST_DESC_CIPHER_TDES "TDES"
@ -67,6 +68,7 @@ extern "C" {
# define OSSL_SELF_TEST_DESC_SIGN_EDDSA "EDDSA"
# define OSSL_SELF_TEST_DESC_SIGN_ML_DSA "ML-DSA"
# define OSSL_SELF_TEST_DESC_KEM "KEM"
# define OSSL_SELF_TEST_DESC_SIGN_SLH_DSA "SLH_DSA"
# define OSSL_SELF_TEST_DESC_DRBG_CTR "CTR"
# define OSSL_SELF_TEST_DESC_DRBG_HASH "HASH"
# define OSSL_SELF_TEST_DESC_DRBG_HMAC "HMAC"
@ -89,6 +91,7 @@ extern "C" {
# define OSSL_SELF_TEST_DESC_DECAP_KEM "KEM_Decap"
# define OSSL_SELF_TEST_DESC_DECAP_KEM_FAIL "KEM_Decap_Reject"
# define OSSL_SELF_TEST_DESC_KEYGEN_KEM "KEM_Keygen"
# define OSSL_SELF_TEST_DESC_KEYGEN_SLH_DSA "SLH_DSA"
void OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK *cb,
void *cbarg);

View File

@ -54,9 +54,10 @@ typedef struct st_kat_st {
#define CIPHER_MODE_ALL (CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT)
/* FIPS 140-3 only allows DSA verification for legacy purposes */
#define SIGNATURE_MODE_VERIFY_ONLY 1
#define SIGNATURE_MODE_SIGN_ONLY 2
#define SIGNATURE_MODE_DIGESTED 4
#define SIGNATURE_MODE_VERIFY_ONLY 1
#define SIGNATURE_MODE_SIGN_ONLY 2
#define SIGNATURE_MODE_DIGESTED 4
#define SIGNATURE_MODE_SIG_DIGESTED 8
typedef ST_KAT ST_KAT_DIGEST;
typedef struct st_kat_cipher_st {
@ -2851,6 +2852,74 @@ static const ST_KAT_PARAM ml_dsa_sig_init[] = {
};
#endif /* OPENSSL_NO_ML_DSA */
#ifndef OPENSSL_NO_SLH_DSA
/*
* Deterministic SLH_DSA key generation supplies the private key elements and
* Half of the public key.
*/
static const uint8_t slh_dsa_sha2_128s_keygen_entropy[] = {
0xaa, 0x9c, 0xc7, 0xdc, 0xa4, 0x91, 0xfc, 0x86, 0xbc, 0xb1, 0x5a, 0x70, 0x9a, 0x15, 0xe9, 0xb3,
0x90, 0x5c, 0x80, 0x0b, 0x6e, 0x2f, 0xb9, 0xb5, 0x4b, 0x6b, 0x05, 0x0e, 0xe5, 0xe4, 0xde, 0x9a,
0xfa, 0x54, 0x64, 0xd1, 0xc6, 0x61, 0xfe, 0xd3, 0x8b, 0x2a, 0x51, 0xca, 0x3e, 0xae, 0x71, 0xba,
};
/* The expected outputs for the public and private key elements */
static const uint8_t slh_dsa_sha2_128s_keygen_priv[] = {
0xaa, 0x9c, 0xc7, 0xdc, 0xa4, 0x91, 0xfc, 0x86, 0xbc, 0xb1, 0x5a, 0x70, 0x9a, 0x15, 0xe9, 0xb3,
0x90, 0x5c, 0x80, 0x0b, 0x6e, 0x2f, 0xb9, 0xb5, 0x4b, 0x6b, 0x05, 0x0e, 0xe5, 0xe4, 0xde, 0x9a,
};
static const uint8_t slh_dsa_sha2_128s_keygen_pub[] = {
0xfa, 0x54, 0x64, 0xd1, 0xc6, 0x61, 0xfe, 0xd3, 0x8b, 0x2a, 0x51, 0xca, 0x3e, 0xae, 0x71, 0xba,
0xca, 0xe3, 0xd1, 0x86, 0x52, 0x15, 0xe3, 0xd3, 0x85, 0x0e, 0x8c, 0x1b, 0x82, 0x92, 0xbf, 0x42,
};
static const ST_KAT_PARAM slh_dsa_sha2_128s_keygen_init_params[] = {
ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_SLH_DSA_ENTROPY,
slh_dsa_sha2_128s_keygen_entropy),
ST_KAT_PARAM_END()
};
static const ST_KAT_PARAM slh_dsa_128_keygen_expected_params[] = {
ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PRIV_KEY,
slh_dsa_sha2_128s_keygen_priv),
ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY,
slh_dsa_sha2_128s_keygen_pub),
ST_KAT_PARAM_END()
};
static const unsigned char slh_dsa_sig_msg[] = {
0x01, 0x02, 0x03, 0x04
};
static int deterministic = 1;
static const ST_KAT_PARAM slh_dsa_sig_params[] = {
ST_KAT_PARAM_INT(OSSL_SIGNATURE_PARAM_DETERMINISTIC, deterministic),
ST_KAT_PARAM_END()
};
static const unsigned char slh_dsa_sha2_128f_priv_pub[] = {
0xbb, 0xc7, 0x43, 0x06, 0xf7, 0x5d, 0xc2, 0xda, 0xf7, 0x37, 0x2b, 0x3c, 0x98, 0x41, 0xa4, 0xd6,
0x85, 0x2c, 0x17, 0xb4, 0x59, 0xf1, 0x69, 0x2b, 0x8e, 0x9a, 0x1a, 0x0d, 0xac, 0xe5, 0xba, 0x26,
0x38, 0x0c, 0x99, 0x30, 0x4a, 0x0d, 0xdd, 0x32, 0xf3, 0x44, 0xb9, 0x51, 0x44, 0xe1, 0xfd, 0xef,
0x60, 0xbb, 0xc2, 0x34, 0x0e, 0x08, 0x77, 0x0f, 0xb4, 0x1a, 0x80, 0xa7, 0x6c, 0xb0, 0x8e, 0x34,
};
static const ST_KAT_PARAM slh_dsa_shake_128f_key_params[] = {
ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PRIV_KEY, slh_dsa_sha2_128f_priv_pub),
ST_KAT_PARAM_END()
};
/* This is the SHA256 digest of the signature */
static const unsigned char slh_dsa_sha2_128s_sig_digest[] = {
0x64, 0x4b, 0x4b, 0xed, 0xc6, 0x21, 0x40, 0x5e,
0x95, 0x2d, 0xe1, 0x94, 0xf6, 0x36, 0x2c, 0xbc,
0x05, 0xf8, 0xb4, 0x9d, 0x66, 0xe0, 0xda, 0xfd,
0xe8, 0x24, 0xd5, 0x38, 0xe6, 0xbb, 0x5b, 0x3a,
};
static const unsigned char slh_dsa_shake_128f_sig_digest[] = {
0xb7, 0xeb, 0x1f, 0x00, 0x33, 0x41, 0xff, 0x11,
0x3f, 0xc7, 0x4d, 0xce, 0x90, 0x6c, 0x55, 0xf7,
0x4a, 0x54, 0x8b, 0x86, 0xc1, 0xb1, 0x08, 0x48,
0x89, 0x77, 0x00, 0x72, 0x03, 0x92, 0xd1, 0xa6,
};
#endif /* OPENSSL_NO_SLH_DSA */
/* Hash DRBG inputs for signature KATs */
static const unsigned char sig_kat_entropyin[] = {
0x06, 0x6d, 0xc8, 0xce, 0x75, 0xb2, 0x89, 0x66, 0xa6, 0x85, 0x16, 0x3f,
@ -2932,6 +3001,7 @@ static const ST_KAT_SIGN st_kat_sign_tests[] = {
ITM(dsa_expected_sig)
},
#endif /* OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_ML_DSA
{
OSSL_SELF_TEST_DESC_SIGN_ML_DSA,
@ -2946,6 +3016,26 @@ static const ST_KAT_SIGN st_kat_sign_tests[] = {
ml_dsa_sig_init
},
#endif /* OPENSSL_NO_ML_DSA */
#ifndef OPENSSL_NO_SLH_DSA
{
OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
"SLH-DSA-SHA2-128s", "SLH-DSA-SHA2-128s", SIGNATURE_MODE_SIG_DIGESTED,
slh_dsa_128_keygen_expected_params,
ITM(slh_dsa_sig_msg),
NULL, 0, NULL, 0, NULL, 0,
ITM(slh_dsa_sha2_128s_sig_digest),
slh_dsa_sig_params
},
{
OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
"SLH-DSA-SHAKE-128f", "SLH-DSA-SHAKE-128f", SIGNATURE_MODE_SIG_DIGESTED,
slh_dsa_shake_128f_key_params,
ITM(slh_dsa_sig_msg),
NULL, 0, NULL, 0, NULL, 0,
ITM(slh_dsa_shake_128f_sig_digest),
slh_dsa_sig_params
},
#endif /* OPENSSL_NO_SLH_DSA */
};
#if !defined(OPENSSL_NO_ML_DSA)
@ -2953,16 +3043,28 @@ static const ST_KAT_PARAM ml_dsa_keygen_params[] = {
ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_ML_DSA_SEED, sig_kat_entropyin),
ST_KAT_PARAM_END()
};
#endif
#if !defined(OPENSSL_NO_ML_DSA) || !defined(OPENSSL_NO_SLH_DSA)
static const ST_KAT_ASYM_KEYGEN st_kat_asym_keygen_tests[] = {
# if !defined(OPENSSL_NO_ML_DSA)
{
OSSL_SELF_TEST_DESC_KEYGEN_ML_DSA,
"ML-DSA-65",
ml_dsa_keygen_params,
ml_dsa_key
},
# endif
# if !defined(OPENSSL_NO_SLH_DSA)
{
OSSL_SELF_TEST_DESC_KEYGEN_SLH_DSA,
"SLH-DSA-SHA2-128s",
slh_dsa_sha2_128s_keygen_init_params,
slh_dsa_128_keygen_expected_params
},
# endif
};
#endif /* !OPENSSL_NO_ML_DSA */
#endif /* !OPENSSL_NO_ML_DSA || !OPENSSL_NO_SLH_DSA */
/*- KEM SELF TEST DATA */

View File

@ -448,6 +448,26 @@ err:
}
#endif /* !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC) */
static int digest_signature(const uint8_t *sig, size_t sig_len,
uint8_t *out, size_t *out_len,
OSSL_LIB_CTX *lib_ctx)
{
int ret;
unsigned int len = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
EVP_MD *md = EVP_MD_fetch(lib_ctx, "SHA256", NULL);
ret = ctx != NULL
&& md != NULL
&& EVP_DigestInit_ex(ctx, md, NULL) == 1
&& EVP_DigestUpdate(ctx, sig, sig_len) == 1
&& EVP_DigestFinal(ctx, out, &len) == 1;
EVP_MD_free(md);
EVP_MD_CTX_free(ctx);
*out_len = len;
return ret;
}
static int self_test_digest_sign(const ST_KAT_SIGN *t,
OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
{
@ -458,9 +478,9 @@ static int self_test_digest_sign(const ST_KAT_SIGN *t,
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY_CTX *fromctx = NULL;
EVP_PKEY *pkey = NULL;
unsigned char sig[MAX_ML_DSA_SIG_LEN];
unsigned char sig[MAX_ML_DSA_SIG_LEN], *psig = sig;
BN_CTX *bnctx = NULL;
size_t siglen = sizeof(sig);
size_t siglen;
int digested = 0;
const char *typ = OSSL_SELF_TEST_TYPE_KAT_SIGNATURE;
@ -516,8 +536,8 @@ static int self_test_digest_sign(const ST_KAT_SIGN *t,
digested = ((t->mode & SIGNATURE_MODE_DIGESTED) != 0);
if ((t->mode & SIGNATURE_MODE_VERIFY_ONLY) != 0) {
memcpy(sig, t->sig_expected, t->sig_expected_len);
siglen = t->sig_expected_len;
memcpy(psig, t->sig_expected, siglen);
} else {
if (digested) {
if (EVP_PKEY_sign_init_ex2(ctx, sigalg, paramsinit) <= 0)
@ -526,13 +546,35 @@ static int self_test_digest_sign(const ST_KAT_SIGN *t,
if (EVP_PKEY_sign_message_init(ctx, sigalg, paramsinit) <= 0)
goto err;
}
if (EVP_PKEY_sign(ctx, sig, &siglen, t->msg, t->msg_len) <= 0)
siglen = sizeof(sig);
if ((t->mode & SIGNATURE_MODE_SIG_DIGESTED) != 0) {
if (EVP_PKEY_sign(ctx, NULL, &siglen, t->msg, t->msg_len) <= 0)
goto err;
if (siglen > sizeof(sig)) {
psig = OPENSSL_malloc(siglen);
if (psig == NULL)
goto err;
}
}
if (EVP_PKEY_sign(ctx, psig, &siglen, t->msg, t->msg_len) <= 0)
goto err;
if (t->sig_expected != NULL
&& (siglen != t->sig_expected_len
|| memcmp(sig, t->sig_expected, t->sig_expected_len) != 0))
goto err;
if (t->sig_expected != NULL) {
if ((t->mode & SIGNATURE_MODE_SIG_DIGESTED) != 0) {
uint8_t digested_sig[EVP_MAX_MD_SIZE];
size_t digested_sig_len = 0;
if (!digest_signature(psig, siglen, digested_sig,
&digested_sig_len, libctx)
|| digested_sig_len != t->sig_expected_len
|| memcmp(digested_sig, t->sig_expected, t->sig_expected_len) != 0)
goto err;
} else {
if (siglen != t->sig_expected_len
|| memcmp(psig, t->sig_expected, t->sig_expected_len) != 0)
goto err;
}
}
}
if ((t->mode & SIGNATURE_MODE_SIGN_ONLY) == 0) {
@ -543,12 +585,14 @@ static int self_test_digest_sign(const ST_KAT_SIGN *t,
if (EVP_PKEY_verify_message_init(ctx, sigalg, paramsverify) <= 0)
goto err;
}
OSSL_SELF_TEST_oncorrupt_byte(st, sig);
if (EVP_PKEY_verify(ctx, sig, siglen, t->msg, t->msg_len) <= 0)
OSSL_SELF_TEST_oncorrupt_byte(st, psig);
if (EVP_PKEY_verify(ctx, psig, siglen, t->msg, t->msg_len) <= 0)
goto err;
}
ret = 1;
err:
if (psig != sig)
OPENSSL_free(psig);
BN_CTX_free(bnctx);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(fromctx);
@ -568,7 +612,7 @@ err:
return ret;
}
#ifndef OPENSSL_NO_ML_DSA
#if !defined(OPENSSL_NO_ML_DSA) || !defined(OPENSSL_NO_SLH_DSA)
/*
* Test that a deterministic key generation produces the correct key
*/
@ -1054,7 +1098,7 @@ static int setup_main_random(OSSL_LIB_CTX *libctx)
static int self_test_asym_keygens(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
{
#ifndef OPENSSL_NO_ML_DSA
#if !defined(OPENSSL_NO_ML_DSA) || !defined(OPENSSL_NO_SLH_DSA)
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_asym_keygen_tests); ++i) {

View File

@ -10,6 +10,7 @@
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include <openssl/self_test.h>
#include "crypto/slh_dsa.h"
#include "internal/param_build_set.h"
#include "prov/implementations.h"
@ -248,6 +249,54 @@ static void *slh_dsa_gen_init(void *provctx, int selection,
return gctx;
}
#ifdef FIPS_MODULE
/*
* Refer to FIPS 140-3 IG 10.3.A Additional Comment 1
* Perform a pairwise test for SLH_DSA by signing and verifying a signature.
*/
static int slh_dsa_fips140_pairwise_test(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *key,
OSSL_LIB_CTX *lib_ctx)
{
int ret = 0;
OSSL_SELF_TEST *st = NULL;
OSSL_CALLBACK *cb = NULL;
void *cb_arg = NULL;
uint8_t msg[16] = {0};
size_t msg_len = sizeof(msg);
uint8_t *sig = NULL;
size_t sig_len;
OSSL_SELF_TEST_get_callback(lib_ctx, &cb, &cb_arg);
st = OSSL_SELF_TEST_new(cb, cb_arg);
if (st == NULL)
return 0;
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
OSSL_SELF_TEST_DESC_PCT_SLH_DSA);
sig_len = ossl_slh_dsa_key_get_sig_len(key);
sig = OPENSSL_malloc(sig_len);
if (sig == NULL)
goto err;
if (ossl_slh_dsa_sign(ctx, key, msg, msg_len, NULL, 0, NULL, 0,
sig, &sig_len, sig_len) != 1)
goto err;
OSSL_SELF_TEST_oncorrupt_byte(st, sig);
if (ossl_slh_dsa_verify(ctx, key, msg, msg_len, NULL, 0, 0, sig, sig_len) != 1)
goto err;
ret = 1;
err:
OPENSSL_free(sig);
OSSL_SELF_TEST_onend(st, ret);
OSSL_SELF_TEST_free(st);
return ret;
}
#endif /* FIPS_MODULE */
static void *slh_dsa_gen(void *genctx, const char *alg)
{
struct slh_dsa_gen_ctx *gctx = genctx;
@ -265,6 +314,10 @@ static void *slh_dsa_gen(void *genctx, const char *alg)
if (!ossl_slh_dsa_generate_key(ctx, gctx->libctx,
gctx->entropy, gctx->entropy_len, key))
goto err;
#ifdef FIPS_MODULE
if (!slh_dsa_fips140_pairwise_test(ctx, key, gctx->libctx))
goto err;
#endif /* FIPS_MODULE */
ossl_slh_dsa_ctx_free(ctx);
return key;
err:

View File

@ -295,187 +295,3 @@ static const SLH_DSA_KEYGEN_TEST_DATA slh_dsa_keygen_testdata[] = {
SLH_DSA_KEYGEN_TEST_ITEM(slh_dsa_shake_256s_0, "SLH-DSA-SHAKE-256s"),
SLH_DSA_KEYGEN_TEST_ITEM(slh_dsa_shake_256f_0, "SLH-DSA-SHAKE-256f"),
};
/*
static const char pem_priv[] =
"-----BEGIN PRIVATE KEY-----\n"
"MFICAQAwCwYJYIZIAWUDBAMUBECg/HdWVy8wCPVEOZwlyeCHwoKHq1StsWAfys+F\n"
"wplaVEBPaQzZoUVRL2Hy5N6SktpxNx51SzwqefJHHhRgii40\n"
"-----END PRIVATE KEY-----\n";
static const char pem_cert[]=
"-----BEGIN CERTIFICATE-----\n"
"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\n"
"1rpNKWJK7upkPEgtkj67Ubs=\n"
"-----END CERTIFICATE-----\n";
*/

View File

@ -11,6 +11,7 @@
#include <openssl/evp.h>
#include <openssl/param_build.h>
#include <openssl/rand.h>
#include <openssl/pem.h>
#include "crypto/slh_dsa.h"
#include "internal/nelem.h"
#include "testutil.h"
@ -323,6 +324,144 @@ err:
return ret;
}
static int slh_dsa_usage_test(void)
{
int ret = 0;
EVP_CIPHER *cipher = NULL; /* Used to encrypt the private key */
char *pass = "Password";
BIO *pub_bio = NULL, *priv_bio = NULL;
EVP_PKEY_CTX *gctx = NULL, *sctx = NULL, *vctx = NULL;
EVP_PKEY *gkey = NULL, *pub = NULL, *priv = NULL;
EVP_SIGNATURE *sig_alg = NULL;
uint8_t *sig = NULL;
size_t sig_len = 0;
uint8_t msg[] = "Hello World";
size_t msg_len = sizeof(msg) - 1;
/* Generate a key */
if (!TEST_ptr(gctx = EVP_PKEY_CTX_new_from_name(lib_ctx, "SLH-DSA-SHA2-128s", NULL))
|| !TEST_int_eq(EVP_PKEY_keygen_init(gctx), 1)
|| !TEST_int_eq(EVP_PKEY_keygen(gctx, &gkey), 1))
goto err;
/* Save it to a BIO - it uses a mem bio for testing */
if (!TEST_ptr(pub_bio = BIO_new(BIO_s_mem()))
|| !TEST_ptr(priv_bio = BIO_new(BIO_s_mem()))
|| !TEST_ptr(cipher = EVP_CIPHER_fetch(lib_ctx, "AES-256-CBC", NULL))
|| !TEST_true(PEM_write_bio_PUBKEY_ex(pub_bio, gkey, lib_ctx, NULL))
|| !TEST_true(PEM_write_bio_PrivateKey_ex(priv_bio, gkey, cipher,
NULL, 0, NULL, (void *)pass,
lib_ctx, NULL)))
goto err;
/* Read the private key and add to a signing ctx */
if (!TEST_ptr(PEM_read_bio_PrivateKey_ex(priv_bio, &priv, NULL, pass, lib_ctx, NULL))
|| !TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, priv, NULL))
|| !TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, "SLH-DSA-SHA2-128s", NULL))
|| !TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, NULL), 1))
goto err;
/* Determine the size of the signature & allocate space */
if (!TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len), 1)
|| !TEST_ptr(sig = OPENSSL_malloc(sig_len))
|| !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len, msg, msg_len), 1))
goto err;
/* Read the public key and add to a verify ctx */
if (!TEST_ptr(PEM_read_bio_PUBKEY_ex(pub_bio, &pub, NULL, NULL, lib_ctx, NULL))
|| !TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pub, NULL)))
goto err;
/* verify the signature */
if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, NULL), 1)
|| !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1))
goto err;
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_SIGNATURE_free(sig_alg);
EVP_PKEY_free(gkey);
EVP_PKEY_free(pub);
EVP_PKEY_free(priv);
EVP_PKEY_CTX_free(gctx);
EVP_PKEY_CTX_free(sctx);
EVP_PKEY_CTX_free(vctx);
BIO_free(pub_bio);
BIO_free(priv_bio);
OPENSSL_free(sig);
return ret;
}
static int slh_dsa_deterministic_usage_test(void)
{
int ret = 0;
EVP_CIPHER *cipher = NULL; /* Used to encrypt the private key */
char *pass = "Password";
BIO *pub_bio = NULL, *priv_bio = NULL;
EVP_PKEY_CTX *gctx = NULL, *sctx = NULL, *vctx = NULL;
EVP_PKEY *gkey = NULL, *pub = NULL, *priv = NULL;
EVP_SIGNATURE *sig_alg = NULL;
uint8_t *sig = NULL;
size_t sig_len = 0;
uint8_t msg[] = { 0x01, 0x02, 0x03, 0x04 };
size_t msg_len = sizeof(msg);
const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[0];
size_t key_len = tst->priv_len / 2;
size_t n = key_len / 2;
int deterministic = 1;
OSSL_PARAM params[2], *p = params;
/* Generate a key */
if (!TEST_ptr(gkey = do_gen_key(tst->name, tst->priv, key_len + n)))
goto err;
/* Save it to a BIO - it uses a mem bio for testing */
if (!TEST_ptr(pub_bio = BIO_new(BIO_s_mem()))
|| !TEST_ptr(priv_bio = BIO_new(BIO_s_mem()))
|| !TEST_ptr(cipher = EVP_CIPHER_fetch(lib_ctx, "AES-256-CBC", NULL))
|| !TEST_true(PEM_write_bio_PUBKEY_ex(pub_bio, gkey, lib_ctx, NULL))
|| !TEST_true(PEM_write_bio_PrivateKey_ex(priv_bio, gkey, cipher,
NULL, 0, NULL, (void *)pass,
lib_ctx, NULL)))
goto err;
*p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_DETERMINISTIC, &deterministic);
*p = OSSL_PARAM_construct_end();
/* Read the private key and add to a signing ctx */
if (!TEST_ptr(PEM_read_bio_PrivateKey_ex(priv_bio, &priv, NULL, pass, lib_ctx, NULL))
|| !TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, priv, NULL))
/* Init the signature */
|| !TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, tst->name, NULL))
|| !TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, params), 1))
goto err;
/* Determine the size of the signature & allocate space */
if (!TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len), 1)
|| !TEST_ptr(sig = OPENSSL_malloc(sig_len))
|| !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len, msg, msg_len), 1))
goto err;
/* Read the public key and add to a verify ctx */
if (!TEST_ptr(PEM_read_bio_PUBKEY_ex(pub_bio, &pub, NULL, NULL, lib_ctx, NULL))
|| !TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pub, NULL)))
goto err;
/* verify the signature */
if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, NULL), 1)
|| !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1))
goto err;
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_SIGNATURE_free(sig_alg);
EVP_PKEY_free(gkey);
EVP_PKEY_free(pub);
EVP_PKEY_free(priv);
EVP_PKEY_CTX_free(gctx);
EVP_PKEY_CTX_free(sctx);
EVP_PKEY_CTX_free(vctx);
BIO_free(pub_bio);
BIO_free(priv_bio);
OPENSSL_free(sig);
return ret;
}
const OPTIONS *test_get_options(void)
{
static const OPTIONS options[] = {
@ -357,6 +496,8 @@ int setup_tests(void)
ADD_TEST(slh_dsa_bad_pub_len_test);
ADD_TEST(slh_dsa_key_validate_test);
ADD_TEST(slh_dsa_key_eq_test);
ADD_TEST(slh_dsa_usage_test);
ADD_TEST(slh_dsa_deterministic_usage_test);
ADD_ALL_TESTS(slh_dsa_sign_verify_test, OSSL_NELEM(slh_dsa_sig_testdata));
ADD_ALL_TESTS(slh_dsa_keygen_test, OSSL_NELEM(slh_dsa_keygen_testdata));
return 1;