Bug Summary

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