xref: /freebsd/crypto/openssl/crypto/pkcs12/p12_key.c (revision e71b70530d95c4f34d8bdbd78d1242df1ba4a945)
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