xref: /openbsd-src/lib/libcrypto/evp/p_lib.c (revision 049ee4e232dfc75f92dcd0e54f31453ba154d906)
1 /* $OpenBSD: p_lib.c,v 1.51 2023/12/29 10:59:00 tb Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 /* ====================================================================
59  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
60  *
61  * Redistribution and use in source and binary forms, with or without
62  * modification, are permitted provided that the following conditions
63  * are met:
64  *
65  * 1. Redistributions of source code must retain the above copyright
66  *    notice, this list of conditions and the following disclaimer.
67  *
68  * 2. Redistributions in binary form must reproduce the above copyright
69  *    notice, this list of conditions and the following disclaimer in
70  *    the documentation and/or other materials provided with the
71  *    distribution.
72  *
73  * 3. All advertising materials mentioning features or use of this
74  *    software must display the following acknowledgment:
75  *    "This product includes software developed by the OpenSSL Project
76  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
77  *
78  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79  *    endorse or promote products derived from this software without
80  *    prior written permission. For written permission, please contact
81  *    licensing@OpenSSL.org.
82  *
83  * 5. Products derived from this software may not be called "OpenSSL"
84  *    nor may "OpenSSL" appear in their names without prior written
85  *    permission of the OpenSSL Project.
86  *
87  * 6. Redistributions of any form whatsoever must retain the following
88  *    acknowledgment:
89  *    "This product includes software developed by the OpenSSL Project
90  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
91  *
92  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103  * OF THE POSSIBILITY OF SUCH DAMAGE.
104  */
105 
106 #include <stdio.h>
107 #include <stdlib.h>
108 #include <string.h>
109 
110 #include <openssl/asn1.h>
111 #include <openssl/bio.h>
112 #include <openssl/cmac.h>
113 #include <openssl/crypto.h>
114 #include <openssl/err.h>
115 #include <openssl/evp.h>
116 #include <openssl/objects.h>
117 #include <openssl/x509.h>
118 
119 #ifndef OPENSSL_NO_DH
120 #include <openssl/dh.h>
121 #endif
122 #ifndef OPENSSL_NO_DSA
123 #include <openssl/dsa.h>
124 #endif
125 #ifndef OPENSSL_NO_EC
126 #include <openssl/ec.h>
127 #endif
128 #ifndef OPENSSL_NO_RSA
129 #include <openssl/rsa.h>
130 #endif
131 
132 #include "evp_local.h"
133 
134 extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
135 extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
136 extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
137 extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
138 extern const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth;
139 extern const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth;
140 extern const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[];
141 extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
142 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
143 extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
144 extern const EVP_PKEY_ASN1_METHOD x25519_asn1_meth;
145 
146 static const EVP_PKEY_ASN1_METHOD *asn1_methods[] = {
147 	&cmac_asn1_meth,
148 	&dh_asn1_meth,
149 	&dsa_asn1_meths[0],
150 	&dsa_asn1_meths[1],
151 	&dsa_asn1_meths[2],
152 	&dsa_asn1_meths[3],
153 	&dsa_asn1_meths[4],
154 	&eckey_asn1_meth,
155 	&ed25519_asn1_meth,
156 	&gostimit_asn1_meth,
157 	&gostr01_asn1_meths[0],
158 	&gostr01_asn1_meths[1],
159 	&gostr01_asn1_meths[2],
160 	&hmac_asn1_meth,
161 	&rsa_asn1_meths[0],
162 	&rsa_asn1_meths[1],
163 	&rsa_pss_asn1_meth,
164 	&x25519_asn1_meth,
165 };
166 
167 #define N_ASN1_METHODS (sizeof(asn1_methods) / sizeof(asn1_methods[0]))
168 
169 int
170 EVP_PKEY_asn1_get_count(void)
171 {
172 	return N_ASN1_METHODS;
173 }
174 
175 const EVP_PKEY_ASN1_METHOD *
176 EVP_PKEY_asn1_get0(int idx)
177 {
178 	if (idx < 0 || idx >= N_ASN1_METHODS)
179 		return NULL;
180 
181 	return asn1_methods[idx];
182 }
183 
184 static const EVP_PKEY_ASN1_METHOD *
185 pkey_asn1_find(int pkey_id)
186 {
187 	const EVP_PKEY_ASN1_METHOD *ameth;
188 	int i;
189 
190 	for (i = EVP_PKEY_asn1_get_count() - 1; i >= 0; i--) {
191 		ameth = EVP_PKEY_asn1_get0(i);
192 		if (ameth->pkey_id == pkey_id)
193 			return ameth;
194 	}
195 
196 	return NULL;
197 }
198 
199 /*
200  * XXX - fix this. In what looks like an infinite loop, this API only makes two
201  * calls to pkey_asn1_find(): If the type resolves to an aliased ASN.1 method,
202  * the second call will find the method it aliases. Codify this in regress and
203  * make this explicit in code.
204  */
205 const EVP_PKEY_ASN1_METHOD *
206 EVP_PKEY_asn1_find(ENGINE **pe, int type)
207 {
208 	const EVP_PKEY_ASN1_METHOD *mp;
209 
210 	if (pe != NULL)
211 		*pe = NULL;
212 
213 	for (;;) {
214 		if ((mp = pkey_asn1_find(type)) == NULL)
215 			break;
216 		if ((mp->pkey_flags & ASN1_PKEY_ALIAS) == 0)
217 			break;
218 		type = mp->pkey_base_id;
219 	}
220 
221 	return mp;
222 }
223 
224 const EVP_PKEY_ASN1_METHOD *
225 EVP_PKEY_asn1_find_str(ENGINE **pe, const char *str, int len)
226 {
227 	const EVP_PKEY_ASN1_METHOD *ameth;
228 	int i;
229 
230 	if (len == -1)
231 		len = strlen(str);
232 	if (pe != NULL)
233 		*pe = NULL;
234 	for (i = EVP_PKEY_asn1_get_count() - 1; i >= 0; i--) {
235 		ameth = EVP_PKEY_asn1_get0(i);
236 		if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
237 			continue;
238 		if (((int)strlen(ameth->pem_str) == len) &&
239 		    !strncasecmp(ameth->pem_str, str, len))
240 			return ameth;
241 	}
242 	return NULL;
243 }
244 
245 int
246 EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags,
247     const char **pinfo, const char **ppem_str,
248     const EVP_PKEY_ASN1_METHOD *ameth)
249 {
250 	if (!ameth)
251 		return 0;
252 	if (ppkey_id)
253 		*ppkey_id = ameth->pkey_id;
254 	if (ppkey_base_id)
255 		*ppkey_base_id = ameth->pkey_base_id;
256 	if (ppkey_flags)
257 		*ppkey_flags = ameth->pkey_flags;
258 	if (pinfo)
259 		*pinfo = ameth->info;
260 	if (ppem_str)
261 		*ppem_str = ameth->pem_str;
262 	return 1;
263 }
264 
265 const EVP_PKEY_ASN1_METHOD*
266 EVP_PKEY_get0_asn1(const EVP_PKEY *pkey)
267 {
268 	return pkey->ameth;
269 }
270 
271 int
272 EVP_PKEY_bits(const EVP_PKEY *pkey)
273 {
274 	if (pkey && pkey->ameth && pkey->ameth->pkey_bits)
275 		return pkey->ameth->pkey_bits(pkey);
276 	return 0;
277 }
278 
279 int
280 EVP_PKEY_security_bits(const EVP_PKEY *pkey)
281 {
282 	if (pkey == NULL)
283 		return 0;
284 	if (pkey->ameth == NULL || pkey->ameth->pkey_security_bits == NULL)
285 		return -2;
286 
287 	return pkey->ameth->pkey_security_bits(pkey);
288 }
289 
290 int
291 EVP_PKEY_size(const EVP_PKEY *pkey)
292 {
293 	if (pkey && pkey->ameth && pkey->ameth->pkey_size)
294 		return pkey->ameth->pkey_size(pkey);
295 	return 0;
296 }
297 
298 int
299 EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
300 {
301 #ifndef OPENSSL_NO_DSA
302 	if (pkey->type == EVP_PKEY_DSA) {
303 		int ret = pkey->save_parameters;
304 
305 		if (mode >= 0)
306 			pkey->save_parameters = mode;
307 		return (ret);
308 	}
309 #endif
310 #ifndef OPENSSL_NO_EC
311 	if (pkey->type == EVP_PKEY_EC) {
312 		int ret = pkey->save_parameters;
313 
314 		if (mode >= 0)
315 			pkey->save_parameters = mode;
316 		return (ret);
317 	}
318 #endif
319 	return (0);
320 }
321 
322 int
323 EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
324 {
325 	if (to->type != from->type) {
326 		EVPerror(EVP_R_DIFFERENT_KEY_TYPES);
327 		goto err;
328 	}
329 
330 	if (EVP_PKEY_missing_parameters(from)) {
331 		EVPerror(EVP_R_MISSING_PARAMETERS);
332 		goto err;
333 	}
334 	if (from->ameth && from->ameth->param_copy)
335 		return from->ameth->param_copy(to, from);
336 
337 err:
338 	return 0;
339 }
340 
341 int
342 EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
343 {
344 	if (pkey->ameth && pkey->ameth->param_missing)
345 		return pkey->ameth->param_missing(pkey);
346 	return 0;
347 }
348 
349 int
350 EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
351 {
352 	if (a->type != b->type)
353 		return -1;
354 	if (a->ameth && a->ameth->param_cmp)
355 		return a->ameth->param_cmp(a, b);
356 	return -2;
357 }
358 
359 int
360 EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
361 {
362 	if (a->type != b->type)
363 		return -1;
364 
365 	if (a->ameth) {
366 		int ret;
367 		/* Compare parameters if the algorithm has them */
368 		if (a->ameth->param_cmp) {
369 			ret = a->ameth->param_cmp(a, b);
370 			if (ret <= 0)
371 				return ret;
372 		}
373 
374 		if (a->ameth->pub_cmp)
375 			return a->ameth->pub_cmp(a, b);
376 	}
377 
378 	return -2;
379 }
380 
381 EVP_PKEY *
382 EVP_PKEY_new(void)
383 {
384 	EVP_PKEY *pkey;
385 
386 	if ((pkey = calloc(1, sizeof(*pkey))) == NULL) {
387 		EVPerror(ERR_R_MALLOC_FAILURE);
388 		return NULL;
389 	}
390 
391 	pkey->type = EVP_PKEY_NONE;
392 	pkey->save_type = EVP_PKEY_NONE;
393 	pkey->references = 1;
394 	pkey->save_parameters = 1;
395 
396 	return pkey;
397 }
398 
399 int
400 EVP_PKEY_up_ref(EVP_PKEY *pkey)
401 {
402 	return CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY) > 1;
403 }
404 
405 static void
406 evp_pkey_free_pkey_ptr(EVP_PKEY *pkey)
407 {
408 	if (pkey == NULL || pkey->ameth == NULL || pkey->ameth->pkey_free == NULL)
409 		return;
410 
411 	pkey->ameth->pkey_free(pkey);
412 	pkey->pkey.ptr = NULL;
413 }
414 
415 void
416 EVP_PKEY_free(EVP_PKEY *pkey)
417 {
418 	if (pkey == NULL)
419 		return;
420 
421 	if (CRYPTO_add(&pkey->references, -1, CRYPTO_LOCK_EVP_PKEY) > 0)
422 		return;
423 
424 	evp_pkey_free_pkey_ptr(pkey);
425 	sk_X509_ATTRIBUTE_pop_free(pkey->attributes, X509_ATTRIBUTE_free);
426 	freezero(pkey, sizeof(*pkey));
427 }
428 
429 int
430 EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
431 {
432 	const EVP_PKEY_ASN1_METHOD *ameth;
433 
434 	evp_pkey_free_pkey_ptr(pkey);
435 
436 	if ((ameth = EVP_PKEY_asn1_find(NULL, type)) == NULL) {
437 		EVPerror(EVP_R_UNSUPPORTED_ALGORITHM);
438 		return 0;
439 	}
440 	if (pkey != NULL) {
441 		pkey->ameth = ameth;
442 		pkey->type = pkey->ameth->pkey_id;
443 		pkey->save_type = type;
444 	}
445 
446 	return 1;
447 }
448 
449 int
450 EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
451 {
452 	const EVP_PKEY_ASN1_METHOD *ameth;
453 
454 	evp_pkey_free_pkey_ptr(pkey);
455 
456 	if ((ameth = EVP_PKEY_asn1_find_str(NULL, str, len)) == NULL) {
457 		EVPerror(EVP_R_UNSUPPORTED_ALGORITHM);
458 		return 0;
459 	}
460 	if (pkey != NULL) {
461 		pkey->ameth = ameth;
462 		pkey->type = pkey->ameth->pkey_id;
463 		pkey->save_type = EVP_PKEY_NONE;
464 	}
465 
466 	return 1;
467 }
468 
469 int
470 EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
471 {
472 	if (!EVP_PKEY_set_type(pkey, type))
473 		return 0;
474 
475 	return (pkey->pkey.ptr = key) != NULL;
476 }
477 
478 EVP_PKEY *
479 EVP_PKEY_new_raw_private_key(int type, ENGINE *engine,
480     const unsigned char *private_key, size_t len)
481 {
482 	EVP_PKEY *pkey;
483 
484 	if ((pkey = EVP_PKEY_new()) == NULL)
485 		goto err;
486 
487 	if (!EVP_PKEY_set_type(pkey, type))
488 		goto err;
489 
490 	if (pkey->ameth->set_priv_key == NULL) {
491 		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
492 		goto err;
493 	}
494 	if (!pkey->ameth->set_priv_key(pkey, private_key, len)) {
495 		EVPerror(EVP_R_KEY_SETUP_FAILED);
496 		goto err;
497 	}
498 
499 	return pkey;
500 
501  err:
502 	EVP_PKEY_free(pkey);
503 
504 	return NULL;
505 }
506 
507 EVP_PKEY *
508 EVP_PKEY_new_raw_public_key(int type, ENGINE *engine,
509     const unsigned char *public_key, size_t len)
510 {
511 	EVP_PKEY *pkey;
512 
513 	if ((pkey = EVP_PKEY_new()) == NULL)
514 		goto err;
515 
516 	if (!EVP_PKEY_set_type(pkey, type))
517 		goto err;
518 
519 	if (pkey->ameth->set_pub_key == NULL) {
520 		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
521 		goto err;
522 	}
523 	if (!pkey->ameth->set_pub_key(pkey, public_key, len)) {
524 		EVPerror(EVP_R_KEY_SETUP_FAILED);
525 		goto err;
526 	}
527 
528 	return pkey;
529 
530  err:
531 	EVP_PKEY_free(pkey);
532 
533 	return NULL;
534 }
535 
536 int
537 EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey,
538     unsigned char *out_private_key, size_t *out_len)
539 {
540 	if (pkey->ameth->get_priv_key == NULL) {
541 		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
542 		return 0;
543 	}
544 	if (!pkey->ameth->get_priv_key(pkey, out_private_key, out_len)) {
545 		EVPerror(EVP_R_GET_RAW_KEY_FAILED);
546 		return 0;
547 	}
548 
549 	return 1;
550 }
551 
552 int
553 EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey,
554     unsigned char *out_public_key, size_t *out_len)
555 {
556 	if (pkey->ameth->get_pub_key == NULL) {
557 		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
558 		return 0;
559 	}
560 	if (!pkey->ameth->get_pub_key(pkey, out_public_key, out_len)) {
561 		EVPerror(EVP_R_GET_RAW_KEY_FAILED);
562 		return 0;
563 	}
564 
565 	return 1;
566 }
567 
568 EVP_PKEY *
569 EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, size_t len,
570     const EVP_CIPHER *cipher)
571 {
572 	EVP_PKEY *pkey = NULL;
573 	CMAC_CTX *cmctx = NULL;
574 
575 	if ((pkey = EVP_PKEY_new()) == NULL)
576 		goto err;
577 	if ((cmctx = CMAC_CTX_new()) == NULL)
578 		goto err;
579 
580 	if (!EVP_PKEY_set_type(pkey, EVP_PKEY_CMAC))
581 		goto err;
582 
583 	if (!CMAC_Init(cmctx, priv, len, cipher, NULL)) {
584 		EVPerror(EVP_R_KEY_SETUP_FAILED);
585 		goto err;
586 	}
587 
588 	pkey->pkey.ptr = cmctx;
589 
590 	return pkey;
591 
592  err:
593 	EVP_PKEY_free(pkey);
594 	CMAC_CTX_free(cmctx);
595 
596 	return NULL;
597 }
598 
599 void *
600 EVP_PKEY_get0(const EVP_PKEY *pkey)
601 {
602 	return pkey->pkey.ptr;
603 }
604 
605 const unsigned char *
606 EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len)
607 {
608 	ASN1_OCTET_STRING *os;
609 
610 	if (pkey->type != EVP_PKEY_HMAC) {
611 		EVPerror(EVP_R_EXPECTING_AN_HMAC_KEY);
612 		return NULL;
613 	}
614 
615 	os = EVP_PKEY_get0(pkey);
616 	*len = os->length;
617 
618 	return os->data;
619 }
620 
621 #ifndef OPENSSL_NO_RSA
622 RSA *
623 EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
624 {
625 	if (pkey->type == EVP_PKEY_RSA || pkey->type == EVP_PKEY_RSA_PSS)
626 		return pkey->pkey.rsa;
627 
628 	EVPerror(EVP_R_EXPECTING_AN_RSA_KEY);
629 	return NULL;
630 }
631 
632 RSA *
633 EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
634 {
635 	RSA *rsa;
636 
637 	if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL)
638 		return NULL;
639 
640 	RSA_up_ref(rsa);
641 
642 	return rsa;
643 }
644 
645 int
646 EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
647 {
648 	int ret = EVP_PKEY_assign_RSA(pkey, key);
649 	if (ret != 0)
650 		RSA_up_ref(key);
651 	return ret;
652 }
653 #endif
654 
655 #ifndef OPENSSL_NO_DSA
656 DSA *
657 EVP_PKEY_get0_DSA(EVP_PKEY *pkey)
658 {
659 	if (pkey->type != EVP_PKEY_DSA) {
660 		EVPerror(EVP_R_EXPECTING_A_DSA_KEY);
661 		return NULL;
662 	}
663 	return pkey->pkey.dsa;
664 }
665 
666 DSA *
667 EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
668 {
669 	DSA *dsa;
670 
671 	if ((dsa = EVP_PKEY_get0_DSA(pkey)) == NULL)
672 		return NULL;
673 
674 	DSA_up_ref(dsa);
675 
676 	return dsa;
677 }
678 
679 int
680 EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
681 {
682 	int ret = EVP_PKEY_assign_DSA(pkey, key);
683 	if (ret != 0)
684 		DSA_up_ref(key);
685 	return ret;
686 }
687 #endif
688 
689 #ifndef OPENSSL_NO_EC
690 EC_KEY *
691 EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
692 {
693 	if (pkey->type != EVP_PKEY_EC) {
694 		EVPerror(EVP_R_EXPECTING_A_EC_KEY);
695 		return NULL;
696 	}
697 	return pkey->pkey.ec;
698 }
699 
700 EC_KEY *
701 EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey)
702 {
703 	EC_KEY *key;
704 
705 	if ((key = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
706 		return NULL;
707 
708 	EC_KEY_up_ref(key);
709 
710 	return key;
711 }
712 
713 int
714 EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
715 {
716 	int ret = EVP_PKEY_assign_EC_KEY(pkey, key);
717 	if (ret != 0)
718 		EC_KEY_up_ref(key);
719 	return ret;
720 }
721 #endif
722 
723 
724 #ifndef OPENSSL_NO_DH
725 DH *
726 EVP_PKEY_get0_DH(EVP_PKEY *pkey)
727 {
728 	if (pkey->type != EVP_PKEY_DH) {
729 		EVPerror(EVP_R_EXPECTING_A_DH_KEY);
730 		return NULL;
731 	}
732 	return pkey->pkey.dh;
733 }
734 
735 DH *
736 EVP_PKEY_get1_DH(EVP_PKEY *pkey)
737 {
738 	DH *dh;
739 
740 	if ((dh = EVP_PKEY_get0_DH(pkey)) == NULL)
741 		return NULL;
742 
743 	DH_up_ref(dh);
744 
745 	return dh;
746 }
747 
748 int
749 EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
750 {
751 	int ret = EVP_PKEY_assign_DH(pkey, key);
752 	if (ret != 0)
753 		DH_up_ref(key);
754 	return ret;
755 }
756 #endif
757 
758 int
759 EVP_PKEY_type(int type)
760 {
761 	const EVP_PKEY_ASN1_METHOD *ameth;
762 
763 	if ((ameth = EVP_PKEY_asn1_find(NULL, type)) != NULL)
764 		return ameth->pkey_id;
765 
766 	return NID_undef;
767 }
768 
769 int
770 EVP_PKEY_id(const EVP_PKEY *pkey)
771 {
772 	return pkey->type;
773 }
774 
775 int
776 EVP_PKEY_base_id(const EVP_PKEY *pkey)
777 {
778 	return EVP_PKEY_type(pkey->type);
779 }
780 
781 static int
782 unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent, const char *kstr)
783 {
784 	if (!BIO_indent(out, indent, 128))
785 		return 0;
786 	BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
787 	    kstr, OBJ_nid2ln(pkey->type));
788 	return 1;
789 }
790 
791 int
792 EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
793     ASN1_PCTX *pctx)
794 {
795 	if (pkey->ameth && pkey->ameth->pub_print)
796 		return pkey->ameth->pub_print(out, pkey, indent, pctx);
797 
798 	return unsup_alg(out, pkey, indent, "Public Key");
799 }
800 
801 int
802 EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
803     ASN1_PCTX *pctx)
804 {
805 	if (pkey->ameth && pkey->ameth->priv_print)
806 		return pkey->ameth->priv_print(out, pkey, indent, pctx);
807 
808 	return unsup_alg(out, pkey, indent, "Private Key");
809 }
810 
811 int
812 EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
813     ASN1_PCTX *pctx)
814 {
815 	if (pkey->ameth && pkey->ameth->param_print)
816 		return pkey->ameth->param_print(out, pkey, indent, pctx);
817 	return unsup_alg(out, pkey, indent, "Parameters");
818 }
819 
820 int
821 EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
822 {
823 	if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
824 		return -2;
825 	return pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID,
826 	    0, pnid);
827 }
828