155714Skris/* crypto/asn1/n_pkey.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8296465Sdelphij * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296465Sdelphij * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22296465Sdelphij * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296465Sdelphij * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52296465Sdelphij * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include "cryptlib.h" 61160814Ssimon#ifndef OPENSSL_NO_RSA 62296465Sdelphij# include <openssl/rsa.h> 63296465Sdelphij# include <openssl/objects.h> 64296465Sdelphij# include <openssl/asn1t.h> 65296465Sdelphij# include <openssl/asn1_mac.h> 66296465Sdelphij# include <openssl/evp.h> 67296465Sdelphij# include <openssl/x509.h> 6855714Skris 69296465Sdelphij# ifndef OPENSSL_NO_RC4 7055714Skris 71296465Sdelphijtypedef struct netscape_pkey_st { 72296465Sdelphij long version; 73296465Sdelphij X509_ALGOR *algor; 74296465Sdelphij ASN1_OCTET_STRING *private_key; 75296465Sdelphij} NETSCAPE_PKEY; 7655714Skris 77296465Sdelphijtypedef struct netscape_encrypted_pkey_st { 78296465Sdelphij ASN1_OCTET_STRING *os; 79296465Sdelphij /* 80296465Sdelphij * This is the same structure as DigestInfo so use it: although this 81296465Sdelphij * isn't really anything to do with digests. 82296465Sdelphij */ 83296465Sdelphij X509_SIG *enckey; 84296465Sdelphij} NETSCAPE_ENCRYPTED_PKEY; 8555714Skris 8655714Skris 87109998SmarkmASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = { 88296465Sdelphij ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, os, ASN1_OCTET_STRING), 89296465Sdelphij ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG) 90109998Smarkm} ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY) 91109998Smarkm 92109998SmarkmDECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) 93109998SmarkmDECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY) 94109998SmarkmIMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) 95109998Smarkm 96109998SmarkmASN1_SEQUENCE(NETSCAPE_PKEY) = { 97296465Sdelphij ASN1_SIMPLE(NETSCAPE_PKEY, version, LONG), 98296465Sdelphij ASN1_SIMPLE(NETSCAPE_PKEY, algor, X509_ALGOR), 99296465Sdelphij ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING) 100109998Smarkm} ASN1_SEQUENCE_END(NETSCAPE_PKEY) 101109998Smarkm 102109998SmarkmDECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) 103109998SmarkmDECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY) 104109998SmarkmIMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) 105109998Smarkm 106109998Smarkmstatic RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os, 107296465Sdelphij int (*cb) (char *buf, int len, const char *prompt, 108296465Sdelphij int verify), int sgckey); 109109998Smarkm 110160814Ssimonint i2d_Netscape_RSA(const RSA *a, unsigned char **pp, 111296465Sdelphij int (*cb) (char *buf, int len, const char *prompt, 112296465Sdelphij int verify)) 11368651Skris{ 114296465Sdelphij return i2d_RSA_NET(a, pp, cb, 0); 11568651Skris} 11668651Skris 117160814Ssimonint i2d_RSA_NET(const RSA *a, unsigned char **pp, 118296465Sdelphij int (*cb) (char *buf, int len, const char *prompt, 119296465Sdelphij int verify), int sgckey) 120296465Sdelphij{ 121296465Sdelphij int i, j, ret = 0; 122296465Sdelphij int rsalen, pkeylen, olen; 123296465Sdelphij NETSCAPE_PKEY *pkey = NULL; 124296465Sdelphij NETSCAPE_ENCRYPTED_PKEY *enckey = NULL; 125296465Sdelphij unsigned char buf[256], *zz; 126296465Sdelphij unsigned char key[EVP_MAX_KEY_LENGTH]; 127296465Sdelphij EVP_CIPHER_CTX ctx; 12855714Skris 129296465Sdelphij if (a == NULL) 130296465Sdelphij return (0); 13155714Skris 132296465Sdelphij if ((pkey = NETSCAPE_PKEY_new()) == NULL) 133296465Sdelphij goto err; 134296465Sdelphij if ((enckey = NETSCAPE_ENCRYPTED_PKEY_new()) == NULL) 135296465Sdelphij goto err; 136296465Sdelphij pkey->version = 0; 13755714Skris 138296465Sdelphij pkey->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption); 139296465Sdelphij if ((pkey->algor->parameter = ASN1_TYPE_new()) == NULL) 140296465Sdelphij goto err; 141296465Sdelphij pkey->algor->parameter->type = V_ASN1_NULL; 14255714Skris 143296465Sdelphij rsalen = i2d_RSAPrivateKey(a, NULL); 14455714Skris 145296465Sdelphij /* 146296465Sdelphij * Fake some octet strings just for the initial length calculation. 147296465Sdelphij */ 14855714Skris 149296465Sdelphij pkey->private_key->length = rsalen; 15055714Skris 151296465Sdelphij pkeylen = i2d_NETSCAPE_PKEY(pkey, NULL); 15255714Skris 153296465Sdelphij enckey->enckey->digest->length = pkeylen; 15455714Skris 155296465Sdelphij enckey->os->length = 11; /* "private-key" */ 15655714Skris 157296465Sdelphij enckey->enckey->algor->algorithm = OBJ_nid2obj(NID_rc4); 158296465Sdelphij if ((enckey->enckey->algor->parameter = ASN1_TYPE_new()) == NULL) 159296465Sdelphij goto err; 160296465Sdelphij enckey->enckey->algor->parameter->type = V_ASN1_NULL; 161109998Smarkm 162296465Sdelphij if (pp == NULL) { 163296465Sdelphij olen = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, NULL); 164296465Sdelphij NETSCAPE_PKEY_free(pkey); 165296465Sdelphij NETSCAPE_ENCRYPTED_PKEY_free(enckey); 166296465Sdelphij return olen; 167296465Sdelphij } 16855714Skris 169296465Sdelphij /* Since its RC4 encrypted length is actual length */ 170296465Sdelphij if ((zz = (unsigned char *)OPENSSL_malloc(rsalen)) == NULL) { 171296465Sdelphij ASN1err(ASN1_F_I2D_RSA_NET, ERR_R_MALLOC_FAILURE); 172296465Sdelphij goto err; 173296465Sdelphij } 174109998Smarkm 175296465Sdelphij pkey->private_key->data = zz; 176296465Sdelphij /* Write out private key encoding */ 177296465Sdelphij i2d_RSAPrivateKey(a, &zz); 178109998Smarkm 179296465Sdelphij if ((zz = OPENSSL_malloc(pkeylen)) == NULL) { 180296465Sdelphij ASN1err(ASN1_F_I2D_RSA_NET, ERR_R_MALLOC_FAILURE); 181296465Sdelphij goto err; 182296465Sdelphij } 18355714Skris 184296465Sdelphij if (!ASN1_STRING_set(enckey->os, "private-key", -1)) { 185296465Sdelphij ASN1err(ASN1_F_I2D_RSA_NET, ERR_R_MALLOC_FAILURE); 186296465Sdelphij goto err; 187296465Sdelphij } 188296465Sdelphij enckey->enckey->digest->data = zz; 189296465Sdelphij i2d_NETSCAPE_PKEY(pkey, &zz); 190109998Smarkm 191296465Sdelphij /* Wipe the private key encoding */ 192296465Sdelphij OPENSSL_cleanse(pkey->private_key->data, rsalen); 193109998Smarkm 194296465Sdelphij if (cb == NULL) 195296465Sdelphij cb = EVP_read_pw_string; 196296465Sdelphij i = cb((char *)buf, 256, "Enter Private Key password:", 1); 197296465Sdelphij if (i != 0) { 198296465Sdelphij ASN1err(ASN1_F_I2D_RSA_NET, ASN1_R_BAD_PASSWORD_READ); 199296465Sdelphij goto err; 200296465Sdelphij } 201296465Sdelphij i = strlen((char *)buf); 202296465Sdelphij /* If the key is used for SGC the algorithm is modified a little. */ 203296465Sdelphij if (sgckey) { 204296465Sdelphij EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL); 205296465Sdelphij memcpy(buf + 16, "SGCKEYSALT", 10); 206296465Sdelphij i = 26; 207296465Sdelphij } 208109998Smarkm 209296465Sdelphij EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, buf, i, 1, key, NULL); 210296465Sdelphij OPENSSL_cleanse(buf, 256); 21155714Skris 212296465Sdelphij /* Encrypt private key in place */ 213296465Sdelphij zz = enckey->enckey->digest->data; 214296465Sdelphij EVP_CIPHER_CTX_init(&ctx); 215296465Sdelphij EVP_EncryptInit_ex(&ctx, EVP_rc4(), NULL, key, NULL); 216296465Sdelphij EVP_EncryptUpdate(&ctx, zz, &i, zz, pkeylen); 217296465Sdelphij EVP_EncryptFinal_ex(&ctx, zz + i, &j); 218296465Sdelphij EVP_CIPHER_CTX_cleanup(&ctx); 21955714Skris 220296465Sdelphij ret = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, pp); 221296465Sdelphij err: 222296465Sdelphij NETSCAPE_ENCRYPTED_PKEY_free(enckey); 223296465Sdelphij NETSCAPE_PKEY_free(pkey); 224296465Sdelphij return (ret); 225296465Sdelphij} 22655714Skris 227160814SsimonRSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length, 228296465Sdelphij int (*cb) (char *buf, int len, const char *prompt, 229296465Sdelphij int verify)) 23068651Skris{ 231296465Sdelphij return d2i_RSA_NET(a, pp, length, cb, 0); 23268651Skris} 23368651Skris 234160814SsimonRSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length, 235296465Sdelphij int (*cb) (char *buf, int len, const char *prompt, 236296465Sdelphij int verify), int sgckey) 237296465Sdelphij{ 238296465Sdelphij RSA *ret = NULL; 239296465Sdelphij const unsigned char *p; 240296465Sdelphij NETSCAPE_ENCRYPTED_PKEY *enckey = NULL; 24155714Skris 242296465Sdelphij p = *pp; 24355714Skris 244296465Sdelphij enckey = d2i_NETSCAPE_ENCRYPTED_PKEY(NULL, &p, length); 245296465Sdelphij if (!enckey) { 246296465Sdelphij ASN1err(ASN1_F_D2I_RSA_NET, ASN1_R_DECODING_ERROR); 247296465Sdelphij return NULL; 248296465Sdelphij } 249109998Smarkm 250296465Sdelphij if ((enckey->os->length != 11) || (strncmp("private-key", 251296465Sdelphij (char *)enckey->os->data, 252296465Sdelphij 11) != 0)) { 253296465Sdelphij ASN1err(ASN1_F_D2I_RSA_NET, ASN1_R_PRIVATE_KEY_HEADER_MISSING); 254296465Sdelphij NETSCAPE_ENCRYPTED_PKEY_free(enckey); 255296465Sdelphij return NULL; 256296465Sdelphij } 257296465Sdelphij if (OBJ_obj2nid(enckey->enckey->algor->algorithm) != NID_rc4) { 258296465Sdelphij ASN1err(ASN1_F_D2I_RSA_NET, ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM); 259296465Sdelphij goto err; 260296465Sdelphij } 261296465Sdelphij if (cb == NULL) 262296465Sdelphij cb = EVP_read_pw_string; 263296465Sdelphij if ((ret = d2i_RSA_NET_2(a, enckey->enckey->digest, cb, sgckey)) == NULL) 264296465Sdelphij goto err; 26555714Skris 266296465Sdelphij *pp = p; 267109998Smarkm 268296465Sdelphij err: 269296465Sdelphij NETSCAPE_ENCRYPTED_PKEY_free(enckey); 270296465Sdelphij return ret; 271109998Smarkm 272296465Sdelphij} 27355714Skris 274109998Smarkmstatic RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os, 275296465Sdelphij int (*cb) (char *buf, int len, const char *prompt, 276296465Sdelphij int verify), int sgckey) 277296465Sdelphij{ 278296465Sdelphij NETSCAPE_PKEY *pkey = NULL; 279296465Sdelphij RSA *ret = NULL; 280296465Sdelphij int i, j; 281296465Sdelphij unsigned char buf[256]; 282296465Sdelphij const unsigned char *zz; 283296465Sdelphij unsigned char key[EVP_MAX_KEY_LENGTH]; 284296465Sdelphij EVP_CIPHER_CTX ctx; 28555714Skris 286296465Sdelphij i = cb((char *)buf, 256, "Enter Private Key password:", 0); 287296465Sdelphij if (i != 0) { 288296465Sdelphij ASN1err(ASN1_F_D2I_RSA_NET_2, ASN1_R_BAD_PASSWORD_READ); 289296465Sdelphij goto err; 290296465Sdelphij } 29155714Skris 292296465Sdelphij i = strlen((char *)buf); 293296465Sdelphij if (sgckey) { 294296465Sdelphij EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL); 295296465Sdelphij memcpy(buf + 16, "SGCKEYSALT", 10); 296296465Sdelphij i = 26; 297296465Sdelphij } 29855714Skris 299296465Sdelphij EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, buf, i, 1, key, NULL); 300296465Sdelphij OPENSSL_cleanse(buf, 256); 30155714Skris 302296465Sdelphij EVP_CIPHER_CTX_init(&ctx); 303296465Sdelphij EVP_DecryptInit_ex(&ctx, EVP_rc4(), NULL, key, NULL); 304296465Sdelphij EVP_DecryptUpdate(&ctx, os->data, &i, os->data, os->length); 305296465Sdelphij EVP_DecryptFinal_ex(&ctx, &(os->data[i]), &j); 306296465Sdelphij EVP_CIPHER_CTX_cleanup(&ctx); 307296465Sdelphij os->length = i + j; 30855714Skris 309296465Sdelphij zz = os->data; 31055714Skris 311296465Sdelphij if ((pkey = d2i_NETSCAPE_PKEY(NULL, &zz, os->length)) == NULL) { 312296465Sdelphij ASN1err(ASN1_F_D2I_RSA_NET_2, 313296465Sdelphij ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY); 314296465Sdelphij goto err; 315296465Sdelphij } 31655714Skris 317296465Sdelphij zz = pkey->private_key->data; 318296465Sdelphij if ((ret = d2i_RSAPrivateKey(a, &zz, pkey->private_key->length)) == NULL) { 319296465Sdelphij ASN1err(ASN1_F_D2I_RSA_NET_2, ASN1_R_UNABLE_TO_DECODE_RSA_KEY); 320296465Sdelphij goto err; 321296465Sdelphij } 322296465Sdelphij err: 323296465Sdelphij NETSCAPE_PKEY_free(pkey); 324296465Sdelphij return (ret); 325296465Sdelphij} 32655714Skris 327296465Sdelphij# endif /* OPENSSL_NO_RC4 */ 328296465Sdelphij 329296465Sdelphij#else /* !OPENSSL_NO_RSA */ 330296465Sdelphij 33159191Skris# if PEDANTIC 332296465Sdelphijstatic void *dummy = &dummy; 33359191Skris# endif 33459191Skris 33555714Skris#endif 336