1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/pk12util/pk12util.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1108 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifdef _CRTDBG_MAP_ALLOC 1.9 +#include <stdlib.h> 1.10 +#include <crtdbg.h> 1.11 +#endif 1.12 + 1.13 +#include "nspr.h" 1.14 +#include "secutil.h" 1.15 +#include "pk11func.h" 1.16 +#include "pkcs12.h" 1.17 +#include "p12plcy.h" 1.18 +#include "pk12util.h" 1.19 +#include "nss.h" 1.20 +#include "secport.h" 1.21 +#include "secpkcs5.h" 1.22 +#include "certdb.h" 1.23 + 1.24 +#define PKCS12_IN_BUFFER_SIZE 200 1.25 + 1.26 +static char *progName; 1.27 +PRBool pk12_debugging = PR_FALSE; 1.28 +PRBool dumpRawFile; 1.29 + 1.30 +PRIntn pk12uErrno = 0; 1.31 + 1.32 +static void 1.33 +Usage(char *progName) 1.34 +{ 1.35 +#define FPS PR_fprintf(PR_STDERR, 1.36 + FPS "Usage: %s -i importfile [-d certdir] [-P dbprefix] [-h tokenname]\n", 1.37 + progName); 1.38 + FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n"); 1.39 + FPS "\t\t [-v]\n"); 1.40 + 1.41 + FPS "Usage: %s -l listfile [-d certdir] [-P dbprefix] [-h tokenname]\n", 1.42 + progName); 1.43 + FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n"); 1.44 + FPS "\t\t [-v]\n"); 1.45 + 1.46 + FPS "Usage: %s -o exportfile -n certname [-d certdir] [-P dbprefix]\n", 1.47 + progName); 1.48 + FPS "\t\t [-c key_cipher] [-C cert_cipher]\n" 1.49 + "\t\t [-m | --key_len keyLen] [--cert_key_len certKeyLen] [-v]\n"); 1.50 + FPS "\t\t [-k slotpwfile | -K slotpw]\n" 1.51 + "\t\t [-w p12filepwfile | -W p12filefilepw]\n"); 1.52 + 1.53 + exit(PK12UERR_USAGE); 1.54 +} 1.55 + 1.56 +static PRBool 1.57 +p12u_OpenFile(p12uContext *p12cxt, PRBool fileRead) 1.58 +{ 1.59 + if(!p12cxt || !p12cxt->filename) { 1.60 + return PR_FALSE; 1.61 + } 1.62 + 1.63 + if(fileRead) { 1.64 + p12cxt->file = PR_Open(p12cxt->filename, 1.65 + PR_RDONLY, 0400); 1.66 + } else { 1.67 + p12cxt->file = PR_Open(p12cxt->filename, 1.68 + PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 1.69 + 0600); 1.70 + } 1.71 + 1.72 + if(!p12cxt->file) { 1.73 + p12cxt->error = PR_TRUE; 1.74 + return PR_FALSE; 1.75 + } 1.76 + 1.77 + return PR_TRUE; 1.78 +} 1.79 + 1.80 +static void 1.81 +p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile) 1.82 +{ 1.83 + if(!ppCtx || !(*ppCtx)) { 1.84 + return; 1.85 + } 1.86 + 1.87 + if((*ppCtx)->file != NULL) { 1.88 + PR_Close((*ppCtx)->file); 1.89 + } 1.90 + 1.91 + if((*ppCtx)->filename != NULL) { 1.92 + if(removeFile) { 1.93 + PR_Delete((*ppCtx)->filename); 1.94 + } 1.95 + PL_strfree((*ppCtx)->filename); 1.96 + (*ppCtx)->filename = NULL; 1.97 + } 1.98 + 1.99 + PR_Free(*ppCtx); 1.100 + *ppCtx = NULL; 1.101 +} 1.102 + 1.103 +static p12uContext * 1.104 +p12u_InitContext(PRBool fileImport, char *filename) 1.105 +{ 1.106 + p12uContext *p12cxt; 1.107 + PRBool fileExist; 1.108 + 1.109 + fileExist = fileImport; 1.110 + 1.111 + p12cxt = PORT_ZNew(p12uContext); 1.112 + if(!p12cxt) { 1.113 + return NULL; 1.114 + } 1.115 + 1.116 + p12cxt->error = PR_FALSE; 1.117 + p12cxt->errorValue = 0; 1.118 + p12cxt->filename = PL_strdup(filename); 1.119 + 1.120 + if(!p12u_OpenFile(p12cxt, fileImport)) { 1.121 + p12u_DestroyContext(&p12cxt, PR_FALSE); 1.122 + return NULL; 1.123 + } 1.124 + 1.125 + return p12cxt; 1.126 +} 1.127 + 1.128 +SECItem * 1.129 +P12U_NicknameCollisionCallback(SECItem *old_nick, PRBool *cancel, void *wincx) 1.130 +{ 1.131 + char *nick = NULL; 1.132 + SECItem *ret_nick = NULL; 1.133 + CERTCertificate* cert = (CERTCertificate*)wincx; 1.134 + 1.135 + if (!cancel || !cert) { 1.136 + pk12uErrno = PK12UERR_USER_CANCELLED; 1.137 + return NULL; 1.138 + } 1.139 + 1.140 + if (!old_nick) 1.141 + fprintf(stdout, "pk12util: no nickname for cert in PKCS12 file.\n"); 1.142 + 1.143 +#if 0 1.144 + /* XXX not handled yet */ 1.145 + *cancel = PR_TRUE; 1.146 + return NULL; 1.147 + 1.148 +#else 1.149 + 1.150 + nick = CERT_MakeCANickname(cert); 1.151 + if (!nick) { 1.152 + return NULL; 1.153 + } 1.154 + 1.155 + if(old_nick && old_nick->data && old_nick->len && 1.156 + PORT_Strlen(nick) == old_nick->len && 1.157 + !PORT_Strncmp((char *)old_nick->data, nick, old_nick->len)) { 1.158 + PORT_Free(nick); 1.159 + PORT_SetError(SEC_ERROR_IO); 1.160 + return NULL; 1.161 + } 1.162 + 1.163 + fprintf(stdout, "pk12util: using nickname: %s\n", nick); 1.164 + ret_nick = PORT_ZNew(SECItem); 1.165 + if(ret_nick == NULL) { 1.166 + PORT_Free(nick); 1.167 + return NULL; 1.168 + } 1.169 + 1.170 + ret_nick->data = (unsigned char *)nick; 1.171 + ret_nick->len = PORT_Strlen(nick); 1.172 + 1.173 + return ret_nick; 1.174 +#endif 1.175 +} 1.176 + 1.177 +static SECStatus 1.178 +p12u_SwapUnicodeBytes(SECItem *uniItem) 1.179 +{ 1.180 + unsigned int i; 1.181 + unsigned char a; 1.182 + if((uniItem == NULL) || (uniItem->len % 2)) { 1.183 + return SECFailure; 1.184 + } 1.185 + for(i = 0; i < uniItem->len; i += 2) { 1.186 + a = uniItem->data[i]; 1.187 + uniItem->data[i] = uniItem->data[i+1]; 1.188 + uniItem->data[i+1] = a; 1.189 + } 1.190 + return SECSuccess; 1.191 +} 1.192 + 1.193 +static PRBool 1.194 +p12u_ucs2_ascii_conversion_function(PRBool toUnicode, 1.195 + unsigned char *inBuf, 1.196 + unsigned int inBufLen, 1.197 + unsigned char *outBuf, 1.198 + unsigned int maxOutBufLen, 1.199 + unsigned int *outBufLen, 1.200 + PRBool swapBytes) 1.201 +{ 1.202 + SECItem it = { 0 }; 1.203 + SECItem *dup = NULL; 1.204 + PRBool ret; 1.205 + 1.206 +#ifdef DEBUG_CONVERSION 1.207 + if (pk12_debugging) { 1.208 + int i; 1.209 + printf("Converted from:\n"); 1.210 + for (i=0; i<inBufLen; i++) { 1.211 + printf("%2x ", inBuf[i]); 1.212 + /*if (i%60 == 0) printf("\n");*/ 1.213 + } 1.214 + printf("\n"); 1.215 + } 1.216 +#endif 1.217 + it.data = inBuf; 1.218 + it.len = inBufLen; 1.219 + dup = SECITEM_DupItem(&it); 1.220 + /* If converting Unicode to ASCII, swap bytes before conversion 1.221 + * as neccessary. 1.222 + */ 1.223 + if (!toUnicode && swapBytes) { 1.224 + if (p12u_SwapUnicodeBytes(dup) != SECSuccess) { 1.225 + SECITEM_ZfreeItem(dup, PR_TRUE); 1.226 + return PR_FALSE; 1.227 + } 1.228 + } 1.229 + /* Perform the conversion. */ 1.230 + ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len, 1.231 + outBuf, maxOutBufLen, outBufLen); 1.232 + if (dup) 1.233 + SECITEM_ZfreeItem(dup, PR_TRUE); 1.234 + 1.235 +#ifdef DEBUG_CONVERSION 1.236 + if (pk12_debugging) { 1.237 + int i; 1.238 + printf("Converted to:\n"); 1.239 + for (i=0; i<*outBufLen; i++) { 1.240 + printf("%2x ", outBuf[i]); 1.241 + /*if (i%60 == 0) printf("\n");*/ 1.242 + } 1.243 + printf("\n"); 1.244 + } 1.245 +#endif 1.246 + return ret; 1.247 +} 1.248 + 1.249 +SECStatus 1.250 +P12U_UnicodeConversion(PLArenaPool *arena, SECItem *dest, SECItem *src, 1.251 + PRBool toUnicode, PRBool swapBytes) 1.252 +{ 1.253 + unsigned int allocLen; 1.254 + if(!dest || !src) { 1.255 + return SECFailure; 1.256 + } 1.257 + allocLen = ((toUnicode) ? (src->len << 2) : src->len); 1.258 + if(arena) { 1.259 + dest->data = PORT_ArenaZAlloc(arena, allocLen); 1.260 + } else { 1.261 + dest->data = PORT_ZAlloc(allocLen); 1.262 + } 1.263 + if(PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len, 1.264 + dest->data, allocLen, &dest->len, 1.265 + swapBytes) == PR_FALSE) { 1.266 + if(!arena) { 1.267 + PORT_Free(dest->data); 1.268 + } 1.269 + dest->data = NULL; 1.270 + return SECFailure; 1.271 + } 1.272 + return SECSuccess; 1.273 +} 1.274 + 1.275 +/* 1.276 + * 1.277 + */ 1.278 +SECItem * 1.279 +P12U_GetP12FilePassword(PRBool confirmPw, secuPWData *p12FilePw) 1.280 +{ 1.281 + char *p0 = NULL; 1.282 + SECItem *pwItem = NULL; 1.283 + 1.284 + if (p12FilePw == NULL || p12FilePw->source == PW_NONE) { 1.285 + char *p1 = NULL; 1.286 + int rc; 1.287 + for (;;) { 1.288 + p0 = SECU_GetPasswordString(NULL, 1.289 + "Enter password for PKCS12 file: "); 1.290 + if (!confirmPw || p0 == NULL) 1.291 + break; 1.292 + p1 = SECU_GetPasswordString(NULL, "Re-enter password: "); 1.293 + if (p1 == NULL) { 1.294 + PORT_ZFree(p0, PL_strlen(p0)); 1.295 + p0 = NULL; 1.296 + break; 1.297 + } 1.298 + rc = PL_strcmp(p0, p1); 1.299 + PORT_ZFree(p1, PL_strlen(p1)); 1.300 + if (rc == 0) 1.301 + break; 1.302 + PORT_ZFree(p0, PL_strlen(p0)); 1.303 + } 1.304 + } else if (p12FilePw->source == PW_FROMFILE) { 1.305 + p0 = SECU_FilePasswd(NULL, PR_FALSE, p12FilePw->data); 1.306 + } else { /* Plaintext */ 1.307 + p0 = PORT_Strdup(p12FilePw->data); 1.308 + } 1.309 + 1.310 + if (p0 == NULL) { 1.311 + return NULL; 1.312 + } 1.313 + pwItem = SECITEM_AllocItem(NULL, NULL, PL_strlen(p0) + 1); 1.314 + memcpy(pwItem->data, p0, pwItem->len); 1.315 + 1.316 + PORT_ZFree(p0, PL_strlen(p0)); 1.317 + 1.318 + return pwItem; 1.319 +} 1.320 + 1.321 +SECStatus 1.322 +P12U_InitSlot(PK11SlotInfo *slot, secuPWData *slotPw) 1.323 +{ 1.324 + SECStatus rv; 1.325 + 1.326 + /* New databases, initialize keydb password. */ 1.327 + if (PK11_NeedUserInit(slot)) { 1.328 + rv = SECU_ChangePW(slot, 1.329 + (slotPw->source == PW_PLAINTEXT) ? slotPw->data : 0, 1.330 + (slotPw->source == PW_FROMFILE) ? slotPw->data : 0); 1.331 + if (rv != SECSuccess) { 1.332 + SECU_PrintError(progName, "Failed to initialize slot \"%s\"", 1.333 + PK11_GetSlotName(slot)); 1.334 + return SECFailure; 1.335 + } 1.336 + } 1.337 + 1.338 + if (PK11_Authenticate(slot, PR_TRUE, slotPw) != SECSuccess) { 1.339 + SECU_PrintError(progName, 1.340 + "Failed to authenticate to PKCS11 slot"); 1.341 + PORT_SetError(SEC_ERROR_USER_CANCELLED); 1.342 + pk12uErrno = PK12UERR_USER_CANCELLED; 1.343 + return SECFailure; 1.344 + } 1.345 + 1.346 + return SECSuccess; 1.347 +} 1.348 + 1.349 +/* This routine takes care of getting the PKCS12 file password, then reading and 1.350 + * verifying the file. It returns the decoder context and a filled in password. 1.351 + * (The password is needed by P12U_ImportPKCS12Object() to import the private 1.352 + * key.) 1.353 + */ 1.354 +SEC_PKCS12DecoderContext * 1.355 +p12U_ReadPKCS12File(SECItem *uniPwp, char *in_file, PK11SlotInfo *slot, 1.356 + secuPWData *slotPw, secuPWData *p12FilePw) 1.357 +{ 1.358 + SEC_PKCS12DecoderContext *p12dcx = NULL; 1.359 + p12uContext *p12cxt = NULL; 1.360 + SECItem *pwitem = NULL; 1.361 + SECItem p12file = { 0 }; 1.362 + SECStatus rv = SECFailure; 1.363 + PRBool swapUnicode = PR_FALSE; 1.364 + PRBool trypw; 1.365 + int error; 1.366 + 1.367 +#ifdef IS_LITTLE_ENDIAN 1.368 + swapUnicode = PR_TRUE; 1.369 +#endif 1.370 + 1.371 + p12cxt = p12u_InitContext(PR_TRUE, in_file); 1.372 + if(!p12cxt) { 1.373 + SECU_PrintError(progName,"File Open failed: %s", in_file); 1.374 + pk12uErrno = PK12UERR_INIT_FILE; 1.375 + return NULL; 1.376 + } 1.377 + 1.378 + /* get the password */ 1.379 + pwitem = P12U_GetP12FilePassword(PR_FALSE, p12FilePw); 1.380 + if (!pwitem) { 1.381 + pk12uErrno = PK12UERR_USER_CANCELLED; 1.382 + goto done; 1.383 + } 1.384 + 1.385 + if(P12U_UnicodeConversion(NULL, uniPwp, pwitem, PR_TRUE, 1.386 + swapUnicode) != SECSuccess) { 1.387 + SECU_PrintError(progName,"Unicode conversion failed"); 1.388 + pk12uErrno = PK12UERR_UNICODECONV; 1.389 + goto done; 1.390 + } 1.391 + rv = SECU_FileToItem(&p12file, p12cxt->file); 1.392 + if (rv != SECSuccess) { 1.393 + SECU_PrintError(progName,"Failed to read from import file"); 1.394 + goto done; 1.395 + } 1.396 + 1.397 + do { 1.398 + trypw = PR_FALSE; /* normally we do this once */ 1.399 + rv = SECFailure; 1.400 + /* init the decoder context */ 1.401 + p12dcx = SEC_PKCS12DecoderStart(uniPwp, slot, slotPw, 1.402 + NULL, NULL, NULL, NULL, NULL); 1.403 + if(!p12dcx) { 1.404 + SECU_PrintError(progName,"PKCS12 decoder start failed"); 1.405 + pk12uErrno = PK12UERR_PK12DECODESTART; 1.406 + break; 1.407 + } 1.408 + 1.409 + /* decode the item */ 1.410 + rv = SEC_PKCS12DecoderUpdate(p12dcx, p12file.data, p12file.len); 1.411 + 1.412 + if(rv != SECSuccess) { 1.413 + error = PR_GetError(); 1.414 + if(error == SEC_ERROR_DECRYPTION_DISALLOWED) { 1.415 + PR_SetError(error, 0); 1.416 + break; 1.417 + } 1.418 + SECU_PrintError(progName,"PKCS12 decoding failed"); 1.419 + pk12uErrno = PK12UERR_DECODE; 1.420 + } 1.421 + 1.422 + /* does the blob authenticate properly? */ 1.423 + rv = SEC_PKCS12DecoderVerify(p12dcx); 1.424 + if (rv != SECSuccess) { 1.425 + if(uniPwp->len == 2) { 1.426 + /* this is a null PW, try once more with a zero-length PW 1.427 + instead of a null string */ 1.428 + SEC_PKCS12DecoderFinish(p12dcx); 1.429 + uniPwp->len = 0; 1.430 + trypw = PR_TRUE; 1.431 + } 1.432 + else { 1.433 + SECU_PrintError(progName,"PKCS12 decode not verified"); 1.434 + pk12uErrno = PK12UERR_DECODEVERIFY; 1.435 + break; 1.436 + } 1.437 + } 1.438 + } while (trypw == PR_TRUE); 1.439 + /* rv has been set at this point */ 1.440 + 1.441 + 1.442 +done: 1.443 + if (rv != SECSuccess) { 1.444 + if (p12dcx != NULL) { 1.445 + SEC_PKCS12DecoderFinish(p12dcx); 1.446 + p12dcx = NULL; 1.447 + } 1.448 + if (uniPwp->data) { 1.449 + SECITEM_ZfreeItem(uniPwp, PR_FALSE); 1.450 + uniPwp->data = NULL; 1.451 + } 1.452 + } 1.453 + PR_Close(p12cxt->file); 1.454 + p12cxt->file = NULL; 1.455 + /* PK11_FreeSlot(slot); */ 1.456 + p12u_DestroyContext(&p12cxt, PR_FALSE); 1.457 + 1.458 + if (pwitem) { 1.459 + SECITEM_ZfreeItem(pwitem, PR_TRUE); 1.460 + } 1.461 + SECITEM_ZfreeItem(&p12file, PR_FALSE); 1.462 + return p12dcx; 1.463 +} 1.464 + 1.465 +/* 1.466 + * given a filename for pkcs12 file, imports certs and keys 1.467 + * 1.468 + * Change: altitude 1.469 + * I've changed this function so that it takes the keydb and pkcs12 file 1.470 + * passwords from files. The "pwdKeyDB" and "pwdP12File" 1.471 + * variables have been added for this purpose. 1.472 + */ 1.473 +PRIntn 1.474 +P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot, 1.475 + secuPWData *slotPw, secuPWData *p12FilePw) 1.476 +{ 1.477 + SEC_PKCS12DecoderContext *p12dcx = NULL; 1.478 + SECItem uniPwitem = { 0 }; 1.479 + SECStatus rv = SECFailure; 1.480 + 1.481 + rv = P12U_InitSlot(slot, slotPw); 1.482 + if (rv != SECSuccess) { 1.483 + SECU_PrintError(progName, "Failed to authenticate to \"%s\"", 1.484 + PK11_GetSlotName(slot)); 1.485 + pk12uErrno = PK12UERR_PK11GETSLOT; 1.486 + return rv; 1.487 + } 1.488 + 1.489 + rv = SECFailure; 1.490 + p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw); 1.491 + 1.492 + if(p12dcx == NULL) { 1.493 + goto loser; 1.494 + } 1.495 + 1.496 + /* make sure the bags are okey dokey -- nicknames correct, etc. */ 1.497 + rv = SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback); 1.498 + if (rv != SECSuccess) { 1.499 + if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) { 1.500 + pk12uErrno = PK12UERR_CERTALREADYEXISTS; 1.501 + } else { 1.502 + pk12uErrno = PK12UERR_DECODEVALIBAGS; 1.503 + } 1.504 + SECU_PrintError(progName,"PKCS12 decode validate bags failed"); 1.505 + goto loser; 1.506 + } 1.507 + 1.508 + /* stuff 'em in */ 1.509 + rv = SEC_PKCS12DecoderImportBags(p12dcx); 1.510 + if (rv != SECSuccess) { 1.511 + SECU_PrintError(progName,"PKCS12 decode import bags failed"); 1.512 + pk12uErrno = PK12UERR_DECODEIMPTBAGS; 1.513 + goto loser; 1.514 + } 1.515 + 1.516 + fprintf(stdout, "%s: PKCS12 IMPORT SUCCESSFUL\n", progName); 1.517 + rv = SECSuccess; 1.518 + 1.519 +loser: 1.520 + if (p12dcx) { 1.521 + SEC_PKCS12DecoderFinish(p12dcx); 1.522 + } 1.523 + 1.524 + if (uniPwitem.data) { 1.525 + SECITEM_ZfreeItem(&uniPwitem, PR_FALSE); 1.526 + } 1.527 + 1.528 + return rv; 1.529 +} 1.530 + 1.531 +static void 1.532 +p12u_DoPKCS12ExportErrors() 1.533 +{ 1.534 + PRErrorCode error_value; 1.535 + 1.536 + error_value = PORT_GetError(); 1.537 + if ((error_value == SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY) || 1.538 + (error_value == SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME) || 1.539 + (error_value == SEC_ERROR_PKCS12_UNABLE_TO_WRITE)) { 1.540 + fputs(SECU_Strerror(error_value), stderr); 1.541 + } else if(error_value == SEC_ERROR_USER_CANCELLED) { 1.542 + ; 1.543 + } else { 1.544 + fputs(SECU_Strerror(SEC_ERROR_EXPORTING_CERTIFICATES), stderr); 1.545 + } 1.546 +} 1.547 + 1.548 +static void 1.549 +p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len) 1.550 +{ 1.551 + p12uContext *p12cxt = arg; 1.552 + int writeLen; 1.553 + 1.554 + if(!p12cxt || (p12cxt->error == PR_TRUE)) { 1.555 + return; 1.556 + } 1.557 + 1.558 + if(p12cxt->file == NULL) { 1.559 + p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE; 1.560 + p12cxt->error = PR_TRUE; 1.561 + return; 1.562 + } 1.563 + 1.564 + writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (PRInt32)len); 1.565 + 1.566 + if(writeLen != (int)len) { 1.567 + PR_Close(p12cxt->file); 1.568 + PL_strfree(p12cxt->filename); 1.569 + p12cxt->filename = NULL; 1.570 + p12cxt->file = NULL; 1.571 + p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE; 1.572 + p12cxt->error = PR_TRUE; 1.573 + } 1.574 +} 1.575 + 1.576 + 1.577 +void 1.578 +P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot, 1.579 + SECOidTag cipher, SECOidTag certCipher, 1.580 + secuPWData *slotPw, secuPWData *p12FilePw) 1.581 +{ 1.582 + SEC_PKCS12ExportContext *p12ecx = NULL; 1.583 + SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL; 1.584 + SECItem *pwitem = NULL; 1.585 + p12uContext *p12cxt = NULL; 1.586 + CERTCertList* certlist = NULL; 1.587 + CERTCertListNode* node = NULL; 1.588 + PK11SlotInfo* slot = NULL; 1.589 + 1.590 + if (P12U_InitSlot(inSlot, slotPw) != SECSuccess) { 1.591 + SECU_PrintError(progName,"Failed to authenticate to \"%s\"", 1.592 + PK11_GetSlotName(inSlot)); 1.593 + pk12uErrno = PK12UERR_PK11GETSLOT; 1.594 + goto loser; 1.595 + } 1.596 + certlist = PK11_FindCertsFromNickname(nn, slotPw); 1.597 + if(!certlist) { 1.598 + SECU_PrintError(progName,"find user certs from nickname failed"); 1.599 + pk12uErrno = PK12UERR_FINDCERTBYNN; 1.600 + return; 1.601 + } 1.602 + 1.603 + if ((SECSuccess != CERT_FilterCertListForUserCerts(certlist)) || 1.604 + CERT_LIST_EMPTY(certlist)) { 1.605 + PR_fprintf(PR_STDERR, "%s: no user certs from given nickname\n", 1.606 + progName); 1.607 + pk12uErrno = PK12UERR_FINDCERTBYNN; 1.608 + goto loser; 1.609 + } 1.610 + 1.611 + /* Password to use for PKCS12 file. */ 1.612 + pwitem = P12U_GetP12FilePassword(PR_TRUE, p12FilePw); 1.613 + if(!pwitem) { 1.614 + goto loser; 1.615 + } 1.616 + 1.617 + p12cxt = p12u_InitContext(PR_FALSE, outfile); 1.618 + if(!p12cxt) { 1.619 + SECU_PrintError(progName,"Initialization failed: %s", outfile); 1.620 + pk12uErrno = PK12UERR_INIT_FILE; 1.621 + goto loser; 1.622 + } 1.623 + 1.624 + if (certlist) { 1.625 + CERTCertificate* cert = NULL; 1.626 + node = CERT_LIST_HEAD(certlist); 1.627 + if (node) { 1.628 + cert = node->cert; 1.629 + } 1.630 + if (cert) { 1.631 + slot = cert->slot; /* use the slot from the first matching 1.632 + certificate to create the context . This is for keygen */ 1.633 + } 1.634 + } 1.635 + if (!slot) { 1.636 + SECU_PrintError(progName,"cert does not have a slot"); 1.637 + pk12uErrno = PK12UERR_FINDCERTBYNN; 1.638 + goto loser; 1.639 + } 1.640 + p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, slotPw); 1.641 + if(!p12ecx) { 1.642 + SECU_PrintError(progName,"export context creation failed"); 1.643 + pk12uErrno = PK12UERR_EXPORTCXCREATE; 1.644 + goto loser; 1.645 + } 1.646 + 1.647 + if(SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, SEC_OID_SHA1) 1.648 + != SECSuccess) { 1.649 + SECU_PrintError(progName,"PKCS12 add password integrity failed"); 1.650 + pk12uErrno = PK12UERR_PK12ADDPWDINTEG; 1.651 + goto loser; 1.652 + } 1.653 + 1.654 + for (node = CERT_LIST_HEAD(certlist); 1.655 + !CERT_LIST_END(node,certlist); 1.656 + node=CERT_LIST_NEXT(node)) { 1.657 + CERTCertificate* cert = node->cert; 1.658 + if (!cert->slot) { 1.659 + SECU_PrintError(progName,"cert does not have a slot"); 1.660 + pk12uErrno = PK12UERR_FINDCERTBYNN; 1.661 + goto loser; 1.662 + } 1.663 + 1.664 + keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx); 1.665 + if(certCipher == SEC_OID_UNKNOWN) { 1.666 + certSafe = keySafe; 1.667 + } else { 1.668 + certSafe = 1.669 + SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem, certCipher); 1.670 + } 1.671 + 1.672 + if(!certSafe || !keySafe) { 1.673 + SECU_PrintError(progName,"key or cert safe creation failed"); 1.674 + pk12uErrno = PK12UERR_CERTKEYSAFE; 1.675 + goto loser; 1.676 + } 1.677 + 1.678 + if(SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert, 1.679 + CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem, cipher) 1.680 + != SECSuccess) { 1.681 + SECU_PrintError(progName,"add cert and key failed"); 1.682 + pk12uErrno = PK12UERR_ADDCERTKEY; 1.683 + goto loser; 1.684 + } 1.685 + } 1.686 + 1.687 + CERT_DestroyCertList(certlist); 1.688 + certlist = NULL; 1.689 + 1.690 + if(SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12cxt) 1.691 + != SECSuccess) { 1.692 + SECU_PrintError(progName,"PKCS12 encode failed"); 1.693 + pk12uErrno = PK12UERR_ENCODE; 1.694 + goto loser; 1.695 + } 1.696 + 1.697 + p12u_DestroyContext(&p12cxt, PR_FALSE); 1.698 + SECITEM_ZfreeItem(pwitem, PR_TRUE); 1.699 + fprintf(stdout, "%s: PKCS12 EXPORT SUCCESSFUL\n", progName); 1.700 + SEC_PKCS12DestroyExportContext(p12ecx); 1.701 + 1.702 + return; 1.703 + 1.704 +loser: 1.705 + SEC_PKCS12DestroyExportContext(p12ecx); 1.706 + 1.707 + if (certlist) { 1.708 + CERT_DestroyCertList(certlist); 1.709 + certlist = NULL; 1.710 + } 1.711 + 1.712 + p12u_DestroyContext(&p12cxt, PR_TRUE); 1.713 + if(pwitem) { 1.714 + SECITEM_ZfreeItem(pwitem, PR_TRUE); 1.715 + } 1.716 + p12u_DoPKCS12ExportErrors(); 1.717 + return; 1.718 +} 1.719 + 1.720 + 1.721 +PRIntn 1.722 +P12U_ListPKCS12File(char *in_file, PK11SlotInfo *slot, 1.723 + secuPWData *slotPw, secuPWData *p12FilePw) 1.724 +{ 1.725 + SEC_PKCS12DecoderContext *p12dcx = NULL; 1.726 + SECItem uniPwitem = { 0 }; 1.727 + SECStatus rv = SECFailure; 1.728 + const SEC_PKCS12DecoderItem *dip; 1.729 + 1.730 + p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw); 1.731 + /* did the blob authenticate properly? */ 1.732 + if(p12dcx == NULL) { 1.733 + SECU_PrintError(progName,"PKCS12 decode not verified"); 1.734 + pk12uErrno = PK12UERR_DECODEVERIFY; 1.735 + goto loser; 1.736 + } 1.737 + rv = SEC_PKCS12DecoderIterateInit(p12dcx); 1.738 + if(rv != SECSuccess) { 1.739 + SECU_PrintError(progName,"PKCS12 decode iterate bags failed"); 1.740 + pk12uErrno = PK12UERR_DECODEIMPTBAGS; 1.741 + rv = SECFailure; 1.742 + } else { 1.743 + int fileCounter = 0; 1.744 + while (SEC_PKCS12DecoderIterateNext(p12dcx, &dip) == SECSuccess) { 1.745 + switch (dip->type) { 1.746 + case SEC_OID_PKCS12_V1_CERT_BAG_ID: 1.747 + printf("Certificate"); 1.748 + if (dumpRawFile) { 1.749 + PRFileDesc * fd; 1.750 + char fileName[20]; 1.751 + sprintf(fileName, "file%04d.der", ++fileCounter); 1.752 + fd = PR_Open(fileName, 1.753 + PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 1.754 + 0600); 1.755 + if (!fd) { 1.756 + SECU_PrintError(progName, 1.757 + "Cannot create output file"); 1.758 + } else { 1.759 + PR_Write(fd, dip->der->data, dip->der->len); 1.760 + PR_Close(fd); 1.761 + } 1.762 + } else 1.763 + if (SECU_PrintSignedData(stdout, dip->der, 1.764 + (dip->hasKey) ? "(has private key)" : "", 1.765 + 0, SECU_PrintCertificate) != 0) { 1.766 + SECU_PrintError(progName,"PKCS12 print cert bag failed"); 1.767 + } 1.768 + if (dip->friendlyName != NULL) { 1.769 + printf(" Friendly Name: %s\n\n", 1.770 + dip->friendlyName->data); 1.771 + } 1.772 + if (dip->shroudAlg) { 1.773 + SECU_PrintAlgorithmID(stdout, dip->shroudAlg, 1.774 + "Encryption algorithm",1); 1.775 + } 1.776 + break; 1.777 + case SEC_OID_PKCS12_V1_KEY_BAG_ID: 1.778 + case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: 1.779 + printf("Key"); 1.780 + if (dip->type == SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID) 1.781 + printf("(shrouded)"); 1.782 + printf(":\n"); 1.783 + if (dip->friendlyName != NULL) { 1.784 + printf(" Friendly Name: %s\n\n", 1.785 + dip->friendlyName->data); 1.786 + } 1.787 + if (dip->shroudAlg) { 1.788 + SECU_PrintAlgorithmID(stdout, dip->shroudAlg, 1.789 + "Encryption algorithm",1); 1.790 + } 1.791 + break; 1.792 + default: 1.793 + printf("unknown bag type(%d): %s\n\n", dip->type, 1.794 + SECOID_FindOIDTagDescription(dip->type)); 1.795 + break; 1.796 + } 1.797 + } 1.798 + rv = SECSuccess; 1.799 + } 1.800 + 1.801 +loser: 1.802 + 1.803 + if (p12dcx) { 1.804 + SEC_PKCS12DecoderFinish(p12dcx); 1.805 + } 1.806 + 1.807 + if (uniPwitem.data) { 1.808 + SECITEM_ZfreeItem(&uniPwitem, PR_FALSE); 1.809 + } 1.810 + 1.811 + return rv; 1.812 +} 1.813 + 1.814 +/* 1.815 + * use the oid table description to map a user input string to a particular 1.816 + * oid. 1.817 + */ 1.818 +SECOidTag 1.819 +PKCS12U_MapCipherFromString(char *cipherString, int keyLen) 1.820 +{ 1.821 + SECOidTag tag; 1.822 + SECOidData *oid; 1.823 + SECOidTag cipher; 1.824 + 1.825 + /* future enhancement: accept dotted oid spec? */ 1.826 + 1.827 + /* future enhancement: provide 'friendlier' typed in names for 1.828 + * pbe mechanisms. 1.829 + */ 1.830 + 1.831 + /* look for the oid tag by Description */ 1.832 + cipher = SEC_OID_UNKNOWN; 1.833 + for (tag=1; (oid=SECOID_FindOIDByTag(tag)) != NULL ; tag++) { 1.834 + /* only interested in oids that we actually understand */ 1.835 + if (oid->mechanism == CKM_INVALID_MECHANISM) { 1.836 + continue; 1.837 + } 1.838 + if (PORT_Strcasecmp(oid->desc, cipherString) != 0) { 1.839 + continue; 1.840 + } 1.841 + /* we found a match... get the PBE version of this 1.842 + * cipher... */ 1.843 + if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) { 1.844 + cipher = SEC_PKCS5GetPBEAlgorithm(tag, keyLen); 1.845 + /* no eqivalent PKCS5/PKCS12 cipher, use the raw 1.846 + * encryption tag we got and pass it directly in, 1.847 + * pkcs12 will use the pkcsv5 mechanism */ 1.848 + if (cipher == SEC_OID_PKCS5_PBES2) { 1.849 + cipher = tag; 1.850 + } else if (cipher == SEC_OID_PKCS5_PBMAC1) { 1.851 + /* make sure we have not macing ciphers here */ 1.852 + cipher = SEC_OID_UNKNOWN; 1.853 + } 1.854 + } else { 1.855 + cipher = tag; 1.856 + } 1.857 + break; 1.858 + } 1.859 + return cipher; 1.860 +} 1.861 + 1.862 +static void 1.863 +p12u_EnableAllCiphers() 1.864 +{ 1.865 + SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1); 1.866 + SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1); 1.867 + SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1); 1.868 + SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1); 1.869 + SEC_PKCS12EnableCipher(PKCS12_DES_56, 1); 1.870 + SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1); 1.871 + SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1); 1.872 +} 1.873 + 1.874 +static PRUintn 1.875 +P12U_Init(char *dir, char *dbprefix, PRBool listonly) 1.876 +{ 1.877 + SECStatus rv; 1.878 + PK11_SetPasswordFunc(SECU_GetModulePassword); 1.879 + 1.880 + PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 1.881 + if (listonly && NSS_NoDB_Init("") == SECSuccess) { 1.882 + rv = SECSuccess; 1.883 + } 1.884 + else { 1.885 + rv = NSS_Initialize(dir,dbprefix,dbprefix,"secmod.db",0); 1.886 + } 1.887 + if (rv != SECSuccess) { 1.888 + SECU_PrintPRandOSError(progName); 1.889 + exit(-1); 1.890 + } 1.891 + 1.892 + /* setup unicode callback functions */ 1.893 + PORT_SetUCS2_ASCIIConversionFunction(p12u_ucs2_ascii_conversion_function); 1.894 + /* use the defaults for UCS4-UTF8 and UCS2-UTF8 */ 1.895 + 1.896 + p12u_EnableAllCiphers(); 1.897 + 1.898 + return 0; 1.899 +} 1.900 + 1.901 +enum { 1.902 + opt_CertDir = 0, 1.903 + opt_TokenName, 1.904 + opt_Import, 1.905 + opt_SlotPWFile, 1.906 + opt_SlotPW, 1.907 + opt_List, 1.908 + opt_Nickname, 1.909 + opt_Export, 1.910 + opt_Raw, 1.911 + opt_P12FilePWFile, 1.912 + opt_P12FilePW, 1.913 + opt_DBPrefix, 1.914 + opt_Debug, 1.915 + opt_Cipher, 1.916 + opt_CertCipher, 1.917 + opt_KeyLength, 1.918 + opt_CertKeyLength 1.919 +}; 1.920 + 1.921 +static secuCommandFlag pk12util_options[] = 1.922 +{ 1.923 + { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, 1.924 + { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE }, 1.925 + { /* opt_Import */ 'i', PR_TRUE, 0, PR_FALSE }, 1.926 + { /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE }, 1.927 + { /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE }, 1.928 + { /* opt_List */ 'l', PR_TRUE, 0, PR_FALSE }, 1.929 + { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE }, 1.930 + { /* opt_Export */ 'o', PR_TRUE, 0, PR_FALSE }, 1.931 + { /* opt_Raw */ 'r', PR_FALSE, 0, PR_FALSE }, 1.932 + { /* opt_P12FilePWFile */ 'w', PR_TRUE, 0, PR_FALSE }, 1.933 + { /* opt_P12FilePW */ 'W', PR_TRUE, 0, PR_FALSE }, 1.934 + { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE }, 1.935 + { /* opt_Debug */ 'v', PR_FALSE, 0, PR_FALSE }, 1.936 + { /* opt_Cipher */ 'c', PR_TRUE, 0, PR_FALSE }, 1.937 + { /* opt_CertCipher */ 'C', PR_TRUE, 0, PR_FALSE }, 1.938 + { /* opt_KeyLength */ 'm', PR_TRUE, 0, PR_FALSE, "key_len" }, 1.939 + { /* opt_CertKeyLength */ 0, PR_TRUE, 0, PR_FALSE, "cert_key_len" } 1.940 +}; 1.941 + 1.942 +int 1.943 +main(int argc, char **argv) 1.944 +{ 1.945 + secuPWData slotPw = { PW_NONE, NULL }; 1.946 + secuPWData p12FilePw = { PW_NONE, NULL }; 1.947 + PK11SlotInfo *slot; 1.948 + char *slotname = NULL; 1.949 + char *import_file = NULL; 1.950 + char *export_file = NULL; 1.951 + char *dbprefix = ""; 1.952 + SECStatus rv; 1.953 + SECOidTag cipher = 1.954 + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC; 1.955 + SECOidTag certCipher; 1.956 + int keyLen = 0; 1.957 + int certKeyLen = 0; 1.958 + secuCommand pk12util; 1.959 + 1.960 +#ifdef _CRTDBG_MAP_ALLOC 1.961 + _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); 1.962 +#endif 1.963 + 1.964 + pk12util.numCommands = 0; 1.965 + pk12util.commands = 0; 1.966 + pk12util.numOptions = sizeof(pk12util_options) / sizeof(secuCommandFlag); 1.967 + pk12util.options = pk12util_options; 1.968 + 1.969 + progName = strrchr(argv[0], '/'); 1.970 + progName = progName ? progName+1 : argv[0]; 1.971 + 1.972 + rv = SECU_ParseCommandLine(argc, argv, progName, &pk12util); 1.973 + 1.974 + if (rv != SECSuccess) 1.975 + Usage(progName); 1.976 + 1.977 + pk12_debugging = pk12util.options[opt_Debug].activated; 1.978 + 1.979 + if ((pk12util.options[opt_Import].activated + 1.980 + pk12util.options[opt_Export].activated + 1.981 + pk12util.options[opt_List].activated) != 1) { 1.982 + Usage(progName); 1.983 + } 1.984 + 1.985 + if (pk12util.options[opt_Export].activated && 1.986 + !pk12util.options[opt_Nickname].activated) { 1.987 + Usage(progName); 1.988 + } 1.989 + 1.990 + slotname = SECU_GetOptionArg(&pk12util, opt_TokenName); 1.991 + 1.992 + import_file = (pk12util.options[opt_List].activated) ? 1.993 + SECU_GetOptionArg(&pk12util, opt_List) : 1.994 + SECU_GetOptionArg(&pk12util, opt_Import); 1.995 + export_file = SECU_GetOptionArg(&pk12util, opt_Export); 1.996 + 1.997 + if (pk12util.options[opt_P12FilePWFile].activated) { 1.998 + p12FilePw.source = PW_FROMFILE; 1.999 + p12FilePw.data = PORT_Strdup(pk12util.options[opt_P12FilePWFile].arg); 1.1000 + } 1.1001 + 1.1002 + if (pk12util.options[opt_P12FilePW].activated) { 1.1003 + p12FilePw.source = PW_PLAINTEXT; 1.1004 + p12FilePw.data = PORT_Strdup(pk12util.options[opt_P12FilePW].arg); 1.1005 + } 1.1006 + 1.1007 + if (pk12util.options[opt_SlotPWFile].activated) { 1.1008 + slotPw.source = PW_FROMFILE; 1.1009 + slotPw.data = PORT_Strdup(pk12util.options[opt_SlotPWFile].arg); 1.1010 + } 1.1011 + 1.1012 + if (pk12util.options[opt_SlotPW].activated) { 1.1013 + slotPw.source = PW_PLAINTEXT; 1.1014 + slotPw.data = PORT_Strdup(pk12util.options[opt_SlotPW].arg); 1.1015 + } 1.1016 + 1.1017 + if (pk12util.options[opt_CertDir].activated) { 1.1018 + SECU_ConfigDirectory(pk12util.options[opt_CertDir].arg); 1.1019 + } 1.1020 + if (pk12util.options[opt_DBPrefix].activated) { 1.1021 + dbprefix = pk12util.options[opt_DBPrefix].arg; 1.1022 + } 1.1023 + if (pk12util.options[opt_Raw].activated) { 1.1024 + dumpRawFile = PR_TRUE; 1.1025 + } 1.1026 + if (pk12util.options[opt_KeyLength].activated) { 1.1027 + keyLen = atoi(pk12util.options[opt_KeyLength].arg); 1.1028 + } 1.1029 + if (pk12util.options[opt_CertKeyLength].activated) { 1.1030 + certKeyLen = atoi(pk12util.options[opt_CertKeyLength].arg); 1.1031 + } 1.1032 + 1.1033 + P12U_Init(SECU_ConfigDirectory(NULL), dbprefix, 1.1034 + pk12util.options[opt_List].activated); 1.1035 + 1.1036 + if (!slotname || PL_strcmp(slotname, "internal") == 0) 1.1037 + slot = PK11_GetInternalKeySlot(); 1.1038 + else 1.1039 + slot = PK11_FindSlotByName(slotname); 1.1040 + 1.1041 + if (!slot) { 1.1042 + SECU_PrintError(progName,"Invalid slot \"%s\"", slotname); 1.1043 + pk12uErrno = PK12UERR_PK11GETSLOT; 1.1044 + goto done; 1.1045 + } 1.1046 + 1.1047 + if (pk12util.options[opt_Cipher].activated) { 1.1048 + char *cipherString = pk12util.options[opt_Cipher].arg; 1.1049 + 1.1050 + cipher = PKCS12U_MapCipherFromString(cipherString, keyLen); 1.1051 + /* We only want encryption PBE's. make sure we don't have 1.1052 + * any MAC pbes */ 1.1053 + if (cipher == SEC_OID_UNKNOWN) { 1.1054 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.1055 + SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString); 1.1056 + pk12uErrno = PK12UERR_INVALIDALGORITHM; 1.1057 + goto done; 1.1058 + } 1.1059 + } 1.1060 + 1.1061 + certCipher = PK11_IsFIPS() ? SEC_OID_UNKNOWN : 1.1062 + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; 1.1063 + if (pk12util.options[opt_CertCipher].activated) { 1.1064 + char *cipherString = pk12util.options[opt_CertCipher].arg; 1.1065 + 1.1066 + if (PORT_Strcasecmp(cipherString, "none") == 0) { 1.1067 + certCipher = SEC_OID_UNKNOWN; 1.1068 + } else { 1.1069 + certCipher = PKCS12U_MapCipherFromString(cipherString, certKeyLen); 1.1070 + /* If the user requested a cipher and we didn't find it, then 1.1071 + * don't just silently not encrypt. */ 1.1072 + if (cipher == SEC_OID_UNKNOWN) { 1.1073 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.1074 + SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString); 1.1075 + pk12uErrno = PK12UERR_INVALIDALGORITHM; 1.1076 + goto done; 1.1077 + } 1.1078 + } 1.1079 + } 1.1080 + 1.1081 + 1.1082 + if (pk12util.options[opt_Import].activated) { 1.1083 + P12U_ImportPKCS12Object(import_file, slot, &slotPw, &p12FilePw); 1.1084 + 1.1085 + } else if (pk12util.options[opt_Export].activated) { 1.1086 + P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg, 1.1087 + export_file, slot, cipher, certCipher, 1.1088 + &slotPw, &p12FilePw); 1.1089 + 1.1090 + } else if (pk12util.options[opt_List].activated) { 1.1091 + P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw); 1.1092 + 1.1093 + } else { 1.1094 + Usage(progName); 1.1095 + pk12uErrno = PK12UERR_USAGE; 1.1096 + } 1.1097 + 1.1098 +done: 1.1099 + if (slotPw.data != NULL) 1.1100 + PORT_ZFree(slotPw.data, PL_strlen(slotPw.data)); 1.1101 + if (p12FilePw.data != NULL) 1.1102 + PORT_ZFree(p12FilePw.data, PL_strlen(p12FilePw.data)); 1.1103 + if (slot) 1.1104 + PK11_FreeSlot(slot); 1.1105 + if (NSS_Shutdown() != SECSuccess) { 1.1106 + pk12uErrno = 1; 1.1107 + } 1.1108 + PL_ArenaFinish(); 1.1109 + PR_Cleanup(); 1.1110 + return pk12uErrno; 1.1111 +}