16f9291ceSJung-uk Kim /* 2*e71b7053SJung-uk Kim * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. 374664626SKris Kennaway * 4*e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5*e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6*e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7*e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 874664626SKris Kennaway */ 974664626SKris Kennaway 1074664626SKris Kennaway #include <stdio.h> 11*e71b7053SJung-uk Kim #include "internal/cryptlib.h" 1274664626SKris Kennaway #include <openssl/pkcs12.h> 133b4e3dcbSSimon L. B. Nielsen #include <openssl/bn.h> 1474664626SKris Kennaway 1574664626SKris Kennaway /* Uncomment out this line to get debugging info about key generation */ 166f9291ceSJung-uk Kim /* 17*e71b7053SJung-uk Kim * #define OPENSSL_DEBUG_KEYGEN 186f9291ceSJung-uk Kim */ 19*e71b7053SJung-uk Kim #ifdef OPENSSL_DEBUG_KEYGEN 20f579bf8eSKris Kennaway # include <openssl/bio.h> 2174664626SKris Kennaway extern BIO *bio_err; 2274664626SKris Kennaway void h__dump(unsigned char *p, int len); 2374664626SKris Kennaway #endif 2474664626SKris Kennaway 2574664626SKris Kennaway /* PKCS12 compatible key/IV generation */ 2674664626SKris Kennaway #ifndef min 2774664626SKris Kennaway # define min(a,b) ((a) < (b) ? (a) : (b)) 2874664626SKris Kennaway #endif 2974664626SKris Kennaway 3074664626SKris Kennaway int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, 316f9291ceSJung-uk Kim int saltlen, int id, int iter, int n, 326f9291ceSJung-uk Kim unsigned char *out, const EVP_MD *md_type) 3374664626SKris Kennaway { 3474664626SKris Kennaway int ret; 3574664626SKris Kennaway unsigned char *unipass; 3674664626SKris Kennaway int uniplen; 371f13597dSJung-uk Kim 38ddd58736SKris Kennaway if (!pass) { 39ddd58736SKris Kennaway unipass = NULL; 40ddd58736SKris Kennaway uniplen = 0; 411f13597dSJung-uk Kim } else if (!OPENSSL_asc2uni(pass, passlen, &unipass, &uniplen)) { 4274664626SKris Kennaway PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC, ERR_R_MALLOC_FAILURE); 4374664626SKris Kennaway return 0; 4474664626SKris Kennaway } 4574664626SKris Kennaway ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen, 4674664626SKris Kennaway id, iter, n, out, md_type); 471f13597dSJung-uk Kim if (ret <= 0) 481f13597dSJung-uk Kim return 0; 49*e71b7053SJung-uk Kim OPENSSL_clear_free(unipass, uniplen); 50*e71b7053SJung-uk Kim return ret; 51ddd58736SKris Kennaway } 52*e71b7053SJung-uk Kim 53*e71b7053SJung-uk Kim int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt, 54*e71b7053SJung-uk Kim int saltlen, int id, int iter, int n, 55*e71b7053SJung-uk Kim unsigned char *out, const EVP_MD *md_type) 56*e71b7053SJung-uk Kim { 57*e71b7053SJung-uk Kim int ret; 58*e71b7053SJung-uk Kim unsigned char *unipass; 59*e71b7053SJung-uk Kim int uniplen; 60*e71b7053SJung-uk Kim 61*e71b7053SJung-uk Kim if (!pass) { 62*e71b7053SJung-uk Kim unipass = NULL; 63*e71b7053SJung-uk Kim uniplen = 0; 64*e71b7053SJung-uk Kim } else if (!OPENSSL_utf82uni(pass, passlen, &unipass, &uniplen)) { 65*e71b7053SJung-uk Kim PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UTF8, ERR_R_MALLOC_FAILURE); 66*e71b7053SJung-uk Kim return 0; 67*e71b7053SJung-uk Kim } 68*e71b7053SJung-uk Kim ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen, 69*e71b7053SJung-uk Kim id, iter, n, out, md_type); 70*e71b7053SJung-uk Kim if (ret <= 0) 71*e71b7053SJung-uk Kim return 0; 72*e71b7053SJung-uk Kim OPENSSL_clear_free(unipass, uniplen); 7374664626SKris Kennaway return ret; 7474664626SKris Kennaway } 7574664626SKris Kennaway 7674664626SKris Kennaway int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, 776f9291ceSJung-uk Kim int saltlen, int id, int iter, int n, 786f9291ceSJung-uk Kim unsigned char *out, const EVP_MD *md_type) 7974664626SKris Kennaway { 80*e71b7053SJung-uk Kim unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL; 81*e71b7053SJung-uk Kim int Slen, Plen, Ilen; 8274664626SKris Kennaway int i, j, u, v; 83a3ddd25aSSimon L. B. Nielsen int ret = 0; 84*e71b7053SJung-uk Kim EVP_MD_CTX *ctx = NULL; 85*e71b7053SJung-uk Kim #ifdef OPENSSL_DEBUG_KEYGEN 8674664626SKris Kennaway unsigned char *tmpout = out; 8774664626SKris Kennaway int tmpn = n; 88f579bf8eSKris Kennaway #endif 89f579bf8eSKris Kennaway 90*e71b7053SJung-uk Kim ctx = EVP_MD_CTX_new(); 91*e71b7053SJung-uk Kim if (ctx == NULL) 92*e71b7053SJung-uk Kim goto err; 93f579bf8eSKris Kennaway 94*e71b7053SJung-uk Kim #ifdef OPENSSL_DEBUG_KEYGEN 95f579bf8eSKris Kennaway fprintf(stderr, "KEYGEN DEBUG\n"); 96f579bf8eSKris Kennaway fprintf(stderr, "ID %d, ITER %d\n", id, iter); 97f579bf8eSKris Kennaway fprintf(stderr, "Password (length %d):\n", passlen); 9874664626SKris Kennaway h__dump(pass, passlen); 99f579bf8eSKris Kennaway fprintf(stderr, "Salt (length %d):\n", saltlen); 10074664626SKris Kennaway h__dump(salt, saltlen); 10174664626SKris Kennaway #endif 10274664626SKris Kennaway v = EVP_MD_block_size(md_type); 10374664626SKris Kennaway u = EVP_MD_size(md_type); 104*e71b7053SJung-uk Kim if (u < 0 || v <= 0) 105*e71b7053SJung-uk Kim goto err; 106ddd58736SKris Kennaway D = OPENSSL_malloc(v); 107ddd58736SKris Kennaway Ai = OPENSSL_malloc(u); 108ddd58736SKris Kennaway B = OPENSSL_malloc(v + 1); 10974664626SKris Kennaway Slen = v * ((saltlen + v - 1) / v); 1106f9291ceSJung-uk Kim if (passlen) 1116f9291ceSJung-uk Kim Plen = v * ((passlen + v - 1) / v); 1126f9291ceSJung-uk Kim else 1136f9291ceSJung-uk Kim Plen = 0; 11474664626SKris Kennaway Ilen = Slen + Plen; 115ddd58736SKris Kennaway I = OPENSSL_malloc(Ilen); 116*e71b7053SJung-uk Kim if (D == NULL || Ai == NULL || B == NULL || I == NULL) 117a3ddd25aSSimon L. B. Nielsen goto err; 1186f9291ceSJung-uk Kim for (i = 0; i < v; i++) 1196f9291ceSJung-uk Kim D[i] = id; 12074664626SKris Kennaway p = I; 1216f9291ceSJung-uk Kim for (i = 0; i < Slen; i++) 1226f9291ceSJung-uk Kim *p++ = salt[i % saltlen]; 1236f9291ceSJung-uk Kim for (i = 0; i < Plen; i++) 1246f9291ceSJung-uk Kim *p++ = pass[i % passlen]; 12574664626SKris Kennaway for (;;) { 126*e71b7053SJung-uk Kim if (!EVP_DigestInit_ex(ctx, md_type, NULL) 127*e71b7053SJung-uk Kim || !EVP_DigestUpdate(ctx, D, v) 128*e71b7053SJung-uk Kim || !EVP_DigestUpdate(ctx, I, Ilen) 129*e71b7053SJung-uk Kim || !EVP_DigestFinal_ex(ctx, Ai, NULL)) 1301f13597dSJung-uk Kim goto err; 13174664626SKris Kennaway for (j = 1; j < iter; j++) { 132*e71b7053SJung-uk Kim if (!EVP_DigestInit_ex(ctx, md_type, NULL) 133*e71b7053SJung-uk Kim || !EVP_DigestUpdate(ctx, Ai, u) 134*e71b7053SJung-uk Kim || !EVP_DigestFinal_ex(ctx, Ai, NULL)) 1351f13597dSJung-uk Kim goto err; 13674664626SKris Kennaway } 13774664626SKris Kennaway memcpy(out, Ai, min(n, u)); 13874664626SKris Kennaway if (u >= n) { 139*e71b7053SJung-uk Kim #ifdef OPENSSL_DEBUG_KEYGEN 140f579bf8eSKris Kennaway fprintf(stderr, "Output KEY (length %d)\n", tmpn); 14174664626SKris Kennaway h__dump(tmpout, tmpn); 14274664626SKris Kennaway #endif 143a3ddd25aSSimon L. B. Nielsen ret = 1; 144a3ddd25aSSimon L. B. Nielsen goto end; 14574664626SKris Kennaway } 14674664626SKris Kennaway n -= u; 14774664626SKris Kennaway out += u; 1486f9291ceSJung-uk Kim for (j = 0; j < v; j++) 1496f9291ceSJung-uk Kim B[j] = Ai[j % u]; 15074664626SKris Kennaway for (j = 0; j < Ilen; j += v) { 151*e71b7053SJung-uk Kim int k; 152*e71b7053SJung-uk Kim unsigned char *Ij = I + j; 153*e71b7053SJung-uk Kim uint16_t c = 1; 154*e71b7053SJung-uk Kim 155*e71b7053SJung-uk Kim /* Work out Ij = Ij + B + 1 */ 156*e71b7053SJung-uk Kim for (k = v - 1; k >= 0; k--) { 157*e71b7053SJung-uk Kim c += Ij[k] + B[k]; 158*e71b7053SJung-uk Kim Ij[k] = (unsigned char)c; 159*e71b7053SJung-uk Kim c >>= 8; 160*e71b7053SJung-uk Kim } 16174664626SKris Kennaway } 16274664626SKris Kennaway } 163a3ddd25aSSimon L. B. Nielsen 164a3ddd25aSSimon L. B. Nielsen err: 165a3ddd25aSSimon L. B. Nielsen PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI, ERR_R_MALLOC_FAILURE); 166a3ddd25aSSimon L. B. Nielsen 167a3ddd25aSSimon L. B. Nielsen end: 168a3ddd25aSSimon L. B. Nielsen OPENSSL_free(Ai); 169a3ddd25aSSimon L. B. Nielsen OPENSSL_free(B); 170a3ddd25aSSimon L. B. Nielsen OPENSSL_free(D); 171a3ddd25aSSimon L. B. Nielsen OPENSSL_free(I); 172*e71b7053SJung-uk Kim EVP_MD_CTX_free(ctx); 173a3ddd25aSSimon L. B. Nielsen return ret; 17474664626SKris Kennaway } 1756f9291ceSJung-uk Kim 176*e71b7053SJung-uk Kim #ifdef OPENSSL_DEBUG_KEYGEN 17774664626SKris Kennaway void h__dump(unsigned char *p, int len) 17874664626SKris Kennaway { 1796f9291ceSJung-uk Kim for (; len--; p++) 1806f9291ceSJung-uk Kim fprintf(stderr, "%02X", *p); 181f579bf8eSKris Kennaway fprintf(stderr, "\n"); 18274664626SKris Kennaway } 18374664626SKris Kennaway #endif 184