evp_pkey.c revision 55714
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" 62#include <openssl/x509.h> 63#include <openssl/rand.h> 64 65/* Extract a private key from a PKCS8 structure */ 66 67EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8) 68{ 69 EVP_PKEY *pkey; 70#ifndef NO_RSA 71 RSA *rsa; 72#endif 73#ifndef NO_DSA 74 DSA *dsa; 75 ASN1_INTEGER *dsapriv; 76 STACK *ndsa; 77 BN_CTX *ctx; 78 int plen; 79#endif 80 X509_ALGOR *a; 81 unsigned char *p; 82 int pkeylen; 83 char obj_tmp[80]; 84 85 switch (p8->broken) { 86 case PKCS8_OK: 87 p = p8->pkey->value.octet_string->data; 88 pkeylen = p8->pkey->value.octet_string->length; 89 break; 90 91 case PKCS8_NO_OCTET: 92 p = p8->pkey->value.sequence->data; 93 pkeylen = p8->pkey->value.sequence->length; 94 break; 95 96 default: 97 EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE); 98 return NULL; 99 break; 100 } 101 if (!(pkey = EVP_PKEY_new())) { 102 EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); 103 return NULL; 104 } 105 a = p8->pkeyalg; 106 switch (OBJ_obj2nid(a->algorithm)) 107 { 108#ifndef NO_RSA 109 case NID_rsaEncryption: 110 if (!(rsa = d2i_RSAPrivateKey (NULL, &p, pkeylen))) { 111 EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); 112 return NULL; 113 } 114 EVP_PKEY_assign_RSA (pkey, rsa); 115 break; 116#endif 117#ifndef NO_DSA 118 case NID_dsa: 119 /* PKCS#8 DSA is weird: you just get a private key integer 120 * and parameters in the AlgorithmIdentifier the pubkey must 121 * be recalculated. 122 */ 123 124 /* Check for broken Netscape Database DSA PKCS#8, UGH! */ 125 if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { 126 if(!(ndsa = ASN1_seq_unpack(p, pkeylen, 127 (char *(*)())d2i_ASN1_INTEGER, 128 ASN1_STRING_free))) { 129 EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); 130 return NULL; 131 } 132 if(sk_num(ndsa) != 2 ) { 133 EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); 134 sk_pop_free(ndsa, ASN1_STRING_free); 135 return NULL; 136 } 137 dsapriv = (ASN1_INTEGER *) sk_pop(ndsa); 138 sk_pop_free(ndsa, ASN1_STRING_free); 139 } else if (!(dsapriv=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) { 140 EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); 141 return NULL; 142 } 143 /* Retrieve parameters */ 144 if (a->parameter->type != V_ASN1_SEQUENCE) { 145 EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_NO_DSA_PARAMETERS); 146 return NULL; 147 } 148 p = a->parameter->value.sequence->data; 149 plen = a->parameter->value.sequence->length; 150 if (!(dsa = d2i_DSAparams (NULL, &p, plen))) { 151 EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); 152 return NULL; 153 } 154 /* We have parameters now set private key */ 155 if (!(dsa->priv_key = ASN1_INTEGER_to_BN(dsapriv, NULL))) { 156 EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR); 157 DSA_free (dsa); 158 return NULL; 159 } 160 /* Calculate public key (ouch!) */ 161 if (!(dsa->pub_key = BN_new())) { 162 EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); 163 DSA_free (dsa); 164 return NULL; 165 } 166 if (!(ctx = BN_CTX_new())) { 167 EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); 168 DSA_free (dsa); 169 return NULL; 170 } 171 172 if (!BN_mod_exp(dsa->pub_key, dsa->g, 173 dsa->priv_key, dsa->p, ctx)) { 174 175 EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR); 176 BN_CTX_free (ctx); 177 DSA_free (dsa); 178 return NULL; 179 } 180 181 EVP_PKEY_assign_DSA (pkey, dsa); 182 BN_CTX_free (ctx); 183 break; 184#endif 185 default: 186 EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); 187 if (!a->algorithm) strcpy (obj_tmp, "NULL"); 188 else i2t_ASN1_OBJECT(obj_tmp, 80, a->algorithm); 189 ERR_add_error_data(2, "TYPE=", obj_tmp); 190 EVP_PKEY_free (pkey); 191 return NULL; 192 } 193 return pkey; 194} 195 196/* Turn a private key into a PKCS8 structure */ 197 198PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) 199{ 200 PKCS8_PRIV_KEY_INFO *p8; 201#ifndef NO_DSA 202 ASN1_INTEGER *dpkey; 203 unsigned char *p, *q; 204 int len; 205#endif 206 if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) { 207 EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); 208 return NULL; 209 } 210 ASN1_INTEGER_set (p8->version, 0); 211 if (!(p8->pkeyalg->parameter = ASN1_TYPE_new ())) { 212 EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); 213 PKCS8_PRIV_KEY_INFO_free (p8); 214 return NULL; 215 } 216 switch (EVP_PKEY_type(pkey->type)) { 217#ifndef NO_RSA 218 case EVP_PKEY_RSA: 219 220 p8->pkeyalg->algorithm = OBJ_nid2obj(NID_rsaEncryption); 221 p8->pkeyalg->parameter->type = V_ASN1_NULL; 222 if (!ASN1_pack_string ((char *)pkey, i2d_PrivateKey, 223 &p8->pkey->value.octet_string)) { 224 EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); 225 PKCS8_PRIV_KEY_INFO_free (p8); 226 return NULL; 227 } 228 break; 229#endif 230#ifndef NO_DSA 231 case EVP_PKEY_DSA: 232 p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa); 233 234 /* get paramaters and place in AlgorithmIdentifier */ 235 len = i2d_DSAparams (pkey->pkey.dsa, NULL); 236 if (!(p = Malloc(len))) { 237 EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); 238 PKCS8_PRIV_KEY_INFO_free (p8); 239 return NULL; 240 } 241 q = p; 242 i2d_DSAparams (pkey->pkey.dsa, &q); 243 p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; 244 p8->pkeyalg->parameter->value.sequence = ASN1_STRING_new(); 245 ASN1_STRING_set(p8->pkeyalg->parameter->value.sequence, p, len); 246 Free(p); 247 /* Get private key into an integer and pack */ 248 if (!(dpkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) { 249 EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR); 250 PKCS8_PRIV_KEY_INFO_free (p8); 251 return NULL; 252 } 253 254 if (!ASN1_pack_string((char *)dpkey, i2d_ASN1_INTEGER, 255 &p8->pkey->value.octet_string)) { 256 EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); 257 ASN1_INTEGER_free (dpkey); 258 PKCS8_PRIV_KEY_INFO_free (p8); 259 return NULL; 260 } 261 ASN1_INTEGER_free (dpkey); 262 break; 263#endif 264 default: 265 EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); 266 PKCS8_PRIV_KEY_INFO_free (p8); 267 return NULL; 268 } 269 p8->pkey->type = V_ASN1_OCTET_STRING; 270 RAND_seed (p8->pkey->value.octet_string->data, 271 p8->pkey->value.octet_string->length); 272 return p8; 273} 274 275PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken) 276{ 277 switch (broken) { 278 279 case PKCS8_OK: 280 p8->broken = PKCS8_OK; 281 return p8; 282 break; 283 284 case PKCS8_NO_OCTET: 285 p8->broken = PKCS8_NO_OCTET; 286 p8->pkey->type = V_ASN1_SEQUENCE; 287 return p8; 288 break; 289 290 default: 291 EVPerr(EVP_F_EVP_PKCS8_SET_BROKEN,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE); 292 return NULL; 293 break; 294 295 } 296} 297 298 299