Home | History | Annotate | Download | only in pkcs12
      1 /* p12_key.c */
      2 /* Written by Dr Stephen N Henson (steve (at) openssl.org) 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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     55  * Hudson (tjh (at) cryptsoft.com).
     56  *
     57  */
     58 
     59 #include <stdio.h>
     60 #include "cryptlib.h"
     61 #include <openssl/pkcs12.h>
     62 #include <openssl/bn.h>
     63 
     64 /* Uncomment out this line to get debugging info about key generation */
     65 /*#define DEBUG_KEYGEN*/
     66 #ifdef DEBUG_KEYGEN
     67 #include <openssl/bio.h>
     68 extern BIO *bio_err;
     69 void h__dump (unsigned char *p, int len);
     70 #endif
     71 
     72 #ifdef OPENSSL_SYS_NETWARE
     73 /* Rename these functions to avoid name clashes on NetWare OS */
     74 #define uni2asc OPENSSL_uni2asc
     75 #define asc2uni OPENSSL_asc2uni
     76 #endif
     77 
     78 /* PKCS12 compatible key/IV generation */
     79 #ifndef min
     80 #define min(a,b) ((a) < (b) ? (a) : (b))
     81 #endif
     82 
     83 int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
     84 	     int saltlen, int id, int iter, int n, unsigned char *out,
     85 	     const EVP_MD *md_type)
     86 {
     87 	int ret;
     88 	unsigned char *unipass;
     89 	int uniplen;
     90 	if(!pass) {
     91 		unipass = NULL;
     92 		uniplen = 0;
     93 	} else if (!asc2uni(pass, passlen, &unipass, &uniplen)) {
     94 		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC,ERR_R_MALLOC_FAILURE);
     95 		return 0;
     96 	}
     97 	ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
     98 						 id, iter, n, out, md_type);
     99 	if(unipass) {
    100 		OPENSSL_cleanse(unipass, uniplen);	/* Clear password from memory */
    101 		OPENSSL_free(unipass);
    102 	}
    103 	return ret;
    104 }
    105 
    106 int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
    107 	     int saltlen, int id, int iter, int n, unsigned char *out,
    108 	     const EVP_MD *md_type)
    109 {
    110 	unsigned char *B, *D, *I, *p, *Ai;
    111 	int Slen, Plen, Ilen, Ijlen;
    112 	int i, j, u, v;
    113 	BIGNUM *Ij, *Bpl1;	/* These hold Ij and B + 1 */
    114 	EVP_MD_CTX ctx;
    115 #ifdef  DEBUG_KEYGEN
    116 	unsigned char *tmpout = out;
    117 	int tmpn = n;
    118 #endif
    119 
    120 #if 0
    121 	if (!pass) {
    122 		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_PASSED_NULL_PARAMETER);
    123 		return 0;
    124 	}
    125 #endif
    126 
    127 	EVP_MD_CTX_init(&ctx);
    128 #ifdef  DEBUG_KEYGEN
    129 	fprintf(stderr, "KEYGEN DEBUG\n");
    130 	fprintf(stderr, "ID %d, ITER %d\n", id, iter);
    131 	fprintf(stderr, "Password (length %d):\n", passlen);
    132 	h__dump(pass, passlen);
    133 	fprintf(stderr, "Salt (length %d):\n", saltlen);
    134 	h__dump(salt, saltlen);
    135 #endif
    136 	v = EVP_MD_block_size (md_type);
    137 	u = EVP_MD_size (md_type);
    138 	D = OPENSSL_malloc (v);
    139 	Ai = OPENSSL_malloc (u);
    140 	B = OPENSSL_malloc (v + 1);
    141 	Slen = v * ((saltlen+v-1)/v);
    142 	if(passlen) Plen = v * ((passlen+v-1)/v);
    143 	else Plen = 0;
    144 	Ilen = Slen + Plen;
    145 	I = OPENSSL_malloc (Ilen);
    146 	Ij = BN_new();
    147 	Bpl1 = BN_new();
    148 	if (!D || !Ai || !B || !I || !Ij || !Bpl1) {
    149 		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_MALLOC_FAILURE);
    150 		return 0;
    151 	}
    152 	for (i = 0; i < v; i++) D[i] = id;
    153 	p = I;
    154 	for (i = 0; i < Slen; i++) *p++ = salt[i % saltlen];
    155 	for (i = 0; i < Plen; i++) *p++ = pass[i % passlen];
    156 	for (;;) {
    157 		EVP_DigestInit_ex(&ctx, md_type, NULL);
    158 		EVP_DigestUpdate(&ctx, D, v);
    159 		EVP_DigestUpdate(&ctx, I, Ilen);
    160 		EVP_DigestFinal_ex(&ctx, Ai, NULL);
    161 		for (j = 1; j < iter; j++) {
    162 			EVP_DigestInit_ex(&ctx, md_type, NULL);
    163 			EVP_DigestUpdate(&ctx, Ai, u);
    164 			EVP_DigestFinal_ex(&ctx, Ai, NULL);
    165 		}
    166 		memcpy (out, Ai, min (n, u));
    167 		if (u >= n) {
    168 			OPENSSL_free (Ai);
    169 			OPENSSL_free (B);
    170 			OPENSSL_free (D);
    171 			OPENSSL_free (I);
    172 			BN_free (Ij);
    173 			BN_free (Bpl1);
    174 			EVP_MD_CTX_cleanup(&ctx);
    175 #ifdef DEBUG_KEYGEN
    176 			fprintf(stderr, "Output KEY (length %d)\n", tmpn);
    177 			h__dump(tmpout, tmpn);
    178 #endif
    179 			return 1;
    180 		}
    181 		n -= u;
    182 		out += u;
    183 		for (j = 0; j < v; j++) B[j] = Ai[j % u];
    184 		/* Work out B + 1 first then can use B as tmp space */
    185 		BN_bin2bn (B, v, Bpl1);
    186 		BN_add_word (Bpl1, 1);
    187 		for (j = 0; j < Ilen ; j+=v) {
    188 			BN_bin2bn (I + j, v, Ij);
    189 			BN_add (Ij, Ij, Bpl1);
    190 			BN_bn2bin (Ij, B);
    191 			Ijlen = BN_num_bytes (Ij);
    192 			/* If more than 2^(v*8) - 1 cut off MSB */
    193 			if (Ijlen > v) {
    194 				BN_bn2bin (Ij, B);
    195 				memcpy (I + j, B + 1, v);
    196 #ifndef PKCS12_BROKEN_KEYGEN
    197 			/* If less than v bytes pad with zeroes */
    198 			} else if (Ijlen < v) {
    199 				memset(I + j, 0, v - Ijlen);
    200 				BN_bn2bin(Ij, I + j + v - Ijlen);
    201 #endif
    202 			} else BN_bn2bin (Ij, I + j);
    203 		}
    204 	}
    205 }
    206 #ifdef DEBUG_KEYGEN
    207 void h__dump (unsigned char *p, int len)
    208 {
    209 	for (; len --; p++) fprintf(stderr, "%02X", *p);
    210 	fprintf(stderr, "\n");
    211 }
    212 #endif
    213