]> git.ipfire.org Git - thirdparty/openssl.git/blame - test/evp_pkey_dhkem_test.c
Security hardening: Expose Build flags for Position Independed Execution (PIE)
[thirdparty/openssl.git] / test / evp_pkey_dhkem_test.c
CommitLineData
78c44b05 1/*
da1c088f 2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
78c44b05 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
29static OSSL_LIB_CTX *libctx = NULL;
30static OSSL_PROVIDER *nullprov = NULL;
31static OSSL_PROVIDER *libprov = NULL;
32static OSSL_PARAM opparam[2];
33static EVP_PKEY *rkey[TEST_KEYTYPES_P256_X25519] = { NULL, NULL };
34static EVP_PKEY_CTX *rctx[TEST_KEYTYPES_P256_X25519] = { NULL, NULL };
35
36#include "dhkem_test.inc"
37
38/* Perform encapsulate KAT's */
39static 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);
58err:
59 EVP_PKEY_free(spriv);
60 EVP_PKEY_free(rpub);
61 return ret;
62}
63
64/* Perform decapsulate KAT's */
65static 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);
81err:
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 */
88static 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 */
105static 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 */
116static 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;
160err:
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 */
168static 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 */
183static 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 */
206static 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);
241err:
242 return ret;
243}
244
245/* Fail if the auth key has a different curve */
246static 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 */
260static 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
269static 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
290static 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 */
324static 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
343static 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);
385err:
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 */
393static 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;
421err:
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 */
428static 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;
457err:
458 EVP_PKEY_free(auth);
459 return ret;
460}
461
462/* EC specific tests */
463
464/* Perform EC DHKEM KATs */
465static 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 */
507static 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);
564err:
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 */
572static 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
587static int test_ec_curve_nonnist(void)
588{
589 return do_ec_curve_failtest("secp256k1");
590}
591
592static 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 */
598static 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;
640err:
641 EVP_PKEY_free(recippriv);
642 EVP_PKEY_CTX_free(ctx);
643 return ret;
644}
645
646static 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;
681err:
682 EVP_PKEY_free(auth);
683 return ret;
684}
685
686static 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
4032cd9a 702#ifndef OPENSSL_NO_ECX
78c44b05 703/* ECX specific tests */
704
705/* Perform ECX DHKEM KATs */
706static int test_ecx_dhkem_derivekey(int tstid)
707{
708 int ret;
709 OSSL_PARAM params[2];
710 EVP_PKEY_CTX *genctx;
711 EVP_PKEY *pkey = NULL;
712 unsigned char pubkey[64];
713 unsigned char privkey[64];
714 unsigned char masked_priv[64];
715 size_t pubkeylen = 0, privkeylen = 0;
716 const TEST_DERIVEKEY_DATA *t = &ecx_derivekey_data[tstid];
717
718 memcpy(masked_priv, t->priv, t->privlen);
719 if (OPENSSL_strcasecmp(t->curvename, "X25519") == 0) {
720 /*
721 * The RFC test vector seems incorrect since it is not in serialized form,
722 * So manually do the conversion here for now.
723 */
724 masked_priv[0] &= 248;
725 masked_priv[t->privlen - 1] &= 127;
726 masked_priv[t->privlen - 1] |= 64;
727 } else {
728 masked_priv[0] &= 252;
729 masked_priv[t->privlen - 1] |= 128;
730 }
731
732 params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
733 (char *)t->ikm, t->ikmlen);
734 params[1] = OSSL_PARAM_construct_end();
735
736 ret = TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, t->curvename, NULL))
737 && TEST_int_eq(EVP_PKEY_keygen_init(genctx), 1)
738 && TEST_int_eq(EVP_PKEY_CTX_set_params(genctx, params), 1)
739 && TEST_int_eq(EVP_PKEY_keygen(genctx, &pkey), 1)
740 && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
741 OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
742 pubkey, sizeof(pubkey), &pubkeylen), 1)
743 && TEST_int_eq(EVP_PKEY_get_octet_string_param(pkey,
744 OSSL_PKEY_PARAM_PRIV_KEY,
745 privkey, sizeof(privkey), &privkeylen), 1)
746 && TEST_mem_eq(t->pub, t->publen, pubkey, pubkeylen)
747 && TEST_mem_eq(masked_priv, t->privlen, privkey, privkeylen);
748
749 EVP_PKEY_free(pkey);
750 EVP_PKEY_CTX_free(genctx);
751 return ret;
752}
753
754/* Fail if the auth key has a different curve */
755static int test_ecx_auth_key_curve_mismatch(void)
756{
757 int ret = 0;
758 EVP_PKEY *auth = NULL;
759
760 if (!TEST_ptr(auth = EVP_PKEY_Q_keygen(libctx, NULL, "X448")))
761 return 0;
762
763 ret = TEST_int_eq(EVP_PKEY_auth_encapsulate_init(rctx[TEST_KEYTYPE_X25519],
764 auth, opparam), 0);
765 EVP_PKEY_free(auth);
766 return ret;
767}
768
769/* Fail if ED448 is used for DHKEM */
770static int test_ed_curve_unsupported(void)
771{
772 int ret;
773 EVP_PKEY *key = NULL;
774 EVP_PKEY_CTX *ctx = NULL;
775
776 ret = TEST_ptr(key = EVP_PKEY_Q_keygen(libctx, NULL, "ED448"))
777 && TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))
778 && TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), -2)
779 && TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), -2);
780 EVP_PKEY_free(key);
781 EVP_PKEY_CTX_free(ctx);
782 return ret;
783}
4032cd9a 784#endif
78c44b05 785
786int setup_tests(void)
787{
788 const char *prov_name = "default";
789 char *config_file = NULL;
790 char *op = OSSL_KEM_PARAM_OPERATION_DHKEM;
791
792 if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name))
793 return 0;
794 opparam[0] = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
795 op, 0);
796 opparam[1] = OSSL_PARAM_construct_end();
797
798 /* Create P256 and X25519 keys and ctxs */
799 if (!TEST_ptr(rkey[TEST_KEYTYPE_P256] = EVP_PKEY_Q_keygen(libctx, NULL,
800 "EC", "P-256")))
801 goto err;
4032cd9a 802#ifndef OPENSSL_NO_ECX
78c44b05 803 if (!TEST_ptr(rkey[TEST_KEYTYPE_X25519] = EVP_PKEY_Q_keygen(libctx, NULL,
804 "X25519")))
805 goto err;
4032cd9a 806#endif
78c44b05 807 if (!TEST_ptr(rctx[TEST_KEYTYPE_P256] =
808 EVP_PKEY_CTX_new_from_pkey(libctx,
809 rkey[TEST_KEYTYPE_P256], NULL)))
810 goto err;
4032cd9a 811#ifndef OPENSSL_NO_ECX
78c44b05 812 if (!TEST_ptr(rctx[TEST_KEYTYPE_X25519] =
813 EVP_PKEY_CTX_new_from_pkey(libctx,
814 rkey[TEST_KEYTYPE_X25519], NULL)))
815 goto err;
4032cd9a 816#endif
78c44b05 817
818 ADD_ALL_TESTS(test_dhkem_encapsulate, OSSL_NELEM(ec_encapdata));
819 ADD_ALL_TESTS(test_dhkem_decapsulate, OSSL_NELEM(ec_encapdata));
4032cd9a 820#ifndef OPENSSL_NO_ECX
78c44b05 821 ADD_ALL_TESTS(test_settables, TEST_KEYTYPES_P256_X25519);
822 ADD_ALL_TESTS(test_init_multiple, TEST_KEYTYPES_P256_X25519);
823
824 ADD_ALL_TESTS(test_auth_key_type_mismatch, TEST_KEYTYPES_P256_X25519);
825 ADD_ALL_TESTS(test_no_operation_set, TEST_KEYTYPES_P256_X25519);
826 ADD_ALL_TESTS(test_ikm_small, TEST_KEYTYPES_P256_X25519);
827 ADD_ALL_TESTS(test_input_size_small, TEST_KEYTYPES_P256_X25519);
828 ADD_ALL_TESTS(test_null_params, TEST_KEYTYPES_P256_X25519);
829 ADD_ALL_TESTS(test_set_params, TEST_KEYTYPES_P256_X25519);
830 ADD_ALL_TESTS(test_nopublic,
831 TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
832 ADD_ALL_TESTS(test_noauthpublic,
833 TEST_KEM_ENCAP_DECAP * TEST_KEYTYPES_P256_X25519);
4032cd9a
YL
834#else
835 ADD_ALL_TESTS(test_settables, TEST_KEYTYPE_P256);
836 ADD_ALL_TESTS(test_init_multiple, TEST_KEYTYPE_P256);
837
838 ADD_ALL_TESTS(test_auth_key_type_mismatch, TEST_KEYTYPE_P256);
839 ADD_ALL_TESTS(test_no_operation_set, TEST_KEYTYPE_P256);
840 ADD_ALL_TESTS(test_ikm_small, TEST_KEYTYPE_P256);
841 ADD_ALL_TESTS(test_input_size_small, TEST_KEYTYPE_P256);
842 ADD_ALL_TESTS(test_null_params, TEST_KEYTYPE_P256);
843 ADD_ALL_TESTS(test_set_params, TEST_KEYTYPE_P256);
844 ADD_ALL_TESTS(test_nopublic,
845 TEST_KEM_ENCAP_DECAP * TEST_KEYTYPE_P256);
846 ADD_ALL_TESTS(test_noauthpublic,
847 TEST_KEM_ENCAP_DECAP * TEST_KEYTYPE_P256);
848#endif
78c44b05 849 /* EC Specific tests */
850 ADD_ALL_TESTS(test_ec_dhkem_derivekey, OSSL_NELEM(ec_derivekey_data));
851 ADD_ALL_TESTS(test_ec_noikme,
852 TEST_TYPE_AUTH_NOAUTH * OSSL_NELEM(dhkem_supported_curves));
853 ADD_TEST(test_ec_auth_key_curve_mismatch);
854 ADD_TEST(test_ec_invalid_private_key);
855 ADD_TEST(test_ec_dhkem_derivekey_fail);
856 ADD_TEST(test_ec_curve_nonnist);
857 ADD_TEST(test_ec_curve_unsupported);
858 ADD_TEST(test_ec_invalid_decap_enc_buffer);
859 ADD_TEST(test_ec_public_key_infinity);
860 ADD_ALL_TESTS(test_ec_badpublic, TEST_KEM_ENCAP_DECAP);
861 ADD_ALL_TESTS(test_ec_badauth, TEST_KEM_ENCAP_DECAP);
862
863 /* ECX specific tests */
4032cd9a 864#ifndef OPENSSL_NO_ECX
78c44b05 865 ADD_ALL_TESTS(test_ecx_dhkem_derivekey, OSSL_NELEM(ecx_derivekey_data));
866 ADD_TEST(test_ecx_auth_key_curve_mismatch);
867 ADD_TEST(test_ed_curve_unsupported);
4032cd9a 868#endif
78c44b05 869 return 1;
870err:
871 return 0;
872}
873
874void cleanup_tests(void)
875{
876 EVP_PKEY_free(rkey[1]);
877 EVP_PKEY_free(rkey[0]);
878 EVP_PKEY_CTX_free(rctx[1]);
879 EVP_PKEY_CTX_free(rctx[0]);
880 OSSL_PROVIDER_unload(libprov);
881 OSSL_LIB_CTX_free(libctx);
882 OSSL_PROVIDER_unload(nullprov);
883}