slh_dsa_test.c 24 KB

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