/* * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ #include #include #include #include #include #include "crypto/slh_dsa.h" #include "internal/nelem.h" #include "testutil.h" #include "slh_dsa.inc" typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_CONFIG_FILE, OPT_TEST_ENUM } OPTION_CHOICE; static OSSL_LIB_CTX *lib_ctx = NULL; static OSSL_PROVIDER *null_prov = NULL; static OSSL_PROVIDER *lib_prov = NULL; static EVP_PKEY *slh_dsa_key_from_data(const char *alg, const unsigned char *data, size_t datalen, int public) { int ret; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *key = NULL; OSSL_PARAM params[2]; const char *keytype = public ? OSSL_PKEY_PARAM_PUB_KEY : OSSL_PKEY_PARAM_PRIV_KEY; int selection = public ? EVP_PKEY_PUBLIC_KEY : EVP_PKEY_KEYPAIR; params[0] = OSSL_PARAM_construct_octet_string(keytype, (uint8_t *)data, datalen); params[1] = OSSL_PARAM_construct_end(); ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, alg, NULL)) && TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1) && (EVP_PKEY_fromdata(ctx, &key, selection, params) == 1); if (ret == 0) { EVP_PKEY_free(key); key = NULL; } EVP_PKEY_CTX_free(ctx); return key; } static int slh_dsa_create_keypair(EVP_PKEY **pkey, const char *name, const uint8_t *priv, size_t priv_len, const uint8_t *pub, size_t pub_len) { int ret = 0; EVP_PKEY_CTX *ctx = NULL; OSSL_PARAM_BLD *bld = NULL; OSSL_PARAM *params = NULL; const char *pub_name = OSSL_PKEY_PARAM_PUB_KEY; if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) || !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv, priv_len) > 0) || !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld, pub_name, pub, pub_len) > 0) || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)) || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, name, NULL)) || !TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1) || !TEST_int_eq(EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_KEYPAIR, params), 1)) goto err; ret = 1; err: OSSL_PARAM_free(params); OSSL_PARAM_BLD_free(bld); EVP_PKEY_CTX_free(ctx); return ret; } static int slh_dsa_bad_pub_len_test(void) { int ret = 0; SLH_DSA_SIG_TEST_DATA *td = &slh_dsa_sig_testdata[0]; EVP_PKEY *pkey = NULL; size_t pub_len = 0; unsigned char pubdata[64 + 1]; if (!TEST_size_t_le(td->pub_len, sizeof(pubdata))) goto end; OPENSSL_cleanse(pubdata, sizeof(pubdata)); memcpy(pubdata, td->pub, td->pub_len); if (!TEST_ptr_null(pkey = slh_dsa_key_from_data(td->alg, pubdata, td->pub_len - 1, 1)) || !TEST_ptr_null(pkey = slh_dsa_key_from_data(td->alg, pubdata, td->pub_len + 1, 1))) goto end; ret = 1; end: if (ret == 0) TEST_note("Incorrectly accepted public key of length %u (expected %u)", (unsigned)pub_len, (unsigned)td->pub_len); EVP_PKEY_free(pkey); return ret == 1; } static int slh_dsa_key_eq_test(void) { int ret = 0; size_t i; EVP_PKEY *key[4] = { NULL, NULL, NULL, NULL }; SLH_DSA_SIG_TEST_DATA *td1 = &slh_dsa_sig_testdata[0]; SLH_DSA_SIG_TEST_DATA *td2 = &slh_dsa_sig_testdata[1]; #ifndef OPENSSL_NO_EC EVP_PKEY *eckey = NULL; #endif if (!TEST_ptr(key[0] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1)) || !TEST_ptr(key[1] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1)) || !TEST_ptr(key[2] = slh_dsa_key_from_data(td2->alg, td2->pub, td2->pub_len, 1)) || !TEST_ptr(key[3] = EVP_PKEY_dup(key[0]))) goto end; if (!TEST_int_eq(EVP_PKEY_eq(key[0], key[1]), 1) || !TEST_int_ne(EVP_PKEY_eq(key[0], key[2]), 1) || !TEST_int_eq(EVP_PKEY_eq(key[0], key[3]), 1)) goto end; #ifndef OPENSSL_NO_EC if (!TEST_ptr(eckey = EVP_PKEY_Q_keygen(lib_ctx, NULL, "EC", "P-256"))) goto end; ret = TEST_int_ne(EVP_PKEY_eq(key[0], eckey), 1); EVP_PKEY_free(eckey); #else ret = 1; #endif end: for (i = 0; i < OSSL_NELEM(key); ++i) EVP_PKEY_free(key[i]); return ret; } static int slh_dsa_key_validate_test(void) { int ret = 0; SLH_DSA_SIG_TEST_DATA *td = &slh_dsa_sig_testdata[0]; EVP_PKEY_CTX *vctx = NULL; EVP_PKEY *key = NULL; if (!TEST_ptr(key = slh_dsa_key_from_data(td->alg, td->pub, td->pub_len, 1))) return 0; if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL))) goto end; if (!TEST_int_eq(EVP_PKEY_public_check(vctx), 1)) goto end; if (!TEST_int_eq(EVP_PKEY_private_check(vctx), 0)) goto end; if (!TEST_int_eq(EVP_PKEY_pairwise_check(vctx), 0)) goto end; ret = 1; end: EVP_PKEY_CTX_free(vctx); EVP_PKEY_free(key); return ret; } static int slh_dsa_key_validate_failure_test(void) { int ret = 0; EVP_PKEY_CTX *vctx = NULL; EVP_PKEY *key = NULL; /* * Loading 128s private key data into a 128f algorithm will have an incorrect * public key. */ if (!TEST_ptr(key = slh_dsa_key_from_data("SLH-DSA-SHA2-128f", slh_dsa_sha2_128s_0_keygen_priv, sizeof(slh_dsa_sha2_128s_0_keygen_priv), 0))) return 0; if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL))) goto end; if (!TEST_int_eq(EVP_PKEY_pairwise_check(vctx), 0)) goto end; ret = 1; end: EVP_PKEY_CTX_free(vctx); EVP_PKEY_free(key); return ret; } /* * Rather than having to store the full signature into a file, we just do a * verify using the output of a sign. The sign test already does a Known answer * test (KAT) using the digest of the signature, so this should be sufficient to * run as a KAT for the verify. */ static int do_slh_dsa_verify(const SLH_DSA_SIG_TEST_DATA *td, uint8_t *sig, size_t sig_len) { int ret = 0; EVP_PKEY_CTX *vctx = NULL; EVP_PKEY *key = NULL; EVP_SIGNATURE *sig_alg = NULL; OSSL_PARAM params[2], *p = params; int encode = 0; *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode); *p = OSSL_PARAM_construct_end(); if (!TEST_ptr(key = slh_dsa_key_from_data(td->alg, td->pub, td->pub_len, 1))) return 0; if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL))) goto err; if (!TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, td->alg, NULL))) goto err; if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, params), 1) || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, td->msg, td->msg_len), 1)) goto err; ret = 1; err: EVP_SIGNATURE_free(sig_alg); EVP_PKEY_free(key); EVP_PKEY_CTX_free(vctx); return ret; } static int slh_dsa_sign_verify_test(int tst_id) { int ret = 0; SLH_DSA_SIG_TEST_DATA *td = &slh_dsa_sig_testdata[tst_id]; EVP_PKEY_CTX *sctx = NULL; EVP_PKEY *pkey = NULL; EVP_SIGNATURE *sig_alg = NULL; OSSL_PARAM params[4], *p = params; uint8_t *psig = NULL; size_t psig_len = 0, sig_len2 = 0; uint8_t digest[32]; size_t digest_len = sizeof(digest); int encode = 0, deterministic = 1; *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_DETERMINISTIC, &deterministic); *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode); if (td->add_random != NULL) *p++ = OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_TEST_ENTROPY, (char *)td->add_random, td->add_random_len); *p = OSSL_PARAM_construct_end(); /* * This just uses from data here, but keygen also works. * The keygen path is tested via slh_dsa_keygen_test */ if (!slh_dsa_create_keypair(&pkey, td->alg, td->priv, td->priv_len, td->pub, td->pub_len)) goto err; if (!TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pkey, NULL))) goto err; if (!TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, td->alg, NULL))) goto err; if (!TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, params), 1) || !TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &psig_len, td->msg, td->msg_len), 1) || !TEST_true(EVP_PKEY_get_size_t_param(pkey, OSSL_PKEY_PARAM_MAX_SIZE, &sig_len2)) || !TEST_int_eq(sig_len2, psig_len) || !TEST_ptr(psig = OPENSSL_zalloc(psig_len)) || !TEST_int_eq(EVP_PKEY_sign(sctx, psig, &psig_len, td->msg, td->msg_len), 1)) goto err; if (!TEST_int_eq(EVP_Q_digest(lib_ctx, "SHA256", NULL, psig, psig_len, digest, &digest_len), 1)) goto err; if (!TEST_mem_eq(digest, digest_len, td->sig_digest, td->sig_digest_len)) goto err; if (!do_slh_dsa_verify(td, psig, psig_len)) goto err; ret = 1; err: EVP_SIGNATURE_free(sig_alg); EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(sctx); OPENSSL_free(psig); return ret; } static EVP_PKEY *do_gen_key(const char *alg, const uint8_t *seed, size_t seed_len) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; OSSL_PARAM params[2], *p = params; if (seed_len != 0) *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED, (char *)seed, seed_len); *p = OSSL_PARAM_construct_end(); if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, alg, NULL)) || !TEST_int_eq(EVP_PKEY_keygen_init(ctx), 1) || !TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 1) || !TEST_int_eq(EVP_PKEY_generate(ctx, &pkey), 1)) pkey = NULL; EVP_PKEY_CTX_free(ctx); return pkey; } static int slh_dsa_keygen_test(int tst_id) { int ret = 0; const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[tst_id]; EVP_PKEY *pkey = NULL; uint8_t priv[64 * 2], pub[32 * 2]; size_t priv_len, pub_len; size_t key_len = tst->priv_len; size_t n = key_len / 4; int bits = 0, sec_bits = 0, sig_len = 0; if (!TEST_ptr(pkey = do_gen_key(tst->name, tst->priv, key_len - n))) goto err; if (!TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, priv, sizeof(priv), &priv_len))) goto err; if (!TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, pub, sizeof(pub), &pub_len))) goto err; if (!TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_BITS, &bits)) || !TEST_int_eq(bits, 8 * 2 * n) || !TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_SECURITY_BITS, &sec_bits)) || !TEST_int_eq(sec_bits, 8 * n) || !TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_MAX_SIZE, &sig_len)) || !TEST_int_ge(sig_len, 7856) || !TEST_int_le(sig_len, 49856)) goto err; if (!TEST_size_t_eq(priv_len, key_len) || !TEST_size_t_eq(pub_len, key_len / 2)) goto err; if (!TEST_mem_eq(pub, pub_len, tst->priv + 2 * n, 2 * n)) goto err; ret = 1; err: EVP_PKEY_free(pkey); 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; if (!TEST_true(EVP_PKEY_pairwise_check(sctx)) || !TEST_true(EVP_PKEY_public_check(sctx)) || !TEST_true(EVP_PKEY_private_check(sctx))) 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, *dupctx = NULL; EVP_PKEY *gkey = NULL, *pub = NULL, *priv = NULL; EVP_SIGNATURE *sig_alg = NULL; uint8_t *sig = NULL; size_t sig_len = 0, 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; if (!TEST_ptr(dupctx = EVP_PKEY_CTX_dup(sctx))) 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)) goto err; len = sig_len; if (!TEST_ptr(sig = OPENSSL_zalloc(sig_len * 2)) || !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &len, msg, msg_len), 1) || !TEST_size_t_eq(sig_len, len) || !TEST_int_eq(EVP_PKEY_sign(dupctx, sig + sig_len, &len, msg, msg_len), 1) || !TEST_size_t_eq(sig_len, len)) 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; EVP_PKEY_CTX_free(dupctx); /* verify the signature */ if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, NULL), 1) || !TEST_ptr(dupctx = EVP_PKEY_CTX_dup(vctx)) || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1) || !TEST_int_eq(EVP_PKEY_verify(dupctx, sig + sig_len, 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); EVP_PKEY_CTX_free(dupctx); BIO_free(pub_bio); BIO_free(priv_bio); OPENSSL_free(sig); return ret; } static int slh_dsa_digest_sign_verify_test(void) { int ret = 0; EVP_PKEY *key = NULL; uint8_t *sig = NULL; size_t sig_len = 0; OSSL_PARAM params[3], *p = params; const char *alg = "SLH-DSA-SHA2-128s"; EVP_MD_CTX *mctx = NULL; static uint8_t context[] = "A context String"; static uint8_t msg[] = "Hello World"; size_t msg_len = sizeof(msg); if (!TEST_ptr(key = do_gen_key(alg, NULL, 0))) goto err; *p++ = OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, context, sizeof(context)); *p++ = OSSL_PARAM_construct_end(); if (!TEST_ptr(mctx = EVP_MD_CTX_new()) || !TEST_int_eq(EVP_DigestSignInit_ex(mctx, NULL, "SHA256", lib_ctx, "?fips=true", key, params), 0) || !TEST_int_eq(EVP_DigestSignInit_ex(mctx, NULL, NULL, lib_ctx, "?fips=true", key, params), 1)) goto err; if (!TEST_int_eq(EVP_DigestSign(mctx, NULL, &sig_len, msg, msg_len), 1) || !TEST_ptr(sig = OPENSSL_zalloc(sig_len))) goto err; sig_len--; if (!TEST_int_eq(EVP_DigestSign(mctx, sig, &sig_len, msg, msg_len), 0)) goto err; sig_len++; if (!TEST_int_eq(EVP_DigestSignInit_ex(mctx, NULL, NULL, lib_ctx, "?fips=true", key, params), 1) || !TEST_int_eq(EVP_DigestSign(mctx, sig, &sig_len, msg, msg_len), 1) || !TEST_int_eq(EVP_DigestVerifyInit_ex(mctx, NULL, "SHA256", lib_ctx, "?fips=true", key, params), 0) || !TEST_int_eq(EVP_DigestVerifyInit_ex(mctx, NULL, NULL, lib_ctx, "?fips=true", key, params), 1) || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, msg, msg_len), 1)) goto err; ret = 1; err: EVP_PKEY_free(key); EVP_MD_CTX_free(mctx); OPENSSL_free(sig); return ret; } static int slh_dsa_keygen_invalid_test(void) { int ret = 0; const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[0]; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; OSSL_PARAM params[2], *p = params; size_t key_len = tst->priv_len; size_t n = key_len / 4; uint8_t seed[128] = {0}; if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, tst->name, NULL)) || !TEST_int_eq(EVP_PKEY_keygen_init(ctx), 1)) goto err; /* Test the set fails if the seed is larger than the internal buffer */ p[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED, seed, 97); p[1] = OSSL_PARAM_construct_end(); if (!TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 0)) goto err; /* Test the generate fails if the seed is not the correct size */ p[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED, seed, n * 3 - 1); p[1] = OSSL_PARAM_construct_end(); if (!TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 1) || !TEST_int_eq(EVP_PKEY_generate(ctx, &pkey), 0)) goto err; /* Test the generate fails if the seed is not the correct size */ p[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED, seed, n * 3 + 1); p[1] = OSSL_PARAM_construct_end(); if (!TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 1) || !TEST_int_eq(EVP_PKEY_generate(ctx, &pkey), 0)) goto err; ret = 1; err: EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); return ret; } const OPTIONS *test_get_options(void) { static const OPTIONS options[] = { OPT_TEST_OPTIONS_DEFAULT_USAGE, { "config", OPT_CONFIG_FILE, '<', "The configuration file to use for the libctx" }, { NULL } }; return options; } int setup_tests(void) { OPTION_CHOICE o; char *config_file = NULL; while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_CONFIG_FILE: config_file = opt_arg(); break; case OPT_TEST_CASES: break; default: case OPT_ERR: return 0; } } if (!test_get_libctx(&lib_ctx, &null_prov, config_file, &lib_prov, NULL)) return 0; ADD_TEST(slh_dsa_bad_pub_len_test); ADD_TEST(slh_dsa_key_validate_test); ADD_TEST(slh_dsa_key_validate_failure_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)); ADD_TEST(slh_dsa_digest_sign_verify_test); ADD_TEST(slh_dsa_keygen_invalid_test); return 1; } void cleanup_tests(void) { OSSL_PROVIDER_unload(null_prov); OSSL_PROVIDER_unload(lib_prov); OSSL_LIB_CTX_free(lib_ctx); }