Bug Summary

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