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