Branch data Line data Source code
1 : : /* p5_crpt2.c */
2 : : /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 : : * project 1999.
4 : : */
5 : : /* ====================================================================
6 : : * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved.
7 : : *
8 : : * Redistribution and use in source and binary forms, with or without
9 : : * modification, are permitted provided that the following conditions
10 : : * are met:
11 : : *
12 : : * 1. Redistributions of source code must retain the above copyright
13 : : * notice, this list of conditions and the following disclaimer.
14 : : *
15 : : * 2. Redistributions in binary form must reproduce the above copyright
16 : : * notice, this list of conditions and the following disclaimer in
17 : : * the documentation and/or other materials provided with the
18 : : * distribution.
19 : : *
20 : : * 3. All advertising materials mentioning features or use of this
21 : : * software must display the following acknowledgment:
22 : : * "This product includes software developed by the OpenSSL Project
23 : : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 : : *
25 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 : : * endorse or promote products derived from this software without
27 : : * prior written permission. For written permission, please contact
28 : : * licensing@OpenSSL.org.
29 : : *
30 : : * 5. Products derived from this software may not be called "OpenSSL"
31 : : * nor may "OpenSSL" appear in their names without prior written
32 : : * permission of the OpenSSL Project.
33 : : *
34 : : * 6. Redistributions of any form whatsoever must retain the following
35 : : * acknowledgment:
36 : : * "This product includes software developed by the OpenSSL Project
37 : : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 : : *
39 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
51 : : * ====================================================================
52 : : *
53 : : * This product includes cryptographic software written by Eric Young
54 : : * (eay@cryptsoft.com). This product includes software written by Tim
55 : : * Hudson (tjh@cryptsoft.com).
56 : : *
57 : : */
58 : : #include <stdio.h>
59 : : #include <stdlib.h>
60 : : #include "cryptlib.h"
61 : : #if !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA)
62 : : #include <openssl/x509.h>
63 : : #include <openssl/evp.h>
64 : : #include <openssl/hmac.h>
65 : : #include "evp_locl.h"
66 : :
67 : : /* set this to print out info about the keygen algorithm */
68 : : /* #define DEBUG_PKCS5V2 */
69 : :
70 : : #ifdef DEBUG_PKCS5V2
71 : : static void h__dump (const unsigned char *p, int len);
72 : : #endif
73 : :
74 : : /* This is an implementation of PKCS#5 v2.0 password based encryption key
75 : : * derivation function PBKDF2.
76 : : * SHA1 version verified against test vectors posted by Peter Gutmann
77 : : * <pgut001@cs.auckland.ac.nz> to the PKCS-TNG <pkcs-tng@rsa.com> mailing list.
78 : : */
79 : :
80 : 15 : int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
81 : : const unsigned char *salt, int saltlen, int iter,
82 : : const EVP_MD *digest,
83 : : int keylen, unsigned char *out)
84 : : {
85 : : unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
86 : : int cplen, j, k, tkeylen, mdlen;
87 : 15 : unsigned long i = 1;
88 : : HMAC_CTX hctx_tpl, hctx;
89 : :
90 : 15 : mdlen = EVP_MD_size(digest);
91 [ + - ]: 15 : if (mdlen < 0)
92 : : return 0;
93 : :
94 : 15 : HMAC_CTX_init(&hctx_tpl);
95 : 15 : p = out;
96 : 15 : tkeylen = keylen;
97 [ + - ]: 15 : if(!pass)
98 : : passlen = 0;
99 [ - + ]: 15 : else if(passlen == -1)
100 : 0 : passlen = strlen(pass);
101 [ + - ]: 15 : if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL))
102 : : {
103 : 0 : HMAC_CTX_cleanup(&hctx_tpl);
104 : 0 : return 0;
105 : : }
106 [ + + ]: 32 : while(tkeylen)
107 : : {
108 [ + + ]: 17 : if(tkeylen > mdlen)
109 : : cplen = mdlen;
110 : : else
111 : 15 : cplen = tkeylen;
112 : : /* We are unlikely to ever use more than 256 blocks (5120 bits!)
113 : : * but just in case...
114 : : */
115 : 17 : itmp[0] = (unsigned char)((i >> 24) & 0xff);
116 : 17 : itmp[1] = (unsigned char)((i >> 16) & 0xff);
117 : 17 : itmp[2] = (unsigned char)((i >> 8) & 0xff);
118 : 17 : itmp[3] = (unsigned char)(i & 0xff);
119 [ - + ]: 17 : if (!HMAC_CTX_copy(&hctx, &hctx_tpl))
120 : : {
121 : 0 : HMAC_CTX_cleanup(&hctx_tpl);
122 : 0 : return 0;
123 : : }
124 [ + - ]: 17 : if (!HMAC_Update(&hctx, salt, saltlen)
125 [ + - ]: 17 : || !HMAC_Update(&hctx, itmp, 4)
126 [ - + ]: 17 : || !HMAC_Final(&hctx, digtmp, NULL))
127 : : {
128 : 0 : HMAC_CTX_cleanup(&hctx_tpl);
129 : 0 : HMAC_CTX_cleanup(&hctx);
130 : 0 : return 0;
131 : : }
132 : 17 : HMAC_CTX_cleanup(&hctx);
133 : 17 : memcpy(p, digtmp, cplen);
134 [ + + ]: 45065 : for(j = 1; j < iter; j++)
135 : : {
136 [ - + ]: 45048 : if (!HMAC_CTX_copy(&hctx, &hctx_tpl))
137 : : {
138 : 0 : HMAC_CTX_cleanup(&hctx_tpl);
139 : 0 : return 0;
140 : : }
141 [ + - ]: 45048 : if (!HMAC_Update(&hctx, digtmp, mdlen)
142 [ - + ]: 45048 : || !HMAC_Final(&hctx, digtmp, NULL))
143 : : {
144 : 0 : HMAC_CTX_cleanup(&hctx_tpl);
145 : 0 : HMAC_CTX_cleanup(&hctx);
146 : 0 : return 0;
147 : : }
148 : 45048 : HMAC_CTX_cleanup(&hctx);
149 [ + + ]: 1244999 : for(k = 0; k < cplen; k++)
150 : 1199951 : p[k] ^= digtmp[k];
151 : : }
152 : 17 : tkeylen-= cplen;
153 : 17 : i++;
154 : 17 : p+= cplen;
155 : : }
156 : 15 : HMAC_CTX_cleanup(&hctx_tpl);
157 : : #ifdef DEBUG_PKCS5V2
158 : : fprintf(stderr, "Password:\n");
159 : : h__dump (pass, passlen);
160 : : fprintf(stderr, "Salt:\n");
161 : : h__dump (salt, saltlen);
162 : : fprintf(stderr, "Iteration count %d\n", iter);
163 : : fprintf(stderr, "Key:\n");
164 : : h__dump (out, keylen);
165 : : #endif
166 : 15 : return 1;
167 : : }
168 : :
169 : 0 : int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
170 : : const unsigned char *salt, int saltlen, int iter,
171 : : int keylen, unsigned char *out)
172 : : {
173 : 0 : return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(),
174 : : keylen, out);
175 : : }
176 : :
177 : : #ifdef DO_TEST
178 : : main()
179 : : {
180 : : unsigned char out[4];
181 : : unsigned char salt[] = {0x12, 0x34, 0x56, 0x78};
182 : : PKCS5_PBKDF2_HMAC_SHA1("password", -1, salt, 4, 5, 4, out);
183 : : fprintf(stderr, "Out %02X %02X %02X %02X\n",
184 : : out[0], out[1], out[2], out[3]);
185 : : }
186 : :
187 : : #endif
188 : :
189 : : /* Now the key derivation function itself. This is a bit evil because
190 : : * it has to check the ASN1 parameters are valid: and there are quite a
191 : : * few of them...
192 : : */
193 : :
194 : 0 : int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
195 : : ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md,
196 : : int en_de)
197 : : {
198 : : const unsigned char *pbuf;
199 : : int plen;
200 : 0 : PBE2PARAM *pbe2 = NULL;
201 : : const EVP_CIPHER *cipher;
202 : :
203 : 0 : int rv = 0;
204 : :
205 [ # # ][ # # ]: 0 : if (param == NULL || param->type != V_ASN1_SEQUENCE ||
[ # # ]
206 : 0 : param->value.sequence == NULL) {
207 : 0 : EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
208 : 0 : goto err;
209 : : }
210 : :
211 : 0 : pbuf = param->value.sequence->data;
212 : 0 : plen = param->value.sequence->length;
213 [ # # ]: 0 : if(!(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) {
214 : 0 : EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
215 : 0 : goto err;
216 : : }
217 : :
218 : : /* See if we recognise the key derivation function */
219 : :
220 [ # # ]: 0 : if(OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) {
221 : 0 : EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
222 : : EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
223 : 0 : goto err;
224 : : }
225 : :
226 : : /* lets see if we recognise the encryption algorithm.
227 : : */
228 : :
229 : 0 : cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm);
230 : :
231 [ # # ]: 0 : if(!cipher) {
232 : 0 : EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
233 : : EVP_R_UNSUPPORTED_CIPHER);
234 : 0 : goto err;
235 : : }
236 : :
237 : : /* Fixup cipher based on AlgorithmIdentifier */
238 [ # # ]: 0 : if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de))
239 : : goto err;
240 [ # # ]: 0 : if(EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) {
241 : 0 : EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
242 : : EVP_R_CIPHER_PARAMETER_ERROR);
243 : 0 : goto err;
244 : : }
245 : 0 : rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass, passlen,
246 : 0 : pbe2->keyfunc->parameter, c, md, en_de);
247 : : err:
248 : 0 : PBE2PARAM_free(pbe2);
249 : 0 : return rv;
250 : : }
251 : :
252 : 0 : int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
253 : : ASN1_TYPE *param,
254 : : const EVP_CIPHER *c, const EVP_MD *md, int en_de)
255 : : {
256 : : unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
257 : : const unsigned char *pbuf;
258 : : int saltlen, iter, plen;
259 : 0 : int rv = 0;
260 : 0 : unsigned int keylen = 0;
261 : : int prf_nid, hmac_md_nid;
262 : 0 : PBKDF2PARAM *kdf = NULL;
263 : : const EVP_MD *prfmd;
264 : :
265 [ # # ]: 0 : if (EVP_CIPHER_CTX_cipher(ctx) == NULL)
266 : : {
267 : 0 : EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,EVP_R_NO_CIPHER_SET);
268 : 0 : goto err;
269 : : }
270 : 0 : keylen = EVP_CIPHER_CTX_key_length(ctx);
271 [ # # ]: 0 : OPENSSL_assert(keylen <= sizeof key);
272 : :
273 : : /* Decode parameter */
274 : :
275 [ # # ][ # # ]: 0 : if(!param || (param->type != V_ASN1_SEQUENCE))
276 : : {
277 : 0 : EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,EVP_R_DECODE_ERROR);
278 : 0 : goto err;
279 : : }
280 : :
281 : 0 : pbuf = param->value.sequence->data;
282 : 0 : plen = param->value.sequence->length;
283 : :
284 [ # # ]: 0 : if(!(kdf = d2i_PBKDF2PARAM(NULL, &pbuf, plen)) ) {
285 : 0 : EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,EVP_R_DECODE_ERROR);
286 : 0 : goto err;
287 : : }
288 : :
289 : 0 : keylen = EVP_CIPHER_CTX_key_length(ctx);
290 : :
291 : : /* Now check the parameters of the kdf */
292 : :
293 [ # # ][ # # ]: 0 : if(kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)){
294 : 0 : EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,
295 : : EVP_R_UNSUPPORTED_KEYLENGTH);
296 : 0 : goto err;
297 : : }
298 : :
299 [ # # ]: 0 : if (kdf->prf)
300 : 0 : prf_nid = OBJ_obj2nid(kdf->prf->algorithm);
301 : : else
302 : : prf_nid = NID_hmacWithSHA1;
303 : :
304 [ # # ]: 0 : if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0))
305 : : {
306 : 0 : EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
307 : 0 : goto err;
308 : : }
309 : :
310 : 0 : prfmd = EVP_get_digestbynid(hmac_md_nid);
311 [ # # ]: 0 : if (prfmd == NULL)
312 : : {
313 : 0 : EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
314 : 0 : goto err;
315 : : }
316 : :
317 [ # # ]: 0 : if(kdf->salt->type != V_ASN1_OCTET_STRING) {
318 : 0 : EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,
319 : : EVP_R_UNSUPPORTED_SALT_TYPE);
320 : 0 : goto err;
321 : : }
322 : :
323 : : /* it seems that its all OK */
324 : 0 : salt = kdf->salt->value.octet_string->data;
325 : 0 : saltlen = kdf->salt->value.octet_string->length;
326 : 0 : iter = ASN1_INTEGER_get(kdf->iter);
327 [ # # ]: 0 : if(!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd,
328 : : keylen, key))
329 : : goto err;
330 : 0 : rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
331 : : err:
332 : 0 : OPENSSL_cleanse(key, keylen);
333 : 0 : PBKDF2PARAM_free(kdf);
334 : 0 : return rv;
335 : : }
336 : :
337 : : #ifdef DEBUG_PKCS5V2
338 : : static void h__dump (const unsigned char *p, int len)
339 : : {
340 : : for (; len --; p++) fprintf(stderr, "%02X ", *p);
341 : : fprintf(stderr, "\n");
342 : : }
343 : : #endif
344 : : #endif
|