Bug Summary

File:s/cmd/pk12util/pk12util.c
Warning:line 913, 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=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/pk12util -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/pk12util -resource-dir /usr/lib/llvm-18/lib/clang/18 -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/Linux4.19_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-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c 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 [-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 [-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{
356 SEC_PKCS12DecoderContext *p12dcx = NULL((void*)0);
357 p12uContext *p12cxt = NULL((void*)0);
358 SECItem *pwitem = NULL((void*)0);
359 SECItem p12file = { 0 };
360 SECStatus rv = SECFailure;
361 PRBool swapUnicode = PR_FALSE0;
362 PRBool forceUnicode = pk12uForceUnicode;
363 PRBool trypw;
364 int error;
365
366#ifdef IS_LITTLE_ENDIAN1
367 swapUnicode = PR_TRUE1;
368#endif
369
370 p12cxt = p12u_InitContext(PR_TRUE1, in_file);
371 if (!p12cxt) {
372 SECU_PrintError(progName, "File Open failed: %s", in_file);
373 pk12uErrno = PK12UERR_INIT_FILE10;
374 return NULL((void*)0);
375 }
376
377 /* get the password */
378 pwitem = P12U_GetP12FilePassword(PR_FALSE0, p12FilePw);
379 if (!pwitem) {
380 pk12uErrno = PK12UERR_USER_CANCELLED1;
381 goto done;
382 }
383
384 if (P12U_UnicodeConversion(NULL((void*)0), uniPwp, pwitem, PR_TRUE1,
385 swapUnicode) != SECSuccess) {
386 SECU_PrintError(progName, "Unicode conversion failed");
387 pk12uErrno = PK12UERR_UNICODECONV11;
388 goto done;
389 }
390 rv = SECU_FileToItem(&p12file, p12cxt->file);
391 if (rv != SECSuccess) {
392 SECU_PrintError(progName, "Failed to read from import file");
393 goto done;
394 }
395
396 do {
397 trypw = PR_FALSE0; /* normally we do this once */
398 rv = SECFailure;
399 /* init the decoder context */
400 p12dcx = SEC_PKCS12DecoderStart(uniPwp, slot, slotPw,
401 NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0));
402 if (!p12dcx) {
403 SECU_PrintError(progName, "PKCS12 decoder start failed");
404 pk12uErrno = PK12UERR_PK12DECODESTART14;
405 break;
406 }
407
408 /* decode the item */
409 rv = SEC_PKCS12DecoderUpdate(p12dcx, p12file.data, p12file.len);
410
411 if (rv != SECSuccess) {
412 error = PR_GetError();
413 if (error == SEC_ERROR_DECRYPTION_DISALLOWED) {
414 PR_SetError(error, 0);
415 break;
416 }
417 SECU_PrintError(progName, "PKCS12 decoding failed");
418 pk12uErrno = PK12UERR_DECODE16;
419 }
420
421 /* does the blob authenticate properly? */
422 rv = SEC_PKCS12DecoderVerify(p12dcx);
423 if (rv != SECSuccess) {
424 if (uniPwp->len == 2) {
425 /* this is a null PW, try once more with a zero-length PW
426 instead of a null string */
427 SEC_PKCS12DecoderFinish(p12dcx);
428 uniPwp->len = 0;
429 trypw = PR_TRUE1;
430 } else if (forceUnicode == pk12uForceUnicode) {
431 /* try again with a different password encoding */
432 forceUnicode = !pk12uForceUnicode;
433 rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c,
434 forceUnicode);
435 if (rv != SECSuccess) {
436 SECU_PrintError(progName, "PKCS12 decoding failed to set option");
437 pk12uErrno = PK12UERR_DECODEVERIFY17;
438 break;
439 }
440 SEC_PKCS12DecoderFinish(p12dcx);
441 trypw = PR_TRUE1;
442 } else {
443 SECU_PrintError(progName, "PKCS12 decode not verified");
444 pk12uErrno = PK12UERR_DECODEVERIFY17;
445 break;
446 }
447 }
448 } while (trypw == PR_TRUE1);
449
450 /* revert the option setting */
451 if (forceUnicode != pk12uForceUnicode) {
452 rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c, pk12uForceUnicode);
453 if (rv != SECSuccess) {
454 SECU_PrintError(progName, "PKCS12 decoding failed to set option");
455 pk12uErrno = PK12UERR_DECODEVERIFY17;
456 }
457 }
458 /* rv has been set at this point */
459
460done:
461 if (rv != SECSuccess) {
462 if (p12dcx != NULL((void*)0)) {
463 SEC_PKCS12DecoderFinish(p12dcx);
464 p12dcx = NULL((void*)0);
465 }
466 if (uniPwp->data) {
467 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(uniPwp, PR_FALSE0);
468 uniPwp->data = NULL((void*)0);
469 }
470 }
471 PR_Close(p12cxt->file);
472 p12cxt->file = NULL((void*)0);
473 /* PK11_FreeSlot(slot); */
474 p12u_DestroyContext(&p12cxt, PR_FALSE0);
475
476 if (pwitem) {
477 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(pwitem, PR_TRUE1);
478 }
479 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&p12file, PR_FALSE0);
480 return p12dcx;
481}
482
483/*
484 * given a filename for pkcs12 file, imports certs and keys
485 *
486 * Change: altitude
487 * I've changed this function so that it takes the keydb and pkcs12 file
488 * passwords from files. The "pwdKeyDB" and "pwdP12File"
489 * variables have been added for this purpose.
490 */
491PRIntn
492P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot,
493 secuPWData *slotPw, secuPWData *p12FilePw)
494{
495 SEC_PKCS12DecoderContext *p12dcx = NULL((void*)0);
496 SECItem uniPwitem = { 0 };
497 PRBool forceUnicode = pk12uForceUnicode;
498 PRBool trypw;
499 SECStatus rv = SECFailure;
500
501 rv = P12U_InitSlot(slot, slotPw);
502 if (rv != SECSuccess) {
503 SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
504 PK11_GetSlotName(slot));
505 pk12uErrno = PK12UERR_PK11GETSLOT13;
506 return rv;
507 }
508
509 do {
510 trypw = PR_FALSE0; /* normally we do this once */
511 rv = SECFailure;
512 p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw);
513
514 if (p12dcx == NULL((void*)0)) {
515 goto loser;
516 }
517
518 /* make sure the bags are okey dokey -- nicknames correct, etc. */
519 rv = SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback);
520 if (rv != SECSuccess) {
521 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
522 pk12uErrno = PK12UERR_CERTALREADYEXISTS20;
523 } else {
524 pk12uErrno = PK12UERR_DECODEVALIBAGS18;
525 }
526 SECU_PrintError(progName, "PKCS12 decode validate bags failed");
527 goto loser;
528 }
529
530 /* stuff 'em in */
531 if (forceUnicode != pk12uForceUnicode) {
532 rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c,
533 forceUnicode);
534 if (rv != SECSuccess) {
535 SECU_PrintError(progName, "PKCS12 decode set option failed");
536 pk12uErrno = PK12UERR_DECODEIMPTBAGS19;
537 goto loser;
538 }
539 }
540 rv = SEC_PKCS12DecoderImportBags(p12dcx);
541 if (rv != SECSuccess) {
542 if (PR_GetError() == SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY &&
543 forceUnicode == pk12uForceUnicode) {
544 /* try again with a different password encoding */
545 forceUnicode = !pk12uForceUnicode;
546 SEC_PKCS12DecoderFinish(p12dcx);
547 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&uniPwitem, PR_FALSE0);
548 trypw = PR_TRUE1;
549 } else {
550 SECU_PrintError(progName, "PKCS12 decode import bags failed");
551 pk12uErrno = PK12UERR_DECODEIMPTBAGS19;
552 goto loser;
553 }
554 }
555 } while (trypw);
556
557 /* revert the option setting */
558 if (forceUnicode != pk12uForceUnicode) {
559 rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c, pk12uForceUnicode);
560 if (rv != SECSuccess) {
561 SECU_PrintError(progName, "PKCS12 decode set option failed");
562 pk12uErrno = PK12UERR_DECODEIMPTBAGS19;
563 goto loser;
564 }
565 }
566
567 fprintf(stdoutstdout, "%s: PKCS12 IMPORT SUCCESSFUL\n", progName);
568 rv = SECSuccess;
569
570loser:
571 if (p12dcx) {
572 SEC_PKCS12DecoderFinish(p12dcx);
573 }
574
575 if (uniPwitem.data) {
576 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&uniPwitem, PR_FALSE0);
577 }
578
579 return rv;
580}
581
582static void
583p12u_DoPKCS12ExportErrors()
584{
585 PRErrorCode error_value;
586
587 error_value = PORT_GetErrorPORT_GetError_Util();
588 if ((error_value == SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY) ||
589 (error_value == SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME) ||
590 (error_value == SEC_ERROR_PKCS12_UNABLE_TO_WRITE)) {
591 fputs(SECU_Strerror(error_value)PR_ErrorToString((error_value), 0), stderrstderr);
592 } else if (error_value == SEC_ERROR_USER_CANCELLED) {
593 ;
594 } else {
595 fputs(SECU_Strerror(SEC_ERROR_EXPORTING_CERTIFICATES)PR_ErrorToString((SEC_ERROR_EXPORTING_CERTIFICATES), 0), stderrstderr);
596 }
597}
598
599static void
600p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
601{
602 p12uContext *p12cxt = arg;
603 int writeLen;
604
605 if (!p12cxt || (p12cxt->error == PR_TRUE1)) {
606 return;
607 }
608
609 if (p12cxt->file == NULL((void*)0)) {
610 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
611 p12cxt->error = PR_TRUE1;
612 return;
613 }
614
615 writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (PRInt32)len);
616
617 if (writeLen != (int)len) {
618 PR_Close(p12cxt->file);
619 PL_strfree(p12cxt->filename);
620 p12cxt->filename = NULL((void*)0);
621 p12cxt->file = NULL((void*)0);
622 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
623 p12cxt->error = PR_TRUE1;
624 }
625}
626
627void
628P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
629 SECOidTag cipher, SECOidTag certCipher, SECOidTag hash,
630 secuPWData *slotPw, secuPWData *p12FilePw)
631{
632 SEC_PKCS12ExportContext *p12ecx = NULL((void*)0);
633 SEC_PKCS12SafeInfo *keySafe = NULL((void*)0), *certSafe = NULL((void*)0);
634 SECItem *pwitem = NULL((void*)0);
635 p12uContext *p12cxt = NULL((void*)0);
636 CERTCertList *certlist = NULL((void*)0);
637 CERTCertListNode *node = NULL((void*)0);
638 PK11SlotInfo *slot = NULL((void*)0);
639
640 if (P12U_InitSlot(inSlot, slotPw) != SECSuccess) {
641 SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
642 PK11_GetSlotName(inSlot));
643 pk12uErrno = PK12UERR_PK11GETSLOT13;
644 goto loser;
645 }
646 certlist = PK11_FindCertsFromNickname(nn, slotPw);
647 if (!certlist) {
648 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNKNOWN_CERT);
649 SECU_PrintError(progName, "find user certs from nickname failed");
650 pk12uErrno = PK12UERR_FINDCERTBYNN24;
651 return;
652 }
653
654 if ((SECSuccess != CERT_FilterCertListForUserCerts(certlist)) ||
655 CERT_LIST_EMPTY(certlist)(((void *)((CERTCertListNode *)(&certlist->list)->next
)) == ((void *)&certlist->list))
) {
656 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: no user certs from given nickname\n",
657 progName);
658 pk12uErrno = PK12UERR_FINDCERTBYNN24;
659 goto loser;
660 }
661
662 /* Password to use for PKCS12 file. */
663 pwitem = P12U_GetP12FilePassword(PR_TRUE1, p12FilePw);
664 if (!pwitem) {
665 goto loser;
666 }
667
668 /* we are passing UTF8, drop the NULL in the normal password value.
669 * UCS2 conversion will add it back if necessary. This only affects
670 * password > Blocksize of the Hash function and pkcs5v2 pbe (if password
671 * <=Blocksize then the password is zero padded anyway, so an extra NULL
672 * at the end has not effect). This is allows us to work with openssl and
673 * gnutls. Older versions of NSS already fail to decrypt long passwords
674 * in this case, so we aren't breaking anyone with this code */
675 if ((pwitem->len > 0) && (!pwitem->data[pwitem->len - 1])) {
676 pwitem->len--;
677 }
678
679 p12cxt = p12u_InitContext(PR_FALSE0, outfile);
680 if (!p12cxt) {
681 SECU_PrintError(progName, "Initialization failed: %s", outfile);
682 pk12uErrno = PK12UERR_INIT_FILE10;
683 goto loser;
684 }
685
686 if (certlist) {
687 CERTCertificate *cert = CERT_LIST_HEAD(certlist)((CERTCertListNode *)(&certlist->list)->next)->cert;
688 if (cert) {
689 slot = cert->slot; /* use the slot from the first matching
690 certificate to create the context . This is for keygen */
691 }
692 }
693 if (!slot) {
694 SECU_PrintError(progName, "cert does not have a slot");
695 pk12uErrno = PK12UERR_FINDCERTBYNN24;
696 goto loser;
697 }
698 p12ecx = SEC_PKCS12CreateExportContext(NULL((void*)0), NULL((void*)0), slot, slotPw);
699 if (!p12ecx) {
700 SECU_PrintError(progName, "export context creation failed");
701 pk12uErrno = PK12UERR_EXPORTCXCREATE25;
702 goto loser;
703 }
704
705 if (SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, hash) !=
706 SECSuccess) {
707 SECU_PrintError(progName, "PKCS12 add password integrity failed");
708 pk12uErrno = PK12UERR_PK12ADDPWDINTEG26;
709 goto loser;
710 }
711
712 for (node = CERT_LIST_HEAD(certlist)((CERTCertListNode *)(&certlist->list)->next);
713 !CERT_LIST_END(node, certlist)(((void *)node) == ((void *)&certlist->list));
714 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
715 CERTCertificate *cert = node->cert;
716 if (!cert->slot) {
717 SECU_PrintError(progName, "cert does not have a slot");
718 pk12uErrno = PK12UERR_FINDCERTBYNN24;
719 goto loser;
720 }
721
722 keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
723 if (certCipher == SEC_OID_UNKNOWN) {
724 certSafe = keySafe;
725 } else {
726 certSafe =
727 SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem, certCipher);
728 }
729
730 if (!certSafe || !keySafe) {
731 SECU_PrintError(progName, "key or cert safe creation failed");
732 pk12uErrno = PK12UERR_CERTKEYSAFE27;
733 goto loser;
734 }
735
736 if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL((void*)0), cert,
737 CERT_GetDefaultCertDB(), keySafe, NULL((void*)0),
738 PR_TRUE1, pwitem, cipher) != SECSuccess) {
739 SECU_PrintError(progName, "add cert and key failed");
740 pk12uErrno = PK12UERR_ADDCERTKEY28;
741 goto loser;
742 }
743 }
744
745 CERT_DestroyCertList(certlist);
746 certlist = NULL((void*)0);
747
748 if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12cxt) !=
749 SECSuccess) {
750 SECU_PrintError(progName, "PKCS12 encode failed");
751 pk12uErrno = PK12UERR_ENCODE29;
752 goto loser;
753 }
754
755 p12u_DestroyContext(&p12cxt, PR_FALSE0);
756 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(pwitem, PR_TRUE1);
757 fprintf(stdoutstdout, "%s: PKCS12 EXPORT SUCCESSFUL\n", progName);
758 SEC_PKCS12DestroyExportContext(p12ecx);
759
760 return;
761
762loser:
763 SEC_PKCS12DestroyExportContext(p12ecx);
764
765 if (certlist) {
766 CERT_DestroyCertList(certlist);
767 certlist = NULL((void*)0);
768 }
769
770 p12u_DestroyContext(&p12cxt, PR_TRUE1);
771 if (pwitem) {
772 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(pwitem, PR_TRUE1);
773 }
774 p12u_DoPKCS12ExportErrors();
775 return;
776}
777
778PRIntn
779P12U_ListPKCS12File(char *in_file, PK11SlotInfo *slot,
780 secuPWData *slotPw, secuPWData *p12FilePw)
781{
782 SEC_PKCS12DecoderContext *p12dcx = NULL((void*)0);
783 SECItem uniPwitem = { 0 };
784 SECStatus rv = SECFailure;
785 const SEC_PKCS12DecoderItem *dip;
786
787 p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw);
788 /* did the blob authenticate properly? */
789 if (p12dcx == NULL((void*)0)) {
790 SECU_PrintError(progName, "PKCS12 decode not verified");
791 pk12uErrno = PK12UERR_DECODEVERIFY17;
792 goto loser;
793 }
794 rv = SEC_PKCS12DecoderIterateInit(p12dcx);
795 if (rv != SECSuccess) {
796 SECU_PrintError(progName, "PKCS12 decode iterate bags failed");
797 pk12uErrno = PK12UERR_DECODEIMPTBAGS19;
798 rv = SECFailure;
799 } else {
800 int fileCounter = 0;
801 while (SEC_PKCS12DecoderIterateNext(p12dcx, &dip) == SECSuccess) {
802 switch (dip->type) {
803 case SEC_OID_PKCS12_V1_CERT_BAG_ID:
804 printf("Certificate");
805 if (dumpRawFile) {
806 PRFileDesc *fd;
807 char fileName[20];
808 snprintf(fileName, sizeof(fileName), "file%04d.der", ++fileCounter);
809 fd = PR_Open(fileName,
810 PR_CREATE_FILE0x08 | PR_RDWR0x04 | PR_TRUNCATE0x20,
811 0600);
812 if (!fd) {
813 SECU_PrintError(progName,
814 "Cannot create output file");
815 } else {
816 PR_Write(fd, dip->der->data, dip->der->len);
817 PR_Close(fd);
818 }
819 } else if (SECU_PrintSignedData(stdoutstdout, dip->der,
820 (dip->hasKey) ? "(has private key)"
821 : "",
822 0, (SECU_PPFunc)SECU_PrintCertificate) !=
823 0) {
824 SECU_PrintError(progName, "PKCS12 print cert bag failed");
825 }
826 if (dip->friendlyName != NULL((void*)0)) {
827 printf(" Friendly Name: %s\n\n",
828 dip->friendlyName->data);
829 }
830 if (dip->shroudAlg) {
831 SECU_PrintAlgorithmID(stdoutstdout, dip->shroudAlg,
832 "Encryption algorithm", 1);
833 }
834 break;
835 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
836 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
837 printf("Key");
838 if (dip->type == SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID)
839 printf("(shrouded)");
840 printf(":\n");
841 if (dip->friendlyName != NULL((void*)0)) {
842 printf(" Friendly Name: %s\n\n",
843 dip->friendlyName->data);
844 }
845 if (dip->shroudAlg) {
846 SECU_PrintAlgorithmID(stdoutstdout, dip->shroudAlg,
847 "Encryption algorithm", 1);
848 }
849 break;
850 default:
851 printf("unknown bag type(%d): %s\n\n", dip->type,
852 SECOID_FindOIDTagDescriptionSECOID_FindOIDTagDescription_Util(dip->type));
853 break;
854 }
855 }
856 rv = SECSuccess;
857 }
858
859loser:
860
861 if (p12dcx) {
862 SEC_PKCS12DecoderFinish(p12dcx);
863 }
864
865 if (uniPwitem.data) {
866 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&uniPwitem, PR_FALSE0);
867 }
868
869 return rv;
870}
871
872SECOidTag
873PKCS12U_FindTagFromString(char *cipherString)
874{
875 SECOidTag tag;
876 SECOidData *oid;
877
878 /* future enhancement: accept dotted oid spec? */
879
880 for (tag = 1; (oid = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(tag)) != NULL((void*)0); tag++) {
881 /* only interested in oids that we actually understand */
882 if (oid->mechanism == CKM_INVALID_MECHANISM0xffffffffUL) {
883 continue;
884 }
885 if (PORT_StrcasecmpPL_strcasecmp(oid->desc, cipherString) != 0) {
886 continue;
887 }
888 return tag;
889 }
890 return SEC_OID_UNKNOWN;
891}
892
893/*
894 * use the oid table description to map a user input string to a particular
895 * oid.
896 */
897SECOidTag
898PKCS12U_MapCipherFromString(char *cipherString, int keyLen)
899{
900 SECOidTag tag;
901 SECOidTag cipher;
902
903 /* future enhancement: provide 'friendlier' typed in names for
904 * pbe mechanisms.
905 */
906
907 /* look for the oid tag by Description */
908 tag = PKCS12U_FindTagFromString(cipherString);
909 if (tag == SEC_OID_UNKNOWN) {
910 return tag;
911 }
912
913 cipher = SEC_OID_UNKNOWN;
Value stored to 'cipher' is never read
914 /* we found a match... get the PBE version of this
915 * cipher... */
916 if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) {
917 cipher = SEC_PKCS5GetPBEAlgorithm(tag, keyLen);
918 /* no eqivalent PKCS5/PKCS12 cipher, use the raw
919 * encryption tag we got and pass it directly in,
920 * pkcs12 will use the pkcsv5 mechanism */
921 if (cipher == SEC_OID_PKCS5_PBES2) {
922 cipher = tag;
923 } else if (cipher == SEC_OID_PKCS5_PBMAC1) {
924 /* make sure we have not macing ciphers here */
925 cipher = SEC_OID_UNKNOWN;
926 }
927 } else {
928 cipher = tag;
929 }
930 return cipher;
931}
932
933SECOidTag
934PKCS12U_MapHashFromString(char *hashString)
935{
936 SECOidTag hashAlg;
937
938 /* look for the oid tag by Description */
939 hashAlg = PKCS12U_FindTagFromString(hashString);
940 if (hashAlg == SEC_OID_UNKNOWN) {
941 return hashAlg;
942 }
943 /* make sure it's a hashing oid */
944 if (HASH_GetHashTypeByOidTag(hashAlg) == HASH_AlgNULL) {
945 return SEC_OID_UNKNOWN;
946 }
947 return hashAlg;
948}
949
950static void
951p12u_EnableAllCiphers()
952{
953 SEC_PKCS12EnableCipher(PKCS12_RC4_40(0x00020000L | 0011), 1);
954 SEC_PKCS12EnableCipher(PKCS12_RC4_128(0x00020000L | 0012), 1);
955 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40(0x00020000L | 0001), 1);
956 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128(0x00020000L | 0002), 1);
957 SEC_PKCS12EnableCipher(PKCS12_DES_56(0x00020000L | 0021), 1);
958 SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168(0x00020000L | 0022), 1);
959 SEC_PKCS12EnableCipher(PKCS12_AES_CBC_128(0x00020000L | 0031), 1);
960 SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192(0x00020000L | 0032), 1);
961 SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256(0x00020000L | 0033), 1);
962 SEC_PKCS12SetPreferredCipher(PKCS12_AES_CBC_256(0x00020000L | 0033), 1);
963}
964
965static PRUintn
966P12U_Init(char *dir, char *dbprefix, PRBool listonly)
967{
968 SECStatus rv;
969 PK11_SetPasswordFunc(SECU_GetModulePassword);
970
971 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
972 if (listonly && NSS_NoDB_Init("") == SECSuccess) {
973 rv = SECSuccess;
974 } else {
975 rv = NSS_Initialize(dir, dbprefix, dbprefix, "secmod.db", 0);
976 }
977 if (rv != SECSuccess) {
978 SECU_PrintPRandOSError(progName);
979 exit(-1);
980 }
981
982 /* setup unicode callback functions */
983 PORT_SetUCS2_ASCIIConversionFunctionPORT_SetUCS2_ASCIIConversionFunction_Util(p12u_ucs2_ascii_conversion_function);
984 /* use the defaults for UCS4-UTF8 and UCS2-UTF8 */
985
986 p12u_EnableAllCiphers();
987
988 return 0;
989}
990
991enum {
992 opt_CertDir = 0,
993 opt_TokenName,
994 opt_Import,
995 opt_SlotPWFile,
996 opt_SlotPW,
997 opt_List,
998 opt_Nickname,
999 opt_Export,
1000 opt_Raw,
1001 opt_P12FilePWFile,
1002 opt_P12FilePW,
1003 opt_DBPrefix,
1004 opt_Debug,
1005 opt_Cipher,
1006 opt_CertCipher,
1007 opt_KeyLength,
1008 opt_CertKeyLength,
1009 opt_Mac
1010};
1011
1012static secuCommandFlag pk12util_options[] = {
1013 { /* opt_CertDir */ 'd', PR_TRUE1, 0, PR_FALSE0 },
1014 { /* opt_TokenName */ 'h', PR_TRUE1, 0, PR_FALSE0 },
1015 { /* opt_Import */ 'i', PR_TRUE1, 0, PR_FALSE0 },
1016 { /* opt_SlotPWFile */ 'k', PR_TRUE1, 0, PR_FALSE0 },
1017 { /* opt_SlotPW */ 'K', PR_TRUE1, 0, PR_FALSE0 },
1018 { /* opt_List */ 'l', PR_TRUE1, 0, PR_FALSE0 },
1019 { /* opt_Nickname */ 'n', PR_TRUE1, 0, PR_FALSE0 },
1020 { /* opt_Export */ 'o', PR_TRUE1, 0, PR_FALSE0 },
1021 { /* opt_Raw */ 'r', PR_FALSE0, 0, PR_FALSE0 },
1022 { /* opt_P12FilePWFile */ 'w', PR_TRUE1, 0, PR_FALSE0 },
1023 { /* opt_P12FilePW */ 'W', PR_TRUE1, 0, PR_FALSE0 },
1024 { /* opt_DBPrefix */ 'P', PR_TRUE1, 0, PR_FALSE0 },
1025 { /* opt_Debug */ 'v', PR_FALSE0, 0, PR_FALSE0 },
1026 { /* opt_Cipher */ 'c', PR_TRUE1, 0, PR_FALSE0 },
1027 { /* opt_CertCipher */ 'C', PR_TRUE1, 0, PR_FALSE0 },
1028 { /* opt_KeyLength */ 'm', PR_TRUE1, 0, PR_FALSE0, "key_len" },
1029 { /* opt_CertKeyLength */ 0, PR_TRUE1, 0, PR_FALSE0, "cert_key_len" },
1030 { /* opt_Mac */ 'M', PR_TRUE1, 0, PR_FALSE0, PR_FALSE0 }
1031};
1032
1033int
1034main(int argc, char **argv)
1035{
1036 secuPWData slotPw = { PW_NONE, NULL((void*)0) };
1037 secuPWData p12FilePw = { PW_NONE, NULL((void*)0) };
1038 PK11SlotInfo *slot;
1039 char *slotname = NULL((void*)0);
1040 char *import_file = NULL((void*)0);
1041 char *export_file = NULL((void*)0);
1042 char *dbprefix = "";
1043 SECStatus rv;
1044 SECOidTag cipher = SEC_OID_AES_256_CBC;
1045 SECOidTag hash = SEC_OID_SHA256;
1046 SECOidTag certCipher = SEC_OID_AES_128_CBC;
1047 int keyLen = 0;
1048 int certKeyLen = 0;
1049 secuCommand pk12util;
1050 PRInt32 forceUnicode;
1051
1052#ifdef _CRTDBG_MAP_ALLOC
1053 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
1054#endif
1055
1056 pk12util.numCommands = 0;
1057 pk12util.commands = 0;
1058 pk12util.numOptions = sizeof(pk12util_options) / sizeof(secuCommandFlag);
1059 pk12util.options = pk12util_options;
1060
1061 progName = strrchr(argv[0], '/');
1062 progName = progName ? progName + 1 : argv[0];
1063
1064 rv = SECU_ParseCommandLine(argc, argv, progName, &pk12util);
1065
1066 if (rv != SECSuccess)
1067 Usage();
1068
1069 pk12_debugging = pk12util.options[opt_Debug].activated;
1070
1071 if ((pk12util.options[opt_Import].activated +
1072 pk12util.options[opt_Export].activated +
1073 pk12util.options[opt_List].activated) != 1) {
1074 Usage();
1075 }
1076
1077 if (pk12util.options[opt_Export].activated &&
1078 !pk12util.options[opt_Nickname].activated) {
1079 Usage();
1080 }
1081
1082 rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE0x00c, &forceUnicode);
1083 if (rv != SECSuccess) {
1084 SECU_PrintError(progName,
1085 "Failed to get NSS_PKCS12_DECODE_FORCE_UNICODE option");
1086 Usage();
1087 }
1088 pk12uForceUnicode = forceUnicode;
1089
1090 slotname = SECU_GetOptionArg(&pk12util, opt_TokenName);
1091
1092 import_file = (pk12util.options[opt_List].activated) ? SECU_GetOptionArg(&pk12util, opt_List)
1093 : SECU_GetOptionArg(&pk12util, opt_Import);
1094 export_file = SECU_GetOptionArg(&pk12util, opt_Export);
1095
1096 if (pk12util.options[opt_P12FilePWFile].activated) {
1097 p12FilePw.source = PW_FROMFILE;
1098 p12FilePw.data = PORT_StrdupPORT_Strdup_Util(pk12util.options[opt_P12FilePWFile].arg);
1099 }
1100
1101 if (pk12util.options[opt_P12FilePW].activated) {
1102 p12FilePw.source = PW_PLAINTEXT;
1103 p12FilePw.data = PORT_StrdupPORT_Strdup_Util(pk12util.options[opt_P12FilePW].arg);
1104 }
1105
1106 if (pk12util.options[opt_SlotPWFile].activated) {
1107 slotPw.source = PW_FROMFILE;
1108 slotPw.data = PORT_StrdupPORT_Strdup_Util(pk12util.options[opt_SlotPWFile].arg);
1109 }
1110
1111 if (pk12util.options[opt_SlotPW].activated) {
1112 slotPw.source = PW_PLAINTEXT;
1113 slotPw.data = PORT_StrdupPORT_Strdup_Util(pk12util.options[opt_SlotPW].arg);
1114 }
1115
1116 if (pk12util.options[opt_CertDir].activated) {
1117 SECU_ConfigDirectory(pk12util.options[opt_CertDir].arg);
1118 }
1119 if (pk12util.options[opt_DBPrefix].activated) {
1120 dbprefix = pk12util.options[opt_DBPrefix].arg;
1121 }
1122 if (pk12util.options[opt_Raw].activated) {
1123 dumpRawFile = PR_TRUE1;
1124 }
1125 if (pk12util.options[opt_KeyLength].activated) {
1126 keyLen = atoi(pk12util.options[opt_KeyLength].arg);
1127 }
1128 if (pk12util.options[opt_CertKeyLength].activated) {
1129 certKeyLen = atoi(pk12util.options[opt_CertKeyLength].arg);
1130 }
1131
1132 P12U_Init(SECU_ConfigDirectory(NULL((void*)0)), dbprefix,
1133 pk12util.options[opt_List].activated);
1134
1135 if (!slotname || PL_strcmp(slotname, "internal") == 0)
1136 slot = PK11_GetInternalKeySlot();
1137 else
1138 slot = PK11_FindSlotByName(slotname);
1139
1140 if (!slot) {
1141 SECU_PrintError(progName, "Invalid slot \"%s\"", slotname);
1142 pk12uErrno = PK12UERR_PK11GETSLOT13;
1143 goto done;
1144 }
1145
1146 if (pk12util.options[opt_Cipher].activated) {
1147 char *cipherString = pk12util.options[opt_Cipher].arg;
1148
1149 cipher = PKCS12U_MapCipherFromString(cipherString, keyLen);
1150 /* We only want encryption PBE's. make sure we don't have
1151 * any MAC pbes */
1152 if (cipher == SEC_OID_UNKNOWN) {
1153 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
1154 SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
1155 pk12uErrno = PK12UERR_INVALIDALGORITHM30;
1156 goto done;
1157 }
1158 }
1159
1160 if (pk12util.options[opt_CertCipher].activated) {
1161 char *cipherString = pk12util.options[opt_CertCipher].arg;
1162
1163 if (PORT_StrcasecmpPL_strcasecmp(cipherString, "none") == 0) {
1164 certCipher = SEC_OID_UNKNOWN;
1165 } else {
1166 certCipher = PKCS12U_MapCipherFromString(cipherString, certKeyLen);
1167 /* If the user requested a cipher and we didn't find it, then
1168 * don't just silently not encrypt. */
1169 if (certCipher == SEC_OID_UNKNOWN) {
1170 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
1171 SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
1172 pk12uErrno = PK12UERR_INVALIDALGORITHM30;
1173 goto done;
1174 }
1175 }
1176 }
1177 if (pk12util.options[opt_Mac].activated) {
1178 char *hashString = pk12util.options[opt_Mac].arg;
1179
1180 hash = PKCS12U_MapHashFromString(hashString);
1181 /* We don't support creating Mac-less pkcs 12 files */
1182 if (hash == SEC_OID_UNKNOWN) {
1183 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
1184 SECU_PrintError(progName, "Algorithm: \"%s\"", hashString);
1185 pk12uErrno = PK12UERR_INVALIDALGORITHM30;
1186 goto done;
1187 }
1188 }
1189
1190 if (pk12util.options[opt_Import].activated) {
1191 P12U_ImportPKCS12Object(import_file, slot, &slotPw, &p12FilePw);
1192
1193 } else if (pk12util.options[opt_Export].activated) {
1194 P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg,
1195 export_file, slot, cipher, certCipher,
1196 hash, &slotPw, &p12FilePw);
1197
1198 } else if (pk12util.options[opt_List].activated) {
1199 P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw);
1200
1201 } else {
1202 Usage();
1203 pk12uErrno = PK12UERR_USAGE2;
1204 }
1205
1206done:
1207 if (import_file != NULL((void*)0))
1208 PORT_ZFreePORT_ZFree_Util(import_file, PL_strlen(import_file));
1209 if (export_file != NULL((void*)0))
1210 PORT_ZFreePORT_ZFree_Util(export_file, PL_strlen(export_file));
1211 if (slotPw.data != NULL((void*)0))
1212 PORT_ZFreePORT_ZFree_Util(slotPw.data, PL_strlen(slotPw.data));
1213 if (p12FilePw.data != NULL((void*)0))
1214 PORT_ZFreePORT_ZFree_Util(p12FilePw.data, PL_strlen(p12FilePw.data));
1215 if (slot)
1216 PK11_FreeSlot(slot);
1217 if (NSS_Shutdown() != SECSuccess) {
1218 pk12uErrno = 1;
1219 }
1220 PL_ArenaFinish();
1221 PR_Cleanup();
1222 return pk12uErrno;
1223}