p12exp.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,408 行 · 第 1/3 页

C
1,408
字号
    *rBaggage = baggage;    *rSafe = safe;    return rv;}/* DER encode the safe contents and return a SECItem.  if an error * occurs, NULL is returned. */static SECItem *sec_pkcs12_encode_safe_contents(SEC_PKCS12SafeContents *safe){    SECItem *dsafe = NULL, *tsafe;    void *dummy = NULL;    PRArenaPool *arena;    if(safe == NULL) {	return NULL;    }/*    rv = sec_pkcs12_prepare_for_der_code_safe(safe, PR_TRUE);    if(rv != SECSuccess) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }*/    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);    if(arena == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    tsafe = (SECItem *)PORT_ArenaZAlloc(arena, sizeof(SECItem));    if(tsafe != NULL) {	dummy = SEC_ASN1EncodeItem(arena, tsafe, safe, 	    SEC_PKCS12SafeContentsTemplate);	if(dummy != NULL) {	    dsafe = SECITEM_DupItem(tsafe);	} else {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	}    } else {	PORT_SetError(SEC_ERROR_NO_MEMORY);    }    PORT_FreeArena(arena, PR_TRUE);    return dsafe;}/* prepare the authenicated safe for encoding and encode it.   *   baggage is copied to the appropriate area, safe is encoded and *   encrypted.  the version and transport mode are set on the asafe. *   the whole ball of wax is then der encoded and packaged up into *   data content info  * safe -- container of certs and keys, is encrypted. * baggage -- container of certs and keys, keys assumed to be encrypted by  *    another method, certs are in the clear * algorithm -- algorithm by which to encrypt safe * pwitem -- password for encryption * wincx - window handle * * return of NULL is an error condition. */static SEC_PKCS7ContentInfo *sec_pkcs12_get_auth_safe(SEC_PKCS12SafeContents *safe, 			 SEC_PKCS12Baggage *baggage,  			 SECOidTag algorithm, 			 SECItem *pwitem,			 PKCS12UnicodeConvertFunction unicodeFn,			 void *wincx){    SECItem *src = NULL, *dest = NULL, *psalt = NULL;    PRArenaPool *poolp;    SEC_PKCS12AuthenticatedSafe *asafe;    SEC_PKCS7ContentInfo *safe_cinfo = NULL;    SEC_PKCS7ContentInfo *asafe_cinfo = NULL;    void *dummy;    SECStatus rv = SECSuccess;    PRBool swapUnicodeBytes = PR_FALSE;#ifdef IS_LITTLE_ENDIAN    swapUnicodeBytes = PR_TRUE;#endif        if(((safe != NULL) && (pwitem == NULL)) && (baggage == NULL))	return NULL;    poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);    if(poolp == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    /* prepare authenticated safe for encode */    asafe = sec_pkcs12_new_asafe(poolp);    if(asafe != NULL) {	/* set version */	dummy = SEC_ASN1EncodeInteger(asafe->poolp, &asafe->version,				      SEC_PKCS12_PFX_VERSION);	if(dummy == NULL) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    rv = SECFailure;	    goto loser;	}	/* generate the privacy salt used to create virtual pwd */	psalt = sec_pkcs12_generate_salt();	if(psalt != NULL) {	    rv = SECITEM_CopyItem(asafe->poolp, &asafe->privacySalt,				  psalt);	    if(rv == SECSuccess) {		asafe->privacySalt.len *= 8;	    } 	    else {		SECITEM_ZfreeItem(psalt, PR_TRUE);		PORT_SetError(SEC_ERROR_NO_MEMORY);		goto loser;	    }	} 	if((psalt == NULL) || (rv == SECFailure)) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    rv = SECFailure;	    goto loser;	}	/* package up safe contents */	if(safe != NULL) 	{	    safe_cinfo = SEC_PKCS7CreateEncryptedData(algorithm, NULL, wincx);	    if((safe_cinfo != NULL) && (safe->safe_size > 0)) {		/* encode the safe and encrypt the contents of the 		 * content info		 */		src = sec_pkcs12_encode_safe_contents(safe);		if(src != NULL) {		    rv = SEC_PKCS7SetContent(safe_cinfo, (char *)src->data, src->len);		    SECITEM_ZfreeItem(src, PR_TRUE);		    if(rv == SECSuccess) {			SECItem *vpwd;			vpwd = sec_pkcs12_create_virtual_password(pwitem, psalt,						unicodeFn, swapUnicodeBytes);			if(vpwd != NULL) {			    rv = SEC_PKCS7EncryptContents(NULL, safe_cinfo,							  vpwd, wincx);			    SECITEM_ZfreeItem(vpwd, PR_TRUE);			} else {			    rv = SECFailure;			    PORT_SetError(SEC_ERROR_NO_MEMORY);			}		    } else {			PORT_SetError(SEC_ERROR_NO_MEMORY);		    }		} else {		    rv = SECFailure;		}	    } else if(safe->safe_size > 0) {		PORT_SetError(SEC_ERROR_NO_MEMORY);		goto loser;	    } else {	    	/* case where there is NULL content in the safe contents */		rv = SEC_PKCS7SetContent(safe_cinfo, NULL, 0);		if(rv != SECFailure) {		    PORT_SetError(SEC_ERROR_NO_MEMORY);		}	    }	    if(rv != SECSuccess) {		SEC_PKCS7DestroyContentInfo(safe_cinfo);		safe_cinfo = NULL;		goto loser;	    }	    asafe->safe = safe_cinfo;		    /*	    PORT_Memcpy(&asafe->safe, safe_cinfo, sizeof(*safe_cinfo));	    */	}	/* copy the baggage to the authenticated safe baggage if present */	if(baggage != NULL) {	    PORT_Memcpy(&asafe->baggage, baggage, sizeof(*baggage));	}	/* encode authenticated safe and store it in a Data content info */	dest = (SECItem *)PORT_ArenaZAlloc(poolp, sizeof(SECItem));	if(dest != NULL) {	    dummy = SEC_ASN1EncodeItem(poolp, dest, asafe, 				SEC_PKCS12AuthenticatedSafeTemplate);	    if(dummy != NULL) {		asafe_cinfo = SEC_PKCS7CreateData();		if(asafe_cinfo != NULL) {		    rv = SEC_PKCS7SetContent(asafe_cinfo, 					 	(char *)dest->data, 						dest->len);		    if(rv != SECSuccess) {			PORT_SetError(SEC_ERROR_NO_MEMORY);			SEC_PKCS7DestroyContentInfo(asafe_cinfo);			asafe_cinfo = NULL;		    }		}	    } else {		PORT_SetError(SEC_ERROR_NO_MEMORY);		rv = SECFailure;	    }	}    }loser:    PORT_FreeArena(poolp, PR_TRUE);    if(safe_cinfo != NULL) {    	SEC_PKCS7DestroyContentInfo(safe_cinfo);    }    if(psalt != NULL) {	SECITEM_ZfreeItem(psalt, PR_TRUE);    }    if(rv == SECFailure) {	return NULL;    }	    return asafe_cinfo;}/* generates the PFX and computes the mac on the authenticated safe  * NULL implies an error */static SEC_PKCS12PFXItem *sec_pkcs12_get_pfx(SEC_PKCS7ContentInfo *cinfo, 		   PRBool do_mac, 		   SECItem *pwitem, PKCS12UnicodeConvertFunction unicodeFn){    SECItem *dest = NULL, *mac = NULL, *salt = NULL, *key = NULL;    SEC_PKCS12PFXItem *pfx;    SECStatus rv = SECFailure;    SGNDigestInfo *di;    SECItem *vpwd;    PRBool swapUnicodeBytes = PR_FALSE;#ifdef IS_LITTLE_ENDIAN    swapUnicodeBytes = PR_TRUE;#endif    if((cinfo == NULL) || ((do_mac == PR_TRUE) && (pwitem == NULL))) {	return NULL;    }    /* allocate new pfx structure */    pfx = sec_pkcs12_new_pfx();    if(pfx == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    PORT_Memcpy(&pfx->authSafe, cinfo, sizeof(*cinfo));    if(do_mac == PR_TRUE) {    	/* salt for computing mac */	salt = sec_pkcs12_generate_salt();	if(salt != NULL) {	    rv = SECITEM_CopyItem(pfx->poolp, &pfx->macData.macSalt, salt);	    pfx->macData.macSalt.len *= 8;	    vpwd = sec_pkcs12_create_virtual_password(pwitem, salt,						unicodeFn, swapUnicodeBytes);	    if(vpwd == NULL) {		rv = SECFailure;		key = NULL;	    } else {		key = sec_pkcs12_generate_key_from_password(SEC_OID_SHA1,							salt, vpwd);		SECITEM_ZfreeItem(vpwd, PR_TRUE);	    }	    if((key != NULL) && (rv == SECSuccess)) {		dest = SEC_PKCS7GetContent(cinfo);		if(dest != NULL) {		    /* compute mac on data -- for password integrity mode */		    mac = sec_pkcs12_generate_mac(key, dest, PR_FALSE);		    if(mac != NULL) {			di = SGN_CreateDigestInfo(SEC_OID_SHA1, 			    			  mac->data, mac->len);			if(di != NULL) {			    rv = SGN_CopyDigestInfo(pfx->poolp, 						    &pfx->macData.safeMac, di);			    SGN_DestroyDigestInfo(di);			} else {			    PORT_SetError(SEC_ERROR_NO_MEMORY);			}			SECITEM_ZfreeItem(mac, PR_TRUE);		    }		} else {		    rv = SECFailure;		}	    } else {		PORT_SetError(SEC_ERROR_NO_MEMORY);		rv = SECFailure;	    }	    if(key != NULL) {		SECITEM_ZfreeItem(key, PR_TRUE);	    }	    SECITEM_ZfreeItem(salt, PR_TRUE);	}    }    if(rv == SECFailure) {	SEC_PKCS12DestroyPFX(pfx);	pfx = NULL;    }    return pfx;}/* der encode the pfx */static SECItem *sec_pkcs12_encode_pfx(SEC_PKCS12PFXItem *pfx){    SECItem *dest;    void *dummy;    if(pfx == NULL) {	return NULL;    }    dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));    if(dest == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    dummy = SEC_ASN1EncodeItem(NULL, dest, pfx, SEC_PKCS12PFXItemTemplate);    if(dummy == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	SECITEM_ZfreeItem(dest, PR_TRUE);	dest = NULL;    }    return dest;}SECItem *SEC_PKCS12GetPFX(char **nicknames,		 CERTCertificate **ref_certs,		 PRBool shroud_keys, 		 SEC_PKCS5GetPBEPassword pbef, 		 void *pbearg,		 PKCS12UnicodeConvertFunction unicodeFn,		 void *wincx){    SECItem **nicks = NULL;    SEC_PKCS12PFXItem *pfx = NULL;    SEC_PKCS12Baggage *baggage = NULL;    SEC_PKCS12SafeContents *safe = NULL;    SEC_PKCS7ContentInfo *cinfo = NULL;    SECStatus rv = SECFailure;    SECItem *dest = NULL, *pwitem = NULL;    PRBool problem = PR_FALSE;    PRBool unencryptedCerts;    SECOidTag shroud_alg, safe_alg;    /* how should we encrypt certs ? */    unencryptedCerts = !SEC_PKCS12IsEncryptionAllowed();    if(!unencryptedCerts) {	safe_alg = SEC_PKCS12GetPreferredEncryptionAlgorithm();	if(safe_alg == SEC_OID_UNKNOWN) {	    safe_alg = SEC_PKCS12GetStrongestAllowedAlgorithm();	}	if(safe_alg == SEC_OID_UNKNOWN) {	    unencryptedCerts = PR_TRUE;	    /* for export where no encryption is allowed, we still need	     * to encrypt the NULL contents per the spec.  encrypted info	     * is known plaintext, so it shouldn't be a problem.	     */	    safe_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;	}    } else {	/* for export where no encryption is allowed, we still need	 * to encrypt the NULL contents per the spec.  encrypted info	 * is known plaintext, so it shouldn't be a problem.	 */	safe_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;    }    /* keys are always stored with triple DES */    shroud_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;    /* check for FIPS, if so, do not encrypt certs */    if(PK11_IsFIPS() && !unencryptedCerts) {	unencryptedCerts = PR_TRUE;    }    if((nicknames == NULL) || (pbef == NULL) || (ref_certs == NULL)) {	problem = PR_TRUE;	goto loser;    }    /* get password */    pwitem = (*pbef)(pbearg);    if(pwitem == NULL) {	problem = PR_TRUE;	goto loser;    }    nicks = sec_pkcs12_convert_nickname_list(nicknames);    /* get safe and baggage */    rv = sec_pkcs12_package_certs_and_keys(nicks, ref_certs, unencryptedCerts,    					   &safe, &baggage, shroud_keys,    					   shroud_alg, pwitem, unicodeFn, wincx);    if(rv == SECFailure) {	problem = PR_TRUE;    }    if((safe != NULL) && (problem == PR_FALSE)) {	/* copy thumbprints */	rv = sec_pkcs12_propagate_thumbprints(nicks, ref_certs, safe, baggage);	/* package everything up into AuthenticatedSafe */	cinfo = sec_pkcs12_get_auth_safe(safe, baggage, 					 safe_alg, pwitem, unicodeFn, wincx);	sec_pkcs12_destroy_cert_content_infos(safe, baggage);	/* get the pfx and mac it */	if(cinfo != NULL) {	    pfx = sec_pkcs12_get_pfx(cinfo, PR_TRUE, pwitem, unicodeFn);	    if(pfx != NULL) {		dest = sec_pkcs12_encode_pfx(pfx);		SEC_PKCS12DestroyPFX(pfx);	    }	    SEC_PKCS7DestroyContentInfo(cinfo);	}	if(safe != NULL) {	    PORT_FreeArena(safe->poolp, PR_TRUE);	}    } else {	if(safe != NULL) {	    PORT_FreeArena(safe->poolp, PR_TRUE);	}    }loser:    if(nicks != NULL) {	sec_pkcs12_destroy_nickname_list(nicks);    }    if(ref_certs != NULL) {	sec_pkcs12_destroy_certificate_list(ref_certs);    }    if(pwitem != NULL) {	SECITEM_ZfreeItem(pwitem, PR_TRUE);    }    if(problem == PR_TRUE) {	dest = NULL;    }    return dest;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?