xref: /freebsd/crypto/openssl/test/slh_dsa_test.c (revision e7be843b4a162e68651d3911f0357ed464915629)
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 
slh_dsa_key_from_data(const char * alg,const unsigned char * data,size_t datalen,int public)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 
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)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 
slh_dsa_bad_pub_len_test(void)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 
slh_dsa_key_eq_test(void)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 
slh_dsa_key_validate_test(void)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 
slh_dsa_key_validate_failure_test(void)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  */
do_slh_dsa_verify(const SLH_DSA_SIG_TEST_DATA * td,uint8_t * sig,size_t sig_len)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 
slh_dsa_sign_verify_test(int tst_id)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 
do_gen_key(const char * alg,const uint8_t * seed,size_t seed_len)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 
slh_dsa_keygen_test(int tst_id)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 
slh_dsa_usage_test(void)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 
slh_dsa_deterministic_usage_test(void)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 
slh_dsa_digest_sign_verify_test(void)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 
slh_dsa_keygen_invalid_test(void)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 
test_get_options(void)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 
setup_tests(void)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 
cleanup_tests(void)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