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