2
0

evp_pkey_dhkem_test.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. /*
  2. * Copyright 2022 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/evp.h>
  10. #include <openssl/core_names.h>
  11. #include <openssl/param_build.h>
  12. #include <openssl/proverr.h>
  13. #include "internal/nelem.h"
  14. #include "testutil.h"
  15. #define TEST_KEM_ENCAP 0
  16. #define TEST_KEM_DECAP 1
  17. #define TEST_KEM_ENCAP_DECAP 2
  18. #define TEST_TYPE_AUTH 0
  19. #define TEST_TYPE_NOAUTH 1
  20. #define TEST_TYPE_AUTH_NOAUTH 2
  21. #define TEST_KEYTYPE_P256 0
  22. #define TEST_KEYTYPE_X25519 1
  23. #define TEST_KEYTYPES_P256_X25519 2
  24. static OSSL_LIB_CTX *libctx = NULL;
  25. static OSSL_PROVIDER *nullprov = NULL;
  26. static OSSL_PROVIDER *libprov = NULL;
  27. static OSSL_PARAM opparam[2];
  28. static EVP_PKEY *rkey[TEST_KEYTYPES_P256_X25519] = { NULL, NULL };
  29. static EVP_PKEY_CTX *rctx[TEST_KEYTYPES_P256_X25519] = { NULL, NULL };
  30. #include "dhkem_test.inc"
  31. /* Perform encapsulate KAT's */
  32. static int test_dhkem_encapsulate(int tstid)
  33. {
  34. int ret = 0;
  35. EVP_PKEY *rpub = NULL, *spriv = NULL;
  36. const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
  37. TEST_note("Test %s %s Decapsulate", t->curve,
  38. t->spriv != NULL ? "Auth" : "");
  39. if (!TEST_ptr(rpub = new_raw_public_key(t->curve, t->rpub, t->rpublen)))
  40. goto err;
  41. if (t->spriv != NULL) {
  42. if (!TEST_ptr(spriv = new_raw_private_key(t->curve,
  43. t->spriv, t->sprivlen,
  44. t->spub, t->spublen)))
  45. goto err;
  46. }
  47. ret = do_encap(t, rpub, spriv);
  48. err:
  49. EVP_PKEY_free(spriv);
  50. EVP_PKEY_free(rpub);
  51. return ret;
  52. }
  53. /* Perform decapsulate KAT's */
  54. static int test_dhkem_decapsulate(int tstid)
  55. {
  56. int ret = 0;
  57. EVP_PKEY *rpriv = NULL, *spub = NULL;
  58. const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
  59. TEST_note("Test %s %s Decapsulate", t->curve, t->spub != NULL ? "Auth" : "");
  60. if (!TEST_ptr(rpriv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
  61. t->rpub, t->rpublen)))
  62. goto err;
  63. if (t->spub != NULL) {
  64. if (!TEST_ptr(spub = new_raw_public_key(t->curve, t->spub, t->spublen)))
  65. goto err;
  66. }
  67. ret = do_decap(t, rpriv, spub);
  68. err:
  69. EVP_PKEY_free(spub);
  70. EVP_PKEY_free(rpriv);
  71. return ret;
  72. }
  73. /* Test that there are settables and they have correct data types */
  74. static int test_settables(int tstid)
  75. {
  76. EVP_PKEY_CTX *ctx = rctx[tstid];
  77. const OSSL_PARAM *settableparams;
  78. const OSSL_PARAM *p;
  79. return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
  80. && TEST_ptr(settableparams = EVP_PKEY_CTX_settable_params(ctx))
  81. && TEST_ptr(p = OSSL_PARAM_locate_const(settableparams,
  82. OSSL_KEM_PARAM_OPERATION))
  83. && TEST_uint_eq(p->data_type, OSSL_PARAM_UTF8_STRING)
  84. && TEST_ptr(p = OSSL_PARAM_locate_const(settableparams,
  85. OSSL_KEM_PARAM_IKME))
  86. && TEST_uint_eq(p->data_type, OSSL_PARAM_OCTET_STRING);
  87. }
  88. /* Test initing multiple times passes */
  89. static int test_init_multiple(int tstid)
  90. {
  91. EVP_PKEY_CTX *ctx = rctx[tstid];
  92. return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
  93. && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
  94. && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1)
  95. && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1);
  96. }
  97. /* Fail is various bad inputs are passed to the derivekey (keygen) operation */
  98. static int test_ec_dhkem_derivekey_fail(void)
  99. {
  100. int ret = 0;
  101. EVP_PKEY *pkey = NULL;
  102. OSSL_PARAM params[3];
  103. EVP_PKEY_CTX *genctx = NULL;
  104. const TEST_DERIVEKEY_DATA *t = &ec_derivekey_data[0];
  105. BIGNUM *priv = NULL;
  106. /* Check non nist curve fails */
  107. params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
  108. "secp256k1", 0);
  109. params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
  110. (char *)t->ikm, t->ikmlen);
  111. params[2] = OSSL_PARAM_construct_end();
  112. if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL))
  113. || !TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
  114. || !TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
  115. || !TEST_int_eq(EVP_PKEY_generate(genctx, &pkey),0))
  116. goto err;
  117. /* Fail if curve is not one of P-256, P-384 or P-521 */
  118. params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
  119. "P-224", 0);
  120. params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
  121. (char *)t->ikm, t->ikmlen);
  122. params[2] = OSSL_PARAM_construct_end();
  123. if (!TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
  124. || !TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
  125. || !TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 0))
  126. goto err;
  127. /* Fail if ikm len is too small*/
  128. params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
  129. "P-256", 0);
  130. params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
  131. (char *)t->ikm, t->ikmlen - 1);
  132. params[2] = OSSL_PARAM_construct_end();
  133. if (!TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
  134. || !TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 0))
  135. goto err;
  136. ret = 1;
  137. err:
  138. BN_free(priv);
  139. EVP_PKEY_free(pkey);
  140. EVP_PKEY_CTX_free(genctx);
  141. return ret;
  142. }
  143. /* Fail if the operation parameter is not set */
  144. static int test_no_operation_set(int tstid)
  145. {
  146. EVP_PKEY_CTX *ctx = rctx[tstid];
  147. const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
  148. size_t len = 0;
  149. return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1)
  150. && TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, &len, NULL, NULL), -2)
  151. && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1)
  152. && TEST_int_eq(EVP_PKEY_decapsulate(ctx, NULL, &len,
  153. t->expected_enc,
  154. t->expected_enclen), -2);
  155. }
  156. /* Fail if the ikm is too small */
  157. static int test_ikm_small(int tstid)
  158. {
  159. unsigned char tmp[16] = { 0 };
  160. unsigned char secret[256];
  161. unsigned char enc[256];
  162. size_t secretlen = sizeof(secret);
  163. size_t enclen = sizeof(enc);
  164. OSSL_PARAM params[3];
  165. EVP_PKEY_CTX *ctx = rctx[tstid];
  166. params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
  167. OSSL_KEM_PARAM_OPERATION_DHKEM,
  168. 0);
  169. params[1] = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME,
  170. tmp, sizeof(tmp));
  171. params[2] = OSSL_PARAM_construct_end();
  172. return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, params), 1)
  173. && TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
  174. secret, &secretlen), 0);
  175. }
  176. /* Fail if buffers lengths are too small to hold returned data */
  177. static int test_input_size_small(int tstid)
  178. {
  179. int ret = 0;
  180. unsigned char sec[256];
  181. unsigned char enc[256];
  182. size_t seclen = sizeof(sec);
  183. size_t enclen = sizeof(enc);
  184. EVP_PKEY_CTX *ctx = rctx[tstid];
  185. if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1)
  186. || !TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, &enclen,
  187. NULL, &seclen), 1))
  188. goto err;
  189. /* buffer too small for enc */
  190. enclen--;
  191. if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen, sec, &seclen),
  192. 0))
  193. goto err;
  194. enclen++;
  195. /* buffer too small for secret */
  196. seclen--;
  197. if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen, sec, &seclen), 0))
  198. goto err;
  199. seclen++;
  200. if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1))
  201. goto err;
  202. /* buffer too small for decapsulate secret */
  203. seclen--;
  204. if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, sec, &seclen, enc, enclen), 0))
  205. goto err;
  206. seclen++;
  207. /* incorrect enclen passed to decap */
  208. enclen--;
  209. ret = TEST_int_eq(EVP_PKEY_decapsulate(ctx, sec, &seclen, enc, enclen), 0);
  210. err:
  211. return ret;
  212. }
  213. /* Fail if the auth key has a different curve */
  214. static int test_ec_auth_key_curve_mismatch(void)
  215. {
  216. int ret = 0;
  217. EVP_PKEY *auth = NULL;
  218. if (!TEST_ptr(auth = EVP_PKEY_Q_keygen(libctx, NULL, "EC", "P-521")))
  219. return 0;
  220. ret = TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[0], auth, opparam), 0);
  221. EVP_PKEY_free(auth);
  222. return ret;
  223. }
  224. /* Fail if the auth key has a different key type to the recipient */
  225. static int test_auth_key_type_mismatch(int tstid)
  226. {
  227. int id1 = tstid;
  228. int id2 = !tstid;
  229. return TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[id1],
  230. rkey[id2], opparam), 0);
  231. }
  232. static int test_ec_invalid_private_key(void)
  233. {
  234. int ret = 0;
  235. EVP_PKEY *priv = NULL;
  236. EVP_PKEY_CTX *ctx = NULL;
  237. const TEST_ENCAPDATA *t = &ec_encapdata[0];
  238. static const unsigned char order[] = {
  239. 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  240. 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
  241. 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
  242. };
  243. ret = TEST_ptr(priv = new_raw_private_key("P-256", order, sizeof(order),
  244. t->rpub, t->rpublen))
  245. && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL))
  246. && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 0);
  247. EVP_PKEY_free(priv);
  248. EVP_PKEY_CTX_free(ctx);
  249. return ret;
  250. }
  251. static int test_ec_public_key_infinity(void)
  252. {
  253. int ret = 0;
  254. EVP_PKEY *key = NULL;
  255. EVP_PKEY_CTX *keyctx = NULL;
  256. unsigned char s[256];
  257. unsigned char e[256];
  258. size_t slen = sizeof(s);
  259. size_t elen = sizeof(e);
  260. unsigned char tmp[1] = { 0 }; /* The encoding for an EC point at infinity */
  261. EVP_PKEY_CTX *ctx = rctx[0];
  262. const TEST_ENCAPDATA *t = &ec_encapdata[0];
  263. ret = TEST_ptr(key = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
  264. tmp, sizeof(tmp)))
  265. && TEST_ptr(keyctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
  266. /* Fail if the recipient public key is invalid */
  267. && TEST_int_eq(EVP_PKEY_encapsulate_init(keyctx, opparam), 1)
  268. && TEST_int_eq(EVP_PKEY_encapsulate(keyctx, e, &elen, s, &slen), 0)
  269. /* Fail the decap if the recipient public key is invalid */
  270. && TEST_int_eq(EVP_PKEY_decapsulate_init(keyctx, opparam), 1)
  271. && TEST_int_eq(EVP_PKEY_decapsulate(keyctx, s, &slen,
  272. t->expected_enc,
  273. t->expected_enclen), 0)
  274. /* Fail if the auth key has a bad public key */
  275. && TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, key, opparam), 1)
  276. && TEST_int_eq(EVP_PKEY_encapsulate(ctx, e, &elen, s, &slen), 0);
  277. EVP_PKEY_free(key);
  278. EVP_PKEY_CTX_free(keyctx);
  279. return ret;
  280. }
  281. /* Test incorrectly passing NULL values fail */
  282. static int test_null_params(int tstid)
  283. {
  284. EVP_PKEY_CTX *ctx = rctx[tstid];
  285. const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
  286. /* auth_encap/decap init must be passed a non NULL value */
  287. return TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, NULL, opparam), 0)
  288. && TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, NULL, opparam), 0)
  289. /* Check decap fails if NULL params are passed */
  290. && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1)
  291. && TEST_int_eq(EVP_PKEY_decapsulate(ctx, NULL, NULL,
  292. t->expected_enc,
  293. t->expected_enclen), 0)
  294. /* Check encap fails if NULL params are passed */
  295. && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1)
  296. && TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, NULL,
  297. NULL, NULL), 0);
  298. }
  299. static int test_set_params(int tstid)
  300. {
  301. int ret = 0;
  302. EVP_PKEY_CTX *ctx = rctx[tstid];
  303. OSSL_PARAM badparams[4];
  304. int val = 1;
  305. /* wrong data type for operation param */
  306. badparams[0] = OSSL_PARAM_construct_int(OSSL_KEM_PARAM_OPERATION, &val);
  307. badparams[1] = OSSL_PARAM_construct_end();
  308. if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
  309. goto err;
  310. /* unknown string used for the operation param */
  311. badparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
  312. "unknown_op", 0);
  313. badparams[1] = OSSL_PARAM_construct_end();
  314. if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
  315. goto err;
  316. /* NULL string set for the operation param */
  317. badparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
  318. NULL, 0);
  319. badparams[1] = OSSL_PARAM_construct_end();
  320. if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
  321. goto err;
  322. /* wrong data type for ikme param */
  323. badparams[0] = OSSL_PARAM_construct_int(OSSL_KEM_PARAM_IKME, &val);
  324. badparams[1] = OSSL_PARAM_construct_end();
  325. if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
  326. goto err;
  327. /* Setting the ikme to NULL is allowed */
  328. badparams[0] = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME, NULL, 0);
  329. badparams[1] = OSSL_PARAM_construct_end();
  330. if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 1))
  331. goto err;
  332. /* Test that unknown params are ignored */
  333. badparams[0] = OSSL_PARAM_construct_int("unknownparam", &val);
  334. badparams[1] = OSSL_PARAM_construct_end();
  335. ret = TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 1);
  336. err:
  337. return ret;
  338. }
  339. /*
  340. * ECX keys autogen the public key if a private key is loaded,
  341. * So this test passes for ECX, but fails for EC
  342. */
  343. static int test_nopublic(int tstid)
  344. {
  345. int ret = 0;
  346. EVP_PKEY_CTX *ctx = NULL;
  347. EVP_PKEY *priv = NULL;
  348. int encap = ((tstid & 1) == 0);
  349. int keytype = tstid >= TEST_KEM_ENCAP_DECAP;
  350. const TEST_ENCAPDATA *t = &ec_encapdata[keytype];
  351. int expected = (keytype == TEST_KEYTYPE_X25519);
  352. TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
  353. if (!TEST_ptr(priv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
  354. NULL, 0)))
  355. goto err;
  356. if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL)))
  357. goto err;
  358. if (encap) {
  359. if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), expected))
  360. goto err;
  361. } else {
  362. if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), expected))
  363. goto err;
  364. }
  365. if (expected == 0
  366. && !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NOT_A_PUBLIC_KEY))
  367. goto err;
  368. ret = 1;
  369. err:
  370. EVP_PKEY_free(priv);
  371. EVP_PKEY_CTX_free(ctx);
  372. return ret;
  373. }
  374. /* Test that not setting the auth public key fails the auth encap/decap init */
  375. static int test_noauthpublic(int tstid)
  376. {
  377. int ret = 0;
  378. EVP_PKEY *auth = NULL;
  379. int encap = ((tstid & 1) == 0);
  380. int keytype = tstid >= TEST_KEM_ENCAP_DECAP;
  381. const TEST_ENCAPDATA *t = &ec_encapdata[keytype];
  382. EVP_PKEY_CTX *ctx = rctx[keytype];
  383. int expected = (keytype == TEST_KEYTYPE_X25519);
  384. TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
  385. if (!TEST_ptr(auth = new_raw_private_key(t->curve, t->rpriv,
  386. t->rprivlen, NULL, expected)))
  387. goto err;
  388. if (encap) {
  389. if (!TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, auth,
  390. opparam), expected))
  391. goto err;
  392. } else {
  393. if (!TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, auth,
  394. opparam), expected))
  395. goto err;
  396. }
  397. if (expected == 0
  398. && !TEST_int_eq(ERR_GET_REASON(ERR_get_error()),
  399. PROV_R_NOT_A_PUBLIC_KEY))
  400. goto err;
  401. ret = 1;
  402. err:
  403. EVP_PKEY_free(auth);
  404. return ret;
  405. }
  406. /* EC specific tests */
  407. /* Perform EC DHKEM KATs */
  408. static int test_ec_dhkem_derivekey(int tstid)
  409. {
  410. int ret = 0;
  411. EVP_PKEY *pkey = NULL;
  412. OSSL_PARAM params[3];
  413. EVP_PKEY_CTX *genctx = NULL;
  414. const TEST_DERIVEKEY_DATA *t = &ec_derivekey_data[tstid];
  415. unsigned char pubkey[133];
  416. unsigned char privkey[66];
  417. size_t pubkeylen = 0, privkeylen = 0;
  418. BIGNUM *priv = NULL;
  419. params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
  420. (char *)t->curvename, 0);
  421. params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
  422. (char *)t->ikm, t->ikmlen);
  423. params[2] = OSSL_PARAM_construct_end();
  424. ret = TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL))
  425. && TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
  426. && TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
  427. && TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 1)
  428. && TEST_true(EVP_PKEY_get_octet_string_param(pkey,
  429. OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
  430. pubkey, sizeof(pubkey), &pubkeylen))
  431. && TEST_true(EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
  432. &priv))
  433. && TEST_int_gt(privkeylen = BN_bn2bin(priv, privkey), 0)
  434. && TEST_int_le(privkeylen, sizeof(privkey))
  435. && TEST_mem_eq(privkey, privkeylen, t->priv, t->privlen)
  436. && TEST_mem_eq(pubkey, pubkeylen, t->pub, t->publen);
  437. BN_free(priv);
  438. EVP_PKEY_free(pkey);
  439. EVP_PKEY_CTX_free(genctx);
  440. return ret;
  441. }
  442. /*
  443. * Test that encapsulation uses a random seed if the ikm is not specified,
  444. * and verify that the shared secret matches the decapsulate result.
  445. */
  446. static int test_ec_noikme(int tstid)
  447. {
  448. int ret = 0, auth = 0;
  449. EVP_PKEY_CTX *ctx = NULL;
  450. EVP_PKEY *recip = NULL;
  451. EVP_PKEY *sender_auth = NULL;
  452. unsigned char sender_secret[256];
  453. unsigned char recip_secret[256];
  454. unsigned char sender_pub[256];
  455. size_t sender_secretlen = sizeof(sender_secret);
  456. size_t recip_secretlen = sizeof(recip_secret);
  457. size_t sender_publen = sizeof(sender_pub);
  458. const char *curve;
  459. int sz = OSSL_NELEM(dhkem_supported_curves);
  460. const char *op = OSSL_KEM_PARAM_OPERATION_DHKEM;
  461. if (tstid >= sz) {
  462. auth = 1;
  463. tstid -= sz;
  464. }
  465. curve = dhkem_supported_curves[tstid];
  466. TEST_note("testing encap/decap of curve %s%s\n", curve,
  467. auth ? " with auth" : "");
  468. if (curve[0] == 'X') {
  469. if (!TEST_ptr(recip = EVP_PKEY_Q_keygen(libctx, NULL, curve))
  470. || (auth
  471. && !TEST_ptr(sender_auth = EVP_PKEY_Q_keygen(libctx, NULL,
  472. curve))))
  473. goto err;
  474. } else {
  475. if (!TEST_ptr(recip = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve))
  476. || (auth
  477. && !TEST_ptr(sender_auth = EVP_PKEY_Q_keygen(libctx, NULL,
  478. "EC", curve))))
  479. goto err;
  480. }
  481. ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, recip, NULL))
  482. && (sender_auth == NULL
  483. || TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, sender_auth,
  484. NULL), 1))
  485. && (sender_auth != NULL
  486. || TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1))
  487. && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, op), 1)
  488. && TEST_int_eq(EVP_PKEY_encapsulate(ctx, sender_pub, &sender_publen,
  489. sender_secret, &sender_secretlen), 1)
  490. && (sender_auth == NULL
  491. || TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, sender_auth,
  492. NULL), 1))
  493. && (sender_auth != NULL
  494. || TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1))
  495. && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, op), 1)
  496. && TEST_int_eq(EVP_PKEY_decapsulate(ctx, recip_secret, &recip_secretlen,
  497. sender_pub, sender_publen), 1)
  498. && TEST_mem_eq(recip_secret, recip_secretlen,
  499. sender_secret, sender_secretlen);
  500. err:
  501. EVP_PKEY_CTX_free(ctx);
  502. EVP_PKEY_free(sender_auth);
  503. EVP_PKEY_free(recip);
  504. return ret;
  505. }
  506. /* Test encap/decap init fail if the curve is invalid */
  507. static int do_ec_curve_failtest(const char *curve)
  508. {
  509. int ret;
  510. EVP_PKEY *key = NULL;
  511. EVP_PKEY_CTX *ctx = NULL;
  512. ret = TEST_ptr(key = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve))
  513. && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
  514. && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), -2)
  515. && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), -2);
  516. EVP_PKEY_free(key);
  517. EVP_PKEY_CTX_free(ctx);
  518. return ret;
  519. }
  520. static int test_ec_curve_nonnist(void)
  521. {
  522. return do_ec_curve_failtest("secp256k1");
  523. }
  524. static int test_ec_curve_unsupported(void)
  525. {
  526. return do_ec_curve_failtest("P-224");
  527. }
  528. /* Test that passing a bad recipient public EC key fails during encap/decap */
  529. static int test_ec_badpublic(int tstid)
  530. {
  531. int ret = 0;
  532. EVP_PKEY *recippriv = NULL;
  533. EVP_PKEY_CTX *ctx = NULL;
  534. unsigned char secret[256];
  535. unsigned char pub[256];
  536. size_t secretlen = sizeof(secret);
  537. int encap = ((tstid & 1) == 0);
  538. const TEST_ENCAPDATA *t = &ec_encapdata[0];
  539. TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
  540. /* Set the recipient public key to the point at infinity */
  541. pub[0] = 0;
  542. if (!TEST_ptr(recippriv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
  543. pub, 1)))
  544. goto err;
  545. if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, recippriv, NULL)))
  546. goto err;
  547. if (encap) {
  548. unsigned char enc[256];
  549. size_t enclen = sizeof(enc);
  550. if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1))
  551. goto err;
  552. if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc , &enclen,
  553. secret, &secretlen), 0 ))
  554. goto err;
  555. } else {
  556. if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1))
  557. goto err;
  558. if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
  559. t->expected_enc,
  560. t->expected_enclen),
  561. 0))
  562. goto err;
  563. }
  564. if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY))
  565. goto err;
  566. ret = 1;
  567. err:
  568. EVP_PKEY_free(recippriv);
  569. EVP_PKEY_CTX_free(ctx);
  570. return ret;
  571. }
  572. static int test_ec_badauth(int tstid)
  573. {
  574. int ret = 0;
  575. EVP_PKEY *auth = NULL;
  576. unsigned char enc[256];
  577. unsigned char secret[256];
  578. unsigned char pub[256];
  579. size_t enclen = sizeof(enc);
  580. size_t secretlen = sizeof(secret);
  581. int encap = ((tstid & 1) == 0);
  582. const TEST_ENCAPDATA *t = &ec_encapdata[TEST_KEYTYPE_P256];
  583. EVP_PKEY_CTX *ctx = rctx[TEST_KEYTYPE_P256];
  584. TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
  585. /* Set the auth public key to the point at infinity */
  586. pub[0] = 0;
  587. if (!TEST_ptr(auth = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
  588. pub, 1)))
  589. goto err;
  590. if (encap) {
  591. if (!TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, auth,
  592. opparam), 1)
  593. || !TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
  594. secret, &secretlen), 0))
  595. goto err;
  596. } else {
  597. if (!TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, auth, opparam), 1)
  598. || !TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
  599. t->expected_enc,
  600. t->expected_enclen), 0))
  601. goto err;
  602. }
  603. if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY))
  604. goto err;
  605. ret = 1;
  606. err:
  607. EVP_PKEY_free(auth);
  608. return ret;
  609. }
  610. static int test_ec_invalid_decap_enc_buffer(void)
  611. {
  612. const TEST_ENCAPDATA *t = &ec_encapdata[TEST_KEYTYPE_P256];
  613. unsigned char enc[256];
  614. unsigned char secret[256];
  615. size_t secretlen = sizeof(secret);
  616. EVP_PKEY_CTX *ctx = rctx[0];
  617. memcpy(enc, t->expected_enc, t->expected_enclen);
  618. enc[0] = 0xFF;
  619. return TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1)
  620. && TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
  621. enc, t->expected_enclen), 0);
  622. }
  623. /* ECX specific tests */
  624. /* Perform ECX DHKEM KATs */
  625. static int test_ecx_dhkem_derivekey(int tstid)
  626. {
  627. int ret;
  628. OSSL_PARAM params[2];
  629. EVP_PKEY_CTX *genctx;
  630. EVP_PKEY *pkey = NULL;
  631. unsigned char pubkey[64];
  632. unsigned char privkey[64];
  633. unsigned char masked_priv[64];
  634. size_t pubkeylen = 0, privkeylen = 0;
  635. const TEST_DERIVEKEY_DATA *t = &ecx_derivekey_data[tstid];
  636. memcpy(masked_priv, t->priv, t->privlen);
  637. if (OPENSSL_strcasecmp(t->curvename, "X25519") == 0) {
  638. /*
  639. * The RFC test vector seems incorrect since it is not in serialized form,
  640. * So manually do the conversion here for now.
  641. */
  642. masked_priv[0] &= 248;
  643. masked_priv[t->privlen - 1] &= 127;
  644. masked_priv[t->privlen - 1] |= 64;
  645. } else {
  646. masked_priv[0] &= 252;
  647. masked_priv[t->privlen - 1] |= 128;
  648. }
  649. params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
  650. (char *)t->ikm, t->ikmlen);
  651. params[1] = OSSL_PARAM_construct_end();
  652. ret = TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, t->curvename, NULL))
  653. && TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
  654. && TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
  655. && TEST_int_eq(EVP_PKEY_keygen(genctx, &pkey), 1)
  656. && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
  657. OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
  658. pubkey, sizeof(pubkey), &pubkeylen), 1)
  659. && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
  660. OSSL_PKEY_PARAM_PRIV_KEY,
  661. privkey, sizeof(privkey), &privkeylen), 1)
  662. && TEST_mem_eq(t->pub, t->publen, pubkey, pubkeylen)
  663. && TEST_mem_eq(masked_priv, t->privlen, privkey, privkeylen);
  664. EVP_PKEY_free(pkey);
  665. EVP_PKEY_CTX_free(genctx);
  666. return ret;
  667. }
  668. /* Fail if the auth key has a different curve */
  669. static int test_ecx_auth_key_curve_mismatch(void)
  670. {
  671. int ret = 0;
  672. EVP_PKEY *auth = NULL;
  673. if (!TEST_ptr(auth = EVP_PKEY_Q_keygen(libctx, NULL, "X448")))
  674. return 0;
  675. ret = TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[TEST_KEYTYPE_X25519],
  676. auth, opparam), 0);
  677. EVP_PKEY_free(auth);
  678. return ret;
  679. }
  680. /* Fail if ED448 is used for DHKEM */
  681. static int test_ed_curve_unsupported(void)
  682. {
  683. int ret;
  684. EVP_PKEY *key = NULL;
  685. EVP_PKEY_CTX *ctx = NULL;
  686. ret = TEST_ptr(key = EVP_PKEY_Q_keygen(libctx, NULL, "ED448"))
  687. && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
  688. && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), -2)
  689. && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), -2);
  690. EVP_PKEY_free(key);
  691. EVP_PKEY_CTX_free(ctx);
  692. return ret;
  693. }
  694. int setup_tests(void)
  695. {
  696. const char *prov_name = "default";
  697. char *config_file = NULL;
  698. char *op = OSSL_KEM_PARAM_OPERATION_DHKEM;
  699. if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name))
  700. return 0;
  701. opparam[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
  702. op, 0);
  703. opparam[1] = OSSL_PARAM_construct_end();
  704. /* Create P256 and X25519 keys and ctxs */
  705. if (!TEST_ptr(rkey[TEST_KEYTYPE_P256] = EVP_PKEY_Q_keygen(libctx, NULL,
  706. "EC", "P-256")))
  707. goto err;
  708. if (!TEST_ptr(rkey[TEST_KEYTYPE_X25519] = EVP_PKEY_Q_keygen(libctx, NULL,
  709. "X25519")))
  710. goto err;
  711. if (!TEST_ptr(rctx[TEST_KEYTYPE_P256] =
  712. EVP_PKEY_CTX_new_from_pkey(libctx,
  713. rkey[TEST_KEYTYPE_P256], NULL)))
  714. goto err;
  715. if (!TEST_ptr(rctx[TEST_KEYTYPE_X25519] =
  716. EVP_PKEY_CTX_new_from_pkey(libctx,
  717. rkey[TEST_KEYTYPE_X25519], NULL)))
  718. goto err;
  719. ADD_ALL_TESTS(test_dhkem_encapsulate, OSSL_NELEM(ec_encapdata));
  720. ADD_ALL_TESTS(test_dhkem_decapsulate, OSSL_NELEM(ec_encapdata));
  721. ADD_ALL_TESTS(test_settables, TEST_KEYTYPES_P256_X25519);
  722. ADD_ALL_TESTS(test_init_multiple, TEST_KEYTYPES_P256_X25519);
  723. ADD_ALL_TESTS(test_auth_key_type_mismatch, TEST_KEYTYPES_P256_X25519);
  724. ADD_ALL_TESTS(test_no_operation_set, TEST_KEYTYPES_P256_X25519);
  725. ADD_ALL_TESTS(test_ikm_small, TEST_KEYTYPES_P256_X25519);
  726. ADD_ALL_TESTS(test_input_size_small, TEST_KEYTYPES_P256_X25519);
  727. ADD_ALL_TESTS(test_null_params, TEST_KEYTYPES_P256_X25519);
  728. ADD_ALL_TESTS(test_set_params, TEST_KEYTYPES_P256_X25519);
  729. ADD_ALL_TESTS(test_nopublic,
  730. TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
  731. ADD_ALL_TESTS(test_noauthpublic,
  732. TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
  733. /* EC Specific tests */
  734. ADD_ALL_TESTS(test_ec_dhkem_derivekey, OSSL_NELEM(ec_derivekey_data));
  735. ADD_ALL_TESTS(test_ec_noikme,
  736. TEST_TYPE_AUTH_NOAUTH * OSSL_NELEM(dhkem_supported_curves));
  737. ADD_TEST(test_ec_auth_key_curve_mismatch);
  738. ADD_TEST(test_ec_invalid_private_key);
  739. ADD_TEST(test_ec_dhkem_derivekey_fail);
  740. ADD_TEST(test_ec_curve_nonnist);
  741. ADD_TEST(test_ec_curve_unsupported);
  742. ADD_TEST(test_ec_invalid_decap_enc_buffer);
  743. ADD_TEST(test_ec_public_key_infinity);
  744. ADD_ALL_TESTS(test_ec_badpublic, TEST_KEM_ENCAP_DECAP);
  745. ADD_ALL_TESTS(test_ec_badauth, TEST_KEM_ENCAP_DECAP);
  746. /* ECX specific tests */
  747. ADD_ALL_TESTS(test_ecx_dhkem_derivekey, OSSL_NELEM(ecx_derivekey_data));
  748. ADD_TEST(test_ecx_auth_key_curve_mismatch);
  749. ADD_TEST(test_ed_curve_unsupported);
  750. return 1;
  751. err:
  752. return 0;
  753. }
  754. void cleanup_tests(void)
  755. {
  756. EVP_PKEY_free(rkey[1]);
  757. EVP_PKEY_free(rkey[0]);
  758. EVP_PKEY_CTX_free(rctx[1]);
  759. EVP_PKEY_CTX_free(rctx[0]);
  760. OSSL_PROVIDER_unload(libprov);
  761. OSSL_LIB_CTX_free(libctx);
  762. OSSL_PROVIDER_unload(nullprov);
  763. }