xref: /freebsd/crypto/openssl/crypto/pkcs12/p12_key.c (revision 3b4e3dcb9f42dc9f4f864acf804677d7a3e0c233)
174664626SKris Kennaway /* p12_key.c */
274664626SKris Kennaway /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
374664626SKris Kennaway  * project 1999.
474664626SKris Kennaway  */
574664626SKris Kennaway /* ====================================================================
674664626SKris Kennaway  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
774664626SKris Kennaway  *
874664626SKris Kennaway  * Redistribution and use in source and binary forms, with or without
974664626SKris Kennaway  * modification, are permitted provided that the following conditions
1074664626SKris Kennaway  * are met:
1174664626SKris Kennaway  *
1274664626SKris Kennaway  * 1. Redistributions of source code must retain the above copyright
1374664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer.
1474664626SKris Kennaway  *
1574664626SKris Kennaway  * 2. Redistributions in binary form must reproduce the above copyright
1674664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer in
1774664626SKris Kennaway  *    the documentation and/or other materials provided with the
1874664626SKris Kennaway  *    distribution.
1974664626SKris Kennaway  *
2074664626SKris Kennaway  * 3. All advertising materials mentioning features or use of this
2174664626SKris Kennaway  *    software must display the following acknowledgment:
2274664626SKris Kennaway  *    "This product includes software developed by the OpenSSL Project
2374664626SKris Kennaway  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2474664626SKris Kennaway  *
2574664626SKris Kennaway  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2674664626SKris Kennaway  *    endorse or promote products derived from this software without
2774664626SKris Kennaway  *    prior written permission. For written permission, please contact
2874664626SKris Kennaway  *    licensing@OpenSSL.org.
2974664626SKris Kennaway  *
3074664626SKris Kennaway  * 5. Products derived from this software may not be called "OpenSSL"
3174664626SKris Kennaway  *    nor may "OpenSSL" appear in their names without prior written
3274664626SKris Kennaway  *    permission of the OpenSSL Project.
3374664626SKris Kennaway  *
3474664626SKris Kennaway  * 6. Redistributions of any form whatsoever must retain the following
3574664626SKris Kennaway  *    acknowledgment:
3674664626SKris Kennaway  *    "This product includes software developed by the OpenSSL Project
3774664626SKris Kennaway  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3874664626SKris Kennaway  *
3974664626SKris Kennaway  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4074664626SKris Kennaway  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4174664626SKris Kennaway  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4274664626SKris Kennaway  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4374664626SKris Kennaway  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4474664626SKris Kennaway  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4574664626SKris Kennaway  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4674664626SKris Kennaway  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4774664626SKris Kennaway  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4874664626SKris Kennaway  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4974664626SKris Kennaway  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5074664626SKris Kennaway  * OF THE POSSIBILITY OF SUCH DAMAGE.
5174664626SKris Kennaway  * ====================================================================
5274664626SKris Kennaway  *
5374664626SKris Kennaway  * This product includes cryptographic software written by Eric Young
5474664626SKris Kennaway  * (eay@cryptsoft.com).  This product includes software written by Tim
5574664626SKris Kennaway  * Hudson (tjh@cryptsoft.com).
5674664626SKris Kennaway  *
5774664626SKris Kennaway  */
5874664626SKris Kennaway 
5974664626SKris Kennaway #include <stdio.h>
6074664626SKris Kennaway #include "cryptlib.h"
6174664626SKris Kennaway #include <openssl/pkcs12.h>
623b4e3dcbSSimon L. B. Nielsen #include <openssl/bn.h>
6374664626SKris Kennaway 
6474664626SKris Kennaway /* Uncomment out this line to get debugging info about key generation */
6574664626SKris Kennaway /*#define DEBUG_KEYGEN*/
6674664626SKris Kennaway #ifdef DEBUG_KEYGEN
67f579bf8eSKris Kennaway #include <openssl/bio.h>
6874664626SKris Kennaway extern BIO *bio_err;
6974664626SKris Kennaway void h__dump (unsigned char *p, int len);
7074664626SKris Kennaway #endif
7174664626SKris Kennaway 
7274664626SKris Kennaway /* PKCS12 compatible key/IV generation */
7374664626SKris Kennaway #ifndef min
7474664626SKris Kennaway #define min(a,b) ((a) < (b) ? (a) : (b))
7574664626SKris Kennaway #endif
7674664626SKris Kennaway 
7774664626SKris Kennaway int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
7874664626SKris Kennaway 	     int saltlen, int id, int iter, int n, unsigned char *out,
7974664626SKris Kennaway 	     const EVP_MD *md_type)
8074664626SKris Kennaway {
8174664626SKris Kennaway 	int ret;
8274664626SKris Kennaway 	unsigned char *unipass;
8374664626SKris Kennaway 	int uniplen;
84ddd58736SKris Kennaway 	if(!pass) {
85ddd58736SKris Kennaway 		unipass = NULL;
86ddd58736SKris Kennaway 		uniplen = 0;
87de7cdddaSKris Kennaway 	} else if (!asc2uni(pass, passlen, &unipass, &uniplen)) {
8874664626SKris Kennaway 		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC,ERR_R_MALLOC_FAILURE);
8974664626SKris Kennaway 		return 0;
9074664626SKris Kennaway 	}
9174664626SKris Kennaway 	ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
9274664626SKris Kennaway 						 id, iter, n, out, md_type);
93ddd58736SKris Kennaway 	if(unipass) {
945c87c606SMark Murray 		OPENSSL_cleanse(unipass, uniplen);	/* Clear password from memory */
95ddd58736SKris Kennaway 		OPENSSL_free(unipass);
96ddd58736SKris Kennaway 	}
9774664626SKris Kennaway 	return ret;
9874664626SKris Kennaway }
9974664626SKris Kennaway 
10074664626SKris Kennaway int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
10174664626SKris Kennaway 	     int saltlen, int id, int iter, int n, unsigned char *out,
10274664626SKris Kennaway 	     const EVP_MD *md_type)
10374664626SKris Kennaway {
10474664626SKris Kennaway 	unsigned char *B, *D, *I, *p, *Ai;
1055740a5e3SKris Kennaway 	int Slen, Plen, Ilen, Ijlen;
10674664626SKris Kennaway 	int i, j, u, v;
10774664626SKris Kennaway 	BIGNUM *Ij, *Bpl1;	/* These hold Ij and B + 1 */
10874664626SKris Kennaway 	EVP_MD_CTX ctx;
10974664626SKris Kennaway #ifdef  DEBUG_KEYGEN
11074664626SKris Kennaway 	unsigned char *tmpout = out;
11174664626SKris Kennaway 	int tmpn = n;
112f579bf8eSKris Kennaway #endif
113f579bf8eSKris Kennaway 
114ddd58736SKris Kennaway #if 0
115f579bf8eSKris Kennaway 	if (!pass) {
116f579bf8eSKris Kennaway 		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_PASSED_NULL_PARAMETER);
117f579bf8eSKris Kennaway 		return 0;
118f579bf8eSKris Kennaway 	}
119ddd58736SKris Kennaway #endif
120f579bf8eSKris Kennaway 
1215c87c606SMark Murray 	EVP_MD_CTX_init(&ctx);
122f579bf8eSKris Kennaway #ifdef  DEBUG_KEYGEN
123f579bf8eSKris Kennaway 	fprintf(stderr, "KEYGEN DEBUG\n");
124f579bf8eSKris Kennaway 	fprintf(stderr, "ID %d, ITER %d\n", id, iter);
125f579bf8eSKris Kennaway 	fprintf(stderr, "Password (length %d):\n", passlen);
12674664626SKris Kennaway 	h__dump(pass, passlen);
127f579bf8eSKris Kennaway 	fprintf(stderr, "Salt (length %d):\n", saltlen);
12874664626SKris Kennaway 	h__dump(salt, saltlen);
12974664626SKris Kennaway #endif
13074664626SKris Kennaway 	v = EVP_MD_block_size (md_type);
13174664626SKris Kennaway 	u = EVP_MD_size (md_type);
132ddd58736SKris Kennaway 	D = OPENSSL_malloc (v);
133ddd58736SKris Kennaway 	Ai = OPENSSL_malloc (u);
134ddd58736SKris Kennaway 	B = OPENSSL_malloc (v + 1);
13574664626SKris Kennaway 	Slen = v * ((saltlen+v-1)/v);
136ddd58736SKris Kennaway 	if(passlen) Plen = v * ((passlen+v-1)/v);
137ddd58736SKris Kennaway 	else Plen = 0;
13874664626SKris Kennaway 	Ilen = Slen + Plen;
139ddd58736SKris Kennaway 	I = OPENSSL_malloc (Ilen);
14074664626SKris Kennaway 	Ij = BN_new();
14174664626SKris Kennaway 	Bpl1 = BN_new();
14274664626SKris Kennaway 	if (!D || !Ai || !B || !I || !Ij || !Bpl1) {
14374664626SKris Kennaway 		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_MALLOC_FAILURE);
14474664626SKris Kennaway 		return 0;
14574664626SKris Kennaway 	}
14674664626SKris Kennaway 	for (i = 0; i < v; i++) D[i] = id;
14774664626SKris Kennaway 	p = I;
14874664626SKris Kennaway 	for (i = 0; i < Slen; i++) *p++ = salt[i % saltlen];
14974664626SKris Kennaway 	for (i = 0; i < Plen; i++) *p++ = pass[i % passlen];
15074664626SKris Kennaway 	for (;;) {
1515c87c606SMark Murray 		EVP_DigestInit_ex(&ctx, md_type, NULL);
15274664626SKris Kennaway 		EVP_DigestUpdate(&ctx, D, v);
15374664626SKris Kennaway 		EVP_DigestUpdate(&ctx, I, Ilen);
1545c87c606SMark Murray 		EVP_DigestFinal_ex(&ctx, Ai, NULL);
15574664626SKris Kennaway 		for (j = 1; j < iter; j++) {
1565c87c606SMark Murray 			EVP_DigestInit_ex(&ctx, md_type, NULL);
15774664626SKris Kennaway 			EVP_DigestUpdate(&ctx, Ai, u);
1585c87c606SMark Murray 			EVP_DigestFinal_ex(&ctx, Ai, NULL);
15974664626SKris Kennaway 		}
16074664626SKris Kennaway 		memcpy (out, Ai, min (n, u));
16174664626SKris Kennaway 		if (u >= n) {
162ddd58736SKris Kennaway 			OPENSSL_free (Ai);
163ddd58736SKris Kennaway 			OPENSSL_free (B);
164ddd58736SKris Kennaway 			OPENSSL_free (D);
165ddd58736SKris Kennaway 			OPENSSL_free (I);
16674664626SKris Kennaway 			BN_free (Ij);
16774664626SKris Kennaway 			BN_free (Bpl1);
1685c87c606SMark Murray 			EVP_MD_CTX_cleanup(&ctx);
16974664626SKris Kennaway #ifdef DEBUG_KEYGEN
170f579bf8eSKris Kennaway 			fprintf(stderr, "Output KEY (length %d)\n", tmpn);
17174664626SKris Kennaway 			h__dump(tmpout, tmpn);
17274664626SKris Kennaway #endif
17374664626SKris Kennaway 			return 1;
17474664626SKris Kennaway 		}
17574664626SKris Kennaway 		n -= u;
17674664626SKris Kennaway 		out += u;
17774664626SKris Kennaway 		for (j = 0; j < v; j++) B[j] = Ai[j % u];
17874664626SKris Kennaway 		/* Work out B + 1 first then can use B as tmp space */
17974664626SKris Kennaway 		BN_bin2bn (B, v, Bpl1);
18074664626SKris Kennaway 		BN_add_word (Bpl1, 1);
18174664626SKris Kennaway 		for (j = 0; j < Ilen ; j+=v) {
18274664626SKris Kennaway 			BN_bin2bn (I + j, v, Ij);
18374664626SKris Kennaway 			BN_add (Ij, Ij, Bpl1);
18474664626SKris Kennaway 			BN_bn2bin (Ij, B);
1855740a5e3SKris Kennaway 			Ijlen = BN_num_bytes (Ij);
18674664626SKris Kennaway 			/* If more than 2^(v*8) - 1 cut off MSB */
1875740a5e3SKris Kennaway 			if (Ijlen > v) {
18874664626SKris Kennaway 				BN_bn2bin (Ij, B);
18974664626SKris Kennaway 				memcpy (I + j, B + 1, v);
1905740a5e3SKris Kennaway #ifndef PKCS12_BROKEN_KEYGEN
1915740a5e3SKris Kennaway 			/* If less than v bytes pad with zeroes */
1925740a5e3SKris Kennaway 			} else if (Ijlen < v) {
1935740a5e3SKris Kennaway 				memset(I + j, 0, v - Ijlen);
1945740a5e3SKris Kennaway 				BN_bn2bin(Ij, I + j + v - Ijlen);
1955740a5e3SKris Kennaway #endif
19674664626SKris Kennaway 			} else BN_bn2bin (Ij, I + j);
19774664626SKris Kennaway 		}
19874664626SKris Kennaway 	}
19974664626SKris Kennaway }
20074664626SKris Kennaway #ifdef DEBUG_KEYGEN
20174664626SKris Kennaway void h__dump (unsigned char *p, int len)
20274664626SKris Kennaway {
203f579bf8eSKris Kennaway 	for (; len --; p++) fprintf(stderr, "%02X", *p);
204f579bf8eSKris Kennaway 	fprintf(stderr, "\n");
20574664626SKris Kennaway }
20674664626SKris Kennaway #endif
207