Bug Summary

File:s/lib/pkcs12/p12dec.c
Warning:line 549, column 9
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 p12dec.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/pkcs12 -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/pkcs12 -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -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 p12dec.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 "pkcs12.h"
6#include "plarena.h"
7#include "secpkcs7.h"
8#include "p12local.h"
9#include "secoid.h"
10#include "secitem.h"
11#include "secport.h"
12#include "secasn1.h"
13#include "secder.h"
14#include "secerr.h"
15#include "cert.h"
16#include "certdb.h"
17#include "p12plcy.h"
18#include "p12.h"
19#include "secpkcs5.h"
20
21/* PFX extraction and validation routines */
22
23/* decode the DER encoded PFX item. if unable to decode, check to see if it
24 * is an older PFX item. If that fails, assume the file was not a valid
25 * pfx file.
26 * the returned pfx structure should be destroyed using SEC_PKCS12DestroyPFX
27 */
28static SEC_PKCS12PFXItem *
29sec_pkcs12_decode_pfx(SECItem *der_pfx)
30{
31 SEC_PKCS12PFXItem *pfx;
32 SECStatus rv;
33
34 if (der_pfx == NULL((void*)0)) {
35 return NULL((void*)0);
36 }
37
38 /* allocate the space for a new PFX item */
39 pfx = sec_pkcs12_new_pfx();
40 if (pfx == NULL((void*)0)) {
41 return NULL((void*)0);
42 }
43
44 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate,
45 der_pfx);
46
47 /* if a failure occurred, check for older version...
48 * we also get rid of the old pfx structure, because we don't
49 * know where it failed and what data in may contain
50 */
51 if (rv != SECSuccess) {
52 SEC_PKCS12DestroyPFX(pfx);
53 pfx = sec_pkcs12_new_pfx();
54 if (pfx == NULL((void*)0)) {
55 return NULL((void*)0);
56 }
57 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate_OLD,
58 der_pfx);
59 if (rv != SECSuccess) {
60 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_DECODING_PFX);
61 PORT_FreeArenaPORT_FreeArena_Util(pfx->poolp, PR_TRUE1);
62 return NULL((void*)0);
63 }
64 pfx->old = PR_TRUE1;
65 rv = SGN_CopyDigestInfoSGN_CopyDigestInfo_Util(pfx->poolp, &pfx->macData.safeMac, &pfx->old_safeMac);
66 if (rv != SECSuccess) {
67 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
68 PORT_FreeArenaPORT_FreeArena_Util(pfx->poolp, PR_TRUE1);
69 return NULL((void*)0);
70 }
71 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(pfx->poolp, &pfx->macData.macSalt, &pfx->old_macSalt);
72 if (rv != SECSuccess) {
73 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
74 PORT_FreeArenaPORT_FreeArena_Util(pfx->poolp, PR_TRUE1);
75 return NULL((void*)0);
76 }
77 } else {
78 pfx->old = PR_FALSE0;
79 }
80
81 /* convert bit string from bits to bytes */
82 pfx->macData.macSalt.len /= 8;
83
84 return pfx;
85}
86
87/* validate the integrity MAC used in the PFX. The MAC is generated
88 * per the PKCS 12 document. If the MAC is incorrect, it is most likely
89 * due to an invalid password.
90 * pwitem is the integrity password
91 * pfx is the decoded pfx item
92 */
93static PRBool
94sec_pkcs12_check_pfx_mac(SEC_PKCS12PFXItem *pfx,
95 SECItem *pwitem)
96{
97 SECItem *key = NULL((void*)0), *mac = NULL((void*)0), *data = NULL((void*)0);
98 SECItem *vpwd = NULL((void*)0);
99 SECOidTag algorithm;
100 PRBool ret = PR_FALSE0;
101
102 if (pfx == NULL((void*)0)) {
103 return PR_FALSE0;
104 }
105
106 algorithm = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&pfx->macData.safeMac.digestAlgorithm);
107 switch (algorithm) {
108 /* only SHA1 hashing supported as a MACing algorithm */
109 case SEC_OID_SHA1:
110 if (pfx->old == PR_FALSE0) {
111 pfx->swapUnicode = PR_FALSE0;
112 }
113
114 recheckUnicodePassword:
115 vpwd = sec_pkcs12_create_virtual_password(pwitem,
116 &pfx->macData.macSalt,
117 pfx->swapUnicode);
118 if (vpwd == NULL((void*)0)) {
119 return PR_FALSE0;
120 }
121
122 key = sec_pkcs12_generate_key_from_password(algorithm,
123 &pfx->macData.macSalt,
124 (pfx->old ? pwitem : vpwd));
125 /* free vpwd only for newer PFX */
126 if (vpwd) {
127 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(vpwd, PR_TRUE1);
128 }
129 if (key == NULL((void*)0)) {
130 return PR_FALSE0;
131 }
132
133 data = SEC_PKCS7GetContent(&pfx->authSafe);
134 if (data == NULL((void*)0)) {
135 break;
136 }
137
138 /* check MAC */
139 mac = sec_pkcs12_generate_mac(key, data, pfx->old);
140 ret = PR_TRUE1;
141 if (mac) {
142 SECItem *safeMac = &pfx->macData.safeMac.digest;
143 if (SECITEM_CompareItemSECITEM_CompareItem_Util(mac, safeMac) != SECEqual) {
144
145 /* if we encounter an invalid mac, lets invert the
146 * password in case of unicode changes
147 */
148 if (((!pfx->old) && pfx->swapUnicode) || (pfx->old)) {
149 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_INVALID_MAC);
150 ret = PR_FALSE0;
151 } else {
152 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(mac, PR_TRUE1);
153 pfx->swapUnicode = PR_TRUE1;
154 goto recheckUnicodePassword;
155 }
156 }
157 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(mac, PR_TRUE1);
158 } else {
159 ret = PR_FALSE0;
160 }
161 break;
162 default:
163 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM);
164 ret = PR_FALSE0;
165 break;
166 }
167
168 /* let success fall through */
169 if (key != NULL((void*)0))
170 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(key, PR_TRUE1);
171
172 return ret;
173}
174
175/* check the validity of the pfx structure. we currently only support
176 * password integrity mode, so we check the MAC.
177 */
178static PRBool
179sec_pkcs12_validate_pfx(SEC_PKCS12PFXItem *pfx,
180 SECItem *pwitem)
181{
182 SECOidTag contentType;
183
184 contentType = SEC_PKCS7ContentType(&pfx->authSafe);
185 switch (contentType) {
186 case SEC_OID_PKCS7_DATA:
187 return sec_pkcs12_check_pfx_mac(pfx, pwitem);
188 break;
189 case SEC_OID_PKCS7_SIGNED_DATA:
190 default:
191 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE);
192 break;
193 }
194
195 return PR_FALSE0;
196}
197
198/* decode and return the valid PFX. if the PFX item is not valid,
199 * NULL is returned.
200 */
201static SEC_PKCS12PFXItem *
202sec_pkcs12_get_pfx(SECItem *pfx_data,
203 SECItem *pwitem)
204{
205 SEC_PKCS12PFXItem *pfx;
206 PRBool valid_pfx;
207
208 if ((pfx_data == NULL((void*)0)) || (pwitem == NULL((void*)0))) {
209 return NULL((void*)0);
210 }
211
212 pfx = sec_pkcs12_decode_pfx(pfx_data);
213 if (pfx == NULL((void*)0)) {
214 return NULL((void*)0);
215 }
216
217 valid_pfx = sec_pkcs12_validate_pfx(pfx, pwitem);
218 if (valid_pfx != PR_TRUE1) {
219 SEC_PKCS12DestroyPFX(pfx);
220 pfx = NULL((void*)0);
221 }
222
223 return pfx;
224}
225
226/* authenticated safe decoding, validation, and access routines
227 */
228
229/* convert dogbert beta 3 authenticated safe structure to a post
230 * beta three structure, so that we don't have to change more routines.
231 */
232static SECStatus
233sec_pkcs12_convert_old_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe)
234{
235 SEC_PKCS12Baggage *baggage;
236 SEC_PKCS12BaggageItem *bag;
237 SECStatus rv = SECSuccess;
238
239 if (asafe->old_baggage.espvks == NULL((void*)0)) {
240 /* XXX should the ASN1 engine produce a single NULL element list
241 * rather than setting the pointer to NULL?
242 * There is no need to return an error -- assume that the list
243 * was empty.
244 */
245 return SECSuccess;
246 }
247
248 baggage = sec_pkcs12_create_baggage(asafe->poolp);
249 if (!baggage) {
250 return SECFailure;
251 }
252 bag = sec_pkcs12_create_external_bag(baggage);
253 if (!bag) {
254 return SECFailure;
255 }
256
257 PORT_Memcpymemcpy(&asafe->baggage, baggage, sizeof(SEC_PKCS12Baggage));
258
259 /* if there are shrouded keys, append them to the bag */
260 rv = SECSuccess;
261 if (asafe->old_baggage.espvks[0] != NULL((void*)0)) {
262 int nEspvk = 0;
263 rv = SECSuccess;
264 while ((asafe->old_baggage.espvks[nEspvk] != NULL((void*)0)) &&
265 (rv == SECSuccess)) {
266 rv = sec_pkcs12_append_shrouded_key(bag,
267 asafe->old_baggage.espvks[nEspvk]);
268 nEspvk++;
269 }
270 }
271
272 return rv;
273}
274
275/* decodes the authenticated safe item. a return of NULL indicates
276 * an error. however, the error will have occurred either in memory
277 * allocation or in decoding the authenticated safe.
278 *
279 * if an old PFX item has been found, we want to convert the
280 * old authenticated safe to the new one.
281 */
282static SEC_PKCS12AuthenticatedSafe *
283sec_pkcs12_decode_authenticated_safe(SEC_PKCS12PFXItem *pfx)
284{
285 SECItem *der_asafe = NULL((void*)0);
286 SEC_PKCS12AuthenticatedSafe *asafe = NULL((void*)0);
287 SECStatus rv;
288
289 if (pfx == NULL((void*)0)) {
290 return NULL((void*)0);
291 }
292
293 der_asafe = SEC_PKCS7GetContent(&pfx->authSafe);
294 if (der_asafe == NULL((void*)0)) {
295 /* XXX set error ? */
296 goto loser;
297 }
298
299 asafe = sec_pkcs12_new_asafe(pfx->poolp);
300 if (asafe == NULL((void*)0)) {
301 goto loser;
302 }
303
304 if (pfx->old == PR_FALSE0) {
305 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(pfx->poolp, asafe,
306 SEC_PKCS12AuthenticatedSafeTemplate,
307 der_asafe);
308 asafe->old = PR_FALSE0;
309 asafe->swapUnicode = pfx->swapUnicode;
310 } else {
311 /* handle beta exported files */
312 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(pfx->poolp, asafe,
313 SEC_PKCS12AuthenticatedSafeTemplate_OLD,
314 der_asafe);
315 asafe->safe = &(asafe->old_safe);
316 rv = sec_pkcs12_convert_old_auth_safe(asafe);
317 asafe->old = PR_TRUE1;
318 }
319
320 if (rv != SECSuccess) {
321 goto loser;
322 }
323
324 asafe->poolp = pfx->poolp;
325
326 return asafe;
327
328loser:
329 return NULL((void*)0);
330}
331
332/* validates the safe within the authenticated safe item.
333 * in order to be valid:
334 * 1. the privacy salt must be present
335 * 2. the encryption algorithm must be supported (including
336 * export policy)
337 * PR_FALSE indicates an error, PR_TRUE indicates a valid safe
338 */
339static PRBool
340sec_pkcs12_validate_encrypted_safe(SEC_PKCS12AuthenticatedSafe *asafe)
341{
342 PRBool valid = PR_FALSE0;
343 SECAlgorithmID *algid;
344
345 if (asafe == NULL((void*)0)) {
346 return PR_FALSE0;
347 }
348
349 /* if mode is password privacy, then privacySalt is assumed
350 * to be non-zero.
351 */
352 if (asafe->privacySalt.len != 0) {
353 valid = PR_TRUE1;
354 asafe->privacySalt.len /= 8;
355 } else {
356 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
357 return PR_FALSE0;
358 }
359
360 /* until spec changes, content will have between 2 and 8 bytes depending
361 * upon the algorithm used if certs are unencrypted...
362 * also want to support case where content is empty -- which we produce
363 */
364 if (SEC_PKCS7IsContentEmpty(asafe->safe, 8) == PR_TRUE1) {
365 asafe->emptySafe = PR_TRUE1;
366 return PR_TRUE1;
367 }
368
369 asafe->emptySafe = PR_FALSE0;
370
371 /* make sure that a pbe algorithm is being used */
372 algid = SEC_PKCS7GetEncryptionAlgorithm(asafe->safe);
373 if (algid != NULL((void*)0)) {
374 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
375 valid = SEC_PKCS12DecryptionAllowed(algid);
376
377 if (valid == PR_FALSE0) {
378 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_EXPORT_ALGORITHM);
379 }
380 } else {
381 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM);
382 valid = PR_FALSE0;
383 }
384 } else {
385 valid = PR_FALSE0;
386 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM);
387 }
388
389 return valid;
390}
391
392/* validates authenticates safe:
393 * 1. checks that the version is supported
394 * 2. checks that only password privacy mode is used (currently)
395 * 3. further, makes sure safe has appropriate policies per above function
396 * PR_FALSE indicates failure.
397 */
398static PRBool
399sec_pkcs12_validate_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe)
400{
401 PRBool valid = PR_TRUE1;
402 SECOidTag safe_type;
403 int version;
404
405 if (asafe == NULL((void*)0)) {
406 return PR_FALSE0;
407 }
408
409 /* check version, since it is default it may not be present.
410 * therefore, assume ok
411 */
412 if ((asafe->version.len > 0) && (asafe->old == PR_FALSE0)) {
413 version = DER_GetIntegerDER_GetInteger_Util(&asafe->version);
414 if (version > SEC_PKCS12_PFX_VERSION1) {
415 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION);
416 return PR_FALSE0;
417 }
418 }
419
420 /* validate password mode is being used */
421 safe_type = SEC_PKCS7ContentType(asafe->safe);
422 switch (safe_type) {
423 case SEC_OID_PKCS7_ENCRYPTED_DATA:
424 valid = sec_pkcs12_validate_encrypted_safe(asafe);
425 break;
426 case SEC_OID_PKCS7_ENVELOPED_DATA:
427 default:
428 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE);
429 valid = PR_FALSE0;
430 break;
431 }
432
433 return valid;
434}
435
436/* retrieves the authenticated safe item from the PFX item
437 * before returning the authenticated safe, the validity of the
438 * authenticated safe is checked and if valid, returned.
439 * a return of NULL indicates that an error occurred.
440 */
441static SEC_PKCS12AuthenticatedSafe *
442sec_pkcs12_get_auth_safe(SEC_PKCS12PFXItem *pfx)
443{
444 SEC_PKCS12AuthenticatedSafe *asafe;
445 PRBool valid_safe;
446
447 if (pfx == NULL((void*)0)) {
448 return NULL((void*)0);
449 }
450
451 asafe = sec_pkcs12_decode_authenticated_safe(pfx);
452 if (asafe == NULL((void*)0)) {
453 return NULL((void*)0);
454 }
455
456 valid_safe = sec_pkcs12_validate_auth_safe(asafe);
457 if (valid_safe != PR_TRUE1) {
458 asafe = NULL((void*)0);
459 } else if (asafe) {
460 asafe->baggage.poolp = asafe->poolp;
461 }
462
463 return asafe;
464}
465
466/* decrypts the authenticated safe.
467 * a return of anything but SECSuccess indicates an error. the
468 * password is not known to be valid until the call to the
469 * function sec_pkcs12_get_safe_contents. If decoding the safe
470 * fails, it is assumed the password was incorrect and the error
471 * is set then. any failure here is assumed to be due to
472 * internal problems in SEC_PKCS7DecryptContents or below.
473 */
474static SECStatus
475sec_pkcs12_decrypt_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe,
476 SECItem *pwitem,
477 void *wincx)
478{
479 SECStatus rv = SECFailure;
480 SECItem *vpwd = NULL((void*)0);
481
482 if ((asafe == NULL((void*)0)) || (pwitem == NULL((void*)0))) {
483 return SECFailure;
484 }
485
486 if (asafe->old == PR_FALSE0) {
487 vpwd = sec_pkcs12_create_virtual_password(pwitem, &asafe->privacySalt,
488 asafe->swapUnicode);
489 if (vpwd == NULL((void*)0)) {
490 return SECFailure;
491 }
492 }
493
494 rv = SEC_PKCS7DecryptContents(asafe->poolp, asafe->safe,
495 (asafe->old ? pwitem : vpwd), wincx);
496
497 if (asafe->old == PR_FALSE0) {
498 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(vpwd, PR_TRUE1);
499 }
500
501 return rv;
502}
503
504/* extract the safe from the authenticated safe.
505 * if we are unable to decode the safe, then it is likely that the
506 * safe has not been decrypted or the password used to decrypt
507 * the safe was invalid. we assume that the password was invalid and
508 * set an error accordingly.
509 * a return of NULL indicates that an error occurred.
510 */
511static SEC_PKCS12SafeContents *
512sec_pkcs12_get_safe_contents(SEC_PKCS12AuthenticatedSafe *asafe)
513{
514 SECItem *src = NULL((void*)0);
515 SEC_PKCS12SafeContents *safe = NULL((void*)0);
516 SECStatus rv = SECFailure;
517
518 if (asafe == NULL((void*)0)) {
519 return NULL((void*)0);
520 }
521
522 safe = (SEC_PKCS12SafeContents *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(asafe->poolp,
523 sizeof(SEC_PKCS12SafeContents));
524 if (safe == NULL((void*)0)) {
525 return NULL((void*)0);
526 }
527 safe->poolp = asafe->poolp;
528 safe->old = asafe->old;
529 safe->swapUnicode = asafe->swapUnicode;
530
531 src = SEC_PKCS7GetContent(asafe->safe);
532 if (src != NULL((void*)0)) {
533 const SEC_ASN1Template *theTemplate;
534 if (asafe->old != PR_TRUE1) {
535 theTemplate = SEC_PKCS12SafeContentsTemplate;
536 } else {
537 theTemplate = SEC_PKCS12SafeContentsTemplate_OLD;
538 }
539
540 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(asafe->poolp, safe, theTemplate, src);
541
542 /* if we could not decode the item, password was probably invalid */
543 if (rv != SECSuccess) {
544 safe = NULL((void*)0);
545 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT);
546 }
547 } else {
548 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
549 rv = SECFailure;
Value stored to 'rv' is never read
550 }
551
552 return safe;
553}
554
555/* import PFX item
556 * der_pfx is the der encoded pfx structure
557 * pbef and pbearg are the integrity/encryption password call back
558 * ncCall is the nickname collision calllback
559 * slot is the destination token
560 * wincx window handler
561 *
562 * on error, error code set and SECFailure returned
563 */
564SECStatus
565SEC_PKCS12PutPFX(SECItem *der_pfx, SECItem *pwitem,
566 SEC_PKCS12NicknameCollisionCallback ncCall,
567 PK11SlotInfo *slot,
568 void *wincx)
569{
570 SEC_PKCS12PFXItem *pfx;
571 SEC_PKCS12AuthenticatedSafe *asafe;
572 SEC_PKCS12SafeContents *safe_contents = NULL((void*)0);
573 SECStatus rv;
574
575 if (!der_pfx || !pwitem || !slot) {
576 return SECFailure;
577 }
578
579 /* decode and validate each section */
580 rv = SECFailure;
581
582 pfx = sec_pkcs12_get_pfx(der_pfx, pwitem);
583 if (pfx != NULL((void*)0)) {
584 asafe = sec_pkcs12_get_auth_safe(pfx);
585 if (asafe != NULL((void*)0)) {
586
587 /* decrypt safe -- only if not empty */
588 if (asafe->emptySafe != PR_TRUE1) {
589 rv = sec_pkcs12_decrypt_auth_safe(asafe, pwitem, wincx);
590 if (rv == SECSuccess) {
591 safe_contents = sec_pkcs12_get_safe_contents(asafe);
592 if (safe_contents == NULL((void*)0)) {
593 rv = SECFailure;
594 }
595 }
596 } else {
597 safe_contents = sec_pkcs12_create_safe_contents(asafe->poolp);
598 if (safe_contents == NULL((void*)0)) {
599 rv = SECFailure;
600 } else {
601 safe_contents->swapUnicode = pfx->swapUnicode;
602 rv = SECSuccess;
603 }
604 }
605
606 /* get safe contents and begin import */
607 if (rv == SECSuccess) {
608 SEC_PKCS12DecoderContext *p12dcx;
609
610 p12dcx = sec_PKCS12ConvertOldSafeToNew(pfx->poolp, slot,
611 pfx->swapUnicode,
612 pwitem, wincx, safe_contents,
613 &asafe->baggage);
614 if (!p12dcx) {
615 rv = SECFailure;
616 goto loser;
617 }
618
619 if (SEC_PKCS12DecoderValidateBags(p12dcx, ncCall) != SECSuccess) {
620 rv = SECFailure;
621 goto loser;
622 }
623
624 rv = SEC_PKCS12DecoderImportBags(p12dcx);
625 }
626 }
627 }
628
629loser:
630
631 if (pfx) {
632 SEC_PKCS12DestroyPFX(pfx);
633 }
634
635 return rv;
636}
637
638PRBool
639SEC_PKCS12ValidData(char *buf, int bufLen, long int totalLength)
640{
641 int lengthLength;
642
643 PRBool valid = PR_FALSE0;
644
645 if (buf == NULL((void*)0)) {
646 return PR_FALSE0;
647 }
648
649 /* check for constructed sequence identifier tag */
650 if (*buf == (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) {
651 totalLength--; /* header byte taken care of */
652 buf++;
653
654 lengthLength = (long int)SEC_ASN1LengthLengthSEC_ASN1LengthLength_Util(totalLength - 1);
655 if (totalLength > 0x7f) {
656 lengthLength--;
657 *buf &= 0x7f; /* remove bit 8 indicator */
658 if ((*buf - (char)lengthLength) == 0) {
659 valid = PR_TRUE1;
660 }
661 } else {
662 lengthLength--;
663 if ((*buf - (char)lengthLength) == 0) {
664 valid = PR_TRUE1;
665 }
666 }
667 }
668
669 return valid;
670}