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