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