Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <openssl/core_names.h>
     11 #include <openssl/evp.h>
     12 #include <openssl/param_build.h>
     13 #include <openssl/rand.h>
     14 #include <openssl/pem.h>
     15 #include "crypto/slh_dsa.h"
     16 #include "internal/nelem.h"
     17 #include "testutil.h"
     18 #include "slh_dsa.inc"
     19 
     20 typedef enum OPTION_choice {
     21     OPT_ERR = -1,
     22     OPT_EOF = 0,
     23     OPT_CONFIG_FILE,
     24     OPT_TEST_ENUM
     25 } OPTION_CHOICE;
     26 
     27 static OSSL_LIB_CTX *lib_ctx = NULL;
     28 static OSSL_PROVIDER *null_prov = NULL;
     29 static OSSL_PROVIDER *lib_prov = NULL;
     30 
     31 static EVP_PKEY *slh_dsa_key_from_data(const char *alg,
     32     const unsigned char *data, size_t datalen,
     33     int public)
     34 {
     35     int ret;
     36     EVP_PKEY_CTX *ctx = NULL;
     37     EVP_PKEY *key = NULL;
     38     OSSL_PARAM params[2];
     39     const char *keytype = public ? OSSL_PKEY_PARAM_PUB_KEY : OSSL_PKEY_PARAM_PRIV_KEY;
     40     int selection = public ? EVP_PKEY_PUBLIC_KEY : EVP_PKEY_KEYPAIR;
     41 
     42     params[0] = OSSL_PARAM_construct_octet_string(keytype, (uint8_t *)data, datalen);
     43     params[1] = OSSL_PARAM_construct_end();
     44     ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, alg, NULL))
     45         && TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
     46         && (EVP_PKEY_fromdata(ctx, &key, selection, params) == 1);
     47     if (ret == 0) {
     48         EVP_PKEY_free(key);
     49         key = NULL;
     50     }
     51     EVP_PKEY_CTX_free(ctx);
     52     return key;
     53 }
     54 
     55 static int slh_dsa_create_keypair(EVP_PKEY **pkey, const char *name,
     56     const uint8_t *priv, size_t priv_len,
     57     const uint8_t *pub, size_t pub_len)
     58 {
     59     int ret = 0;
     60     EVP_PKEY_CTX *ctx = NULL;
     61     OSSL_PARAM_BLD *bld = NULL;
     62     OSSL_PARAM *params = NULL;
     63     const char *pub_name = OSSL_PKEY_PARAM_PUB_KEY;
     64 
     65     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
     66         || !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld,
     67                           OSSL_PKEY_PARAM_PRIV_KEY,
     68                           priv, priv_len)
     69             > 0)
     70         || !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld,
     71                           pub_name,
     72                           pub, pub_len)
     73             > 0)
     74         || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
     75         || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, name, NULL))
     76         || !TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
     77         || !TEST_int_eq(EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_KEYPAIR,
     78                             params),
     79             1))
     80         goto err;
     81 
     82     ret = 1;
     83 err:
     84     OSSL_PARAM_free(params);
     85     OSSL_PARAM_BLD_free(bld);
     86     EVP_PKEY_CTX_free(ctx);
     87     return ret;
     88 }
     89 
     90 static int slh_dsa_bad_pub_len_test(void)
     91 {
     92     int ret = 0;
     93     SLH_DSA_SIG_TEST_DATA *td = &slh_dsa_sig_testdata[0];
     94     EVP_PKEY *pkey = NULL;
     95     size_t pub_len = 0;
     96     unsigned char pubdata[64 + 1];
     97 
     98     if (!TEST_size_t_le(td->pub_len, sizeof(pubdata)))
     99         goto end;
    100 
    101     OPENSSL_cleanse(pubdata, sizeof(pubdata));
    102     memcpy(pubdata, td->pub, td->pub_len);
    103 
    104     if (!TEST_ptr_null(pkey = slh_dsa_key_from_data(td->alg, pubdata,
    105                            td->pub_len - 1, 1))
    106         || !TEST_ptr_null(pkey = slh_dsa_key_from_data(td->alg, pubdata,
    107                               td->pub_len + 1, 1)))
    108         goto end;
    109 
    110     ret = 1;
    111 end:
    112     if (ret == 0)
    113         TEST_note("Incorrectly accepted public key of length %u (expected %u)",
    114             (unsigned)pub_len, (unsigned)td->pub_len);
    115     EVP_PKEY_free(pkey);
    116     return ret == 1;
    117 }
    118 
    119 static int slh_dsa_key_eq_test(void)
    120 {
    121     int ret = 0;
    122     size_t i;
    123     EVP_PKEY *key[4] = { NULL, NULL, NULL, NULL };
    124     SLH_DSA_SIG_TEST_DATA *td1 = &slh_dsa_sig_testdata[0];
    125     SLH_DSA_SIG_TEST_DATA *td2 = &slh_dsa_sig_testdata[1];
    126 #ifndef OPENSSL_NO_EC
    127     EVP_PKEY *eckey = NULL;
    128 #endif
    129 
    130     if (!TEST_ptr(key[0] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1))
    131         || !TEST_ptr(key[1] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1))
    132         || !TEST_ptr(key[2] = slh_dsa_key_from_data(td2->alg, td2->pub, td2->pub_len, 1))
    133         || !TEST_ptr(key[3] = EVP_PKEY_dup(key[0])))
    134         goto end;
    135 
    136     if (!TEST_int_eq(EVP_PKEY_eq(key[0], key[1]), 1)
    137         || !TEST_int_ne(EVP_PKEY_eq(key[0], key[2]), 1)
    138         || !TEST_int_eq(EVP_PKEY_eq(key[0], key[3]), 1))
    139         goto end;
    140 
    141 #ifndef OPENSSL_NO_EC
    142     if (!TEST_ptr(eckey = EVP_PKEY_Q_keygen(lib_ctx, NULL, "EC", "P-256")))
    143         goto end;
    144     ret = TEST_int_ne(EVP_PKEY_eq(key[0], eckey), 1);
    145     EVP_PKEY_free(eckey);
    146 #else
    147     ret = 1;
    148 #endif
    149 end:
    150     for (i = 0; i < OSSL_NELEM(key); ++i)
    151         EVP_PKEY_free(key[i]);
    152     return ret;
    153 }
    154 
    155 static int slh_dsa_key_validate_test(void)
    156 {
    157     int ret = 0;
    158     SLH_DSA_SIG_TEST_DATA *td = &slh_dsa_sig_testdata[0];
    159     EVP_PKEY_CTX *vctx = NULL;
    160     EVP_PKEY *key = NULL;
    161 
    162     if (!TEST_ptr(key = slh_dsa_key_from_data(td->alg, td->pub, td->pub_len, 1)))
    163         return 0;
    164     if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL)))
    165         goto end;
    166     if (!TEST_int_eq(EVP_PKEY_public_check(vctx), 1))
    167         goto end;
    168     if (!TEST_int_eq(EVP_PKEY_private_check(vctx), 0))
    169         goto end;
    170     if (!TEST_int_eq(EVP_PKEY_pairwise_check(vctx), 0))
    171         goto end;
    172     ret = 1;
    173 end:
    174     EVP_PKEY_CTX_free(vctx);
    175     EVP_PKEY_free(key);
    176     return ret;
    177 }
    178 
    179 static int slh_dsa_key_validate_failure_test(void)
    180 {
    181     int ret = 0;
    182     EVP_PKEY_CTX *vctx = NULL;
    183     EVP_PKEY *key = NULL;
    184 
    185     /*
    186      * Loading 128s private key data into a 128f algorithm will have an incorrect
    187      * public key.
    188      */
    189     key = slh_dsa_key_from_data("SLH-DSA-SHA2-128f",
    190         slh_dsa_sha2_128s_0_keygen_priv,
    191         sizeof(slh_dsa_sha2_128s_0_keygen_priv), 0);
    192     if (!TEST_ptr(key))
    193         goto end;
    194     if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL)))
    195         goto end;
    196     if (!TEST_int_eq(EVP_PKEY_pairwise_check(vctx), 0))
    197         goto end;
    198     ret = 1;
    199 end:
    200     EVP_PKEY_CTX_free(vctx);
    201     EVP_PKEY_free(key);
    202     return ret;
    203 }
    204 
    205 /*
    206  * Rather than having to store the full signature into a file, we just do a
    207  * verify using the output of a sign. The sign test already does a Known answer
    208  * test (KAT) using the digest of the signature, so this should be sufficient to
    209  * run as a KAT for the verify.
    210  */
    211 static int do_slh_dsa_verify(const SLH_DSA_SIG_TEST_DATA *td,
    212     uint8_t *sig, size_t sig_len)
    213 {
    214     int ret = 0;
    215     EVP_PKEY_CTX *vctx = NULL;
    216     EVP_PKEY *key = NULL;
    217     EVP_SIGNATURE *sig_alg = NULL;
    218     OSSL_PARAM params[2], *p = params;
    219     int encode = 0;
    220 
    221     *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode);
    222     *p = OSSL_PARAM_construct_end();
    223 
    224     if (!TEST_ptr(key = slh_dsa_key_from_data(td->alg, td->pub, td->pub_len, 1)))
    225         return 0;
    226     if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL)))
    227         goto err;
    228     if (!TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, td->alg, NULL)))
    229         goto err;
    230     if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, params), 1)
    231         || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len,
    232                             td->msg, td->msg_len),
    233             1))
    234         goto err;
    235     ret = 1;
    236 err:
    237     EVP_SIGNATURE_free(sig_alg);
    238     EVP_PKEY_free(key);
    239     EVP_PKEY_CTX_free(vctx);
    240     return ret;
    241 }
    242 
    243 static int slh_dsa_sign_verify_test(int tst_id)
    244 {
    245     int ret = 0;
    246     SLH_DSA_SIG_TEST_DATA *td = &slh_dsa_sig_testdata[tst_id];
    247     EVP_PKEY_CTX *sctx = NULL;
    248     EVP_PKEY *pkey = NULL;
    249     EVP_SIGNATURE *sig_alg = NULL;
    250     OSSL_PARAM params[4], *p = params;
    251     uint8_t *psig = NULL;
    252     size_t psig_len = 0, sig_len2 = 0;
    253     uint8_t digest[32];
    254     size_t digest_len = sizeof(digest);
    255     int encode = 0, deterministic = 1;
    256 
    257     *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_DETERMINISTIC, &deterministic);
    258     *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode);
    259     if (td->add_random != NULL)
    260         *p++ = OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_TEST_ENTROPY,
    261             (char *)td->add_random,
    262             td->add_random_len);
    263     *p = OSSL_PARAM_construct_end();
    264 
    265     /*
    266      * This just uses from data here, but keygen also works.
    267      * The keygen path is tested via slh_dsa_keygen_test
    268      */
    269     if (!slh_dsa_create_keypair(&pkey, td->alg, td->priv, td->priv_len,
    270             td->pub, td->pub_len))
    271         goto err;
    272 
    273     if (!TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pkey, NULL)))
    274         goto err;
    275     if (!TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, td->alg, NULL)))
    276         goto err;
    277     if (!TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, params), 1)
    278         || !TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &psig_len,
    279                             td->msg, td->msg_len),
    280             1)
    281         || !TEST_true(EVP_PKEY_get_size_t_param(pkey, OSSL_PKEY_PARAM_MAX_SIZE,
    282             &sig_len2))
    283         || !TEST_int_eq(sig_len2, psig_len)
    284         || !TEST_ptr(psig = OPENSSL_zalloc(psig_len))
    285         || !TEST_int_eq(EVP_PKEY_sign(sctx, psig, &psig_len,
    286                             td->msg, td->msg_len),
    287             1))
    288         goto err;
    289     if (!TEST_int_eq(EVP_Q_digest(lib_ctx, "SHA256", NULL, psig, psig_len,
    290                          digest, &digest_len),
    291             1))
    292         goto err;
    293     if (!TEST_mem_eq(digest, digest_len, td->sig_digest, td->sig_digest_len))
    294         goto err;
    295     if (!do_slh_dsa_verify(td, psig, psig_len))
    296         goto err;
    297     ret = 1;
    298 err:
    299     EVP_SIGNATURE_free(sig_alg);
    300     EVP_PKEY_free(pkey);
    301     EVP_PKEY_CTX_free(sctx);
    302     OPENSSL_free(psig);
    303     return ret;
    304 }
    305 
    306 static EVP_PKEY *do_gen_key(const char *alg,
    307     const uint8_t *seed, size_t seed_len)
    308 {
    309     EVP_PKEY *pkey = NULL;
    310     EVP_PKEY_CTX *ctx = NULL;
    311     OSSL_PARAM params[2], *p = params;
    312 
    313     if (seed_len != 0)
    314         *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED,
    315             (char *)seed, seed_len);
    316     *p = OSSL_PARAM_construct_end();
    317 
    318     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, alg, NULL))
    319         || !TEST_int_eq(EVP_PKEY_keygen_init(ctx), 1)
    320         || !TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 1)
    321         || !TEST_int_eq(EVP_PKEY_generate(ctx, &pkey), 1))
    322         pkey = NULL;
    323 
    324     EVP_PKEY_CTX_free(ctx);
    325     return pkey;
    326 }
    327 
    328 static int slh_dsa_keygen_test(int tst_id)
    329 {
    330     int ret = 0;
    331     const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[tst_id];
    332     EVP_PKEY *pkey = NULL;
    333     uint8_t priv[64 * 2], pub[32 * 2];
    334     size_t priv_len, pub_len;
    335     size_t key_len = tst->priv_len;
    336     size_t n = key_len / 4;
    337     int bits = 0, sec_bits = 0, sig_len = 0;
    338 
    339     if (!TEST_ptr(pkey = do_gen_key(tst->name, tst->priv, key_len - n)))
    340         goto err;
    341 
    342     if (!TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
    343             priv, sizeof(priv), &priv_len)))
    344         goto err;
    345     if (!TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
    346             pub, sizeof(pub), &pub_len)))
    347         goto err;
    348     if (!TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_BITS, &bits))
    349         || !TEST_int_eq(bits, 8 * 2 * n)
    350         || !TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_SECURITY_BITS,
    351             &sec_bits))
    352         || !TEST_int_eq(sec_bits, 8 * n)
    353         || !TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_MAX_SIZE,
    354             &sig_len))
    355         || !TEST_int_ge(sig_len, 7856)
    356         || !TEST_int_le(sig_len, 49856))
    357         goto err;
    358 
    359     if (!TEST_size_t_eq(priv_len, key_len)
    360         || !TEST_size_t_eq(pub_len, key_len / 2))
    361         goto err;
    362     if (!TEST_mem_eq(pub, pub_len, tst->priv + 2 * n, 2 * n))
    363         goto err;
    364     ret = 1;
    365 err:
    366     EVP_PKEY_free(pkey);
    367     return ret;
    368 }
    369 
    370 static int slh_dsa_usage_test(void)
    371 {
    372     int ret = 0;
    373     EVP_CIPHER *cipher = NULL; /* Used to encrypt the private key */
    374     char *pass = "Password";
    375     BIO *pub_bio = NULL, *priv_bio = NULL;
    376     EVP_PKEY_CTX *gctx = NULL, *sctx = NULL, *vctx = NULL;
    377     EVP_PKEY *gkey = NULL, *pub = NULL, *priv = NULL;
    378     EVP_SIGNATURE *sig_alg = NULL;
    379     uint8_t *sig = NULL;
    380     size_t sig_len = 0;
    381     uint8_t msg[] = "Hello World";
    382     size_t msg_len = sizeof(msg) - 1;
    383 
    384     /* Generate a key */
    385     if (!TEST_ptr(gctx = EVP_PKEY_CTX_new_from_name(lib_ctx, "SLH-DSA-SHA2-128s", NULL))
    386         || !TEST_int_eq(EVP_PKEY_keygen_init(gctx), 1)
    387         || !TEST_int_eq(EVP_PKEY_keygen(gctx, &gkey), 1))
    388         goto err;
    389 
    390     /* Save it to a BIO - it uses a mem bio for testing */
    391     if (!TEST_ptr(pub_bio = BIO_new(BIO_s_mem()))
    392         || !TEST_ptr(priv_bio = BIO_new(BIO_s_mem()))
    393         || !TEST_ptr(cipher = EVP_CIPHER_fetch(lib_ctx, "AES-256-CBC", NULL))
    394         || !TEST_true(PEM_write_bio_PUBKEY_ex(pub_bio, gkey, lib_ctx, NULL))
    395         || !TEST_true(PEM_write_bio_PrivateKey_ex(priv_bio, gkey, cipher,
    396             NULL, 0, NULL, (void *)pass,
    397             lib_ctx, NULL)))
    398         goto err;
    399 
    400     /* Read the private key and add to a signing ctx */
    401     if (!TEST_ptr(PEM_read_bio_PrivateKey_ex(priv_bio, &priv, NULL, pass, lib_ctx, NULL))
    402         || !TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, priv, NULL))
    403         || !TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, "SLH-DSA-SHA2-128s", NULL))
    404         || !TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, NULL), 1))
    405         goto err;
    406     /* Determine the size of the signature & allocate space */
    407     if (!TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len), 1)
    408         || !TEST_ptr(sig = OPENSSL_malloc(sig_len))
    409         || !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len, msg, msg_len), 1))
    410         goto err;
    411     if (!TEST_true(EVP_PKEY_pairwise_check(sctx))
    412         || !TEST_true(EVP_PKEY_public_check(sctx))
    413         || !TEST_true(EVP_PKEY_private_check(sctx)))
    414         goto err;
    415     /* Read the public key and add to a verify ctx */
    416     if (!TEST_ptr(PEM_read_bio_PUBKEY_ex(pub_bio, &pub, NULL, NULL, lib_ctx, NULL))
    417         || !TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pub, NULL)))
    418         goto err;
    419     /* verify the signature */
    420     if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, NULL), 1)
    421         || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1))
    422         goto err;
    423 
    424     ret = 1;
    425 err:
    426     EVP_CIPHER_free(cipher);
    427     EVP_SIGNATURE_free(sig_alg);
    428     EVP_PKEY_free(gkey);
    429     EVP_PKEY_free(pub);
    430     EVP_PKEY_free(priv);
    431     EVP_PKEY_CTX_free(gctx);
    432     EVP_PKEY_CTX_free(sctx);
    433     EVP_PKEY_CTX_free(vctx);
    434     BIO_free(pub_bio);
    435     BIO_free(priv_bio);
    436     OPENSSL_free(sig);
    437     return ret;
    438 }
    439 
    440 static int slh_dsa_deterministic_usage_test(void)
    441 {
    442     int ret = 0;
    443     EVP_CIPHER *cipher = NULL; /* Used to encrypt the private key */
    444     char *pass = "Password";
    445     BIO *pub_bio = NULL, *priv_bio = NULL;
    446     EVP_PKEY_CTX *gctx = NULL, *sctx = NULL, *vctx = NULL, *dupctx = NULL;
    447     EVP_PKEY *gkey = NULL, *pub = NULL, *priv = NULL;
    448     EVP_SIGNATURE *sig_alg = NULL;
    449     uint8_t *sig = NULL;
    450     size_t sig_len = 0, len = 0;
    451     uint8_t msg[] = { 0x01, 0x02, 0x03, 0x04 };
    452     size_t msg_len = sizeof(msg);
    453     const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[0];
    454     size_t key_len = tst->priv_len / 2;
    455     size_t n = key_len / 2;
    456     int deterministic = 1;
    457     OSSL_PARAM params[2], *p = params;
    458 
    459     /* Generate a key */
    460     if (!TEST_ptr(gkey = do_gen_key(tst->name, tst->priv, key_len + n)))
    461         goto err;
    462 
    463     /* Save it to a BIO - it uses a mem bio for testing */
    464     if (!TEST_ptr(pub_bio = BIO_new(BIO_s_mem()))
    465         || !TEST_ptr(priv_bio = BIO_new(BIO_s_mem()))
    466         || !TEST_ptr(cipher = EVP_CIPHER_fetch(lib_ctx, "AES-256-CBC", NULL))
    467         || !TEST_true(PEM_write_bio_PUBKEY_ex(pub_bio, gkey, lib_ctx, NULL))
    468         || !TEST_true(PEM_write_bio_PrivateKey_ex(priv_bio, gkey, cipher,
    469             NULL, 0, NULL, (void *)pass,
    470             lib_ctx, NULL)))
    471         goto err;
    472 
    473     *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_DETERMINISTIC, &deterministic);
    474     *p = OSSL_PARAM_construct_end();
    475 
    476     /* Read the private key and add to a signing ctx */
    477     if (!TEST_ptr(PEM_read_bio_PrivateKey_ex(priv_bio, &priv, NULL, pass, lib_ctx, NULL))
    478         || !TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, priv, NULL))
    479         /* Init the signature */
    480         || !TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, tst->name, NULL))
    481         || !TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, params), 1))
    482         goto err;
    483 
    484     if (!TEST_ptr(dupctx = EVP_PKEY_CTX_dup(sctx)))
    485         goto err;
    486 
    487     /* Determine the size of the signature & allocate space */
    488     if (!TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len), 1))
    489         goto err;
    490     len = sig_len;
    491     if (!TEST_ptr(sig = OPENSSL_zalloc(sig_len * 2))
    492         || !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &len, msg, msg_len), 1)
    493         || !TEST_size_t_eq(sig_len, len)
    494         || !TEST_int_eq(EVP_PKEY_sign(dupctx, sig + sig_len, &len,
    495                             msg, msg_len),
    496             1)
    497         || !TEST_size_t_eq(sig_len, len))
    498         goto err;
    499     /* Read the public key and add to a verify ctx */
    500     if (!TEST_ptr(PEM_read_bio_PUBKEY_ex(pub_bio, &pub, NULL, NULL, lib_ctx, NULL))
    501         || !TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pub, NULL)))
    502         goto err;
    503     EVP_PKEY_CTX_free(dupctx);
    504 
    505     /* verify the signature */
    506     if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, NULL), 1)
    507         || !TEST_ptr(dupctx = EVP_PKEY_CTX_dup(vctx))
    508         || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1)
    509         || !TEST_int_eq(EVP_PKEY_verify(dupctx, sig + sig_len, sig_len,
    510                             msg, msg_len),
    511             1))
    512         goto err;
    513     ret = 1;
    514 err:
    515     EVP_CIPHER_free(cipher);
    516     EVP_SIGNATURE_free(sig_alg);
    517     EVP_PKEY_free(gkey);
    518     EVP_PKEY_free(pub);
    519     EVP_PKEY_free(priv);
    520     EVP_PKEY_CTX_free(gctx);
    521     EVP_PKEY_CTX_free(sctx);
    522     EVP_PKEY_CTX_free(vctx);
    523     EVP_PKEY_CTX_free(dupctx);
    524     BIO_free(pub_bio);
    525     BIO_free(priv_bio);
    526     OPENSSL_free(sig);
    527     return ret;
    528 }
    529 
    530 static int slh_dsa_digest_sign_verify_test(void)
    531 {
    532     int ret = 0;
    533     EVP_PKEY *key = NULL;
    534     uint8_t *sig = NULL;
    535     size_t sig_len = 0;
    536     OSSL_PARAM params[3], *p = params;
    537     const char *alg = "SLH-DSA-SHA2-128s";
    538     EVP_MD_CTX *mctx = NULL;
    539     static uint8_t context[] = "A context String";
    540     static uint8_t msg[] = "Hello World";
    541     size_t msg_len = sizeof(msg);
    542 
    543     if (!TEST_ptr(key = do_gen_key(alg, NULL, 0)))
    544         goto err;
    545 
    546     *p++ = OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING,
    547         context, sizeof(context));
    548     *p++ = OSSL_PARAM_construct_end();
    549 
    550     if (!TEST_ptr(mctx = EVP_MD_CTX_new())
    551         || !TEST_int_eq(EVP_DigestSignInit_ex(mctx, NULL, "SHA256",
    552                             lib_ctx, "?fips=true",
    553                             key, params),
    554             0)
    555         || !TEST_int_eq(EVP_DigestSignInit_ex(mctx, NULL, NULL, lib_ctx,
    556                             "?fips=true", key, params),
    557             1))
    558         goto err;
    559     if (!TEST_int_eq(EVP_DigestSign(mctx, NULL, &sig_len, msg, msg_len), 1)
    560         || !TEST_ptr(sig = OPENSSL_zalloc(sig_len)))
    561         goto err;
    562     sig_len--;
    563     if (!TEST_int_eq(EVP_DigestSign(mctx, sig, &sig_len, msg, msg_len), 0))
    564         goto err;
    565     sig_len++;
    566     if (!TEST_int_eq(EVP_DigestSignInit_ex(mctx, NULL, NULL, lib_ctx, "?fips=true",
    567                          key, params),
    568             1)
    569         || !TEST_int_eq(EVP_DigestSign(mctx, sig, &sig_len, msg, msg_len), 1)
    570         || !TEST_int_eq(EVP_DigestVerifyInit_ex(mctx, NULL, "SHA256",
    571                             lib_ctx, "?fips=true",
    572                             key, params),
    573             0)
    574         || !TEST_int_eq(EVP_DigestVerifyInit_ex(mctx, NULL, NULL,
    575                             lib_ctx, "?fips=true",
    576                             key, params),
    577             1)
    578         || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, msg, msg_len), 1))
    579         goto err;
    580     ret = 1;
    581 err:
    582     EVP_PKEY_free(key);
    583     EVP_MD_CTX_free(mctx);
    584     OPENSSL_free(sig);
    585     return ret;
    586 }
    587 
    588 static int slh_dsa_keygen_invalid_test(void)
    589 {
    590     int ret = 0;
    591     const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[0];
    592     EVP_PKEY *pkey = NULL;
    593     EVP_PKEY_CTX *ctx = NULL;
    594     OSSL_PARAM params[2], *p = params;
    595     size_t key_len = tst->priv_len;
    596     size_t n = key_len / 4;
    597     uint8_t seed[128] = { 0 };
    598 
    599     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, tst->name, NULL))
    600         || !TEST_int_eq(EVP_PKEY_keygen_init(ctx), 1))
    601         goto err;
    602 
    603     /* Test the set fails if the seed is larger than the internal buffer */
    604     p[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED,
    605         seed, 97);
    606     p[1] = OSSL_PARAM_construct_end();
    607     if (!TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 0))
    608         goto err;
    609 
    610     /* Test the generate fails if the seed is not the correct size */
    611     p[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED,
    612         seed, n * 3 - 1);
    613     p[1] = OSSL_PARAM_construct_end();
    614 
    615     if (!TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 1)
    616         || !TEST_int_eq(EVP_PKEY_generate(ctx, &pkey), 0))
    617         goto err;
    618 
    619     /* Test the generate fails if the seed is not the correct size */
    620     p[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED,
    621         seed, n * 3 + 1);
    622     p[1] = OSSL_PARAM_construct_end();
    623     if (!TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 1)
    624         || !TEST_int_eq(EVP_PKEY_generate(ctx, &pkey), 0))
    625         goto err;
    626     ret = 1;
    627 err:
    628     EVP_PKEY_free(pkey);
    629     EVP_PKEY_CTX_free(ctx);
    630     return ret;
    631 }
    632 
    633 const OPTIONS *test_get_options(void)
    634 {
    635     static const OPTIONS options[] = {
    636         OPT_TEST_OPTIONS_DEFAULT_USAGE,
    637         { "config", OPT_CONFIG_FILE, '<',
    638             "The configuration file to use for the libctx" },
    639         { NULL }
    640     };
    641     return options;
    642 }
    643 
    644 int setup_tests(void)
    645 {
    646     OPTION_CHOICE o;
    647     char *config_file = NULL;
    648 
    649     while ((o = opt_next()) != OPT_EOF) {
    650         switch (o) {
    651         case OPT_CONFIG_FILE:
    652             config_file = opt_arg();
    653             break;
    654         case OPT_TEST_CASES:
    655             break;
    656         default:
    657         case OPT_ERR:
    658             return 0;
    659         }
    660     }
    661     if (!test_get_libctx(&lib_ctx, &null_prov, config_file, &lib_prov, NULL))
    662         return 0;
    663 
    664     ADD_TEST(slh_dsa_bad_pub_len_test);
    665     ADD_TEST(slh_dsa_key_validate_test);
    666     ADD_TEST(slh_dsa_key_validate_failure_test);
    667     ADD_TEST(slh_dsa_key_eq_test);
    668     ADD_TEST(slh_dsa_usage_test);
    669     ADD_TEST(slh_dsa_deterministic_usage_test);
    670     ADD_ALL_TESTS(slh_dsa_sign_verify_test, OSSL_NELEM(slh_dsa_sig_testdata));
    671     ADD_ALL_TESTS(slh_dsa_keygen_test, OSSL_NELEM(slh_dsa_keygen_testdata));
    672     ADD_TEST(slh_dsa_digest_sign_verify_test);
    673     ADD_TEST(slh_dsa_keygen_invalid_test);
    674     return 1;
    675 }
    676 
    677 void cleanup_tests(void)
    678 {
    679     OSSL_PROVIDER_unload(null_prov);
    680     OSSL_PROVIDER_unload(lib_prov);
    681     OSSL_LIB_CTX_free(lib_ctx);
    682 }
    683