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) 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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