# 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"
# 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"
# 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);
#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 {
};
#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,
ITM(dsa_expected_sig)
},
#endif /* OPENSSL_NO_DSA */
+
#ifndef OPENSSL_NO_ML_DSA
{
OSSL_SELF_TEST_DESC_SIGN_ML_DSA,
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)
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 */
}
#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)
{
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;
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)
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) {
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);
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
*/
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) {
#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"
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;
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:
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";
-*/
#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"
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[] = {
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;