]>
Commit | Line | Data |
---|---|---|
97e4a932 | 1 | /* p5_crpt2.c */ |
2e597528 | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
97e4a932 DSH |
3 | * project 1999. |
4 | */ | |
5 | /* ==================================================================== | |
856640b5 | 6 | * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved. |
97e4a932 DSH |
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> | |
7b63c0fa | 60 | #include "cryptlib.h" |
9c354528 | 61 | #if !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA) |
97e4a932 DSH |
62 | #include <openssl/x509.h> |
63 | #include <openssl/evp.h> | |
64 | #include <openssl/hmac.h> | |
3d63b396 | 65 | #include "evp_locl.h" |
97e4a932 | 66 | |
f513939e DSH |
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 | ||
97e4a932 | 74 | /* This is an implementation of PKCS#5 v2.0 password based encryption key |
856640b5 DSH |
75 | * derivation function PBKDF2. |
76 | * SHA1 version verified against test vectors posted by Peter Gutmann | |
97e4a932 DSH |
77 | * <pgut001@cs.auckland.ac.nz> to the PKCS-TNG <pkcs-tng@rsa.com> mailing list. |
78 | */ | |
79 | ||
856640b5 | 80 | int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, |
875a644a | 81 | const unsigned char *salt, int saltlen, int iter, |
856640b5 | 82 | const EVP_MD *digest, |
72fbe87d | 83 | int keylen, unsigned char *out) |
856640b5 DSH |
84 | { |
85 | unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; | |
86 | int cplen, j, k, tkeylen, mdlen; | |
97e4a932 | 87 | unsigned long i = 1; |
c10e3f0c | 88 | HMAC_CTX hctx_tpl, hctx; |
dbad1690 | 89 | |
856640b5 | 90 | mdlen = EVP_MD_size(digest); |
0eab41fb BL |
91 | if (mdlen < 0) |
92 | return 0; | |
856640b5 | 93 | |
dbad1690 | 94 | HMAC_CTX_init(&hctx); |
97e4a932 | 95 | p = out; |
f513939e | 96 | tkeylen = keylen; |
856640b5 DSH |
97 | if(!pass) |
98 | passlen = 0; | |
99 | else if(passlen == -1) | |
100 | passlen = strlen(pass); | |
c10e3f0c BL |
101 | if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL)) |
102 | { | |
103 | HMAC_CTX_cleanup(&hctx_tpl); | |
104 | return 0; | |
105 | } | |
856640b5 DSH |
106 | while(tkeylen) |
107 | { | |
108 | if(tkeylen > mdlen) | |
109 | cplen = mdlen; | |
110 | else | |
111 | cplen = tkeylen; | |
97e4a932 DSH |
112 | /* We are unlikely to ever use more than 256 blocks (5120 bits!) |
113 | * but just in case... | |
114 | */ | |
f598cd13 DSH |
115 | itmp[0] = (unsigned char)((i >> 24) & 0xff); |
116 | itmp[1] = (unsigned char)((i >> 16) & 0xff); | |
117 | itmp[2] = (unsigned char)((i >> 8) & 0xff); | |
118 | itmp[3] = (unsigned char)(i & 0xff); | |
c10e3f0c | 119 | if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) |
b6dcdbfc | 120 | { |
c10e3f0c BL |
121 | HMAC_CTX_cleanup(&hctx_tpl); |
122 | return 0; | |
123 | } | |
124 | if (!HMAC_Update(&hctx, salt, saltlen) | |
125 | || !HMAC_Update(&hctx, itmp, 4) | |
126 | || !HMAC_Final(&hctx, digtmp, NULL)) | |
127 | { | |
128 | HMAC_CTX_cleanup(&hctx_tpl); | |
b6dcdbfc DSH |
129 | HMAC_CTX_cleanup(&hctx); |
130 | return 0; | |
131 | } | |
97e4a932 | 132 | memcpy(p, digtmp, cplen); |
856640b5 DSH |
133 | for(j = 1; j < iter; j++) |
134 | { | |
c10e3f0c BL |
135 | if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) |
136 | { | |
137 | HMAC_CTX_cleanup(&hctx_tpl); | |
138 | return 0; | |
139 | } | |
140 | if (!HMAC_Update(&hctx, digtmp, mdlen) | |
141 | || !HMAC_Final(&hctx, digtmp, NULL)) | |
142 | { | |
143 | HMAC_CTX_cleanup(&hctx_tpl); | |
144 | HMAC_CTX_cleanup(&hctx); | |
145 | return 0; | |
146 | } | |
147 | HMAC_CTX_cleanup(&hctx); | |
856640b5 DSH |
148 | for(k = 0; k < cplen; k++) |
149 | p[k] ^= digtmp[k]; | |
150 | } | |
f513939e | 151 | tkeylen-= cplen; |
97e4a932 DSH |
152 | i++; |
153 | p+= cplen; | |
856640b5 | 154 | } |
c10e3f0c | 155 | HMAC_CTX_cleanup(&hctx_tpl); |
f513939e DSH |
156 | #ifdef DEBUG_PKCS5V2 |
157 | fprintf(stderr, "Password:\n"); | |
158 | h__dump (pass, passlen); | |
159 | fprintf(stderr, "Salt:\n"); | |
160 | h__dump (salt, saltlen); | |
161 | fprintf(stderr, "Iteration count %d\n", iter); | |
162 | fprintf(stderr, "Key:\n"); | |
163 | h__dump (out, keylen); | |
164 | #endif | |
97e4a932 | 165 | return 1; |
856640b5 DSH |
166 | } |
167 | ||
168 | int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, | |
169 | const unsigned char *salt, int saltlen, int iter, | |
170 | int keylen, unsigned char *out) | |
171 | { | |
172 | return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(), | |
173 | keylen, out); | |
174 | } | |
97e4a932 DSH |
175 | |
176 | #ifdef DO_TEST | |
177 | main() | |
178 | { | |
179 | unsigned char out[4]; | |
180 | unsigned char salt[] = {0x12, 0x34, 0x56, 0x78}; | |
181 | PKCS5_PBKDF2_HMAC_SHA1("password", -1, salt, 4, 5, 4, out); | |
182 | fprintf(stderr, "Out %02X %02X %02X %02X\n", | |
183 | out[0], out[1], out[2], out[3]); | |
184 | } | |
185 | ||
186 | #endif | |
187 | ||
188 | /* Now the key derivation function itself. This is a bit evil because | |
189 | * it has to check the ASN1 parameters are valid: and there are quite a | |
190 | * few of them... | |
191 | */ | |
192 | ||
193 | int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, | |
13588350 | 194 | ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, |
97e4a932 DSH |
195 | int en_de) |
196 | { | |
875a644a | 197 | const unsigned char *pbuf; |
3d63b396 | 198 | int plen; |
97e4a932 DSH |
199 | PBE2PARAM *pbe2 = NULL; |
200 | const EVP_CIPHER *cipher; | |
3d63b396 DSH |
201 | |
202 | int rv = 0; | |
97e4a932 | 203 | |
c755c5fd NL |
204 | if (param == NULL || param->type != V_ASN1_SEQUENCE || |
205 | param->value.sequence == NULL) { | |
206 | EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); | |
3d63b396 | 207 | goto err; |
c755c5fd NL |
208 | } |
209 | ||
97e4a932 DSH |
210 | pbuf = param->value.sequence->data; |
211 | plen = param->value.sequence->length; | |
c755c5fd | 212 | if(!(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) { |
97e4a932 | 213 | EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); |
3d63b396 | 214 | goto err; |
97e4a932 DSH |
215 | } |
216 | ||
217 | /* See if we recognise the key derivation function */ | |
218 | ||
219 | if(OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) { | |
220 | EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, | |
221 | EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); | |
222 | goto err; | |
223 | } | |
224 | ||
225 | /* lets see if we recognise the encryption algorithm. | |
226 | */ | |
227 | ||
a620626a | 228 | cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm); |
97e4a932 DSH |
229 | |
230 | if(!cipher) { | |
231 | EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, | |
232 | EVP_R_UNSUPPORTED_CIPHER); | |
233 | goto err; | |
234 | } | |
235 | ||
236 | /* Fixup cipher based on AlgorithmIdentifier */ | |
b6dcdbfc | 237 | if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de)) |
b6dcdbfc | 238 | goto err; |
97e4a932 DSH |
239 | if(EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { |
240 | EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, | |
241 | EVP_R_CIPHER_PARAMETER_ERROR); | |
242 | goto err; | |
243 | } | |
3d63b396 DSH |
244 | rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass, passlen, |
245 | pbe2->keyfunc->parameter, c, md, en_de); | |
246 | err: | |
247 | PBE2PARAM_free(pbe2); | |
248 | return rv; | |
249 | } | |
250 | ||
251 | int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, | |
252 | ASN1_TYPE *param, | |
253 | const EVP_CIPHER *c, const EVP_MD *md, int en_de) | |
254 | { | |
255 | unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; | |
256 | const unsigned char *pbuf; | |
257 | int saltlen, iter, plen; | |
258 | int rv = 0; | |
19ec2f41 | 259 | unsigned int keylen = 0; |
3d63b396 DSH |
260 | int prf_nid, hmac_md_nid; |
261 | PBKDF2PARAM *kdf = NULL; | |
262 | const EVP_MD *prfmd; | |
263 | ||
264 | if (EVP_CIPHER_CTX_cipher(ctx) == NULL) | |
265 | { | |
266 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,EVP_R_NO_CIPHER_SET); | |
267 | goto err; | |
268 | } | |
97e4a932 | 269 | keylen = EVP_CIPHER_CTX_key_length(ctx); |
54a656ef | 270 | OPENSSL_assert(keylen <= sizeof key); |
97e4a932 | 271 | |
3d63b396 | 272 | /* Decode parameter */ |
97e4a932 | 273 | |
3d63b396 | 274 | if(!param || (param->type != V_ASN1_SEQUENCE)) |
9dc17a25 | 275 | { |
3d63b396 | 276 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,EVP_R_DECODE_ERROR); |
9dc17a25 DSH |
277 | goto err; |
278 | } | |
279 | ||
3d63b396 DSH |
280 | pbuf = param->value.sequence->data; |
281 | plen = param->value.sequence->length; | |
282 | ||
9dc17a25 | 283 | if(!(kdf = d2i_PBKDF2PARAM(NULL, &pbuf, plen)) ) { |
3d63b396 | 284 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,EVP_R_DECODE_ERROR); |
97e4a932 DSH |
285 | goto err; |
286 | } | |
287 | ||
3d63b396 | 288 | keylen = EVP_CIPHER_CTX_key_length(ctx); |
97e4a932 DSH |
289 | |
290 | /* Now check the parameters of the kdf */ | |
291 | ||
27545970 | 292 | if(kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)){ |
3d63b396 | 293 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, |
97e4a932 DSH |
294 | EVP_R_UNSUPPORTED_KEYLENGTH); |
295 | goto err; | |
296 | } | |
297 | ||
856640b5 DSH |
298 | if (kdf->prf) |
299 | prf_nid = OBJ_obj2nid(kdf->prf->algorithm); | |
300 | else | |
301 | prf_nid = NID_hmacWithSHA1; | |
302 | ||
303 | if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) | |
304 | { | |
3d63b396 | 305 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); |
97e4a932 | 306 | goto err; |
856640b5 DSH |
307 | } |
308 | ||
309 | prfmd = EVP_get_digestbynid(hmac_md_nid); | |
310 | if (prfmd == NULL) | |
311 | { | |
3d63b396 | 312 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); |
856640b5 DSH |
313 | goto err; |
314 | } | |
97e4a932 DSH |
315 | |
316 | if(kdf->salt->type != V_ASN1_OCTET_STRING) { | |
3d63b396 | 317 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, |
97e4a932 DSH |
318 | EVP_R_UNSUPPORTED_SALT_TYPE); |
319 | goto err; | |
320 | } | |
321 | ||
322 | /* it seems that its all OK */ | |
323 | salt = kdf->salt->value.octet_string->data; | |
324 | saltlen = kdf->salt->value.octet_string->length; | |
325 | iter = ASN1_INTEGER_get(kdf->iter); | |
0eab41fb BL |
326 | if(!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd, |
327 | keylen, key)) | |
328 | goto err; | |
3d63b396 | 329 | rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); |
97e4a932 | 330 | err: |
3d63b396 | 331 | OPENSSL_cleanse(key, keylen); |
97e4a932 | 332 | PBKDF2PARAM_free(kdf); |
3d63b396 | 333 | return rv; |
97e4a932 | 334 | } |
f513939e DSH |
335 | |
336 | #ifdef DEBUG_PKCS5V2 | |
337 | static void h__dump (const unsigned char *p, int len) | |
338 | { | |
339 | for (; len --; p++) fprintf(stderr, "%02X ", *p); | |
340 | fprintf(stderr, "\n"); | |
341 | } | |
5676d8cb | 342 | #endif |
9a3bbbce | 343 | #endif |