xref: /freebsd/crypto/openssl/test/evp_pkey_dhkem_test.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
1 /*
2  * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <openssl/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 */
test_dhkem_encapsulate(int tstid)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 */
test_dhkem_decapsulate(int tstid)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 */
test_settables(int tstid)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 */
test_init_multiple(int tstid)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 */
test_ec_dhkem_derivekey_fail(void)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 /* Succeed even if the operation parameter is not set */
test_no_operation_set(int tstid)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), 1)
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),
180             1);
181 }
182 
183 /* Fail if the ikm is too small */
test_ikm_small(int tstid)184 static int test_ikm_small(int tstid)
185 {
186     unsigned char tmp[16] = { 0 };
187     unsigned char secret[256];
188     unsigned char enc[256];
189     size_t secretlen = sizeof(secret);
190     size_t enclen = sizeof(enc);
191     OSSL_PARAM params[3];
192     EVP_PKEY_CTX *ctx = rctx[tstid];
193 
194     params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
195         OSSL_KEM_PARAM_OPERATION_DHKEM,
196         0);
197     params[1] = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME,
198         tmp, sizeof(tmp));
199     params[2] = OSSL_PARAM_construct_end();
200 
201     return TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, params), 1)
202         && TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
203                            secret, &secretlen),
204             0);
205 }
206 
207 /* Fail if buffers lengths are too small to hold returned data */
test_input_size_small(int tstid)208 static int test_input_size_small(int tstid)
209 {
210     int ret = 0;
211     unsigned char sec[256];
212     unsigned char enc[256];
213     size_t seclen = sizeof(sec);
214     size_t enclen = sizeof(enc);
215     EVP_PKEY_CTX *ctx = rctx[tstid];
216 
217     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1)
218         || !TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, &enclen,
219                             NULL, &seclen),
220             1))
221         goto err;
222 
223     /* buffer too small for enc */
224     enclen--;
225     if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen, sec, &seclen),
226             0))
227         goto err;
228     enclen++;
229     /* buffer too small for secret */
230     seclen--;
231     if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen, sec, &seclen), 0))
232         goto err;
233     seclen++;
234     if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1))
235         goto err;
236     /* buffer too small for decapsulate secret */
237     seclen--;
238     if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, sec, &seclen, enc, enclen), 0))
239         goto err;
240     seclen++;
241     /* incorrect enclen passed to decap  */
242     enclen--;
243     ret = TEST_int_eq(EVP_PKEY_decapsulate(ctx, sec, &seclen, enc, enclen), 0);
244 err:
245     return ret;
246 }
247 
248 /* Fail if the auth key has a different curve */
test_ec_auth_key_curve_mismatch(void)249 static int test_ec_auth_key_curve_mismatch(void)
250 {
251     int ret = 0;
252     EVP_PKEY *auth = NULL;
253 
254     if (!TEST_ptr(auth = EVP_PKEY_Q_keygen(libctx, NULL, "EC", "P-521")))
255         return 0;
256 
257     ret = TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[0], auth, opparam), 0);
258     EVP_PKEY_free(auth);
259     return ret;
260 }
261 
262 /* Fail if the auth key has a different key type to the recipient */
test_auth_key_type_mismatch(int tstid)263 static int test_auth_key_type_mismatch(int tstid)
264 {
265     int id1 = tstid;
266     int id2 = !tstid;
267 
268     return TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[id1],
269                            rkey[id2], opparam),
270         0);
271 }
272 
test_ec_invalid_private_key(void)273 static int test_ec_invalid_private_key(void)
274 {
275     int ret = 0;
276     EVP_PKEY *priv = NULL;
277     EVP_PKEY_CTX *ctx = NULL;
278     const TEST_ENCAPDATA *t = &ec_encapdata[0];
279     static const unsigned char order[] = {
280         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
281         0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
282         0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
283     };
284 
285     ret = TEST_ptr(priv = new_raw_private_key("P-256", order, sizeof(order),
286                        t->rpub, t->rpublen))
287         && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL))
288         && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 0);
289     EVP_PKEY_free(priv);
290     EVP_PKEY_CTX_free(ctx);
291     return ret;
292 }
293 
test_ec_public_key_infinity(void)294 static int test_ec_public_key_infinity(void)
295 {
296     int ret = 0;
297     EVP_PKEY *key = NULL;
298     EVP_PKEY_CTX *keyctx = NULL;
299     unsigned char s[256];
300     unsigned char e[256];
301     size_t slen = sizeof(s);
302     size_t elen = sizeof(e);
303     unsigned char tmp[1] = { 0 }; /* The encoding for an EC point at infinity */
304     EVP_PKEY_CTX *ctx = rctx[0];
305     const TEST_ENCAPDATA *t = &ec_encapdata[0];
306 
307     ret = TEST_ptr(key = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
308                        tmp, sizeof(tmp)))
309         && TEST_ptr(keyctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
310         /* Fail if the recipient public key is invalid */
311         && TEST_int_eq(EVP_PKEY_encapsulate_init(keyctx, opparam), 1)
312         && TEST_int_eq(EVP_PKEY_encapsulate(keyctx, e, &elen, s, &slen), 0)
313         /* Fail the decap if the recipient public key is invalid */
314         && TEST_int_eq(EVP_PKEY_decapsulate_init(keyctx, opparam), 1)
315         && TEST_int_eq(EVP_PKEY_decapsulate(keyctx, s, &slen,
316                            t->expected_enc,
317                            t->expected_enclen),
318             0)
319         /* Fail if the auth key has a bad public key */
320         && TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, key, opparam), 1)
321         && TEST_int_eq(EVP_PKEY_encapsulate(ctx, e, &elen, s, &slen), 0);
322 
323     EVP_PKEY_free(key);
324     EVP_PKEY_CTX_free(keyctx);
325     return ret;
326 }
327 
328 /* Test incorrectly passing NULL values fail */
test_null_params(int tstid)329 static int test_null_params(int tstid)
330 {
331     EVP_PKEY_CTX *ctx = rctx[tstid];
332     const TEST_ENCAPDATA *t = &ec_encapdata[tstid];
333 
334     /* auth_encap/decap init must be passed a non NULL value */
335     return TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, NULL, opparam), 0)
336         && TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, NULL, opparam), 0)
337         /* Check decap fails if NULL params are passed */
338         && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1)
339         && TEST_int_eq(EVP_PKEY_decapsulate(ctx, NULL, NULL,
340                            t->expected_enc,
341                            t->expected_enclen),
342             0)
343         /* Check encap fails if NULL params are passed */
344         && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1)
345         && TEST_int_eq(EVP_PKEY_encapsulate(ctx, NULL, NULL,
346                            NULL, NULL),
347             0);
348 }
349 
test_set_params(int tstid)350 static int test_set_params(int tstid)
351 {
352     int ret = 0;
353     EVP_PKEY_CTX *ctx = rctx[tstid];
354     OSSL_PARAM badparams[4];
355     int val = 1;
356 
357     /* wrong data type for operation param */
358     badparams[0] = OSSL_PARAM_construct_int(OSSL_KEM_PARAM_OPERATION, &val);
359     badparams[1] = OSSL_PARAM_construct_end();
360     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
361         goto err;
362     /* unknown string used for the operation param */
363     badparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
364         "unknown_op", 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     /* NULL string set for the operation param */
370     badparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
371         NULL, 0);
372     badparams[1] = OSSL_PARAM_construct_end();
373     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
374         goto err;
375 
376     /* wrong data type for ikme param */
377     badparams[0] = OSSL_PARAM_construct_int(OSSL_KEM_PARAM_IKME, &val);
378     badparams[1] = OSSL_PARAM_construct_end();
379     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 0))
380         goto err;
381 
382     /* Setting the ikme to NULL is allowed */
383     badparams[0] = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME, NULL, 0);
384     badparams[1] = OSSL_PARAM_construct_end();
385     if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 1))
386         goto err;
387 
388     /* Test that unknown params are ignored */
389     badparams[0] = OSSL_PARAM_construct_int("unknownparam", &val);
390     badparams[1] = OSSL_PARAM_construct_end();
391     ret = TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, badparams), 1);
392 err:
393     return ret;
394 }
395 
396 /*
397  * ECX keys autogen the public key if a private key is loaded,
398  * So this test passes for ECX, but fails for EC
399  */
test_nopublic(int tstid)400 static int test_nopublic(int tstid)
401 {
402     int ret = 0;
403     EVP_PKEY_CTX *ctx = NULL;
404     EVP_PKEY *priv = NULL;
405     int encap = ((tstid & 1) == 0);
406     int keytype = tstid >= TEST_KEM_ENCAP_DECAP;
407     const TEST_ENCAPDATA *t = &ec_encapdata[keytype];
408     int expected = (keytype == TEST_KEYTYPE_X25519);
409 
410     TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
411     if (!TEST_ptr(priv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
412                       NULL, 0)))
413         goto err;
414     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL)))
415         goto err;
416 
417     if (encap) {
418         if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), expected))
419             goto err;
420     } else {
421         if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), expected))
422             goto err;
423     }
424     if (expected == 0
425         && !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NOT_A_PUBLIC_KEY))
426         goto err;
427     ret = 1;
428 err:
429     EVP_PKEY_free(priv);
430     EVP_PKEY_CTX_free(ctx);
431     return ret;
432 }
433 
434 /* Test that not setting the auth public key fails the auth encap/decap init */
test_noauthpublic(int tstid)435 static int test_noauthpublic(int tstid)
436 {
437     int ret = 0;
438     EVP_PKEY *auth = NULL;
439     int encap = ((tstid & 1) == 0);
440     int keytype = tstid >= TEST_KEM_ENCAP_DECAP;
441     const TEST_ENCAPDATA *t = &ec_encapdata[keytype];
442     EVP_PKEY_CTX *ctx = rctx[keytype];
443     int expected = (keytype == TEST_KEYTYPE_X25519);
444 
445     TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
446     if (!TEST_ptr(auth = new_raw_private_key(t->curve, t->rpriv,
447                       t->rprivlen, NULL, expected)))
448         goto err;
449 
450     if (encap) {
451         if (!TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, auth,
452                              opparam),
453                 expected))
454             goto err;
455     } else {
456         if (!TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, auth,
457                              opparam),
458                 expected))
459             goto err;
460     }
461     if (expected == 0
462         && !TEST_int_eq(ERR_GET_REASON(ERR_get_error()),
463             PROV_R_NOT_A_PUBLIC_KEY))
464         goto err;
465     ret = 1;
466 err:
467     EVP_PKEY_free(auth);
468     return ret;
469 }
470 
471 /* EC specific tests */
472 
473 /* Perform EC DHKEM KATs */
test_ec_dhkem_derivekey(int tstid)474 static int test_ec_dhkem_derivekey(int tstid)
475 {
476     int ret = 0;
477     EVP_PKEY *pkey = NULL;
478     OSSL_PARAM params[3];
479     EVP_PKEY_CTX *genctx = NULL;
480     const TEST_DERIVEKEY_DATA *t = &ec_derivekey_data[tstid];
481     unsigned char pubkey[133];
482     unsigned char privkey[66];
483     size_t pubkeylen = 0, privkeylen = 0;
484     BIGNUM *priv = NULL;
485 
486     params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
487         (char *)t->curvename, 0);
488     params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
489         (char *)t->ikm, t->ikmlen);
490     params[2] = OSSL_PARAM_construct_end();
491 
492     ret = TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL))
493         && TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
494         && TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
495         && TEST_int_eq(EVP_PKEY_generate(genctx, &pkey), 1)
496         && TEST_true(EVP_PKEY_get_octet_string_param(pkey,
497             OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
498             pubkey, sizeof(pubkey), &pubkeylen))
499         && TEST_true(EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
500             &priv))
501         && TEST_int_gt(privkeylen = BN_bn2bin(priv, privkey), 0)
502         && TEST_int_le(privkeylen, sizeof(privkey))
503         && TEST_mem_eq(privkey, privkeylen, t->priv, t->privlen)
504         && TEST_mem_eq(pubkey, pubkeylen, t->pub, t->publen);
505 
506     BN_free(priv);
507     EVP_PKEY_free(pkey);
508     EVP_PKEY_CTX_free(genctx);
509     return ret;
510 }
511 
512 /*
513  * Test that encapsulation uses a random seed if the ikm is not specified,
514  * and verify that the shared secret matches the decapsulate result.
515  */
test_ec_noikme(int tstid)516 static int test_ec_noikme(int tstid)
517 {
518     int ret = 0, auth = 0;
519     EVP_PKEY_CTX *ctx = NULL;
520     EVP_PKEY *recip = NULL;
521     EVP_PKEY *sender_auth = NULL;
522     unsigned char sender_secret[256];
523     unsigned char recip_secret[256];
524     unsigned char sender_pub[256];
525     size_t sender_secretlen = sizeof(sender_secret);
526     size_t recip_secretlen = sizeof(recip_secret);
527     size_t sender_publen = sizeof(sender_pub);
528     const char *curve;
529     int sz = OSSL_NELEM(dhkem_supported_curves);
530     const char *op = OSSL_KEM_PARAM_OPERATION_DHKEM;
531 
532     if (tstid >= sz) {
533         auth = 1;
534         tstid -= sz;
535     }
536     curve = dhkem_supported_curves[tstid];
537     TEST_note("testing encap/decap of curve %s%s\n", curve,
538         auth ? " with auth" : "");
539 
540     if (curve[0] == 'X') {
541         if (!TEST_ptr(recip = EVP_PKEY_Q_keygen(libctx, NULL, curve))
542             || (auth
543                 && !TEST_ptr(sender_auth = EVP_PKEY_Q_keygen(libctx, NULL,
544                                  curve))))
545             goto err;
546     } else {
547         if (!TEST_ptr(recip = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve))
548             || (auth
549                 && !TEST_ptr(sender_auth = EVP_PKEY_Q_keygen(libctx, NULL,
550                                  "EC", curve))))
551             goto err;
552     }
553 
554     ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, recip, NULL))
555         && (sender_auth == NULL
556             || TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, sender_auth,
557                                NULL),
558                 1))
559         && (sender_auth != NULL
560             || TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 1))
561         && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, op), 1)
562         && TEST_int_eq(EVP_PKEY_encapsulate(ctx, sender_pub, &sender_publen,
563                            sender_secret, &sender_secretlen),
564             1)
565         && (sender_auth == NULL
566             || TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, sender_auth,
567                                NULL),
568                 1))
569         && (sender_auth != NULL
570             || TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1))
571         && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, op), 1)
572         && TEST_int_eq(EVP_PKEY_decapsulate(ctx, recip_secret, &recip_secretlen,
573                            sender_pub, sender_publen),
574             1)
575         && TEST_mem_eq(recip_secret, recip_secretlen,
576             sender_secret, sender_secretlen);
577 err:
578     EVP_PKEY_CTX_free(ctx);
579     EVP_PKEY_free(sender_auth);
580     EVP_PKEY_free(recip);
581     return ret;
582 }
583 
584 /* Test encap/decap init fail if the curve is invalid */
do_ec_curve_failtest(const char * curve)585 static int do_ec_curve_failtest(const char *curve)
586 {
587     int ret;
588     EVP_PKEY *key = NULL;
589     EVP_PKEY_CTX *ctx = NULL;
590 
591     ret = TEST_ptr(key = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve))
592         && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
593         && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), -2)
594         && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), -2);
595     EVP_PKEY_free(key);
596     EVP_PKEY_CTX_free(ctx);
597     return ret;
598 }
599 
test_ec_curve_nonnist(void)600 static int test_ec_curve_nonnist(void)
601 {
602     return do_ec_curve_failtest("secp256k1");
603 }
604 
test_ec_curve_unsupported(void)605 static int test_ec_curve_unsupported(void)
606 {
607     return do_ec_curve_failtest("P-224");
608 }
609 
610 /* Test that passing a bad recipient public EC key fails during encap/decap */
test_ec_badpublic(int tstid)611 static int test_ec_badpublic(int tstid)
612 {
613     int ret = 0;
614     EVP_PKEY *recippriv = NULL;
615     EVP_PKEY_CTX *ctx = NULL;
616     unsigned char secret[256];
617     unsigned char pub[256];
618     size_t secretlen = sizeof(secret);
619     int encap = ((tstid & 1) == 0);
620     const TEST_ENCAPDATA *t = &ec_encapdata[0];
621 
622     TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
623     /* Set the recipient public key to the point at infinity */
624     pub[0] = 0;
625     if (!TEST_ptr(recippriv = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
626                       pub, 1)))
627         goto err;
628 
629     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, recippriv, NULL)))
630         goto err;
631 
632     if (encap) {
633         unsigned char enc[256];
634         size_t enclen = sizeof(enc);
635 
636         if (!TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, opparam), 1))
637             goto err;
638         if (!TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
639                              secret, &secretlen),
640                 0))
641             goto err;
642     } else {
643         if (!TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1))
644             goto err;
645         if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
646                              t->expected_enc,
647                              t->expected_enclen),
648                 0))
649             goto err;
650     }
651     if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY))
652         goto err;
653     ret = 1;
654 err:
655     EVP_PKEY_free(recippriv);
656     EVP_PKEY_CTX_free(ctx);
657     return ret;
658 }
659 
test_ec_badauth(int tstid)660 static int test_ec_badauth(int tstid)
661 {
662     int ret = 0;
663     EVP_PKEY *auth = NULL;
664     unsigned char enc[256];
665     unsigned char secret[256];
666     unsigned char pub[256];
667     size_t enclen = sizeof(enc);
668     size_t secretlen = sizeof(secret);
669     int encap = ((tstid & 1) == 0);
670     const TEST_ENCAPDATA *t = &ec_encapdata[TEST_KEYTYPE_P256];
671     EVP_PKEY_CTX *ctx = rctx[TEST_KEYTYPE_P256];
672 
673     TEST_note("%s %s", t->curve, encap ? "Encap" : "Decap");
674     /* Set the auth public key to the point at infinity */
675     pub[0] = 0;
676     if (!TEST_ptr(auth = new_raw_private_key(t->curve, t->rpriv, t->rprivlen,
677                       pub, 1)))
678         goto err;
679     if (encap) {
680         if (!TEST_int_eq(EVP_PKEY_auth_encapsulate_init(ctx, auth,
681                              opparam),
682                 1)
683             || !TEST_int_eq(EVP_PKEY_encapsulate(ctx, enc, &enclen,
684                                 secret, &secretlen),
685                 0))
686             goto err;
687     } else {
688         if (!TEST_int_eq(EVP_PKEY_auth_decapsulate_init(ctx, auth, opparam), 1)
689             || !TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
690                                 t->expected_enc,
691                                 t->expected_enclen),
692                 0))
693             goto err;
694     }
695     if (!TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY))
696         goto err;
697     ret = 1;
698 err:
699     EVP_PKEY_free(auth);
700     return ret;
701 }
702 
test_ec_invalid_decap_enc_buffer(void)703 static int test_ec_invalid_decap_enc_buffer(void)
704 {
705     const TEST_ENCAPDATA *t = &ec_encapdata[TEST_KEYTYPE_P256];
706     unsigned char enc[256];
707     unsigned char secret[256];
708     size_t secretlen = sizeof(secret);
709     EVP_PKEY_CTX *ctx = rctx[0];
710 
711     memcpy(enc, t->expected_enc, t->expected_enclen);
712     enc[0] = 0xFF;
713 
714     return TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, opparam), 1)
715         && TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen,
716                            enc, t->expected_enclen),
717             0);
718 }
719 
720 #ifndef OPENSSL_NO_ECX
721 /* ECX specific tests */
722 
723 /* Perform ECX DHKEM KATs */
test_ecx_dhkem_derivekey(int tstid)724 static int test_ecx_dhkem_derivekey(int tstid)
725 {
726     int ret;
727     OSSL_PARAM params[2];
728     EVP_PKEY_CTX *genctx;
729     EVP_PKEY *pkey = NULL;
730     unsigned char pubkey[64];
731     unsigned char privkey[64];
732     unsigned char masked_priv[64];
733     size_t pubkeylen = 0, privkeylen = 0;
734     const TEST_DERIVEKEY_DATA *t = &ecx_derivekey_data[tstid];
735 
736     memcpy(masked_priv, t->priv, t->privlen);
737     if (OPENSSL_strcasecmp(t->curvename, "X25519") == 0) {
738         /*
739          * The RFC test vector seems incorrect since it is not in serialized form,
740          * So manually do the conversion here for now.
741          */
742         masked_priv[0] &= 248;
743         masked_priv[t->privlen - 1] &= 127;
744         masked_priv[t->privlen - 1] |= 64;
745     } else {
746         masked_priv[0] &= 252;
747         masked_priv[t->privlen - 1] |= 128;
748     }
749 
750     params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
751         (char *)t->ikm, t->ikmlen);
752     params[1] = OSSL_PARAM_construct_end();
753 
754     ret = TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, t->curvename, NULL))
755         && TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
756         && TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
757         && TEST_int_eq(EVP_PKEY_keygen(genctx, &pkey), 1)
758         && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
759                            OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
760                            pubkey, sizeof(pubkey), &pubkeylen),
761             1)
762         && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
763                            OSSL_PKEY_PARAM_PRIV_KEY,
764                            privkey, sizeof(privkey), &privkeylen),
765             1)
766         && TEST_mem_eq(t->pub, t->publen, pubkey, pubkeylen)
767         && TEST_mem_eq(masked_priv, t->privlen, privkey, privkeylen);
768 
769     EVP_PKEY_free(pkey);
770     EVP_PKEY_CTX_free(genctx);
771     return ret;
772 }
773 
774 /* Fail if the auth key has a different curve */
test_ecx_auth_key_curve_mismatch(void)775 static int test_ecx_auth_key_curve_mismatch(void)
776 {
777     int ret = 0;
778     EVP_PKEY *auth = NULL;
779 
780     if (!TEST_ptr(auth = EVP_PKEY_Q_keygen(libctx, NULL, "X448")))
781         return 0;
782 
783     ret = TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[TEST_KEYTYPE_X25519],
784                           auth, opparam),
785         0);
786     EVP_PKEY_free(auth);
787     return ret;
788 }
789 
790 /* Fail if ED448 is used for DHKEM */
test_ed_curve_unsupported(void)791 static int test_ed_curve_unsupported(void)
792 {
793     int ret;
794     EVP_PKEY *key = NULL;
795     EVP_PKEY_CTX *ctx = NULL;
796 
797     ret = TEST_ptr(key = EVP_PKEY_Q_keygen(libctx, NULL, "ED448"))
798         && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
799         && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), -2)
800         && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), -2);
801     EVP_PKEY_free(key);
802     EVP_PKEY_CTX_free(ctx);
803     return ret;
804 }
805 #endif
806 
setup_tests(void)807 int setup_tests(void)
808 {
809     const char *prov_name = "default";
810     char *config_file = NULL;
811     char *op = OSSL_KEM_PARAM_OPERATION_DHKEM;
812 
813     if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name))
814         return 0;
815     opparam[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
816         op, 0);
817     opparam[1] = OSSL_PARAM_construct_end();
818 
819     /* Create P256 and X25519 keys and ctxs */
820     if (!TEST_ptr(rkey[TEST_KEYTYPE_P256] = EVP_PKEY_Q_keygen(libctx, NULL,
821                       "EC", "P-256")))
822         goto err;
823 #ifndef OPENSSL_NO_ECX
824     if (!TEST_ptr(rkey[TEST_KEYTYPE_X25519] = EVP_PKEY_Q_keygen(libctx, NULL,
825                       "X25519")))
826         goto err;
827 #endif
828     if (!TEST_ptr(rctx[TEST_KEYTYPE_P256] = EVP_PKEY_CTX_new_from_pkey(libctx,
829                       rkey[TEST_KEYTYPE_P256], NULL)))
830         goto err;
831 #ifndef OPENSSL_NO_ECX
832     if (!TEST_ptr(rctx[TEST_KEYTYPE_X25519] = EVP_PKEY_CTX_new_from_pkey(libctx,
833                       rkey[TEST_KEYTYPE_X25519], NULL)))
834         goto err;
835 #endif
836 
837     ADD_ALL_TESTS(test_dhkem_encapsulate, OSSL_NELEM(ec_encapdata));
838     ADD_ALL_TESTS(test_dhkem_decapsulate, OSSL_NELEM(ec_encapdata));
839 #ifndef OPENSSL_NO_ECX
840     ADD_ALL_TESTS(test_settables, TEST_KEYTYPES_P256_X25519);
841     ADD_ALL_TESTS(test_init_multiple, TEST_KEYTYPES_P256_X25519);
842 
843     ADD_ALL_TESTS(test_auth_key_type_mismatch, TEST_KEYTYPES_P256_X25519);
844     ADD_ALL_TESTS(test_no_operation_set, TEST_KEYTYPES_P256_X25519);
845     ADD_ALL_TESTS(test_ikm_small, TEST_KEYTYPES_P256_X25519);
846     ADD_ALL_TESTS(test_input_size_small, TEST_KEYTYPES_P256_X25519);
847     ADD_ALL_TESTS(test_null_params, TEST_KEYTYPES_P256_X25519);
848     ADD_ALL_TESTS(test_set_params, TEST_KEYTYPES_P256_X25519);
849     ADD_ALL_TESTS(test_nopublic,
850         TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
851     ADD_ALL_TESTS(test_noauthpublic,
852         TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
853 #else
854     ADD_ALL_TESTS(test_settables, TEST_KEYTYPE_P256);
855     ADD_ALL_TESTS(test_init_multiple, TEST_KEYTYPE_P256);
856 
857     ADD_ALL_TESTS(test_auth_key_type_mismatch, TEST_KEYTYPE_P256);
858     ADD_ALL_TESTS(test_no_operation_set, TEST_KEYTYPE_P256);
859     ADD_ALL_TESTS(test_ikm_small, TEST_KEYTYPE_P256);
860     ADD_ALL_TESTS(test_input_size_small, TEST_KEYTYPE_P256);
861     ADD_ALL_TESTS(test_null_params, TEST_KEYTYPE_P256);
862     ADD_ALL_TESTS(test_set_params, TEST_KEYTYPE_P256);
863     ADD_ALL_TESTS(test_nopublic,
864         TEST_KEM_ENCAP_DECAP * TEST_KEYTYPE_P256);
865     ADD_ALL_TESTS(test_noauthpublic,
866         TEST_KEM_ENCAP_DECAP * TEST_KEYTYPE_P256);
867 #endif
868     /* EC Specific tests */
869     ADD_ALL_TESTS(test_ec_dhkem_derivekey, OSSL_NELEM(ec_derivekey_data));
870     ADD_ALL_TESTS(test_ec_noikme,
871         TEST_TYPE_AUTH_NOAUTH * OSSL_NELEM(dhkem_supported_curves));
872     ADD_TEST(test_ec_auth_key_curve_mismatch);
873     ADD_TEST(test_ec_invalid_private_key);
874     ADD_TEST(test_ec_dhkem_derivekey_fail);
875     ADD_TEST(test_ec_curve_nonnist);
876     ADD_TEST(test_ec_curve_unsupported);
877     ADD_TEST(test_ec_invalid_decap_enc_buffer);
878     ADD_TEST(test_ec_public_key_infinity);
879     ADD_ALL_TESTS(test_ec_badpublic, TEST_KEM_ENCAP_DECAP);
880     ADD_ALL_TESTS(test_ec_badauth, TEST_KEM_ENCAP_DECAP);
881 
882     /* ECX specific tests */
883 #ifndef OPENSSL_NO_ECX
884     ADD_ALL_TESTS(test_ecx_dhkem_derivekey, OSSL_NELEM(ecx_derivekey_data));
885     ADD_TEST(test_ecx_auth_key_curve_mismatch);
886     ADD_TEST(test_ed_curve_unsupported);
887 #endif
888     return 1;
889 err:
890     return 0;
891 }
892 
cleanup_tests(void)893 void cleanup_tests(void)
894 {
895     EVP_PKEY_free(rkey[1]);
896     EVP_PKEY_free(rkey[0]);
897     EVP_PKEY_CTX_free(rctx[1]);
898     EVP_PKEY_CTX_free(rctx[0]);
899     OSSL_PROVIDER_unload(libprov);
900     OSSL_LIB_CTX_free(libctx);
901     OSSL_PROVIDER_unload(nullprov);
902 }
903