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