ssl/libcrypto/src/crypto/asn1/n_pkey.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* crypto/asn1/n_pkey.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  © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
    60  */
       
    61 
       
    62 #include <stdio.h>
       
    63 #include "cryptlib.h"
       
    64 #ifndef OPENSSL_NO_RSA
       
    65 #include <openssl/rsa.h>
       
    66 #include <openssl/objects.h>
       
    67 #include <openssl/asn1t.h>
       
    68 #include <openssl/asn1_mac.h>
       
    69 #include <openssl/evp.h>
       
    70 #include <openssl/x509.h>
       
    71 
       
    72 
       
    73 #ifndef OPENSSL_NO_RC4
       
    74 
       
    75 typedef struct netscape_pkey_st
       
    76 	{
       
    77 	long version;
       
    78 	X509_ALGOR *algor;
       
    79 	ASN1_OCTET_STRING *private_key;
       
    80 	} NETSCAPE_PKEY;
       
    81 
       
    82 typedef struct netscape_encrypted_pkey_st
       
    83 	{
       
    84 	ASN1_OCTET_STRING *os;
       
    85 	/* This is the same structure as DigestInfo so use it:
       
    86 	 * although this isn't really anything to do with
       
    87 	 * digests.
       
    88 	 */
       
    89 	X509_SIG *enckey;
       
    90 	} NETSCAPE_ENCRYPTED_PKEY;
       
    91 
       
    92 
       
    93 ASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = {
       
    94 	ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, os, ASN1_OCTET_STRING),
       
    95 	ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG)
       
    96 } ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY)
       
    97 
       
    98 DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
       
    99 DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY)
       
   100 IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
       
   101 
       
   102 ASN1_SEQUENCE(NETSCAPE_PKEY) = {
       
   103 	ASN1_SIMPLE(NETSCAPE_PKEY, version, LONG),
       
   104 	ASN1_SIMPLE(NETSCAPE_PKEY, algor, X509_ALGOR),
       
   105 	ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING)
       
   106 } ASN1_SEQUENCE_END(NETSCAPE_PKEY)
       
   107 
       
   108 DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
       
   109 DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY)
       
   110 IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
       
   111 
       
   112 static RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os,
       
   113 			  int (*cb)(char *buf, int len, const char *prompt,
       
   114 				    int verify),
       
   115 			  int sgckey);
       
   116 
       
   117 EXPORT_C int i2d_Netscape_RSA(const RSA *a, unsigned char **pp,
       
   118 		     int (*cb)(char *buf, int len, const char *prompt,
       
   119 			       int verify))
       
   120 {
       
   121 	return i2d_RSA_NET(a, pp, cb, 0);
       
   122 }
       
   123 
       
   124 EXPORT_C int i2d_RSA_NET(const RSA *a, unsigned char **pp,
       
   125 		int (*cb)(char *buf, int len, const char *prompt, int verify),
       
   126 		int sgckey)
       
   127 	{
       
   128 	int i, j, ret = 0;
       
   129 	int rsalen, pkeylen, olen;
       
   130 	NETSCAPE_PKEY *pkey = NULL;
       
   131 	NETSCAPE_ENCRYPTED_PKEY *enckey = NULL;
       
   132 	unsigned char buf[256],*zz;
       
   133 	unsigned char key[EVP_MAX_KEY_LENGTH];
       
   134 	EVP_CIPHER_CTX ctx;
       
   135 
       
   136 	if (a == NULL) return(0);
       
   137 
       
   138 	if ((pkey=NETSCAPE_PKEY_new()) == NULL) goto err;
       
   139 	if ((enckey=NETSCAPE_ENCRYPTED_PKEY_new()) == NULL) goto err;
       
   140 	pkey->version = 0;
       
   141 
       
   142 	pkey->algor->algorithm=OBJ_nid2obj(NID_rsaEncryption);
       
   143 	if ((pkey->algor->parameter=ASN1_TYPE_new()) == NULL) goto err;
       
   144 	pkey->algor->parameter->type=V_ASN1_NULL;
       
   145 
       
   146 	rsalen = i2d_RSAPrivateKey(a, NULL);
       
   147 
       
   148 	/* Fake some octet strings just for the initial length
       
   149 	 * calculation.
       
   150  	 */
       
   151 
       
   152 	pkey->private_key->length=rsalen;
       
   153 
       
   154 	pkeylen=i2d_NETSCAPE_PKEY(pkey,NULL);
       
   155 
       
   156 	enckey->enckey->digest->length = pkeylen;
       
   157 
       
   158 	enckey->os->length = 11;	/* "private-key" */
       
   159 
       
   160 	enckey->enckey->algor->algorithm=OBJ_nid2obj(NID_rc4);
       
   161 	if ((enckey->enckey->algor->parameter=ASN1_TYPE_new()) == NULL) goto err;
       
   162 	enckey->enckey->algor->parameter->type=V_ASN1_NULL;
       
   163 
       
   164 	if (pp == NULL)
       
   165 		{
       
   166 		olen = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, NULL);
       
   167 		NETSCAPE_PKEY_free(pkey);
       
   168 		NETSCAPE_ENCRYPTED_PKEY_free(enckey);
       
   169 		return olen;
       
   170 		}
       
   171 
       
   172 
       
   173 	/* Since its RC4 encrypted length is actual length */
       
   174 	if ((zz=(unsigned char *)OPENSSL_malloc(rsalen)) == NULL)
       
   175 		{
       
   176 		ASN1err(ASN1_F_I2D_RSA_NET,ERR_R_MALLOC_FAILURE);
       
   177 		goto err;
       
   178 		}
       
   179 
       
   180 	pkey->private_key->data = zz;
       
   181 	/* Write out private key encoding */
       
   182 	i2d_RSAPrivateKey(a,&zz);
       
   183 
       
   184 	if ((zz=OPENSSL_malloc(pkeylen)) == NULL)
       
   185 		{
       
   186 		ASN1err(ASN1_F_I2D_RSA_NET,ERR_R_MALLOC_FAILURE);
       
   187 		goto err;
       
   188 		}
       
   189 
       
   190 	if (!ASN1_STRING_set(enckey->os, "private-key", -1)) 
       
   191 		{
       
   192 		ASN1err(ASN1_F_I2D_RSA_NET,ERR_R_MALLOC_FAILURE);
       
   193 		goto err;
       
   194 		}
       
   195 	enckey->enckey->digest->data = zz;
       
   196 	i2d_NETSCAPE_PKEY(pkey,&zz);
       
   197 
       
   198 	/* Wipe the private key encoding */
       
   199 	OPENSSL_cleanse(pkey->private_key->data, rsalen);
       
   200 		
       
   201 	if (cb == NULL)
       
   202 		cb=EVP_read_pw_string;
       
   203 	i=cb((char *)buf,256,"Enter Private Key password:",1);
       
   204 	if (i != 0)
       
   205 		{
       
   206 		ASN1err(ASN1_F_I2D_RSA_NET,ASN1_R_BAD_PASSWORD_READ);
       
   207 		goto err;
       
   208 		}
       
   209 	i = strlen((char *)buf);
       
   210 	/* If the key is used for SGC the algorithm is modified a little. */
       
   211 	if(sgckey) {
       
   212 		EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL);
       
   213 		memcpy(buf + 16, "SGCKEYSALT", 10);
       
   214 		i = 26;
       
   215 	}
       
   216 
       
   217 	EVP_BytesToKey(EVP_rc4(),EVP_md5(),NULL,buf,i,1,key,NULL);
       
   218 	OPENSSL_cleanse(buf,256);
       
   219 
       
   220 	/* Encrypt private key in place */
       
   221 	zz = enckey->enckey->digest->data;
       
   222 	EVP_CIPHER_CTX_init(&ctx);
       
   223 	EVP_EncryptInit_ex(&ctx,EVP_rc4(),NULL,key,NULL);
       
   224 	EVP_EncryptUpdate(&ctx,zz,&i,zz,pkeylen);
       
   225 	EVP_EncryptFinal_ex(&ctx,zz + i,&j);
       
   226 	EVP_CIPHER_CTX_cleanup(&ctx);
       
   227 
       
   228 	ret = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, pp);
       
   229 err:
       
   230 	NETSCAPE_ENCRYPTED_PKEY_free(enckey);
       
   231 	NETSCAPE_PKEY_free(pkey);
       
   232 	return(ret);
       
   233 	}
       
   234 
       
   235 
       
   236 EXPORT_C RSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length,
       
   237 		      int (*cb)(char *buf, int len, const char *prompt,
       
   238 				int verify))
       
   239 {
       
   240 	return d2i_RSA_NET(a, pp, length, cb, 0);
       
   241 }
       
   242 
       
   243 EXPORT_C RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length,
       
   244 		 int (*cb)(char *buf, int len, const char *prompt, int verify),
       
   245 		 int sgckey)
       
   246 	{
       
   247 	RSA *ret=NULL;
       
   248 	const unsigned char *p, *kp;
       
   249 	NETSCAPE_ENCRYPTED_PKEY *enckey = NULL;
       
   250 
       
   251 	p = *pp;
       
   252 
       
   253 	enckey = d2i_NETSCAPE_ENCRYPTED_PKEY(NULL, &p, length);
       
   254 	if(!enckey) {
       
   255 		ASN1err(ASN1_F_D2I_RSA_NET,ASN1_R_DECODING_ERROR);
       
   256 		return NULL;
       
   257 	}
       
   258 
       
   259 	if ((enckey->os->length != 11) || (strncmp("private-key",
       
   260 		(char *)enckey->os->data,11) != 0))
       
   261 		{
       
   262 		ASN1err(ASN1_F_D2I_RSA_NET,ASN1_R_PRIVATE_KEY_HEADER_MISSING);
       
   263 		NETSCAPE_ENCRYPTED_PKEY_free(enckey);
       
   264 		return NULL;
       
   265 		}
       
   266 	if (OBJ_obj2nid(enckey->enckey->algor->algorithm) != NID_rc4)
       
   267 		{
       
   268 		ASN1err(ASN1_F_D2I_RSA_NET,ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM);
       
   269 		goto err;
       
   270 	}
       
   271 	kp = enckey->enckey->digest->data;
       
   272 	if (cb == NULL)
       
   273 		cb=EVP_read_pw_string;
       
   274 	if ((ret=d2i_RSA_NET_2(a, enckey->enckey->digest,cb, sgckey)) == NULL) goto err;
       
   275 
       
   276 	*pp = p;
       
   277 
       
   278 	err:
       
   279 	NETSCAPE_ENCRYPTED_PKEY_free(enckey);
       
   280 	return ret;
       
   281 
       
   282 	}
       
   283 
       
   284 static RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os,
       
   285 			  int (*cb)(char *buf, int len, const char *prompt,
       
   286 				    int verify), int sgckey)
       
   287 	{
       
   288 	NETSCAPE_PKEY *pkey=NULL;
       
   289 	RSA *ret=NULL;
       
   290 	int i,j;
       
   291 	unsigned char buf[256];
       
   292 	const unsigned char *zz;
       
   293 	unsigned char key[EVP_MAX_KEY_LENGTH];
       
   294 	EVP_CIPHER_CTX ctx;
       
   295 
       
   296 	i=cb((char *)buf,256,"Enter Private Key password:",0);
       
   297 	if (i != 0)
       
   298 		{
       
   299 		ASN1err(ASN1_F_D2I_RSA_NET_2,ASN1_R_BAD_PASSWORD_READ);
       
   300 		goto err;
       
   301 		}
       
   302 
       
   303 	i = strlen((char *)buf);
       
   304 	if(sgckey){
       
   305 		EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL);
       
   306 		memcpy(buf + 16, "SGCKEYSALT", 10);
       
   307 		i = 26;
       
   308 	}
       
   309 		
       
   310 	EVP_BytesToKey(EVP_rc4(),EVP_md5(),NULL,buf,i,1,key,NULL);
       
   311 	OPENSSL_cleanse(buf,256);
       
   312 
       
   313 	EVP_CIPHER_CTX_init(&ctx);
       
   314 	EVP_DecryptInit_ex(&ctx,EVP_rc4(),NULL, key,NULL);
       
   315 	EVP_DecryptUpdate(&ctx,os->data,&i,os->data,os->length);
       
   316 	EVP_DecryptFinal_ex(&ctx,&(os->data[i]),&j);
       
   317 	EVP_CIPHER_CTX_cleanup(&ctx);
       
   318 	os->length=i+j;
       
   319 
       
   320 	zz=os->data;
       
   321 
       
   322 	if ((pkey=d2i_NETSCAPE_PKEY(NULL,&zz,os->length)) == NULL)
       
   323 		{
       
   324 		ASN1err(ASN1_F_D2I_RSA_NET_2,ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY);
       
   325 		goto err;
       
   326 		}
       
   327 		
       
   328 	zz=pkey->private_key->data;
       
   329 	if ((ret=d2i_RSAPrivateKey(a,&zz,pkey->private_key->length)) == NULL)
       
   330 		{
       
   331 		ASN1err(ASN1_F_D2I_RSA_NET_2,ASN1_R_UNABLE_TO_DECODE_RSA_KEY);
       
   332 		goto err;
       
   333 		}
       
   334 		
       
   335 err:
       
   336 	NETSCAPE_PKEY_free(pkey);
       
   337 	return(ret);
       
   338 	}
       
   339 
       
   340 #endif /* OPENSSL_NO_RC4 */
       
   341 
       
   342 #else /* !OPENSSL_NO_RSA */
       
   343 
       
   344 # if PEDANTIC
       
   345 static void *dummy=&dummy;
       
   346 # endif
       
   347 
       
   348 #endif