p12_key.c revision 68651
1238438Sdteske/* p12_key.c */
2238438Sdteske/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3238438Sdteske * project 1999.
4252980Sdteske */
5238438Sdteske/* ====================================================================
6238438Sdteske * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7238438Sdteske *
8238438Sdteske * Redistribution and use in source and binary forms, with or without
9238438Sdteske * modification, are permitted provided that the following conditions
10238438Sdteske * are met:
11238438Sdteske *
12238438Sdteske * 1. Redistributions of source code must retain the above copyright
13238438Sdteske *    notice, this list of conditions and the following disclaimer.
14238438Sdteske *
15238438Sdteske * 2. Redistributions in binary form must reproduce the above copyright
16252987Sdteske *    notice, this list of conditions and the following disclaimer in
17238438Sdteske *    the documentation and/or other materials provided with the
18238438Sdteske *    distribution.
19238438Sdteske *
20252987Sdteske * 3. All advertising materials mentioning features or use of this
21238438Sdteske *    software must display the following acknowledgment:
22238438Sdteske *    "This product includes software developed by the OpenSSL Project
23238438Sdteske *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24238438Sdteske *
25238438Sdteske * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26238438Sdteske *    endorse or promote products derived from this software without
27238438Sdteske *    prior written permission. For written permission, please contact
28238438Sdteske *    licensing@OpenSSL.org.
29238438Sdteske *
30238438Sdteske * 5. Products derived from this software may not be called "OpenSSL"
31240684Sdteske *    nor may "OpenSSL" appear in their names without prior written
32240684Sdteske *    permission of the OpenSSL Project.
33244675Sdteske *
34240684Sdteske * 6. Redistributions of any form whatsoever must retain the following
35259054Sdteske *    acknowledgment:
36240684Sdteske *    "This product includes software developed by the OpenSSL Project
37238438Sdteske *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38240684Sdteske *
39238438Sdteske * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40238438Sdteske * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41238438Sdteske * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42238438Sdteske * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43238438Sdteske * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44238438Sdteske * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45238438Sdteske * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46238438Sdteske * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47238438Sdteske * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48238438Sdteske * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49238438Sdteske * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50238438Sdteske * OF THE POSSIBILITY OF SUCH DAMAGE.
51238438Sdteske * ====================================================================
52238438Sdteske *
53238438Sdteske * This product includes cryptographic software written by Eric Young
54238438Sdteske * (eay@cryptsoft.com).  This product includes software written by Tim
55238438Sdteske * Hudson (tjh@cryptsoft.com).
56238438Sdteske *
57238438Sdteske */
58238438Sdteske
59238438Sdteske#include <stdio.h>
60238438Sdteske#include "cryptlib.h"
61238438Sdteske#include <openssl/pkcs12.h>
62238438Sdteske
63238438Sdteske
64238438Sdteske/* Uncomment out this line to get debugging info about key generation */
65238438Sdteske/*#define DEBUG_KEYGEN*/
66238438Sdteske#ifdef DEBUG_KEYGEN
67238438Sdteske#include <openssl/bio.h>
68238438Sdteskeextern BIO *bio_err;
69238438Sdteskevoid h__dump (unsigned char *p, int len);
70238438Sdteske#endif
71238438Sdteske
72238438Sdteske/* PKCS12 compatible key/IV generation */
73238438Sdteske#ifndef min
74238438Sdteske#define min(a,b) ((a) < (b) ? (a) : (b))
75238438Sdteske#endif
76238438Sdteske
77238438Sdteskeint PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
78238438Sdteske	     int saltlen, int id, int iter, int n, unsigned char *out,
79238438Sdteske	     const EVP_MD *md_type)
80238438Sdteske{
81238438Sdteske	int ret;
82238438Sdteske	unsigned char *unipass;
83238438Sdteske	int uniplen;
84238438Sdteske	if(!pass) {
85238438Sdteske		unipass = NULL;
86238438Sdteske		uniplen = 0;
87238438Sdteske	} else if (!asc2uni(pass, &unipass, &uniplen)) {
88238438Sdteske		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC,ERR_R_MALLOC_FAILURE);
89238438Sdteske		return 0;
90238438Sdteske	}
91238438Sdteske	ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
92238438Sdteske						 id, iter, n, out, md_type);
93238438Sdteske	if(unipass) {
94238438Sdteske		memset(unipass, 0, uniplen);	/* Clear password from memory */
95238438Sdteske		OPENSSL_free(unipass);
96238438Sdteske	}
97238438Sdteske	return ret;
98238438Sdteske}
99238438Sdteske
100238438Sdteskeint PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
101238438Sdteske	     int saltlen, int id, int iter, int n, unsigned char *out,
102238438Sdteske	     const EVP_MD *md_type)
103238438Sdteske{
104238438Sdteske	unsigned char *B, *D, *I, *p, *Ai;
105238438Sdteske	int Slen, Plen, Ilen;
106238438Sdteske	int i, j, u, v;
107238438Sdteske	BIGNUM *Ij, *Bpl1;	/* These hold Ij and B + 1 */
108238438Sdteske	EVP_MD_CTX ctx;
109238438Sdteske#ifdef  DEBUG_KEYGEN
110238438Sdteske	unsigned char *tmpout = out;
111238438Sdteske	int tmpn = n;
112238438Sdteske#endif
113238438Sdteske
114238438Sdteske#if 0
115238438Sdteske	if (!pass) {
116238438Sdteske		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_PASSED_NULL_PARAMETER);
117238438Sdteske		return 0;
118238438Sdteske	}
119238438Sdteske#endif
120238438Sdteske
121238438Sdteske#ifdef  DEBUG_KEYGEN
122238438Sdteske	fprintf(stderr, "KEYGEN DEBUG\n");
123238438Sdteske	fprintf(stderr, "ID %d, ITER %d\n", id, iter);
124238438Sdteske	fprintf(stderr, "Password (length %d):\n", passlen);
125238438Sdteske	h__dump(pass, passlen);
126238438Sdteske	fprintf(stderr, "Salt (length %d):\n", saltlen);
127238438Sdteske	h__dump(salt, saltlen);
128238438Sdteske#endif
129238438Sdteske	v = EVP_MD_block_size (md_type);
130238438Sdteske	u = EVP_MD_size (md_type);
131238438Sdteske	D = OPENSSL_malloc (v);
132238438Sdteske	Ai = OPENSSL_malloc (u);
133238438Sdteske	B = OPENSSL_malloc (v + 1);
134238438Sdteske	Slen = v * ((saltlen+v-1)/v);
135238438Sdteske	if(passlen) Plen = v * ((passlen+v-1)/v);
136238438Sdteske	else Plen = 0;
137238438Sdteske	Ilen = Slen + Plen;
138238438Sdteske	I = OPENSSL_malloc (Ilen);
139238438Sdteske	Ij = BN_new();
140238438Sdteske	Bpl1 = BN_new();
141238438Sdteske	if (!D || !Ai || !B || !I || !Ij || !Bpl1) {
142238438Sdteske		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_MALLOC_FAILURE);
143238438Sdteske		return 0;
144238438Sdteske	}
145238438Sdteske	for (i = 0; i < v; i++) D[i] = id;
146238438Sdteske	p = I;
147238438Sdteske	for (i = 0; i < Slen; i++) *p++ = salt[i % saltlen];
148238438Sdteske	for (i = 0; i < Plen; i++) *p++ = pass[i % passlen];
149238438Sdteske	for (;;) {
150238438Sdteske		EVP_DigestInit (&ctx, md_type);
151238438Sdteske		EVP_DigestUpdate (&ctx, D, v);
152238438Sdteske		EVP_DigestUpdate (&ctx, I, Ilen);
153238438Sdteske		EVP_DigestFinal (&ctx, Ai, NULL);
154238438Sdteske		for (j = 1; j < iter; j++) {
155238438Sdteske			EVP_DigestInit (&ctx, md_type);
156238438Sdteske			EVP_DigestUpdate (&ctx, Ai, u);
157238438Sdteske			EVP_DigestFinal (&ctx, Ai, NULL);
158238438Sdteske		}
159238438Sdteske		memcpy (out, Ai, min (n, u));
160238438Sdteske		if (u >= n) {
161238438Sdteske			OPENSSL_free (Ai);
162238438Sdteske			OPENSSL_free (B);
163238438Sdteske			OPENSSL_free (D);
164238438Sdteske			OPENSSL_free (I);
165238438Sdteske			BN_free (Ij);
166238438Sdteske			BN_free (Bpl1);
167238438Sdteske#ifdef DEBUG_KEYGEN
168238438Sdteske			fprintf(stderr, "Output KEY (length %d)\n", tmpn);
169238438Sdteske			h__dump(tmpout, tmpn);
170238438Sdteske#endif
171238438Sdteske			return 1;
172238438Sdteske		}
173238438Sdteske		n -= u;
174238438Sdteske		out += u;
175238438Sdteske		for (j = 0; j < v; j++) B[j] = Ai[j % u];
176238438Sdteske		/* Work out B + 1 first then can use B as tmp space */
177238438Sdteske		BN_bin2bn (B, v, Bpl1);
178238438Sdteske		BN_add_word (Bpl1, 1);
179238438Sdteske		for (j = 0; j < Ilen ; j+=v) {
180238438Sdteske			BN_bin2bn (I + j, v, Ij);
181238438Sdteske			BN_add (Ij, Ij, Bpl1);
182238438Sdteske			BN_bn2bin (Ij, B);
183238438Sdteske			/* If more than 2^(v*8) - 1 cut off MSB */
184238438Sdteske			if (BN_num_bytes (Ij) > v) {
185238438Sdteske				BN_bn2bin (Ij, B);
186238438Sdteske				memcpy (I + j, B + 1, v);
187238438Sdteske			} else BN_bn2bin (Ij, I + j);
188238438Sdteske		}
189238438Sdteske	}
190238438Sdteske}
191238438Sdteske#ifdef DEBUG_KEYGEN
192238438Sdteskevoid h__dump (unsigned char *p, int len)
193238438Sdteske{
194238438Sdteske	for (; len --; p++) fprintf(stderr, "%02X", *p);
195238438Sdteske	fprintf(stderr, "\n");
196238438Sdteske}
197238438Sdteske#endif
198238438Sdteske