xref: /openbsd-src/lib/libcrypto/evp/pmeth_lib.c (revision e05b8d4e6f0de945e1edc947d55553a43d8c04ad)
1*e05b8d4eStb /* $OpenBSD: pmeth_lib.c,v 1.42 2025/01/20 12:57:28 tb Exp $ */
2f1535dc8Sdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3f1535dc8Sdjm  * project 2006.
4f1535dc8Sdjm  */
5f1535dc8Sdjm /* ====================================================================
6f1535dc8Sdjm  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7f1535dc8Sdjm  *
8f1535dc8Sdjm  * Redistribution and use in source and binary forms, with or without
9f1535dc8Sdjm  * modification, are permitted provided that the following conditions
10f1535dc8Sdjm  * are met:
11f1535dc8Sdjm  *
12f1535dc8Sdjm  * 1. Redistributions of source code must retain the above copyright
13f1535dc8Sdjm  *    notice, this list of conditions and the following disclaimer.
14f1535dc8Sdjm  *
15f1535dc8Sdjm  * 2. Redistributions in binary form must reproduce the above copyright
16f1535dc8Sdjm  *    notice, this list of conditions and the following disclaimer in
17f1535dc8Sdjm  *    the documentation and/or other materials provided with the
18f1535dc8Sdjm  *    distribution.
19f1535dc8Sdjm  *
20f1535dc8Sdjm  * 3. All advertising materials mentioning features or use of this
21f1535dc8Sdjm  *    software must display the following acknowledgment:
22f1535dc8Sdjm  *    "This product includes software developed by the OpenSSL Project
23f1535dc8Sdjm  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24f1535dc8Sdjm  *
25f1535dc8Sdjm  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26f1535dc8Sdjm  *    endorse or promote products derived from this software without
27f1535dc8Sdjm  *    prior written permission. For written permission, please contact
28f1535dc8Sdjm  *    licensing@OpenSSL.org.
29f1535dc8Sdjm  *
30f1535dc8Sdjm  * 5. Products derived from this software may not be called "OpenSSL"
31f1535dc8Sdjm  *    nor may "OpenSSL" appear in their names without prior written
32f1535dc8Sdjm  *    permission of the OpenSSL Project.
33f1535dc8Sdjm  *
34f1535dc8Sdjm  * 6. Redistributions of any form whatsoever must retain the following
35f1535dc8Sdjm  *    acknowledgment:
36f1535dc8Sdjm  *    "This product includes software developed by the OpenSSL Project
37f1535dc8Sdjm  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38f1535dc8Sdjm  *
39f1535dc8Sdjm  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40f1535dc8Sdjm  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41f1535dc8Sdjm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42f1535dc8Sdjm  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43f1535dc8Sdjm  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44f1535dc8Sdjm  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45f1535dc8Sdjm  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46f1535dc8Sdjm  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47f1535dc8Sdjm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48f1535dc8Sdjm  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49f1535dc8Sdjm  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50f1535dc8Sdjm  * OF THE POSSIBILITY OF SUCH DAMAGE.
51f1535dc8Sdjm  * ====================================================================
52f1535dc8Sdjm  *
53f1535dc8Sdjm  * This product includes cryptographic software written by Eric Young
54f1535dc8Sdjm  * (eay@cryptsoft.com).  This product includes software written by Tim
55f1535dc8Sdjm  * Hudson (tjh@cryptsoft.com).
56f1535dc8Sdjm  *
57f1535dc8Sdjm  */
58f1535dc8Sdjm 
59e604f303Stb #include <limits.h>
60f1535dc8Sdjm #include <stdio.h>
61f1535dc8Sdjm #include <stdlib.h>
62a8913c44Sjsing #include <string.h>
63a8913c44Sjsing 
648cf4d6a6Sjsing #include <openssl/opensslconf.h>
658cf4d6a6Sjsing 
66a7b8f3c1Sdoug #include <openssl/err.h>
67f1535dc8Sdjm #include <openssl/evp.h>
68b6ab114eSjsing #include <openssl/objects.h>
69e604f303Stb #include <openssl/x509v3.h>
70b6ab114eSjsing 
71c9675a23Stb #include "asn1_local.h"
72c9675a23Stb #include "evp_local.h"
73f1535dc8Sdjm 
74343fdb86Sjsing extern const EVP_PKEY_METHOD cmac_pkey_meth;
75343fdb86Sjsing extern const EVP_PKEY_METHOD dh_pkey_meth;
76343fdb86Sjsing extern const EVP_PKEY_METHOD dsa_pkey_meth;
77343fdb86Sjsing extern const EVP_PKEY_METHOD ec_pkey_meth;
78c93606bbSjsing extern const EVP_PKEY_METHOD ed25519_pkey_meth;
79c7411d0fStb extern const EVP_PKEY_METHOD hkdf_pkey_meth;
80343fdb86Sjsing extern const EVP_PKEY_METHOD hmac_pkey_meth;
81343fdb86Sjsing extern const EVP_PKEY_METHOD rsa_pkey_meth;
82343fdb86Sjsing extern const EVP_PKEY_METHOD rsa_pss_pkey_meth;
83baa34b12Stb extern const EVP_PKEY_METHOD tls1_prf_pkey_meth;
84c93606bbSjsing extern const EVP_PKEY_METHOD x25519_pkey_meth;
85f1535dc8Sdjm 
86469689ecSjsing static const EVP_PKEY_METHOD *pkey_methods[] = {
8790f161ccSmiod 	&cmac_pkey_meth,
88469689ecSjsing 	&dh_pkey_meth,
89469689ecSjsing 	&dsa_pkey_meth,
90469689ecSjsing 	&ec_pkey_meth,
91c93606bbSjsing 	&ed25519_pkey_meth,
92c7411d0fStb 	&hkdf_pkey_meth,
93469689ecSjsing 	&hmac_pkey_meth,
94469689ecSjsing 	&rsa_pkey_meth,
95469689ecSjsing 	&rsa_pss_pkey_meth,
96baa34b12Stb 	&tls1_prf_pkey_meth,
97c93606bbSjsing 	&x25519_pkey_meth,
98f1535dc8Sdjm };
99f1535dc8Sdjm 
10020c8931aStb #define N_PKEY_METHODS (sizeof(pkey_methods) / sizeof(pkey_methods[0]))
101f1535dc8Sdjm 
102d4370d4fStb static const EVP_PKEY_METHOD *
103d4370d4fStb evp_pkey_method_find(int nid)
104f1535dc8Sdjm {
10520c8931aStb 	size_t i;
106f7631d64Sjsing 
10720c8931aStb 	for (i = 0; i < N_PKEY_METHODS; i++) {
10820c8931aStb 		const EVP_PKEY_METHOD *pmeth = pkey_methods[i];
109d4370d4fStb 		if (pmeth->pkey_id == nid)
110469689ecSjsing 			return pmeth;
111f1535dc8Sdjm 	}
112469689ecSjsing 
113f1535dc8Sdjm 	return NULL;
114f1535dc8Sdjm }
115f1535dc8Sdjm 
116f7631d64Sjsing static EVP_PKEY_CTX *
117d4370d4fStb evp_pkey_ctx_new(EVP_PKEY *pkey, int nid)
118f1535dc8Sdjm {
119d506f566Stb 	EVP_PKEY_CTX *pkey_ctx = NULL;
120f1535dc8Sdjm 	const EVP_PKEY_METHOD *pmeth;
121f7631d64Sjsing 
122d4370d4fStb 	if (nid == -1) {
123d506f566Stb 		if (pkey == NULL || pkey->ameth == NULL)
124f1535dc8Sdjm 			return NULL;
125d4370d4fStb 		nid = pkey->ameth->pkey_id;
126f1535dc8Sdjm 	}
127f1535dc8Sdjm 
128d4370d4fStb 	if ((pmeth = evp_pkey_method_find(nid)) == NULL) {
1295067ae9fSbeck 		EVPerror(EVP_R_UNSUPPORTED_ALGORITHM);
130d506f566Stb 		goto err;
131f1535dc8Sdjm 	}
132f1535dc8Sdjm 
133d506f566Stb 	if ((pkey_ctx = calloc(1, sizeof(*pkey_ctx))) == NULL) {
134d506f566Stb 		EVPerror(ERR_R_MALLOC_FAILURE);
135d506f566Stb 		goto err;
136d506f566Stb 	}
137d506f566Stb 	pkey_ctx->pmeth = pmeth;
138d506f566Stb 	pkey_ctx->operation = EVP_PKEY_OP_UNDEFINED;
139d506f566Stb 	if ((pkey_ctx->pkey = pkey) != NULL)
140d506f566Stb 		EVP_PKEY_up_ref(pkey_ctx->pkey);
141d506f566Stb 
142d506f566Stb 	if (pmeth->init != NULL) {
143d506f566Stb 		if (pmeth->init(pkey_ctx) <= 0)
144d506f566Stb 			goto err;
145d506f566Stb 	}
146d506f566Stb 
147d506f566Stb 	return pkey_ctx;
148d506f566Stb 
149d506f566Stb  err:
150d506f566Stb 	EVP_PKEY_CTX_free(pkey_ctx);
151f1535dc8Sdjm 
152f1535dc8Sdjm 	return NULL;
153f1535dc8Sdjm }
154f1535dc8Sdjm 
155f7631d64Sjsing EVP_PKEY_CTX *
1568b753e6bStb EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *engine)
157f1535dc8Sdjm {
158592331b2Stb 	return evp_pkey_ctx_new(pkey, -1);
159f1535dc8Sdjm }
1609bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_new);
161f1535dc8Sdjm 
162f7631d64Sjsing EVP_PKEY_CTX *
163d4370d4fStb EVP_PKEY_CTX_new_id(int nid, ENGINE *engine)
164f1535dc8Sdjm {
165d4370d4fStb 	return evp_pkey_ctx_new(NULL, nid);
166f1535dc8Sdjm }
1679bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_new_id);
168f1535dc8Sdjm 
169f7631d64Sjsing EVP_PKEY_CTX *
170f7631d64Sjsing EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx)
171f1535dc8Sdjm {
172451a4610Stb 	EVP_PKEY_CTX *rctx = NULL;
173f7631d64Sjsing 
174451a4610Stb 	if (pctx->pmeth == NULL || pctx->pmeth->copy == NULL)
175451a4610Stb 		goto err;
176451a4610Stb 	if ((rctx = calloc(1, sizeof(*rctx))) == NULL) {
177451a4610Stb 		EVPerror(ERR_R_MALLOC_FAILURE);
178451a4610Stb 		goto err;
179451a4610Stb 	}
180f1535dc8Sdjm 
181f1535dc8Sdjm 	rctx->pmeth = pctx->pmeth;
182f1535dc8Sdjm 
183451a4610Stb 	if ((rctx->pkey = pctx->pkey) != NULL)
184451a4610Stb 		EVP_PKEY_up_ref(rctx->pkey);
185451a4610Stb 	if ((rctx->peerkey = pctx->peerkey) != NULL)
186451a4610Stb 		EVP_PKEY_up_ref(rctx->peerkey);
187f1535dc8Sdjm 
188f1535dc8Sdjm 	rctx->operation = pctx->operation;
189f1535dc8Sdjm 
190451a4610Stb 	if (pctx->pmeth->copy(rctx, pctx) <= 0)
191451a4610Stb 		goto err;
192451a4610Stb 
193f1535dc8Sdjm 	return rctx;
194f1535dc8Sdjm 
195451a4610Stb  err:
196f1535dc8Sdjm 	EVP_PKEY_CTX_free(rctx);
197f1535dc8Sdjm 	return NULL;
198f1535dc8Sdjm }
1999bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_dup);
200f1535dc8Sdjm 
201f7631d64Sjsing void
202f7631d64Sjsing EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
203f1535dc8Sdjm {
204f1535dc8Sdjm 	if (ctx == NULL)
205f1535dc8Sdjm 		return;
206f1535dc8Sdjm 	if (ctx->pmeth && ctx->pmeth->cleanup)
207f1535dc8Sdjm 		ctx->pmeth->cleanup(ctx);
208f1535dc8Sdjm 	EVP_PKEY_free(ctx->pkey);
209f1535dc8Sdjm 	EVP_PKEY_free(ctx->peerkey);
2106f3a6cb1Sbeck 	free(ctx);
211f1535dc8Sdjm }
2129bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_free);
213f1535dc8Sdjm 
214f7631d64Sjsing int
215f7631d64Sjsing EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd,
216f7631d64Sjsing     int p1, void *p2)
217f1535dc8Sdjm {
218f1535dc8Sdjm 	int ret;
219f7631d64Sjsing 
220f7631d64Sjsing 	if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
2215067ae9fSbeck 		EVPerror(EVP_R_COMMAND_NOT_SUPPORTED);
222f1535dc8Sdjm 		return -2;
223f1535dc8Sdjm 	}
224f1535dc8Sdjm 	if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
225f1535dc8Sdjm 		return -1;
226f1535dc8Sdjm 
227f7631d64Sjsing 	if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
2285067ae9fSbeck 		EVPerror(EVP_R_NO_OPERATION_SET);
229f1535dc8Sdjm 		return -1;
230f1535dc8Sdjm 	}
231f1535dc8Sdjm 
232f7631d64Sjsing 	if ((optype != -1) && !(ctx->operation & optype)) {
2335067ae9fSbeck 		EVPerror(EVP_R_INVALID_OPERATION);
234f1535dc8Sdjm 		return -1;
235f1535dc8Sdjm 	}
236f1535dc8Sdjm 
237f1535dc8Sdjm 	ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
238f1535dc8Sdjm 
239f1535dc8Sdjm 	if (ret == -2)
2405067ae9fSbeck 		EVPerror(EVP_R_COMMAND_NOT_SUPPORTED);
241f1535dc8Sdjm 
242f1535dc8Sdjm 	return ret;
243f1535dc8Sdjm 
244f1535dc8Sdjm }
2459bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_ctrl);
246f1535dc8Sdjm 
247*e05b8d4eStb /*
248*e05b8d4eStb  * This is practically unused and would best be a part of the openssl(1) code,
249*e05b8d4eStb  * but, unfortunately, openssl-ruby exposes this directly in an interface and
250*e05b8d4eStb  * it's currently the only way to do RSA-PSS in Ruby.
251*e05b8d4eStb  */
252f7631d64Sjsing int
253f7631d64Sjsing EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *name, const char *value)
254f1535dc8Sdjm {
255f7631d64Sjsing 	if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) {
2565067ae9fSbeck 		EVPerror(EVP_R_COMMAND_NOT_SUPPORTED);
257f1535dc8Sdjm 		return -2;
258f1535dc8Sdjm 	}
259f7631d64Sjsing 	if (!strcmp(name, "digest")) {
26026d13399Sjsing 		return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG,
26126d13399Sjsing 		    EVP_PKEY_CTRL_MD, value);
26226d13399Sjsing 	}
26326d13399Sjsing 	return ctx->pmeth->ctrl_str(ctx, name, value);
26426d13399Sjsing }
2659bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_ctrl_str);
26626d13399Sjsing 
26726d13399Sjsing int
268e604f303Stb EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str)
269e604f303Stb {
270e604f303Stb 	size_t len;
271e604f303Stb 
272e604f303Stb 	if ((len = strlen(str)) > INT_MAX)
273e604f303Stb 		return -1;
274e604f303Stb 
275e604f303Stb 	return ctx->pmeth->ctrl(ctx, cmd, len, (void *)str);
276e604f303Stb }
277e604f303Stb 
278e604f303Stb int
279e604f303Stb EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hexstr)
280e604f303Stb {
281e604f303Stb 	unsigned char *hex = NULL;
282e604f303Stb 	long length;
283e604f303Stb 	int ret = 0;
284e604f303Stb 
285e604f303Stb 	if ((hex = string_to_hex(hexstr, &length)) == NULL)
286e604f303Stb 		goto err;
287e604f303Stb 	if (length < 0 || length > INT_MAX) {
288e604f303Stb 		ret = -1;
289e604f303Stb 		goto err;
290e604f303Stb 	}
291e604f303Stb 
292e604f303Stb 	ret = ctx->pmeth->ctrl(ctx, cmd, length, hex);
293e604f303Stb 
294e604f303Stb  err:
295e604f303Stb 	free(hex);
296e604f303Stb 	return ret;
297e604f303Stb }
298e604f303Stb 
299e604f303Stb int
30026d13399Sjsing EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md_name)
30126d13399Sjsing {
302f1535dc8Sdjm 	const EVP_MD *md;
30326d13399Sjsing 
30426d13399Sjsing 	if ((md = EVP_get_digestbyname(md_name)) == NULL) {
3055067ae9fSbeck 		EVPerror(EVP_R_INVALID_DIGEST);
306f1535dc8Sdjm 		return 0;
307f1535dc8Sdjm 	}
30826d13399Sjsing 	return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, 0, (void *)md);
309f1535dc8Sdjm }
310f1535dc8Sdjm 
311f7631d64Sjsing int
312f7631d64Sjsing EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx)
313f1535dc8Sdjm {
314f1535dc8Sdjm 	return ctx->operation;
315f1535dc8Sdjm }
3169bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get_operation);
317f1535dc8Sdjm 
318f7631d64Sjsing void
319f7631d64Sjsing EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen)
320f1535dc8Sdjm {
321f1535dc8Sdjm 	ctx->keygen_info = dat;
322f1535dc8Sdjm 	ctx->keygen_info_count = datlen;
323f1535dc8Sdjm }
3249bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_set0_keygen_info);
325f1535dc8Sdjm 
326f7631d64Sjsing void
327f7631d64Sjsing EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data)
328f1535dc8Sdjm {
329f1535dc8Sdjm 	ctx->data = data;
330f1535dc8Sdjm }
3319bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_set_data);
332f1535dc8Sdjm 
333f7631d64Sjsing void *
334f7631d64Sjsing EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx)
335f1535dc8Sdjm {
336f1535dc8Sdjm 	return ctx->data;
337f1535dc8Sdjm }
3389bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get_data);
339f1535dc8Sdjm 
340f7631d64Sjsing EVP_PKEY *
341f7631d64Sjsing EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx)
342f1535dc8Sdjm {
343f1535dc8Sdjm 	return ctx->pkey;
344f1535dc8Sdjm }
3459bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get0_pkey);
346f1535dc8Sdjm 
347f7631d64Sjsing EVP_PKEY *
348f7631d64Sjsing EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx)
349f1535dc8Sdjm {
350f1535dc8Sdjm 	return ctx->peerkey;
351f1535dc8Sdjm }
3529bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get0_peerkey);
353f1535dc8Sdjm 
354f7631d64Sjsing void
355f7631d64Sjsing EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
356f1535dc8Sdjm {
357f1535dc8Sdjm 	ctx->app_data = data;
358f1535dc8Sdjm }
3599bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_set_app_data);
360f1535dc8Sdjm 
361f7631d64Sjsing void *
362f7631d64Sjsing EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx)
363f1535dc8Sdjm {
364f1535dc8Sdjm 	return ctx->app_data;
365f1535dc8Sdjm }
3669bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get_app_data);
367