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 /* PKCS12 compatible key/IV generation */
     73 #ifndef min
     74 #define min(a,b) ((a) < (b) ? (a) : (b))
     75 #endif
     76 
     77 int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
     78 	     int saltlen, int id, int iter, int n, unsigned char *out,
     79 	     const EVP_MD *md_type)
     80 {
     81 	int ret;
     82 	unsigned char *unipass;
     83 	int uniplen;
     84 
     85 	if(!pass) {
     86 		unipass = NULL;
     87 		uniplen = 0;
     88 	} else if (!OPENSSL_asc2uni(pass, passlen, &unipass, &uniplen)) {
     89 		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC,ERR_R_MALLOC_FAILURE);
     90 		return 0;
     91 	}
     92 	ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
     93 						 id, iter, n, out, md_type);
     94 	if (ret <= 0)
     95 	    return 0;
     96 	if(unipass) {
     97 		OPENSSL_cleanse(unipass, uniplen);	/* Clear password from memory */
     98 		OPENSSL_free(unipass);
     99 	}
    100 	return ret;
    101 }
    102 
    103 int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
    104 	     int saltlen, int id, int iter, int n, unsigned char *out,
    105 	     const EVP_MD *md_type)
    106 {
    107 	unsigned char *B, *D, *I, *p, *Ai;
    108 	int Slen, Plen, Ilen, Ijlen;
    109 	int i, j, u, v;
    110 	int ret = 0;
    111 	BIGNUM *Ij, *Bpl1;	/* These hold Ij and B + 1 */
    112 	EVP_MD_CTX ctx;
    113 #ifdef  DEBUG_KEYGEN
    114 	unsigned char *tmpout = out;
    115 	int tmpn = n;
    116 #endif
    117 
    118 #if 0
    119 	if (!pass) {
    120 		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_PASSED_NULL_PARAMETER);
    121 		return 0;
    122 	}
    123 #endif
    124 
    125 	EVP_MD_CTX_init(&ctx);
    126 #ifdef  DEBUG_KEYGEN
    127 	fprintf(stderr, "KEYGEN DEBUG\n");
    128 	fprintf(stderr, "ID %d, ITER %d\n", id, iter);
    129 	fprintf(stderr, "Password (length %d):\n", passlen);
    130 	h__dump(pass, passlen);
    131 	fprintf(stderr, "Salt (length %d):\n", saltlen);
    132 	h__dump(salt, saltlen);
    133 #endif
    134 	v = EVP_MD_block_size (md_type);
    135 	u = EVP_MD_size (md_type);
    136 	if (u < 0)
    137 	    return 0;
    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 		goto err;
    150 	for (i = 0; i < v; i++) D[i] = id;
    151 	p = I;
    152 	for (i = 0; i < Slen; i++) *p++ = salt[i % saltlen];
    153 	for (i = 0; i < Plen; i++) *p++ = pass[i % passlen];
    154 	for (;;) {
    155 		EVP_DigestInit_ex(&ctx, md_type, NULL);
    156 		EVP_DigestUpdate(&ctx, D, v);
    157 		EVP_DigestUpdate(&ctx, I, Ilen);
    158 		EVP_DigestFinal_ex(&ctx, Ai, NULL);
    159 		for (j = 1; j < iter; j++) {
    160 			EVP_DigestInit_ex(&ctx, md_type, NULL);
    161 			EVP_DigestUpdate(&ctx, Ai, u);
    162 			EVP_DigestFinal_ex(&ctx, Ai, NULL);
    163 		}
    164 		memcpy (out, Ai, min (n, u));
    165 		if (u >= n) {
    166 #ifdef DEBUG_KEYGEN
    167 			fprintf(stderr, "Output KEY (length %d)\n", tmpn);
    168 			h__dump(tmpout, tmpn);
    169 #endif
    170 			ret = 1;
    171 			goto end;
    172 		}
    173 		n -= u;
    174 		out += u;
    175 		for (j = 0; j < v; j++) B[j] = Ai[j % u];
    176 		/* Work out B + 1 first then can use B as tmp space */
    177 		if (!BN_bin2bn (B, v, Bpl1)) goto err;
    178 		if (!BN_add_word (Bpl1, 1)) goto err;
    179 		for (j = 0; j < Ilen ; j+=v) {
    180 			if (!BN_bin2bn (I + j, v, Ij)) goto err;
    181 			if (!BN_add (Ij, Ij, Bpl1)) goto err;
    182 			BN_bn2bin (Ij, B);
    183 			Ijlen = BN_num_bytes (Ij);
    184 			/* If more than 2^(v*8) - 1 cut off MSB */
    185 			if (Ijlen > v) {
    186 				BN_bn2bin (Ij, B);
    187 				memcpy (I + j, B + 1, v);
    188 #ifndef PKCS12_BROKEN_KEYGEN
    189 			/* If less than v bytes pad with zeroes */
    190 			} else if (Ijlen < v) {
    191 				memset(I + j, 0, v - Ijlen);
    192 				BN_bn2bin(Ij, I + j + v - Ijlen);
    193 #endif
    194 			} else BN_bn2bin (Ij, I + j);
    195 		}
    196 	}
    197 
    198 err:
    199 	PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_MALLOC_FAILURE);
    200 
    201 end:
    202 	OPENSSL_free (Ai);
    203 	OPENSSL_free (B);
    204 	OPENSSL_free (D);
    205 	OPENSSL_free (I);
    206 	BN_free (Ij);
    207 	BN_free (Bpl1);
    208 	EVP_MD_CTX_cleanup(&ctx);
    209 	return ret;
    210 }
    211 #ifdef DEBUG_KEYGEN
    212 void h__dump (unsigned char *p, int len)
    213 {
    214 	for (; len --; p++) fprintf(stderr, "%02X", *p);
    215 	fprintf(stderr, "\n");
    216 }
    217 #endif
    218