]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
33388b44 | 2 | * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. |
f733a5ef | 3 | * |
4a8b0c55 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
aa6bb135 RS |
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 | |
f733a5ef DSH |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
c20276e4 | 12 | #include <openssl/objects.h> |
f733a5ef | 13 | #include <openssl/evp.h> |
ff64702b | 14 | #include "internal/cryptlib.h" |
25f2138b | 15 | #include "crypto/evp.h" |
dfcb5d29 | 16 | #include "internal/provider.h" |
706457b7 | 17 | #include "evp_local.h" |
b010b7c4 | 18 | |
2c938e2e | 19 | static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation) |
0f113f3e | 20 | { |
2c938e2e MC |
21 | int ret = 0; |
22 | void *provkey = NULL; | |
23 | EVP_ASYM_CIPHER *cipher = NULL; | |
f6aa5774 RL |
24 | EVP_KEYMGMT *tmp_keymgmt = NULL; |
25 | const char *supported_ciph = NULL; | |
2c938e2e MC |
26 | |
27 | if (ctx == NULL) { | |
28 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
0f113f3e MC |
29 | return -2; |
30 | } | |
2c938e2e MC |
31 | |
32 | evp_pkey_ctx_free_old_ops(ctx); | |
33 | ctx->operation = operation; | |
34 | ||
0b9dd384 RL |
35 | /* |
36 | * TODO when we stop falling back to legacy, this and the ERR_pop_to_mark() | |
37 | * calls can be removed. | |
38 | */ | |
39 | ERR_set_mark(); | |
40 | ||
df13defd | 41 | if (ctx->engine != NULL || ctx->keytype == NULL) |
2c938e2e MC |
42 | goto legacy; |
43 | ||
3c6ed955 RL |
44 | /* |
45 | * Ensure that the key is provided, either natively, or as a cached export. | |
46 | * If not, go legacy | |
47 | */ | |
f6aa5774 | 48 | tmp_keymgmt = ctx->keymgmt; |
3c6ed955 RL |
49 | provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, |
50 | &tmp_keymgmt, ctx->propquery); | |
f6aa5774 RL |
51 | if (provkey == NULL) |
52 | goto legacy; | |
0b9dd384 RL |
53 | if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { |
54 | ERR_clear_last_mark(); | |
55 | ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); | |
56 | goto err; | |
57 | } | |
f6aa5774 RL |
58 | EVP_KEYMGMT_free(ctx->keymgmt); |
59 | ctx->keymgmt = tmp_keymgmt; | |
f23bc0b7 | 60 | |
f6aa5774 RL |
61 | if (ctx->keymgmt->query_operation_name != NULL) |
62 | supported_ciph = | |
63 | ctx->keymgmt->query_operation_name(OSSL_OP_ASYM_CIPHER); | |
f23bc0b7 | 64 | |
f6aa5774 RL |
65 | /* |
66 | * If we didn't get a supported ciph, assume there is one with the | |
67 | * same name as the key type. | |
68 | */ | |
69 | if (supported_ciph == NULL) | |
70 | supported_ciph = ctx->keytype; | |
f23bc0b7 | 71 | |
f6aa5774 RL |
72 | /* |
73 | * Because we cleared out old ops, we shouldn't need to worry about | |
74 | * checking if cipher is already there. | |
75 | */ | |
76 | cipher = | |
77 | EVP_ASYM_CIPHER_fetch(ctx->libctx, supported_ciph, ctx->propquery); | |
2c938e2e | 78 | |
f6aa5774 | 79 | if (cipher == NULL |
2c938e2e MC |
80 | || (EVP_KEYMGMT_provider(ctx->keymgmt) |
81 | != EVP_ASYM_CIPHER_provider(cipher))) { | |
82 | /* | |
0b9dd384 RL |
83 | * We don't need to free ctx->keymgmt here, as it's not necessarily |
84 | * tied to this operation. It will be freed by EVP_PKEY_CTX_free(). | |
2c938e2e MC |
85 | */ |
86 | EVP_ASYM_CIPHER_free(cipher); | |
87 | goto legacy; | |
88 | } | |
89 | ||
0b9dd384 RL |
90 | /* |
91 | * TODO remove this when legacy is gone | |
92 | * If we don't have the full support we need with provided methods, | |
93 | * let's go see if legacy does. | |
94 | */ | |
95 | ERR_pop_to_mark(); | |
96 | ||
97 | /* No more legacy from here down to legacy: */ | |
98 | ||
2c938e2e | 99 | ctx->op.ciph.cipher = cipher; |
2c938e2e MC |
100 | ctx->op.ciph.ciphprovctx = cipher->newctx(ossl_provider_ctx(cipher->prov)); |
101 | if (ctx->op.ciph.ciphprovctx == NULL) { | |
102 | /* The provider key can stay in the cache */ | |
103 | EVPerr(0, EVP_R_INITIALIZATION_ERROR); | |
104 | goto err; | |
105 | } | |
106 | ||
107 | switch (operation) { | |
108 | case EVP_PKEY_OP_ENCRYPT: | |
109 | if (cipher->encrypt_init == NULL) { | |
110 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
111 | ret = -2; | |
112 | goto err; | |
113 | } | |
114 | ret = cipher->encrypt_init(ctx->op.ciph.ciphprovctx, provkey); | |
115 | break; | |
116 | case EVP_PKEY_OP_DECRYPT: | |
117 | if (cipher->decrypt_init == NULL) { | |
118 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
119 | ret = -2; | |
120 | goto err; | |
121 | } | |
122 | ret = cipher->decrypt_init(ctx->op.ciph.ciphprovctx, provkey); | |
123 | break; | |
124 | default: | |
125 | EVPerr(0, EVP_R_INITIALIZATION_ERROR); | |
126 | goto err; | |
127 | } | |
128 | ||
c7fa9297 | 129 | if (ret <= 0) |
2c938e2e | 130 | goto err; |
2c938e2e MC |
131 | return 1; |
132 | ||
133 | legacy: | |
0b9dd384 RL |
134 | /* |
135 | * TODO remove this when legacy is gone | |
136 | * If we don't have the full support we need with provided methods, | |
137 | * let's go see if legacy does. | |
138 | */ | |
139 | ERR_pop_to_mark(); | |
140 | ||
2c938e2e MC |
141 | if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) { |
142 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
143 | return -2; | |
144 | } | |
145 | switch(ctx->operation) { | |
146 | case EVP_PKEY_OP_ENCRYPT: | |
147 | if (ctx->pmeth->encrypt_init == NULL) | |
148 | return 1; | |
149 | ret = ctx->pmeth->encrypt_init(ctx); | |
150 | break; | |
151 | case EVP_PKEY_OP_DECRYPT: | |
152 | if (ctx->pmeth->decrypt_init == NULL) | |
153 | return 1; | |
154 | ret = ctx->pmeth->decrypt_init(ctx); | |
155 | break; | |
156 | default: | |
157 | EVPerr(0, EVP_R_INITIALIZATION_ERROR); | |
158 | ret = -1; | |
159 | } | |
160 | ||
161 | err: | |
c7fa9297 RL |
162 | if (ret <= 0) { |
163 | evp_pkey_ctx_free_old_ops(ctx); | |
0f113f3e | 164 | ctx->operation = EVP_PKEY_OP_UNDEFINED; |
c7fa9297 | 165 | } |
0f113f3e MC |
166 | return ret; |
167 | } | |
f733a5ef | 168 | |
2c938e2e MC |
169 | int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) |
170 | { | |
171 | return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_ENCRYPT); | |
172 | } | |
173 | ||
f733a5ef | 174 | int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, |
0f113f3e MC |
175 | unsigned char *out, size_t *outlen, |
176 | const unsigned char *in, size_t inlen) | |
177 | { | |
2c938e2e MC |
178 | int ret; |
179 | ||
180 | if (ctx == NULL) { | |
181 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
0f113f3e MC |
182 | return -2; |
183 | } | |
2c938e2e | 184 | |
0f113f3e | 185 | if (ctx->operation != EVP_PKEY_OP_ENCRYPT) { |
2c938e2e | 186 | EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); |
0f113f3e MC |
187 | return -1; |
188 | } | |
2c938e2e MC |
189 | |
190 | if (ctx->op.ciph.ciphprovctx == NULL) | |
191 | goto legacy; | |
192 | ||
193 | ret = ctx->op.ciph.cipher->encrypt(ctx->op.ciph.ciphprovctx, out, outlen, | |
194 | (out == NULL ? 0 : *outlen), in, inlen); | |
195 | return ret; | |
196 | ||
197 | legacy: | |
198 | if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) { | |
199 | EVPerr(EVP_F_EVP_PKEY_ENCRYPT, | |
200 | EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
201 | return -2; | |
202 | } | |
0f113f3e MC |
203 | M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT) |
204 | return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen); | |
205 | } | |
f733a5ef | 206 | |
cd763898 | 207 | int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) |
0f113f3e | 208 | { |
2c938e2e | 209 | return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_DECRYPT); |
0f113f3e | 210 | } |
f733a5ef DSH |
211 | |
212 | int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, | |
0f113f3e MC |
213 | unsigned char *out, size_t *outlen, |
214 | const unsigned char *in, size_t inlen) | |
215 | { | |
2c938e2e MC |
216 | int ret; |
217 | ||
218 | if (ctx == NULL) { | |
219 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
0f113f3e MC |
220 | return -2; |
221 | } | |
2c938e2e | 222 | |
0f113f3e | 223 | if (ctx->operation != EVP_PKEY_OP_DECRYPT) { |
2c938e2e | 224 | EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); |
0f113f3e MC |
225 | return -1; |
226 | } | |
2c938e2e MC |
227 | |
228 | if (ctx->op.ciph.ciphprovctx == NULL) | |
229 | goto legacy; | |
230 | ||
231 | ret = ctx->op.ciph.cipher->decrypt(ctx->op.ciph.ciphprovctx, out, outlen, | |
232 | (out == NULL ? 0 : *outlen), in, inlen); | |
233 | return ret; | |
234 | ||
235 | legacy: | |
236 | if (ctx->pmeth == NULL || ctx->pmeth->decrypt == NULL) { | |
237 | EVPerr(EVP_F_EVP_PKEY_DECRYPT, | |
238 | EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
239 | return -2; | |
240 | } | |
0f113f3e MC |
241 | M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT) |
242 | return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen); | |
243 | } | |
2c938e2e MC |
244 | |
245 | ||
246 | static EVP_ASYM_CIPHER *evp_asym_cipher_new(OSSL_PROVIDER *prov) | |
247 | { | |
248 | EVP_ASYM_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_ASYM_CIPHER)); | |
249 | ||
c1ff5994 MC |
250 | if (cipher == NULL) { |
251 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); | |
252 | return NULL; | |
253 | } | |
254 | ||
2c938e2e MC |
255 | cipher->lock = CRYPTO_THREAD_lock_new(); |
256 | if (cipher->lock == NULL) { | |
c1ff5994 | 257 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); |
2c938e2e MC |
258 | OPENSSL_free(cipher); |
259 | return NULL; | |
260 | } | |
261 | cipher->prov = prov; | |
262 | ossl_provider_up_ref(prov); | |
263 | cipher->refcnt = 1; | |
264 | ||
265 | return cipher; | |
266 | } | |
267 | ||
268 | static void *evp_asym_cipher_from_dispatch(int name_id, | |
269 | const OSSL_DISPATCH *fns, | |
270 | OSSL_PROVIDER *prov) | |
271 | { | |
272 | EVP_ASYM_CIPHER *cipher = NULL; | |
273 | int ctxfncnt = 0, encfncnt = 0, decfncnt = 0; | |
274 | int gparamfncnt = 0, sparamfncnt = 0; | |
275 | ||
276 | if ((cipher = evp_asym_cipher_new(prov)) == NULL) { | |
277 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); | |
278 | goto err; | |
279 | } | |
280 | ||
281 | cipher->name_id = name_id; | |
282 | ||
283 | for (; fns->function_id != 0; fns++) { | |
284 | switch (fns->function_id) { | |
285 | case OSSL_FUNC_ASYM_CIPHER_NEWCTX: | |
286 | if (cipher->newctx != NULL) | |
287 | break; | |
363b1e5d | 288 | cipher->newctx = OSSL_FUNC_asym_cipher_newctx(fns); |
2c938e2e MC |
289 | ctxfncnt++; |
290 | break; | |
291 | case OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT: | |
292 | if (cipher->encrypt_init != NULL) | |
293 | break; | |
363b1e5d | 294 | cipher->encrypt_init = OSSL_FUNC_asym_cipher_encrypt_init(fns); |
2c938e2e MC |
295 | encfncnt++; |
296 | break; | |
297 | case OSSL_FUNC_ASYM_CIPHER_ENCRYPT: | |
298 | if (cipher->encrypt != NULL) | |
299 | break; | |
363b1e5d | 300 | cipher->encrypt = OSSL_FUNC_asym_cipher_encrypt(fns); |
2c938e2e MC |
301 | encfncnt++; |
302 | break; | |
303 | case OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT: | |
304 | if (cipher->decrypt_init != NULL) | |
305 | break; | |
363b1e5d | 306 | cipher->decrypt_init = OSSL_FUNC_asym_cipher_decrypt_init(fns); |
2c938e2e MC |
307 | decfncnt++; |
308 | break; | |
309 | case OSSL_FUNC_ASYM_CIPHER_DECRYPT: | |
310 | if (cipher->decrypt != NULL) | |
311 | break; | |
363b1e5d | 312 | cipher->decrypt = OSSL_FUNC_asym_cipher_decrypt(fns); |
2c938e2e MC |
313 | decfncnt++; |
314 | break; | |
315 | case OSSL_FUNC_ASYM_CIPHER_FREECTX: | |
316 | if (cipher->freectx != NULL) | |
317 | break; | |
363b1e5d | 318 | cipher->freectx = OSSL_FUNC_asym_cipher_freectx(fns); |
2c938e2e MC |
319 | ctxfncnt++; |
320 | break; | |
321 | case OSSL_FUNC_ASYM_CIPHER_DUPCTX: | |
322 | if (cipher->dupctx != NULL) | |
323 | break; | |
363b1e5d | 324 | cipher->dupctx = OSSL_FUNC_asym_cipher_dupctx(fns); |
2c938e2e MC |
325 | break; |
326 | case OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS: | |
327 | if (cipher->get_ctx_params != NULL) | |
328 | break; | |
329 | cipher->get_ctx_params | |
363b1e5d | 330 | = OSSL_FUNC_asym_cipher_get_ctx_params(fns); |
2c938e2e MC |
331 | gparamfncnt++; |
332 | break; | |
333 | case OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS: | |
334 | if (cipher->gettable_ctx_params != NULL) | |
335 | break; | |
336 | cipher->gettable_ctx_params | |
363b1e5d | 337 | = OSSL_FUNC_asym_cipher_gettable_ctx_params(fns); |
2c938e2e MC |
338 | gparamfncnt++; |
339 | break; | |
340 | case OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS: | |
341 | if (cipher->set_ctx_params != NULL) | |
342 | break; | |
343 | cipher->set_ctx_params | |
363b1e5d | 344 | = OSSL_FUNC_asym_cipher_set_ctx_params(fns); |
2c938e2e MC |
345 | sparamfncnt++; |
346 | break; | |
347 | case OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS: | |
348 | if (cipher->settable_ctx_params != NULL) | |
349 | break; | |
350 | cipher->settable_ctx_params | |
363b1e5d | 351 | = OSSL_FUNC_asym_cipher_settable_ctx_params(fns); |
2c938e2e MC |
352 | sparamfncnt++; |
353 | break; | |
354 | } | |
355 | } | |
356 | if (ctxfncnt != 2 | |
357 | || (encfncnt != 0 && encfncnt != 2) | |
358 | || (decfncnt != 0 && decfncnt != 2) | |
359 | || (encfncnt != 2 && decfncnt != 2) | |
360 | || (gparamfncnt != 0 && gparamfncnt != 2) | |
361 | || (sparamfncnt != 0 && sparamfncnt != 2)) { | |
362 | /* | |
363 | * In order to be a consistent set of functions we must have at least | |
364 | * a set of context functions (newctx and freectx) as well as a pair of | |
365 | * "cipher" functions: (encrypt_init, encrypt) or | |
366 | * (decrypt_init decrypt). set_ctx_params and settable_ctx_params are | |
367 | * optional, but if one of them is present then the other one must also | |
368 | * be present. The same applies to get_ctx_params and | |
369 | * gettable_ctx_params. The dupctx function is optional. | |
370 | */ | |
371 | ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); | |
372 | goto err; | |
373 | } | |
374 | ||
375 | return cipher; | |
376 | err: | |
377 | EVP_ASYM_CIPHER_free(cipher); | |
378 | return NULL; | |
379 | } | |
380 | ||
381 | void EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER *cipher) | |
382 | { | |
383 | if (cipher != NULL) { | |
384 | int i; | |
385 | ||
386 | CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock); | |
387 | if (i > 0) | |
388 | return; | |
389 | ossl_provider_free(cipher->prov); | |
390 | CRYPTO_THREAD_lock_free(cipher->lock); | |
391 | OPENSSL_free(cipher); | |
392 | } | |
393 | } | |
394 | ||
395 | int EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER *cipher) | |
396 | { | |
397 | int ref = 0; | |
398 | ||
399 | CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock); | |
400 | return 1; | |
401 | } | |
402 | ||
403 | OSSL_PROVIDER *EVP_ASYM_CIPHER_provider(const EVP_ASYM_CIPHER *cipher) | |
404 | { | |
405 | return cipher->prov; | |
406 | } | |
407 | ||
408 | EVP_ASYM_CIPHER *EVP_ASYM_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm, | |
409 | const char *properties) | |
410 | { | |
411 | return evp_generic_fetch(ctx, OSSL_OP_ASYM_CIPHER, algorithm, properties, | |
412 | evp_asym_cipher_from_dispatch, | |
413 | (int (*)(void *))EVP_ASYM_CIPHER_up_ref, | |
414 | (void (*)(void *))EVP_ASYM_CIPHER_free); | |
415 | } | |
416 | ||
417 | int EVP_ASYM_CIPHER_is_a(const EVP_ASYM_CIPHER *cipher, const char *name) | |
418 | { | |
e4a1d023 | 419 | return evp_is_a(cipher->prov, cipher->name_id, NULL, name); |
2c938e2e MC |
420 | } |
421 | ||
422 | int EVP_ASYM_CIPHER_number(const EVP_ASYM_CIPHER *cipher) | |
423 | { | |
424 | return cipher->name_id; | |
425 | } | |
426 | ||
427 | void EVP_ASYM_CIPHER_do_all_provided(OPENSSL_CTX *libctx, | |
428 | void (*fn)(EVP_ASYM_CIPHER *cipher, | |
429 | void *arg), | |
430 | void *arg) | |
431 | { | |
432 | evp_generic_do_all(libctx, OSSL_OP_ASYM_CIPHER, | |
433 | (void (*)(void *, void *))fn, arg, | |
434 | evp_asym_cipher_from_dispatch, | |
435 | (void (*)(void *))EVP_ASYM_CIPHER_free); | |
436 | } | |
437 | ||
438 | ||
439 | void EVP_ASYM_CIPHER_names_do_all(const EVP_ASYM_CIPHER *cipher, | |
440 | void (*fn)(const char *name, void *data), | |
441 | void *data) | |
442 | { | |
443 | if (cipher->prov != NULL) | |
444 | evp_names_do_all(cipher->prov, cipher->name_id, fn, data); | |
445 | } | |
446 | ||
1c52bf3c SL |
447 | const OSSL_PARAM *EVP_ASYM_CIPHER_gettable_ctx_params(const EVP_ASYM_CIPHER *cip) |
448 | { | |
449 | void *provctx; | |
450 | ||
451 | if (cip == NULL || cip->gettable_ctx_params == NULL) | |
452 | return NULL; | |
453 | ||
454 | provctx = ossl_provider_ctx(EVP_ASYM_CIPHER_provider(cip)); | |
455 | return cip->gettable_ctx_params(provctx); | |
456 | } | |
457 | ||
458 | const OSSL_PARAM *EVP_ASYM_CIPHER_settable_ctx_params(const EVP_ASYM_CIPHER *cip) | |
459 | { | |
460 | void *provctx; | |
461 | ||
462 | if (cip == NULL || cip->settable_ctx_params == NULL) | |
463 | return NULL; | |
464 | ||
465 | provctx = ossl_provider_ctx(EVP_ASYM_CIPHER_provider(cip)); | |
466 | return cip->settable_ctx_params(provctx); | |
467 | } |