1232633Smp/* crypto/asn1/d2i_pr.c */ 259243Sobrien/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 359243Sobrien * All rights reserved. 459243Sobrien * 559243Sobrien * This package is an SSL implementation written 659243Sobrien * by Eric Young (eay@cryptsoft.com). 759243Sobrien * The implementation was written so as to conform with Netscapes SSL. 859243Sobrien * 959243Sobrien * This library is free for commercial and non-commercial use as long as 1059243Sobrien * the following conditions are aheared to. The following conditions 1159243Sobrien * apply to all code found in this distribution, be it the RC4, RSA, 1259243Sobrien * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1359243Sobrien * included with this distribution is covered by the same copyright terms 1459243Sobrien * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1559243Sobrien * 1659243Sobrien * Copyright remains Eric Young's, and as such any Copyright notices in 17100616Smp * the code are not to be removed. 1859243Sobrien * If this package is used in a product, Eric Young should be given attribution 1959243Sobrien * as the author of the parts of the library used. 2059243Sobrien * This can be in the form of a textual message at program startup or 2159243Sobrien * in documentation (online or textual) provided with the package. 2259243Sobrien * 2359243Sobrien * Redistribution and use in source and binary forms, with or without 2459243Sobrien * modification, are permitted provided that the following conditions 2559243Sobrien * are met: 2659243Sobrien * 1. Redistributions of source code must retain the copyright 2759243Sobrien * notice, this list of conditions and the following disclaimer. 2859243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 2959243Sobrien * notice, this list of conditions and the following disclaimer in the 3059243Sobrien * documentation and/or other materials provided with the distribution. 3159243Sobrien * 3. All advertising materials mentioning features or use of this software 3259243Sobrien * must display the following acknowledgement: 3359243Sobrien * "This product includes cryptographic software written by 3459243Sobrien * Eric Young (eay@cryptsoft.com)" 35232633Smp * The word 'cryptographic' can be left out if the rouines from the library 3659243Sobrien * being used are not cryptographic related :-). 3759243Sobrien * 4. If you include any Windows specific code (or a derivative thereof) from 38100616Smp * the apps directory (application code) you must include an acknowledgement: 3959243Sobrien * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4059243Sobrien * 4159243Sobrien * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5159243Sobrien * SUCH DAMAGE. 5259243Sobrien * 5359243Sobrien * The licence and distribution terms for any publically available version or 5459243Sobrien * derivative of this code cannot be changed. i.e. this code cannot simply be 5559243Sobrien * copied and put under another distribution licence 5659243Sobrien * [including the GNU Public Licence.] 5759243Sobrien */ 5859243Sobrien 5959243Sobrien#include <stdio.h> 6059243Sobrien#include "cryptlib.h" 6159243Sobrien#include <openssl/bn.h> 6259243Sobrien#include <openssl/evp.h> 6359243Sobrien#include <openssl/objects.h> 6459243Sobrien#ifndef OPENSSL_NO_ENGINE 6559243Sobrien#include <openssl/engine.h> 6659243Sobrien#endif 67167465Smp#include <openssl/x509.h> 68167465Smp#include <openssl/asn1.h> 69167465Smp#include "asn1_locl.h" 70167465Smp 71167465SmpEVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, 72167465Smp long length) 73167465Smp { 74167465Smp EVP_PKEY *ret; 75167465Smp 7659243Sobrien if ((a == NULL) || (*a == NULL)) 77167465Smp { 7859243Sobrien if ((ret=EVP_PKEY_new()) == NULL) 79167465Smp { 8059243Sobrien ASN1err(ASN1_F_D2I_PRIVATEKEY,ERR_R_EVP_LIB); 8159243Sobrien return(NULL); 82167465Smp } 8359243Sobrien } 84167465Smp else 85167465Smp { 86167465Smp ret= *a; 87167465Smp#ifndef OPENSSL_NO_ENGINE 88167465Smp if (ret->engine) 89167465Smp { 90167465Smp ENGINE_finish(ret->engine); 91167465Smp ret->engine = NULL; 92167465Smp } 93167465Smp#endif 9459243Sobrien } 9559243Sobrien 9659243Sobrien if (!EVP_PKEY_set_type(ret, type)) 97167465Smp { 98167465Smp ASN1err(ASN1_F_D2I_PRIVATEKEY,ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); 99167465Smp goto err; 100167465Smp } 101167465Smp 102167465Smp if (!ret->ameth->old_priv_decode || 103167465Smp !ret->ameth->old_priv_decode(ret, pp, length)) 104167465Smp { 10559243Sobrien if (ret->ameth->priv_decode) 10659243Sobrien { 107167465Smp PKCS8_PRIV_KEY_INFO *p8=NULL; 10859243Sobrien p8=d2i_PKCS8_PRIV_KEY_INFO(NULL,pp,length); 109167465Smp if (!p8) goto err; 11059243Sobrien EVP_PKEY_free(ret); 11159243Sobrien ret = EVP_PKCS82PKEY(p8); 112167465Smp PKCS8_PRIV_KEY_INFO_free(p8); 113167465Smp 11459243Sobrien } 11559243Sobrien else 11659243Sobrien { 11759243Sobrien ASN1err(ASN1_F_D2I_PRIVATEKEY,ERR_R_ASN1_LIB); 11859243Sobrien goto err; 11959243Sobrien } 12059243Sobrien } 121167465Smp if (a != NULL) (*a)=ret; 122167465Smp return(ret); 123167465Smperr: 124167465Smp if ((ret != NULL) && ((a == NULL) || (*a != ret))) EVP_PKEY_free(ret); 125167465Smp return(NULL); 12659243Sobrien } 12759243Sobrien 12859243Sobrien/* This works like d2i_PrivateKey() except it automatically works out the type */ 12959243Sobrien 13059243SobrienEVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, 13159243Sobrien long length) 13259243Sobrien{ 13359243Sobrien STACK_OF(ASN1_TYPE) *inkey; 13459243Sobrien const unsigned char *p; 13559243Sobrien int keytype; 13659243Sobrien p = *pp; 13759243Sobrien /* Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): 13859243Sobrien * by analyzing it we can determine the passed structure: this 13959243Sobrien * assumes the input is surrounded by an ASN1 SEQUENCE. 14059243Sobrien */ 14159243Sobrien inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length); 142167465Smp /* Since we only need to discern "traditional format" RSA and DSA 143167465Smp * keys we can just count the elements. 14459243Sobrien */ 145167465Smp if(sk_ASN1_TYPE_num(inkey) == 6) 14659243Sobrien keytype = EVP_PKEY_DSA; 14759243Sobrien else if (sk_ASN1_TYPE_num(inkey) == 4) 14859243Sobrien keytype = EVP_PKEY_EC; 149167465Smp else if (sk_ASN1_TYPE_num(inkey) == 3) 15059243Sobrien { /* This seems to be PKCS8, not traditional format */ 151167465Smp PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL,pp,length); 152167465Smp EVP_PKEY *ret; 153167465Smp 154167465Smp sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); 155167465Smp if (!p8) 15659243Sobrien { 15759243Sobrien ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); 158167465Smp return NULL; 159167465Smp } 160167465Smp ret = EVP_PKCS82PKEY(p8); 16159243Sobrien PKCS8_PRIV_KEY_INFO_free(p8); 16259243Sobrien if (a) { 16359243Sobrien *a = ret; 16459243Sobrien } 16559243Sobrien return ret; 16659243Sobrien } 16759243Sobrien else keytype = EVP_PKEY_RSA; 168167465Smp sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); 16959243Sobrien return d2i_PrivateKey(keytype, a, pp, length); 17059243Sobrien} 17159243Sobrien