]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | ||
4032cd9a | 702 | #ifndef OPENSSL_NO_ECX |
78c44b05 | 703 | /* ECX specific tests */ |
704 | ||
705 | /* Perform ECX DHKEM KATs */ | |
706 | static 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 */ | |
755 | static 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 */ | |
770 | static 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 | |
786 | int 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; |
870 | err: | |
871 | return 0; | |
872 | } | |
873 | ||
874 | void 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 | } |