s390x assembly pack: perlasm module update
[openssl.git] / crypto / pkcs12 / p12_key.c
1 /*
2  * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/pkcs12.h>
13 #include <openssl/bn.h>
14 #include <openssl/trace.h>
15
16 /* PKCS12 compatible key/IV generation */
17 #ifndef min
18 # define min(a,b) ((a) < (b) ? (a) : (b))
19 #endif
20
21 int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
22                        int saltlen, int id, int iter, int n,
23                        unsigned char *out, const EVP_MD *md_type)
24 {
25     int ret;
26     unsigned char *unipass;
27     int uniplen;
28
29     if (pass == NULL) {
30         unipass = NULL;
31         uniplen = 0;
32     } else if (!OPENSSL_asc2uni(pass, passlen, &unipass, &uniplen)) {
33         PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC, ERR_R_MALLOC_FAILURE);
34         return 0;
35     }
36     ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
37                              id, iter, n, out, md_type);
38     if (ret <= 0)
39         return 0;
40     OPENSSL_clear_free(unipass, uniplen);
41     return ret;
42 }
43
44 int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
45                         int saltlen, int id, int iter, int n,
46                         unsigned char *out, const EVP_MD *md_type)
47 {
48     int ret;
49     unsigned char *unipass;
50     int uniplen;
51
52     if (pass == NULL) {
53         unipass = NULL;
54         uniplen = 0;
55     } else if (!OPENSSL_utf82uni(pass, passlen, &unipass, &uniplen)) {
56         PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UTF8, ERR_R_MALLOC_FAILURE);
57         return 0;
58     }
59     ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
60                              id, iter, n, out, md_type);
61     if (ret <= 0)
62         return 0;
63     OPENSSL_clear_free(unipass, uniplen);
64     return ret;
65 }
66
67 int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
68                        int saltlen, int id, int iter, int n,
69                        unsigned char *out, const EVP_MD *md_type)
70 {
71     unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
72     int Slen, Plen, Ilen;
73     int i, j, u, v;
74     int ret = 0;
75     EVP_MD_CTX *ctx = NULL;
76     unsigned char *tmpout = out;
77     int tmpn = n;
78
79     ctx = EVP_MD_CTX_new();
80     if (ctx == NULL)
81         goto err;
82
83     OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
84         BIO_printf(trc_out, "PKCS12_key_gen_uni(): ID %d, ITER %d\n", id, iter);
85         BIO_printf(trc_out, "Password (length %d):\n", passlen);
86         BIO_hex_string(trc_out, 0, passlen, pass, passlen);
87         BIO_printf(trc_out, "\n");
88         BIO_printf(trc_out, "Salt (length %d):\n", saltlen);
89         BIO_hex_string(trc_out, 0, saltlen, salt, saltlen);
90         BIO_printf(trc_out, "\n");
91     } OSSL_TRACE_END(PKCS12_KEYGEN);
92     v = EVP_MD_block_size(md_type);
93     u = EVP_MD_size(md_type);
94     if (u < 0 || v <= 0)
95         goto err;
96     D = OPENSSL_malloc(v);
97     Ai = OPENSSL_malloc(u);
98     B = OPENSSL_malloc(v + 1);
99     Slen = v * ((saltlen + v - 1) / v);
100     if (passlen)
101         Plen = v * ((passlen + v - 1) / v);
102     else
103         Plen = 0;
104     Ilen = Slen + Plen;
105     I = OPENSSL_malloc(Ilen);
106     if (D == NULL || Ai == NULL || B == NULL || I == NULL)
107         goto err;
108     for (i = 0; i < v; i++)
109         D[i] = id;
110     p = I;
111     for (i = 0; i < Slen; i++)
112         *p++ = salt[i % saltlen];
113     for (i = 0; i < Plen; i++)
114         *p++ = pass[i % passlen];
115     for (;;) {
116         if (!EVP_DigestInit_ex(ctx, md_type, NULL)
117             || !EVP_DigestUpdate(ctx, D, v)
118             || !EVP_DigestUpdate(ctx, I, Ilen)
119             || !EVP_DigestFinal_ex(ctx, Ai, NULL))
120             goto err;
121         for (j = 1; j < iter; j++) {
122             if (!EVP_DigestInit_ex(ctx, md_type, NULL)
123                 || !EVP_DigestUpdate(ctx, Ai, u)
124                 || !EVP_DigestFinal_ex(ctx, Ai, NULL))
125                 goto err;
126         }
127         memcpy(out, Ai, min(n, u));
128         if (u >= n) {
129             OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
130                 BIO_printf(trc_out, "Output KEY (length %d)\n", tmpn);
131                 BIO_hex_string(trc_out, 0, tmpn, tmpout, tmpn);
132                 BIO_printf(trc_out, "\n");
133             } OSSL_TRACE_END(PKCS12_KEYGEN);
134             ret = 1;
135             goto end;
136         }
137         n -= u;
138         out += u;
139         for (j = 0; j < v; j++)
140             B[j] = Ai[j % u];
141         for (j = 0; j < Ilen; j += v) {
142             int k;
143             unsigned char *Ij = I + j;
144             uint16_t c = 1;
145
146             /* Work out Ij = Ij + B + 1 */
147             for (k = v - 1; k >= 0; k--) {
148                 c += Ij[k] + B[k];
149                 Ij[k] = (unsigned char)c;
150                 c >>= 8;
151             }
152         }
153     }
154
155  err:
156     PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI, ERR_R_MALLOC_FAILURE);
157
158  end:
159     OPENSSL_free(Ai);
160     OPENSSL_free(B);
161     OPENSSL_free(D);
162     OPENSSL_free(I);
163     EVP_MD_CTX_free(ctx);
164     return ret;
165 }