pk12util.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,236 行 · 第 1/2 页
C
1,236 行
PRBool retval;#ifdef DEBUG unsigned int i;#endif if(!inBuf || !outBuf || !outBufLen) { return PR_FALSE; }#ifdef DEBUG /* printf("---UCS4_UTF8Conversion (%s)---\nInput: " (toUnicode?"to UCS4":"to UTF8")); */ for(i=0; i< inBufLen; i++) { printf("%c", (char) inBuf[i]); } printf("\n"); for(i=0; i< inBufLen; i++) { printf("%2x ", (char) inBuf[i]); } printf("\n\n");#endif *outBufLen = 0; if(toUnicode) { retval = p12u_UTF8ToUCS4(inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen); } else { retval = p12u_UCS4ToUTF8(inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen); }#ifdef DEBUG printf("Output: "); for(i=0; i< *outBufLen; i++) { printf("%c", (char) outBuf[i]); } printf("\n"); for(i=0; i< *outBufLen; i++) { printf("%2x ", (char) outBuf[i]); } printf("\n\n");#endif return retval;}/* * */SECItem *P12U_GetP12FilePassword(PRBool confirmPw, secuPWData *p12FilePw){ char *p0 = NULL, *p1 = NULL; SECItem *pwItem = NULL; if (p12FilePw == NULL || p12FilePw->source == PW_NONE) { for (;;) { p0 = SECU_GetPasswordString(NULL, "Enter password for PKCS12 file: "); if (!confirmPw) break; p1 = SECU_GetPasswordString(NULL, "Re-enter password: "); if (PL_strcmp(p0, p1) == 0) break; } } else if (p12FilePw->source == PW_FROMFILE) { p0 = SECU_FilePasswd(NULL, PR_FALSE, p12FilePw->data); } else { /* Plaintext */ p0 = p12FilePw->data; } pwItem = SECITEM_AllocItem(NULL, NULL, PL_strlen(p0)); pwItem->data = PL_strdup(p0); PORT_Memset(p0, 0, PL_strlen(p0)); PORT_Free(p0); PORT_Memset(p1, 0, PL_strlen(p1)); PORT_Free(p1); return pwItem;}SECStatusP12U_InitSlot(PK11SlotInfo *slot, secuPWData *slotPw){ SECStatus rv; /* New databases, initialize keydb password. */ if (PK11_NeedUserInit(slot)) { rv = SECU_ChangePW(slot, (slotPw->source == PW_PLAINTEXT) ? slotPw->data : 0, (slotPw->source == PW_FROMFILE) ? slotPw->data : 0); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "%s: Failed to initialize slot \"%s\".\n", progName, PK11_GetSlotName(slot)); return SECFailure; } } if (PK11_Authenticate(slot, PR_TRUE, slotPw) != SECSuccess) { PR_fprintf(PR_STDERR, "%s: Failed to authenticate to PKCS11 slot.\n", progName); PORT_SetError(SEC_ERROR_USER_CANCELLED); pk12uErrno = PK12UERR_USER_CANCELLED; return SECFailure; } return SECSuccess;}/* !!! "kinda gross," said Tori. */static voidp12u_EnableAllCiphers(){ SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1); SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1); SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1); SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1); SEC_PKCS12EnableCipher(PKCS12_DES_56, 1); SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);}/* * given a filename for pkcs12 file, imports certs and keys * * Change: altitude * I've changed this function so that it takes the keydb and pkcs12 file * passwords from files. The "pwdKeyDB" and "pwdP12File" * variables have been added for this purpose. */PRIntnP12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot, secuPWData *slotPw, secuPWData *p12FilePw){ p12uContext *p12cxt = NULL, *tmpcxt = NULL; unsigned char inBuf[PKCS12_IN_BUFFER_SIZE]; SEC_PKCS12DecoderContext *p12dcx = NULL; SECItem *pwitem = NULL, uniPwitem = {0, 0}; SECStatus rv = SECFailure; PRBool swapUnicode = PR_FALSE; int error;#ifdef IS_LITTLE_ENDIAN swapUnicode = PR_TRUE;#endif rv = P12U_InitSlot(slot, slotPw); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "%s: Failed to authenticate to \"%s\".\n", progName, PK11_GetSlotName(slot)); pk12uErrno = PK12UERR_PK11GETSLOT; goto loser; } p12cxt = p12u_InitFile(PR_TRUE, in_file); if(!p12cxt) { printf("%s: Initialization failed: %s\n", progName, in_file); pk12uErrno = PK12UERR_INIT_FILE; goto loser; } /* get the password */ pwitem = P12U_GetP12FilePassword(PR_FALSE, p12FilePw); if (!pwitem) { pk12uErrno = PK12UERR_USER_CANCELLED; goto loser; } if(P12U_UnicodeConversion(NULL, &uniPwitem, pwitem, PR_TRUE, swapUnicode) != SECSuccess) { printf("%s: Unicode conversion failed \n", progName); pk12uErrno = PK12UERR_UNICODECONV; goto loser; } tmpcxt = p12u_CreateTemporaryDigestFile(); if(!tmpcxt) { printf("%s: Create Temporary digest file failed.\n", progName); pk12uErrno = PK12UERR_TMPDIGCREATE; goto loser; } /* init the decoder context */ p12dcx = SEC_PKCS12DecoderStart(&uniPwitem, slot, NULL, p12u_DigestOpen, p12u_DigestClose, p12u_DigestRead, p12u_DigestWrite, tmpcxt); if(!p12dcx) { printf("%s: PKCS12 decoder start failed.\n", progName); pk12uErrno = PK12UERR_PK12DECODESTART; goto loser; } /* decode the item */ while(PR_TRUE) { int readLen = p12u_ReadFromImportFile(p12cxt, inBuf, PKCS12_IN_BUFFER_SIZE); if(readLen < 0) { printf("%s: Reading from importfile failed\n", progName); pk12uErrno = PK12UERR_IMPORTFILEREAD; goto loser; } rv = SEC_PKCS12DecoderUpdate(p12dcx, inBuf, readLen); if(rv != SECSuccess || readLen != PKCS12_IN_BUFFER_SIZE) { break; } } if(rv != SECSuccess) { error = PR_GetError(); if(error == SEC_ERROR_DECRYPTION_DISALLOWED) { PR_SetError(error, 0); goto loser; }#ifdef EXTRA /* unable to import as a new blob, it might be an old one */ if(p12u_TryToImportOldPDU(p12cxt, pwitem, slot, import_arg->nickCb, import_arg->proto_win) != SECSuccess) { goto loser; } goto tried_pdu_import;#endif /* EXTRA */ printf("%s: PKCS12 decoding failed.\n", progName); pk12uErrno = PK12UERR_DECODE; } rv = SECFailure; /* does the blob authenticate properly? */ if(SEC_PKCS12DecoderVerify(p12dcx) != SECSuccess) { printf("%s: PKCS12 decode not verified\n", progName); pk12uErrno = PK12UERR_DECODEVERIFY; goto loser; } /* make sure the bags are okey dokey -- nicknames correct, etc. */ if (SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback) != SECSuccess) { if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) { pk12uErrno = PK12UERR_CERTALREADYEXISTS; } printf("%s: PKCS12 decode validate bags failed.\n", progName); pk12uErrno = PK12UERR_DECODEVALIBAGS; goto loser; } /* stuff 'em in */ if(SEC_PKCS12DecoderImportBags(p12dcx) != SECSuccess) { printf("%s: PKCS12 decode import bags failed.\n", progName); pk12uErrno = PK12UERR_DECODEIMPTBAGS; goto loser; }#if 0 /* important - to add the password hash into the key database */ rv = PK11_CheckUserPassword(slot, pw_string); if( rv != SECSuccess ) { printf("Failed to CheckUserPassword\n"); exit(-1); }#endif PR_Close(p12cxt->file); p12cxt->file = NULL; PK11_FreeSlot(slot); rv = SECSuccess;loser: if (rv != SECSuccess) { /* pk12u_report_failure */ } else { /* pk12u_report_success ? */ } if (p12dcx) { SEC_PKCS12DecoderFinish(p12dcx); } p12u_DestroyExportFileInfo(&p12cxt, PR_FALSE); if (uniPwitem.data) { SECITEM_ZfreeItem(&uniPwitem, PR_FALSE); } if (pwitem) { SECITEM_ZfreeItem(pwitem, PR_TRUE); } return rv; }static voidp12u_DoPKCS12ExportErrors(){ int error_value; error_value = PORT_GetError(); if ((error_value == SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY) || (error_value == SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME) || (error_value == SEC_ERROR_PKCS12_UNABLE_TO_WRITE)) { fprintf(stderr, SECU_ErrorStringRaw((int16)error_value)); } else if(error_value == SEC_ERROR_USER_CANCELLED) { ; } else { fprintf(stderr, SECU_ErrorStringRaw(SEC_ERROR_EXPORTING_CERTIFICATES)); }}static voidp12u_WriteToExportFile(void *arg, const char *buf, unsigned long len){ p12uContext *p12cxt = arg; int writeLen; if(!p12cxt || (p12cxt->error == PR_TRUE)) { return; } if(p12cxt->file == NULL) { p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE; p12cxt->error = PR_TRUE; return; } writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len); if(writeLen != (int)len) { PR_Close(p12cxt->file); PR_Delete(p12cxt->filename); p12cxt->file = NULL; p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE; p12cxt->error = PR_TRUE; }}voidP12U_ExportPKCS12Object(char *nn, char *outfile, secuPWData *slotPw, secuPWData *p12FilePw){ SEC_PKCS12ExportContext *p12ecx = NULL; SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL; SECItem *pwitem = NULL; PK11SlotInfo *slot = NULL; p12uContext *p12cxt = NULL; CERTCertificate *cert; cert = PK11_FindCertFromNickname(nn, NULL); if(!cert) { printf("%s: find cert by nickname failed.\n", progName); pk12uErrno = PK12UERR_FINDCERTBYNN; return; } /* Password to use for PKCS12 file. */ pwitem = P12U_GetP12FilePassword(PR_TRUE, p12FilePw); if(!pwitem) { goto loser; } p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, cert->slot, NULL); if(!p12ecx) { printf("%s: export context creation failed.\n", progName); pk12uErrno = PK12UERR_EXPORTCXCREATE; goto loser; } if(SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, SEC_OID_SHA1) != SECSuccess) { printf("%s: PKCS12 add password integrity failed.\n", progName); pk12uErrno = PK12UERR_PK12ADDPWDINTEG; goto loser; } keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx); if(!SEC_PKCS12IsEncryptionAllowed() || PK11_IsFIPS()) { certSafe = keySafe; } else { certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem, SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC); } if(!certSafe || !keySafe) { printf("%s: key or cert safe creation failed.\n", progName); pk12uErrno = PK12UERR_CERTKEYSAFE; goto loser; } if(SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert, CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem, SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC) != SECSuccess) { printf("%s: add cert and key failed.\n", progName); pk12uErrno = PK12UERR_ADDCERTKEY; goto loser; } p12cxt = p12u_InitFile(PR_FALSE, outfile); if(!p12cxt) { printf("%s: Initialization failed: %s\n", progName, outfile); pk12uErrno = PK12UERR_INIT_FILE; goto loser; } if(SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12cxt) != SECSuccess) { printf("%s: PKCS12 encode failed.\n", progName); pk12uErrno = PK12UERR_ENCODE; goto loser; } p12u_DestroyExportFileInfo(&p12cxt, PR_FALSE); SECITEM_ZfreeItem(pwitem, PR_TRUE); CERT_DestroyCertificate(cert); if(slot) { PK11_FreeSlot(slot); } fprintf(stdout, "%s: PKCS12 EXPORT SUCCESSFUL\n", progName); SEC_PKCS12DestroyExportContext(p12ecx); return;loser: SEC_PKCS12DestroyExportContext(p12ecx); if (slotPw) PR_Free(slotPw->data); if (p12FilePw) PR_Free(p12FilePw->data); if(slot && (slot != cert->slot)) { PK11_FreeSlot(slot); } if(cert) { CERT_DestroyCertificate(cert); } p12u_DestroyExportFileInfo(&p12cxt, PR_TRUE); if(pwitem) { SECITEM_ZfreeItem(pwitem, PR_TRUE); } p12u_DoPKCS12ExportErrors(); return;}static PRUintnP12U_Init(){ PK11_SetPasswordFunc(SECU_GetModulePassword); PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); SECU_PKCS11Init(PR_FALSE); SEC_Init(); /* needed for PK11_FindCertByNickname on internal token */ SECU_OpenCertDB(PR_TRUE); /* enable all ciphers */ p12u_EnableAllCiphers(); /* setup unicode callback functions */ PORT_SetUCS2_ASCIIConversionFunction(P12U_UCS2_ASCIIConversion);#ifdef nodef PORT_SetUCS4_UTF8ConversionFunction(P12U_UCS4_UTF8Conversion); PORT_SetUCS2_UTF8ConversionFunction(P12U_UCS2_UTF8Conversion);#endif return 0;}/* * Shutdown the security library. * * Currently closes the certificate and key databases. * XXX this should be handled elsewhere (NSS_Shutdown?) */voidP12U_Shutdown(void){ CERTCertDBHandle *cdb_handle; SECKEYKeyDBHandle *kdb_handle; cdb_handle = CERT_GetDefaultCertDB(); if (cdb_handle != NULL) { CERT_ClosePermCertDB(cdb_handle); } kdb_handle = SECKEY_GetDefaultKeyDB(); if (kdb_handle != NULL) { SECKEY_CloseKeyDB(kdb_handle); }}enum { opt_CertDir = 0, opt_TokenName, opt_Import, opt_SlotPWFile, opt_SlotPW, opt_Mode, opt_Nickname, opt_Export, opt_P12FilePWFile, opt_P12FilePW};static secuCommandFlag pk12util_options[] ={ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE }, { /* opt_Import */ 'i', PR_TRUE, 0, PR_FALSE }, { /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE }, { /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE }, { /* opt_Mode */ 'm', PR_TRUE, 0, PR_FALSE }, { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE }, { /* opt_Export */ 'o', PR_TRUE, 0, PR_FALSE }, { /* opt_P12FilePWFile */ 'w', PR_TRUE, 0, PR_FALSE }, { /* opt_P12FilePW */ 'W', PR_TRUE, 0, PR_FALSE }};intmain(int argc, char **argv){ PRIntn ret = 0; secuPWData slotPw = { PW_NONE, NULL }; secuPWData p12FilePw = { PW_NONE, NULL }; PK11SlotInfo *slot; char *slotname = NULL; SECStatus rv; secuCommand pk12util; pk12util.numCommands = 0; pk12util.commands = 0; pk12util.numOptions = sizeof(pk12util_options) / sizeof(secuCommandFlag); pk12util.options = pk12util_options; progName = strrchr(argv[0], '/'); progName = progName ? progName+1 : argv[0]; rv = SECU_ParseCommandLine(argc, argv, progName, &pk12util); if (rv != SECSuccess) Usage(progName); if (pk12util.options[opt_Import].activated && pk12util.options[opt_Export].activated) { Usage(progName); } if (pk12util.options[opt_Export].activated && !pk12util.options[opt_Nickname].activated) { Usage(progName); } if (pk12util.options[opt_CertDir].activated) SECU_ConfigDirectory(pk12util.options[opt_CertDir].arg); slotname = SECU_GetOptionArg(&pk12util, opt_TokenName); if (pk12util.options[opt_P12FilePWFile].activated) { p12FilePw.source = PW_FROMFILE; p12FilePw.data = PL_strdup(pk12util.options[opt_P12FilePWFile].arg); } if (pk12util.options[opt_P12FilePW].activated) { p12FilePw.source = PW_PLAINTEXT; p12FilePw.data = PL_strdup(pk12util.options[opt_P12FilePW].arg); } if (pk12util.options[opt_SlotPWFile].activated) { slotPw.source = PW_FROMFILE; slotPw.data = PL_strdup(pk12util.options[opt_SlotPWFile].arg); } if (pk12util.options[opt_SlotPW].activated) { slotPw.source = PW_PLAINTEXT; slotPw.data = PL_strdup(pk12util.options[opt_SlotPW].arg); } P12U_Init(); if (pk12util.options[opt_Import].activated) { if (!slotname || PL_strcmp(slotname, "internal") == 0) slot = PK11_GetInternalKeySlot(); else slot = PK11_FindSlotByName(slotname); if (!slot) { PR_fprintf(PR_STDERR, "%s: Invalid slot \"%s\".\n", progName, slotname); goto done; } if ((ret = P12U_ImportPKCS12Object(pk12util.options[opt_Import].arg, slot, &slotPw, &p12FilePw)) != 0) goto done; } else if (pk12util.options[opt_Export].activated) { P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg, pk12util.options[opt_Export].arg, &slotPw, &p12FilePw); } else { Usage(progName); pk12uErrno = PK12UERR_USAGE; }done: NSS_Shutdown(); exit(pk12uErrno);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?