Bug Summary

File:root/firefox-clang/security/nss/lib/pkcs12/p12d.c
Warning:line 2275, column 9
Value stored to 'setNickname' 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 p12d.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/pkcs12/pkcs12_pkcs12 -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/pkcs12/pkcs12_pkcs12 -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 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/pkcs12 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/pkcs12/pkcs12_pkcs12 -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/pkcs12/p12d.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 "nssrenam.h"
6#include "nss.h"
7#include "p12t.h"
8#include "p12.h"
9#include "plarena.h"
10#include "secitem.h"
11#include "secoid.h"
12#include "seccomon.h"
13#include "secport.h"
14#include "cert.h"
15#include "secpkcs7.h"
16#include "secasn1.h"
17#include "secerr.h"
18#include "pk11func.h"
19#include "p12plcy.h"
20#include "p12local.h"
21#include "secder.h"
22#include "secport.h"
23
24#include "certdb.h"
25
26#include "prcpucfg.h"
27
28/* This belongs in secport.h */
29#define PORT_ArenaGrowArray(poolp, oldptr, type, oldnum, newnum)(type *)PORT_ArenaGrow_Util((poolp), (oldptr), (oldnum) * sizeof
(type), (newnum) * sizeof(type))
\
30 (type *)PORT_ArenaGrowPORT_ArenaGrow_Util((poolp), (oldptr), \
31 (oldnum) * sizeof(type), (newnum) * sizeof(type))
32
33typedef struct sec_PKCS12SafeContentsContextStr sec_PKCS12SafeContentsContext;
34
35/* Opaque structure for decoding SafeContents. These are used
36 * for each authenticated safe as well as any nested safe contents.
37 */
38struct sec_PKCS12SafeContentsContextStr {
39 /* the parent decoder context */
40 SEC_PKCS12DecoderContext *p12dcx;
41
42 /* memory arena to allocate space from */
43 PLArenaPool *arena;
44
45 /* decoder context and destination for decoding safe contents */
46 SEC_ASN1DecoderContext *safeContentsA1Dcx;
47 sec_PKCS12SafeContents safeContents;
48
49 /* information for decoding safe bags within the safe contents.
50 * these variables are updated for each safe bag decoded.
51 */
52 SEC_ASN1DecoderContext *currentSafeBagA1Dcx;
53 sec_PKCS12SafeBag *currentSafeBag;
54 PRBool skipCurrentSafeBag;
55
56 /* if the safe contents is nested, the parent is pointed to here. */
57 sec_PKCS12SafeContentsContext *nestedSafeContentsCtx;
58};
59
60/* opaque decoder context structure. information for decoding a pkcs 12
61 * PDU are stored here as well as decoding pointers for intermediary
62 * structures which are part of the PKCS 12 PDU. Upon a successful
63 * decode, the safe bags containing certificates and keys encountered.
64 */
65struct SEC_PKCS12DecoderContextStr {
66 PLArenaPool *arena;
67 PK11SlotInfo *slot;
68 void *wincx;
69 PRBool error;
70 int errorValue;
71
72 /* password */
73 SECItem *pwitem;
74
75 /* used for decoding the PFX structure */
76 SEC_ASN1DecoderContext *pfxA1Dcx;
77 sec_PKCS12PFXItem pfx;
78
79 /* safe bags found during decoding */
80 sec_PKCS12SafeBag **safeBags;
81 unsigned int safeBagCount;
82
83 /* state variables for decoding authenticated safes. */
84 SEC_PKCS7DecoderContext *currentASafeP7Dcx;
85 SEC_ASN1DecoderContext *aSafeA1Dcx;
86 SEC_PKCS7DecoderContext *aSafeP7Dcx;
87 SEC_PKCS7ContentInfo *aSafeCinfo;
88 sec_PKCS12AuthenticatedSafe authSafe;
89 sec_PKCS12SafeContents safeContents;
90
91 /* safe contents info */
92 unsigned int safeContentsCnt;
93 sec_PKCS12SafeContentsContext **safeContentsList;
94
95 /* HMAC info */
96 sec_PKCS12MacData macData;
97
98 /* routines for reading back the data to be hmac'd */
99 /* They are called as follows.
100 *
101 * Stage 1: decode the aSafes cinfo into a buffer in dArg,
102 * which p12d.c sometimes refers to as the "temp file".
103 * This occurs during SEC_PKCS12DecoderUpdate calls.
104 *
105 * dOpen(dArg, PR_FALSE)
106 * dWrite(dArg, buf, len)
107 * ...
108 * dWrite(dArg, buf, len)
109 * dClose(dArg, PR_FALSE)
110 *
111 * Stage 2: verify MAC
112 * This occurs SEC_PKCS12DecoderVerify.
113 *
114 * dOpen(dArg, PR_TRUE)
115 * dRead(dArg, buf, IN_BUF_LEN)
116 * ...
117 * dRead(dArg, buf, IN_BUF_LEN)
118 * dClose(dArg, PR_TRUE)
119 */
120 digestOpenFn dOpen;
121 digestCloseFn dClose;
122 digestIOFn dRead, dWrite;
123 void *dArg;
124 PRBool dIsOpen; /* is the temp file created? */
125
126 /* helper functions */
127 SECKEYGetPasswordKey pwfn;
128 void *pwfnarg;
129 PRBool swapUnicodeBytes;
130 PRBool forceUnicode;
131
132 /* import information */
133 PRBool bagsVerified;
134
135 /* buffer management for the default callbacks implementation */
136 void *buffer; /* storage area */
137 PRInt32 filesize; /* actual data size */
138 PRInt32 allocated; /* total buffer size allocated */
139 PRInt32 currentpos; /* position counter */
140 SECPKCS12TargetTokenCAs tokenCAs;
141 sec_PKCS12SafeBag **keyList; /* used by ...IterateNext() */
142 unsigned int iteration;
143 SEC_PKCS12DecoderItem decitem;
144};
145
146/* forward declarations of functions that are used when decoding
147 * safeContents bags which are nested and when decoding the
148 * authenticatedSafes.
149 */
150static SECStatus
151sec_pkcs12_decoder_begin_nested_safe_contents(sec_PKCS12SafeContentsContext
152 *safeContentsCtx);
153static SECStatus
154sec_pkcs12_decoder_finish_nested_safe_contents(sec_PKCS12SafeContentsContext
155 *safeContentsCtx);
156
157/* make sure that the PFX version being decoded is a version
158 * which we support.
159 */
160static PRBool
161sec_pkcs12_proper_version(sec_PKCS12PFXItem *pfx)
162{
163 /* if no version, assume it is not supported */
164 if (pfx->version.len == 0) {
165 return PR_FALSE0;
166 }
167
168 if (DER_GetIntegerDER_GetInteger_Util(&pfx->version) > SEC_PKCS12_VERSION3) {
169 return PR_FALSE0;
170 }
171
172 return PR_TRUE1;
173}
174
175/* retrieve the key for decrypting the safe contents */
176static PK11SymKey *
177sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
178{
179 SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg;
180 PK11SlotInfo *slot;
181 PK11SymKey *bulkKey;
182 SECItem pwitem = { 0 };
183 SECOidTag algorithm;
184
185 if (!p12dcx) {
186 return NULL((void*)0);
187 }
188
189 /* if no slot specified, use the internal key slot */
190 if (p12dcx->slot) {
191 slot = PK11_ReferenceSlot(p12dcx->slot);
192 } else {
193 slot = PK11_GetInternalKeySlot();
194 }
195
196 algorithm = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(algid);
197
198 if (p12dcx->forceUnicode) {
199 if (SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), &pwitem, p12dcx->pwitem) != SECSuccess) {
200 PK11_FreeSlot(slot);
201 return NULL((void*)0);
202 }
203 } else {
204 if (!sec_pkcs12_decode_password(NULL((void*)0), &pwitem, algorithm, p12dcx->pwitem)) {
205 PK11_FreeSlot(slot);
206 return NULL((void*)0);
207 }
208 }
209
210 bulkKey = PK11_PBEKeyGen(slot, algid, &pwitem, PR_FALSE0, p12dcx->wincx);
211 /* some tokens can't generate PBE keys on their own, generate the
212 * key in the internal slot, and let the Import code deal with it,
213 * (if the slot can't generate PBEs, then we need to use the internal
214 * slot anyway to unwrap). */
215 if (!bulkKey && !PK11_IsInternal(slot)) {
216 PK11_FreeSlot(slot);
217 slot = PK11_GetInternalKeySlot();
218 bulkKey = PK11_PBEKeyGen(slot, algid, &pwitem, PR_FALSE0, p12dcx->wincx);
219 }
220 PK11_FreeSlot(slot);
221
222 /* set the password data on the key */
223 if (bulkKey) {
224 PK11_SetSymKeyUserData(bulkKey, p12dcx->pwitem, NULL((void*)0));
225 }
226
227 if (pwitem.data) {
228 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&pwitem, PR_FALSE0);
229 }
230
231 return bulkKey;
232}
233
234/* XXX this needs to be modified to handle enveloped data. most
235 * likely, it should mirror the routines for SMIME in that regard.
236 */
237static PRBool
238sec_pkcs12_decoder_decryption_allowed(SECAlgorithmID *algid,
239 PK11SymKey *bulkkey)
240{
241 PRBool decryptionAllowed = SEC_PKCS12DecryptionAllowed(algid);
242
243 if (!decryptionAllowed) {
244 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_EXPORT_ALGORITHM);
245 return PR_FALSE0;
246 }
247
248 return PR_TRUE1;
249}
250
251/* when we encounter a new safe bag during the decoding, we need
252 * to allocate space for the bag to be decoded to and set the
253 * state variables appropriately. all of the safe bags are allocated
254 * in a buffer in the outer SEC_PKCS12DecoderContext, however,
255 * a pointer to the safeBag is also used in the sec_PKCS12SafeContentsContext
256 * for the current bag.
257 */
258static SECStatus
259sec_pkcs12_decoder_init_new_safe_bag(sec_PKCS12SafeContentsContext
260 *safeContentsCtx)
261{
262 void *mark = NULL((void*)0);
263 SEC_PKCS12DecoderContext *p12dcx;
264
265 /* make sure that the structures are defined, and there has
266 * not been an error in the decoding
267 */
268 if (!safeContentsCtx || !safeContentsCtx->p12dcx || safeContentsCtx->p12dcx->error) {
269 return SECFailure;
270 }
271
272 p12dcx = safeContentsCtx->p12dcx;
273 mark = PORT_ArenaMarkPORT_ArenaMark_Util(p12dcx->arena);
274
275 /* allocate a new safe bag, if bags already exist, grow the
276 * list of bags, otherwise allocate a new list. the list is
277 * NULL terminated.
278 */
279 p12dcx->safeBags = (!p12dcx->safeBagCount)
280 ? PORT_ArenaZNewArray(p12dcx->arena, sec_PKCS12SafeBag *, 2)(sec_PKCS12SafeBag * *)PORT_ArenaZAlloc_Util(p12dcx->arena
, sizeof(sec_PKCS12SafeBag *) * (2))
281 : PORT_ArenaGrowArray(p12dcx->arena, p12dcx->safeBags,(sec_PKCS12SafeBag * *)PORT_ArenaGrow_Util((p12dcx->arena)
, (p12dcx->safeBags), (p12dcx->safeBagCount + 1) * sizeof
(sec_PKCS12SafeBag *), (p12dcx->safeBagCount + 2) * sizeof
(sec_PKCS12SafeBag *))
282 sec_PKCS12SafeBag *, p12dcx->safeBagCount + 1,(sec_PKCS12SafeBag * *)PORT_ArenaGrow_Util((p12dcx->arena)
, (p12dcx->safeBags), (p12dcx->safeBagCount + 1) * sizeof
(sec_PKCS12SafeBag *), (p12dcx->safeBagCount + 2) * sizeof
(sec_PKCS12SafeBag *))
283 p12dcx->safeBagCount + 2)(sec_PKCS12SafeBag * *)PORT_ArenaGrow_Util((p12dcx->arena)
, (p12dcx->safeBags), (p12dcx->safeBagCount + 1) * sizeof
(sec_PKCS12SafeBag *), (p12dcx->safeBagCount + 2) * sizeof
(sec_PKCS12SafeBag *))
;
284
285 if (!p12dcx->safeBags) {
286 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
287 goto loser;
288 }
289
290 /* append the bag to the end of the list and update the reference
291 * in the safeContentsCtx.
292 */
293 p12dcx->safeBags[p12dcx->safeBagCount] =
294 safeContentsCtx->currentSafeBag =
295 PORT_ArenaZNew(p12dcx->arena, sec_PKCS12SafeBag)(sec_PKCS12SafeBag *)PORT_ArenaZAlloc_Util(p12dcx->arena, sizeof
(sec_PKCS12SafeBag))
;
296 if (!safeContentsCtx->currentSafeBag) {
297 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
298 goto loser;
299 }
300 p12dcx->safeBags[++p12dcx->safeBagCount] = NULL((void*)0);
301
302 safeContentsCtx->currentSafeBag->slot = safeContentsCtx->p12dcx->slot;
303 safeContentsCtx->currentSafeBag->pwitem = safeContentsCtx->p12dcx->pwitem;
304 safeContentsCtx->currentSafeBag->swapUnicodeBytes =
305 safeContentsCtx->p12dcx->swapUnicodeBytes;
306 safeContentsCtx->currentSafeBag->arena = safeContentsCtx->p12dcx->arena;
307 safeContentsCtx->currentSafeBag->tokenCAs =
308 safeContentsCtx->p12dcx->tokenCAs;
309
310 PORT_ArenaUnmarkPORT_ArenaUnmark_Util(p12dcx->arena, mark);
311 return SECSuccess;
312
313loser:
314
315 /* if an error occurred, release the memory and set the error flag
316 * the only possible errors triggered by this function are memory
317 * related.
318 */
319 if (mark) {
320 PORT_ArenaReleasePORT_ArenaRelease_Util(p12dcx->arena, mark);
321 }
322
323 p12dcx->error = PR_TRUE1;
324 return SECFailure;
325}
326
327/* A wrapper for updating the ASN1 context in which a safeBag is
328 * being decoded. This function is called as a callback from
329 * secasn1d when decoding SafeContents structures.
330 */
331static void
332sec_pkcs12_decoder_safe_bag_update(void *arg, const char *data,
333 unsigned long len, int depth,
334 SEC_ASN1EncodingPart data_kind)
335{
336 sec_PKCS12SafeContentsContext *safeContentsCtx =
337 (sec_PKCS12SafeContentsContext *)arg;
338 SEC_PKCS12DecoderContext *p12dcx;
339 SECStatus rv;
340
341 if (!safeContentsCtx || !safeContentsCtx->p12dcx || !safeContentsCtx->currentSafeBagA1Dcx) {
342 return;
343 }
344 p12dcx = safeContentsCtx->p12dcx;
345
346 /* make sure that there are no errors and we are not skipping the current safeBag */
347 if (p12dcx->error || safeContentsCtx->skipCurrentSafeBag) {
348 goto loser;
349 }
350
351 rv = SEC_ASN1DecoderUpdateSEC_ASN1DecoderUpdate_Util(safeContentsCtx->currentSafeBagA1Dcx, data, len);
352 if (rv != SECSuccess) {
353 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
354 p12dcx->error = PR_TRUE1;
355 goto loser;
356 }
357
358 /* The update may have set safeContentsCtx->skipCurrentSafeBag, and we
359 * may not get another opportunity to clean up the decoder context.
360 */
361 if (safeContentsCtx->skipCurrentSafeBag) {
362 goto loser;
363 }
364
365 return;
366
367loser:
368 /* Finish the decoder context. Because there
369 * is not a way of returning an error message, it may be worth
370 * while to do a check higher up and finish any decoding contexts
371 * that are still open.
372 */
373 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(safeContentsCtx->currentSafeBagA1Dcx);
374 safeContentsCtx->currentSafeBagA1Dcx = NULL((void*)0);
375 return;
376}
377
378/* notify function for decoding safeBags. This function is
379 * used to filter safeBag types which are not supported,
380 * initiate the decoding of nested safe contents, and decode
381 * safeBags in general. this function is set when the decoder
382 * context for the safeBag is first created.
383 */
384static void
385sec_pkcs12_decoder_safe_bag_notify(void *arg, PRBool before,
386 void *dest, int real_depth)
387{
388 sec_PKCS12SafeContentsContext *safeContentsCtx =
389 (sec_PKCS12SafeContentsContext *)arg;
390 SEC_PKCS12DecoderContext *p12dcx;
391 sec_PKCS12SafeBag *bag;
392 PRBool after;
393
394 /* if an error is encountered, return */
395 if (!safeContentsCtx || !safeContentsCtx->p12dcx ||
396 safeContentsCtx->p12dcx->error) {
397 return;
398 }
399 p12dcx = safeContentsCtx->p12dcx;
400
401 /* to make things more readable */
402 if (before)
403 after = PR_FALSE0;
404 else
405 after = PR_TRUE1;
406
407 /* have we determined the safeBagType yet? */
408 bag = safeContentsCtx->currentSafeBag;
409 if (bag->bagTypeTag == NULL((void*)0)) {
410 if (after && (dest == &(bag->safeBagType))) {
411 bag->bagTypeTag = SECOID_FindOIDSECOID_FindOID_Util(&(bag->safeBagType));
412 if (bag->bagTypeTag == NULL((void*)0)) {
413 p12dcx->error = PR_TRUE1;
414 p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
415 }
416 }
417 return;
418 }
419
420 /* process the safeBag depending on it's type. those
421 * which we do not support, are ignored. we start a decoding
422 * context for a nested safeContents.
423 */
424 switch (bag->bagTypeTag->offset) {
425 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
426 case SEC_OID_PKCS12_V1_CERT_BAG_ID:
427 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
428 break;
429 case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID:
430 /* if we are just starting to decode the safeContents, initialize
431 * a new safeContentsCtx to process it.
432 */
433 if (before && (dest == &(bag->safeBagContent))) {
434 sec_pkcs12_decoder_begin_nested_safe_contents(safeContentsCtx);
435 } else if (after && (dest == &(bag->safeBagContent))) {
436 /* clean up the nested decoding */
437 sec_pkcs12_decoder_finish_nested_safe_contents(safeContentsCtx);
438 }
439 break;
440 case SEC_OID_PKCS12_V1_CRL_BAG_ID:
441 case SEC_OID_PKCS12_V1_SECRET_BAG_ID:
442 default:
443 /* skip any safe bag types we don't understand or handle */
444 safeContentsCtx->skipCurrentSafeBag = PR_TRUE1;
445 break;
446 }
447
448 return;
449}
450
451/* notify function for decoding safe contents. each entry in the
452 * safe contents is a safeBag which needs to be allocated and
453 * the decoding context initialized at the beginning and then
454 * the context needs to be closed and finished at the end.
455 *
456 * this function is set when the safeContents decode context is
457 * initialized.
458 */
459static void
460sec_pkcs12_decoder_safe_contents_notify(void *arg, PRBool before,
461 void *dest, int real_depth)
462{
463 sec_PKCS12SafeContentsContext *safeContentsCtx =
464 (sec_PKCS12SafeContentsContext *)arg;
465 SEC_PKCS12DecoderContext *p12dcx;
466 SECStatus rv;
467
468 /* if there is an error we don't want to continue processing,
469 * just return and keep going.
470 */
471 if (!safeContentsCtx || !safeContentsCtx->p12dcx ||
472 safeContentsCtx->p12dcx->error) {
473 return;
474 }
475 p12dcx = safeContentsCtx->p12dcx;
476
477 /* if we are done with the current safeBag, then we need to
478 * finish the context and set the state variables appropriately.
479 */
480 if (!before) {
481 SEC_ASN1DecoderClearFilterProcSEC_ASN1DecoderClearFilterProc_Util(safeContentsCtx->safeContentsA1Dcx);
482 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(safeContentsCtx->currentSafeBagA1Dcx);
483 safeContentsCtx->currentSafeBagA1Dcx = NULL((void*)0);
484 safeContentsCtx->skipCurrentSafeBag = PR_FALSE0;
485 } else {
486 /* we are starting a new safe bag. we need to allocate space
487 * for the bag and initialize the decoding context.
488 */
489 rv = sec_pkcs12_decoder_init_new_safe_bag(safeContentsCtx);
490 if (rv != SECSuccess) {
491 goto loser;
492 }
493
494 /* set up the decoder context */
495 safeContentsCtx->currentSafeBagA1Dcx =
496 SEC_ASN1DecoderStartSEC_ASN1DecoderStart_Util(p12dcx->arena,
497 safeContentsCtx->currentSafeBag,
498 sec_PKCS12SafeBagTemplate);
499 if (!safeContentsCtx->currentSafeBagA1Dcx) {
500 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
501 goto loser;
502 }
503
504 /* set the notify and filter procs so that the safe bag
505 * data gets sent to the proper location when decoding.
506 */
507 SEC_ASN1DecoderSetNotifyProcSEC_ASN1DecoderSetNotifyProc_Util(safeContentsCtx->currentSafeBagA1Dcx,
508 sec_pkcs12_decoder_safe_bag_notify,
509 safeContentsCtx);
510 SEC_ASN1DecoderSetFilterProcSEC_ASN1DecoderSetFilterProc_Util(safeContentsCtx->safeContentsA1Dcx,
511 sec_pkcs12_decoder_safe_bag_update,
512 safeContentsCtx, PR_TRUE1);
513 }
514
515 return;
516
517loser:
518 /* in the event of an error, we want to close the decoding
519 * context and clear the filter and notify procedures.
520 */
521 p12dcx->error = PR_TRUE1;
522
523 if (safeContentsCtx->currentSafeBagA1Dcx) {
524 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(safeContentsCtx->currentSafeBagA1Dcx);
525 safeContentsCtx->currentSafeBagA1Dcx = NULL((void*)0);
526 }
527
528 SEC_ASN1DecoderClearNotifyProcSEC_ASN1DecoderClearNotifyProc_Util(safeContentsCtx->safeContentsA1Dcx);
529 SEC_ASN1DecoderClearFilterProcSEC_ASN1DecoderClearFilterProc_Util(safeContentsCtx->safeContentsA1Dcx);
530
531 return;
532}
533
534/* initialize the safeContents for decoding. this routine
535 * is used for authenticatedSafes as well as nested safeContents.
536 */
537static sec_PKCS12SafeContentsContext *
538sec_pkcs12_decoder_safe_contents_init_decode(SEC_PKCS12DecoderContext *p12dcx,
539 PRBool nestedSafe)
540{
541 sec_PKCS12SafeContentsContext *safeContentsCtx = NULL((void*)0);
542 const SEC_ASN1Template *theTemplate;
543
544 if (!p12dcx || p12dcx->error) {
545 return NULL((void*)0);
546 }
547
548 /* allocate a new safeContents list or grow the existing list and
549 * append the new safeContents onto the end.
550 */
551 p12dcx->safeContentsList = (!p12dcx->safeContentsCnt)
552 ? PORT_ArenaZNewArray(p12dcx->arena, sec_PKCS12SafeContentsContext *, 2)(sec_PKCS12SafeContentsContext * *)PORT_ArenaZAlloc_Util(p12dcx
->arena, sizeof(sec_PKCS12SafeContentsContext *) * (2))
553 : PORT_ArenaGrowArray(p12dcx->arena, p12dcx->safeContentsList,(sec_PKCS12SafeContentsContext * *)PORT_ArenaGrow_Util((p12dcx
->arena), (p12dcx->safeContentsList), (1 + p12dcx->safeContentsCnt
) * sizeof(sec_PKCS12SafeContentsContext *), (2 + p12dcx->
safeContentsCnt) * sizeof(sec_PKCS12SafeContentsContext *))
554 sec_PKCS12SafeContentsContext *,(sec_PKCS12SafeContentsContext * *)PORT_ArenaGrow_Util((p12dcx
->arena), (p12dcx->safeContentsList), (1 + p12dcx->safeContentsCnt
) * sizeof(sec_PKCS12SafeContentsContext *), (2 + p12dcx->
safeContentsCnt) * sizeof(sec_PKCS12SafeContentsContext *))
555 1 + p12dcx->safeContentsCnt,(sec_PKCS12SafeContentsContext * *)PORT_ArenaGrow_Util((p12dcx
->arena), (p12dcx->safeContentsList), (1 + p12dcx->safeContentsCnt
) * sizeof(sec_PKCS12SafeContentsContext *), (2 + p12dcx->
safeContentsCnt) * sizeof(sec_PKCS12SafeContentsContext *))
556 2 + p12dcx->safeContentsCnt)(sec_PKCS12SafeContentsContext * *)PORT_ArenaGrow_Util((p12dcx
->arena), (p12dcx->safeContentsList), (1 + p12dcx->safeContentsCnt
) * sizeof(sec_PKCS12SafeContentsContext *), (2 + p12dcx->
safeContentsCnt) * sizeof(sec_PKCS12SafeContentsContext *))
;
557
558 if (!p12dcx->safeContentsList) {
559 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
560 goto loser;
561 }
562
563 p12dcx->safeContentsList[p12dcx->safeContentsCnt] = safeContentsCtx =
564 PORT_ArenaZNew(p12dcx->arena, sec_PKCS12SafeContentsContext)(sec_PKCS12SafeContentsContext *)PORT_ArenaZAlloc_Util(p12dcx
->arena, sizeof(sec_PKCS12SafeContentsContext))
;
565 if (!p12dcx->safeContentsList[p12dcx->safeContentsCnt]) {
566 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
567 goto loser;
568 }
569 p12dcx->safeContentsList[++p12dcx->safeContentsCnt] = NULL((void*)0);
570
571 /* set up the state variables */
572 safeContentsCtx->p12dcx = p12dcx;
573 safeContentsCtx->arena = p12dcx->arena;
574
575 /* begin the decoding -- the template is based on whether we are
576 * decoding a nested safeContents or not.
577 */
578 if (nestedSafe == PR_TRUE1) {
579 theTemplate = sec_PKCS12NestedSafeContentsDecodeTemplate;
580 } else {
581 theTemplate = sec_PKCS12SafeContentsDecodeTemplate;
582 }
583
584 /* start the decoder context */
585 safeContentsCtx->safeContentsA1Dcx = SEC_ASN1DecoderStartSEC_ASN1DecoderStart_Util(p12dcx->arena,
586 &safeContentsCtx->safeContents,
587 theTemplate);
588
589 if (!safeContentsCtx->safeContentsA1Dcx) {
590 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
591 goto loser;
592 }
593
594 /* set the safeContents notify procedure to look for
595 * and start the decode of safeBags.
596 */
597 SEC_ASN1DecoderSetNotifyProcSEC_ASN1DecoderSetNotifyProc_Util(safeContentsCtx->safeContentsA1Dcx,
598 sec_pkcs12_decoder_safe_contents_notify,
599 safeContentsCtx);
600
601 return safeContentsCtx;
602
603loser:
604 /* in the case of an error, we want to finish the decoder
605 * context and set the error flag.
606 */
607 if (safeContentsCtx && safeContentsCtx->safeContentsA1Dcx) {
608 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(safeContentsCtx->safeContentsA1Dcx);
609 safeContentsCtx->safeContentsA1Dcx = NULL((void*)0);
610 }
611
612 p12dcx->error = PR_TRUE1;
613
614 return NULL((void*)0);
615}
616
617/* wrapper for updating safeContents. this is set as the filter of
618 * safeBag when there is a nested safeContents.
619 */
620static void
621sec_pkcs12_decoder_nested_safe_contents_update(void *arg, const char *buf,
622 unsigned long len, int depth,
623 SEC_ASN1EncodingPart data_kind)
624{
625 sec_PKCS12SafeContentsContext *safeContentsCtx =
626 (sec_PKCS12SafeContentsContext *)arg;
627 SEC_PKCS12DecoderContext *p12dcx;
628 SECStatus rv;
629
630 /* check for an error */
631 if (!safeContentsCtx || !safeContentsCtx->p12dcx ||
632 safeContentsCtx->p12dcx->error || !safeContentsCtx->safeContentsA1Dcx) {
633 return;
634 }
635
636 /* no need to update if no data sent in */
637 if (!len || !buf) {
638 return;
639 }
640
641 /* update the decoding context */
642 p12dcx = safeContentsCtx->p12dcx;
643 rv = SEC_ASN1DecoderUpdateSEC_ASN1DecoderUpdate_Util(safeContentsCtx->safeContentsA1Dcx, buf, len);
644 if (rv != SECSuccess) {
645 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
646 goto loser;
647 }
648
649 return;
650
651loser:
652 /* handle any errors. If a decoding context is open, close it. */
653 p12dcx->error = PR_TRUE1;
654 if (safeContentsCtx->safeContentsA1Dcx) {
655 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(safeContentsCtx->safeContentsA1Dcx);
656 safeContentsCtx->safeContentsA1Dcx = NULL((void*)0);
657 }
658}
659
660/* whenever a new safeContentsSafeBag is encountered, we need
661 * to init a safeContentsContext.
662 */
663static SECStatus
664sec_pkcs12_decoder_begin_nested_safe_contents(sec_PKCS12SafeContentsContext
665 *safeContentsCtx)
666{
667 /* check for an error */
668 if (!safeContentsCtx || !safeContentsCtx->p12dcx ||
669 safeContentsCtx->p12dcx->error) {
670 return SECFailure;
671 }
672
673 safeContentsCtx->nestedSafeContentsCtx =
674 sec_pkcs12_decoder_safe_contents_init_decode(safeContentsCtx->p12dcx,
675 PR_TRUE1);
676 if (!safeContentsCtx->nestedSafeContentsCtx) {
677 return SECFailure;
678 }
679
680 /* set up new filter proc */
681 SEC_ASN1DecoderSetNotifyProcSEC_ASN1DecoderSetNotifyProc_Util(
682 safeContentsCtx->nestedSafeContentsCtx->safeContentsA1Dcx,
683 sec_pkcs12_decoder_safe_contents_notify,
684 safeContentsCtx->nestedSafeContentsCtx);
685
686 SEC_ASN1DecoderSetFilterProcSEC_ASN1DecoderSetFilterProc_Util(safeContentsCtx->currentSafeBagA1Dcx,
687 sec_pkcs12_decoder_nested_safe_contents_update,
688 safeContentsCtx->nestedSafeContentsCtx,
689 PR_TRUE1);
690
691 return SECSuccess;
692}
693
694/* when the safeContents is done decoding, we need to reset the
695 * proper filter and notify procs and close the decoding context
696 */
697static SECStatus
698sec_pkcs12_decoder_finish_nested_safe_contents(sec_PKCS12SafeContentsContext
699 *safeContentsCtx)
700{
701 /* check for error */
702 if (!safeContentsCtx || !safeContentsCtx->p12dcx ||
703 safeContentsCtx->p12dcx->error) {
704 return SECFailure;
705 }
706
707 /* clean up */
708 SEC_ASN1DecoderClearFilterProcSEC_ASN1DecoderClearFilterProc_Util(safeContentsCtx->currentSafeBagA1Dcx);
709 SEC_ASN1DecoderClearNotifyProcSEC_ASN1DecoderClearNotifyProc_Util(
710 safeContentsCtx->nestedSafeContentsCtx->safeContentsA1Dcx);
711 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(
712 safeContentsCtx->nestedSafeContentsCtx->safeContentsA1Dcx);
713 safeContentsCtx->nestedSafeContentsCtx->safeContentsA1Dcx = NULL((void*)0);
714 safeContentsCtx->nestedSafeContentsCtx = NULL((void*)0);
715
716 return SECSuccess;
717}
718
719/* wrapper for updating safeContents. This is used when decoding
720 * the nested safeContents and any authenticatedSafes.
721 */
722static void
723sec_pkcs12_decoder_safe_contents_callback(void *arg, const char *buf,
724 unsigned long len)
725{
726 SECStatus rv;
727 sec_PKCS12SafeContentsContext *safeContentsCtx =
728 (sec_PKCS12SafeContentsContext *)arg;
729 SEC_PKCS12DecoderContext *p12dcx;
730
731 /* check for error */
732 if (!safeContentsCtx || !safeContentsCtx->p12dcx ||
733 safeContentsCtx->p12dcx->error || !safeContentsCtx->safeContentsA1Dcx) {
734 return;
735 }
736 p12dcx = safeContentsCtx->p12dcx;
737
738 /* update the decoder */
739 rv = SEC_ASN1DecoderUpdateSEC_ASN1DecoderUpdate_Util(safeContentsCtx->safeContentsA1Dcx, buf, len);
740 if (rv != SECSuccess) {
741 /* if we fail while trying to decode a 'safe', it's probably because
742 * we didn't have the correct password. */
743 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_PASSWORD);
744 p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
745 SEC_PKCS7DecoderAbort(p12dcx->currentASafeP7Dcx, SEC_ERROR_BAD_PASSWORD);
746 goto loser;
747 }
748
749 return;
750
751loser:
752 /* set the error and finish the context */
753 p12dcx->error = PR_TRUE1;
754 if (safeContentsCtx->safeContentsA1Dcx) {
755 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(safeContentsCtx->safeContentsA1Dcx);
756 safeContentsCtx->safeContentsA1Dcx = NULL((void*)0);
757 }
758
759 return;
760}
761
762/* this is a wrapper for the ASN1 decoder to call SEC_PKCS7DecoderUpdate
763 */
764static void
765sec_pkcs12_decoder_wrap_p7_update(void *arg, const char *data,
766 unsigned long len, int depth,
767 SEC_ASN1EncodingPart data_kind)
768{
769 SEC_PKCS7DecoderContext *p7dcx = (SEC_PKCS7DecoderContext *)arg;
770
771 SEC_PKCS7DecoderUpdate(p7dcx, data, len);
772}
773
774/* notify function for decoding aSafes. at the beginning,
775 * of an authenticatedSafe, we start a decode of a safeContents.
776 * at the end, we clean up the safeContents decoder context and
777 * reset state variables
778 */
779static void
780sec_pkcs12_decoder_asafes_notify(void *arg, PRBool before, void *dest,
781 int real_depth)
782{
783 SEC_PKCS12DecoderContext *p12dcx;
784 sec_PKCS12SafeContentsContext *safeContentsCtx;
785
786 /* make sure no error occurred. */
787 p12dcx = (SEC_PKCS12DecoderContext *)arg;
788 if (!p12dcx || p12dcx->error) {
789 return;
790 }
791
792 if (before) {
793
794 /* init a new safeContentsContext */
795 safeContentsCtx = sec_pkcs12_decoder_safe_contents_init_decode(p12dcx,
796 PR_FALSE0);
797 if (!safeContentsCtx) {
798 goto loser;
799 }
800
801 /* initiate the PKCS7ContentInfo decode */
802 p12dcx->currentASafeP7Dcx = SEC_PKCS7DecoderStart(
803 sec_pkcs12_decoder_safe_contents_callback,
804 safeContentsCtx,
805 p12dcx->pwfn, p12dcx->pwfnarg,
806 sec_pkcs12_decoder_get_decrypt_key, p12dcx,
807 sec_pkcs12_decoder_decryption_allowed);
808 if (!p12dcx->currentASafeP7Dcx) {
809 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
810 goto loser;
811 }
812 SEC_ASN1DecoderSetFilterProcSEC_ASN1DecoderSetFilterProc_Util(p12dcx->aSafeA1Dcx,
813 sec_pkcs12_decoder_wrap_p7_update,
814 p12dcx->currentASafeP7Dcx, PR_TRUE1);
815 }
816
817 if (!before) {
818 /* if one is being decoded, finish the decode */
819 if (p12dcx->currentASafeP7Dcx != NULL((void*)0)) {
820 SEC_PKCS7ContentInfo *cinfo;
821 unsigned int cnt = p12dcx->safeContentsCnt - 1;
822 safeContentsCtx = p12dcx->safeContentsList[cnt];
823 if (safeContentsCtx->safeContentsA1Dcx) {
824 SEC_ASN1DecoderClearFilterProcSEC_ASN1DecoderClearFilterProc_Util(p12dcx->aSafeA1Dcx);
825 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(safeContentsCtx->safeContentsA1Dcx);
826 safeContentsCtx->safeContentsA1Dcx = NULL((void*)0);
827 }
828 cinfo = SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx);
829 SEC_ASN1DecoderClearFilterProcSEC_ASN1DecoderClearFilterProc_Util(p12dcx->aSafeA1Dcx);
830 p12dcx->currentASafeP7Dcx = NULL((void*)0);
831 if (!cinfo) {
832 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
833 goto loser;
834 }
835 SEC_PKCS7DestroyContentInfo(cinfo); /* don't leak it */
836 }
837 }
838
839 return;
840
841loser:
842 /* set the error flag */
843 p12dcx->error = PR_TRUE1;
844 return;
845}
846
847/* wrapper for updating asafes decoding context. this function
848 * writes data being decoded to disk, so that a mac can be computed
849 * later.
850 */
851static void
852sec_pkcs12_decoder_asafes_callback(void *arg, const char *buf,
853 unsigned long len)
854{
855 SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg;
856 SECStatus rv;
857
858 if (!p12dcx || p12dcx->error) {
859 return;
860 }
861
862 /* update the context */
863 rv = SEC_ASN1DecoderUpdateSEC_ASN1DecoderUpdate_Util(p12dcx->aSafeA1Dcx, buf, len);
864 if (rv != SECSuccess) {
865 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
866 p12dcx->error = PR_TRUE1;
867 goto loser;
868 }
869
870 /* if we are writing to a file, write out the new information */
871 if (p12dcx->dWrite) {
872 unsigned long writeLen = (*p12dcx->dWrite)(p12dcx->dArg,
873 (unsigned char *)buf, len);
874 if (writeLen != len) {
875 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
876 goto loser;
877 }
878 }
879
880 return;
881
882loser:
883 /* set the error flag */
884 p12dcx->error = PR_TRUE1;
885 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(p12dcx->aSafeA1Dcx);
886 p12dcx->aSafeA1Dcx = NULL((void*)0);
887
888 return;
889}
890
891/* start the decode of an authenticatedSafe contentInfo.
892 */
893static SECStatus
894sec_pkcs12_decode_start_asafes_cinfo(SEC_PKCS12DecoderContext *p12dcx)
895{
896 if (!p12dcx || p12dcx->error) {
897 return SECFailure;
898 }
899
900 /* start the decode context */
901 p12dcx->aSafeA1Dcx = SEC_ASN1DecoderStartSEC_ASN1DecoderStart_Util(p12dcx->arena,
902 &p12dcx->authSafe,
903 sec_PKCS12AuthenticatedSafeTemplate);
904 if (!p12dcx->aSafeA1Dcx) {
905 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
906 goto loser;
907 }
908
909 /* set the notify function */
910 SEC_ASN1DecoderSetNotifyProcSEC_ASN1DecoderSetNotifyProc_Util(p12dcx->aSafeA1Dcx,
911 sec_pkcs12_decoder_asafes_notify, p12dcx);
912
913 /* begin the authSafe decoder context */
914 p12dcx->aSafeP7Dcx = SEC_PKCS7DecoderStart(
915 sec_pkcs12_decoder_asafes_callback, p12dcx,
916 p12dcx->pwfn, p12dcx->pwfnarg, NULL((void*)0), NULL((void*)0), NULL((void*)0));
917 if (!p12dcx->aSafeP7Dcx) {
918 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
919 goto loser;
920 }
921
922 /* open the temp file for writing, if the digest functions were set */
923 if (p12dcx->dOpen && (*p12dcx->dOpen)(p12dcx->dArg, PR_FALSE0) != SECSuccess) {
924 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
925 goto loser;
926 }
927 /* dOpen(dArg, PR_FALSE) creates the temp file */
928 p12dcx->dIsOpen = PR_TRUE1;
929
930 return SECSuccess;
931
932loser:
933 p12dcx->error = PR_TRUE1;
934
935 if (p12dcx->aSafeA1Dcx) {
936 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(p12dcx->aSafeA1Dcx);
937 p12dcx->aSafeA1Dcx = NULL((void*)0);
938 }
939
940 if (p12dcx->aSafeP7Dcx) {
941 SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);
942 p12dcx->aSafeP7Dcx = NULL((void*)0);
943 }
944
945 return SECFailure;
946}
947
948/* wrapper for updating the safeContents. this function is used as
949 * a filter for the pfx when decoding the authenticated safes
950 */
951static void
952sec_pkcs12_decode_asafes_cinfo_update(void *arg, const char *buf,
953 unsigned long len, int depth,
954 SEC_ASN1EncodingPart data_kind)
955{
956 SEC_PKCS12DecoderContext *p12dcx;
957 SECStatus rv;
958
959 p12dcx = (SEC_PKCS12DecoderContext *)arg;
960 if (!p12dcx || p12dcx->error) {
961 return;
962 }
963
964 /* update the safeContents decoder */
965 rv = SEC_PKCS7DecoderUpdate(p12dcx->aSafeP7Dcx, buf, len);
966 if (rv != SECSuccess) {
967 p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
968 goto loser;
969 }
970
971 return;
972
973loser:
974
975 /* did we find an error? if so, close the context and set the
976 * error flag.
977 */
978 SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);
979 p12dcx->aSafeP7Dcx = NULL((void*)0);
980 p12dcx->error = PR_TRUE1;
981}
982
983/* notify procedure used while decoding the pfx. When we encounter
984 * the authSafes, we want to trigger the decoding of authSafes as well
985 * as when we encounter the macData, trigger the decoding of it. we do
986 * this because we we are streaming the decoder and not decoding in place.
987 * the pfx which is the destination, only has the version decoded into it.
988 */
989static void
990sec_pkcs12_decoder_pfx_notify_proc(void *arg, PRBool before, void *dest,
991 int real_depth)
992{
993 SECStatus rv;
994 SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg;
995
996 /* if an error occurs, clear the notifyProc and the filterProc
997 * and continue.
998 */
999 if (p12dcx->error) {
1000 SEC_ASN1DecoderClearNotifyProcSEC_ASN1DecoderClearNotifyProc_Util(p12dcx->pfxA1Dcx);
1001 SEC_ASN1DecoderClearFilterProcSEC_ASN1DecoderClearFilterProc_Util(p12dcx->pfxA1Dcx);
1002 return;
1003 }
1004
1005 if (before && (dest == &p12dcx->pfx.encodedAuthSafe)) {
1006
1007 /* we want to make sure this is a version we support */
1008 if (!sec_pkcs12_proper_version(&p12dcx->pfx)) {
1009 p12dcx->errorValue = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION;
1010 goto loser;
1011 }
1012
1013 /* start the decode of the aSafes cinfo... */
1014 rv = sec_pkcs12_decode_start_asafes_cinfo(p12dcx);
1015 if (rv != SECSuccess) {
1016 goto loser;
1017 }
1018
1019 /* set the filter proc to update the authenticated safes. */
1020 SEC_ASN1DecoderSetFilterProcSEC_ASN1DecoderSetFilterProc_Util(p12dcx->pfxA1Dcx,
1021 sec_pkcs12_decode_asafes_cinfo_update,
1022 p12dcx, PR_TRUE1);
1023 }
1024
1025 if (!before && (dest == &p12dcx->pfx.encodedAuthSafe)) {
1026
1027 /* we are done decoding the authenticatedSafes, so we need to
1028 * finish the decoderContext and clear the filter proc
1029 * and close the hmac callback, if present
1030 */
1031 p12dcx->aSafeCinfo = SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);
1032 p12dcx->aSafeP7Dcx = NULL((void*)0);
1033 if (!p12dcx->aSafeCinfo) {
1034 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
1035 goto loser;
1036 }
1037 SEC_ASN1DecoderClearFilterProcSEC_ASN1DecoderClearFilterProc_Util(p12dcx->pfxA1Dcx);
1038 if (p12dcx->dClose && ((*p12dcx->dClose)(p12dcx->dArg, PR_FALSE0) != SECSuccess)) {
1039 p12dcx->errorValue = PORT_GetErrorPORT_GetError_Util();
1040 goto loser;
1041 }
1042 }
1043
1044 return;
1045
1046loser:
1047 p12dcx->error = PR_TRUE1;
1048}
1049
1050/* default implementations of the open/close/read/write functions for
1051 SEC_PKCS12DecoderStart
1052*/
1053
1054#define DEFAULT_TEMP_SIZE4096 4096
1055
1056static SECStatus
1057p12u_DigestOpen(void *arg, PRBool readData)
1058{
1059 SEC_PKCS12DecoderContext *p12cxt = arg;
1060
1061 p12cxt->currentpos = 0;
1062
1063 if (PR_FALSE0 == readData) {
1064 /* allocate an initial buffer */
1065 p12cxt->filesize = 0;
1066 p12cxt->allocated = DEFAULT_TEMP_SIZE4096;
1067 p12cxt->buffer = PORT_AllocPORT_Alloc_Util(DEFAULT_TEMP_SIZE4096);
1068 PR_ASSERT(p12cxt->buffer)((p12cxt->buffer) ? ((void)0) : PR_Assert("p12cxt->buffer"
, "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c", 1068)
)
;
1069 } else {
1070 PR_ASSERT(p12cxt->buffer)((p12cxt->buffer) ? ((void)0) : PR_Assert("p12cxt->buffer"
, "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c", 1070)
)
;
1071 if (!p12cxt->buffer) {
1072 return SECFailure; /* no data to read */
1073 }
1074 }
1075
1076 return SECSuccess;
1077}
1078
1079static SECStatus
1080p12u_DigestClose(void *arg, PRBool removeFile)
1081{
1082 SEC_PKCS12DecoderContext *p12cxt = arg;
1083
1084 PR_ASSERT(p12cxt)((p12cxt) ? ((void)0) : PR_Assert("p12cxt", "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c"
, 1084))
;
1085 if (!p12cxt) {
1086 return SECFailure;
1087 }
1088 p12cxt->currentpos = 0;
1089
1090 if (PR_TRUE1 == removeFile) {
1091 PR_ASSERT(p12cxt->buffer)((p12cxt->buffer) ? ((void)0) : PR_Assert("p12cxt->buffer"
, "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c", 1091)
)
;
1092 if (!p12cxt->buffer) {
1093 return SECFailure;
1094 }
1095 if (p12cxt->buffer) {
1096 PORT_FreePORT_Free_Util(p12cxt->buffer);
1097 p12cxt->buffer = NULL((void*)0);
1098 p12cxt->allocated = 0;
1099 p12cxt->filesize = 0;
1100 }
1101 }
1102
1103 return SECSuccess;
1104}
1105
1106static int
1107p12u_DigestRead(void *arg, unsigned char *buf, unsigned long len)
1108{
1109 int toread;
1110 SEC_PKCS12DecoderContext *p12cxt = arg;
1111
1112 if (!buf || len == 0 || !p12cxt->buffer) {
1113 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1114 return -1;
1115 }
1116
1117 /* Clamp `len` to the bytes left in the buffer. toread is positive here,
1118 * so the comparison stays unsigned and `len` cannot wrap. */
1119 toread = p12cxt->filesize - p12cxt->currentpos;
1120 if (toread <= 0) {
1121 return 0;
1122 }
1123 if (len < (unsigned long)toread) {
1124 toread = (int)len;
1125 }
1126
1127 memcpy(buf, (char *)p12cxt->buffer + p12cxt->currentpos, toread);
1128 p12cxt->currentpos += toread;
1129 return toread;
1130}
1131
1132static int
1133p12u_DigestWrite(void *arg, unsigned char *buf, unsigned long len)
1134{
1135 SEC_PKCS12DecoderContext *p12cxt = arg;
1136
1137 if (!buf || len == 0) {
1138 return -1;
1139 }
1140
1141 /* The buffer position counters are signed PRInt32. Reject any write
1142 * whose length would not fit so that `len` cannot overflow or wrap them
1143 * on LLP64 platforms where unsigned long is 32-bit (Win64). */
1144 if (len > (unsigned long)(PR_INT32_MAX2147483647 - p12cxt->currentpos)) {
1145 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1146 return -1;
1147 }
1148
1149 if (p12cxt->currentpos + (PRInt32)len > p12cxt->filesize) {
1150 p12cxt->filesize = p12cxt->currentpos + (PRInt32)len;
1151 } else {
1152 p12cxt->filesize += (PRInt32)len;
1153 }
1154 if (p12cxt->filesize > p12cxt->allocated) {
1155 void *newbuffer;
1156 size_t newsize = p12cxt->filesize + DEFAULT_TEMP_SIZE4096;
1157 newbuffer = PORT_ReallocPORT_Realloc_Util(p12cxt->buffer, newsize);
1158 if (NULL((void*)0) == newbuffer) {
1159 return -1; /* can't extend the buffer */
1160 }
1161 p12cxt->buffer = newbuffer;
1162 p12cxt->allocated = newsize;
1163 }
1164 PR_ASSERT(p12cxt->buffer)((p12cxt->buffer) ? ((void)0) : PR_Assert("p12cxt->buffer"
, "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c", 1164)
)
;
1165 memcpy((char *)p12cxt->buffer + p12cxt->currentpos, buf, len);
1166 p12cxt->currentpos += len;
1167 return len;
1168}
1169
1170/* SEC_PKCS12DecoderStart
1171 * Creates a decoder context for decoding a PKCS 12 PDU objct.
1172 * This function sets up the initial decoding context for the
1173 * PFX and sets the needed state variables.
1174 *
1175 * pwitem - the password for the hMac and any encoded safes.
1176 * this should be changed to take a callback which retrieves
1177 * the password. it may be possible for different safes to
1178 * have different passwords. also, the password is already
1179 * in unicode. it should probably be converted down below via
1180 * a unicode conversion callback.
1181 * slot - the slot to import the dataa into should multiple slots
1182 * be supported based on key type and cert type?
1183 * dOpen, dClose, dRead, dWrite - digest routines for writing data
1184 * to a file so it could be read back and the hmac recomputed
1185 * and verified. doesn't seem to be a way for both encoding
1186 * and decoding to be single pass, thus the need for these
1187 * routines.
1188 * dArg - the argument for dOpen, etc.
1189 *
1190 * if NULL == dOpen == dClose == dRead == dWrite == dArg, then default
1191 * implementations using a memory buffer are used
1192 *
1193 * This function returns the decoder context, if it was successful.
1194 * Otherwise, null is returned.
1195 */
1196SEC_PKCS12DecoderContext *
1197SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx,
1198 digestOpenFn dOpen, digestCloseFn dClose,
1199 digestIOFn dRead, digestIOFn dWrite, void *dArg)
1200{
1201 SEC_PKCS12DecoderContext *p12dcx;
1202 PLArenaPool *arena;
1203 PRInt32 forceUnicode = PR_FALSE0;
1204 SECStatus rv;
1205
1206 arena = PORT_NewArenaPORT_NewArena_Util(2048); /* different size? */
1207 if (!arena) {
1208 return NULL((void*)0); /* error is already set */
1209 }
1210
1211 /* allocate the decoder context and set the state variables */
1212 p12dcx = PORT_ArenaZNew(arena, SEC_PKCS12DecoderContext)(SEC_PKCS12DecoderContext *)PORT_ArenaZAlloc_Util(arena, sizeof
(SEC_PKCS12DecoderContext))
;
1213 if (!p12dcx) {
1214 goto loser; /* error is already set */
1215 }
1216
1217 if (!dOpen && !dClose && !dRead && !dWrite && !dArg) {
1218 /* use default implementations */
1219 dOpen = p12u_DigestOpen;
1220 dClose = p12u_DigestClose;
1221 dRead = p12u_DigestRead;
1222 dWrite = p12u_DigestWrite;
1223 dArg = (void *)p12dcx;
1224 }
1225
1226 p12dcx->arena = arena;
1227 p12dcx->pwitem = pwitem;
1228 p12dcx->slot = (slot ? PK11_ReferenceSlot(slot)
1229 : PK11_GetInternalKeySlot());
1230 p12dcx->wincx = wincx;
1231 p12dcx->tokenCAs = SECPKCS12TargetTokenNoCAs;
1232#ifdef IS_LITTLE_ENDIAN1
1233 p12dcx->swapUnicodeBytes = PR_TRUE1;
1234#else
1235 p12dcx->swapUnicodeBytes = PR_FALSE0;
1236#endif
1237 rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c, &forceUnicode);
1238 if (rv != SECSuccess) {
1239 goto loser;
1240 }
1241 p12dcx->forceUnicode = forceUnicode;
1242 p12dcx->errorValue = 0;
1243 p12dcx->error = PR_FALSE0;
1244
1245 /* start the decoding of the PFX and set the notify proc
1246 * for the PFX item.
1247 */
1248 p12dcx->pfxA1Dcx = SEC_ASN1DecoderStartSEC_ASN1DecoderStart_Util(p12dcx->arena, &p12dcx->pfx,
1249 sec_PKCS12PFXItemTemplate);
1250 if (!p12dcx->pfxA1Dcx) {
1251 PK11_FreeSlot(p12dcx->slot);
1252 goto loser;
1253 }
1254
1255 SEC_ASN1DecoderSetNotifyProcSEC_ASN1DecoderSetNotifyProc_Util(p12dcx->pfxA1Dcx,
1256 sec_pkcs12_decoder_pfx_notify_proc,
1257 p12dcx);
1258
1259 /* set up digest functions */
1260 p12dcx->dOpen = dOpen;
1261 p12dcx->dWrite = dWrite;
1262 p12dcx->dClose = dClose;
1263 p12dcx->dRead = dRead;
1264 p12dcx->dArg = dArg;
1265 p12dcx->dIsOpen = PR_FALSE0;
1266
1267 p12dcx->keyList = NULL((void*)0);
1268 p12dcx->decitem.type = 0;
1269 p12dcx->decitem.der = NULL((void*)0);
1270 p12dcx->decitem.hasKey = PR_FALSE0;
1271 p12dcx->decitem.friendlyName = NULL((void*)0);
1272 p12dcx->iteration = 0;
1273
1274 return p12dcx;
1275
1276loser:
1277 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_TRUE1);
1278 return NULL((void*)0);
1279}
1280
1281SECStatus
1282SEC_PKCS12DecoderSetMaxElementLen(SEC_PKCS12DecoderContext *p12dcx,
1283 unsigned long maxLen)
1284{
1285 if (!p12dcx || p12dcx->error) {
1286 return SECFailure;
1287 }
1288 SEC_ASN1DecoderSetMaximumElementSize(p12dcx->pfxA1Dcx, maxLen);
1289 return SECSuccess;
1290}
1291
1292SECStatus
1293SEC_PKCS12DecoderSetTargetTokenCAs(SEC_PKCS12DecoderContext *p12dcx,
1294 SECPKCS12TargetTokenCAs tokenCAs)
1295{
1296 if (!p12dcx || p12dcx->error) {
1297 return SECFailure;
1298 }
1299 p12dcx->tokenCAs = tokenCAs;
1300 return SECSuccess;
1301}
1302
1303/* SEC_PKCS12DecoderUpdate
1304 * Streaming update sending more data to the decoder. If
1305 * an error occurs, SECFailure is returned.
1306 *
1307 * p12dcx - the decoder context
1308 * data, len - the data buffer and length of data to send to
1309 * the update functions.
1310 */
1311SECStatus
1312SEC_PKCS12DecoderUpdate(SEC_PKCS12DecoderContext *p12dcx,
1313 unsigned char *data, unsigned long len)
1314{
1315 SECStatus rv;
1316
1317 if (!p12dcx || p12dcx->error) {
1318 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1319 return SECFailure;
1320 }
1321
1322 /* update the PFX decoder context */
1323 rv = SEC_ASN1DecoderUpdateSEC_ASN1DecoderUpdate_Util(p12dcx->pfxA1Dcx, (const char *)data, len);
1324 if (rv != SECSuccess) {
1325 p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
1326 goto loser;
1327 }
1328
1329 return SECSuccess;
1330
1331loser:
1332
1333 p12dcx->error = PR_TRUE1;
1334 return SECFailure;
1335}
1336
1337/* This should be a nice sized buffer for reading in data (potentially large
1338** amounts) to be MACed. It should be MUCH larger than HASH_LENGTH_MAX.
1339*/
1340#define IN_BUF_LEN1024 1024
1341#ifdef DEBUG1
1342static const char bufferEnd[] = { "BufferEnd" };
1343#endif
1344#define FUDGE128 128 /* must be as large as bufferEnd or more. */
1345
1346#ifdef UNSAFE_FUZZER_MODE
1347static SECStatus
1348sec_pkcs12_decoder_verify_fuzzer(SEC_PKCS12DecoderContext *p12dcx)
1349{
1350 if (p12dcx->dClose) {
1351 (*p12dcx->dClose)(p12dcx->dArg, PR_TRUE1);
1352 p12dcx->dIsOpen = PR_FALSE0;
1353 }
1354
1355 return SECSuccess;
1356}
1357#endif /* UNSAFE_FUZZER_MODE */
1358
1359/* verify the hmac by reading the data from the temporary file
1360 * using the routines specified when the decodingContext was
1361 * created and return SECSuccess if the hmac matches.
1362 */
1363static SECStatus
1364sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx)
1365{
1366 PK11Context *pk11cx = NULL((void*)0);
1367 PK11SymKey *symKey = NULL((void*)0);
1368 unsigned char *buf;
1369 SECStatus rv = SECFailure;
1370 SECStatus lrv;
1371 unsigned int bufLen;
1372 int bytesRead;
1373 SECItem hmacRes;
1374 SECItem ignore = { 0 };
1375 CK_MECHANISM_TYPE hmacMech;
1376
1377 if (!p12dcx || p12dcx->error) {
1378 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1379 return SECFailure;
1380 }
1381#ifdef UNSAFE_FUZZER_MODE
1382 return sec_pkcs12_decoder_verify_fuzzer(p12dcx);
1383#endif /* UNSAFE_FUZZER_MODE */
1384 buf = (unsigned char *)PORT_AllocPORT_Alloc_Util(IN_BUF_LEN1024 + FUDGE128);
1385 if (!buf)
1386 return SECFailure; /* error code has been set. */
1387
1388#ifdef DEBUG1
1389 memcpy(buf + IN_BUF_LEN1024, bufferEnd, sizeof bufferEnd);
1390#endif
1391
1392 /* generate hmac key */
1393 symKey = sec_pkcs12_integrity_key(p12dcx->slot, &p12dcx->macData,
1394 p12dcx->pwitem, &hmacMech, PR_TRUE1,
1395 p12dcx->wincx);
1396 if (symKey == NULL((void*)0)) {
1397 goto loser;
1398 }
1399
1400 /* init hmac */
1401 pk11cx = PK11_CreateContextBySymKey(hmacMech, CKA_SIGN0x00000108UL, symKey, &ignore);
1402 if (!pk11cx) {
1403 goto loser;
1404 }
1405 lrv = PK11_DigestBegin(pk11cx);
1406 if (lrv == SECFailure) {
1407 goto loser;
1408 }
1409
1410 /* try to open the data for readback */
1411 if (p12dcx->dOpen && ((*p12dcx->dOpen)(p12dcx->dArg, PR_TRUE1) != SECSuccess)) {
1412 goto loser;
1413 }
1414
1415 /* read the data back IN_BUF_LEN bytes at a time and recompute
1416 * the hmac. if fewer bytes are read than are requested, it is
1417 * assumed that the end of file has been reached. if bytesRead
1418 * is returned as -1, then an error occurred reading from the
1419 * file.
1420 */
1421 do {
1422 bytesRead = (*p12dcx->dRead)(p12dcx->dArg, buf, IN_BUF_LEN1024);
1423 if (bytesRead < 0) {
1424 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_UNABLE_TO_READ);
1425 goto loser;
1426 }
1427 PORT_Assert(bytesRead <= IN_BUF_LEN)((bytesRead <= 1024) ? ((void)0) : PR_Assert("bytesRead <= IN_BUF_LEN"
, "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c", 1427)
)
;
1428 PORT_Assert(!memcmp(buf + IN_BUF_LEN, bufferEnd, sizeof bufferEnd))((!memcmp(buf + 1024, bufferEnd, sizeof bufferEnd)) ? ((void)
0) : PR_Assert("!memcmp(buf + IN_BUF_LEN, bufferEnd, sizeof bufferEnd)"
, "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c", 1428)
)
;
1429
1430 if (bytesRead > IN_BUF_LEN1024) {
1431 /* dRead callback overflowed buffer. */
1432 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INPUT_LEN);
1433 goto loser;
1434 }
1435
1436 if (bytesRead) {
1437 lrv = PK11_DigestOp(pk11cx, buf, bytesRead);
1438 if (lrv == SECFailure) {
1439 goto loser;
1440 }
1441 }
1442 } while (bytesRead == IN_BUF_LEN1024);
1443
1444 /* finish the hmac context */
1445 lrv = PK11_DigestFinal(pk11cx, buf, &bufLen, IN_BUF_LEN1024);
1446 if (lrv == SECFailure) {
1447 goto loser;
1448 }
1449
1450 hmacRes.data = buf;
1451 hmacRes.len = bufLen;
1452
1453 /* is the hmac computed the same as the hmac which was decoded? */
1454 rv = SECSuccess;
1455 if (SECITEM_CompareItemSECITEM_CompareItem_Util(&hmacRes, &p12dcx->macData.safeMac.digest) != SECEqual) {
1456 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_INVALID_MAC);
1457 rv = SECFailure;
1458 }
1459
1460loser:
1461 /* close the file and remove it */
1462 if (p12dcx->dClose) {
1463 (*p12dcx->dClose)(p12dcx->dArg, PR_TRUE1);
1464 p12dcx->dIsOpen = PR_FALSE0;
1465 }
1466
1467 if (pk11cx) {
1468 PK11_DestroyContext(pk11cx, PR_TRUE1);
1469 }
1470 if (symKey) {
1471 PK11_FreeSymKey(symKey);
1472 }
1473 PORT_ZFreePORT_ZFree_Util(buf, IN_BUF_LEN1024 + FUDGE128);
1474
1475 return rv;
1476}
1477
1478/* SEC_PKCS12DecoderVerify
1479 * Verify the macData or the signature of the decoded PKCS 12 PDU.
1480 * If the signature or the macData do not match, SECFailure is
1481 * returned.
1482 *
1483 * p12dcx - the decoder context
1484 */
1485SECStatus
1486SEC_PKCS12DecoderVerify(SEC_PKCS12DecoderContext *p12dcx)
1487{
1488 SECStatus rv = SECSuccess;
1489
1490 /* make sure that no errors have occurred... */
1491 if (!p12dcx) {
1492 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1493 return SECFailure;
1494 }
1495 if (p12dcx->error) {
1496 /* error code is already set! PORT_SetError(p12dcx->errorValue); */
1497 return SECFailure;
1498 }
1499
1500 rv = SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(p12dcx->pfxA1Dcx);
1501 p12dcx->pfxA1Dcx = NULL((void*)0);
1502 if (rv != SECSuccess) {
1503 return rv;
1504 }
1505#ifdef UNSAFE_FUZZER_MODE
1506 return sec_pkcs12_decoder_verify_fuzzer(p12dcx);
1507#else /* UNSAFE_FUZZER_MODE */
1508 /* check the signature or the mac depending on the type of
1509 * integrity used.
1510 */
1511 if (p12dcx->pfx.encodedMacData.len) {
1512 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(p12dcx->arena, &p12dcx->macData,
1513 sec_PKCS12MacDataTemplate,
1514 &p12dcx->pfx.encodedMacData);
1515 if (rv == SECSuccess) {
1516 return sec_pkcs12_decoder_verify_mac(p12dcx);
1517 }
1518 return rv;
1519 }
1520 if (SEC_PKCS7VerifySignature(p12dcx->aSafeCinfo, certUsageEmailSigner,
1521 PR_FALSE0)) {
1522 return SECSuccess;
1523 }
1524 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS12_INVALID_MAC);
1525 return SECFailure;
1526#endif /* UNSAFE_FUZZER_MODE */
1527}
1528
1529/* SEC_PKCS12DecoderFinish
1530 * Free any open ASN1 or PKCS7 decoder contexts and then
1531 * free the arena pool which everything should be allocated
1532 * from. This function should be called upon completion of
1533 * decoding and installing of a pfx pdu. This should be
1534 * called even if an error occurs.
1535 *
1536 * p12dcx - the decoder context
1537 */
1538void
1539SEC_PKCS12DecoderFinish(SEC_PKCS12DecoderContext *p12dcx)
1540{
1541 unsigned int i;
1542
1543 if (!p12dcx) {
1544 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1545 return;
1546 }
1547
1548 if (p12dcx->pfxA1Dcx) {
1549 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(p12dcx->pfxA1Dcx);
1550 p12dcx->pfxA1Dcx = NULL((void*)0);
1551 }
1552
1553 if (p12dcx->aSafeA1Dcx) {
1554 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(p12dcx->aSafeA1Dcx);
1555 p12dcx->aSafeA1Dcx = NULL((void*)0);
1556 }
1557
1558 /* cleanup any old ASN1 decoder contexts */
1559 for (i = 0; i < p12dcx->safeContentsCnt; ++i) {
1560 sec_PKCS12SafeContentsContext *safeContentsCtx, *nested;
1561 safeContentsCtx = p12dcx->safeContentsList[i];
1562 if (safeContentsCtx) {
1563 nested = safeContentsCtx->nestedSafeContentsCtx;
1564 while (nested) {
1565 if (nested->currentSafeBagA1Dcx) {
1566 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(nested->currentSafeBagA1Dcx);
1567 nested->currentSafeBagA1Dcx = NULL((void*)0);
1568 }
1569 if (nested->safeContentsA1Dcx) {
1570 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(nested->safeContentsA1Dcx);
1571 nested->safeContentsA1Dcx = NULL((void*)0);
1572 }
1573 nested = nested->nestedSafeContentsCtx;
1574 }
1575 if (safeContentsCtx->currentSafeBagA1Dcx) {
1576 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(safeContentsCtx->currentSafeBagA1Dcx);
1577 safeContentsCtx->currentSafeBagA1Dcx = NULL((void*)0);
1578 }
1579 if (safeContentsCtx->safeContentsA1Dcx) {
1580 SEC_ASN1DecoderFinishSEC_ASN1DecoderFinish_Util(safeContentsCtx->safeContentsA1Dcx);
1581 safeContentsCtx->safeContentsA1Dcx = NULL((void*)0);
1582 }
1583 }
1584 }
1585
1586 if (p12dcx->currentASafeP7Dcx &&
1587 p12dcx->currentASafeP7Dcx != p12dcx->aSafeP7Dcx) {
1588 SEC_PKCS7ContentInfo *cinfo;
1589 cinfo = SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx);
1590 if (cinfo) {
1591 SEC_PKCS7DestroyContentInfo(cinfo); /* don't leak it */
1592 }
1593 }
1594 p12dcx->currentASafeP7Dcx = NULL((void*)0);
1595
1596 if (p12dcx->aSafeP7Dcx) {
1597 SEC_PKCS7ContentInfo *cinfo;
1598 cinfo = SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);
1599 if (cinfo) {
1600 SEC_PKCS7DestroyContentInfo(cinfo);
1601 }
1602 p12dcx->aSafeP7Dcx = NULL((void*)0);
1603 }
1604
1605 if (p12dcx->aSafeCinfo) {
1606 SEC_PKCS7DestroyContentInfo(p12dcx->aSafeCinfo);
1607 p12dcx->aSafeCinfo = NULL((void*)0);
1608 }
1609
1610 if (p12dcx->decitem.type != 0 && p12dcx->decitem.der != NULL((void*)0)) {
1611 SECITEM_FreeItemSECITEM_FreeItem_Util(p12dcx->decitem.der, PR_TRUE1);
1612 }
1613 if (p12dcx->decitem.friendlyName != NULL((void*)0)) {
1614 SECITEM_FreeItemSECITEM_FreeItem_Util(p12dcx->decitem.friendlyName, PR_TRUE1);
1615 }
1616
1617 if (p12dcx->slot) {
1618 PK11_FreeSlot(p12dcx->slot);
1619 p12dcx->slot = NULL((void*)0);
1620 }
1621
1622 if (p12dcx->dIsOpen && p12dcx->dClose) {
1623 (*p12dcx->dClose)(p12dcx->dArg, PR_TRUE1);
1624 p12dcx->dIsOpen = PR_FALSE0;
1625 }
1626
1627 if (p12dcx->arena) {
1628 PORT_FreeArenaPORT_FreeArena_Util(p12dcx->arena, PR_TRUE1);
1629 }
1630}
1631
1632static SECStatus
1633sec_pkcs12_decoder_set_attribute_value(sec_PKCS12SafeBag *bag,
1634 SECOidTag attributeType,
1635 SECItem *attrValue)
1636{
1637 int i = 0;
1638 SECOidData *oid;
1639
1640 if (!bag || !attrValue) {
1641 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1642 return SECFailure;
1643 }
1644
1645 oid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(attributeType);
1646 if (!oid) {
1647 return SECFailure;
1648 }
1649
1650 if (!bag->attribs) {
1651 bag->attribs =
1652 PORT_ArenaZNewArray(bag->arena, sec_PKCS12Attribute *, 2)(sec_PKCS12Attribute * *)PORT_ArenaZAlloc_Util(bag->arena,
sizeof(sec_PKCS12Attribute *) * (2))
;
1653 } else {
1654 while (bag->attribs[i])
1655 i++;
1656 bag->attribs = PORT_ArenaGrowArray(bag->arena, bag->attribs,(sec_PKCS12Attribute * *)PORT_ArenaGrow_Util((bag->arena),
(bag->attribs), (i + 1) * sizeof(sec_PKCS12Attribute *), (
i + 2) * sizeof(sec_PKCS12Attribute *))
1657 sec_PKCS12Attribute *, i + 1, i + 2)(sec_PKCS12Attribute * *)PORT_ArenaGrow_Util((bag->arena),
(bag->attribs), (i + 1) * sizeof(sec_PKCS12Attribute *), (
i + 2) * sizeof(sec_PKCS12Attribute *))
;
1658 }
1659
1660 if (!bag->attribs) {
1661 return SECFailure;
1662 }
1663
1664 bag->attribs[i] = PORT_ArenaZNew(bag->arena, sec_PKCS12Attribute)(sec_PKCS12Attribute *)PORT_ArenaZAlloc_Util(bag->arena, sizeof
(sec_PKCS12Attribute))
;
1665 if (!bag->attribs[i]) {
1666 return SECFailure;
1667 }
1668
1669 bag->attribs[i]->attrValue = PORT_ArenaZNewArray(bag->arena, SECItem *, 2)(SECItem * *)PORT_ArenaZAlloc_Util(bag->arena, sizeof(SECItem
*) * (2))
;
1670 if (!bag->attribs[i]->attrValue) {
1671 return SECFailure;
1672 }
1673
1674 bag->attribs[i + 1] = NULL((void*)0);
1675 bag->attribs[i]->attrValue[0] = attrValue;
1676 bag->attribs[i]->attrValue[1] = NULL((void*)0);
1677
1678 return SECITEM_CopyItemSECITEM_CopyItem_Util(bag->arena, &bag->attribs[i]->attrType, &oid->oid);
1679}
1680
1681static SECItem *
1682sec_pkcs12_get_attribute_value(sec_PKCS12SafeBag *bag,
1683 SECOidTag attributeType)
1684{
1685 int i;
1686
1687 if (!bag->attribs) {
1688 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1689 return NULL((void*)0);
1690 }
1691
1692 for (i = 0; bag->attribs[i] != NULL((void*)0); i++) {
1693 if (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&bag->attribs[i]->attrType) == attributeType) {
1694 return bag->attribs[i]->attrValue[0];
1695 }
1696 }
1697 return NULL((void*)0);
1698}
1699
1700/* For now, this function will merely remove any ":"
1701 * in the nickname which the PK11 functions may have
1702 * placed there. This will keep dual certs from appearing
1703 * twice under "Your" certificates when imported onto smart
1704 * cards. Once with the name "Slot:Cert" and another with
1705 * the nickname "Slot:Slot:Cert"
1706 */
1707static void
1708sec_pkcs12_sanitize_nickname(PK11SlotInfo *slot, SECItem *nick)
1709{
1710 char *nickname;
1711 char *delimit;
1712 int delimitlen;
1713
1714 nickname = (char *)nick->data;
1715 if ((delimit = PORT_Strchrstrchr(nickname, ':')) != NULL((void*)0)) {
1716 char *slotName;
1717 int slotNameLen;
1718
1719 slotNameLen = delimit - nickname;
1720 slotName = PORT_NewArray(char, (slotNameLen + 1))(char *)PORT_Alloc_Util(sizeof(char) * ((slotNameLen + 1)));
1721 PORT_Assert(slotName)((slotName) ? ((void)0) : PR_Assert("slotName", "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c"
, 1721))
;
1722 if (slotName == NULL((void*)0)) {
1723 /* What else can we do?*/
1724 return;
1725 }
1726 PORT_Memcpymemcpy(slotName, nickname, slotNameLen);
1727 slotName[slotNameLen] = '\0';
1728 if (PORT_Strcmpstrcmp(PK11_GetTokenName(slot), slotName) == 0) {
1729 delimitlen = PORT_Strlen(delimit + 1)strlen(delimit + 1);
1730 if (delimitlen == 0) {
1731 /* Nickname was exactly "TokenName:" with nothing after the
1732 * prefix. Stripping it would yield an empty SECItem, which
1733 * is not a useful nickname; leave the original in place. */
1734 PORT_FreePORT_Free_Util(slotName);
1735 return;
1736 }
1737 PORT_Memmovememmove(nickname, delimit + 1, delimitlen + 1);
1738 nick->len = delimitlen;
1739 }
1740 PORT_FreePORT_Free_Util(slotName);
1741 }
1742}
1743
1744static SECItem *
1745sec_pkcs12_get_nickname(sec_PKCS12SafeBag *bag)
1746{
1747 SECItem *src, *dest;
1748
1749 if (!bag) {
1750 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1751 return NULL((void*)0);
1752 }
1753
1754 src = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_FRIENDLY_NAME);
1755
1756 /* The return value src is 16-bit Unicode characters, in big-endian format.
1757 * Check if it is NULL or empty name.
1758 */
1759 if (!src || !src->data || src->len < 2 || (!src->data[0] && !src->data[1])) {
1760 return NULL((void*)0);
1761 }
1762
1763 dest = (SECItem *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(SECItem));
1764 if (!dest) {
1765 goto loser;
1766 }
1767 if (!sec_pkcs12_convert_item_to_unicode(NULL((void*)0), dest, src, PR_FALSE0,
1768 PR_FALSE0, PR_FALSE0)) {
1769 goto loser;
1770 }
1771
1772 sec_pkcs12_sanitize_nickname(bag->slot, dest);
1773
1774 return dest;
1775
1776loser:
1777 if (dest) {
1778 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dest, PR_TRUE1);
1779 }
1780
1781 bag->problem = PR_TRUE1;
1782 bag->error = PORT_GetErrorPORT_GetError_Util();
1783 return NULL((void*)0);
1784}
1785
1786static SECStatus
1787sec_pkcs12_set_nickname(sec_PKCS12SafeBag *bag, SECItem *name)
1788{
1789 sec_PKCS12Attribute *attr = NULL((void*)0);
1790 SECOidData *oid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(SEC_OID_PKCS9_FRIENDLY_NAME);
1791
1792 if (!bag || !bag->arena || !name) {
1793 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1794 return SECFailure;
1795 }
1796
1797 if (!bag->attribs) {
1798 if (!oid) {
1799 goto loser;
1800 }
1801
1802 bag->attribs =
1803 PORT_ArenaZNewArray(bag->arena, sec_PKCS12Attribute *, 2)(sec_PKCS12Attribute * *)PORT_ArenaZAlloc_Util(bag->arena,
sizeof(sec_PKCS12Attribute *) * (2))
;
1804 if (!bag->attribs) {
1805 goto loser;
1806 }
1807 bag->attribs[0] = PORT_ArenaZNew(bag->arena, sec_PKCS12Attribute)(sec_PKCS12Attribute *)PORT_ArenaZAlloc_Util(bag->arena, sizeof
(sec_PKCS12Attribute))
;
1808 if (!bag->attribs[0]) {
1809 goto loser;
1810 }
1811 bag->attribs[1] = NULL((void*)0);
1812
1813 attr = bag->attribs[0];
1814 if (SECITEM_CopyItemSECITEM_CopyItem_Util(bag->arena, &attr->attrType, &oid->oid) != SECSuccess) {
1815 goto loser;
1816 }
1817 } else {
1818 int i;
1819 for (i = 0; bag->attribs[i]; i++) {
1820 if (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&bag->attribs[i]->attrType) == SEC_OID_PKCS9_FRIENDLY_NAME) {
1821 attr = bag->attribs[i];
1822 break;
1823 }
1824 }
1825 if (!attr) {
1826 if (!oid) {
1827 goto loser;
1828 }
1829 bag->attribs = PORT_ArenaGrowArray(bag->arena, bag->attribs,(sec_PKCS12Attribute * *)PORT_ArenaGrow_Util((bag->arena),
(bag->attribs), (i + 1) * sizeof(sec_PKCS12Attribute *), (
i + 2) * sizeof(sec_PKCS12Attribute *))
1830 sec_PKCS12Attribute *, i + 1, i + 2)(sec_PKCS12Attribute * *)PORT_ArenaGrow_Util((bag->arena),
(bag->attribs), (i + 1) * sizeof(sec_PKCS12Attribute *), (
i + 2) * sizeof(sec_PKCS12Attribute *))
;
1831 if (!bag->attribs) {
1832 goto loser;
1833 }
1834 bag->attribs[i] = PORT_ArenaZNew(bag->arena, sec_PKCS12Attribute)(sec_PKCS12Attribute *)PORT_ArenaZAlloc_Util(bag->arena, sizeof
(sec_PKCS12Attribute))
;
1835 if (!bag->attribs[i]) {
1836 goto loser;
1837 }
1838 bag->attribs[i + 1] = NULL((void*)0);
1839 attr = bag->attribs[i];
1840 if (SECITEM_CopyItemSECITEM_CopyItem_Util(bag->arena, &attr->attrType, &oid->oid) != SECSuccess) {
1841 goto loser;
1842 }
1843 }
1844 }
1845
1846 PORT_Assert(attr)((attr) ? ((void)0) : PR_Assert("attr", "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c"
, 1846))
;
1847 if (!attr->attrValue) {
1848 attr->attrValue = PORT_ArenaZNewArray(bag->arena, SECItem *, 2)(SECItem * *)PORT_ArenaZAlloc_Util(bag->arena, sizeof(SECItem
*) * (2))
;
1849 if (!attr->attrValue) {
1850 goto loser;
1851 }
1852 attr->attrValue[0] = PORT_ArenaZNew(bag->arena, SECItem)(SECItem *)PORT_ArenaZAlloc_Util(bag->arena, sizeof(SECItem
))
;
1853 if (!attr->attrValue[0]) {
1854 goto loser;
1855 }
1856 attr->attrValue[1] = NULL((void*)0);
1857 }
1858
1859 name->len = PORT_Strlen((char *)name->data)strlen((char *)name->data);
1860 if (!sec_pkcs12_convert_item_to_unicode(bag->arena, attr->attrValue[0],
1861 name, PR_FALSE0, PR_FALSE0, PR_TRUE1)) {
1862 goto loser;
1863 }
1864
1865 return SECSuccess;
1866
1867loser:
1868 bag->problem = PR_TRUE1;
1869 bag->error = PORT_GetErrorPORT_GetError_Util();
1870 return SECFailure;
1871}
1872
1873static SECStatus
1874sec_pkcs12_get_key_info(sec_PKCS12SafeBag *key)
1875{
1876 int i = 0;
1877 SECKEYPrivateKeyInfo *pki = NULL((void*)0);
1878
1879 if (!key) {
1880 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1881 return SECFailure;
1882 }
1883
1884 /* if the bag does *not* contain an unencrypted PrivateKeyInfo
1885 * then we cannot convert the attributes. We are propagating
1886 * attributes within the PrivateKeyInfo to the SafeBag level.
1887 */
1888 if (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&(key->safeBagType)) !=
1889 SEC_OID_PKCS12_V1_KEY_BAG_ID) {
1890 return SECSuccess;
1891 }
1892
1893 pki = key->safeBagContent.pkcs8KeyBag;
1894
1895 if (!pki || !pki->attributes) {
1896 return SECSuccess;
1897 }
1898
1899 while (pki->attributes[i]) {
1900 SECOidTag tag = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&pki->attributes[i]->attrType);
1901
1902 if (tag == SEC_OID_PKCS9_LOCAL_KEY_ID ||
1903 tag == SEC_OID_PKCS9_FRIENDLY_NAME) {
1904 SECItem *attrValue = sec_pkcs12_get_attribute_value(key, tag);
1905 if (!attrValue) {
1906 if (sec_pkcs12_decoder_set_attribute_value(key, tag,
1907 pki->attributes[i]->attrValue[0]) != SECSuccess) {
1908 key->problem = PR_TRUE1;
1909 key->error = PORT_GetErrorPORT_GetError_Util();
1910 return SECFailure;
1911 }
1912 }
1913 }
1914 i++;
1915 }
1916
1917 return SECSuccess;
1918}
1919
1920/* retrieve the nickname for the certificate bag. first look
1921 * in the cert bag, otherwise get it from the key.
1922 */
1923static SECItem *
1924sec_pkcs12_get_nickname_for_cert(sec_PKCS12SafeBag *cert,
1925 sec_PKCS12SafeBag *key)
1926{
1927 SECItem *nickname;
1928
1929 if (!cert) {
1930 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1931 return NULL((void*)0);
1932 }
1933
1934 nickname = sec_pkcs12_get_nickname(cert);
1935 if (nickname) {
1936 return nickname;
1937 }
1938
1939 if (key) {
1940 nickname = sec_pkcs12_get_nickname(key);
1941
1942 if (nickname && sec_pkcs12_set_nickname(cert, nickname) != SECSuccess) {
1943 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(nickname, PR_TRUE1);
1944 return NULL((void*)0);
1945 }
1946 }
1947
1948 return nickname;
1949}
1950
1951/* set the nickname for the certificate */
1952static SECStatus
1953sec_pkcs12_set_nickname_for_cert(sec_PKCS12SafeBag *cert,
1954 sec_PKCS12SafeBag *key,
1955 SECItem *nickname)
1956{
1957 if (!nickname || !cert) {
1958 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1959 return SECFailure;
1960 }
1961
1962 if (sec_pkcs12_set_nickname(cert, nickname) != SECSuccess) {
1963 return SECFailure;
1964 }
1965
1966 if (key) {
1967 if (sec_pkcs12_set_nickname(key, nickname) != SECSuccess) {
1968 cert->problem = PR_TRUE1;
1969 cert->error = key->error;
1970 return SECFailure;
1971 }
1972 }
1973
1974 return SECSuccess;
1975}
1976
1977/* retrieve the DER cert from the cert bag */
1978static SECItem *
1979sec_pkcs12_get_der_cert(sec_PKCS12SafeBag *cert)
1980{
1981 if (!cert || !cert->safeBagContent.certBag) {
1982 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1983 return NULL((void*)0);
1984 }
1985
1986 if (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&cert->safeBagType) != SEC_OID_PKCS12_V1_CERT_BAG_ID) {
1987 return NULL((void*)0);
1988 }
1989
1990 /* only support X509 certs not SDSI */
1991 if (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&cert->safeBagContent.certBag->bagID) != SEC_OID_PKCS9_X509_CERT) {
1992 return NULL((void*)0);
1993 }
1994
1995 return SECITEM_DupItemSECITEM_DupItem_Util(&(cert->safeBagContent.certBag->value.x509Cert));
1996}
1997
1998struct certNickInfo {
1999 PLArenaPool *arena;
2000 unsigned int nNicks;
2001 SECItem **nickList;
2002 unsigned int error;
2003};
2004
2005/* callback for traversing certificates to gather the nicknames
2006 * used in a particular traversal. for instance, when using
2007 * CERT_TraversePermCertsForSubject, gather the nicknames and
2008 * store them in the certNickInfo for a particular DN.
2009 *
2010 * this handles the case where multiple nicknames are allowed
2011 * for the same dn, which is not currently allowed, but may be
2012 * in the future.
2013 */
2014static SECStatus
2015gatherNicknames(CERTCertificate *cert, void *arg)
2016{
2017 struct certNickInfo *nickArg = (struct certNickInfo *)arg;
2018 SECItem tempNick;
2019 unsigned int i;
2020
2021 if (!cert || !nickArg || nickArg->error) {
2022 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2023 return SECFailure;
2024 }
2025
2026 if (!cert->nickname) {
2027 return SECSuccess;
2028 }
2029
2030 tempNick.data = (unsigned char *)cert->nickname;
2031 tempNick.len = PORT_Strlen(cert->nickname)strlen(cert->nickname) + 1;
2032 tempNick.type = siAsciiString;
2033
2034 /* do we already have the nickname in the list? */
2035 if (nickArg->nNicks > 0) {
2036
2037 /* nicknames have been encountered, but there is no list -- bad */
2038 if (!nickArg->nickList) {
2039 nickArg->error = SEC_ERROR_INVALID_ARGS;
2040 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2041 return SECFailure;
2042 }
2043
2044 for (i = 0; i < nickArg->nNicks; i++) {
2045 if (SECITEM_CompareItemSECITEM_CompareItem_Util(nickArg->nickList[i], &tempNick) == SECEqual) {
2046 return SECSuccess;
2047 }
2048 }
2049 }
2050
2051 /* add the nickname to the list */
2052 nickArg->nickList = (nickArg->nNicks == 0)
2053 ? PORT_ArenaZNewArray(nickArg->arena, SECItem *, 2)(SECItem * *)PORT_ArenaZAlloc_Util(nickArg->arena, sizeof(
SECItem *) * (2))
2054 : PORT_ArenaGrowArray(nickArg->arena, nickArg->nickList, SECItem *,(SECItem * *)PORT_ArenaGrow_Util((nickArg->arena), (nickArg
->nickList), (nickArg->nNicks + 1) * sizeof(SECItem *),
(nickArg->nNicks + 2) * sizeof(SECItem *))
2055 nickArg->nNicks + 1, nickArg->nNicks + 2)(SECItem * *)PORT_ArenaGrow_Util((nickArg->arena), (nickArg
->nickList), (nickArg->nNicks + 1) * sizeof(SECItem *),
(nickArg->nNicks + 2) * sizeof(SECItem *))
;
2056
2057 if (!nickArg->nickList) {
2058 nickArg->error = SEC_ERROR_NO_MEMORY;
2059 return SECFailure;
2060 }
2061
2062 nickArg->nickList[nickArg->nNicks] =
2063 PORT_ArenaZNew(nickArg->arena, SECItem)(SECItem *)PORT_ArenaZAlloc_Util(nickArg->arena, sizeof(SECItem
))
;
2064 if (!nickArg->nickList[nickArg->nNicks]) {
2065 nickArg->error = PORT_GetErrorPORT_GetError_Util();
2066 return SECFailure;
2067 }
2068
2069 if (SECITEM_CopyItemSECITEM_CopyItem_Util(nickArg->arena, nickArg->nickList[nickArg->nNicks],
2070 &tempNick) != SECSuccess) {
2071 nickArg->error = PORT_GetErrorPORT_GetError_Util();
2072 return SECFailure;
2073 }
2074
2075 nickArg->nNicks++;
2076
2077 return SECSuccess;
2078}
2079
2080/* traverses the certs in the data base or in the token for the
2081 * DN to see if any certs currently have a nickname set.
2082 * If so, return it.
2083 */
2084static SECItem *
2085sec_pkcs12_get_existing_nick_for_dn(sec_PKCS12SafeBag *cert)
2086{
2087 struct certNickInfo *nickArg = NULL((void*)0);
2088 SECItem *derCert, *returnDn = NULL((void*)0);
2089 PLArenaPool *arena = NULL((void*)0);
2090 CERTCertificate *tempCert;
2091
2092 if (!cert) {
2093 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2094 return NULL((void*)0);
2095 }
2096
2097 derCert = sec_pkcs12_get_der_cert(cert);
2098 if (!derCert) {
2099 return NULL((void*)0);
2100 }
2101
2102 tempCert = CERT_DecodeDERCertificate__CERT_DecodeDERCertificate(derCert, PR_FALSE0, NULL((void*)0));
2103 if (!tempCert) {
2104 returnDn = NULL((void*)0);
2105 goto loser;
2106 }
2107
2108 arena = PORT_NewArenaPORT_NewArena_Util(1024);
2109 if (!arena) {
2110 returnDn = NULL((void*)0);
2111 goto loser;
2112 }
2113 nickArg = PORT_ArenaZNew(arena, struct certNickInfo)(struct certNickInfo *)PORT_ArenaZAlloc_Util(arena, sizeof(struct
certNickInfo))
;
2114 if (!nickArg) {
2115 returnDn = NULL((void*)0);
2116 goto loser;
2117 }
2118 nickArg->error = 0;
2119 nickArg->nNicks = 0;
2120 nickArg->nickList = NULL((void*)0);
2121 nickArg->arena = arena;
2122
2123 /* if the token is local, first traverse the cert database
2124 * then traverse the token.
2125 */
2126 if (PK11_TraverseCertsForSubjectInSlot(tempCert, cert->slot, gatherNicknames,
2127 (void *)nickArg) != SECSuccess) {
2128 returnDn = NULL((void*)0);
2129 goto loser;
2130 }
2131
2132 if (nickArg->error) {
2133 /* XXX do we want to set the error? */
2134 returnDn = NULL((void*)0);
2135 goto loser;
2136 }
2137
2138 if (nickArg->nNicks == 0) {
2139 returnDn = NULL((void*)0);
2140 goto loser;
2141 }
2142
2143 /* set it to the first name, for now. handle multiple names? */
2144 returnDn = SECITEM_DupItemSECITEM_DupItem_Util(nickArg->nickList[0]);
2145
2146loser:
2147 if (arena) {
2148 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_TRUE1);
2149 }
2150
2151 if (tempCert) {
2152 CERT_DestroyCertificate(tempCert);
2153 }
2154
2155 if (derCert) {
2156 SECITEM_FreeItemSECITEM_FreeItem_Util(derCert, PR_TRUE1);
2157 }
2158
2159 return (returnDn);
2160}
2161
2162/* counts certificates found for a given traversal function */
2163static SECStatus
2164countCertificate(CERTCertificate *cert, void *arg)
2165{
2166 unsigned int *nCerts = (unsigned int *)arg;
2167
2168 if (!cert || !arg) {
2169 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2170 return SECFailure;
2171 }
2172
2173 (*nCerts)++;
2174 return SECSuccess;
2175}
2176
2177static PRBool
2178sec_pkcs12_certs_for_nickname_exist(SECItem *nickname, PK11SlotInfo *slot)
2179{
2180 unsigned int nCerts = 0;
2181
2182 if (!nickname || !slot) {
2183 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2184 return PR_TRUE1;
2185 }
2186
2187 /* we want to check the local database first if we are importing to it */
2188 PK11_TraverseCertsForNicknameInSlot(nickname, slot, countCertificate,
2189 (void *)&nCerts);
2190 return (PRBool)(nCerts != 0);
2191}
2192
2193/* validate cert nickname such that there is a one-to-one relation
2194 * between nicknames and dn's. we want to enforce the case that the
2195 * nickname is non-NULL and that there is only one nickname per DN.
2196 *
2197 * if there is a problem with a nickname or the nickname is not present,
2198 * the user will be prompted for it.
2199 */
2200static void
2201sec_pkcs12_validate_cert_nickname(sec_PKCS12SafeBag *cert,
2202 sec_PKCS12SafeBag *key,
2203 SEC_PKCS12NicknameCollisionCallback nicknameCb,
2204 CERTCertificate *leafCert)
2205{
2206 SECItem *certNickname, *existingDNNick;
2207 PRBool setNickname = PR_FALSE0, cancel = PR_FALSE0;
2208 SECItem *newNickname = NULL((void*)0);
2209
2210 if (!cert || !cert->hasKey) {
2211 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2212 return;
2213 }
2214
2215 if (!nicknameCb) {
2216 cert->problem = PR_TRUE1;
2217 cert->error = SEC_ERROR_INVALID_ARGS;
2218 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2219 return;
2220 }
2221
2222 if (cert->hasKey && !key) {
2223 cert->problem = PR_TRUE1;
2224 cert->error = SEC_ERROR_INVALID_ARGS;
2225 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2226 return;
2227 }
2228
2229 certNickname = sec_pkcs12_get_nickname_for_cert(cert, key);
2230 existingDNNick = sec_pkcs12_get_existing_nick_for_dn(cert);
2231
2232 /* nickname is already used w/ this dn, so it is safe to return */
2233 if (certNickname && existingDNNick &&
2234 SECITEM_CompareItemSECITEM_CompareItem_Util(certNickname, existingDNNick) == SECEqual) {
2235 goto loser;
2236 }
2237
2238 /* nickname not set in pkcs 12 bags, but a nick is already used for
2239 * this dn. set the nicks in the p12 bags and finish.
2240 */
2241 if (existingDNNick) {
2242 sec_pkcs12_set_nickname_for_cert(cert, key, existingDNNick);
2243 goto loser;
2244 }
2245
2246 /* at this point, we have a certificate for which the DN is not located
2247 * on the token. the nickname specified may or may not be NULL. if it
2248 * is not null, we need to make sure that there are no other certificates
2249 * with this nickname in the token for it to be valid. this imposes a
2250 * one to one relationship between DN and nickname.
2251 *
2252 * if the nickname is null, we need the user to enter a nickname for
2253 * the certificate.
2254 *
2255 * once we have a nickname, we make sure that the nickname is unique
2256 * for the DN. if it is not, the user is reprompted to enter a new
2257 * nickname.
2258 *
2259 * in order to exit this loop, the nickname entered is either unique
2260 * or the user hits cancel and the certificate is not imported.
2261 */
2262 setNickname = PR_FALSE0;
2263 while (1) {
2264 /* we will use the nickname so long as no other certs have the
2265 * same nickname. and the nickname is not NULL.
2266 */
2267 if (certNickname && certNickname->data &&
2268 !sec_pkcs12_certs_for_nickname_exist(certNickname, cert->slot)) {
2269 if (setNickname) {
2270 sec_pkcs12_set_nickname_for_cert(cert, key, certNickname);
2271 }
2272 break;
2273 }
2274
2275 setNickname = PR_FALSE0;
Value stored to 'setNickname' is never read
2276 newNickname = (*nicknameCb)(certNickname, &cancel, leafCert);
2277 if (cancel) {
2278 cert->problem = PR_TRUE1;
2279 cert->error = SEC_ERROR_USER_CANCELLED;
2280 break;
2281 }
2282
2283 if (!newNickname) {
2284 cert->problem = PR_TRUE1;
2285 cert->error = PORT_GetErrorPORT_GetError_Util();
2286 break;
2287 }
2288
2289 /* at this point we have a new nickname, if we have an existing
2290 * certNickname, we need to free it and assign the new nickname
2291 * to it to avoid a memory leak. happy?
2292 */
2293 if (certNickname) {
2294 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(certNickname, PR_TRUE1);
2295 certNickname = NULL((void*)0);
2296 }
2297
2298 certNickname = newNickname;
2299 setNickname = PR_TRUE1;
2300 /* go back and recheck the new nickname */
2301 }
2302
2303loser:
2304 if (certNickname) {
2305 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(certNickname, PR_TRUE1);
2306 }
2307
2308 if (existingDNNick) {
2309 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(existingDNNick, PR_TRUE1);
2310 }
2311}
2312
2313static void
2314sec_pkcs12_validate_cert(sec_PKCS12SafeBag *cert,
2315 sec_PKCS12SafeBag *key,
2316 SEC_PKCS12NicknameCollisionCallback nicknameCb)
2317{
2318 CERTCertificate *leafCert;
2319
2320 if (!cert) {
2321 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2322 return;
2323 }
2324
2325 cert->validated = PR_TRUE1;
2326
2327 if (!nicknameCb) {
2328 cert->noInstall = PR_TRUE1;
2329 cert->problem = PR_TRUE1;
2330 cert->error = SEC_ERROR_INVALID_ARGS;
2331 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2332 return;
2333 }
2334
2335 if (!cert->safeBagContent.certBag) {
2336 cert->noInstall = PR_TRUE1;
2337 cert->problem = PR_TRUE1;
2338 cert->error = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
2339 return;
2340 }
2341
2342 cert->noInstall = PR_FALSE0;
2343 cert->unused = PR_FALSE0;
2344 cert->problem = PR_FALSE0;
2345 cert->error = 0;
2346
2347 leafCert = CERT_DecodeDERCertificate__CERT_DecodeDERCertificate(
2348 &cert->safeBagContent.certBag->value.x509Cert, PR_FALSE0, NULL((void*)0));
2349 if (!leafCert) {
2350 cert->noInstall = PR_TRUE1;
2351 cert->problem = PR_TRUE1;
2352 cert->error = PORT_GetErrorPORT_GetError_Util();
2353 return;
2354 }
2355
2356 sec_pkcs12_validate_cert_nickname(cert, key, nicknameCb, leafCert);
2357
2358 CERT_DestroyCertificate(leafCert);
2359}
2360
2361static void
2362sec_pkcs12_validate_key_by_cert(sec_PKCS12SafeBag *cert, sec_PKCS12SafeBag *key,
2363 void *wincx)
2364{
2365 CERTCertificate *leafCert;
2366 SECKEYPrivateKey *privk;
2367
2368 if (!key) {
2369 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2370 return;
2371 }
2372
2373 key->validated = PR_TRUE1;
2374
2375 if (!cert) {
2376 key->problem = PR_TRUE1;
2377 key->noInstall = PR_TRUE1;
2378 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
2379 return;
2380 }
2381
2382 leafCert = CERT_DecodeDERCertificate__CERT_DecodeDERCertificate(
2383 &(cert->safeBagContent.certBag->value.x509Cert), PR_FALSE0, NULL((void*)0));
2384 if (!leafCert) {
2385 key->problem = PR_TRUE1;
2386 key->noInstall = PR_TRUE1;
2387 key->error = PORT_GetErrorPORT_GetError_Util();
2388 return;
2389 }
2390
2391 privk = PK11_FindPrivateKeyFromCert(key->slot, leafCert, wincx);
2392 if (!privk) {
2393 privk = PK11_FindKeyByDERCert(key->slot, leafCert, wincx);
2394 }
2395
2396 if (privk) {
2397 SECKEY_DestroyPrivateKey(privk);
2398 key->noInstall = PR_TRUE1;
2399 }
2400
2401 CERT_DestroyCertificate(leafCert);
2402}
2403
2404static SECStatus
2405sec_pkcs12_add_cert(sec_PKCS12SafeBag *cert, PRBool keyExists, void *wincx)
2406{
2407 SECItem *derCert, *nickName;
2408 char *nickData = NULL((void*)0);
2409 PRBool isIntermediateCA;
2410 SECStatus rv;
2411
2412 if (!cert) {
2413 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2414 return SECFailure;
2415 }
2416
2417 if (cert->problem || cert->noInstall || cert->installed) {
2418 return SECSuccess;
2419 }
2420
2421 derCert = &cert->safeBagContent.certBag->value.x509Cert;
2422
2423 PORT_Assert(!cert->problem && !cert->noInstall)((!cert->problem && !cert->noInstall) ? ((void)
0) : PR_Assert("!cert->problem && !cert->noInstall"
, "/root/firefox-clang/security/nss/lib/pkcs12/p12d.c", 2423)
)
;
2424
2425 nickName = sec_pkcs12_get_nickname(cert);
2426 if (nickName) {
2427 nickData = (char *)nickName->data;
2428 }
2429
2430 isIntermediateCA = CERT_IsCADERCert(derCert, NULL((void*)0)) &&
2431 !CERT_IsRootDERCert(derCert);
2432
2433 if (keyExists) {
2434 CERTCertificate *newCert;
2435
2436 newCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
2437 derCert, NULL((void*)0), PR_FALSE0, PR_FALSE0);
2438 if (!newCert) {
2439 if (nickName)
2440 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(nickName, PR_TRUE1);
2441 cert->error = PORT_GetErrorPORT_GetError_Util();
2442 cert->problem = PR_TRUE1;
2443 return SECFailure;
2444 }
2445
2446 rv = PK11_ImportCertForKeyToSlot(cert->slot, newCert, nickData,
2447 PR_TRUE1, wincx);
2448 CERT_DestroyCertificate(newCert);
2449 } else if ((cert->tokenCAs == SECPKCS12TargetTokenNoCAs) ||
2450 ((cert->tokenCAs == SECPKCS12TargetTokenIntermediateCAs) &&
2451 !isIntermediateCA)) {
2452 SECItem *certList[2];
2453 certList[0] = derCert;
2454 certList[1] = NULL((void*)0);
2455
2456 rv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageUserCertImport,
2457 1, certList, NULL((void*)0), PR_TRUE1, PR_FALSE0, nickData);
2458 } else {
2459 rv = PK11_ImportDERCert(cert->slot, derCert, CK_INVALID_HANDLE0,
2460 nickData, PR_FALSE0);
2461 }
2462 if (rv) {
2463 cert->problem = 1;
2464 cert->error = PORT_GetErrorPORT_GetError_Util();
2465 }
2466 cert->installed = PR_TRUE1;
2467 if (nickName)
2468 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(nickName, PR_TRUE1);
2469 return rv;
2470}
2471
2472static const SECItem *
2473sec_pkcs12_get_public_value_and_type(const SECKEYPublicKey *pubKey,
2474 KeyType *type);
2475
2476static SECStatus
2477sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECKEYPublicKey *pubKey,
2478 unsigned int keyUsage,
2479 SECItem *nickName, PRBool forceUnicode, void *wincx)
2480{
2481 SECStatus rv;
2482 const SECItem *publicValue = NULL((void*)0);
2483 KeyType keyType;
2484
2485 /* We should always have values for "key" and "pubKey"
2486 so they can be dereferenced later. */
2487 if (!key || !pubKey) {
2488 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2489 return SECFailure;
2490 }
2491
2492 if (key->problem || key->noInstall) {
2493 return SECSuccess;
2494 }
2495
2496 /* get the value and type from the public key */
2497 publicValue = sec_pkcs12_get_public_value_and_type(pubKey, &keyType);
2498 if (!publicValue) {
2499 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
2500 key->problem = PR_TRUE1;
2501 return SECFailure;
2502 }
2503
2504 switch (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&key->safeBagType)) {
2505 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
2506 rv = PK11_ImportPrivateKeyInfo(key->slot,
2507 key->safeBagContent.pkcs8KeyBag,
2508 nickName, publicValue, PR_TRUE1, PR_TRUE1,
2509 keyUsage, wincx);
2510 break;
2511 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: {
2512 SECItem pwitem = { 0 };
2513 SECAlgorithmID *algid =
2514 &key->safeBagContent.pkcs8ShroudedKeyBag->algorithm;
2515 SECOidTag algorithm = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(algid);
2516
2517 if (!SEC_PKCS12DecryptionAllowed(algid)) {
2518 key->error = SEC_ERROR_BAD_EXPORT_ALGORITHM;
2519 key->problem = PR_TRUE1;
2520 return SECFailure;
2521 }
2522
2523 if (forceUnicode) {
2524 if (SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), &pwitem, key->pwitem) != SECSuccess) {
2525 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
2526 key->problem = PR_TRUE1;
2527 return SECFailure;
2528 }
2529 } else {
2530 if (!sec_pkcs12_decode_password(NULL((void*)0), &pwitem, algorithm,
2531 key->pwitem)) {
2532 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
2533 key->problem = PR_TRUE1;
2534 return SECFailure;
2535 }
2536 }
2537
2538 rv = PK11_ImportEncryptedPrivateKeyInfo(key->slot,
2539 key->safeBagContent.pkcs8ShroudedKeyBag,
2540 &pwitem, nickName, publicValue,
2541 PR_TRUE1, PR_TRUE1, keyType, keyUsage,
2542 wincx);
2543 if (pwitem.data) {
2544 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&pwitem, PR_FALSE0);
2545 }
2546 break;
2547 }
2548 default:
2549 key->error = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION;
2550 key->problem = PR_TRUE1;
2551 if (nickName) {
2552 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(nickName, PR_TRUE1);
2553 }
2554 return SECFailure;
2555 }
2556
2557 if (rv != SECSuccess) {
2558 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
2559 key->problem = PR_TRUE1;
2560 } else {
2561 /* try to import the public key. Failure to do so is not fatal,
2562 * not all tokens can store the public key */
2563 if (pubKey) {
2564 PK11_ImportPublicKey(key->slot, pubKey, PR_TRUE1);
2565 }
2566 key->installed = PR_TRUE1;
2567 }
2568
2569 return rv;
2570}
2571
2572/*
2573 * The correctness of the code in this file ABSOLUTELY REQUIRES
2574 * that ALL BAGs share a single common arena.
2575 *
2576 * This function allocates the bag list from the arena of whatever bag
2577 * happens to be passed to it. Each time a new bag is handed to it,
2578 * it grows (resizes) the arena of the bag that was handed to it.
2579 * If the bags have different arenas, it will grow the wrong arena.
2580 *
2581 * Worse, if the bags had separate arenas, then while destroying the bags
2582 * in a bag list, when the bag whose arena contained the bag list was
2583 * destroyed, the baglist itself would be destroyed, making it difficult
2584 * or impossible to continue to destroy the bags in the destroyed list.
2585 */
2586static SECStatus
2587sec_pkcs12_add_item_to_bag_list(sec_PKCS12SafeBag ***bagList,
2588 sec_PKCS12SafeBag *bag)
2589{
2590 sec_PKCS12SafeBag **newBagList = NULL((void*)0);
2591 int i = 0;
2592
2593 if (!bagList || !bag) {
2594 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2595 return SECFailure;
2596 }
2597
2598 if (!(*bagList)) {
2599 newBagList = PORT_ArenaZNewArray(bag->arena, sec_PKCS12SafeBag *, 2)(sec_PKCS12SafeBag * *)PORT_ArenaZAlloc_Util(bag->arena, sizeof
(sec_PKCS12SafeBag *) * (2))
;
2600 } else {
2601 while ((*bagList)[i])
2602 i++;
2603 newBagList = PORT_ArenaGrowArray(bag->arena, *bagList,(sec_PKCS12SafeBag * *)PORT_ArenaGrow_Util((bag->arena), (
*bagList), (i + 1) * sizeof(sec_PKCS12SafeBag *), (i + 2) * sizeof
(sec_PKCS12SafeBag *))
2604 sec_PKCS12SafeBag *, i + 1, i + 2)(sec_PKCS12SafeBag * *)PORT_ArenaGrow_Util((bag->arena), (
*bagList), (i + 1) * sizeof(sec_PKCS12SafeBag *), (i + 2) * sizeof
(sec_PKCS12SafeBag *))
;
2605 }
2606
2607 if (!newBagList) {
2608 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
2609 return SECFailure;
2610 }
2611
2612 newBagList[i] = bag;
2613 newBagList[i + 1] = NULL((void*)0);
2614 *bagList = newBagList;
2615
2616 return SECSuccess;
2617}
2618
2619static sec_PKCS12SafeBag **
2620sec_pkcs12_find_certs_for_key(sec_PKCS12SafeBag **safeBags,
2621 sec_PKCS12SafeBag *key)
2622{
2623 sec_PKCS12SafeBag **certList = NULL((void*)0);
2624 SECItem *keyId;
2625 int i;
2626
2627 if (!safeBags || !safeBags[0]) {
2628 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2629 return NULL((void*)0);
2630 }
2631
2632 keyId = sec_pkcs12_get_attribute_value(key, SEC_OID_PKCS9_LOCAL_KEY_ID);
2633 if (!keyId) {
2634 return NULL((void*)0);
2635 }
2636
2637 for (i = 0; safeBags[i]; i++) {
2638 if (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&(safeBags[i]->safeBagType)) == SEC_OID_PKCS12_V1_CERT_BAG_ID) {
2639 SECItem *certKeyId = sec_pkcs12_get_attribute_value(safeBags[i],
2640 SEC_OID_PKCS9_LOCAL_KEY_ID);
2641
2642 if (certKeyId && (SECITEM_CompareItemSECITEM_CompareItem_Util(certKeyId, keyId) == SECEqual)) {
2643 if (sec_pkcs12_add_item_to_bag_list(&certList, safeBags[i]) != SECSuccess) {
2644 /* This would leak the partial list of safeBags,
2645 * but that list is allocated from the arena of
2646 * one of the safebags, and will be destroyed when
2647 * that arena is destroyed. So this is not a real leak.
2648 */
2649 return NULL((void*)0);
2650 }
2651 }
2652 }
2653 }
2654
2655 return certList;
2656}
2657
2658CERTCertList *
2659SEC_PKCS12DecoderGetCerts(SEC_PKCS12DecoderContext *p12dcx)
2660{
2661 CERTCertList *certList = NULL((void*)0);
2662 sec_PKCS12SafeBag **safeBags;
2663 int i;
2664
2665 if (!p12dcx || !p12dcx->safeBags || !p12dcx->safeBags[0]) {
2666 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2667 return NULL((void*)0);
2668 }
2669
2670 safeBags = p12dcx->safeBags;
2671 certList = CERT_NewCertList();
2672
2673 if (certList == NULL((void*)0)) {
2674 return NULL((void*)0);
2675 }
2676
2677 for (i = 0; safeBags[i]; i++) {
2678 if (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&(safeBags[i]->safeBagType)) == SEC_OID_PKCS12_V1_CERT_BAG_ID) {
2679 SECItem *derCert = sec_pkcs12_get_der_cert(safeBags[i]);
2680 CERTCertificate *tempCert = NULL((void*)0);
2681
2682 if (derCert == NULL((void*)0))
2683 continue;
2684 tempCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
2685 derCert, NULL((void*)0),
2686 PR_FALSE0, PR_TRUE1);
2687
2688 if (tempCert) {
2689 CERT_AddCertToListTail(certList, tempCert);
2690 }
2691 SECITEM_FreeItemSECITEM_FreeItem_Util(derCert, PR_TRUE1);
2692 }
2693 /* fixed an infinite loop here, by ensuring that i gets incremented
2694 * if derCert is NULL above.
2695 */
2696 }
2697
2698 return certList;
2699}
2700static sec_PKCS12SafeBag **
2701sec_pkcs12_get_key_bags(sec_PKCS12SafeBag **safeBags)
2702{
2703 int i;
2704 sec_PKCS12SafeBag **keyList = NULL((void*)0);
2705 SECOidTag bagType;
2706
2707 if (!safeBags || !safeBags[0]) {
2708 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2709 return NULL((void*)0);
2710 }
2711
2712 for (i = 0; safeBags[i]; i++) {
2713 bagType = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&(safeBags[i]->safeBagType));
2714 switch (bagType) {
2715 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
2716 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
2717 if (sec_pkcs12_add_item_to_bag_list(&keyList, safeBags[i]) != SECSuccess) {
2718 /* This would leak, except that keyList is allocated
2719 * from the arena shared by all the safeBags.
2720 */
2721 return NULL((void*)0);
2722 }
2723 break;
2724 default:
2725 break;
2726 }
2727 }
2728
2729 return keyList;
2730}
2731
2732/* This function takes two passes over the bags, validating them
2733 * The two passes are intended to mirror exactly the two passes in
2734 * sec_pkcs12_install_bags. But they don't. :(
2735 */
2736static SECStatus
2737sec_pkcs12_validate_bags(sec_PKCS12SafeBag **safeBags,
2738 SEC_PKCS12NicknameCollisionCallback nicknameCb,
2739 void *wincx)
2740{
2741 sec_PKCS12SafeBag **keyList;
2742 int i;
2743
2744 if (!safeBags || !nicknameCb) {
2745 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2746 return SECFailure;
2747 }
2748
2749 if (!safeBags[0]) {
2750 return SECSuccess;
2751 }
2752
2753 /* First pass. Find all the key bags.
2754 * Find the matching cert(s) for each key.
2755 */
2756 keyList = sec_pkcs12_get_key_bags(safeBags);
2757 if (keyList) {
2758 for (i = 0; keyList[i]; ++i) {
2759 sec_PKCS12SafeBag *key = keyList[i];
2760 sec_PKCS12SafeBag **certList =
2761 sec_pkcs12_find_certs_for_key(safeBags, key);
2762
2763 if (certList) {
2764 int j;
2765
2766 if (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&(key->safeBagType)) ==
2767 SEC_OID_PKCS12_V1_KEY_BAG_ID) {
2768 /* if it is an unencrypted private key then make sure
2769 * the attributes are propageted to the appropriate
2770 * level
2771 */
2772 if (sec_pkcs12_get_key_info(key) != SECSuccess) {
2773 return SECFailure;
2774 }
2775 }
2776
2777 sec_pkcs12_validate_key_by_cert(certList[0], key, wincx);
2778 for (j = 0; certList[j]; ++j) {
2779 sec_PKCS12SafeBag *cert = certList[j];
2780 cert->hasKey = PR_TRUE1;
2781 if (key->problem) {
2782 cert->problem = PR_TRUE1;
2783 cert->error = key->error;
2784 continue;
2785 }
2786 sec_pkcs12_validate_cert(cert, key, nicknameCb);
2787 if (cert->problem) {
2788 key->problem = cert->problem;
2789 key->error = cert->error;
2790 }
2791 }
2792 }
2793 }
2794 }
2795
2796 /* Now take a second pass over the safebags and mark for installation any
2797 * certs that were neither installed nor disqualified by the first pass.
2798 */
2799 for (i = 0; safeBags[i]; ++i) {
2800 sec_PKCS12SafeBag *bag = safeBags[i];
2801
2802 if (!bag->validated) {
2803 SECOidTag bagType = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&bag->safeBagType);
2804
2805 switch (bagType) {
2806 case SEC_OID_PKCS12_V1_CERT_BAG_ID:
2807 sec_pkcs12_validate_cert(bag, NULL((void*)0), nicknameCb);
2808 break;
2809 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
2810 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
2811 bag->noInstall = PR_TRUE1;
2812 bag->problem = PR_TRUE1;
2813 bag->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
2814 break;
2815 default:
2816 bag->noInstall = PR_TRUE1;
2817 }
2818 }
2819 }
2820
2821 return SECSuccess;
2822}
2823
2824SECStatus
2825SEC_PKCS12DecoderValidateBags(SEC_PKCS12DecoderContext *p12dcx,
2826 SEC_PKCS12NicknameCollisionCallback nicknameCb)
2827{
2828 SECStatus rv;
2829 int i, probCnt, errorVal = 0;
2830 if (!p12dcx || p12dcx->error || !p12dcx->safeBags) {
2831 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2832 return SECFailure;
2833 }
2834
2835 rv = sec_pkcs12_validate_bags(p12dcx->safeBags, nicknameCb, p12dcx->wincx);
2836 if (rv == SECSuccess) {
2837 p12dcx->bagsVerified = PR_TRUE1;
2838 }
2839
2840 probCnt = 0;
2841 i = 0;
2842 while (p12dcx->safeBags[i]) {
2843 if (p12dcx->safeBags[i]->problem) {
2844 probCnt++;
2845 errorVal = p12dcx->safeBags[i]->error;
2846 }
2847 i++;
2848 }
2849
2850 if (probCnt) {
2851 PORT_SetErrorPORT_SetError_Util(errorVal);
2852 return SECFailure;
2853 }
2854
2855 return rv;
2856}
2857
2858SECStatus
2859SEC_PKCS12DecoderRenameCertNicknames(SEC_PKCS12DecoderContext *p12dcx,
2860 SEC_PKCS12NicknameRenameCallback nicknameCb,
2861 void *arg)
2862{
2863 int i;
2864 sec_PKCS12SafeBag *safeBag;
2865 CERTCertificate *cert;
2866 SECStatus srv;
2867
2868 if (!p12dcx || p12dcx->error || !p12dcx->safeBags || !nicknameCb) {
2869 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2870 return SECFailure;
2871 }
2872
2873 for (i = 0; (safeBag = p12dcx->safeBags[i]); i++) {
2874 SECItem *newNickname = NULL((void*)0);
2875 SECItem *defaultNickname = NULL((void*)0);
2876 SECStatus rename_rv;
2877
2878 if (SECOID_FindOIDTagSECOID_FindOIDTag_Util(&(safeBag->safeBagType)) !=
2879 SEC_OID_PKCS12_V1_CERT_BAG_ID) {
2880 continue;
2881 }
2882
2883 cert = CERT_DecodeDERCertificate__CERT_DecodeDERCertificate(
2884 &safeBag->safeBagContent.certBag->value.x509Cert,
2885 PR_FALSE0, NULL((void*)0));
2886 if (!cert) {
2887 return SECFailure;
2888 }
2889
2890 defaultNickname = sec_pkcs12_get_nickname(safeBag);
2891 rename_rv = (*nicknameCb)(cert, defaultNickname, &newNickname, arg);
2892
2893 CERT_DestroyCertificate(cert);
2894
2895 if (defaultNickname) {
2896 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(defaultNickname, PR_TRUE1);
2897 defaultNickname = NULL((void*)0);
2898 }
2899
2900 if (rename_rv != SECSuccess) {
2901 return rename_rv;
2902 }
2903
2904 if (newNickname) {
2905 srv = sec_pkcs12_set_nickname(safeBag, newNickname);
2906 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(newNickname, PR_TRUE1);
2907 newNickname = NULL((void*)0);
2908 if (srv != SECSuccess) {
2909 return SECFailure;
2910 }
2911 }
2912 }
2913
2914 return SECSuccess;
2915}
2916
2917static SECKEYPublicKey *
2918sec_pkcs12_get_public_key_and_usage(sec_PKCS12SafeBag *certBag,
2919 unsigned int *usage)
2920{
2921 SECKEYPublicKey *pubKey = NULL((void*)0);
2922 CERTCertificate *cert = NULL((void*)0);
2923
2924 if (!certBag || !usage) {
2925 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2926 return NULL((void*)0);
2927 }
2928
2929 *usage = 0;
2930
2931 cert = CERT_DecodeDERCertificate__CERT_DecodeDERCertificate(
2932 &certBag->safeBagContent.certBag->value.x509Cert, PR_FALSE0, NULL((void*)0));
2933 if (!cert) {
2934 return NULL((void*)0);
2935 }
2936
2937 *usage = cert->keyUsage;
2938 pubKey = CERT_ExtractPublicKey(cert);
2939 CERT_DestroyCertificate(cert);
2940 return pubKey;
2941}
2942
2943static const SECItem *
2944sec_pkcs12_get_public_value_and_type(const SECKEYPublicKey *pubKey,
2945 KeyType *type)
2946{
2947
2948 if (!type || !pubKey) {
2949 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2950 return NULL((void*)0);
2951 }
2952
2953 *type = pubKey->keyType;
2954 return PK11_GetPublicValueFromPublicKey(pubKey);
2955}
2956
2957/* This function takes two passes over the bags, installing them in the
2958 * desired slot. The two passes are intended to mirror exactly the
2959 * two passes in sec_pkcs12_validate_bags.
2960 */
2961static SECStatus
2962sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, PRBool forceUnicode,
2963 void *wincx)
2964{
2965 sec_PKCS12SafeBag **keyList;
2966 int i;
2967 int failedKeys = 0;
2968
2969 if (!safeBags) {
2970 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2971 return SECFailure;
2972 }
2973
2974 if (!safeBags[0]) {
2975 return SECSuccess;
2976 }
2977
2978 /* First pass. Find all the key bags.
2979 * Try to install them, and any certs associated with them.
2980 */
2981 keyList = sec_pkcs12_get_key_bags(safeBags);
2982 if (keyList) {
2983 for (i = 0; keyList[i]; i++) {
2984 SECStatus rv;
2985 SECKEYPublicKey *pubKey = NULL((void*)0);
2986 SECItem *nickName = NULL((void*)0);
2987 sec_PKCS12SafeBag *key = keyList[i];
2988 sec_PKCS12SafeBag **certList;
2989 unsigned int keyUsage;
2990
2991 if (key->problem) {
2992 ++failedKeys;
2993 continue;
2994 }
2995
2996 certList = sec_pkcs12_find_certs_for_key(safeBags, key);
2997 if (certList && certList[0]) {
2998 pubKey = sec_pkcs12_get_public_key_and_usage(certList[0],
2999 &keyUsage);
3000 /* use the cert's nickname, if it has one, else use the
3001 * key's nickname, else fail.
3002 */
3003 nickName = sec_pkcs12_get_nickname_for_cert(certList[0], key);
3004 } else {
3005 nickName = sec_pkcs12_get_nickname(key);
3006 }
3007 if (!nickName) {
3008 key->error = SEC_ERROR_BAD_NICKNAME;
3009 key->problem = PR_TRUE1;
3010 rv = SECFailure;
3011 } else if (!pubKey) {
3012 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
3013 key->problem = PR_TRUE1;
3014 rv = SECFailure;
3015 } else {
3016 rv = sec_pkcs12_add_key(key, pubKey, keyUsage, nickName,
3017 forceUnicode, wincx);
3018 }
3019 if (pubKey) {
3020 SECKEY_DestroyPublicKey(pubKey);
3021 pubKey = NULL((void*)0);
3022 }
3023 if (nickName) {
3024 SECITEM_FreeItemSECITEM_FreeItem_Util(nickName, PR_TRUE1);
3025 nickName = NULL((void*)0);
3026 }
3027 if (rv != SECSuccess) {
3028 PORT_SetErrorPORT_SetError_Util(key->error);
3029 ++failedKeys;
3030 }
3031
3032 if (certList) {
3033 int j;
3034
3035 for (j = 0; certList[j]; j++) {
3036 sec_PKCS12SafeBag *cert = certList[j];
3037 SECStatus certRv;
3038
3039 if (!cert)
3040 continue;
3041 if (rv != SECSuccess) {
3042 cert->problem = key->problem;
3043 cert->error = key->error;
3044 cert->noInstall = PR_TRUE1;
3045 continue;
3046 }
3047
3048 certRv = sec_pkcs12_add_cert(cert, cert->hasKey, wincx);
3049 if (certRv != SECSuccess) {
3050 key->problem = cert->problem;
3051 key->error = cert->error;
3052 PORT_SetErrorPORT_SetError_Util(cert->error);
3053 return SECFailure;
3054 }
3055 }
3056 }
3057 }
3058 }
3059 if (failedKeys)
3060 return SECFailure;
3061
3062 /* Now take a second pass over the safebags and install any certs
3063 * that were neither installed nor disqualified by the first pass.
3064 */
3065 for (i = 0; safeBags[i]; i++) {
3066 sec_PKCS12SafeBag *bag = safeBags[i];
3067
3068 if (!bag->installed && !bag->problem && !bag->noInstall) {
3069 SECStatus rv;
3070 SECOidTag bagType = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&(bag->safeBagType));
3071
3072 switch (bagType) {
3073 case SEC_OID_PKCS12_V1_CERT_BAG_ID:
3074 rv = sec_pkcs12_add_cert(bag, bag->hasKey, wincx);
3075 if (rv != SECSuccess) {
3076 PORT_SetErrorPORT_SetError_Util(bag->error);
3077 return SECFailure;
3078 }
3079 break;
3080 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
3081 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
3082 default:
3083 break;
3084 }
3085 }
3086 }
3087
3088 return SECSuccess;
3089}
3090
3091SECStatus
3092SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx)
3093{
3094 PRBool forceUnicode = PR_FALSE0;
3095 SECStatus rv;
3096
3097 if (!p12dcx || p12dcx->error) {
3098 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
3099 return SECFailure;
3100 }
3101
3102 if (!p12dcx->bagsVerified) {
3103 return SECFailure;
3104 }
3105
3106 /* We need to check the option here as well as in
3107 * SEC_PKCS12DecoderStart, because different PBE's could be used
3108 * for PKCS #7 and PKCS #8 */
3109 rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c, &forceUnicode);
3110 if (rv != SECSuccess) {
3111 return SECFailure;
3112 }
3113
3114 return sec_pkcs12_install_bags(p12dcx->safeBags, forceUnicode,
3115 p12dcx->wincx);
3116}
3117
3118PRBool
3119sec_pkcs12_bagHasKey(SEC_PKCS12DecoderContext *p12dcx, sec_PKCS12SafeBag *bag)
3120{
3121 int i;
3122 SECItem *keyId;
3123 SECItem *certKeyId;
3124
3125 certKeyId = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_LOCAL_KEY_ID);
3126 if (certKeyId == NULL((void*)0)) {
3127 return PR_FALSE0;
3128 }
3129
3130 for (i = 0; p12dcx->keyList && p12dcx->keyList[i]; i++) {
3131 keyId = sec_pkcs12_get_attribute_value(p12dcx->keyList[i],
3132 SEC_OID_PKCS9_LOCAL_KEY_ID);
3133 if (!keyId) {
3134 continue;
3135 }
3136 if (SECITEM_CompareItemSECITEM_CompareItem_Util(certKeyId, keyId) == SECEqual) {
3137 return PR_TRUE1;
3138 }
3139 }
3140 return PR_FALSE0;
3141}
3142
3143SECItem *
3144sec_pkcs12_get_friendlyName(sec_PKCS12SafeBag *bag)
3145{
3146 SECItem *friendlyName;
3147 SECItem *tempnm;
3148
3149 tempnm = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_FRIENDLY_NAME);
3150 friendlyName = (SECItem *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(SECItem));
3151 if (friendlyName) {
3152 if (!sec_pkcs12_convert_item_to_unicode(NULL((void*)0), friendlyName,
3153 tempnm, PR_TRUE1, PR_FALSE0, PR_FALSE0)) {
3154 SECITEM_FreeItemSECITEM_FreeItem_Util(friendlyName, PR_TRUE1);
3155 friendlyName = NULL((void*)0);
3156 }
3157 }
3158 return friendlyName;
3159}
3160
3161/* Following two functions provide access to selected portions of the safe bags.
3162 * Iteration is implemented per decoder context and may be accessed after
3163 * SEC_PKCS12DecoderVerify() returns success.
3164 * When ...DecoderIterateNext() returns SUCCESS a decoder item has been returned
3165 * where item.type is always set; item.friendlyName is set if it is non-null;
3166 * item.der, item.hasKey are set only for SEC_OID_PKCS12_V1_CERT_BAG_ID items.
3167 * ...DecoderIterateNext() returns FAILURE when the list is exhausted or when
3168 * arguments are invalid; PORT_GetError() is 0 at end-of-list.
3169 * Caller has read-only access to decoder items. Any SECItems generated are
3170 * owned by the decoder context and are freed by ...DecoderFinish().
3171 */
3172SECStatus
3173SEC_PKCS12DecoderIterateInit(SEC_PKCS12DecoderContext *p12dcx)
3174{
3175 if (!p12dcx || p12dcx->error) {
3176 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
3177 return SECFailure;
3178 }
3179
3180 p12dcx->iteration = 0;
3181 return SECSuccess;
3182}
3183
3184SECStatus
3185SEC_PKCS12DecoderIterateNext(SEC_PKCS12DecoderContext *p12dcx,
3186 const SEC_PKCS12DecoderItem **ipp)
3187{
3188 sec_PKCS12SafeBag *bag;
3189
3190 if (!p12dcx || p12dcx->error) {
3191 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
3192 return SECFailure;
3193 }
3194
3195 if (p12dcx->decitem.type != 0 && p12dcx->decitem.der != NULL((void*)0)) {
3196 SECITEM_FreeItemSECITEM_FreeItem_Util(p12dcx->decitem.der, PR_TRUE1);
3197 }
3198 if (p12dcx->decitem.shroudAlg != NULL((void*)0)) {
3199 SECOID_DestroyAlgorithmIDSECOID_DestroyAlgorithmID_Util(p12dcx->decitem.shroudAlg, PR_TRUE1);
3200 }
3201 if (p12dcx->decitem.friendlyName != NULL((void*)0)) {
3202 SECITEM_FreeItemSECITEM_FreeItem_Util(p12dcx->decitem.friendlyName, PR_TRUE1);
3203 }
3204 p12dcx->decitem.type = 0;
3205 p12dcx->decitem.der = NULL((void*)0);
3206 p12dcx->decitem.shroudAlg = NULL((void*)0);
3207 p12dcx->decitem.friendlyName = NULL((void*)0);
3208 p12dcx->decitem.hasKey = PR_FALSE0;
3209 *ipp = NULL((void*)0);
3210 if (p12dcx->keyList == NULL((void*)0)) {
3211 p12dcx->keyList = sec_pkcs12_get_key_bags(p12dcx->safeBags);
3212 }
3213
3214 for (; p12dcx->iteration < p12dcx->safeBagCount; p12dcx->iteration++) {
3215 bag = p12dcx->safeBags[p12dcx->iteration];
3216 if (bag == NULL((void*)0) || bag->problem) {
3217 continue;
3218 }
3219 p12dcx->decitem.type = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&(bag->safeBagType));
3220 switch (p12dcx->decitem.type) {
3221 case SEC_OID_PKCS12_V1_CERT_BAG_ID:
3222 p12dcx->decitem.der = sec_pkcs12_get_der_cert(bag);
3223 p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag);
3224 p12dcx->decitem.hasKey = sec_pkcs12_bagHasKey(p12dcx, bag);
3225 /* if we don't understand the cert, or it's not parsable, skip it */
3226 /* as per the comment above, friendlyName may be null legitimately */
3227 if (!p12dcx->decitem.der) {
3228 p12dcx->decitem.type = 0; /* clear out the type we are ignoring */
3229 continue;
3230 }
3231 break;
3232 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
3233 p12dcx->decitem.shroudAlg = PORT_ZNew(SECAlgorithmID)(SECAlgorithmID *)PORT_ZAlloc_Util(sizeof(SECAlgorithmID));
3234 if (p12dcx->decitem.shroudAlg) {
3235 SECOID_CopyAlgorithmIDSECOID_CopyAlgorithmID_Util(NULL((void*)0), p12dcx->decitem.shroudAlg,
3236 &bag->safeBagContent.pkcs8ShroudedKeyBag->algorithm);
3237 }
3238 /* fall through */
3239 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
3240 p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag);
3241 break;
3242 default:
3243 /* return these even though we don't expect them */
3244 break;
3245 case SEC_OID_UNKNOWN:
3246 /* ignore these */
3247 p12dcx->decitem.type = 0; /* clear out the type we are ignoring */
3248 continue;
3249 }
3250 *ipp = &p12dcx->decitem;
3251 p12dcx->iteration++;
3252 break; /* end for() */
3253 }
3254
3255 PORT_SetErrorPORT_SetError_Util(0); /* end-of-list is SECFailure with no PORT error */
3256 return ((p12dcx->decitem.type == 0) ? SECFailure : SECSuccess);
3257}