]>
Commit | Line | Data |
---|---|---|
cfcefcbe DSH |
1 | /* evp_pkey.c */ |
2 | /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL | |
3 | * project 1999. | |
4 | */ | |
5 | /* ==================================================================== | |
6 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * | |
12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | |
14 | * | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in | |
17 | * the documentation and/or other materials provided with the | |
18 | * distribution. | |
19 | * | |
20 | * 3. All advertising materials mentioning features or use of this | |
21 | * software must display the following acknowledgment: | |
22 | * "This product includes software developed by the OpenSSL Project | |
23 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
24 | * | |
25 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
26 | * endorse or promote products derived from this software without | |
27 | * prior written permission. For written permission, please contact | |
28 | * licensing@OpenSSL.org. | |
29 | * | |
30 | * 5. Products derived from this software may not be called "OpenSSL" | |
31 | * nor may "OpenSSL" appear in their names without prior written | |
32 | * permission of the OpenSSL Project. | |
33 | * | |
34 | * 6. Redistributions of any form whatsoever must retain the following | |
35 | * acknowledgment: | |
36 | * "This product includes software developed by the OpenSSL Project | |
37 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
38 | * | |
39 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
40 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
41 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
42 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
43 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
44 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
45 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
46 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
48 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
49 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
50 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
51 | * ==================================================================== | |
52 | * | |
53 | * This product includes cryptographic software written by Eric Young | |
54 | * (eay@cryptsoft.com). This product includes software written by Tim | |
55 | * Hudson (tjh@cryptsoft.com). | |
56 | * | |
57 | */ | |
58 | ||
59 | #include <stdio.h> | |
60 | #include <stdlib.h> | |
61 | #include "cryptlib.h" | |
ec577822 BM |
62 | #include <openssl/x509.h> |
63 | #include <openssl/rand.h> | |
cfcefcbe | 64 | |
66430207 DSH |
65 | static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8inf, EVP_PKEY *pkey); |
66 | ||
cfcefcbe DSH |
67 | /* Extract a private key from a PKCS8 structure */ |
68 | ||
6b691a5c | 69 | EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8) |
cfcefcbe | 70 | { |
66430207 | 71 | EVP_PKEY *pkey = NULL; |
f5d7a031 | 72 | #ifndef NO_RSA |
66430207 | 73 | RSA *rsa = NULL; |
f5d7a031 UM |
74 | #endif |
75 | #ifndef NO_DSA | |
66430207 DSH |
76 | DSA *dsa = NULL; |
77 | ASN1_INTEGER *privkey; | |
78 | ASN1_TYPE *t1, *t2, *param = NULL; | |
371acb22 | 79 | STACK_OF(ASN1_TYPE) *ndsa = NULL; |
66430207 | 80 | BN_CTX *ctx = NULL; |
f5d7a031 UM |
81 | int plen; |
82 | #endif | |
83 | X509_ALGOR *a; | |
cfcefcbe | 84 | unsigned char *p; |
f5d7a031 | 85 | int pkeylen; |
cfcefcbe DSH |
86 | char obj_tmp[80]; |
87 | ||
66430207 DSH |
88 | if(p8->pkey->type == V_ASN1_OCTET_STRING) { |
89 | p8->broken = PKCS8_OK; | |
cfcefcbe DSH |
90 | p = p8->pkey->value.octet_string->data; |
91 | pkeylen = p8->pkey->value.octet_string->length; | |
66430207 DSH |
92 | } else { |
93 | p8->broken = PKCS8_NO_OCTET; | |
cfcefcbe DSH |
94 | p = p8->pkey->value.sequence->data; |
95 | pkeylen = p8->pkey->value.sequence->length; | |
cfcefcbe DSH |
96 | } |
97 | if (!(pkey = EVP_PKEY_new())) { | |
98 | EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); | |
99 | return NULL; | |
100 | } | |
101 | a = p8->pkeyalg; | |
102 | switch (OBJ_obj2nid(a->algorithm)) | |
103 | { | |
f5d7a031 | 104 | #ifndef NO_RSA |
cfcefcbe DSH |
105 | case NID_rsaEncryption: |
106 | if (!(rsa = d2i_RSAPrivateKey (NULL, &p, pkeylen))) { | |
107 | EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); | |
108 | return NULL; | |
109 | } | |
110 | EVP_PKEY_assign_RSA (pkey, rsa); | |
111 | break; | |
f5d7a031 UM |
112 | #endif |
113 | #ifndef NO_DSA | |
cfcefcbe DSH |
114 | case NID_dsa: |
115 | /* PKCS#8 DSA is weird: you just get a private key integer | |
116 | * and parameters in the AlgorithmIdentifier the pubkey must | |
117 | * be recalculated. | |
118 | */ | |
119 | ||
66430207 | 120 | /* Check for broken DSA PKCS#8, UGH! */ |
cfcefcbe | 121 | if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { |
371acb22 BL |
122 | if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pkeylen, |
123 | d2i_ASN1_TYPE, | |
124 | ASN1_TYPE_free))) { | |
cfcefcbe | 125 | EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); |
66430207 | 126 | goto dsaerr; |
cfcefcbe | 127 | } |
371acb22 | 128 | if(sk_ASN1_TYPE_num(ndsa) != 2 ) { |
cfcefcbe | 129 | EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); |
66430207 | 130 | goto dsaerr; |
cfcefcbe | 131 | } |
66430207 DSH |
132 | /* Handle Two broken types: |
133 | * SEQUENCE {parameters, priv_key} | |
134 | * SEQUENCE {pub_key, priv_key} | |
135 | */ | |
48fe0eec | 136 | |
371acb22 BL |
137 | t1 = sk_ASN1_TYPE_value(ndsa, 0); |
138 | t2 = sk_ASN1_TYPE_value(ndsa, 1); | |
66430207 DSH |
139 | if(t1->type == V_ASN1_SEQUENCE) { |
140 | p8->broken = PKCS8_EMBEDDED_PARAM; | |
141 | param = t1; | |
142 | } else if(a->parameter->type == V_ASN1_SEQUENCE) { | |
143 | p8->broken = PKCS8_NS_DB; | |
144 | param = a->parameter; | |
145 | } else { | |
cfcefcbe | 146 | EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); |
66430207 DSH |
147 | goto dsaerr; |
148 | } | |
149 | ||
150 | if(t2->type != V_ASN1_INTEGER) { | |
151 | EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); | |
152 | goto dsaerr; | |
153 | } | |
154 | privkey = t2->value.integer; | |
48fe0eec DSH |
155 | } else { |
156 | if (!(privkey=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) { | |
157 | EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); | |
158 | goto dsaerr; | |
159 | } | |
160 | param = p8->pkeyalg->parameter; | |
161 | } | |
162 | if (!param || (param->type != V_ASN1_SEQUENCE)) { | |
66430207 DSH |
163 | EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); |
164 | goto dsaerr; | |
cfcefcbe | 165 | } |
66430207 DSH |
166 | p = param->value.sequence->data; |
167 | plen = param->value.sequence->length; | |
cfcefcbe DSH |
168 | if (!(dsa = d2i_DSAparams (NULL, &p, plen))) { |
169 | EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); | |
66430207 | 170 | goto dsaerr; |
cfcefcbe DSH |
171 | } |
172 | /* We have parameters now set private key */ | |
66430207 | 173 | if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) { |
cfcefcbe | 174 | EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR); |
66430207 | 175 | goto dsaerr; |
cfcefcbe DSH |
176 | } |
177 | /* Calculate public key (ouch!) */ | |
178 | if (!(dsa->pub_key = BN_new())) { | |
179 | EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); | |
66430207 | 180 | goto dsaerr; |
cfcefcbe DSH |
181 | } |
182 | if (!(ctx = BN_CTX_new())) { | |
183 | EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); | |
66430207 | 184 | goto dsaerr; |
cfcefcbe DSH |
185 | } |
186 | ||
187 | if (!BN_mod_exp(dsa->pub_key, dsa->g, | |
188 | dsa->priv_key, dsa->p, ctx)) { | |
189 | ||
190 | EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR); | |
66430207 | 191 | goto dsaerr; |
cfcefcbe DSH |
192 | } |
193 | ||
66430207 | 194 | EVP_PKEY_assign_DSA(pkey, dsa); |
cfcefcbe | 195 | BN_CTX_free (ctx); |
371acb22 | 196 | if(ndsa) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); |
48fe0eec | 197 | else ASN1_INTEGER_free(privkey); |
66430207 DSH |
198 | break; |
199 | dsaerr: | |
200 | BN_CTX_free (ctx); | |
371acb22 | 201 | sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); |
66430207 DSH |
202 | DSA_free(dsa); |
203 | EVP_PKEY_free(pkey); | |
204 | return NULL; | |
cfcefcbe | 205 | break; |
f5d7a031 | 206 | #endif |
cfcefcbe DSH |
207 | default: |
208 | EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); | |
209 | if (!a->algorithm) strcpy (obj_tmp, "NULL"); | |
210 | else i2t_ASN1_OBJECT(obj_tmp, 80, a->algorithm); | |
211 | ERR_add_error_data(2, "TYPE=", obj_tmp); | |
212 | EVP_PKEY_free (pkey); | |
213 | return NULL; | |
214 | } | |
215 | return pkey; | |
216 | } | |
217 | ||
66430207 DSH |
218 | PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) |
219 | { | |
220 | return EVP_PKEY2PKCS8_broken(pkey, PKCS8_OK); | |
221 | } | |
222 | ||
cfcefcbe DSH |
223 | /* Turn a private key into a PKCS8 structure */ |
224 | ||
66430207 | 225 | PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken) |
cfcefcbe DSH |
226 | { |
227 | PKCS8_PRIV_KEY_INFO *p8; | |
66430207 | 228 | |
cfcefcbe DSH |
229 | if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) { |
230 | EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); | |
231 | return NULL; | |
232 | } | |
66430207 | 233 | p8->broken = broken; |
cfcefcbe DSH |
234 | ASN1_INTEGER_set (p8->version, 0); |
235 | if (!(p8->pkeyalg->parameter = ASN1_TYPE_new ())) { | |
236 | EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); | |
237 | PKCS8_PRIV_KEY_INFO_free (p8); | |
238 | return NULL; | |
239 | } | |
66430207 | 240 | p8->pkey->type = V_ASN1_OCTET_STRING; |
cfcefcbe | 241 | switch (EVP_PKEY_type(pkey->type)) { |
f5d7a031 | 242 | #ifndef NO_RSA |
cfcefcbe DSH |
243 | case EVP_PKEY_RSA: |
244 | ||
66430207 DSH |
245 | if(p8->broken == PKCS8_NO_OCTET) p8->pkey->type = V_ASN1_SEQUENCE; |
246 | ||
cfcefcbe DSH |
247 | p8->pkeyalg->algorithm = OBJ_nid2obj(NID_rsaEncryption); |
248 | p8->pkeyalg->parameter->type = V_ASN1_NULL; | |
249 | if (!ASN1_pack_string ((char *)pkey, i2d_PrivateKey, | |
250 | &p8->pkey->value.octet_string)) { | |
251 | EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); | |
252 | PKCS8_PRIV_KEY_INFO_free (p8); | |
253 | return NULL; | |
254 | } | |
255 | break; | |
f5d7a031 UM |
256 | #endif |
257 | #ifndef NO_DSA | |
cfcefcbe | 258 | case EVP_PKEY_DSA: |
66430207 | 259 | if(!dsa_pkey2pkcs8(p8, pkey)) { |
cfcefcbe DSH |
260 | PKCS8_PRIV_KEY_INFO_free (p8); |
261 | return NULL; | |
262 | } | |
66430207 | 263 | |
cfcefcbe | 264 | break; |
f5d7a031 | 265 | #endif |
cfcefcbe DSH |
266 | default: |
267 | EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); | |
268 | PKCS8_PRIV_KEY_INFO_free (p8); | |
269 | return NULL; | |
270 | } | |
eb952088 UM |
271 | RAND_add(p8->pkey->value.octet_string->data, |
272 | p8->pkey->value.octet_string->length, 0); | |
cfcefcbe DSH |
273 | return p8; |
274 | } | |
275 | ||
6b691a5c | 276 | PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken) |
cfcefcbe DSH |
277 | { |
278 | switch (broken) { | |
279 | ||
280 | case PKCS8_OK: | |
281 | p8->broken = PKCS8_OK; | |
282 | return p8; | |
283 | break; | |
284 | ||
285 | case PKCS8_NO_OCTET: | |
286 | p8->broken = PKCS8_NO_OCTET; | |
287 | p8->pkey->type = V_ASN1_SEQUENCE; | |
288 | return p8; | |
289 | break; | |
290 | ||
291 | default: | |
292 | EVPerr(EVP_F_EVP_PKCS8_SET_BROKEN,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE); | |
293 | return NULL; | |
294 | break; | |
295 | ||
296 | } | |
297 | } | |
298 | ||
66430207 DSH |
299 | #ifndef NO_DSA |
300 | static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey) | |
301 | { | |
302 | ASN1_STRING *params; | |
303 | ASN1_INTEGER *prkey; | |
304 | ASN1_TYPE *ttmp; | |
371acb22 | 305 | STACK_OF(ASN1_TYPE) *ndsa; |
66430207 DSH |
306 | unsigned char *p, *q; |
307 | int len; | |
371acb22 | 308 | |
66430207 DSH |
309 | p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa); |
310 | len = i2d_DSAparams (pkey->pkey.dsa, NULL); | |
26a3a48d | 311 | if (!(p = OPENSSL_malloc(len))) { |
66430207 DSH |
312 | EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); |
313 | PKCS8_PRIV_KEY_INFO_free (p8); | |
314 | return 0; | |
315 | } | |
316 | q = p; | |
317 | i2d_DSAparams (pkey->pkey.dsa, &q); | |
318 | params = ASN1_STRING_new(); | |
319 | ASN1_STRING_set(params, p, len); | |
26a3a48d | 320 | OPENSSL_free(p); |
66430207 DSH |
321 | /* Get private key into integer */ |
322 | if (!(prkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) { | |
323 | EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR); | |
324 | return 0; | |
325 | } | |
326 | ||
327 | switch(p8->broken) { | |
cfcefcbe | 328 | |
66430207 DSH |
329 | case PKCS8_OK: |
330 | case PKCS8_NO_OCTET: | |
331 | ||
332 | if (!ASN1_pack_string((char *)prkey, i2d_ASN1_INTEGER, | |
333 | &p8->pkey->value.octet_string)) { | |
334 | EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); | |
335 | M_ASN1_INTEGER_free (prkey); | |
336 | return 0; | |
337 | } | |
338 | ||
339 | M_ASN1_INTEGER_free (prkey); | |
340 | p8->pkeyalg->parameter->value.sequence = params; | |
341 | p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; | |
342 | ||
343 | break; | |
344 | ||
345 | case PKCS8_NS_DB: | |
346 | ||
347 | p8->pkeyalg->parameter->value.sequence = params; | |
348 | p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; | |
371acb22 | 349 | ndsa = sk_ASN1_TYPE_new_null(); |
66430207 DSH |
350 | ttmp = ASN1_TYPE_new(); |
351 | if (!(ttmp->value.integer = BN_to_ASN1_INTEGER (pkey->pkey.dsa->pub_key, NULL))) { | |
352 | EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR); | |
353 | PKCS8_PRIV_KEY_INFO_free(p8); | |
354 | return 0; | |
355 | } | |
356 | ttmp->type = V_ASN1_INTEGER; | |
371acb22 | 357 | sk_ASN1_TYPE_push(ndsa, ttmp); |
66430207 DSH |
358 | |
359 | ttmp = ASN1_TYPE_new(); | |
360 | ttmp->value.integer = prkey; | |
361 | ttmp->type = V_ASN1_INTEGER; | |
371acb22 | 362 | sk_ASN1_TYPE_push(ndsa, ttmp); |
66430207 DSH |
363 | |
364 | p8->pkey->value.octet_string = ASN1_OCTET_STRING_new(); | |
365 | ||
371acb22 | 366 | if (!ASN1_seq_pack_ASN1_TYPE(ndsa, i2d_ASN1_TYPE, |
66430207 DSH |
367 | &p8->pkey->value.octet_string->data, |
368 | &p8->pkey->value.octet_string->length)) { | |
369 | ||
370 | EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); | |
371acb22 | 371 | sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); |
66430207 DSH |
372 | M_ASN1_INTEGER_free(prkey); |
373 | return 0; | |
374 | } | |
371acb22 | 375 | sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); |
66430207 DSH |
376 | break; |
377 | ||
378 | case PKCS8_EMBEDDED_PARAM: | |
379 | ||
380 | p8->pkeyalg->parameter->type = V_ASN1_NULL; | |
371acb22 | 381 | ndsa = sk_ASN1_TYPE_new_null(); |
66430207 DSH |
382 | ttmp = ASN1_TYPE_new(); |
383 | ttmp->value.sequence = params; | |
384 | ttmp->type = V_ASN1_SEQUENCE; | |
371acb22 | 385 | sk_ASN1_TYPE_push(ndsa, ttmp); |
66430207 DSH |
386 | |
387 | ttmp = ASN1_TYPE_new(); | |
388 | ttmp->value.integer = prkey; | |
389 | ttmp->type = V_ASN1_INTEGER; | |
371acb22 | 390 | sk_ASN1_TYPE_push(ndsa, ttmp); |
66430207 DSH |
391 | |
392 | p8->pkey->value.octet_string = ASN1_OCTET_STRING_new(); | |
393 | ||
371acb22 | 394 | if (!ASN1_seq_pack_ASN1_TYPE(ndsa, i2d_ASN1_TYPE, |
66430207 DSH |
395 | &p8->pkey->value.octet_string->data, |
396 | &p8->pkey->value.octet_string->length)) { | |
397 | ||
398 | EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); | |
371acb22 | 399 | sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); |
66430207 DSH |
400 | M_ASN1_INTEGER_free (prkey); |
401 | return 0; | |
402 | } | |
371acb22 | 403 | sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); |
66430207 DSH |
404 | break; |
405 | } | |
406 | return 1; | |
407 | } | |
408 | #endif |