Bug Summary

File:root/firefox-clang/security/nss/cmd/pk12util/pk12util.c
Warning:line 907, column 5
Value stored to 'cipher' 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 pk12util.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/cmd/pk12util/pk12util_pk12util -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/pk12util/pk12util_pk12util -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 NSPR20 -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/cmd/pk12util -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/pk12util/pk12util_pk12util -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/cmd/pk12util/pk12util.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#ifdef _CRTDBG_MAP_ALLOC
6#include <stdlib.h>
7#include <crtdbg.h>
8#endif
9
10#include "nspr.h"
11#include "secutil.h"
12#include "pk11func.h"
13#include "p12plcy.h"
14#include "pk12util.h"
15#include "nss.h"
16#include "secport.h"
17#include "secpkcs5.h"
18#include "sechash.h"
19#include "certdb.h"
20#include "cert.h"
21#include "p12.h"
22
23#define PKCS12_IN_BUFFER_SIZE200 200
24
25static char *progName;
26PRBool pk12_debugging = PR_FALSE0;
27PRBool dumpRawFile;
28static PRBool pk12uForceUnicode;
29
30PRIntn pk12uErrno = 0;
31
32static void
33Usage()
34{
35#define FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
36 FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), "Usage: %s -i importfile [-I] [-d certdir] [-P dbprefix] [-h tokenname]\n",
37 progName);
38 FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
39 FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), "\t\t [-v]\n");
40
41 FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), "Usage: %s -l listfile [-I] [-d certdir] [-P dbprefix] [-h tokenname]\n",
42 progName);
43 FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
44 FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), "\t\t [-v]\n");
45
46 FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), "Usage: %s -o exportfile -n certname [-d certdir] [-P dbprefix]\n",
47 progName);
48 FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), "\t\t [-c key_cipher] [-C cert_cipher] [-M mac_alg]\n"
49 "\t\t [-m | --key_len keyLen] [--cert_key_len certKeyLen] [-v]\n");
50 FPSPR_fprintf(PR_GetSpecialFD(PR_StandardError), "\t\t [-k slotpwfile | -K slotpw]\n"
51 "\t\t [-w p12filepwfile | -W p12filepw]\n");
52
53 exit(PK12UERR_USAGE2);
54}
55
56static PRBool
57p12u_OpenFile(p12uContext *p12cxt, PRBool fileRead)
58{
59 if (!p12cxt || !p12cxt->filename) {
60 return PR_FALSE0;
61 }
62
63 if (fileRead) {
64 p12cxt->file = PR_Open(p12cxt->filename,
65 PR_RDONLY0x01, 0400);
66 } else {
67 p12cxt->file = PR_Open(p12cxt->filename,
68 PR_CREATE_FILE0x08 | PR_RDWR0x04 | PR_TRUNCATE0x20,
69 0600);
70 }
71
72 if (!p12cxt->file) {
73 p12cxt->error = PR_TRUE1;
74 return PR_FALSE0;
75 }
76
77 return PR_TRUE1;
78}
79
80static void
81p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
82{
83 if (!ppCtx || !(*ppCtx)) {
84 return;
85 }
86
87 if ((*ppCtx)->file != NULL((void*)0)) {
88 PR_Close((*ppCtx)->file);
89 }
90
91 if ((*ppCtx)->filename != NULL((void*)0)) {
92 if (removeFile) {
93 PR_Delete((*ppCtx)->filename);
94 }
95 PL_strfree((*ppCtx)->filename);
96 (*ppCtx)->filename = NULL((void*)0);
97 }
98
99 PR_Free(*ppCtx);
100 *ppCtx = NULL((void*)0);
101}
102
103static p12uContext *
104p12u_InitContext(PRBool fileImport, char *filename)
105{
106 p12uContext *p12cxt;
107
108 p12cxt = PORT_ZNew(p12uContext)(p12uContext *)PORT_ZAlloc_Util(sizeof(p12uContext));
109 if (!p12cxt) {
110 return NULL((void*)0);
111 }
112
113 p12cxt->error = PR_FALSE0;
114 p12cxt->errorValue = 0;
115 p12cxt->filename = PL_strdup(filename);
116
117 if (!p12u_OpenFile(p12cxt, fileImport)) {
118 p12u_DestroyContext(&p12cxt, PR_FALSE0);
119 return NULL((void*)0);
120 }
121
122 return p12cxt;
123}
124
125SECItem *
126P12U_NicknameCollisionCallback(SECItem *old_nick, PRBool *cancel, void *wincx)
127{
128 char *nick = NULL((void*)0);
129 SECItem *ret_nick = NULL((void*)0);
130 CERTCertificate *cert = (CERTCertificate *)wincx;
131
132 if (!cancel || !cert) {
133 pk12uErrno = PK12UERR_USER_CANCELLED1;
134 return NULL((void*)0);
135 }
136
137 if (!old_nick)
138 fprintf(stdoutstdout, "pk12util: no nickname for cert in PKCS12 file.\n");
139
140#if 0
141 /* XXX not handled yet */
142 *cancel = PR_TRUE1;
143 return NULL((void*)0);
144
145#else
146
147 nick = CERT_MakeCANickname(cert);
148 if (!nick) {
149 return NULL((void*)0);
150 }
151
152 if (old_nick && old_nick->data && old_nick->len &&
153 PORT_Strlen(nick)strlen(nick) == old_nick->len &&
154 !PORT_Strncmpstrncmp((char *)old_nick->data, nick, old_nick->len)) {
155 PORT_FreePORT_Free_Util(nick);
156 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_IO);
157 return NULL((void*)0);
158 }
159
160 fprintf(stdoutstdout, "pk12util: using nickname: %s\n", nick);
161 ret_nick = PORT_ZNew(SECItem)(SECItem *)PORT_ZAlloc_Util(sizeof(SECItem));
162 if (ret_nick == NULL((void*)0)) {
163 PORT_FreePORT_Free_Util(nick);
164 return NULL((void*)0);
165 }
166
167 ret_nick->data = (unsigned char *)nick;
168 ret_nick->len = PORT_Strlen(nick)strlen(nick);
169
170 return ret_nick;
171#endif
172}
173
174static SECStatus
175p12u_SwapUnicodeBytes(SECItem *uniItem)
176{
177 unsigned int i;
178 unsigned char a;
179 if ((uniItem == NULL((void*)0)) || (uniItem->len % 2)) {
180 return SECFailure;
181 }
182 for (i = 0; i < uniItem->len; i += 2) {
183 a = uniItem->data[i];
184 uniItem->data[i] = uniItem->data[i + 1];
185 uniItem->data[i + 1] = a;
186 }
187 return SECSuccess;
188}
189
190static PRBool
191p12u_ucs2_ascii_conversion_function(PRBool toUnicode,
192 unsigned char *inBuf,
193 unsigned int inBufLen,
194 unsigned char *outBuf,
195 unsigned int maxOutBufLen,
196 unsigned int *outBufLen,
197 PRBool swapBytes)
198{
199 SECItem it = { 0 };
200 SECItem *dup = NULL((void*)0);
201 PRBool ret;
202
203#ifdef DEBUG_CONVERSION
204 if (pk12_debugging) {
205 int i;
206 printf("Converted from:\n");
207 for (i = 0; i < inBufLen; i++) {
208 printf("%2x ", inBuf[i]);
209 /*if (i%60 == 0) printf("\n");*/
210 }
211 printf("\n");
212 }
213#endif
214 it.data = inBuf;
215 it.len = inBufLen;
216 dup = SECITEM_DupItemSECITEM_DupItem_Util(&it);
217 if (!dup) {
218 return PR_FALSE0;
219 }
220 /* If converting Unicode to ASCII, swap bytes before conversion
221 * as neccessary.
222 */
223 if (!toUnicode && swapBytes) {
224 if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
225 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup, PR_TRUE1);
226 return PR_FALSE0;
227 }
228 }
229 /* Perform the conversion. */
230 ret = PORT_UCS2_UTF8ConversionPORT_UCS2_UTF8Conversion_Util(toUnicode, dup->data, dup->len,
231 outBuf, maxOutBufLen, outBufLen);
232 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(dup, PR_TRUE1);
233
234#ifdef DEBUG_CONVERSION
235 if (pk12_debugging) {
236 int i;
237 printf("Converted to:\n");
238 for (i = 0; i < *outBufLen; i++) {
239 printf("%2x ", outBuf[i]);
240 /*if (i%60 == 0) printf("\n");*/
241 }
242 printf("\n");
243 }
244#endif
245 return ret;
246}
247
248SECStatus
249P12U_UnicodeConversion(PLArenaPool *arena, SECItem *dest, SECItem *src,
250 PRBool toUnicode, PRBool swapBytes)
251{
252 unsigned int allocLen;
253 if (!dest || !src) {
254 return SECFailure;
255 }
256 allocLen = ((toUnicode) ? (src->len << 2) : src->len);
257 if (arena) {
258 dest->data = PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, allocLen);
259 } else {
260 dest->data = PORT_ZAllocPORT_ZAlloc_Util(allocLen);
261 }
262 if (PORT_UCS2_ASCIIConversionPORT_UCS2_ASCIIConversion_Util(toUnicode, src->data, src->len,
263 dest->data, allocLen, &dest->len,
264 swapBytes) == PR_FALSE0) {
265 if (!arena) {
266 PORT_FreePORT_Free_Util(dest->data);
267 }
268 dest->data = NULL((void*)0);
269 return SECFailure;
270 }
271 return SECSuccess;
272}
273
274/*
275 *
276 */
277SECItem *
278P12U_GetP12FilePassword(PRBool confirmPw, secuPWData *p12FilePw)
279{
280 char *p0 = NULL((void*)0);
281 SECItem *pwItem = NULL((void*)0);
282
283 if (p12FilePw == NULL((void*)0) || p12FilePw->source == PW_NONE) {
284 char *p1 = NULL((void*)0);
285 int rc;
286 for (;;) {
287 p0 = SECU_GetPasswordString(NULL((void*)0),
288 "Enter password for PKCS12 file: ");
289 if (!confirmPw || p0 == NULL((void*)0))
290 break;
291 p1 = SECU_GetPasswordString(NULL((void*)0), "Re-enter password: ");
292 if (p1 == NULL((void*)0)) {
293 PORT_ZFreePORT_ZFree_Util(p0, PL_strlen(p0));
294 p0 = NULL((void*)0);
295 break;
296 }
297 rc = PL_strcmp(p0, p1);
298 PORT_ZFreePORT_ZFree_Util(p1, PL_strlen(p1));
299 if (rc == 0)
300 break;
301 PORT_ZFreePORT_ZFree_Util(p0, PL_strlen(p0));
302 }
303 } else if (p12FilePw->source == PW_FROMFILE) {
304 p0 = SECU_FilePasswd(NULL((void*)0), PR_FALSE0, p12FilePw->data);
305 } else { /* Plaintext */
306 p0 = PORT_StrdupPORT_Strdup_Util(p12FilePw->data);
307 }
308
309 if (p0 == NULL((void*)0)) {
310 return NULL((void*)0);
311 }
312 pwItem = SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), NULL((void*)0), PL_strlen(p0) + 1);
313 memcpy(pwItem->data, p0, pwItem->len);
314
315 PORT_ZFreePORT_ZFree_Util(p0, PL_strlen(p0));
316
317 return pwItem;
318}
319
320SECStatus
321P12U_InitSlot(PK11SlotInfo *slot, secuPWData *slotPw)
322{
323 SECStatus rv;
324
325 /* New databases, initialize keydb password. */
326 if (PK11_NeedUserInit(slot)) {
327 rv = SECU_ChangePW(slot,
328 (slotPw->source == PW_PLAINTEXT) ? slotPw->data : 0,
329 (slotPw->source == PW_FROMFILE) ? slotPw->data : 0);
330 if (rv != SECSuccess) {
331 SECU_PrintError(progName, "Failed to initialize slot \"%s\"",
332 PK11_GetSlotName(slot));
333 return SECFailure;
334 }
335 }
336
337 if (PK11_Authenticate(slot, PR_TRUE1, slotPw) != SECSuccess) {
338 SECU_PrintError(progName,
339 "Failed to authenticate to PKCS11 slot");
340 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_USER_CANCELLED);
341 pk12uErrno = PK12UERR_USER_CANCELLED1;
342 return SECFailure;
343 }
344
345 return SECSuccess;
346}
347
348/* This routine takes care of getting the PKCS12 file password, then reading and
349 * verifying the file. It returns the decoder context and a filled in password.
350 * (The password is needed by P12U_ImportPKCS12Object() to import the private
351 * key.)
352 */
353SEC_PKCS12DecoderContext *
354p12U_ReadPKCS12File(SECItem *uniPwp, char *in_file, PK11SlotInfo *slot,
355 secuPWData *slotPw, secuPWData *p12FilePw,
356 PRBool ignoreIntegrity)
357{
358 SEC_PKCS12DecoderContext *p12dcx = NULL((void*)0);
359 p12uContext *p12cxt = NULL((void*)0);
360 SECItem *pwitem = NULL((void*)0);
361 SECItem p12file = { 0 };
362 SECStatus rv = SECFailure;
363 PRBool swapUnicode = PR_FALSE0;
364 PRBool forceUnicode = pk12uForceUnicode;
365 PRBool trypw;
366 int error;
367
368#ifdef IS_LITTLE_ENDIAN1
369 swapUnicode = PR_TRUE1;
370#endif
371
372 p12cxt = p12u_InitContext(PR_TRUE1, in_file);
373 if (!p12cxt) {
374 SECU_PrintError(progName, "File Open failed: %s", in_file);
375 pk12uErrno = PK12UERR_INIT_FILE10;
376 return NULL((void*)0);
377 }
378
379 /* get the password */
380 pwitem = P12U_GetP12FilePassword(PR_FALSE0, p12FilePw);
381 if (!pwitem) {
382 pk12uErrno = PK12UERR_USER_CANCELLED1;
383 goto done;
384 }
385
386 if (P12U_UnicodeConversion(NULL((void*)0), uniPwp, pwitem, PR_TRUE1,
387 swapUnicode) != SECSuccess) {
388 SECU_PrintError(progName, "Unicode conversion failed");
389 pk12uErrno = PK12UERR_UNICODECONV11;
390 goto done;
391 }
392 rv = SECU_FileToItem(&p12file, p12cxt->file);
393 if (rv != SECSuccess) {
394 SECU_PrintError(progName, "Failed to read from import file");
395 goto done;
396 }
397
398 do {
399 trypw = PR_FALSE0; /* normally we do this once */
400 rv = SECFailure;
401 /* init the decoder context */
402 p12dcx = SEC_PKCS12DecoderStart(uniPwp, slot, slotPw,
403 NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0));
404 if (!p12dcx) {
405 SECU_PrintError(progName, "PKCS12 decoder start failed");
406 pk12uErrno = PK12UERR_PK12DECODESTART14;
407 break;
408 }
409
410 /* decode the item */
411 rv = SEC_PKCS12DecoderUpdate(p12dcx, p12file.data, p12file.len);
412
413 if (rv != SECSuccess) {
414 error = PR_GetError();
415 if (error == SEC_ERROR_DECRYPTION_DISALLOWED) {
416 PR_SetError(error, 0);
417 break;
418 }
419 SECU_PrintError(progName, "PKCS12 decoding failed");
420 pk12uErrno = PK12UERR_DECODE16;
421 }
422
423 /* does the blob authenticate properly? */
424 rv = SEC_PKCS12DecoderVerify(p12dcx);
425 if (rv != SECSuccess) {
426 if (uniPwp->len == 2) {
427 /* this is a null PW, try once more with a zero-length PW
428 instead of a null string */
429 SEC_PKCS12DecoderFinish(p12dcx);
430 uniPwp->len = 0;
431 trypw = PR_TRUE1;
432 } else if (forceUnicode == pk12uForceUnicode) {
433 /* try again with a different password encoding */
434 forceUnicode = !pk12uForceUnicode;
435 rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c,
436 forceUnicode);
437 if (rv != SECSuccess) {
438 SECU_PrintError(progName, "PKCS12 decoding failed to set option");
439 pk12uErrno = PK12UERR_DECODEVERIFY17;
440 break;
441 }
442 SEC_PKCS12DecoderFinish(p12dcx);
443 trypw = PR_TRUE1;
444 } else {
445 SECU_PrintError(progName, "PKCS12 decode not verified");
446 pk12uErrno = PK12UERR_DECODEVERIFY17;
447 break;
448 }
449 }
450 } while (trypw == PR_TRUE1);
451
452 /* revert the option setting */
453 if (forceUnicode != pk12uForceUnicode) {
454 if (SECSuccess != NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c, pk12uForceUnicode)) {
455 SECU_PrintError(progName, "PKCS12 decoding failed to set option");
456 pk12uErrno = PK12UERR_DECODEVERIFY17;
457 rv = SECFailure;
458 }
459 }
460 /* rv has been set at this point */
461
462done:
463 /* if we are ignoring Integrity and we failed because we couldn't
464 * verify the integrity code, go ahead and succeed */
465 if (rv != SECSuccess && !(ignoreIntegrity &&
466 (pk12uErrno == PK12UERR_DECODEVERIFY17))) {
467 if (p12dcx != NULL((void*)0)) {
468 SEC_PKCS12DecoderFinish(p12dcx);
469 p12dcx = NULL((void*)0);
470 }
471 if (uniPwp->data) {
472 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(uniPwp, PR_FALSE0);
473 uniPwp->data = NULL((void*)0);
474 }
475 }
476 PR_Close(p12cxt->file);
477 p12cxt->file = NULL((void*)0);
478 /* PK11_FreeSlot(slot); */
479 p12u_DestroyContext(&p12cxt, PR_FALSE0);
480
481 if (pwitem) {
482 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(pwitem, PR_TRUE1);
483 }
484 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&p12file, PR_FALSE0);
485 return p12dcx;
486}
487
488/*
489 * given a filename for pkcs12 file, imports certs and keys
490 *
491 * Change: altitude
492 * I've changed this function so that it takes the keydb and pkcs12 file
493 * passwords from files. The "pwdKeyDB" and "pwdP12File"
494 * variables have been added for this purpose.
495 */
496PRIntn
497P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot,
498 secuPWData *slotPw, secuPWData *p12FilePw,
499 PRBool ignoreIntegrity)
500{
501 SEC_PKCS12DecoderContext *p12dcx = NULL((void*)0);
502 SECItem uniPwitem = { 0 };
503 PRBool forceUnicode = pk12uForceUnicode;
504 PRBool trypw;
505 SECStatus rv = SECFailure;
506
507 rv = P12U_InitSlot(slot, slotPw);
508 if (rv != SECSuccess) {
509 SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
510 PK11_GetSlotName(slot));
511 pk12uErrno = PK12UERR_PK11GETSLOT13;
512 return rv;
513 }
514
515 do {
516 trypw = PR_FALSE0; /* normally we do this once */
517 rv = SECFailure;
518 p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw,
519 p12FilePw, ignoreIntegrity);
520
521 if (p12dcx == NULL((void*)0)) {
522 goto loser;
523 }
524
525 /* make sure the bags are okey dokey -- nicknames correct, etc. */
526 rv = SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback);
527 if (rv != SECSuccess) {
528 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
529 pk12uErrno = PK12UERR_CERTALREADYEXISTS20;
530 } else {
531 pk12uErrno = PK12UERR_DECODEVALIBAGS18;
532 }
533 SECU_PrintError(progName, "PKCS12 decode validate bags failed");
534 goto loser;
535 }
536
537 /* stuff 'em in */
538 if (forceUnicode != pk12uForceUnicode) {
539 rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c,
540 forceUnicode);
541 if (rv != SECSuccess) {
542 SECU_PrintError(progName, "PKCS12 decode set option failed");
543 pk12uErrno = PK12UERR_DECODEIMPTBAGS19;
544 goto loser;
545 }
546 }
547 rv = SEC_PKCS12DecoderImportBags(p12dcx);
548 if (rv != SECSuccess) {
549 if (PR_GetError() == SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY &&
550 forceUnicode == pk12uForceUnicode) {
551 /* try again with a different password encoding */
552 forceUnicode = !pk12uForceUnicode;
553 SEC_PKCS12DecoderFinish(p12dcx);
554 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&uniPwitem, PR_FALSE0);
555 trypw = PR_TRUE1;
556 } else {
557 SECU_PrintError(progName, "PKCS12 decode import bags failed");
558 pk12uErrno = PK12UERR_DECODEIMPTBAGS19;
559 goto loser;
560 }
561 }
562 } while (trypw);
563
564 /* revert the option setting */
565 if (forceUnicode != pk12uForceUnicode) {
566 rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c, pk12uForceUnicode);
567 if (rv != SECSuccess) {
568 SECU_PrintError(progName, "PKCS12 decode set option failed");
569 pk12uErrno = PK12UERR_DECODEIMPTBAGS19;
570 goto loser;
571 }
572 }
573
574 fprintf(stdoutstdout, "%s: PKCS12 IMPORT SUCCESSFUL\n", progName);
575 rv = SECSuccess;
576
577loser:
578 if (p12dcx) {
579 SEC_PKCS12DecoderFinish(p12dcx);
580 }
581
582 if (uniPwitem.data) {
583 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&uniPwitem, PR_FALSE0);
584 }
585
586 return rv;
587}
588
589static void
590p12u_DoPKCS12ExportErrors()
591{
592 PRErrorCode error_value;
593
594 error_value = PORT_GetErrorPORT_GetError_Util();
595 if ((error_value == SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY) ||
596 (error_value == SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME) ||
597 (error_value == SEC_ERROR_PKCS12_UNABLE_TO_WRITE)) {
598 fputs(SECU_Strerror(error_value)PR_ErrorToString((error_value), 0), stderrstderr);
599 } else if (error_value == SEC_ERROR_USER_CANCELLED) {
600 ;
601 } else {
602 fputs(SECU_Strerror(SEC_ERROR_EXPORTING_CERTIFICATES)PR_ErrorToString((SEC_ERROR_EXPORTING_CERTIFICATES), 0), stderrstderr);
603 }
604}
605
606static void
607p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
608{
609 p12uContext *p12cxt = arg;
610 int writeLen;
611
612 if (!p12cxt || (p12cxt->error == PR_TRUE1)) {
613 return;
614 }
615
616 if (p12cxt->file == NULL((void*)0)) {
617 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
618 p12cxt->error = PR_TRUE1;
619 return;
620 }
621
622 writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (PRInt32)len);
623
624 if (writeLen != (int)len) {
625 PR_Close(p12cxt->file);
626 PL_strfree(p12cxt->filename);
627 p12cxt->filename = NULL((void*)0);
628 p12cxt->file = NULL((void*)0);
629 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
630 p12cxt->error = PR_TRUE1;
631 }
632}
633
634void
635P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
636 SECOidTag cipher, SECOidTag certCipher, SECOidTag hash,
637 secuPWData *slotPw, secuPWData *p12FilePw)
638{
639 SEC_PKCS12ExportContext *p12ecx = NULL((void*)0);
640 SEC_PKCS12SafeInfo *keySafe = NULL((void*)0), *certSafe = NULL((void*)0);
641 SECItem *pwitem = NULL((void*)0);
642 p12uContext *p12cxt = NULL((void*)0);
643 CERTCertList *certlist = NULL((void*)0);
644 CERTCertListNode *node = NULL((void*)0);
645 PK11SlotInfo *slot = NULL((void*)0);
646
647 if (P12U_InitSlot(inSlot, slotPw) != SECSuccess) {
648 SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
649 PK11_GetSlotName(inSlot));
650 pk12uErrno = PK12UERR_PK11GETSLOT13;
651 goto loser;
652 }
653 certlist = PK11_FindCertsFromNickname(nn, slotPw);
654 if (!certlist) {
655 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNKNOWN_CERT);
656 SECU_PrintError(progName, "find user certs from nickname failed");
657 pk12uErrno = PK12UERR_FINDCERTBYNN24;
658 return;
659 }
660
661 if ((SECSuccess != CERT_FilterCertListForUserCerts(certlist)) ||
662 CERT_LIST_EMPTY(certlist)(((void *)((CERTCertListNode *)(&certlist->list)->next
)) == ((void *)&certlist->list))
) {
663 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: no user certs from given nickname\n",
664 progName);
665 pk12uErrno = PK12UERR_FINDCERTBYNN24;
666 goto loser;
667 }
668
669 /* Password to use for PKCS12 file. */
670 pwitem = P12U_GetP12FilePassword(PR_TRUE1, p12FilePw);
671 if (!pwitem) {
672 goto loser;
673 }
674
675 /* we are passing UTF8, drop the NULL in the normal password value.
676 * UCS2 conversion will add it back if necessary. This only affects
677 * password > Blocksize of the Hash function and pkcs5v2 pbe (if password
678 * <=Blocksize then the password is zero padded anyway, so an extra NULL
679 * at the end has not effect). This is allows us to work with openssl and
680 * gnutls. Older versions of NSS already fail to decrypt long passwords
681 * in this case, so we aren't breaking anyone with this code */
682 if ((pwitem->len > 0) && (!pwitem->data[pwitem->len - 1])) {
683 pwitem->len--;
684 }
685
686 p12cxt = p12u_InitContext(PR_FALSE0, outfile);
687 if (!p12cxt) {
688 SECU_PrintError(progName, "Initialization failed: %s", outfile);
689 pk12uErrno = PK12UERR_INIT_FILE10;
690 goto loser;
691 }
692
693 if (certlist) {
694 CERTCertificate *cert = CERT_LIST_HEAD(certlist)((CERTCertListNode *)(&certlist->list)->next)->cert;
695 if (cert) {
696 slot = cert->slot; /* use the slot from the first matching
697 certificate to create the context . This is for keygen */
698 }
699 }
700 if (!slot) {
701 SECU_PrintError(progName, "cert does not have a slot");
702 pk12uErrno = PK12UERR_FINDCERTBYNN24;
703 goto loser;
704 }
705 p12ecx = SEC_PKCS12CreateExportContext(NULL((void*)0), NULL((void*)0), slot, slotPw);
706 if (!p12ecx) {
707 SECU_PrintError(progName, "export context creation failed");
708 pk12uErrno = PK12UERR_EXPORTCXCREATE25;
709 goto loser;
710 }
711
712 if (SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, hash) !=
713 SECSuccess) {
714 SECU_PrintError(progName, "PKCS12 add password integrity failed");
715 pk12uErrno = PK12UERR_PK12ADDPWDINTEG26;
716 goto loser;
717 }
718
719 for (node = CERT_LIST_HEAD(certlist)((CERTCertListNode *)(&certlist->list)->next);
720 !CERT_LIST_END(node, certlist)(((void *)node) == ((void *)&certlist->list));
721 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
722 CERTCertificate *cert = node->cert;
723 if (!cert->slot) {
724 SECU_PrintError(progName, "cert does not have a slot");
725 pk12uErrno = PK12UERR_FINDCERTBYNN24;
726 goto loser;
727 }
728
729 keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
730 if (certCipher == SEC_OID_UNKNOWN) {
731 certSafe = keySafe;
732 } else {
733 certSafe =
734 SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem, certCipher);
735 }
736
737 if (!certSafe || !keySafe) {
738 SECU_PrintError(progName, "key or cert safe creation failed");
739 pk12uErrno = PK12UERR_CERTKEYSAFE27;
740 goto loser;
741 }
742
743 if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL((void*)0), cert,
744 CERT_GetDefaultCertDB(), keySafe, NULL((void*)0),
745 PR_TRUE1, pwitem, cipher) != SECSuccess) {
746 SECU_PrintError(progName, "add cert and key failed");
747 pk12uErrno = PK12UERR_ADDCERTKEY28;
748 goto loser;
749 }
750 }
751
752 CERT_DestroyCertList(certlist);
753 certlist = NULL((void*)0);
754
755 if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12cxt) !=
756 SECSuccess) {
757 SECU_PrintError(progName, "PKCS12 encode failed");
758 pk12uErrno = PK12UERR_ENCODE29;
759 goto loser;
760 }
761
762 p12u_DestroyContext(&p12cxt, PR_FALSE0);
763 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(pwitem, PR_TRUE1);
764 fprintf(stdoutstdout, "%s: PKCS12 EXPORT SUCCESSFUL\n", progName);
765 SEC_PKCS12DestroyExportContext(p12ecx);
766
767 return;
768
769loser:
770 SEC_PKCS12DestroyExportContext(p12ecx);
771
772 if (certlist) {
773 CERT_DestroyCertList(certlist);
774 certlist = NULL((void*)0);
775 }
776
777 p12u_DestroyContext(&p12cxt, PR_TRUE1);
778 if (pwitem) {
779 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(pwitem, PR_TRUE1);
780 }
781 p12u_DoPKCS12ExportErrors();
782 return;
783}
784
785PRIntn
786P12U_ListPKCS12File(char *in_file, PK11SlotInfo *slot,
787 secuPWData *slotPw, secuPWData *p12FilePw,
788 PRBool ignoreIntegrity)
789{
790 SEC_PKCS12DecoderContext *p12dcx = NULL((void*)0);
791 SECItem uniPwitem = { 0 };
792 SECStatus rv = SECFailure;
793 const SEC_PKCS12DecoderItem *dip;
794
795 p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw,
796 ignoreIntegrity);
797 /* did the blob authenticate properly? */
798 if (p12dcx == NULL((void*)0)) {
799 SECU_PrintError(progName, "PKCS12 decode not verified");
800 pk12uErrno = PK12UERR_DECODEVERIFY17;
801 goto loser;
802 }
803 rv = SEC_PKCS12DecoderIterateInit(p12dcx);
804 if (rv != SECSuccess) {
805 SECU_PrintError(progName, "PKCS12 decode iterate bags failed");
806 pk12uErrno = PK12UERR_DECODEIMPTBAGS19;
807 rv = SECFailure;
808 } else {
809 int fileCounter = 0;
810 while (SEC_PKCS12DecoderIterateNext(p12dcx, &dip) == SECSuccess) {
811 switch (dip->type) {
812 case SEC_OID_PKCS12_V1_CERT_BAG_ID:
813 printf("Certificate");
814 if (dumpRawFile) {
815 PRFileDesc *fd;
816 char fileName[20];
817 snprintf(fileName, sizeof(fileName), "file%04d.der", ++fileCounter);
818 fd = PR_Open(fileName,
819 PR_CREATE_FILE0x08 | PR_RDWR0x04 | PR_TRUNCATE0x20,
820 0600);
821 if (!fd) {
822 SECU_PrintError(progName,
823 "Cannot create output file");
824 } else {
825 PR_Write(fd, dip->der->data, dip->der->len);
826 PR_Close(fd);
827 }
828 } else if (SECU_PrintSignedData(stdoutstdout, dip->der,
829 (dip->hasKey) ? "(has private key)"
830 : "",
831 0, SECU_PrintCertificate) !=
832 0) {
833 SECU_PrintError(progName, "PKCS12 print cert bag failed");
834 }
835 if (dip->friendlyName != NULL((void*)0)) {
836 printf(" Friendly Name: %s\n\n",
837 dip->friendlyName->data);
838 }
839 if (dip->shroudAlg) {
840 SECU_PrintAlgorithmID(stdoutstdout, dip->shroudAlg,
841 "Encryption algorithm", 1);
842 }
843 break;
844 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
845 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
846 printf("Key");
847 if (dip->type == SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID)
848 printf("(shrouded)");
849 printf(":\n");
850 if (dip->friendlyName != NULL((void*)0)) {
851 printf(" Friendly Name: %s\n\n",
852 dip->friendlyName->data);
853 }
854 if (dip->shroudAlg) {
855 SECU_PrintAlgorithmID(stdoutstdout, dip->shroudAlg,
856 "Encryption algorithm", 1);
857 }
858 break;
859 default:
860 printf("unknown bag type(%d): %s\n\n", dip->type,
861 SECOID_FindOIDTagDescriptionSECOID_FindOIDTagDescription_Util(dip->type));
862 break;
863 }
864 }
865 rv = SECSuccess;
866 }
867
868loser:
869
870 if (p12dcx) {
871 SEC_PKCS12DecoderFinish(p12dcx);
872 }
873
874 if (uniPwitem.data) {
875 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&uniPwitem, PR_FALSE0);
876 }
877
878 return rv;
879}
880
881SECOidTag
882PKCS12U_FindTagFromString(char *cipherString)
883{
884 return SECOID_FindOIDTagFromDescripton(cipherString, (size_t)-1, PR_TRUE1);
885}
886
887/*
888 * use the oid table description to map a user input string to a particular
889 * oid.
890 */
891SECOidTag
892PKCS12U_MapCipherFromString(char *cipherString, int keyLen)
893{
894 SECOidTag tag;
895 SECOidTag cipher;
896
897 /* future enhancement: provide 'friendlier' typed in names for
898 * pbe mechanisms.
899 */
900
901 /* look for the oid tag by Description */
902 tag = PKCS12U_FindTagFromString(cipherString);
903 if (tag == SEC_OID_UNKNOWN) {
904 return tag;
905 }
906
907 cipher = SEC_OID_UNKNOWN;
Value stored to 'cipher' is never read
908 /* we found a match... get the PBE version of this
909 * cipher... */
910 if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) {
911 cipher = SEC_PKCS5GetPBEAlgorithm(tag, keyLen);
912 /* no eqivalent PKCS5/PKCS12 cipher, use the raw
913 * encryption tag we got and pass it directly in,
914 * pkcs12 will use the pkcsv5 mechanism */
915 if (cipher == SEC_OID_PKCS5_PBES2) {
916 cipher = tag;
917 } else if (cipher == SEC_OID_PKCS5_PBMAC1) {
918 /* make sure we have not macing ciphers here */
919 cipher = SEC_OID_UNKNOWN;
920 }
921 } else {
922 cipher = tag;
923 }
924 return cipher;
925}
926
927SECOidTag
928PKCS12U_MapHashFromString(char *hashString)
929{
930 SECOidTag hashAlg;
931
932 /* look for the oid tag by Description */
933 hashAlg = PKCS12U_FindTagFromString(hashString);
934 if (hashAlg == SEC_OID_UNKNOWN) {
935 return hashAlg;
936 }
937 /* make sure it's a hashing oid */
938 if (HASH_GetHashTypeByOidTagHASH_GetHashTypeByOidTag_Util(hashAlg) == HASH_AlgNULL) {
939 /* allow HMAC here. HMAC implies PKCS 5 v2 pba */
940 SECOidTag baseHashAlg = HASH_GetHashOidTagByHMACOidTagHASH_GetHashOidTagByHMACOidTag_Util(hashAlg);
941 if (baseHashAlg == SEC_OID_UNKNOWN) {
942 /* not an hmac either, reject the entry */
943 return SEC_OID_UNKNOWN;
944 }
945 }
946 return hashAlg;
947}
948
949static PRUintn
950P12U_Init(char *dir, char *dbprefix, PRBool listonly)
951{
952 SECStatus rv;
953 PK11_SetPasswordFunc(SECU_GetModulePassword);
954
955 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
956 if (listonly && NSS_NoDB_Init("") == SECSuccess) {
957 rv = SECSuccess;
958 } else {
959 rv = NSS_Initialize(dir, dbprefix, dbprefix, "secmod.db", 0);
960 }
961 if (rv != SECSuccess) {
962 SECU_PrintPRandOSError(progName);
963 exit(-1);
964 }
965
966 /* setup unicode callback functions */
967 PORT_SetUCS2_ASCIIConversionFunctionPORT_SetUCS2_ASCIIConversionFunction_Util(p12u_ucs2_ascii_conversion_function);
968 /* use the defaults for UCS4-UTF8 and UCS2-UTF8 */
969
970 /* ciphers are already enabled by default, allow policy to work */
971 /* p12u_EnableAllCiphers(); */
972
973 return 0;
974}
975
976enum {
977 opt_CertDir = 0,
978 opt_TokenName,
979 opt_Import,
980 opt_SlotPWFile,
981 opt_SlotPW,
982 opt_List,
983 opt_Nickname,
984 opt_Export,
985 opt_Raw,
986 opt_P12FilePWFile,
987 opt_P12FilePW,
988 opt_DBPrefix,
989 opt_Debug,
990 opt_Cipher,
991 opt_CertCipher,
992 opt_KeyLength,
993 opt_CertKeyLength,
994 opt_Mac,
995 opt_IgnoreIntegrity
996};
997
998static secuCommandFlag pk12util_options[] = {
999 { /* opt_CertDir */ 'd', PR_TRUE1, 0, PR_FALSE0 },
1000 { /* opt_TokenName */ 'h', PR_TRUE1, 0, PR_FALSE0 },
1001 { /* opt_Import */ 'i', PR_TRUE1, 0, PR_FALSE0 },
1002 { /* opt_SlotPWFile */ 'k', PR_TRUE1, 0, PR_FALSE0 },
1003 { /* opt_SlotPW */ 'K', PR_TRUE1, 0, PR_FALSE0 },
1004 { /* opt_List */ 'l', PR_TRUE1, 0, PR_FALSE0 },
1005 { /* opt_Nickname */ 'n', PR_TRUE1, 0, PR_FALSE0 },
1006 { /* opt_Export */ 'o', PR_TRUE1, 0, PR_FALSE0 },
1007 { /* opt_Raw */ 'r', PR_FALSE0, 0, PR_FALSE0 },
1008 { /* opt_P12FilePWFile */ 'w', PR_TRUE1, 0, PR_FALSE0 },
1009 { /* opt_P12FilePW */ 'W', PR_TRUE1, 0, PR_FALSE0 },
1010 { /* opt_DBPrefix */ 'P', PR_TRUE1, 0, PR_FALSE0 },
1011 { /* opt_Debug */ 'v', PR_FALSE0, 0, PR_FALSE0 },
1012 { /* opt_Cipher */ 'c', PR_TRUE1, 0, PR_FALSE0 },
1013 { /* opt_CertCipher */ 'C', PR_TRUE1, 0, PR_FALSE0 },
1014 { /* opt_KeyLength */ 'm', PR_TRUE1, 0, PR_FALSE0, "key_len" },
1015 { /* opt_CertKeyLength */ 0, PR_TRUE1, 0, PR_FALSE0, "cert_key_len" },
1016 { /* opt_Mac */ 'M', PR_TRUE1, 0, PR_FALSE0 },
1017 { /* opt_IgnoreIntegrity */ 'I', PR_FALSE0, 0, PR_FALSE0 }
1018};
1019
1020int
1021main(int argc, char **argv)
1022{
1023 secuPWData slotPw = { PW_NONE, NULL((void*)0) };
1024 secuPWData p12FilePw = { PW_NONE, NULL((void*)0) };
1025 PK11SlotInfo *slot;
1026 char *slotname = NULL((void*)0);
1027 char *import_file = NULL((void*)0);
1028 char *export_file = NULL((void*)0);
1029 char *dbprefix = "";
1030 SECStatus rv;
1031 SECOidTag cipher = SEC_OID_AES_256_CBC;
1032 SECOidTag hash = SEC_OID_SHA256;
1033 SECOidTag certCipher = SEC_OID_AES_128_CBC;
1034 int keyLen = 0;
1035 int certKeyLen = 0;
1036 secuCommand pk12util;
1037 PRInt32 forceUnicode;
1038 PRBool ignoreIntegrity = PR_FALSE0;
1039
1040#ifdef _CRTDBG_MAP_ALLOC
1041 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
1042#endif
1043
1044 pk12util.numCommands = 0;
1045 pk12util.commands = 0;
1046 pk12util.numOptions = sizeof(pk12util_options) / sizeof(secuCommandFlag);
1047 pk12util.options = pk12util_options;
1048
1049 progName = strrchr(argv[0], '/');
1050 progName = progName ? progName + 1 : argv[0];
1051
1052 rv = SECU_ParseCommandLine(argc, argv, progName, &pk12util);
1053
1054 if (rv != SECSuccess)
1055 Usage();
1056
1057 pk12_debugging = pk12util.options[opt_Debug].activated;
1058
1059 if ((pk12util.options[opt_Import].activated +
1060 pk12util.options[opt_Export].activated +
1061 pk12util.options[opt_List].activated) != 1) {
1062 Usage();
1063 }
1064
1065 if (pk12util.options[opt_Export].activated &&
1066 !pk12util.options[opt_Nickname].activated) {
1067 Usage();
1068 }
1069
1070 rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c, &forceUnicode);
1071 if (rv != SECSuccess) {
1072 SECU_PrintError(progName,
1073 "Failed to get NSS_PKCS12_DECODE_FORCE_UNICODE option");
1074 Usage();
1075 }
1076 pk12uForceUnicode = forceUnicode;
1077
1078 slotname = SECU_GetOptionArg(&pk12util, opt_TokenName);
1079
1080 import_file = (pk12util.options[opt_List].activated) ? SECU_GetOptionArg(&pk12util, opt_List)
1081 : SECU_GetOptionArg(&pk12util, opt_Import);
1082 export_file = SECU_GetOptionArg(&pk12util, opt_Export);
1083
1084 if (pk12util.options[opt_P12FilePWFile].activated) {
1085 p12FilePw.source = PW_FROMFILE;
1086 p12FilePw.data = PORT_StrdupPORT_Strdup_Util(pk12util.options[opt_P12FilePWFile].arg);
1087 }
1088
1089 if (pk12util.options[opt_P12FilePW].activated) {
1090 p12FilePw.source = PW_PLAINTEXT;
1091 p12FilePw.data = PORT_StrdupPORT_Strdup_Util(pk12util.options[opt_P12FilePW].arg);
1092 }
1093
1094 if (pk12util.options[opt_SlotPWFile].activated) {
1095 slotPw.source = PW_FROMFILE;
1096 slotPw.data = PORT_StrdupPORT_Strdup_Util(pk12util.options[opt_SlotPWFile].arg);
1097 }
1098
1099 if (pk12util.options[opt_SlotPW].activated) {
1100 slotPw.source = PW_PLAINTEXT;
1101 slotPw.data = PORT_StrdupPORT_Strdup_Util(pk12util.options[opt_SlotPW].arg);
1102 }
1103
1104 if (pk12util.options[opt_CertDir].activated) {
1105 SECU_ConfigDirectory(pk12util.options[opt_CertDir].arg);
1106 }
1107 if (pk12util.options[opt_DBPrefix].activated) {
1108 dbprefix = pk12util.options[opt_DBPrefix].arg;
1109 }
1110 if (pk12util.options[opt_Raw].activated) {
1111 dumpRawFile = PR_TRUE1;
1112 }
1113 if (pk12util.options[opt_IgnoreIntegrity].activated) {
1114 ignoreIntegrity = PR_TRUE1;
1115 }
1116 if (pk12util.options[opt_KeyLength].activated) {
1117 keyLen = atoi(pk12util.options[opt_KeyLength].arg);
1118 }
1119 if (pk12util.options[opt_CertKeyLength].activated) {
1120 certKeyLen = atoi(pk12util.options[opt_CertKeyLength].arg);
1121 }
1122
1123 P12U_Init(SECU_ConfigDirectory(NULL((void*)0)), dbprefix,
1124 pk12util.options[opt_List].activated);
1125
1126 if (!slotname || PL_strcmp(slotname, "internal") == 0)
1127 slot = PK11_GetInternalKeySlot();
1128 else
1129 slot = PK11_FindSlotByName(slotname);
1130
1131 if (!slot) {
1132 SECU_PrintError(progName, "Invalid slot \"%s\"", slotname);
1133 pk12uErrno = PK12UERR_PK11GETSLOT13;
1134 goto done;
1135 }
1136
1137 if (pk12util.options[opt_Cipher].activated) {
1138 char *cipherString = pk12util.options[opt_Cipher].arg;
1139
1140 cipher = PKCS12U_MapCipherFromString(cipherString, keyLen);
1141 /* We only want encryption PBE's. make sure we don't have
1142 * any MAC pbes */
1143 if (cipher == SEC_OID_UNKNOWN) {
1144 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
1145 SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
1146 pk12uErrno = PK12UERR_INVALIDALGORITHM30;
1147 goto done;
1148 }
1149 }
1150
1151 if (pk12util.options[opt_CertCipher].activated) {
1152 char *cipherString = pk12util.options[opt_CertCipher].arg;
1153
1154 if (PORT_StrcasecmpPL_strcasecmp(cipherString, "none") == 0) {
1155 certCipher = SEC_OID_UNKNOWN;
1156 } else {
1157 certCipher = PKCS12U_MapCipherFromString(cipherString, certKeyLen);
1158 /* If the user requested a cipher and we didn't find it, then
1159 * don't just silently not encrypt. */
1160 if (certCipher == SEC_OID_UNKNOWN) {
1161 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
1162 SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
1163 pk12uErrno = PK12UERR_INVALIDALGORITHM30;
1164 goto done;
1165 }
1166 }
1167 }
1168 /* in FIPS mode default to encoding with pkcs5v2 for the MAC */
1169 if (PK11_IsFIPS()) {
1170 hash = SEC_OID_HMAC_SHA256;
1171 }
1172 if (pk12util.options[opt_Mac].activated) {
1173 char *hashString = pk12util.options[opt_Mac].arg;
1174
1175 hash = PKCS12U_MapHashFromString(hashString);
1176 /* We don't support creating Mac-less pkcs 12 files */
1177 if (hash == SEC_OID_UNKNOWN) {
1178 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
1179 SECU_PrintError(progName, "Algorithm: \"%s\"", hashString);
1180 pk12uErrno = PK12UERR_INVALIDALGORITHM30;
1181 goto done;
1182 }
1183 }
1184
1185 if (pk12util.options[opt_Import].activated) {
1186 P12U_ImportPKCS12Object(import_file, slot, &slotPw, &p12FilePw,
1187 ignoreIntegrity);
1188
1189 } else if (pk12util.options[opt_Export].activated) {
1190 P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg,
1191 export_file, slot, cipher, certCipher,
1192 hash, &slotPw, &p12FilePw);
1193
1194 } else if (pk12util.options[opt_List].activated) {
1195 P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw,
1196 ignoreIntegrity);
1197
1198 } else {
1199 Usage();
1200 pk12uErrno = PK12UERR_USAGE2;
1201 }
1202
1203done:
1204 if (import_file != NULL((void*)0))
1205 PORT_ZFreePORT_ZFree_Util(import_file, PL_strlen(import_file));
1206 if (export_file != NULL((void*)0))
1207 PORT_ZFreePORT_ZFree_Util(export_file, PL_strlen(export_file));
1208 if (slotPw.data != NULL((void*)0))
1209 PORT_ZFreePORT_ZFree_Util(slotPw.data, PL_strlen(slotPw.data));
1210 if (p12FilePw.data != NULL((void*)0))
1211 PORT_ZFreePORT_ZFree_Util(p12FilePw.data, PL_strlen(p12FilePw.data));
1212 if (slot)
1213 PK11_FreeSlot(slot);
1214 if (NSS_Shutdown() != SECSuccess) {
1215 pk12uErrno = 1;
1216 }
1217 PL_ArenaFinish();
1218 PR_Cleanup();
1219 return pk12uErrno;
1220}