ml_dsa_test.c 22 KB

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