File: | s/lib/softoken/lowpbe.c |
Warning: | line 1125, column 5 Value stored to 'rv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | |
5 | #include "plarena.h" |
6 | |
7 | #include "seccomon.h" |
8 | #include "secitem.h" |
9 | #include "secport.h" |
10 | #include "hasht.h" |
11 | #include "pkcs11t.h" |
12 | #include "blapi.h" |
13 | #include "hasht.h" |
14 | #include "secasn1.h" |
15 | #include "secder.h" |
16 | #include "lowpbe.h" |
17 | #include "secoid.h" |
18 | #include "alghmac.h" |
19 | #include "softoken.h" |
20 | #include "secerr.h" |
21 | #include "pkcs11i.h" |
22 | |
23 | SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
24 | |
25 | /* how much a crypto encrypt/decryption may expand a buffer */ |
26 | #define MAX_CRYPTO_EXPANSION64 64 |
27 | |
28 | /* template for PKCS 5 PBE Parameter. This template has been expanded |
29 | * based upon the additions in PKCS 12. This should eventually be moved |
30 | * if RSA updates PKCS 5. |
31 | */ |
32 | static const SEC_ASN1Template NSSPKCS5PBEParameterTemplate[] = { |
33 | { SEC_ASN1_SEQUENCE0x10, |
34 | 0, NULL((void*)0), sizeof(NSSPKCS5PBEParameter) }, |
35 | { SEC_ASN1_OCTET_STRING0x04, |
36 | offsetof(NSSPKCS5PBEParameter, salt)__builtin_offsetof(NSSPKCS5PBEParameter, salt) }, |
37 | { SEC_ASN1_INTEGER0x02, |
38 | offsetof(NSSPKCS5PBEParameter, iteration)__builtin_offsetof(NSSPKCS5PBEParameter, iteration) }, |
39 | { 0 } |
40 | }; |
41 | |
42 | static const SEC_ASN1Template NSSPKCS5PKCS12V2PBEParameterTemplate[] = { |
43 | { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSPKCS5PBEParameter) }, |
44 | { SEC_ASN1_OCTET_STRING0x04, offsetof(NSSPKCS5PBEParameter, salt)__builtin_offsetof(NSSPKCS5PBEParameter, salt) }, |
45 | { SEC_ASN1_INTEGER0x02, offsetof(NSSPKCS5PBEParameter, iteration)__builtin_offsetof(NSSPKCS5PBEParameter, iteration) }, |
46 | { 0 } |
47 | }; |
48 | |
49 | /* PKCS5 v2 */ |
50 | |
51 | struct nsspkcs5V2PBEParameterStr { |
52 | SECAlgorithmID keyParams; /* parameters of the key generation */ |
53 | SECAlgorithmID algParams; /* parameters for the encryption or mac op */ |
54 | }; |
55 | |
56 | typedef struct nsspkcs5V2PBEParameterStr nsspkcs5V2PBEParameter; |
57 | |
58 | static const SEC_ASN1Template NSSPKCS5V2PBES2ParameterTemplate[] = { |
59 | { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(nsspkcs5V2PBEParameter) }, |
60 | { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0, |
61 | offsetof(nsspkcs5V2PBEParameter, keyParams)__builtin_offsetof(nsspkcs5V2PBEParameter, keyParams), |
62 | SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util }, |
63 | { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0, |
64 | offsetof(nsspkcs5V2PBEParameter, algParams)__builtin_offsetof(nsspkcs5V2PBEParameter, algParams), |
65 | SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util }, |
66 | { 0 } |
67 | }; |
68 | |
69 | static const SEC_ASN1Template NSSPKCS5V2PBEParameterTemplate[] = { |
70 | { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSPKCS5PBEParameter) }, |
71 | /* this is really a choice, but since we don't understand any other |
72 | * choice, just inline it. */ |
73 | { SEC_ASN1_OCTET_STRING0x04, offsetof(NSSPKCS5PBEParameter, salt)__builtin_offsetof(NSSPKCS5PBEParameter, salt) }, |
74 | { SEC_ASN1_INTEGER0x02, offsetof(NSSPKCS5PBEParameter, iteration)__builtin_offsetof(NSSPKCS5PBEParameter, iteration) }, |
75 | { SEC_ASN1_INTEGER0x02, offsetof(NSSPKCS5PBEParameter, keyLength)__builtin_offsetof(NSSPKCS5PBEParameter, keyLength) }, |
76 | { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0, |
77 | offsetof(NSSPKCS5PBEParameter, prfAlg)__builtin_offsetof(NSSPKCS5PBEParameter, prfAlg), |
78 | SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util }, |
79 | { 0 } |
80 | }; |
81 | |
82 | SECStatus |
83 | nsspkcs5_HashBuf(const SECHashObject *hashObj, unsigned char *dest, |
84 | unsigned char *src, int len) |
85 | { |
86 | void *ctx; |
87 | unsigned int retLen; |
88 | |
89 | ctx = hashObj->create(); |
90 | if (ctx == NULL((void*)0)) { |
91 | return SECFailure; |
92 | } |
93 | hashObj->begin(ctx); |
94 | hashObj->update(ctx, src, len); |
95 | hashObj->end(ctx, dest, &retLen, hashObj->length); |
96 | hashObj->destroy(ctx, PR_TRUE1); |
97 | return SECSuccess; |
98 | } |
99 | |
100 | /* generate bits using any hash |
101 | */ |
102 | static SECItem * |
103 | nsspkcs5_PBKDF1(const SECHashObject *hashObj, SECItem *salt, SECItem *pwd, |
104 | int iter, PRBool faulty3DES) |
105 | { |
106 | SECItem *hash = NULL((void*)0), *pre_hash = NULL((void*)0); |
107 | SECStatus rv = SECFailure; |
108 | |
109 | if ((salt == NULL((void*)0)) || (pwd == NULL((void*)0)) || (iter < 0)) { |
110 | return NULL((void*)0); |
111 | } |
112 | |
113 | hash = (SECItem *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(SECItem)); |
114 | pre_hash = (SECItem *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(SECItem)); |
115 | |
116 | if ((hash != NULL((void*)0)) && (pre_hash != NULL((void*)0))) { |
117 | int i, ph_len; |
118 | |
119 | ph_len = hashObj->length; |
120 | if ((salt->len + pwd->len) > hashObj->length) { |
121 | ph_len = salt->len + pwd->len; |
122 | } |
123 | |
124 | rv = SECFailure; |
125 | |
126 | /* allocate buffers */ |
127 | hash->len = hashObj->length; |
128 | hash->data = (unsigned char *)PORT_ZAllocPORT_ZAlloc_Util(hash->len); |
129 | pre_hash->data = (unsigned char *)PORT_ZAllocPORT_ZAlloc_Util(ph_len); |
130 | |
131 | /* in pbeSHA1TripleDESCBC there was an allocation error that made |
132 | * it into the caller. We do not want to propagate those errors |
133 | * further, so we are doing it correctly, but reading the old method. |
134 | */ |
135 | if (faulty3DES) { |
136 | pre_hash->len = ph_len; |
137 | } else { |
138 | pre_hash->len = salt->len + pwd->len; |
139 | } |
140 | |
141 | /* preform hash */ |
142 | if ((hash->data != NULL((void*)0)) && (pre_hash->data != NULL((void*)0))) { |
143 | rv = SECSuccess; |
144 | /* check for 0 length password */ |
145 | if (pwd->len > 0) { |
146 | PORT_Memcpymemcpy(pre_hash->data, pwd->data, pwd->len); |
147 | } |
148 | if (salt->len > 0) { |
149 | PORT_Memcpymemcpy((pre_hash->data + pwd->len), salt->data, salt->len); |
150 | } |
151 | for (i = 0; ((i < iter) && (rv == SECSuccess)); i++) { |
152 | rv = nsspkcs5_HashBuf(hashObj, hash->data, |
153 | pre_hash->data, pre_hash->len); |
154 | if (rv != SECFailure) { |
155 | pre_hash->len = hashObj->length; |
156 | PORT_Memcpymemcpy(pre_hash->data, hash->data, hashObj->length); |
157 | } |
158 | } |
159 | } |
160 | } |
161 | |
162 | if (pre_hash != NULL((void*)0)) { |
163 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(pre_hash, PR_TRUE1); |
164 | } |
165 | |
166 | if ((rv != SECSuccess) && (hash != NULL((void*)0))) { |
167 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(hash, PR_TRUE1); |
168 | hash = NULL((void*)0); |
169 | } |
170 | |
171 | return hash; |
172 | } |
173 | |
174 | /* this bit generation routine is described in PKCS 12 and the proposed |
175 | * extensions to PKCS 5. an initial hash is generated following the |
176 | * instructions laid out in PKCS 5. If the number of bits generated is |
177 | * insufficient, then the method discussed in the proposed extensions to |
178 | * PKCS 5 in PKCS 12 are used. This extension makes use of the HMAC |
179 | * function. And the P_Hash function from the TLS standard. |
180 | */ |
181 | static SECItem * |
182 | nsspkcs5_PFXPBE(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param, |
183 | SECItem *init_hash, unsigned int bytes_needed) |
184 | { |
185 | SECItem *ret_bits = NULL((void*)0); |
186 | int hash_size = 0; |
187 | unsigned int i; |
188 | unsigned int hash_iter; |
189 | unsigned int dig_len; |
190 | SECStatus rv = SECFailure; |
191 | unsigned char *state = NULL((void*)0); |
192 | unsigned int state_len; |
193 | HMACContext *cx = NULL((void*)0); |
194 | |
195 | hash_size = hashObj->length; |
196 | hash_iter = (bytes_needed + (unsigned int)hash_size - 1) / hash_size; |
197 | |
198 | /* allocate return buffer */ |
199 | ret_bits = (SECItem *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(SECItem)); |
200 | if (ret_bits == NULL((void*)0)) |
201 | return NULL((void*)0); |
202 | ret_bits->data = (unsigned char *)PORT_ZAllocPORT_ZAlloc_Util((hash_iter * hash_size) + 1); |
203 | ret_bits->len = (hash_iter * hash_size); |
204 | if (ret_bits->data == NULL((void*)0)) { |
205 | PORT_FreePORT_Free_Util(ret_bits); |
206 | return NULL((void*)0); |
207 | } |
208 | |
209 | /* allocate intermediate hash buffer. 8 is for the 8 bytes of |
210 | * data which are added based on iteration number |
211 | */ |
212 | |
213 | if ((unsigned int)hash_size > pbe_param->salt.len) { |
214 | state_len = hash_size; |
215 | } else { |
216 | state_len = pbe_param->salt.len; |
217 | } |
218 | state = (unsigned char *)PORT_ZAllocPORT_ZAlloc_Util(state_len); |
219 | if (state == NULL((void*)0)) { |
220 | rv = SECFailure; |
221 | goto loser; |
222 | } |
223 | if (pbe_param->salt.len > 0) { |
224 | PORT_Memcpymemcpy(state, pbe_param->salt.data, pbe_param->salt.len); |
225 | } |
226 | |
227 | cx = HMAC_Create(hashObj, init_hash->data, init_hash->len, PR_TRUE1); |
228 | if (cx == NULL((void*)0)) { |
229 | rv = SECFailure; |
230 | goto loser; |
231 | } |
232 | |
233 | for (i = 0; i < hash_iter; i++) { |
234 | |
235 | /* generate output bits */ |
236 | HMAC_Begin(cx); |
237 | HMAC_Update(cx, state, state_len); |
238 | HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len); |
239 | rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size), |
240 | &dig_len, hash_size); |
241 | if (rv != SECSuccess) |
242 | goto loser; |
243 | PORT_Assert((unsigned int)hash_size == dig_len)(((unsigned int)hash_size == dig_len)?((void)0):PR_Assert("(unsigned int)hash_size == dig_len" ,"lowpbe.c",243)); |
244 | |
245 | /* generate new state */ |
246 | HMAC_Begin(cx); |
247 | HMAC_Update(cx, state, state_len); |
248 | rv = HMAC_Finish(cx, state, &state_len, state_len); |
249 | if (rv != SECSuccess) |
250 | goto loser; |
251 | PORT_Assert(state_len == dig_len)((state_len == dig_len)?((void)0):PR_Assert("state_len == dig_len" ,"lowpbe.c",251)); |
252 | } |
253 | |
254 | loser: |
255 | if (state != NULL((void*)0)) |
256 | PORT_ZFreePORT_ZFree_Util(state, state_len); |
257 | HMAC_Destroy(cx, PR_TRUE1); |
258 | |
259 | if (rv != SECSuccess) { |
260 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(ret_bits, PR_TRUE1); |
261 | ret_bits = NULL((void*)0); |
262 | } |
263 | |
264 | return ret_bits; |
265 | } |
266 | |
267 | /* generate bits for the key and iv determination. if enough bits |
268 | * are not generated using PKCS 5, then we need to generate more bits |
269 | * based on the extension proposed in PKCS 12 |
270 | */ |
271 | static SECItem * |
272 | nsspkcs5_PBKDF1Extended(const SECHashObject *hashObj, |
273 | NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, PRBool faulty3DES) |
274 | { |
275 | SECItem *hash = NULL((void*)0); |
276 | SECItem *newHash = NULL((void*)0); |
277 | int bytes_needed; |
278 | int bytes_available; |
279 | |
280 | bytes_needed = pbe_param->ivLen + pbe_param->keyLen; |
281 | bytes_available = hashObj->length; |
282 | |
283 | hash = nsspkcs5_PBKDF1(hashObj, &pbe_param->salt, pwitem, |
284 | pbe_param->iter, faulty3DES); |
285 | |
286 | if (hash == NULL((void*)0)) { |
287 | return NULL((void*)0); |
288 | } |
289 | |
290 | if (bytes_needed <= bytes_available) { |
291 | return hash; |
292 | } |
293 | |
294 | newHash = nsspkcs5_PFXPBE(hashObj, pbe_param, hash, bytes_needed); |
295 | if (hash != newHash) |
296 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(hash, PR_TRUE1); |
297 | return newHash; |
298 | } |
299 | |
300 | /* |
301 | * PBDKDF2 is PKCS #5 v2.0 it's currently not used by NSS |
302 | */ |
303 | static void |
304 | do_xor(unsigned char *dest, unsigned char *src, int len) |
305 | { |
306 | /* use byt xor, not all platforms are happy about inaligned |
307 | * integer fetches */ |
308 | while (len--) { |
309 | *dest = *dest ^ *src; |
310 | dest++; |
311 | src++; |
312 | } |
313 | } |
314 | |
315 | static SECStatus |
316 | nsspkcs5_PBKDF2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt, |
317 | int iterations, unsigned int i, unsigned char *T) |
318 | { |
319 | int j; |
320 | HMACContext *cx = NULL((void*)0); |
321 | unsigned int hLen = hashobj->length; |
322 | SECStatus rv = SECFailure; |
323 | unsigned char *last = NULL((void*)0); |
324 | unsigned int lastLength = salt->len + 4; |
325 | unsigned int lastBufLength; |
326 | |
327 | cx = HMAC_Create(hashobj, pwitem->data, pwitem->len, PR_FALSE0); |
328 | if (cx == NULL((void*)0)) { |
329 | goto loser; |
330 | } |
331 | PORT_Memsetmemset(T, 0, hLen); |
332 | lastBufLength = PR_MAX(lastLength, hLen)((lastLength)>(hLen)?(lastLength):(hLen)); |
333 | last = PORT_AllocPORT_Alloc_Util(lastBufLength); |
334 | if (last == NULL((void*)0)) { |
335 | goto loser; |
336 | } |
337 | PORT_Memcpymemcpy(last, salt->data, salt->len); |
338 | last[salt->len] = (i >> 24) & 0xff; |
339 | last[salt->len + 1] = (i >> 16) & 0xff; |
340 | last[salt->len + 2] = (i >> 8) & 0xff; |
341 | last[salt->len + 3] = i & 0xff; |
342 | |
343 | /* NOTE: we need at least one iteration to return success! */ |
344 | for (j = 0; j < iterations; j++) { |
345 | HMAC_Begin(cx); |
346 | HMAC_Update(cx, last, lastLength); |
347 | rv = HMAC_Finish(cx, last, &lastLength, hLen); |
348 | if (rv != SECSuccess) { |
349 | break; |
350 | } |
351 | do_xor(T, last, hLen); |
352 | } |
353 | loser: |
354 | if (cx) { |
355 | HMAC_Destroy(cx, PR_TRUE1); |
356 | } |
357 | if (last) { |
358 | PORT_ZFreePORT_ZFree_Util(last, lastBufLength); |
359 | } |
360 | return rv; |
361 | } |
362 | |
363 | static SECItem * |
364 | nsspkcs5_PBKDF2(const SECHashObject *hashobj, NSSPKCS5PBEParameter *pbe_param, |
365 | SECItem *pwitem) |
366 | { |
367 | int iterations = pbe_param->iter; |
368 | int bytesNeeded = pbe_param->keyLen; |
369 | unsigned int dkLen = bytesNeeded; |
370 | unsigned int hLen = hashobj->length; |
371 | unsigned int nblocks = (dkLen + hLen - 1) / hLen; |
372 | unsigned int i; |
373 | unsigned char *rp; |
374 | unsigned char *T = NULL((void*)0); |
375 | SECItem *result = NULL((void*)0); |
376 | SECItem *salt = &pbe_param->salt; |
377 | SECStatus rv = SECFailure; |
378 | |
379 | result = SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), NULL((void*)0), nblocks * hLen); |
380 | if (result == NULL((void*)0)) { |
381 | return NULL((void*)0); |
382 | } |
383 | |
384 | T = PORT_AllocPORT_Alloc_Util(hLen); |
385 | if (T == NULL((void*)0)) { |
386 | goto loser; |
387 | } |
388 | |
389 | for (i = 1, rp = result->data; i <= nblocks; i++, rp += hLen) { |
390 | rv = nsspkcs5_PBKDF2_F(hashobj, pwitem, salt, iterations, i, T); |
391 | if (rv != SECSuccess) { |
392 | break; |
393 | } |
394 | PORT_Memcpymemcpy(rp, T, hLen); |
395 | } |
396 | |
397 | loser: |
398 | if (T) { |
399 | PORT_ZFreePORT_ZFree_Util(T, hLen); |
400 | } |
401 | if (rv != SECSuccess) { |
402 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(result, PR_TRUE1); |
403 | result = NULL((void*)0); |
404 | } else { |
405 | result->len = dkLen; |
406 | } |
407 | |
408 | return result; |
409 | } |
410 | |
411 | #define NSSPBE_ROUNDUP(x, y)((((x) + ((y)-1)) / (y)) * (y)) ((((x) + ((y)-1)) / (y)) * (y)) |
412 | #define NSSPBE_MIN(x, y)((x) < (y) ? (x) : (y)) ((x) < (y) ? (x) : (y)) |
413 | /* |
414 | * This is the extended PBE function defined by the final PKCS #12 spec. |
415 | */ |
416 | static SECItem * |
417 | nsspkcs5_PKCS12PBE(const SECHashObject *hashObject, |
418 | NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, |
419 | PBEBitGenID bitGenPurpose, unsigned int bytesNeeded) |
420 | { |
421 | PLArenaPool *arena = NULL((void*)0); |
422 | unsigned int SLen, PLen; |
423 | unsigned int hashLength = hashObject->length; |
424 | unsigned char *S, *P; |
425 | SECItem *A = NULL((void*)0), B, D, I; |
426 | SECItem *salt = &pbe_param->salt; |
427 | unsigned int c, i = 0; |
428 | unsigned int hashLen; |
429 | int iter; |
430 | unsigned char *iterBuf; |
431 | void *hash = NULL((void*)0); |
432 | unsigned int bufferLength; |
433 | |
434 | arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048)); |
435 | if (!arena) { |
436 | return NULL((void*)0); |
437 | } |
438 | |
439 | /* how many hash object lengths are needed */ |
440 | c = (bytesNeeded + (hashLength - 1)) / hashLength; |
441 | |
442 | /* 64 if 0 < hashLength <= 32, 128 if 32 < hashLength <= 64 */ |
443 | bufferLength = NSSPBE_ROUNDUP(hashLength * 2, 64)((((hashLength * 2) + ((64)-1)) / (64)) * (64)); |
444 | |
445 | /* initialize our buffers */ |
446 | D.len = bufferLength; |
447 | /* B and D are the same length, use one alloc go get both */ |
448 | D.data = (unsigned char *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, D.len * 2); |
449 | B.len = D.len; |
450 | B.data = D.data + D.len; |
451 | |
452 | /* if all goes well, A will be returned, so don't use our temp arena */ |
453 | A = SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), NULL((void*)0), c * hashLength); |
454 | if (A == NULL((void*)0)) { |
455 | goto loser; |
456 | } |
457 | |
458 | SLen = NSSPBE_ROUNDUP(salt->len, bufferLength)((((salt->len) + ((bufferLength)-1)) / (bufferLength)) * ( bufferLength)); |
459 | PLen = NSSPBE_ROUNDUP(pwitem->len, bufferLength)((((pwitem->len) + ((bufferLength)-1)) / (bufferLength)) * (bufferLength)); |
460 | I.len = SLen + PLen; |
461 | I.data = (unsigned char *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, I.len); |
462 | if (I.data == NULL((void*)0)) { |
463 | goto loser; |
464 | } |
465 | |
466 | /* S & P are only used to initialize I */ |
467 | S = I.data; |
468 | P = S + SLen; |
469 | |
470 | PORT_Memsetmemset(D.data, (char)bitGenPurpose, D.len); |
471 | if (SLen) { |
472 | for (i = 0; i < SLen; i += salt->len) { |
473 | PORT_Memcpymemcpy(S + i, salt->data, NSSPBE_MIN(SLen - i, salt->len)((SLen - i) < (salt->len) ? (SLen - i) : (salt->len) )); |
474 | } |
475 | } |
476 | if (PLen) { |
477 | for (i = 0; i < PLen; i += pwitem->len) { |
478 | PORT_Memcpymemcpy(P + i, pwitem->data, NSSPBE_MIN(PLen - i, pwitem->len)((PLen - i) < (pwitem->len) ? (PLen - i) : (pwitem-> len))); |
479 | } |
480 | } |
481 | |
482 | iterBuf = (unsigned char *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, hashLength); |
483 | if (iterBuf == NULL((void*)0)) { |
484 | goto loser; |
485 | } |
486 | |
487 | hash = hashObject->create(); |
488 | if (!hash) { |
489 | goto loser; |
490 | } |
491 | /* calculate the PBE now */ |
492 | for (i = 0; i < c; i++) { |
493 | int Bidx; /* must be signed or the for loop won't terminate */ |
494 | unsigned int k, j; |
495 | unsigned char *Ai = A->data + i * hashLength; |
496 | |
497 | for (iter = 0; iter < pbe_param->iter; iter++) { |
498 | hashObject->begin(hash); |
499 | |
500 | if (iter) { |
501 | hashObject->update(hash, iterBuf, hashLen); |
502 | } else { |
503 | hashObject->update(hash, D.data, D.len); |
504 | hashObject->update(hash, I.data, I.len); |
505 | } |
506 | |
507 | hashObject->end(hash, iterBuf, &hashLen, hashObject->length); |
508 | if (hashLen != hashObject->length) { |
509 | break; |
510 | } |
511 | } |
512 | |
513 | PORT_Memcpymemcpy(Ai, iterBuf, hashLength); |
514 | for (Bidx = 0; Bidx < (int)B.len; Bidx += hashLength) { |
515 | PORT_Memcpymemcpy(B.data + Bidx, iterBuf, NSSPBE_MIN(B.len - Bidx, hashLength)((B.len - Bidx) < (hashLength) ? (B.len - Bidx) : (hashLength ))); |
516 | } |
517 | |
518 | k = I.len / B.len; |
519 | for (j = 0; j < k; j++) { |
520 | unsigned int q, carryBit; |
521 | unsigned char *Ij = I.data + j * B.len; |
522 | |
523 | /* (Ij = Ij+B+1) */ |
524 | for (Bidx = (B.len - 1), q = 1, carryBit = 0; Bidx >= 0; Bidx--, q = 0) { |
525 | q += (unsigned int)Ij[Bidx]; |
526 | q += (unsigned int)B.data[Bidx]; |
527 | q += carryBit; |
528 | |
529 | carryBit = (q > 0xff); |
530 | Ij[Bidx] = (unsigned char)(q & 0xff); |
531 | } |
532 | } |
533 | } |
534 | loser: |
535 | if (hash) { |
536 | hashObject->destroy(hash, PR_TRUE1); |
537 | } |
538 | if (arena) { |
539 | PORT_FreeArenaPORT_FreeArena_Util(arena, PR_TRUE1); |
540 | } |
541 | |
542 | if (A) { |
543 | /* if i != c, then we didn't complete the loop above and must of failed |
544 | * somwhere along the way */ |
545 | if (i != c) { |
546 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(A, PR_TRUE1); |
547 | A = NULL((void*)0); |
548 | } else { |
549 | A->len = bytesNeeded; |
550 | } |
551 | } |
552 | |
553 | return A; |
554 | } |
555 | |
556 | struct KDFCacheItemStr { |
557 | SECItem *hash; |
558 | SECItem *salt; |
559 | SECItem *pwItem; |
560 | HASH_HashType hashType; |
561 | int iterations; |
562 | int keyLen; |
563 | }; |
564 | typedef struct KDFCacheItemStr KDFCacheItem; |
565 | |
566 | /* Bug 1606992 - Cache the hash result for the common case that we're |
567 | * asked to repeatedly compute the key for the same password item, |
568 | * hash, iterations and salt. */ |
569 | #define KDF2_CACHE_COUNT150 150 |
570 | static struct { |
571 | PZLockPRLock *lock; |
572 | struct { |
573 | KDFCacheItem common; |
574 | int ivLen; |
575 | PRBool faulty3DES; |
576 | } cacheKDF1; |
577 | struct { |
578 | KDFCacheItem common[KDF2_CACHE_COUNT150]; |
579 | int next; |
580 | } cacheKDF2; |
581 | } PBECache; |
582 | |
583 | void |
584 | sftk_PBELockInit(void) |
585 | { |
586 | if (!PBECache.lock) { |
587 | PBECache.lock = PZ_NewLock(nssIPBECacheLock)PR_NewLock(); |
588 | } |
589 | } |
590 | |
591 | static void |
592 | sftk_clearPBECommonCacheItemsLocked(KDFCacheItem *item) |
593 | { |
594 | if (item->hash) { |
595 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(item->hash, PR_TRUE1); |
596 | item->hash = NULL((void*)0); |
597 | } |
598 | if (item->salt) { |
599 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(item->salt, PR_TRUE1); |
600 | item->salt = NULL((void*)0); |
601 | } |
602 | if (item->pwItem) { |
603 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(item->pwItem, PR_TRUE1); |
604 | item->pwItem = NULL((void*)0); |
605 | } |
606 | } |
607 | |
608 | static void |
609 | sftk_setPBECommonCacheItemsKDFLocked(KDFCacheItem *cacheItem, |
610 | const SECItem *hash, |
611 | const NSSPKCS5PBEParameter *pbe_param, |
612 | const SECItem *pwItem) |
613 | { |
614 | cacheItem->hash = SECITEM_DupItemSECITEM_DupItem_Util(hash); |
615 | cacheItem->hashType = pbe_param->hashType; |
616 | cacheItem->iterations = pbe_param->iter; |
617 | cacheItem->keyLen = pbe_param->keyLen; |
618 | cacheItem->salt = SECITEM_DupItemSECITEM_DupItem_Util(&pbe_param->salt); |
619 | cacheItem->pwItem = SECITEM_DupItemSECITEM_DupItem_Util(pwItem); |
620 | } |
621 | |
622 | static void |
623 | sftk_setPBECacheKDF2(const SECItem *hash, |
624 | const NSSPKCS5PBEParameter *pbe_param, |
625 | const SECItem *pwItem) |
626 | { |
627 | PZ_Lock(PBECache.lock)PR_Lock((PBECache.lock)); |
628 | KDFCacheItem *next = &PBECache.cacheKDF2.common[PBECache.cacheKDF2.next]; |
629 | |
630 | sftk_clearPBECommonCacheItemsLocked(next); |
631 | |
632 | sftk_setPBECommonCacheItemsKDFLocked(next, hash, pbe_param, pwItem); |
633 | PBECache.cacheKDF2.next++; |
634 | if (PBECache.cacheKDF2.next >= KDF2_CACHE_COUNT150) { |
635 | PBECache.cacheKDF2.next = 0; |
636 | } |
637 | |
638 | PZ_Unlock(PBECache.lock)PR_Unlock((PBECache.lock)); |
639 | } |
640 | |
641 | static void |
642 | sftk_setPBECacheKDF1(const SECItem *hash, |
643 | const NSSPKCS5PBEParameter *pbe_param, |
644 | const SECItem *pwItem, |
645 | PRBool faulty3DES) |
646 | { |
647 | PZ_Lock(PBECache.lock)PR_Lock((PBECache.lock)); |
648 | |
649 | sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF1.common); |
650 | |
651 | sftk_setPBECommonCacheItemsKDFLocked(&PBECache.cacheKDF1.common, |
652 | hash, pbe_param, pwItem); |
653 | PBECache.cacheKDF1.faulty3DES = faulty3DES; |
654 | PBECache.cacheKDF1.ivLen = pbe_param->ivLen; |
655 | |
656 | PZ_Unlock(PBECache.lock)PR_Unlock((PBECache.lock)); |
657 | } |
658 | |
659 | static PRBool |
660 | sftk_comparePBECommonCacheItemLocked(const KDFCacheItem *cacheItem, |
661 | const NSSPKCS5PBEParameter *pbe_param, |
662 | const SECItem *pwItem) |
663 | { |
664 | return (cacheItem->hash && |
665 | cacheItem->salt && |
666 | cacheItem->pwItem && |
667 | pbe_param->hashType == cacheItem->hashType && |
668 | pbe_param->iter == cacheItem->iterations && |
669 | pbe_param->keyLen == cacheItem->keyLen && |
670 | SECITEM_ItemsAreEqualSECITEM_ItemsAreEqual_Util(&pbe_param->salt, cacheItem->salt) && |
671 | SECITEM_ItemsAreEqualSECITEM_ItemsAreEqual_Util(pwItem, cacheItem->pwItem)); |
672 | } |
673 | |
674 | static SECItem * |
675 | sftk_getPBECacheKDF2(const NSSPKCS5PBEParameter *pbe_param, |
676 | const SECItem *pwItem) |
677 | { |
678 | SECItem *result = NULL((void*)0); |
679 | int i; |
680 | |
681 | PZ_Lock(PBECache.lock)PR_Lock((PBECache.lock)); |
682 | for (i = 0; i < KDF2_CACHE_COUNT150; i++) { |
683 | const KDFCacheItem *cacheItem = &PBECache.cacheKDF2.common[i]; |
684 | if (sftk_comparePBECommonCacheItemLocked(cacheItem, |
685 | pbe_param, pwItem)) { |
686 | result = SECITEM_DupItemSECITEM_DupItem_Util(cacheItem->hash); |
687 | break; |
688 | } |
689 | } |
690 | PZ_Unlock(PBECache.lock)PR_Unlock((PBECache.lock)); |
691 | |
692 | return result; |
693 | } |
694 | |
695 | static SECItem * |
696 | sftk_getPBECacheKDF1(const NSSPKCS5PBEParameter *pbe_param, |
697 | const SECItem *pwItem, |
698 | PRBool faulty3DES) |
699 | { |
700 | SECItem *result = NULL((void*)0); |
701 | const KDFCacheItem *cacheItem = &PBECache.cacheKDF1.common; |
702 | |
703 | PZ_Lock(PBECache.lock)PR_Lock((PBECache.lock)); |
704 | if (sftk_comparePBECommonCacheItemLocked(cacheItem, pbe_param, pwItem) && |
705 | PBECache.cacheKDF1.faulty3DES == faulty3DES && |
706 | PBECache.cacheKDF1.ivLen == pbe_param->ivLen) { |
707 | result = SECITEM_DupItemSECITEM_DupItem_Util(cacheItem->hash); |
708 | } |
709 | PZ_Unlock(PBECache.lock)PR_Unlock((PBECache.lock)); |
710 | |
711 | return result; |
712 | } |
713 | |
714 | void |
715 | sftk_PBELockShutdown(void) |
716 | { |
717 | int i; |
718 | if (PBECache.lock) { |
719 | PZ_DestroyLock(PBECache.lock)PR_DestroyLock((PBECache.lock)); |
720 | PBECache.lock = 0; |
721 | } |
722 | sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF1.common); |
723 | for (i = 0; i < KDF2_CACHE_COUNT150; i++) { |
724 | sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF2.common[i]); |
725 | } |
726 | PBECache.cacheKDF2.next = 0; |
727 | } |
728 | |
729 | /* |
730 | * generate key as per PKCS 5 |
731 | */ |
732 | SECItem * |
733 | nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, |
734 | SECItem *iv, PRBool faulty3DES) |
735 | { |
736 | SECItem *hash = NULL((void*)0), *key = NULL((void*)0); |
737 | const SECHashObject *hashObj; |
738 | PRBool getIV = PR_FALSE0; |
739 | |
740 | if ((pbe_param == NULL((void*)0)) || (pwitem == NULL((void*)0))) { |
741 | return NULL((void*)0); |
742 | } |
743 | |
744 | key = SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), NULL((void*)0), pbe_param->keyLen); |
745 | if (key == NULL((void*)0)) { |
746 | return NULL((void*)0); |
747 | } |
748 | |
749 | if (iv && (pbe_param->ivLen) && (iv->data == NULL((void*)0))) { |
750 | getIV = PR_TRUE1; |
751 | iv->data = (unsigned char *)PORT_AllocPORT_Alloc_Util(pbe_param->ivLen); |
752 | if (iv->data == NULL((void*)0)) { |
753 | goto loser; |
754 | } |
755 | iv->len = pbe_param->ivLen; |
756 | } |
757 | |
758 | hashObj = HASH_GetRawHashObject(pbe_param->hashType); |
759 | switch (pbe_param->pbeType) { |
760 | case NSSPKCS5_PBKDF1: |
761 | hash = sftk_getPBECacheKDF1(pbe_param, pwitem, faulty3DES); |
762 | if (!hash) { |
763 | hash = nsspkcs5_PBKDF1Extended(hashObj, pbe_param, pwitem, faulty3DES); |
764 | sftk_setPBECacheKDF1(hash, pbe_param, pwitem, faulty3DES); |
765 | } |
766 | if (hash == NULL((void*)0)) { |
767 | goto loser; |
768 | } |
769 | PORT_Assert(hash->len >= key->len + (getIV ? iv->len : 0))((hash->len >= key->len + (getIV ? iv->len : 0))? ((void)0):PR_Assert("hash->len >= key->len + (getIV ? iv->len : 0)" ,"lowpbe.c",769)); |
770 | if (getIV) { |
771 | PORT_Memcpymemcpy(iv->data, hash->data + (hash->len - iv->len), iv->len); |
772 | } |
773 | |
774 | break; |
775 | case NSSPKCS5_PBKDF2: |
776 | hash = sftk_getPBECacheKDF2(pbe_param, pwitem); |
777 | if (!hash) { |
778 | hash = nsspkcs5_PBKDF2(hashObj, pbe_param, pwitem); |
779 | sftk_setPBECacheKDF2(hash, pbe_param, pwitem); |
780 | } |
781 | if (getIV) { |
782 | PORT_Memcpymemcpy(iv->data, pbe_param->ivData, iv->len); |
783 | } |
784 | break; |
785 | case NSSPKCS5_PKCS12_V2: |
786 | if (getIV) { |
787 | hash = nsspkcs5_PKCS12PBE(hashObj, pbe_param, pwitem, |
788 | pbeBitGenCipherIV, iv->len); |
789 | if (hash == NULL((void*)0)) { |
790 | goto loser; |
791 | } |
792 | PORT_Memcpymemcpy(iv->data, hash->data, iv->len); |
793 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(hash, PR_TRUE1); |
794 | hash = NULL((void*)0); |
795 | } |
796 | hash = nsspkcs5_PKCS12PBE(hashObj, pbe_param, pwitem, |
797 | pbe_param->keyID, key->len); |
798 | default: |
799 | break; |
800 | } |
801 | |
802 | if (hash == NULL((void*)0)) { |
803 | goto loser; |
804 | } |
805 | |
806 | PORT_Memcpymemcpy(key->data, hash->data, key->len); |
807 | |
808 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(hash, PR_TRUE1); |
809 | return key; |
810 | |
811 | loser: |
812 | if (getIV && iv->data) { |
813 | PORT_ZFreePORT_ZFree_Util(iv->data, iv->len); |
814 | iv->data = NULL((void*)0); |
815 | } |
816 | |
817 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(key, PR_TRUE1); |
818 | return NULL((void*)0); |
819 | } |
820 | |
821 | #define MAX_IV_LENGTH64 64 |
822 | /* get a random IV into the parameters */ |
823 | static SECStatus |
824 | nsspkcs5_SetIVParam(NSSPKCS5PBEParameter *pbe_param, int ivLen) |
825 | { |
826 | SECStatus rv; |
827 | SECItem derIV; |
828 | SECItem iv; |
829 | SECItem *dummy = NULL((void*)0); |
830 | unsigned char ivData[MAX_IV_LENGTH64]; |
831 | |
832 | PORT_Assert(ivLen <= MAX_IV_LENGTH)((ivLen <= 64)?((void)0):PR_Assert("ivLen <= MAX_IV_LENGTH" ,"lowpbe.c",832)); |
833 | |
834 | /* Because of a bug in the decode section, the IV's not are expected |
835 | * to be der encoded, but still need to parse as if they were der data. |
836 | * because we want to be compatible with existing versions of nss that |
837 | * have that bug, create an IV that looks like der data. That still |
838 | * leaves 14 bytes of entropy in the IV */ |
839 | rv = RNG_GenerateGlobalRandomBytes(ivData, ivLen - 2); |
840 | if (rv != SECSuccess) { |
841 | return SECFailure; |
842 | } |
843 | derIV.data = NULL((void*)0); |
844 | derIV.len = 0; |
845 | iv.data = ivData; |
846 | iv.len = ivLen - 2; |
847 | dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(pbe_param->poolp, &derIV, &iv, |
848 | SEC_ASN1_GET(SEC_OctetStringTemplate)SEC_OctetStringTemplate_Util); |
849 | if (dummy == NULL((void*)0)) { |
850 | return SECFailure; |
851 | } |
852 | pbe_param->ivData = derIV.data; |
853 | pbe_param->ivLen = derIV.len; |
854 | PORT_Assert(pbe_param->ivLen == ivLen)((pbe_param->ivLen == ivLen)?((void)0):PR_Assert("pbe_param->ivLen == ivLen" ,"lowpbe.c",854)); |
855 | return SECSuccess; |
856 | } |
857 | |
858 | static SECStatus |
859 | nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType, |
860 | NSSPKCS5PBEParameter *pbe_param) |
861 | { |
862 | PRBool skipType = PR_FALSE0; |
863 | SECStatus rv; |
864 | |
865 | pbe_param->keyLen = 5; |
866 | pbe_param->ivLen = 8; |
867 | pbe_param->hashType = hashType; |
868 | pbe_param->pbeType = NSSPKCS5_PBKDF1; |
869 | pbe_param->encAlg = SEC_OID_RC2_CBC; |
870 | pbe_param->is2KeyDES = PR_FALSE0; |
871 | switch (algorithm) { |
872 | /* DES3 Algorithms */ |
873 | case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: |
874 | pbe_param->is2KeyDES = PR_TRUE1; |
875 | pbe_param->pbeType = NSSPKCS5_PKCS12_V2; |
876 | pbe_param->keyLen = 16; |
877 | pbe_param->encAlg = SEC_OID_DES_EDE3_CBC; |
878 | break; |
879 | case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: |
880 | pbe_param->pbeType = NSSPKCS5_PKCS12_V2; |
881 | pbe_param->keyLen = 24; |
882 | pbe_param->encAlg = SEC_OID_DES_EDE3_CBC; |
883 | break; |
884 | case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: |
885 | pbe_param->keyLen = 24; |
886 | pbe_param->encAlg = SEC_OID_DES_EDE3_CBC; |
887 | break; |
888 | |
889 | /* DES Algorithms */ |
890 | case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: |
891 | pbe_param->hashType = HASH_AlgMD2; |
892 | goto finish_des; |
893 | case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: |
894 | pbe_param->hashType = HASH_AlgMD5; |
895 | /* fall through */ |
896 | case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: |
897 | finish_des: |
898 | pbe_param->keyLen = 8; |
899 | pbe_param->encAlg = SEC_OID_DES_CBC; |
900 | break; |
901 | |
902 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
903 | /* RC2 Algorithms */ |
904 | case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: |
905 | pbe_param->keyLen = 16; |
906 | /* fall through */ |
907 | case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: |
908 | pbe_param->pbeType = NSSPKCS5_PKCS12_V2; |
909 | break; |
910 | case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: |
911 | pbe_param->keyLen = 16; |
912 | /* fall through */ |
913 | case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: |
914 | break; |
915 | #endif |
916 | |
917 | /* RC4 algorithms */ |
918 | case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: |
919 | skipType = PR_TRUE1; |
920 | /* fall through */ |
921 | case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: |
922 | pbe_param->keyLen = 16; |
923 | /* fall through */ |
924 | case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: |
925 | if (!skipType) { |
926 | pbe_param->pbeType = NSSPKCS5_PKCS12_V2; |
927 | } |
928 | /* fall through */ |
929 | case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: |
930 | pbe_param->ivLen = 0; |
931 | pbe_param->encAlg = SEC_OID_RC4; |
932 | break; |
933 | |
934 | case SEC_OID_PKCS5_PBKDF2: |
935 | case SEC_OID_PKCS5_PBES2: |
936 | case SEC_OID_PKCS5_PBMAC1: |
937 | /* everything else will be filled in by the template */ |
938 | pbe_param->ivLen = 0; |
939 | pbe_param->pbeType = NSSPKCS5_PBKDF2; |
940 | pbe_param->encAlg = SEC_OID_PKCS5_PBKDF2; |
941 | pbe_param->keyLen = 0; /* needs to be set by caller after return */ |
942 | break; |
943 | /* AES uses PBKDF2 */ |
944 | case SEC_OID_AES_128_CBC: |
945 | rv = nsspkcs5_SetIVParam(pbe_param, 16); |
946 | if (rv != SECSuccess) { |
947 | return rv; |
948 | } |
949 | pbe_param->ivLen = 16; |
950 | pbe_param->pbeType = NSSPKCS5_PBKDF2; |
951 | pbe_param->encAlg = algorithm; |
952 | pbe_param->keyLen = 128 / 8; |
953 | break; |
954 | case SEC_OID_AES_192_CBC: |
955 | rv = nsspkcs5_SetIVParam(pbe_param, 16); |
956 | if (rv != SECSuccess) { |
957 | return rv; |
958 | } |
959 | pbe_param->pbeType = NSSPKCS5_PBKDF2; |
960 | pbe_param->encAlg = algorithm; |
961 | pbe_param->keyLen = 192 / 8; |
962 | break; |
963 | case SEC_OID_AES_256_CBC: |
964 | rv = nsspkcs5_SetIVParam(pbe_param, 16); |
965 | if (rv != SECSuccess) { |
966 | return rv; |
967 | } |
968 | pbe_param->pbeType = NSSPKCS5_PBKDF2; |
969 | pbe_param->encAlg = algorithm; |
970 | pbe_param->keyLen = 256 / 8; |
971 | break; |
972 | case SEC_OID_AES_128_KEY_WRAP: |
973 | pbe_param->ivLen = 0; |
974 | pbe_param->pbeType = NSSPKCS5_PBKDF2; |
975 | pbe_param->encAlg = algorithm; |
976 | pbe_param->keyLen = 128 / 8; |
977 | break; |
978 | case SEC_OID_AES_192_KEY_WRAP: |
979 | pbe_param->ivLen = 0; |
980 | pbe_param->pbeType = NSSPKCS5_PBKDF2; |
981 | pbe_param->encAlg = algorithm; |
982 | pbe_param->keyLen = 192 / 8; |
983 | break; |
984 | case SEC_OID_AES_256_KEY_WRAP: |
985 | pbe_param->ivLen = 0; |
986 | pbe_param->pbeType = NSSPKCS5_PBKDF2; |
987 | pbe_param->encAlg = algorithm; |
988 | pbe_param->keyLen = 256 / 8; |
989 | break; |
990 | |
991 | default: |
992 | return SECFailure; |
993 | } |
994 | if (pbe_param->pbeType == NSSPKCS5_PBKDF2) { |
995 | SECOidTag prfAlg = HASH_HMACOidFromHash(pbe_param->hashType); |
996 | if (prfAlg == SEC_OID_UNKNOWN) { |
997 | return SECFailure; |
998 | } |
999 | rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(pbe_param->poolp, &pbe_param->prfAlg, |
1000 | prfAlg, NULL((void*)0)); |
1001 | if (rv != SECSuccess) { |
1002 | return rv; |
1003 | } |
1004 | } |
1005 | return SECSuccess; |
1006 | } |
1007 | |
1008 | /* decode the algid and generate a PKCS 5 parameter from it |
1009 | */ |
1010 | NSSPKCS5PBEParameter * |
1011 | nsspkcs5_NewParam(SECOidTag alg, HASH_HashType hashType, SECItem *salt, |
1012 | int iterationCount) |
1013 | { |
1014 | PLArenaPool *arena = NULL((void*)0); |
1015 | NSSPKCS5PBEParameter *pbe_param = NULL((void*)0); |
1016 | SECStatus rv = SECFailure; |
1017 | |
1018 | arena = PORT_NewArenaPORT_NewArena_Util(SEC_ASN1_DEFAULT_ARENA_SIZE(2048)); |
1019 | if (arena == NULL((void*)0)) |
1020 | return NULL((void*)0); |
1021 | |
1022 | /* allocate memory for the parameter */ |
1023 | pbe_param = (NSSPKCS5PBEParameter *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, |
1024 | sizeof(NSSPKCS5PBEParameter)); |
1025 | |
1026 | if (pbe_param == NULL((void*)0)) { |
1027 | goto loser; |
1028 | } |
1029 | |
1030 | pbe_param->poolp = arena; |
1031 | |
1032 | rv = nsspkcs5_FillInParam(alg, hashType, pbe_param); |
1033 | if (rv != SECSuccess) { |
1034 | goto loser; |
1035 | } |
1036 | |
1037 | pbe_param->iter = iterationCount; |
1038 | if (salt) { |
1039 | rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pbe_param->salt, salt); |
1040 | } |
1041 | |
1042 | /* default key gen */ |
1043 | pbe_param->keyID = pbeBitGenCipherKey; |
1044 | |
1045 | loser: |
1046 | if (rv != SECSuccess) { |
1047 | PORT_FreeArenaPORT_FreeArena_Util(arena, PR_TRUE1); |
1048 | pbe_param = NULL((void*)0); |
1049 | } |
1050 | |
1051 | return pbe_param; |
1052 | } |
1053 | |
1054 | /* |
1055 | * find the hash type needed to implement a specific HMAC. |
1056 | * OID definitions are from pkcs 5 v2.0 and 2.1 |
1057 | */ |
1058 | HASH_HashType |
1059 | HASH_FromHMACOid(SECOidTag hmac) |
1060 | { |
1061 | switch (hmac) { |
1062 | case SEC_OID_HMAC_SHA1: |
1063 | return HASH_AlgSHA1; |
1064 | case SEC_OID_HMAC_SHA256: |
1065 | return HASH_AlgSHA256; |
1066 | case SEC_OID_HMAC_SHA384: |
1067 | return HASH_AlgSHA384; |
1068 | case SEC_OID_HMAC_SHA512: |
1069 | return HASH_AlgSHA512; |
1070 | case SEC_OID_HMAC_SHA224: |
1071 | default: |
1072 | break; |
1073 | } |
1074 | return HASH_AlgNULL; |
1075 | } |
1076 | |
1077 | SECOidTag |
1078 | HASH_HMACOidFromHash(HASH_HashType hashType) |
1079 | { |
1080 | switch (hashType) { |
1081 | case HASH_AlgSHA1: |
1082 | return SEC_OID_HMAC_SHA1; |
1083 | case HASH_AlgSHA256: |
1084 | return SEC_OID_HMAC_SHA256; |
1085 | case HASH_AlgSHA384: |
1086 | return SEC_OID_HMAC_SHA384; |
1087 | case HASH_AlgSHA512: |
1088 | return SEC_OID_HMAC_SHA512; |
1089 | case HASH_AlgSHA224: |
1090 | return SEC_OID_HMAC_SHA224; |
1091 | case HASH_AlgMD2: |
1092 | case HASH_AlgMD5: |
1093 | case HASH_AlgTOTAL: |
1094 | default: |
1095 | break; |
1096 | } |
1097 | return SEC_OID_UNKNOWN; |
1098 | } |
1099 | |
1100 | /* decode the algid and generate a PKCS 5 parameter from it |
1101 | */ |
1102 | NSSPKCS5PBEParameter * |
1103 | nsspkcs5_AlgidToParam(SECAlgorithmID *algid) |
1104 | { |
1105 | NSSPKCS5PBEParameter *pbe_param = NULL((void*)0); |
1106 | nsspkcs5V2PBEParameter pbev2_param; |
1107 | SECOidTag algorithm; |
1108 | SECStatus rv = SECFailure; |
1109 | |
1110 | if (algid == NULL((void*)0)) { |
1111 | return NULL((void*)0); |
1112 | } |
1113 | |
1114 | algorithm = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(algid); |
1115 | if (algorithm == SEC_OID_UNKNOWN) { |
1116 | goto loser; |
1117 | } |
1118 | |
1119 | pbe_param = nsspkcs5_NewParam(algorithm, HASH_AlgSHA1, NULL((void*)0), 1); |
1120 | if (pbe_param == NULL((void*)0)) { |
1121 | goto loser; |
1122 | } |
1123 | |
1124 | /* decode parameter */ |
1125 | rv = SECFailure; |
Value stored to 'rv' is never read | |
1126 | switch (pbe_param->pbeType) { |
1127 | case NSSPKCS5_PBKDF1: |
1128 | rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(pbe_param->poolp, pbe_param, |
1129 | NSSPKCS5PBEParameterTemplate, &algid->parameters); |
1130 | break; |
1131 | case NSSPKCS5_PKCS12_V2: |
1132 | rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(pbe_param->poolp, pbe_param, |
1133 | NSSPKCS5PKCS12V2PBEParameterTemplate, &algid->parameters); |
1134 | break; |
1135 | case NSSPKCS5_PBKDF2: |
1136 | PORT_Memsetmemset(&pbev2_param, 0, sizeof(pbev2_param)); |
1137 | /* just the PBE */ |
1138 | if (algorithm == SEC_OID_PKCS5_PBKDF2) { |
1139 | rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(pbe_param->poolp, pbe_param, |
1140 | NSSPKCS5V2PBEParameterTemplate, &algid->parameters); |
1141 | } else { |
1142 | /* PBE data an others */ |
1143 | rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(pbe_param->poolp, &pbev2_param, |
1144 | NSSPKCS5V2PBES2ParameterTemplate, &algid->parameters); |
1145 | if (rv != SECSuccess) { |
1146 | break; |
1147 | } |
1148 | pbe_param->encAlg = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&pbev2_param.algParams); |
1149 | rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(pbe_param->poolp, pbe_param, |
1150 | NSSPKCS5V2PBEParameterTemplate, |
1151 | &pbev2_param.keyParams.parameters); |
1152 | if (rv != SECSuccess) { |
1153 | break; |
1154 | } |
1155 | pbe_param->keyLen = DER_GetIntegerDER_GetInteger_Util(&pbe_param->keyLength); |
1156 | } |
1157 | /* we we are encrypting, save any iv's */ |
1158 | if (algorithm == SEC_OID_PKCS5_PBES2) { |
1159 | pbe_param->ivLen = pbev2_param.algParams.parameters.len; |
1160 | pbe_param->ivData = pbev2_param.algParams.parameters.data; |
1161 | } |
1162 | pbe_param->hashType = |
1163 | HASH_FromHMACOid(SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&pbe_param->prfAlg)); |
1164 | if (pbe_param->hashType == HASH_AlgNULL) { |
1165 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM); |
1166 | rv = SECFailure; |
1167 | } |
1168 | break; |
1169 | } |
1170 | |
1171 | loser: |
1172 | PORT_Memsetmemset(&pbev2_param, 0, sizeof(pbev2_param)); |
1173 | if (rv == SECSuccess) { |
1174 | pbe_param->iter = DER_GetIntegerDER_GetInteger_Util(&pbe_param->iteration); |
1175 | } else { |
1176 | nsspkcs5_DestroyPBEParameter(pbe_param); |
1177 | pbe_param = NULL((void*)0); |
1178 | } |
1179 | |
1180 | return pbe_param; |
1181 | } |
1182 | |
1183 | /* destroy a pbe parameter. it assumes that the parameter was |
1184 | * generated using the appropriate create function and therefor |
1185 | * contains an arena pool. |
1186 | */ |
1187 | void |
1188 | nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param) |
1189 | { |
1190 | if (pbe_param != NULL((void*)0)) { |
1191 | PORT_FreeArenaPORT_FreeArena_Util(pbe_param->poolp, PR_TRUE1); |
1192 | } |
1193 | } |
1194 | |
1195 | /* crypto routines */ |
1196 | /* perform DES encryption and decryption. these routines are called |
1197 | * by nsspkcs5_CipherData. In the case of an error, NULL is returned. |
1198 | */ |
1199 | static SECItem * |
1200 | sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des, |
1201 | PRBool encrypt) |
1202 | { |
1203 | SECItem *dest; |
1204 | SECItem *dup_src; |
1205 | CK_RV crv = CKR_DEVICE_ERROR0x00000030UL; |
1206 | int error; |
1207 | SECStatus rv = SECFailure; |
1208 | DESContext *ctxt; |
1209 | unsigned int pad; |
1210 | |
1211 | if ((src == NULL((void*)0)) || (key == NULL((void*)0)) || (iv == NULL((void*)0))) { |
1212 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
1213 | return NULL((void*)0); |
1214 | } |
1215 | |
1216 | dup_src = SECITEM_DupItemSECITEM_DupItem_Util(src); |
1217 | if (dup_src == NULL((void*)0)) { |
1218 | return NULL((void*)0); |
1219 | } |
1220 | |
1221 | if (encrypt != PR_FALSE0) { |
1222 | void *dummy; |
1223 | |
1224 | dummy = CBC_PadBuffer(NULL((void*)0), dup_src->data, |
1225 | dup_src->len, &dup_src->len, DES_BLOCK_SIZE8); |
1226 | if (dummy == NULL((void*)0)) { |
1227 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup_src, PR_TRUE1); |
1228 | return NULL((void*)0); |
1229 | } |
1230 | dup_src->data = (unsigned char *)dummy; |
1231 | } |
1232 | |
1233 | dest = SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), NULL((void*)0), dup_src->len + MAX_CRYPTO_EXPANSION64); |
1234 | if (dest == NULL((void*)0)) { |
1235 | goto loser; |
1236 | } |
1237 | ctxt = DES_CreateContext(key->data, iv->data, |
1238 | (triple_des ? NSS_DES_EDE3_CBC3 : NSS_DES_CBC1), |
1239 | encrypt); |
1240 | if (ctxt == NULL((void*)0)) { |
1241 | goto loser; |
1242 | } |
1243 | rv = (encrypt ? DES_Encrypt : DES_Decrypt)( |
1244 | ctxt, dest->data, &dest->len, |
1245 | dest->len, dup_src->data, dup_src->len); |
1246 | |
1247 | crv = (rv == SECSuccess) ? CKR_OK0x00000000UL : CKR_DEVICE_ERROR0x00000030UL; |
1248 | error = PORT_GetErrorPORT_GetError_Util(); |
1249 | |
1250 | /* remove padding */ |
1251 | if ((encrypt == PR_FALSE0) && (rv == SECSuccess)) { |
1252 | crv = sftk_CheckCBCPadding(dest->data, dest->len, DES_BLOCK_SIZE8, &pad); |
1253 | dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len)(((sftk_CKRVToMask(crv)) & (dest->len - pad)) | (~(sftk_CKRVToMask (crv)) & (dest->len))); |
1254 | PORT_SetErrorPORT_SetError_Util(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD)(((sftk_CKRVToMask(crv)) & (error)) | (~(sftk_CKRVToMask( crv)) & (SEC_ERROR_BAD_PASSWORD)))); |
1255 | } |
1256 | DES_DestroyContext(ctxt, PR_TRUE1); |
1257 | |
1258 | loser: |
1259 | if (crv != CKR_OK0x00000000UL) { |
1260 | if (dest != NULL((void*)0)) { |
1261 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dest, PR_TRUE1); |
1262 | } |
1263 | dest = NULL((void*)0); |
1264 | } |
1265 | |
1266 | if (dup_src != NULL((void*)0)) { |
1267 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup_src, PR_TRUE1); |
1268 | } |
1269 | |
1270 | return dest; |
1271 | } |
1272 | |
1273 | /* perform aes encryption/decryption if an error occurs, NULL is returned |
1274 | */ |
1275 | static SECItem * |
1276 | sec_pkcs5_aes(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des, |
1277 | PRBool encrypt) |
1278 | { |
1279 | SECItem *dest; |
1280 | SECItem *dup_src; |
1281 | CK_RV crv = CKR_DEVICE_ERROR0x00000030UL; |
1282 | int error; |
1283 | SECStatus rv = SECFailure; |
1284 | AESContext *ctxt; |
1285 | unsigned int pad; |
1286 | |
1287 | if ((src == NULL((void*)0)) || (key == NULL((void*)0)) || (iv == NULL((void*)0))) { |
1288 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
1289 | return NULL((void*)0); |
1290 | } |
1291 | |
1292 | dup_src = SECITEM_DupItemSECITEM_DupItem_Util(src); |
1293 | if (dup_src == NULL((void*)0)) { |
1294 | return NULL((void*)0); |
1295 | } |
1296 | |
1297 | if (encrypt != PR_FALSE0) { |
1298 | void *dummy; |
1299 | |
1300 | dummy = CBC_PadBuffer(NULL((void*)0), dup_src->data, |
1301 | dup_src->len, &dup_src->len, AES_BLOCK_SIZE16); |
1302 | if (dummy == NULL((void*)0)) { |
1303 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup_src, PR_TRUE1); |
1304 | return NULL((void*)0); |
1305 | } |
1306 | dup_src->data = (unsigned char *)dummy; |
1307 | } |
1308 | |
1309 | dest = SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), NULL((void*)0), dup_src->len + MAX_CRYPTO_EXPANSION64); |
1310 | if (dest == NULL((void*)0)) { |
1311 | goto loser; |
1312 | } |
1313 | ctxt = AES_CreateContext(key->data, iv->data, NSS_AES_CBC1, |
1314 | encrypt, key->len, AES_BLOCK_SIZE16); |
1315 | if (ctxt == NULL((void*)0)) { |
1316 | goto loser; |
1317 | } |
1318 | rv = (encrypt ? AES_Encrypt : AES_Decrypt)( |
1319 | ctxt, dest->data, &dest->len, |
1320 | dest->len, dup_src->data, dup_src->len); |
1321 | |
1322 | crv = (rv == SECSuccess) ? CKR_OK0x00000000UL : CKR_DEVICE_ERROR0x00000030UL; |
1323 | error = PORT_GetErrorPORT_GetError_Util(); |
1324 | |
1325 | /* remove padding */ |
1326 | if ((encrypt == PR_FALSE0) && (rv == SECSuccess)) { |
1327 | crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE16, &pad); |
1328 | dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len)(((sftk_CKRVToMask(crv)) & (dest->len - pad)) | (~(sftk_CKRVToMask (crv)) & (dest->len))); |
1329 | PORT_SetErrorPORT_SetError_Util(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD)(((sftk_CKRVToMask(crv)) & (error)) | (~(sftk_CKRVToMask( crv)) & (SEC_ERROR_BAD_PASSWORD)))); |
1330 | } |
1331 | AES_DestroyContext(ctxt, PR_TRUE1); |
1332 | |
1333 | loser: |
1334 | if (crv != CKR_OK0x00000000UL) { |
1335 | if (dest != NULL((void*)0)) { |
1336 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dest, PR_TRUE1); |
1337 | } |
1338 | dest = NULL((void*)0); |
1339 | } |
1340 | |
1341 | if (dup_src != NULL((void*)0)) { |
1342 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup_src, PR_TRUE1); |
1343 | } |
1344 | |
1345 | return dest; |
1346 | } |
1347 | |
1348 | /* perform aes encryption/decryption if an error occurs, NULL is returned |
1349 | */ |
1350 | static SECItem * |
1351 | sec_pkcs5_aes_key_wrap(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des, |
1352 | PRBool encrypt) |
1353 | { |
1354 | SECItem *dest; |
1355 | SECItem *dup_src; |
1356 | CK_RV crv = CKR_DEVICE_ERROR0x00000030UL; |
1357 | int error; |
1358 | SECStatus rv = SECFailure; |
1359 | AESKeyWrapContext *ctxt; |
1360 | unsigned int pad; |
1361 | |
1362 | if ((src == NULL((void*)0)) || (key == NULL((void*)0)) || (iv == NULL((void*)0))) { |
1363 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
1364 | return NULL((void*)0); |
1365 | } |
1366 | |
1367 | dup_src = SECITEM_DupItemSECITEM_DupItem_Util(src); |
1368 | if (dup_src == NULL((void*)0)) { |
1369 | return NULL((void*)0); |
1370 | } |
1371 | |
1372 | if (encrypt != PR_FALSE0) { |
1373 | void *dummy; |
1374 | |
1375 | dummy = CBC_PadBuffer(NULL((void*)0), dup_src->data, |
1376 | dup_src->len, &dup_src->len, AES_BLOCK_SIZE16); |
1377 | if (dummy == NULL((void*)0)) { |
1378 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup_src, PR_TRUE1); |
1379 | return NULL((void*)0); |
1380 | } |
1381 | dup_src->data = (unsigned char *)dummy; |
1382 | } |
1383 | |
1384 | dest = SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), NULL((void*)0), dup_src->len + MAX_CRYPTO_EXPANSION64); |
1385 | if (dest == NULL((void*)0)) { |
1386 | goto loser; |
1387 | } |
1388 | ctxt = AESKeyWrap_CreateContext(key->data, iv->data, encrypt, |
1389 | key->len); |
1390 | |
1391 | if (ctxt == NULL((void*)0)) { |
1392 | goto loser; |
1393 | } |
1394 | rv = (encrypt ? AESKeyWrap_Encrypt : AESKeyWrap_Decrypt)( |
1395 | ctxt, dest->data, &dest->len, |
1396 | dest->len, dup_src->data, dup_src->len); |
1397 | |
1398 | crv = (rv == SECSuccess) ? CKR_OK0x00000000UL : CKR_DEVICE_ERROR0x00000030UL; |
1399 | error = PORT_GetErrorPORT_GetError_Util(); |
1400 | |
1401 | /* remove padding */ |
1402 | if ((encrypt == PR_FALSE0) && (rv == SECSuccess)) { |
1403 | crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE16, &pad); |
1404 | dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len)(((sftk_CKRVToMask(crv)) & (dest->len - pad)) | (~(sftk_CKRVToMask (crv)) & (dest->len))); |
1405 | PORT_SetErrorPORT_SetError_Util(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD)(((sftk_CKRVToMask(crv)) & (error)) | (~(sftk_CKRVToMask( crv)) & (SEC_ERROR_BAD_PASSWORD)))); |
1406 | } |
1407 | AESKeyWrap_DestroyContext(ctxt, PR_TRUE1); |
1408 | |
1409 | loser: |
1410 | if (crv != CKR_OK0x00000000UL) { |
1411 | if (dest != NULL((void*)0)) { |
1412 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dest, PR_TRUE1); |
1413 | } |
1414 | dest = NULL((void*)0); |
1415 | } |
1416 | |
1417 | if (dup_src != NULL((void*)0)) { |
1418 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup_src, PR_TRUE1); |
1419 | } |
1420 | |
1421 | return dest; |
1422 | } |
1423 | |
1424 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
1425 | /* perform rc2 encryption/decryption if an error occurs, NULL is returned |
1426 | */ |
1427 | static SECItem * |
1428 | sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy, |
1429 | PRBool encrypt) |
1430 | { |
1431 | SECItem *dest; |
1432 | SECItem *dup_src; |
1433 | SECStatus rv = SECFailure; |
1434 | int pad; |
1435 | |
1436 | if ((src == NULL((void*)0)) || (key == NULL((void*)0)) || (iv == NULL((void*)0))) { |
1437 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
1438 | return NULL((void*)0); |
1439 | } |
1440 | |
1441 | dup_src = SECITEM_DupItemSECITEM_DupItem_Util(src); |
1442 | if (dup_src == NULL((void*)0)) { |
1443 | return NULL((void*)0); |
1444 | } |
1445 | |
1446 | if (encrypt != PR_FALSE0) { |
1447 | void *v; |
1448 | |
1449 | v = CBC_PadBuffer(NULL((void*)0), dup_src->data, |
1450 | dup_src->len, &dup_src->len, 8 /* RC2_BLOCK_SIZE */); |
1451 | if (v == NULL((void*)0)) { |
1452 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup_src, PR_TRUE1); |
1453 | return NULL((void*)0); |
1454 | } |
1455 | dup_src->data = (unsigned char *)v; |
1456 | } |
1457 | |
1458 | dest = (SECItem *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(SECItem)); |
1459 | if (dest != NULL((void*)0)) { |
1460 | dest->data = (unsigned char *)PORT_ZAllocPORT_ZAlloc_Util(dup_src->len + 64); |
1461 | if (dest->data != NULL((void*)0)) { |
1462 | RC2Context *ctxt; |
1463 | |
1464 | ctxt = RC2_CreateContext(key->data, key->len, iv->data, |
1465 | NSS_RC2_CBC1, key->len); |
1466 | |
1467 | if (ctxt != NULL((void*)0)) { |
1468 | rv = (encrypt ? RC2_Encrypt : RC2_Decrypt)( |
1469 | ctxt, dest->data, &dest->len, |
1470 | dup_src->len + 64, dup_src->data, dup_src->len); |
1471 | |
1472 | /* assumes 8 byte blocks -- remove padding */ |
1473 | if ((rv == SECSuccess) && (encrypt != PR_TRUE1)) { |
1474 | pad = dest->data[dest->len - 1]; |
1475 | if ((pad > 0) && (pad <= 8)) { |
1476 | if (dest->data[dest->len - pad] != pad) { |
1477 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_PASSWORD); |
1478 | rv = SECFailure; |
1479 | } else { |
1480 | dest->len -= pad; |
1481 | } |
1482 | } else { |
1483 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_PASSWORD); |
1484 | rv = SECFailure; |
1485 | } |
1486 | } |
1487 | } |
1488 | } |
1489 | } |
1490 | |
1491 | if ((rv != SECSuccess) && (dest != NULL((void*)0))) { |
1492 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dest, PR_TRUE1); |
1493 | dest = NULL((void*)0); |
1494 | } |
1495 | |
1496 | if (dup_src != NULL((void*)0)) { |
1497 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup_src, PR_TRUE1); |
1498 | } |
1499 | |
1500 | return dest; |
1501 | } |
1502 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
1503 | |
1504 | /* perform rc4 encryption and decryption */ |
1505 | static SECItem * |
1506 | sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op, |
1507 | PRBool encrypt) |
1508 | { |
1509 | SECItem *dest; |
1510 | SECStatus rv = SECFailure; |
1511 | |
1512 | if ((src == NULL((void*)0)) || (key == NULL((void*)0)) || (iv == NULL((void*)0))) { |
1513 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
1514 | return NULL((void*)0); |
1515 | } |
1516 | |
1517 | dest = (SECItem *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(SECItem)); |
1518 | if (dest != NULL((void*)0)) { |
1519 | dest->data = (unsigned char *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(unsigned char) * |
1520 | (src->len + 64)); |
1521 | if (dest->data != NULL((void*)0)) { |
1522 | RC4Context *ctxt; |
1523 | |
1524 | ctxt = RC4_CreateContext(key->data, key->len); |
1525 | if (ctxt) { |
1526 | rv = (encrypt ? RC4_Encrypt : RC4_Decrypt)( |
1527 | ctxt, dest->data, &dest->len, |
1528 | src->len + 64, src->data, src->len); |
1529 | RC4_DestroyContext(ctxt, PR_TRUE1); |
1530 | } |
1531 | } |
1532 | } |
1533 | |
1534 | if ((rv != SECSuccess) && (dest)) { |
1535 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dest, PR_TRUE1); |
1536 | dest = NULL((void*)0); |
1537 | } |
1538 | |
1539 | return dest; |
1540 | } |
1541 | /* function pointer template for crypto functions */ |
1542 | typedef SECItem *(*pkcs5_crypto_func)(SECItem *key, SECItem *iv, |
1543 | SECItem *src, PRBool op1, PRBool op2); |
1544 | |
1545 | /* performs the cipher operation on the src and returns the result. |
1546 | * if an error occurs, NULL is returned. |
1547 | * |
1548 | * a null length password is allowed. this corresponds to encrypting |
1549 | * the data with ust the salt. |
1550 | */ |
1551 | /* change this to use PKCS 11? */ |
1552 | SECItem * |
1553 | nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, |
1554 | SECItem *src, PRBool encrypt, PRBool *update) |
1555 | { |
1556 | SECItem *key = NULL((void*)0), iv; |
1557 | SECItem *dest = NULL((void*)0); |
1558 | PRBool tripleDES = PR_TRUE1; |
1559 | pkcs5_crypto_func cryptof; |
1560 | |
1561 | iv.data = NULL((void*)0); |
1562 | |
1563 | if (update) { |
1564 | *update = PR_FALSE0; |
1565 | } |
1566 | |
1567 | if ((pwitem == NULL((void*)0)) || (src == NULL((void*)0))) { |
1568 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
1569 | return NULL((void*)0); |
1570 | } |
1571 | |
1572 | /* get key, and iv */ |
1573 | key = nsspkcs5_ComputeKeyAndIV(pbe_param, pwitem, &iv, PR_FALSE0); |
1574 | if (key == NULL((void*)0)) { |
1575 | return NULL((void*)0); |
1576 | } |
1577 | |
1578 | switch (pbe_param->encAlg) { |
1579 | /* PKCS 5 v2 only */ |
1580 | case SEC_OID_AES_128_KEY_WRAP: |
1581 | case SEC_OID_AES_192_KEY_WRAP: |
1582 | case SEC_OID_AES_256_KEY_WRAP: |
1583 | cryptof = sec_pkcs5_aes_key_wrap; |
1584 | break; |
1585 | case SEC_OID_AES_128_CBC: |
1586 | case SEC_OID_AES_192_CBC: |
1587 | case SEC_OID_AES_256_CBC: |
1588 | cryptof = sec_pkcs5_aes; |
1589 | break; |
1590 | case SEC_OID_DES_EDE3_CBC: |
1591 | cryptof = sec_pkcs5_des; |
1592 | tripleDES = PR_TRUE1; |
1593 | break; |
1594 | case SEC_OID_DES_CBC: |
1595 | cryptof = sec_pkcs5_des; |
1596 | tripleDES = PR_FALSE0; |
1597 | break; |
1598 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
1599 | case SEC_OID_RC2_CBC: |
1600 | cryptof = sec_pkcs5_rc2; |
1601 | break; |
1602 | #endif |
1603 | case SEC_OID_RC4: |
1604 | cryptof = sec_pkcs5_rc4; |
1605 | break; |
1606 | default: |
1607 | cryptof = NULL((void*)0); |
1608 | break; |
1609 | } |
1610 | |
1611 | if (cryptof == NULL((void*)0)) { |
1612 | goto loser; |
1613 | } |
1614 | |
1615 | dest = (*cryptof)(key, &iv, src, tripleDES, encrypt); |
1616 | /* |
1617 | * it's possible for some keys and keydb's to claim to |
1618 | * be triple des when they're really des. In this case |
1619 | * we simply try des. If des works we set the update flag |
1620 | * so the key db knows it needs to update all it's entries. |
1621 | * The case can only happen on decrypted of a |
1622 | * SEC_OID_DES_EDE3_CBD. |
1623 | */ |
1624 | if ((pbe_param->encAlg == SEC_OID_DES_EDE3_CBC) && |
1625 | (dest == NULL((void*)0)) && (encrypt == PR_FALSE0)) { |
1626 | dest = (*cryptof)(key, &iv, src, PR_FALSE0, encrypt); |
1627 | if (update && (dest != NULL((void*)0))) |
1628 | *update = PR_TRUE1; |
1629 | } |
1630 | |
1631 | loser: |
1632 | if (key != NULL((void*)0)) { |
1633 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(key, PR_TRUE1); |
1634 | } |
1635 | if (iv.data != NULL((void*)0)) { |
1636 | SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&iv, PR_FALSE0); |
1637 | } |
1638 | |
1639 | return dest; |
1640 | } |
1641 | |
1642 | /* creates a algorithm ID containing the PBE algorithm and appropriate |
1643 | * parameters. the required parameter is the algorithm. if salt is |
1644 | * not specified, it is generated randomly. if IV is specified, it overrides |
1645 | * the PKCS 5 generation of the IV. |
1646 | * |
1647 | * the returned SECAlgorithmID should be destroyed using |
1648 | * SECOID_DestroyAlgorithmID |
1649 | */ |
1650 | SECAlgorithmID * |
1651 | nsspkcs5_CreateAlgorithmID(PLArenaPool *arena, SECOidTag algorithm, |
1652 | NSSPKCS5PBEParameter *pbe_param) |
1653 | { |
1654 | SECAlgorithmID *algid, *ret_algid = NULL((void*)0); |
1655 | SECItem der_param; |
1656 | nsspkcs5V2PBEParameter pkcs5v2_param; |
1657 | |
1658 | SECStatus rv = SECFailure; |
1659 | void *dummy = NULL((void*)0); |
1660 | |
1661 | if (arena == NULL((void*)0)) { |
1662 | return NULL((void*)0); |
1663 | } |
1664 | |
1665 | der_param.data = NULL((void*)0); |
1666 | der_param.len = 0; |
1667 | |
1668 | /* generate the algorithm id */ |
1669 | algid = (SECAlgorithmID *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, sizeof(SECAlgorithmID)); |
1670 | if (algid == NULL((void*)0)) { |
1671 | goto loser; |
1672 | } |
1673 | |
1674 | if (pbe_param->iteration.data == NULL((void*)0)) { |
1675 | dummy = SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(pbe_param->poolp, &pbe_param->iteration, |
1676 | pbe_param->iter); |
1677 | if (dummy == NULL((void*)0)) { |
1678 | goto loser; |
1679 | } |
1680 | } |
1681 | switch (pbe_param->pbeType) { |
1682 | case NSSPKCS5_PBKDF1: |
1683 | dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &der_param, pbe_param, |
1684 | NSSPKCS5PBEParameterTemplate); |
1685 | break; |
1686 | case NSSPKCS5_PKCS12_V2: |
1687 | dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &der_param, pbe_param, |
1688 | NSSPKCS5PKCS12V2PBEParameterTemplate); |
1689 | break; |
1690 | case NSSPKCS5_PBKDF2: |
1691 | if (pbe_param->keyLength.data == NULL((void*)0)) { |
1692 | dummy = SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(pbe_param->poolp, |
1693 | &pbe_param->keyLength, pbe_param->keyLen); |
1694 | if (dummy == NULL((void*)0)) { |
1695 | goto loser; |
1696 | } |
1697 | } |
1698 | PORT_Memsetmemset(&pkcs5v2_param, 0, sizeof(pkcs5v2_param)); |
1699 | dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &der_param, pbe_param, |
1700 | NSSPKCS5V2PBEParameterTemplate); |
1701 | if (dummy == NULL((void*)0)) { |
1702 | break; |
1703 | } |
1704 | dummy = NULL((void*)0); |
1705 | rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &pkcs5v2_param.keyParams, |
1706 | SEC_OID_PKCS5_PBKDF2, &der_param); |
1707 | if (rv != SECSuccess) { |
1708 | break; |
1709 | } |
1710 | der_param.data = pbe_param->ivData; |
1711 | der_param.len = pbe_param->ivLen; |
1712 | rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &pkcs5v2_param.algParams, |
1713 | pbe_param->encAlg, pbe_param->ivLen ? &der_param : NULL((void*)0)); |
1714 | if (rv != SECSuccess) { |
1715 | dummy = NULL((void*)0); |
1716 | break; |
1717 | } |
1718 | der_param.data = NULL((void*)0); |
1719 | der_param.len = 0; |
1720 | dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &der_param, &pkcs5v2_param, |
1721 | NSSPKCS5V2PBES2ParameterTemplate); |
1722 | /* If the algorithm was set to some encryption oid, set it |
1723 | * to PBES2 */ |
1724 | if ((algorithm != SEC_OID_PKCS5_PBKDF2) && |
1725 | (algorithm != SEC_OID_PKCS5_PBMAC1)) { |
1726 | algorithm = SEC_OID_PKCS5_PBES2; |
1727 | } |
1728 | break; |
1729 | default: |
1730 | break; |
1731 | } |
1732 | |
1733 | if (dummy == NULL((void*)0)) { |
1734 | goto loser; |
1735 | } |
1736 | |
1737 | rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, algid, algorithm, &der_param); |
1738 | if (rv != SECSuccess) { |
1739 | goto loser; |
1740 | } |
1741 | |
1742 | ret_algid = (SECAlgorithmID *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(SECAlgorithmID)); |
1743 | if (ret_algid == NULL((void*)0)) { |
1744 | goto loser; |
1745 | } |
1746 | |
1747 | rv = SECOID_CopyAlgorithmIDSECOID_CopyAlgorithmID_Util(NULL((void*)0), ret_algid, algid); |
1748 | if (rv != SECSuccess) { |
1749 | SECOID_DestroyAlgorithmIDSECOID_DestroyAlgorithmID_Util(ret_algid, PR_TRUE1); |
1750 | ret_algid = NULL((void*)0); |
1751 | } |
1752 | |
1753 | loser: |
1754 | |
1755 | return ret_algid; |
1756 | } |
1757 | |
1758 | #define TEST_KEY"pbkdf test key" "pbkdf test key" |
1759 | SECStatus |
1760 | sftk_fips_pbkdf_PowerUpSelfTests(void) |
1761 | { |
1762 | SECItem *result; |
1763 | SECItem inKey; |
1764 | NSSPKCS5PBEParameter pbe_params; |
1765 | unsigned char iteration_count = 5; |
1766 | unsigned char keyLen = 64; |
1767 | char *inKeyData = TEST_KEY"pbkdf test key"; |
1768 | static const unsigned char saltData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; |
1769 | static const unsigned char pbkdf_known_answer[] = { |
1770 | 0x31, 0xf0, 0xe5, 0x39, 0x9f, 0x39, 0xb9, 0x29, |
1771 | 0x68, 0xac, 0xf2, 0xe9, 0x53, 0x9b, 0xb4, 0x9c, |
1772 | 0x28, 0x59, 0x8b, 0x5c, 0xd8, 0xd4, 0x02, 0x37, |
1773 | 0x18, 0x22, 0xc1, 0x92, 0xd0, 0xfa, 0x72, 0x90, |
1774 | 0x2c, 0x8d, 0x19, 0xd4, 0x56, 0xfb, 0x16, 0xfa, |
1775 | 0x8d, 0x5c, 0x06, 0x33, 0xd1, 0x5f, 0x17, 0xb1, |
1776 | 0x22, 0xd9, 0x9c, 0xaf, 0x5e, 0x3f, 0xf3, 0x66, |
1777 | 0xc6, 0x14, 0xfe, 0x83, 0xfa, 0x1a, 0x2a, 0xc5 |
1778 | }; |
1779 | |
1780 | sftk_PBELockInit(); |
1781 | |
1782 | inKey.data = (unsigned char *)inKeyData; |
1783 | inKey.len = sizeof(TEST_KEY"pbkdf test key") - 1; |
1784 | |
1785 | pbe_params.salt.data = (unsigned char *)saltData; |
1786 | pbe_params.salt.len = sizeof(saltData); |
1787 | /* the interation and keyLength are used as intermediate |
1788 | * values when decoding the Algorithm ID, set them for completeness, |
1789 | * but they are not used */ |
1790 | pbe_params.iteration.data = &iteration_count; |
1791 | pbe_params.iteration.len = 1; |
1792 | pbe_params.keyLength.data = &keyLen; |
1793 | pbe_params.keyLength.len = 1; |
1794 | /* pkcs5v2 stores the key in the AlgorithmID, so we don't need to |
1795 | * generate it here */ |
1796 | pbe_params.ivLen = 0; |
1797 | pbe_params.ivData = NULL((void*)0); |
1798 | /* keyID is only used by pkcs12 extensions to pkcs5v1 */ |
1799 | pbe_params.keyID = pbeBitGenCipherKey; |
1800 | /* Algorithm is used by the decryption code after get get our key */ |
1801 | pbe_params.encAlg = SEC_OID_AES_256_CBC; |
1802 | /* these are the fields actually used in nsspkcs5_ComputeKeyAndIV |
1803 | * for NSSPKCS5_PBKDF2 */ |
1804 | pbe_params.iter = iteration_count; |
1805 | pbe_params.keyLen = keyLen; |
1806 | pbe_params.hashType = HASH_AlgSHA256; |
1807 | pbe_params.pbeType = NSSPKCS5_PBKDF2; |
1808 | pbe_params.is2KeyDES = PR_FALSE0; |
1809 | |
1810 | result = nsspkcs5_ComputeKeyAndIV(&pbe_params, &inKey, NULL((void*)0), PR_FALSE0); |
1811 | if ((result == NULL((void*)0)) || (result->len != sizeof(pbkdf_known_answer)) || |
1812 | (PORT_Memcmpmemcmp(result->data, pbkdf_known_answer, sizeof(pbkdf_known_answer)) != 0)) { |
1813 | SECITEM_FreeItemSECITEM_FreeItem_Util(result, PR_TRUE1); |
1814 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE); |
1815 | return SECFailure; |
1816 | } |
1817 | SECITEM_FreeItemSECITEM_FreeItem_Util(result, PR_TRUE1); |
1818 | return SECSuccess; |
1819 | } |