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 + -
显示快捷键?