security/nss/cmd/pk12util/pk12util.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial