]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/pmeth_fn.c
EVP: Add evp_pkey_make_provided() and refactor around it
[thirdparty/openssl.git] / crypto / evp / pmeth_fn.c
CommitLineData
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 19static 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
143int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx)
144{
145 return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_ENCRYPT);
146}
147
f733a5ef 148int 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 181int 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
186int 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
220static 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
242static 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
355void 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
369int 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
377OSSL_PROVIDER *EVP_ASYM_CIPHER_provider(const EVP_ASYM_CIPHER *cipher)
378{
379 return cipher->prov;
380}
381
382EVP_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
391int 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
396int EVP_ASYM_CIPHER_number(const EVP_ASYM_CIPHER *cipher)
397{
398 return cipher->name_id;
399}
400
401void 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
413void 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