Bug Summary

File:s/lib/softoken/lowpbe.c
Warning:line 1125, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lowpbe.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/softoken -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/softoken -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D SHLIB_SUFFIX="so" -D SHLIB_PREFIX="lib" -D SOFTOKEN_LIB_NAME="libsoftokn3.so" -D SHLIB_VERSION="3" -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c lowpbe.c
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
23SEC_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 */
32static 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
42static 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
51struct nsspkcs5V2PBEParameterStr {
52 SECAlgorithmID keyParams; /* parameters of the key generation */
53 SECAlgorithmID algParams; /* parameters for the encryption or mac op */
54};
55
56typedef struct nsspkcs5V2PBEParameterStr nsspkcs5V2PBEParameter;
57
58static 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
69static 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
82SECStatus
83nsspkcs5_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 */
102static SECItem *
103nsspkcs5_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 */
181static SECItem *
182nsspkcs5_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
254loser:
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 */
271static SECItem *
272nsspkcs5_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 */
303static void
304do_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
315static SECStatus
316nsspkcs5_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 }
353loser:
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
363static SECItem *
364nsspkcs5_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
397loser:
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 */
416static SECItem *
417nsspkcs5_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 }
534loser:
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
556struct KDFCacheItemStr {
557 SECItem *hash;
558 SECItem *salt;
559 SECItem *pwItem;
560 HASH_HashType hashType;
561 int iterations;
562 int keyLen;
563};
564typedef 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
570static 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
583void
584sftk_PBELockInit(void)
585{
586 if (!PBECache.lock) {
587 PBECache.lock = PZ_NewLock(nssIPBECacheLock)PR_NewLock();
588 }
589}
590
591static void
592sftk_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
608static void
609sftk_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
622static void
623sftk_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
641static void
642sftk_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
659static PRBool
660sftk_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
674static SECItem *
675sftk_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
695static SECItem *
696sftk_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
714void
715sftk_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 */
732SECItem *
733nsspkcs5_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
811loser:
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 */
823static SECStatus
824nsspkcs5_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
858static SECStatus
859nsspkcs5_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 */
1010NSSPKCS5PBEParameter *
1011nsspkcs5_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
1045loser:
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 */
1058HASH_HashType
1059HASH_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
1077SECOidTag
1078HASH_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 */
1102NSSPKCS5PBEParameter *
1103nsspkcs5_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
1171loser:
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 */
1187void
1188nsspkcs5_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 */
1199static SECItem *
1200sec_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
1258loser:
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 */
1275static SECItem *
1276sec_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
1333loser:
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 */
1350static SECItem *
1351sec_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
1409loser:
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 */
1427static SECItem *
1428sec_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 */
1505static SECItem *
1506sec_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 */
1542typedef 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? */
1552SECItem *
1553nsspkcs5_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
1631loser:
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 */
1650SECAlgorithmID *
1651nsspkcs5_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
1753loser:
1754
1755 return ret_algid;
1756}
1757
1758#define TEST_KEY"pbkdf test key" "pbkdf test key"
1759SECStatus
1760sftk_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}