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