]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
aa6bb135 | 2 | * Copyright 2006-2016 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 | ||
f23bc0b7 | 35 | if (ctx->keytype == NULL || ctx->engine != NULL) |
2c938e2e MC |
36 | goto legacy; |
37 | ||
f6aa5774 RL |
38 | /* Ensure that the key is provided. If not, go legacy */ |
39 | tmp_keymgmt = ctx->keymgmt; | |
40 | provkey = evp_pkey_make_provided(ctx->pkey, ctx->libctx, | |
41 | &tmp_keymgmt, ctx->propquery, 0); | |
42 | if (provkey == NULL) | |
43 | goto legacy; | |
44 | EVP_KEYMGMT_up_ref(tmp_keymgmt); | |
45 | EVP_KEYMGMT_free(ctx->keymgmt); | |
46 | ctx->keymgmt = tmp_keymgmt; | |
f23bc0b7 | 47 | |
f6aa5774 RL |
48 | if (ctx->keymgmt->query_operation_name != NULL) |
49 | supported_ciph = | |
50 | ctx->keymgmt->query_operation_name(OSSL_OP_ASYM_CIPHER); | |
f23bc0b7 | 51 | |
f6aa5774 RL |
52 | /* |
53 | * If we didn't get a supported ciph, assume there is one with the | |
54 | * same name as the key type. | |
55 | */ | |
56 | if (supported_ciph == NULL) | |
57 | supported_ciph = ctx->keytype; | |
f23bc0b7 | 58 | |
f6aa5774 RL |
59 | /* |
60 | * Because we cleared out old ops, we shouldn't need to worry about | |
61 | * checking if cipher is already there. | |
62 | */ | |
63 | cipher = | |
64 | EVP_ASYM_CIPHER_fetch(ctx->libctx, supported_ciph, ctx->propquery); | |
2c938e2e | 65 | |
f6aa5774 | 66 | if (cipher == NULL |
2c938e2e MC |
67 | || (EVP_KEYMGMT_provider(ctx->keymgmt) |
68 | != EVP_ASYM_CIPHER_provider(cipher))) { | |
69 | /* | |
70 | * We don't have the full support we need with provided methods, | |
71 | * let's go see if legacy does. Also, we don't need to free | |
72 | * ctx->keymgmt here, as it's not necessarily tied to this | |
73 | * operation. It will be freed by EVP_PKEY_CTX_free(). | |
74 | */ | |
75 | EVP_ASYM_CIPHER_free(cipher); | |
76 | goto legacy; | |
77 | } | |
78 | ||
79 | ctx->op.ciph.cipher = cipher; | |
2c938e2e MC |
80 | ctx->op.ciph.ciphprovctx = cipher->newctx(ossl_provider_ctx(cipher->prov)); |
81 | if (ctx->op.ciph.ciphprovctx == NULL) { | |
82 | /* The provider key can stay in the cache */ | |
83 | EVPerr(0, EVP_R_INITIALIZATION_ERROR); | |
84 | goto err; | |
85 | } | |
86 | ||
87 | switch (operation) { | |
88 | case EVP_PKEY_OP_ENCRYPT: | |
89 | if (cipher->encrypt_init == NULL) { | |
90 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
91 | ret = -2; | |
92 | goto err; | |
93 | } | |
94 | ret = cipher->encrypt_init(ctx->op.ciph.ciphprovctx, provkey); | |
95 | break; | |
96 | case EVP_PKEY_OP_DECRYPT: | |
97 | if (cipher->decrypt_init == NULL) { | |
98 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
99 | ret = -2; | |
100 | goto err; | |
101 | } | |
102 | ret = cipher->decrypt_init(ctx->op.ciph.ciphprovctx, provkey); | |
103 | break; | |
104 | default: | |
105 | EVPerr(0, EVP_R_INITIALIZATION_ERROR); | |
106 | goto err; | |
107 | } | |
108 | ||
109 | if (ret <= 0) { | |
110 | cipher->freectx(ctx->op.ciph.ciphprovctx); | |
111 | ctx->op.ciph.ciphprovctx = NULL; | |
112 | goto err; | |
113 | } | |
114 | return 1; | |
115 | ||
116 | legacy: | |
117 | if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) { | |
118 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
119 | return -2; | |
120 | } | |
121 | switch(ctx->operation) { | |
122 | case EVP_PKEY_OP_ENCRYPT: | |
123 | if (ctx->pmeth->encrypt_init == NULL) | |
124 | return 1; | |
125 | ret = ctx->pmeth->encrypt_init(ctx); | |
126 | break; | |
127 | case EVP_PKEY_OP_DECRYPT: | |
128 | if (ctx->pmeth->decrypt_init == NULL) | |
129 | return 1; | |
130 | ret = ctx->pmeth->decrypt_init(ctx); | |
131 | break; | |
132 | default: | |
133 | EVPerr(0, EVP_R_INITIALIZATION_ERROR); | |
134 | ret = -1; | |
135 | } | |
136 | ||
137 | err: | |
0f113f3e MC |
138 | if (ret <= 0) |
139 | ctx->operation = EVP_PKEY_OP_UNDEFINED; | |
140 | return ret; | |
141 | } | |
f733a5ef | 142 | |
2c938e2e MC |
143 | int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) |
144 | { | |
145 | return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_ENCRYPT); | |
146 | } | |
147 | ||
f733a5ef | 148 | int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, |
0f113f3e MC |
149 | unsigned char *out, size_t *outlen, |
150 | const unsigned char *in, size_t inlen) | |
151 | { | |
2c938e2e MC |
152 | int ret; |
153 | ||
154 | if (ctx == NULL) { | |
155 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
0f113f3e MC |
156 | return -2; |
157 | } | |
2c938e2e | 158 | |
0f113f3e | 159 | if (ctx->operation != EVP_PKEY_OP_ENCRYPT) { |
2c938e2e | 160 | EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); |
0f113f3e MC |
161 | return -1; |
162 | } | |
2c938e2e MC |
163 | |
164 | if (ctx->op.ciph.ciphprovctx == NULL) | |
165 | goto legacy; | |
166 | ||
167 | ret = ctx->op.ciph.cipher->encrypt(ctx->op.ciph.ciphprovctx, out, outlen, | |
168 | (out == NULL ? 0 : *outlen), in, inlen); | |
169 | return ret; | |
170 | ||
171 | legacy: | |
172 | if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) { | |
173 | EVPerr(EVP_F_EVP_PKEY_ENCRYPT, | |
174 | EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
175 | return -2; | |
176 | } | |
0f113f3e MC |
177 | M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT) |
178 | return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen); | |
179 | } | |
f733a5ef | 180 | |
cd763898 | 181 | int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) |
0f113f3e | 182 | { |
2c938e2e | 183 | return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_DECRYPT); |
0f113f3e | 184 | } |
f733a5ef DSH |
185 | |
186 | int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, | |
0f113f3e MC |
187 | unsigned char *out, size_t *outlen, |
188 | const unsigned char *in, size_t inlen) | |
189 | { | |
2c938e2e MC |
190 | int ret; |
191 | ||
192 | if (ctx == NULL) { | |
193 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
0f113f3e MC |
194 | return -2; |
195 | } | |
2c938e2e | 196 | |
0f113f3e | 197 | if (ctx->operation != EVP_PKEY_OP_DECRYPT) { |
2c938e2e | 198 | EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); |
0f113f3e MC |
199 | return -1; |
200 | } | |
2c938e2e MC |
201 | |
202 | if (ctx->op.ciph.ciphprovctx == NULL) | |
203 | goto legacy; | |
204 | ||
205 | ret = ctx->op.ciph.cipher->decrypt(ctx->op.ciph.ciphprovctx, out, outlen, | |
206 | (out == NULL ? 0 : *outlen), in, inlen); | |
207 | return ret; | |
208 | ||
209 | legacy: | |
210 | if (ctx->pmeth == NULL || ctx->pmeth->decrypt == NULL) { | |
211 | EVPerr(EVP_F_EVP_PKEY_DECRYPT, | |
212 | EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
213 | return -2; | |
214 | } | |
0f113f3e MC |
215 | M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT) |
216 | return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen); | |
217 | } | |
2c938e2e MC |
218 | |
219 | ||
220 | static EVP_ASYM_CIPHER *evp_asym_cipher_new(OSSL_PROVIDER *prov) | |
221 | { | |
222 | EVP_ASYM_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_ASYM_CIPHER)); | |
223 | ||
c1ff5994 MC |
224 | if (cipher == NULL) { |
225 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); | |
226 | return NULL; | |
227 | } | |
228 | ||
2c938e2e MC |
229 | cipher->lock = CRYPTO_THREAD_lock_new(); |
230 | if (cipher->lock == NULL) { | |
c1ff5994 | 231 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); |
2c938e2e MC |
232 | OPENSSL_free(cipher); |
233 | return NULL; | |
234 | } | |
235 | cipher->prov = prov; | |
236 | ossl_provider_up_ref(prov); | |
237 | cipher->refcnt = 1; | |
238 | ||
239 | return cipher; | |
240 | } | |
241 | ||
242 | static void *evp_asym_cipher_from_dispatch(int name_id, | |
243 | const OSSL_DISPATCH *fns, | |
244 | OSSL_PROVIDER *prov) | |
245 | { | |
246 | EVP_ASYM_CIPHER *cipher = NULL; | |
247 | int ctxfncnt = 0, encfncnt = 0, decfncnt = 0; | |
248 | int gparamfncnt = 0, sparamfncnt = 0; | |
249 | ||
250 | if ((cipher = evp_asym_cipher_new(prov)) == NULL) { | |
251 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); | |
252 | goto err; | |
253 | } | |
254 | ||
255 | cipher->name_id = name_id; | |
256 | ||
257 | for (; fns->function_id != 0; fns++) { | |
258 | switch (fns->function_id) { | |
259 | case OSSL_FUNC_ASYM_CIPHER_NEWCTX: | |
260 | if (cipher->newctx != NULL) | |
261 | break; | |
262 | cipher->newctx = OSSL_get_OP_asym_cipher_newctx(fns); | |
263 | ctxfncnt++; | |
264 | break; | |
265 | case OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT: | |
266 | if (cipher->encrypt_init != NULL) | |
267 | break; | |
268 | cipher->encrypt_init = OSSL_get_OP_asym_cipher_encrypt_init(fns); | |
269 | encfncnt++; | |
270 | break; | |
271 | case OSSL_FUNC_ASYM_CIPHER_ENCRYPT: | |
272 | if (cipher->encrypt != NULL) | |
273 | break; | |
274 | cipher->encrypt = OSSL_get_OP_asym_cipher_encrypt(fns); | |
275 | encfncnt++; | |
276 | break; | |
277 | case OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT: | |
278 | if (cipher->decrypt_init != NULL) | |
279 | break; | |
280 | cipher->decrypt_init = OSSL_get_OP_asym_cipher_decrypt_init(fns); | |
281 | decfncnt++; | |
282 | break; | |
283 | case OSSL_FUNC_ASYM_CIPHER_DECRYPT: | |
284 | if (cipher->decrypt != NULL) | |
285 | break; | |
286 | cipher->decrypt = OSSL_get_OP_asym_cipher_decrypt(fns); | |
287 | decfncnt++; | |
288 | break; | |
289 | case OSSL_FUNC_ASYM_CIPHER_FREECTX: | |
290 | if (cipher->freectx != NULL) | |
291 | break; | |
292 | cipher->freectx = OSSL_get_OP_asym_cipher_freectx(fns); | |
293 | ctxfncnt++; | |
294 | break; | |
295 | case OSSL_FUNC_ASYM_CIPHER_DUPCTX: | |
296 | if (cipher->dupctx != NULL) | |
297 | break; | |
298 | cipher->dupctx = OSSL_get_OP_asym_cipher_dupctx(fns); | |
299 | break; | |
300 | case OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS: | |
301 | if (cipher->get_ctx_params != NULL) | |
302 | break; | |
303 | cipher->get_ctx_params | |
304 | = OSSL_get_OP_asym_cipher_get_ctx_params(fns); | |
305 | gparamfncnt++; | |
306 | break; | |
307 | case OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS: | |
308 | if (cipher->gettable_ctx_params != NULL) | |
309 | break; | |
310 | cipher->gettable_ctx_params | |
311 | = OSSL_get_OP_asym_cipher_gettable_ctx_params(fns); | |
312 | gparamfncnt++; | |
313 | break; | |
314 | case OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS: | |
315 | if (cipher->set_ctx_params != NULL) | |
316 | break; | |
317 | cipher->set_ctx_params | |
318 | = OSSL_get_OP_asym_cipher_set_ctx_params(fns); | |
319 | sparamfncnt++; | |
320 | break; | |
321 | case OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS: | |
322 | if (cipher->settable_ctx_params != NULL) | |
323 | break; | |
324 | cipher->settable_ctx_params | |
325 | = OSSL_get_OP_asym_cipher_settable_ctx_params(fns); | |
326 | sparamfncnt++; | |
327 | break; | |
328 | } | |
329 | } | |
330 | if (ctxfncnt != 2 | |
331 | || (encfncnt != 0 && encfncnt != 2) | |
332 | || (decfncnt != 0 && decfncnt != 2) | |
333 | || (encfncnt != 2 && decfncnt != 2) | |
334 | || (gparamfncnt != 0 && gparamfncnt != 2) | |
335 | || (sparamfncnt != 0 && sparamfncnt != 2)) { | |
336 | /* | |
337 | * In order to be a consistent set of functions we must have at least | |
338 | * a set of context functions (newctx and freectx) as well as a pair of | |
339 | * "cipher" functions: (encrypt_init, encrypt) or | |
340 | * (decrypt_init decrypt). set_ctx_params and settable_ctx_params are | |
341 | * optional, but if one of them is present then the other one must also | |
342 | * be present. The same applies to get_ctx_params and | |
343 | * gettable_ctx_params. The dupctx function is optional. | |
344 | */ | |
345 | ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); | |
346 | goto err; | |
347 | } | |
348 | ||
349 | return cipher; | |
350 | err: | |
351 | EVP_ASYM_CIPHER_free(cipher); | |
352 | return NULL; | |
353 | } | |
354 | ||
355 | void EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER *cipher) | |
356 | { | |
357 | if (cipher != NULL) { | |
358 | int i; | |
359 | ||
360 | CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock); | |
361 | if (i > 0) | |
362 | return; | |
363 | ossl_provider_free(cipher->prov); | |
364 | CRYPTO_THREAD_lock_free(cipher->lock); | |
365 | OPENSSL_free(cipher); | |
366 | } | |
367 | } | |
368 | ||
369 | int EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER *cipher) | |
370 | { | |
371 | int ref = 0; | |
372 | ||
373 | CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock); | |
374 | return 1; | |
375 | } | |
376 | ||
377 | OSSL_PROVIDER *EVP_ASYM_CIPHER_provider(const EVP_ASYM_CIPHER *cipher) | |
378 | { | |
379 | return cipher->prov; | |
380 | } | |
381 | ||
382 | EVP_ASYM_CIPHER *EVP_ASYM_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm, | |
383 | const char *properties) | |
384 | { | |
385 | return evp_generic_fetch(ctx, OSSL_OP_ASYM_CIPHER, algorithm, properties, | |
386 | evp_asym_cipher_from_dispatch, | |
387 | (int (*)(void *))EVP_ASYM_CIPHER_up_ref, | |
388 | (void (*)(void *))EVP_ASYM_CIPHER_free); | |
389 | } | |
390 | ||
391 | int EVP_ASYM_CIPHER_is_a(const EVP_ASYM_CIPHER *cipher, const char *name) | |
392 | { | |
e4a1d023 | 393 | return evp_is_a(cipher->prov, cipher->name_id, NULL, name); |
2c938e2e MC |
394 | } |
395 | ||
396 | int EVP_ASYM_CIPHER_number(const EVP_ASYM_CIPHER *cipher) | |
397 | { | |
398 | return cipher->name_id; | |
399 | } | |
400 | ||
401 | void EVP_ASYM_CIPHER_do_all_provided(OPENSSL_CTX *libctx, | |
402 | void (*fn)(EVP_ASYM_CIPHER *cipher, | |
403 | void *arg), | |
404 | void *arg) | |
405 | { | |
406 | evp_generic_do_all(libctx, OSSL_OP_ASYM_CIPHER, | |
407 | (void (*)(void *, void *))fn, arg, | |
408 | evp_asym_cipher_from_dispatch, | |
409 | (void (*)(void *))EVP_ASYM_CIPHER_free); | |
410 | } | |
411 | ||
412 | ||
413 | void EVP_ASYM_CIPHER_names_do_all(const EVP_ASYM_CIPHER *cipher, | |
414 | void (*fn)(const char *name, void *data), | |
415 | void *data) | |
416 | { | |
417 | if (cipher->prov != NULL) | |
418 | evp_names_do_all(cipher->prov, cipher->name_id, fn, data); | |
419 | } | |
420 |