Line data Source code
1 : /* crypto/evp/p_lib.c */
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 : #include <stdio.h>
60 : #include "cryptlib.h"
61 : #include <openssl/bn.h>
62 : #include <openssl/err.h>
63 : #include <openssl/objects.h>
64 : #include <openssl/evp.h>
65 : #include <openssl/asn1_mac.h>
66 : #include <openssl/x509.h>
67 : #ifndef OPENSSL_NO_RSA
68 : # include <openssl/rsa.h>
69 : #endif
70 : #ifndef OPENSSL_NO_DSA
71 : # include <openssl/dsa.h>
72 : #endif
73 : #ifndef OPENSSL_NO_DH
74 : # include <openssl/dh.h>
75 : #endif
76 :
77 : #ifndef OPENSSL_NO_ENGINE
78 : # include <openssl/engine.h>
79 : #endif
80 :
81 : #include "asn1_locl.h"
82 :
83 : static void EVP_PKEY_free_it(EVP_PKEY *x);
84 :
85 370 : int EVP_PKEY_bits(EVP_PKEY *pkey)
86 : {
87 370 : if (pkey && pkey->ameth && pkey->ameth->pkey_bits)
88 370 : return pkey->ameth->pkey_bits(pkey);
89 : return 0;
90 : }
91 :
92 2251 : int EVP_PKEY_size(EVP_PKEY *pkey)
93 : {
94 2251 : if (pkey && pkey->ameth && pkey->ameth->pkey_size)
95 2251 : return pkey->ameth->pkey_size(pkey);
96 : return 0;
97 : }
98 :
99 0 : int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
100 : {
101 : #ifndef OPENSSL_NO_DSA
102 0 : if (pkey->type == EVP_PKEY_DSA) {
103 0 : int ret = pkey->save_parameters;
104 :
105 0 : if (mode >= 0)
106 0 : pkey->save_parameters = mode;
107 0 : return (ret);
108 : }
109 : #endif
110 : #ifndef OPENSSL_NO_EC
111 0 : if (pkey->type == EVP_PKEY_EC) {
112 0 : int ret = pkey->save_parameters;
113 :
114 0 : if (mode >= 0)
115 0 : pkey->save_parameters = mode;
116 0 : return (ret);
117 : }
118 : #endif
119 : return (0);
120 : }
121 :
122 438 : int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
123 : {
124 438 : if (to->type != from->type) {
125 0 : EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES);
126 0 : goto err;
127 : }
128 :
129 438 : if (EVP_PKEY_missing_parameters(from)) {
130 0 : EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_MISSING_PARAMETERS);
131 0 : goto err;
132 : }
133 438 : if (from->ameth && from->ameth->param_copy)
134 0 : return from->ameth->param_copy(to, from);
135 : err:
136 : return 0;
137 : }
138 :
139 1113 : int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
140 : {
141 1551 : if (pkey->ameth && pkey->ameth->param_missing)
142 0 : return pkey->ameth->param_missing(pkey);
143 : return 0;
144 : }
145 :
146 0 : int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
147 : {
148 0 : if (a->type != b->type)
149 : return -1;
150 0 : if (a->ameth && a->ameth->param_cmp)
151 0 : return a->ameth->param_cmp(a, b);
152 : return -2;
153 : }
154 :
155 876 : int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
156 : {
157 876 : if (a->type != b->type)
158 : return -1;
159 :
160 876 : if (a->ameth) {
161 : int ret;
162 : /* Compare parameters if the algorithm has them */
163 876 : if (a->ameth->param_cmp) {
164 0 : ret = a->ameth->param_cmp(a, b);
165 0 : if (ret <= 0)
166 : return ret;
167 : }
168 :
169 876 : if (a->ameth->pub_cmp)
170 876 : return a->ameth->pub_cmp(a, b);
171 : }
172 :
173 : return -2;
174 : }
175 :
176 5277 : EVP_PKEY *EVP_PKEY_new(void)
177 : {
178 : EVP_PKEY *ret;
179 :
180 5277 : ret = (EVP_PKEY *)OPENSSL_malloc(sizeof(EVP_PKEY));
181 5277 : if (ret == NULL) {
182 0 : EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
183 0 : return (NULL);
184 : }
185 5277 : ret->type = EVP_PKEY_NONE;
186 5277 : ret->save_type = EVP_PKEY_NONE;
187 5277 : ret->references = 1;
188 5277 : ret->ameth = NULL;
189 5277 : ret->engine = NULL;
190 5277 : ret->pkey.ptr = NULL;
191 5277 : ret->attributes = NULL;
192 5277 : ret->save_parameters = 1;
193 5277 : return (ret);
194 : }
195 :
196 : /*
197 : * Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey
198 : * is NULL just return 1 or 0 if the algorithm exists.
199 : */
200 :
201 6866 : static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
202 : {
203 : const EVP_PKEY_ASN1_METHOD *ameth;
204 6866 : ENGINE *e = NULL;
205 6866 : if (pkey) {
206 6866 : if (pkey->pkey.ptr)
207 0 : EVP_PKEY_free_it(pkey);
208 : /*
209 : * If key type matches and a method exists then this lookup has
210 : * succeeded once so just indicate success.
211 : */
212 6866 : if ((type == pkey->save_type) && pkey->ameth)
213 : return 1;
214 : #ifndef OPENSSL_NO_ENGINE
215 : /* If we have an ENGINE release it */
216 5277 : if (pkey->engine) {
217 0 : ENGINE_finish(pkey->engine);
218 0 : pkey->engine = NULL;
219 : }
220 : #endif
221 : }
222 5277 : if (str)
223 0 : ameth = EVP_PKEY_asn1_find_str(&e, str, len);
224 : else
225 5277 : ameth = EVP_PKEY_asn1_find(&e, type);
226 : #ifndef OPENSSL_NO_ENGINE
227 5277 : if (!pkey && e)
228 0 : ENGINE_finish(e);
229 : #endif
230 5277 : if (!ameth) {
231 0 : EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
232 0 : return 0;
233 : }
234 5277 : if (pkey) {
235 5277 : pkey->ameth = ameth;
236 5277 : pkey->engine = e;
237 :
238 5277 : pkey->type = pkey->ameth->pkey_id;
239 5277 : pkey->save_type = type;
240 : }
241 : return 1;
242 : }
243 :
244 1589 : int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
245 : {
246 6866 : return pkey_set_type(pkey, type, NULL, -1);
247 : }
248 :
249 0 : int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
250 : {
251 0 : return pkey_set_type(pkey, EVP_PKEY_NONE, str, len);
252 : }
253 :
254 5264 : int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
255 : {
256 5277 : if (!EVP_PKEY_set_type(pkey, type))
257 : return 0;
258 5277 : pkey->pkey.ptr = key;
259 5277 : return (key != NULL);
260 : }
261 :
262 0 : void *EVP_PKEY_get0(EVP_PKEY *pkey)
263 : {
264 0 : return pkey->pkey.ptr;
265 : }
266 :
267 : #ifndef OPENSSL_NO_RSA
268 13 : int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
269 : {
270 : int ret = EVP_PKEY_assign_RSA(pkey, key);
271 13 : if (ret)
272 13 : RSA_up_ref(key);
273 13 : return ret;
274 : }
275 :
276 12 : RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
277 : {
278 12 : if (pkey->type != EVP_PKEY_RSA) {
279 0 : EVPerr(EVP_F_EVP_PKEY_GET1_RSA, EVP_R_EXPECTING_AN_RSA_KEY);
280 0 : return NULL;
281 : }
282 12 : RSA_up_ref(pkey->pkey.rsa);
283 12 : return pkey->pkey.rsa;
284 : }
285 : #endif
286 :
287 : #ifndef OPENSSL_NO_DSA
288 0 : int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
289 : {
290 : int ret = EVP_PKEY_assign_DSA(pkey, key);
291 0 : if (ret)
292 0 : DSA_up_ref(key);
293 0 : return ret;
294 : }
295 :
296 0 : DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
297 : {
298 0 : if (pkey->type != EVP_PKEY_DSA) {
299 0 : EVPerr(EVP_F_EVP_PKEY_GET1_DSA, EVP_R_EXPECTING_A_DSA_KEY);
300 0 : return NULL;
301 : }
302 0 : DSA_up_ref(pkey->pkey.dsa);
303 0 : return pkey->pkey.dsa;
304 : }
305 : #endif
306 :
307 : #ifndef OPENSSL_NO_EC
308 :
309 0 : int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
310 : {
311 : int ret = EVP_PKEY_assign_EC_KEY(pkey, key);
312 0 : if (ret)
313 0 : EC_KEY_up_ref(key);
314 0 : return ret;
315 : }
316 :
317 0 : EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey)
318 : {
319 0 : if (pkey->type != EVP_PKEY_EC) {
320 0 : EVPerr(EVP_F_EVP_PKEY_GET1_EC_KEY, EVP_R_EXPECTING_A_EC_KEY);
321 0 : return NULL;
322 : }
323 0 : EC_KEY_up_ref(pkey->pkey.ec);
324 0 : return pkey->pkey.ec;
325 : }
326 : #endif
327 :
328 : #ifndef OPENSSL_NO_DH
329 :
330 0 : int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
331 : {
332 : int ret = EVP_PKEY_assign_DH(pkey, key);
333 0 : if (ret)
334 0 : DH_up_ref(key);
335 0 : return ret;
336 : }
337 :
338 0 : DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
339 : {
340 0 : if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
341 0 : EVPerr(EVP_F_EVP_PKEY_GET1_DH, EVP_R_EXPECTING_A_DH_KEY);
342 0 : return NULL;
343 : }
344 0 : DH_up_ref(pkey->pkey.dh);
345 0 : return pkey->pkey.dh;
346 : }
347 : #endif
348 :
349 370 : int EVP_PKEY_type(int type)
350 : {
351 : int ret;
352 : const EVP_PKEY_ASN1_METHOD *ameth;
353 : ENGINE *e;
354 370 : ameth = EVP_PKEY_asn1_find(&e, type);
355 370 : if (ameth)
356 370 : ret = ameth->pkey_id;
357 : else
358 : ret = NID_undef;
359 : #ifndef OPENSSL_NO_ENGINE
360 370 : if (e)
361 0 : ENGINE_finish(e);
362 : #endif
363 370 : return ret;
364 : }
365 :
366 0 : int EVP_PKEY_id(const EVP_PKEY *pkey)
367 : {
368 0 : return pkey->type;
369 : }
370 :
371 0 : int EVP_PKEY_base_id(const EVP_PKEY *pkey)
372 : {
373 0 : return EVP_PKEY_type(pkey->type);
374 : }
375 :
376 37869 : void EVP_PKEY_free(EVP_PKEY *x)
377 : {
378 : int i;
379 :
380 37869 : if (x == NULL)
381 : return;
382 :
383 36223 : i = CRYPTO_add(&x->references, -1, CRYPTO_LOCK_EVP_PKEY);
384 : #ifdef REF_PRINT
385 : REF_PRINT("EVP_PKEY", x);
386 : #endif
387 36223 : if (i > 0)
388 : return;
389 : #ifdef REF_CHECK
390 : if (i < 0) {
391 : fprintf(stderr, "EVP_PKEY_free, bad reference count\n");
392 : abort();
393 : }
394 : #endif
395 5277 : EVP_PKEY_free_it(x);
396 5277 : if (x->attributes)
397 0 : sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
398 5277 : OPENSSL_free(x);
399 : }
400 :
401 5277 : static void EVP_PKEY_free_it(EVP_PKEY *x)
402 : {
403 5277 : if (x->ameth && x->ameth->pkey_free) {
404 5277 : x->ameth->pkey_free(x);
405 5277 : x->pkey.ptr = NULL;
406 : }
407 : #ifndef OPENSSL_NO_ENGINE
408 5277 : if (x->engine) {
409 0 : ENGINE_finish(x->engine);
410 0 : x->engine = NULL;
411 : }
412 : #endif
413 5277 : }
414 :
415 0 : static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
416 : const char *kstr)
417 : {
418 0 : BIO_indent(out, indent, 128);
419 0 : BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
420 : kstr, OBJ_nid2ln(pkey->type));
421 0 : return 1;
422 : }
423 :
424 0 : int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
425 : int indent, ASN1_PCTX *pctx)
426 : {
427 0 : if (pkey->ameth && pkey->ameth->pub_print)
428 0 : return pkey->ameth->pub_print(out, pkey, indent, pctx);
429 :
430 0 : return unsup_alg(out, pkey, indent, "Public Key");
431 : }
432 :
433 0 : int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
434 : int indent, ASN1_PCTX *pctx)
435 : {
436 0 : if (pkey->ameth && pkey->ameth->priv_print)
437 0 : return pkey->ameth->priv_print(out, pkey, indent, pctx);
438 :
439 0 : return unsup_alg(out, pkey, indent, "Private Key");
440 : }
441 :
442 0 : int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
443 : int indent, ASN1_PCTX *pctx)
444 : {
445 0 : if (pkey->ameth && pkey->ameth->param_print)
446 0 : return pkey->ameth->param_print(out, pkey, indent, pctx);
447 0 : return unsup_alg(out, pkey, indent, "Parameters");
448 : }
449 :
450 0 : int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
451 : {
452 0 : if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
453 : return -2;
454 0 : return pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID,
455 : 0, pnid);
456 : }
|