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 "internal/nelem.h" 13 #include "testutil.h" 14 #include "ml_dsa.inc" 15 #include "crypto/ml_dsa.h" 16 17 typedef enum OPTION_choice { 18 OPT_ERR = -1, 19 OPT_EOF = 0, 20 OPT_CONFIG_FILE, 21 OPT_TEST_ENUM 22 } OPTION_CHOICE; 23 24 static OSSL_LIB_CTX *lib_ctx = NULL; 25 static OSSL_PROVIDER *null_prov = NULL; 26 static OSSL_PROVIDER *lib_prov = NULL; 27 28 static EVP_PKEY *do_gen_key(const char *alg, 29 const uint8_t *seed, size_t seed_len) 30 { 31 EVP_PKEY *pkey = NULL; 32 EVP_PKEY_CTX *ctx = NULL; 33 OSSL_PARAM params[3], *p = params; 34 35 if (seed_len != 0) 36 *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ML_DSA_SEED, 37 (char *)seed, seed_len); 38 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, 39 "?fips=yes", 0); 40 *p = OSSL_PARAM_construct_end(); 41 42 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, alg, NULL)) 43 || !TEST_int_eq(EVP_PKEY_keygen_init(ctx), 1) 44 || !TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 1) 45 || !TEST_int_eq(EVP_PKEY_generate(ctx, &pkey), 1)) 46 pkey = NULL; 47 48 EVP_PKEY_CTX_free(ctx); 49 return pkey; 50 } 51 52 static int ml_dsa_create_keypair(EVP_PKEY **pkey, const char *name, 53 const uint8_t *priv, size_t priv_len, 54 const uint8_t *pub, size_t pub_len, 55 int expected) 56 { 57 int ret = 0, selection = 0; 58 EVP_PKEY_CTX *ctx = NULL; 59 OSSL_PARAM params[3], *p = params; 60 61 if (priv != NULL) { 62 *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, 63 (uint8_t *)priv, priv_len); 64 selection = OSSL_KEYMGMT_SELECT_PRIVATE_KEY; 65 } 66 if (pub != NULL) { 67 *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, 68 (uint8_t *)pub, pub_len); 69 selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; 70 } 71 *p = OSSL_PARAM_construct_end(); 72 73 if (!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, selection, 76 params), expected)) 77 goto err; 78 79 ret = 1; 80 err: 81 EVP_PKEY_CTX_free(ctx); 82 return ret; 83 } 84 85 static int ml_dsa_keygen_test(int tst_id) 86 { 87 int ret = 0; 88 const ML_DSA_KEYGEN_TEST_DATA *tst = &ml_dsa_keygen_testdata[tst_id]; 89 EVP_PKEY *pkey = NULL; 90 uint8_t priv[5 * 1024], pub[3 * 1024], seed[ML_DSA_SEED_BYTES]; 91 size_t priv_len, pub_len, seed_len; 92 int bits = 0, sec_bits = 0, sig_len = 0; 93 94 if (!TEST_ptr(pkey = do_gen_key(tst->name, tst->seed, tst->seed_len)) 95 || !TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_ML_DSA_SEED, 96 seed, sizeof(seed), &seed_len)) 97 || !TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, 98 priv, sizeof(priv), &priv_len)) 99 || !TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, 100 pub, sizeof(pub), &pub_len)) 101 || !TEST_mem_eq(pub, pub_len, tst->pub, tst->pub_len) 102 || !TEST_mem_eq(priv, priv_len, tst->priv, tst->priv_len) 103 || !TEST_mem_eq(seed, seed_len, tst->seed, tst->seed_len) 104 /* The following checks assume that algorithm is ML-DSA-65 */ 105 || !TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_BITS, &bits)) 106 || !TEST_int_eq(bits, 1952 * 8) 107 || !TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_SECURITY_BITS, 108 &sec_bits)) 109 || !TEST_int_eq(sec_bits, 192) 110 || !TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_MAX_SIZE, 111 &sig_len)) 112 || !TEST_int_ge(sig_len, 3309)) 113 goto err; 114 ret = 1; 115 err: 116 EVP_PKEY_free(pkey); 117 return ret; 118 } 119 120 static int ml_dsa_siggen_test(int tst_id) 121 { 122 int ret = 0; 123 const ML_DSA_SIG_GEN_TEST_DATA *td = &ml_dsa_siggen_testdata[tst_id]; 124 EVP_PKEY_CTX *sctx = NULL; 125 EVP_PKEY *pkey = NULL; 126 EVP_SIGNATURE *sig_alg = NULL; 127 OSSL_PARAM params[4], *p = params; 128 uint8_t *psig = NULL; 129 size_t psig_len = 0, sig_len2 = 0; 130 uint8_t digest[32]; 131 size_t digest_len = sizeof(digest); 132 int encode = 0, deterministic = 1; 133 134 *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_DETERMINISTIC, &deterministic); 135 *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode); 136 if (td->add_random != NULL) 137 *p++ = OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_TEST_ENTROPY, 138 (char *)td->add_random, 139 td->add_random_len); 140 *p = OSSL_PARAM_construct_end(); 141 142 /* 143 * This just uses from data here, but keygen also works. 144 * The keygen path is tested via ml_dsa_keygen_test 145 */ 146 if (!TEST_true(ml_dsa_create_keypair(&pkey, td->alg, td->priv, td->priv_len, 147 NULL, 0, 1)) 148 || !TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pkey, NULL)) 149 || !TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, td->alg, NULL)) 150 || !TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, params), 1) 151 || !TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &psig_len, 152 td->msg, td->msg_len), 1) 153 || !TEST_true(EVP_PKEY_get_size_t_param(pkey, OSSL_PKEY_PARAM_MAX_SIZE, 154 &sig_len2)) 155 || !TEST_int_eq(sig_len2, psig_len) 156 || !TEST_ptr(psig = OPENSSL_zalloc(psig_len)) 157 || !TEST_int_eq(EVP_PKEY_sign(sctx, psig, &psig_len, 158 td->msg, td->msg_len), 1) 159 || !TEST_int_eq(EVP_Q_digest(lib_ctx, "SHA256", NULL, psig, psig_len, 160 digest, &digest_len), 1) 161 || !TEST_mem_eq(digest, digest_len, td->sig_digest, td->sig_digest_len)) 162 goto err; 163 ret = 1; 164 err: 165 EVP_SIGNATURE_free(sig_alg); 166 EVP_PKEY_free(pkey); 167 EVP_PKEY_CTX_free(sctx); 168 OPENSSL_free(psig); 169 return ret; 170 } 171 172 static int ml_dsa_sigver_test(int tst_id) 173 { 174 int ret = 0; 175 const ML_DSA_SIG_VER_TEST_DATA *td = &ml_dsa_sigver_testdata[tst_id]; 176 EVP_PKEY_CTX *vctx = NULL; 177 EVP_PKEY *pkey = NULL; 178 EVP_SIGNATURE *sig_alg = NULL; 179 OSSL_PARAM params[2], *p = params; 180 int encode = 0; 181 182 *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode); 183 *p = OSSL_PARAM_construct_end(); 184 185 if (!TEST_true(ml_dsa_create_keypair(&pkey, td->alg, NULL, 0, 186 td->pub, td->pub_len, 1))) 187 goto err; 188 189 if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pkey, NULL))) 190 goto err; 191 if (!TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, td->alg, NULL))) 192 goto err; 193 if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, params), 1) 194 || !TEST_int_eq(EVP_PKEY_verify(vctx, td->sig, td->sig_len, 195 td->msg, td->msg_len), td->expected)) 196 goto err; 197 ret = 1; 198 err: 199 EVP_SIGNATURE_free(sig_alg); 200 EVP_PKEY_free(pkey); 201 EVP_PKEY_CTX_free(vctx); 202 return ret; 203 } 204 205 static int ml_dsa_key_dup_test(void) 206 { 207 int ret = 0; 208 const ML_DSA_KEYGEN_TEST_DATA *tst = &ml_dsa_keygen_testdata[0]; 209 EVP_PKEY *pkey = NULL, *pkey_copy = NULL; 210 EVP_PKEY_CTX *ctx = NULL; 211 212 if (!TEST_ptr(pkey = do_gen_key(tst->name, tst->seed, tst->seed_len)) 213 || !TEST_ptr(pkey_copy = EVP_PKEY_dup(pkey)) 214 || !TEST_int_eq(EVP_PKEY_eq(pkey, pkey_copy), 1) 215 || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pkey_copy, NULL)) 216 || !TEST_int_eq(EVP_PKEY_check(ctx), 1)) 217 goto err; 218 ret = 1; 219 err: 220 EVP_PKEY_free(pkey); 221 EVP_PKEY_free(pkey_copy); 222 EVP_PKEY_CTX_free(ctx); 223 return ret; 224 } 225 226 static int ml_dsa_key_internal_test(void) 227 { 228 int ret = 0; 229 ML_DSA_KEY *key = NULL, *key1 = NULL; 230 231 /* check passing NULL is ok */ 232 ossl_ml_dsa_key_free(NULL); 233 234 /* We should fail to fetch and fail here if the libctx is not set */ 235 if (!TEST_ptr_null(key = ossl_ml_dsa_key_new(NULL, NULL, EVP_PKEY_ML_DSA_44)) 236 /* fail if the algorithm is invalid */ 237 || !TEST_ptr_null(key = ossl_ml_dsa_key_new(lib_ctx, "", NID_undef)) 238 /* Dup should fail if the src is NULL */ 239 || !TEST_ptr_null(key1 = ossl_ml_dsa_key_dup(NULL, OSSL_KEYMGMT_SELECT_KEYPAIR)) 240 || !TEST_ptr(key = ossl_ml_dsa_key_new(lib_ctx, "?fips=yes", 241 EVP_PKEY_ML_DSA_44)) 242 || !TEST_ptr(key1 = ossl_ml_dsa_key_dup(key, OSSL_KEYMGMT_SELECT_KEYPAIR)) 243 || !TEST_true(ossl_ml_dsa_key_pub_alloc(key1)) 244 || !TEST_false(ossl_ml_dsa_key_pub_alloc(key1)) 245 || !TEST_true(ossl_ml_dsa_key_priv_alloc(key)) 246 || !TEST_false(ossl_ml_dsa_key_priv_alloc(key))) 247 goto err; 248 249 ret = 1; 250 err: 251 ossl_ml_dsa_key_free(key1); 252 ossl_ml_dsa_key_free(key); 253 return ret; 254 } 255 256 static int from_data_invalid_public_test(void) 257 { 258 int ret = 0; 259 const ML_DSA_KEYGEN_TEST_DATA *tst = &ml_dsa_keygen_testdata[0]; 260 uint8_t *pub = NULL; 261 EVP_PKEY *pkey = NULL; 262 263 /* corrupt the public key */ 264 if (!TEST_ptr(pub = OPENSSL_memdup(tst->pub, tst->pub_len))) 265 goto err; 266 pub[0] ^= 1; 267 268 if (!TEST_true(ml_dsa_create_keypair(&pkey, tst->name, tst->priv, tst->priv_len, 269 tst->pub, tst->pub_len, 1)) 270 || !TEST_true(ml_dsa_create_keypair(&pkey, tst->name, tst->priv, tst->priv_len, 271 pub, tst->pub_len, 0)) 272 || !TEST_true(ml_dsa_create_keypair(&pkey, tst->name, tst->priv, tst->priv_len, 273 tst->pub, tst->pub_len - 1, 0)) 274 || !TEST_true(ml_dsa_create_keypair(&pkey, tst->name, tst->priv, tst->priv_len, 275 tst->pub, tst->pub_len + 1, 0)) 276 || !TEST_true(ml_dsa_create_keypair(&pkey, tst->name, tst->priv, tst->priv_len - 1, 277 tst->pub, tst->pub_len, 0)) 278 || !TEST_true(ml_dsa_create_keypair(&pkey, tst->name, tst->priv, tst->priv_len + 1, 279 tst->pub, tst->pub_len, 0))) 280 goto err; 281 282 ret = 1; 283 err: 284 OPENSSL_free(pub); 285 EVP_PKEY_free(pkey); 286 return ret; 287 } 288 289 static int from_data_bad_input_test(void) 290 { 291 int ret = 0; 292 EVP_PKEY_CTX *ctx = NULL; 293 OSSL_PARAM params[2]; 294 EVP_PKEY *pkey = NULL; 295 uint32_t i = 0; 296 297 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, "ML-DSA-44", NULL)) 298 || !TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1) 299 || !TEST_ptr(EVP_PKEY_fromdata_settable(ctx, OSSL_KEYMGMT_SELECT_KEYPAIR)) 300 || !TEST_ptr_null(EVP_PKEY_fromdata_settable(ctx, 0))) 301 goto err; 302 303 params[0] = OSSL_PARAM_construct_uint32(OSSL_PKEY_PARAM_PRIV_KEY, &i); 304 params[1] = OSSL_PARAM_construct_end(); 305 if (!TEST_int_ne(EVP_PKEY_fromdata(ctx, &pkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, 306 params), 1)) 307 goto err; 308 params[0] = OSSL_PARAM_construct_uint32(OSSL_PKEY_PARAM_PUB_KEY, &i); 309 params[1] = OSSL_PARAM_construct_end(); 310 if (!TEST_int_ne(EVP_PKEY_fromdata(ctx, &pkey, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, 311 params), 1)) 312 goto err; 313 ret = 1; 314 err: 315 EVP_PKEY_free(pkey); 316 EVP_PKEY_CTX_free(ctx); 317 return ret; 318 } 319 320 static int ml_dsa_keygen_drbg_test(void) 321 { 322 int ret = 0; 323 EVP_PKEY *pkey = NULL, *pkey2 = NULL, *pkey3 = NULL, *pkey_pub = NULL; 324 size_t len = 0; 325 uint8_t *priv = NULL, *pub = NULL; 326 327 if (!TEST_ptr(pkey = do_gen_key("ML-DSA-44", NULL, 0)) 328 || !TEST_ptr(pkey2 = do_gen_key("ML-DSA-44", NULL, 0)) 329 || !TEST_ptr(pkey3 = do_gen_key("ML-DSA-65", NULL, 0)) 330 || !TEST_int_eq(EVP_PKEY_eq(pkey, pkey2), 0) 331 || !TEST_int_eq(EVP_PKEY_eq(pkey, pkey3), -1) 332 || !TEST_int_eq(EVP_PKEY_get_raw_private_key(pkey, NULL, &len), 1) 333 || !TEST_int_gt(len, 0) 334 || !TEST_ptr(priv = OPENSSL_malloc(len)) 335 || !TEST_int_eq(EVP_PKEY_get_raw_private_key(pkey, priv, &len), 1) 336 || !TEST_int_eq(EVP_PKEY_get_raw_public_key(pkey, NULL, &len), 1) 337 || !TEST_int_gt(len, 0) 338 || !TEST_ptr(pub = OPENSSL_malloc(len)) 339 || !TEST_int_eq(EVP_PKEY_get_raw_public_key(pkey, pub, &len), 1) 340 /* Load just the public part into a PKEY */ 341 || !TEST_true(ml_dsa_create_keypair(&pkey_pub, "ML-DSA-44", NULL, 0, 342 pub, len, 1)) 343 /* test that the KEY's are equal */ 344 || !TEST_int_eq(EVP_PKEY_eq(pkey_pub, pkey), 1)) 345 goto err; 346 ret = 1; 347 err: 348 OPENSSL_free(pub); 349 OPENSSL_free(priv); 350 EVP_PKEY_free(pkey); 351 EVP_PKEY_free(pkey2); 352 EVP_PKEY_free(pkey3); 353 EVP_PKEY_free(pkey_pub); 354 return ret; 355 } 356 357 static uint8_t msg1[] = "Hello World"; 358 static uint8_t ctx1[] = "Context Test"; 359 /* This message size will not fit into the internal buffer - so an alloc occurs */ 360 static uint8_t msg2[2048] = {0}; 361 /* This ctx is larger than 255 and will fail */ 362 static uint8_t ctx2[256] = {0}; 363 364 static struct sig_params_st { 365 uint8_t *msg; 366 size_t msg_len; 367 uint8_t *ctx; 368 size_t ctx_len; 369 int encoded; 370 int expected; 371 } sig_params[] = { 372 { msg1, sizeof(msg1), NULL, 0, 0, 1 }, 373 { msg1, sizeof(msg1), NULL, 0, 1, 1 }, 374 { msg1, sizeof(msg1), ctx1, sizeof(ctx1), 0, 1 }, 375 { msg1, sizeof(msg1), ctx1, sizeof(ctx1), 1, 1 }, 376 { msg1, sizeof(msg1), ctx2, sizeof(ctx2), 0, 0 }, 377 { msg1, sizeof(msg1), ctx2, sizeof(ctx2), 1, 0 }, 378 { msg2, sizeof(msg2), NULL, 0, 0, 1 }, 379 { msg2, sizeof(msg2), NULL, 0, 1, 1 }, 380 { msg2, sizeof(msg2), ctx1, sizeof(ctx1), 0, 1 }, 381 { msg2, sizeof(msg2), ctx1, sizeof(ctx1), 1, 1 }, 382 { msg2, sizeof(msg2), ctx2, sizeof(ctx2), 0, 0 }, 383 { msg2, sizeof(msg2), ctx2, sizeof(ctx2), 1, 0 }, 384 }; 385 386 static int do_ml_dsa_sign_verify(const char *alg, int tstid) 387 { 388 int ret = 0; 389 const struct sig_params_st *sp = &sig_params[tstid]; 390 EVP_PKEY_CTX *sctx = NULL, *vctx = NULL; 391 EVP_PKEY *key = NULL; 392 EVP_SIGNATURE *sig_alg = NULL; 393 uint8_t *sig = NULL; 394 size_t sig_len = 0; 395 OSSL_PARAM params[3], *p = params; 396 397 if (!TEST_ptr(key = do_gen_key(alg, NULL, 0))) 398 goto err; 399 400 *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, 401 (int *)&sp->encoded); 402 if (sp->ctx != NULL) 403 *p++ = OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, 404 sp->ctx, sp->ctx_len); 405 *p++ = OSSL_PARAM_construct_end(); 406 407 if (!TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL)) 408 || !TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, alg, NULL)) 409 || !TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, params), sp->expected)) 410 goto err; 411 if (sp->expected == 0) { 412 ret = 1; /* return true as we expected to fail */ 413 goto err; 414 } 415 if (!TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &sig_len, sp->msg, sp->msg_len), 1) 416 || !TEST_ptr(sig = OPENSSL_zalloc(sig_len))) 417 goto err; 418 sig_len--; 419 if (!TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len, sp->msg, sp->msg_len), 0)) 420 goto err; 421 sig_len++; 422 if (!TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len, sp->msg, sp->msg_len), 1) 423 || !TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL)) 424 || !TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, params), 1) 425 || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, sp->msg, sp->msg_len), 1)) 426 goto err; 427 ret = 1; 428 err: 429 EVP_PKEY_free(key); 430 EVP_SIGNATURE_free(sig_alg); 431 OPENSSL_free(sig); 432 EVP_PKEY_CTX_free(sctx); 433 EVP_PKEY_CTX_free(vctx); 434 return ret; 435 } 436 static int ml_dsa_44_sign_verify_test(int tstid) 437 { 438 return do_ml_dsa_sign_verify("ML-DSA-44", tstid); 439 } 440 static int ml_dsa_65_sign_verify_test(int tstid) 441 { 442 return do_ml_dsa_sign_verify("ML-DSA-65", tstid); 443 } 444 static int ml_dsa_87_sign_verify_test(int tstid) 445 { 446 return do_ml_dsa_sign_verify("ML-DSA-87", tstid); 447 } 448 449 static int ml_dsa_digest_sign_verify_test(void) 450 { 451 int ret = 0; 452 const struct sig_params_st *sp = &sig_params[0]; 453 EVP_PKEY *key = NULL; 454 uint8_t *sig = NULL; 455 size_t sig_len = 0; 456 OSSL_PARAM params[3], *p = params; 457 const char *alg = "ML-DSA-44"; 458 EVP_MD_CTX *mctx = NULL; 459 460 if (!TEST_ptr(key = do_gen_key(alg, NULL, 0))) 461 goto err; 462 463 *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, 464 (int *)&sp->encoded); 465 if (sp->ctx != NULL) 466 *p++ = OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, 467 sp->ctx, sp->ctx_len); 468 *p++ = OSSL_PARAM_construct_end(); 469 470 if (!TEST_ptr(mctx = EVP_MD_CTX_new()) 471 || !TEST_int_eq(EVP_DigestSignInit_ex(mctx, NULL, "SHA256", 472 lib_ctx, "?fips=true", 473 key, params), 0) 474 || !TEST_int_eq(EVP_DigestSignInit_ex(mctx, NULL, NULL, lib_ctx, 475 "?fips=true", key, params), 1)) 476 goto err; 477 if (sp->expected == 0) { 478 ret = 1; /* return true as we expected to fail */ 479 goto err; 480 } 481 if (!TEST_int_eq(EVP_DigestSign(mctx, NULL, &sig_len, sp->msg, sp->msg_len), 1) 482 || !TEST_ptr(sig = OPENSSL_zalloc(sig_len))) 483 goto err; 484 sig_len--; 485 if (!TEST_int_eq(EVP_DigestSign(mctx, sig, &sig_len, sp->msg, sp->msg_len), 0)) 486 goto err; 487 sig_len++; 488 if (!TEST_int_eq(EVP_DigestSignInit_ex(mctx, NULL, NULL, lib_ctx, "?fips=true", 489 key, params), 1) 490 || !TEST_int_eq(EVP_DigestSign(mctx, sig, &sig_len, 491 sp->msg, sp->msg_len), 1) 492 || !TEST_int_eq(EVP_DigestVerifyInit_ex(mctx, NULL, "SHA256", 493 lib_ctx, "?fips=true", 494 key, params), 0) 495 || !TEST_int_eq(EVP_DigestVerifyInit_ex(mctx, NULL, NULL, 496 lib_ctx, "?fips=true", 497 key, params), 1) 498 || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, 499 sp->msg, sp->msg_len), 1)) 500 goto err; 501 ret = 1; 502 err: 503 EVP_PKEY_free(key); 504 EVP_MD_CTX_free(mctx); 505 OPENSSL_free(sig); 506 return ret; 507 } 508 509 static int ml_dsa_priv_pub_bad_t0_test(void) 510 { 511 int ret = 0; 512 EVP_PKEY *key = NULL; 513 ML_DSA_SIG_GEN_TEST_DATA *td = &ml_dsa_siggen_testdata[0]; 514 uint8_t *priv = OPENSSL_memdup(td->priv, td->priv_len); 515 516 if (!TEST_ptr(priv)) 517 goto err; 518 memcpy(priv, td->priv, td->priv_len); 519 /* 520 * t0 is at the end of the encoding so corrupt it. 521 * This offset is the start of t0 (which is the last 416 * k bytes)) 522 */ 523 priv[td->priv_len - 6 * 416] ^= 1; 524 if (!TEST_true(ml_dsa_create_keypair(&key, td->alg, 525 priv, td->priv_len, NULL, 0, 0))) 526 goto err; 527 528 priv[td->priv_len - 6 * 416] ^= 1; 529 if (!TEST_true(ml_dsa_create_keypair(&key, td->alg, 530 priv, td->priv_len, NULL, 0, 1))) 531 goto err; 532 ret = 1; 533 err: 534 OPENSSL_free(priv); 535 EVP_PKEY_free(key); 536 return ret; 537 } 538 539 const OPTIONS *test_get_options(void) 540 { 541 static const OPTIONS options[] = { 542 OPT_TEST_OPTIONS_DEFAULT_USAGE, 543 { "config", OPT_CONFIG_FILE, '<', 544 "The configuration file to use for the libctx" }, 545 { NULL } 546 }; 547 return options; 548 } 549 550 int setup_tests(void) 551 { 552 OPTION_CHOICE o; 553 char *config_file = NULL; 554 555 while ((o = opt_next()) != OPT_EOF) { 556 switch (o) { 557 case OPT_CONFIG_FILE: 558 config_file = opt_arg(); 559 break; 560 case OPT_TEST_CASES: 561 break; 562 default: 563 case OPT_ERR: 564 return 0; 565 } 566 } 567 if (!test_get_libctx(&lib_ctx, &null_prov, config_file, &lib_prov, NULL)) 568 return 0; 569 570 ADD_ALL_TESTS(ml_dsa_keygen_test, OSSL_NELEM(ml_dsa_keygen_testdata)); 571 ADD_ALL_TESTS(ml_dsa_siggen_test, OSSL_NELEM(ml_dsa_siggen_testdata)); 572 ADD_ALL_TESTS(ml_dsa_sigver_test, OSSL_NELEM(ml_dsa_sigver_testdata)); 573 ADD_TEST(ml_dsa_key_dup_test); 574 ADD_TEST(ml_dsa_key_internal_test); 575 ADD_TEST(ml_dsa_keygen_drbg_test); 576 ADD_ALL_TESTS(ml_dsa_44_sign_verify_test, OSSL_NELEM(sig_params)); 577 ADD_ALL_TESTS(ml_dsa_65_sign_verify_test, OSSL_NELEM(sig_params)); 578 ADD_ALL_TESTS(ml_dsa_87_sign_verify_test, OSSL_NELEM(sig_params)); 579 ADD_TEST(from_data_invalid_public_test); 580 ADD_TEST(from_data_bad_input_test); 581 ADD_TEST(ml_dsa_digest_sign_verify_test); 582 ADD_TEST(ml_dsa_priv_pub_bad_t0_test); 583 return 1; 584 } 585 586 void cleanup_tests(void) 587 { 588 OSSL_PROVIDER_unload(null_prov); 589 OSSL_PROVIDER_unload(lib_prov); 590 OSSL_LIB_CTX_free(lib_ctx); 591 } 592