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