/src/openssl/crypto/evp/p5_crpt2.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the OpenSSL license (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 <stdlib.h> |
12 | | #include "internal/cryptlib.h" |
13 | | # include <openssl/x509.h> |
14 | | # include <openssl/evp.h> |
15 | | # include <openssl/hmac.h> |
16 | | # include "evp_locl.h" |
17 | | |
18 | | /* set this to print out info about the keygen algorithm */ |
19 | | /* #define OPENSSL_DEBUG_PKCS5V2 */ |
20 | | |
21 | | # ifdef OPENSSL_DEBUG_PKCS5V2 |
22 | | static void h__dump(const unsigned char *p, int len); |
23 | | # endif |
24 | | |
25 | | /* |
26 | | * This is an implementation of PKCS#5 v2.0 password based encryption key |
27 | | * derivation function PBKDF2. SHA1 version verified against test vectors |
28 | | * posted by Peter Gutmann to the PKCS-TNG mailing list. |
29 | | */ |
30 | | |
31 | | int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, |
32 | | const unsigned char *salt, int saltlen, int iter, |
33 | | const EVP_MD *digest, int keylen, unsigned char *out) |
34 | 0 | { |
35 | 0 | const char *empty = ""; |
36 | 0 | unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; |
37 | 0 | int cplen, j, k, tkeylen, mdlen; |
38 | 0 | unsigned long i = 1; |
39 | 0 | HMAC_CTX *hctx_tpl = NULL, *hctx = NULL; |
40 | 0 |
|
41 | 0 | mdlen = EVP_MD_size(digest); |
42 | 0 | if (mdlen < 0) |
43 | 0 | return 0; |
44 | 0 | |
45 | 0 | hctx_tpl = HMAC_CTX_new(); |
46 | 0 | if (hctx_tpl == NULL) |
47 | 0 | return 0; |
48 | 0 | p = out; |
49 | 0 | tkeylen = keylen; |
50 | 0 | if (pass == NULL) { |
51 | 0 | pass = empty; |
52 | 0 | passlen = 0; |
53 | 0 | } else if (passlen == -1) { |
54 | 0 | passlen = strlen(pass); |
55 | 0 | } |
56 | 0 | if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) { |
57 | 0 | HMAC_CTX_free(hctx_tpl); |
58 | 0 | return 0; |
59 | 0 | } |
60 | 0 | hctx = HMAC_CTX_new(); |
61 | 0 | if (hctx == NULL) { |
62 | 0 | HMAC_CTX_free(hctx_tpl); |
63 | 0 | return 0; |
64 | 0 | } |
65 | 0 | while (tkeylen) { |
66 | 0 | if (tkeylen > mdlen) |
67 | 0 | cplen = mdlen; |
68 | 0 | else |
69 | 0 | cplen = tkeylen; |
70 | 0 | /* |
71 | 0 | * We are unlikely to ever use more than 256 blocks (5120 bits!) but |
72 | 0 | * just in case... |
73 | 0 | */ |
74 | 0 | itmp[0] = (unsigned char)((i >> 24) & 0xff); |
75 | 0 | itmp[1] = (unsigned char)((i >> 16) & 0xff); |
76 | 0 | itmp[2] = (unsigned char)((i >> 8) & 0xff); |
77 | 0 | itmp[3] = (unsigned char)(i & 0xff); |
78 | 0 | if (!HMAC_CTX_copy(hctx, hctx_tpl)) { |
79 | 0 | HMAC_CTX_free(hctx); |
80 | 0 | HMAC_CTX_free(hctx_tpl); |
81 | 0 | return 0; |
82 | 0 | } |
83 | 0 | if (!HMAC_Update(hctx, salt, saltlen) |
84 | 0 | || !HMAC_Update(hctx, itmp, 4) |
85 | 0 | || !HMAC_Final(hctx, digtmp, NULL)) { |
86 | 0 | HMAC_CTX_free(hctx); |
87 | 0 | HMAC_CTX_free(hctx_tpl); |
88 | 0 | return 0; |
89 | 0 | } |
90 | 0 | memcpy(p, digtmp, cplen); |
91 | 0 | for (j = 1; j < iter; j++) { |
92 | 0 | if (!HMAC_CTX_copy(hctx, hctx_tpl)) { |
93 | 0 | HMAC_CTX_free(hctx); |
94 | 0 | HMAC_CTX_free(hctx_tpl); |
95 | 0 | return 0; |
96 | 0 | } |
97 | 0 | if (!HMAC_Update(hctx, digtmp, mdlen) |
98 | 0 | || !HMAC_Final(hctx, digtmp, NULL)) { |
99 | 0 | HMAC_CTX_free(hctx); |
100 | 0 | HMAC_CTX_free(hctx_tpl); |
101 | 0 | return 0; |
102 | 0 | } |
103 | 0 | for (k = 0; k < cplen; k++) |
104 | 0 | p[k] ^= digtmp[k]; |
105 | 0 | } |
106 | 0 | tkeylen -= cplen; |
107 | 0 | i++; |
108 | 0 | p += cplen; |
109 | 0 | } |
110 | 0 | HMAC_CTX_free(hctx); |
111 | 0 | HMAC_CTX_free(hctx_tpl); |
112 | | # ifdef OPENSSL_DEBUG_PKCS5V2 |
113 | | fprintf(stderr, "Password:\n"); |
114 | | h__dump(pass, passlen); |
115 | | fprintf(stderr, "Salt:\n"); |
116 | | h__dump(salt, saltlen); |
117 | | fprintf(stderr, "Iteration count %d\n", iter); |
118 | | fprintf(stderr, "Key:\n"); |
119 | | h__dump(out, keylen); |
120 | | # endif |
121 | | return 1; |
122 | 0 | } |
123 | | |
124 | | int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, |
125 | | const unsigned char *salt, int saltlen, int iter, |
126 | | int keylen, unsigned char *out) |
127 | 0 | { |
128 | 0 | return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(), |
129 | 0 | keylen, out); |
130 | 0 | } |
131 | | |
132 | | /* |
133 | | * Now the key derivation function itself. This is a bit evil because it has |
134 | | * to check the ASN1 parameters are valid: and there are quite a few of |
135 | | * them... |
136 | | */ |
137 | | |
138 | | int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, |
139 | | ASN1_TYPE *param, const EVP_CIPHER *c, |
140 | | const EVP_MD *md, int en_de) |
141 | 0 | { |
142 | 0 | PBE2PARAM *pbe2 = NULL; |
143 | 0 | const EVP_CIPHER *cipher; |
144 | 0 | EVP_PBE_KEYGEN *kdf; |
145 | 0 |
|
146 | 0 | int rv = 0; |
147 | 0 |
|
148 | 0 | pbe2 = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBE2PARAM), param); |
149 | 0 | if (pbe2 == NULL) { |
150 | 0 | EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_DECODE_ERROR); |
151 | 0 | goto err; |
152 | 0 | } |
153 | 0 |
|
154 | 0 | /* See if we recognise the key derivation function */ |
155 | 0 | if (!EVP_PBE_find(EVP_PBE_TYPE_KDF, OBJ_obj2nid(pbe2->keyfunc->algorithm), |
156 | 0 | NULL, NULL, &kdf)) { |
157 | 0 | EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, |
158 | 0 | EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); |
159 | 0 | goto err; |
160 | 0 | } |
161 | 0 |
|
162 | 0 | /* |
163 | 0 | * lets see if we recognise the encryption algorithm. |
164 | 0 | */ |
165 | 0 |
|
166 | 0 | cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm); |
167 | 0 |
|
168 | 0 | if (!cipher) { |
169 | 0 | EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_CIPHER); |
170 | 0 | goto err; |
171 | 0 | } |
172 | 0 |
|
173 | 0 | /* Fixup cipher based on AlgorithmIdentifier */ |
174 | 0 | if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de)) |
175 | 0 | goto err; |
176 | 0 | if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { |
177 | 0 | EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_CIPHER_PARAMETER_ERROR); |
178 | 0 | goto err; |
179 | 0 | } |
180 | 0 | rv = kdf(ctx, pass, passlen, pbe2->keyfunc->parameter, NULL, NULL, en_de); |
181 | 0 | err: |
182 | 0 | PBE2PARAM_free(pbe2); |
183 | 0 | return rv; |
184 | 0 | } |
185 | | |
186 | | int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, |
187 | | int passlen, ASN1_TYPE *param, |
188 | | const EVP_CIPHER *c, const EVP_MD *md, int en_de) |
189 | 0 | { |
190 | 0 | unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; |
191 | 0 | int saltlen, iter; |
192 | 0 | int rv = 0; |
193 | 0 | unsigned int keylen = 0; |
194 | 0 | int prf_nid, hmac_md_nid; |
195 | 0 | PBKDF2PARAM *kdf = NULL; |
196 | 0 | const EVP_MD *prfmd; |
197 | 0 |
|
198 | 0 | if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { |
199 | 0 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_NO_CIPHER_SET); |
200 | 0 | goto err; |
201 | 0 | } |
202 | 0 | keylen = EVP_CIPHER_CTX_key_length(ctx); |
203 | 0 | OPENSSL_assert(keylen <= sizeof(key)); |
204 | 0 |
|
205 | 0 | /* Decode parameter */ |
206 | 0 |
|
207 | 0 | kdf = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), param); |
208 | 0 |
|
209 | 0 | if (kdf == NULL) { |
210 | 0 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_DECODE_ERROR); |
211 | 0 | goto err; |
212 | 0 | } |
213 | 0 |
|
214 | 0 | keylen = EVP_CIPHER_CTX_key_length(ctx); |
215 | 0 |
|
216 | 0 | /* Now check the parameters of the kdf */ |
217 | 0 |
|
218 | 0 | if (kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)) { |
219 | 0 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_KEYLENGTH); |
220 | 0 | goto err; |
221 | 0 | } |
222 | 0 |
|
223 | 0 | if (kdf->prf) |
224 | 0 | prf_nid = OBJ_obj2nid(kdf->prf->algorithm); |
225 | 0 | else |
226 | 0 | prf_nid = NID_hmacWithSHA1; |
227 | 0 |
|
228 | 0 | if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) { |
229 | 0 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); |
230 | 0 | goto err; |
231 | 0 | } |
232 | 0 |
|
233 | 0 | prfmd = EVP_get_digestbynid(hmac_md_nid); |
234 | 0 | if (prfmd == NULL) { |
235 | 0 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); |
236 | 0 | goto err; |
237 | 0 | } |
238 | 0 |
|
239 | 0 | if (kdf->salt->type != V_ASN1_OCTET_STRING) { |
240 | 0 | EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_SALT_TYPE); |
241 | 0 | goto err; |
242 | 0 | } |
243 | 0 |
|
244 | 0 | /* it seems that its all OK */ |
245 | 0 | salt = kdf->salt->value.octet_string->data; |
246 | 0 | saltlen = kdf->salt->value.octet_string->length; |
247 | 0 | iter = ASN1_INTEGER_get(kdf->iter); |
248 | 0 | if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd, |
249 | 0 | keylen, key)) |
250 | 0 | goto err; |
251 | 0 | rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); |
252 | 0 | err: |
253 | 0 | OPENSSL_cleanse(key, keylen); |
254 | 0 | PBKDF2PARAM_free(kdf); |
255 | 0 | return rv; |
256 | 0 | } |
257 | | |
258 | | # ifdef OPENSSL_DEBUG_PKCS5V2 |
259 | | static void h__dump(const unsigned char *p, int len) |
260 | | { |
261 | | for (; len--; p++) |
262 | | fprintf(stderr, "%02X ", *p); |
263 | | fprintf(stderr, "\n"); |
264 | | } |
265 | | # endif |