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