p12e.c

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

C
2,255
字号
 *	it. * *	p12ctxt - the export context  *	safe - the safeInfo to place the key in *	nestedDest - the nested safeContents to place a key *	cert - the certificate which the key belongs to *	shroudKey - encrypt the private key for export.  This value should  *		always be true.  lower level code will not allow the export *		of unencrypted private keys. *	algorithm - the algorithm with which to encrypt the private key *	pwitem - the password to encrypted the private key with *	keyId - the keyID attribute *	nickName - the nickname attribute */static SECStatusSEC_PKCS12AddEncryptedKey(SEC_PKCS12ExportContext *p12ctxt, 		SECKEYEncryptedPrivateKeyInfo *epki, SEC_PKCS12SafeInfo *safe,		void *nestedDest, SECItem *keyId, SECItem *nickName){    void *mark;    void *keyItem;    SECOidTag keyType;    SECStatus rv = SECFailure;    sec_PKCS12SafeBag *returnBag;    if(!p12ctxt || !safe || !epki) {	return SECFailure;    }    mark = PORT_ArenaMark(p12ctxt->arena);    keyItem = PORT_ArenaZAlloc(p12ctxt->arena, 				sizeof(SECKEYEncryptedPrivateKeyInfo));    if(!keyItem) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    rv = SECKEY_CopyEncryptedPrivateKeyInfo(p12ctxt->arena, 					(SECKEYEncryptedPrivateKeyInfo *)keyItem,					epki);    keyType = SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID;    if(rv != SECSuccess) {	goto loser;    }	    /* create the safe bag and set any attributes */    returnBag = sec_PKCS12CreateSafeBag(p12ctxt, keyType, keyItem);    if(!returnBag) {	rv = SECFailure;	goto loser;    }    if(nickName) {	if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, 				       SEC_OID_PKCS9_FRIENDLY_NAME, nickName) 				       != SECSuccess) {	    goto loser;	}    }	       if(keyId) {	if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, SEC_OID_PKCS9_LOCAL_KEY_ID,				       keyId) != SECSuccess) {	    goto loser;	}    }    if(nestedDest) {	rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, 					   (sec_PKCS12SafeContents*)nestedDest,					   returnBag);    } else {	rv = sec_pkcs12_append_bag(p12ctxt, safe, returnBag);    }loser:    if (rv != SECSuccess) {	PORT_ArenaRelease(p12ctxt->arena, mark);    } else {	PORT_ArenaUnmark(p12ctxt->arena, mark);    }    return rv;}/* SEC_PKCS12AddKeyForCert *	Extracts the key associated with a particular certificate and exports *	it. * *	p12ctxt - the export context  *	safe - the safeInfo to place the key in *	nestedDest - the nested safeContents to place a key *	cert - the certificate which the key belongs to *	shroudKey - encrypt the private key for export.  This value should  *		always be true.  lower level code will not allow the export *		of unencrypted private keys. *	algorithm - the algorithm with which to encrypt the private key *	pwitem - the password to encrypt the private key with *	keyId - the keyID attribute *	nickName - the nickname attribute */SECStatusSEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *safe, 			void *nestedDest, CERTCertificate *cert,			PRBool shroudKey, SECOidTag algorithm, SECItem *pwitem,			SECItem *keyId, SECItem *nickName){    void *mark;    void *keyItem;    SECOidTag keyType;    SECStatus rv = SECFailure;    SECItem nickname = {siBuffer,NULL,0}, uniPwitem = {siBuffer, NULL, 0};    sec_PKCS12SafeBag *returnBag;    if(!p12ctxt || !cert || !safe) {	return SECFailure;    }    mark = PORT_ArenaMark(p12ctxt->arena);    /* retrieve the key based upon the type that it is and      * specify the type of safeBag to store the key in     */	       if(!shroudKey) {	/* extract the key unencrypted.  this will most likely go away */	SECKEYPrivateKeyInfo *pki = PK11_ExportPrivateKeyInfo(cert, 							      p12ctxt->wincx);	if(!pki) {	    PORT_ArenaRelease(p12ctxt->arena, mark);	    PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY);	    return SECFailure;	}   	keyItem = PORT_ArenaZAlloc(p12ctxt->arena, sizeof(SECKEYPrivateKeyInfo));	if(!keyItem) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    goto loser;	}	rv = SECKEY_CopyPrivateKeyInfo(p12ctxt->arena, 				       (SECKEYPrivateKeyInfo *)keyItem, pki);	keyType = SEC_OID_PKCS12_V1_KEY_BAG_ID;	SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE);    } else {	/* extract the key encrypted */	SECKEYEncryptedPrivateKeyInfo *epki = NULL;	PK11SlotInfo *slot = p12ctxt->slot;	if(!sec_pkcs12_convert_item_to_unicode(p12ctxt->arena, &uniPwitem,				 pwitem, PR_TRUE, PR_TRUE, PR_TRUE)) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    goto loser;	}	/* we want to make sure to take the key out of the key slot */	if(PK11_IsInternal(p12ctxt->slot)) {	    slot = PK11_GetInternalKeySlot();	}	epki = PK11_ExportEncryptedPrivateKeyInfo(slot, algorithm, 						  &uniPwitem, cert, 1, 						  p12ctxt->wincx);	if(PK11_IsInternal(p12ctxt->slot)) {	    PK11_FreeSlot(slot);	}		keyItem = PORT_ArenaZAlloc(p12ctxt->arena, 				  sizeof(SECKEYEncryptedPrivateKeyInfo));	if(!keyItem) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    goto loser;	}	if(!epki) {	    PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY);	    return SECFailure;	}   	rv = SECKEY_CopyEncryptedPrivateKeyInfo(p12ctxt->arena, 					(SECKEYEncryptedPrivateKeyInfo *)keyItem,					epki);	keyType = SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID;	SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE);    }    if(rv != SECSuccess) {	goto loser;    }	    /* if no nickname specified, let's see if the certificate has a      * nickname.     */					      if(!nickName) {	if(cert->nickname) {	    nickname.data = (unsigned char *)cert->nickname;	    nickname.len = PORT_Strlen(cert->nickname);	    nickName = &nickname;	}    }    /* create the safe bag and set any attributes */    returnBag = sec_PKCS12CreateSafeBag(p12ctxt, keyType, keyItem);    if(!returnBag) {	rv = SECFailure;	goto loser;    }    if(nickName) {	if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, 				       SEC_OID_PKCS9_FRIENDLY_NAME, nickName) 				       != SECSuccess) {	    goto loser;	}    }	       if(keyId) {	if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, SEC_OID_PKCS9_LOCAL_KEY_ID,				       keyId) != SECSuccess) {	    goto loser;	}    }    if(nestedDest) {	rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena,					  (sec_PKCS12SafeContents*)nestedDest, 					  returnBag);    } else {	rv = sec_pkcs12_append_bag(p12ctxt, safe, returnBag);    }loser:    if (rv != SECSuccess) {	PORT_ArenaRelease(p12ctxt->arena, mark);    } else {	PORT_ArenaUnmark(p12ctxt->arena, mark);    }    return rv;}/* SEC_PKCS12AddCertAndEncryptedKey *	Add a certificate and key pair to be exported. * *	p12ctxt - the export context  * 	certSafe - the safeInfo where the cert is stored *	certNestedDest - the nested safeContents to store the cert *	keySafe - the safeInfo where the key is stored *	keyNestedDest - the nested safeContents to store the key *	shroudKey - extract the private key encrypted? *	pwitem - the password with which the key is encrypted *	algorithm - the algorithm with which the key is encrypted */SECStatusSEC_PKCS12AddDERCertAndEncryptedKey(SEC_PKCS12ExportContext *p12ctxt, 		void *certSafe, void *certNestedDest, 		SECItem *derCert, void *keySafe, 		void *keyNestedDest, SECKEYEncryptedPrivateKeyInfo *epki,		char *nickname){		    SECStatus rv = SECFailure;    SGNDigestInfo *digest = NULL;    void *mark = NULL;    CERTCertificate *cert;    SECItem nick = {siBuffer, NULL,0}, *nickPtr = NULL;     if(!p12ctxt || !certSafe || !keySafe || !derCert) {	return SECFailure;    }    mark = PORT_ArenaMark(p12ctxt->arena);    cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert,				   NULL, PR_FALSE, PR_TRUE);    if(!cert) {	PORT_ArenaRelease(p12ctxt->arena, mark);	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;    }    cert->nickname = nickname;    /* generate the thumbprint of the cert to use as a keyId */    digest = sec_pkcs12_compute_thumbprint(&cert->derCert);    if(!digest) {	CERT_DestroyCertificate(cert);	return SECFailure;    }    /* add the certificate */    rv = SEC_PKCS12AddCert(p12ctxt, (SEC_PKCS12SafeInfo*)certSafe, 			   certNestedDest, cert, NULL,    			   &digest->digest, PR_FALSE);    if(rv != SECSuccess) {	goto loser;    }    if(nickname) {	nick.data = (unsigned char *)nickname;	nick.len = PORT_Strlen(nickname);	nickPtr = &nick;    } else {	nickPtr = NULL;    }    /* add the key */    rv = SEC_PKCS12AddEncryptedKey(p12ctxt, epki, (SEC_PKCS12SafeInfo*)keySafe,				   keyNestedDest, &digest->digest, nickPtr );    if(rv != SECSuccess) {	goto loser;    }    SGN_DestroyDigestInfo(digest);    PORT_ArenaUnmark(p12ctxt->arena, mark);    return SECSuccess;loser:    SGN_DestroyDigestInfo(digest);    CERT_DestroyCertificate(cert);    PORT_ArenaRelease(p12ctxt->arena, mark);        return SECFailure; }/* SEC_PKCS12AddCertAndKey *	Add a certificate and key pair to be exported. * *	p12ctxt - the export context  * 	certSafe - the safeInfo where the cert is stored *	certNestedDest - the nested safeContents to store the cert *	keySafe - the safeInfo where the key is stored *	keyNestedDest - the nested safeContents to store the key *	shroudKey - extract the private key encrypted? *	pwitem - the password with which the key is encrypted *	algorithm - the algorithm with which the key is encrypted */SECStatusSEC_PKCS12AddCertAndKey(SEC_PKCS12ExportContext *p12ctxt, 			void *certSafe, void *certNestedDest, 			CERTCertificate *cert, CERTCertDBHandle *certDb,			void *keySafe, void *keyNestedDest, 			PRBool shroudKey, SECItem *pwitem, SECOidTag algorithm){		    SECStatus rv = SECFailure;    SGNDigestInfo *digest = NULL;    void *mark = NULL;    if(!p12ctxt || !certSafe || !keySafe || !cert) {	return SECFailure;    }    mark = PORT_ArenaMark(p12ctxt->arena);    /* generate the thumbprint of the cert to use as a keyId */    digest = sec_pkcs12_compute_thumbprint(&cert->derCert);    if(!digest) {	PORT_ArenaRelease(p12ctxt->arena, mark);	return SECFailure;    }    /* add the certificate */    rv = SEC_PKCS12AddCert(p12ctxt, (SEC_PKCS12SafeInfo*)certSafe, 			   (SEC_PKCS12SafeInfo*)certNestedDest, cert, certDb,    			   &digest->digest, PR_TRUE);    if(rv != SECSuccess) {	goto loser;    }    /* add the key */    rv = SEC_PKCS12AddKeyForCert(p12ctxt, (SEC_PKCS12SafeInfo*)keySafe, 				 keyNestedDest, cert,     				 shroudKey, algorithm, pwitem,     				 &digest->digest, NULL );    if(rv != SECSuccess) {	goto loser;    }    SGN_DestroyDigestInfo(digest);    PORT_ArenaUnmark(p12ctxt->arena, mark);    return SECSuccess;loser:    SGN_DestroyDigestInfo(digest);    PORT_ArenaRelease(p12ctxt->arena, mark);        return SECFailure; }/* SEC_PKCS12CreateNestedSafeContents * 	Allows nesting of safe contents to be implemented.  No limit imposed on  *	depth.   * *	p12ctxt - the export context  *	baseSafe - the base safeInfo  *	nestedDest - a parent safeContents (?) */void *SEC_PKCS12CreateNestedSafeContents(SEC_PKCS12ExportContext *p12ctxt,				   void *baseSafe, void *nestedDest){    sec_PKCS12SafeContents *newSafe;    sec_PKCS12SafeBag *safeContentsBag;    void *mark;    SECStatus rv;    if(!p12ctxt || !baseSafe) {	return NULL;    }    mark = PORT_ArenaMark(p12ctxt->arena);    newSafe = sec_PKCS12CreateSafeContents(p12ctxt->arena);    if(!newSafe) {	PORT_ArenaRelease(p12ctxt->arena, mark);	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    /* create the safeContents safeBag */    safeContentsBag = sec_PKCS12CreateSafeBag(p12ctxt, 					SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID,					newSafe);    if(!safeContentsBag) {	goto loser;    }    /* append the safeContents to the appropriate area */    if(nestedDest) {	rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, 					   (sec_PKCS12SafeContents*)nestedDest,					   safeContentsBag);    } else {	rv = sec_pkcs12_append_bag(p12ctxt, (SEC_PKCS12SafeInfo*)baseSafe, 				   safeContentsBag);    }    if(rv != SECSuccess) {	goto loser;    }    PORT_ArenaUnmark(p12ctxt->arena, mark);    return newSafe;loser:    PORT_ArenaRelease(p12ctxt->arena, mark);    return NULL;}/********************************* * Encoding routines *********************************//* set up the encoder context based on information in the export context * and return the newly allocated enocoder context.  A return of NULL  * indicates an error occurred.  */sec_PKCS12EncoderContext *sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp){    sec_PKCS12EncoderContext *p12enc = NULL;    unsigned int i, nonEmptyCnt;    if(!p12exp || !p12exp->safeInfos) {	return NULL;    }    /* check for any empty safes and skip them */    i = nonEmptyCnt = 0;    while(p12exp->safeInfos[i]) {	if(p12exp->safeInfos[i]->itemCount) {	    nonEmptyCnt++;	}	i++;    }    if(nonEmptyCnt == 0) {	return NULL;    }    p12exp->authSafe.encodedSafes[nonEmptyCnt] = NULL;    /* allocate the encoder context */    p12enc = (sec_PKCS12EncoderContext*)PORT_ArenaZAlloc(p12exp->arena,     			      sizeof(sec_PKCS12EncoderContext));    if(!p12enc) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    p12enc->arena = p12exp->arena;    p12enc->p12exp = p12exp;    /* set up the PFX version and information */    PORT_Memset(&p12enc->pfx, 0, sizeof(sec_PKCS12PFXItem));    if(!SEC_ASN1EncodeInteger(p12exp->arena, &(p12enc->pfx.version),     			      SEC_PKCS12_VERSION) ) {	PORT_SetError(SEC_ERROR_NO_MEMORY);    	goto loser;    }    /* set up the authenticated safe content info based on the      * type of integrity being used.  this should be changed to     * enforce integrity mode, but will not be implemented until     * it is confirmed that integrity must be in place     */    if(p12exp->integrityEnabled && !p12exp->pwdIntegrity) {	SECStatus rv;	/* create public key integrity mode */	p12enc->aSafeCinfo = SEC_PKCS7CreateSignedData(				p12exp->integrityInfo.pubkeyInfo.cert,				certUsageEmailSigner,				p12exp->integrityInfo.pubkeyInfo.certDb,				p12exp->integrityInfo.pubkeyInfo.algorithm,				NULL,				p12exp->pwfn,				p12exp->pwfnarg);	if(!p12enc->aSafeCinfo) {	    goto loser;	}	if(SEC_PKCS7IncludeCertChain(p12enc->aSafeCinfo,NULL) != SECSuccess) {	    SEC_PKCS7DestroyContentInfo(p12enc->aSafeCinfo);	    goto loser;	}	rv = SEC_PKCS7AddSigningTime(p12enc->aSafeCinfo);	PORT_Assert(rv == SECSuccess);    } else {	p12enc->aSafeCinfo = SEC_PKCS7CreateData();	/* init password pased integrity mode */	if(p12exp->integrityEnabled) {	    SECItem  pwd = {siBuffer,NULL, 0}, *key;	    SECItem *salt = sec_pkcs12_generate_salt();	    PBEBitGenContext *pbeCtxt = NULL;	    /* zero out macData and set values */	    PORT_Memset(&p12enc->mac, 0, sizeof(sec_PKCS12MacData));	    if(!salt) {		PORT_SetError(SEC_ERROR_NO_MEMORY);		goto loser;	    }	    if(SECITEM_CopyItem(p12exp->arena, &(p12enc->mac.macSalt), salt) 			!= SECSuccess) {		PORT_SetError(SEC_ERROR_NO_MEMORY);		goto loser;	    }   	    SECITEM_ZfreeItem(salt, PR_TRUE);	    /* generate HMAC key */	    if(!sec_pkcs12_convert_item_to_unicode(p12exp->arena, &pwd, 			p12exp->integrityInfo.pwdInfo.password, PR_TRUE, 			PR_TRUE, PR_TRUE)) {		goto loser;	    }	    pbeCtxt = PBE_CreateContext(p12exp->integrityInfo.pwdInfo.algorithm,					pbeBitGenIntegrityKey, &pwd, 					&(p12enc->mac.macSalt), 160, 1);	    if(!pbeCtxt) {		goto loser;	    }	    key = PBE_GenerateBits(pbeCtxt);	    PBE_DestroyContext(pbeCtxt);	    if(!key) {		goto loser;

⌨️ 快捷键说明

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