p12e.c

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

C
2,255
字号
 * Routines to handle the exporting of the keys and certificates *********************************//* creates a safe contents which safeBags will be appended to */sec_PKCS12SafeContents *sec_PKCS12CreateSafeContents(PRArenaPool *arena){    sec_PKCS12SafeContents *safeContents;    if(arena == NULL) {	return NULL;     }    /* create the safe contents */    safeContents = (sec_PKCS12SafeContents *)PORT_ArenaZAlloc(arena,					    sizeof(sec_PKCS12SafeContents));    if(!safeContents) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    /* set up the internal contents info */    safeContents->safeBags = NULL;    safeContents->arena = arena;    safeContents->bagCount = 0;    return safeContents;loser:    return NULL;}   /* appends a safe bag to a safeContents using the specified arena.  */SECStatussec_pkcs12_append_bag_to_safe_contents(PRArenaPool *arena, 				       sec_PKCS12SafeContents *safeContents,				       sec_PKCS12SafeBag *safeBag){    void *mark = NULL, *dummy = NULL;    if(!arena || !safeBag || !safeContents) {	return SECFailure;    }    mark = PORT_ArenaMark(arena);    if(!mark) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;    }    /* allocate space for the list, or reallocate to increase space */    if(!safeContents->safeBags) {	safeContents->safeBags = (sec_PKCS12SafeBag **)PORT_ArenaZAlloc(arena, 						(2 * sizeof(sec_PKCS12SafeBag *)));	dummy = safeContents->safeBags;	safeContents->bagCount = 0;    } else {	dummy = PORT_ArenaGrow(arena, safeContents->safeBags, 			(safeContents->bagCount + 1) * sizeof(sec_PKCS12SafeBag *),			(safeContents->bagCount + 2) * sizeof(sec_PKCS12SafeBag *));	safeContents->safeBags = (sec_PKCS12SafeBag **)dummy;    }    if(!dummy) {	PORT_ArenaRelease(arena, mark);	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;    }    /* append the bag at the end and null terminate the list */    safeContents->safeBags[safeContents->bagCount++] = safeBag;    safeContents->safeBags[safeContents->bagCount] = NULL;    PORT_ArenaUnmark(arena, mark);    return SECSuccess;}/* appends a safeBag to a specific safeInfo. */SECStatussec_pkcs12_append_bag(SEC_PKCS12ExportContext *p12ctxt, 		      SEC_PKCS12SafeInfo *safeInfo, sec_PKCS12SafeBag *safeBag){    sec_PKCS12SafeContents *dest;    SECStatus rv = SECFailure;    if(!p12ctxt || !safeBag || !safeInfo) {	return SECFailure;    }    if(!safeInfo->safe) {	safeInfo->safe = sec_PKCS12CreateSafeContents(p12ctxt->arena);	if(!safeInfo->safe) {	    return SECFailure;	}    }    dest = safeInfo->safe;    rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, dest, safeBag);    if(rv == SECSuccess) {	safeInfo->itemCount++;    }        return rv;} /* Creates a safeBag of the specified type, and if bagData is specified, * the contents are set.  The contents could be set later by the calling * routine. */sec_PKCS12SafeBag *sec_PKCS12CreateSafeBag(SEC_PKCS12ExportContext *p12ctxt, SECOidTag bagType, 			void *bagData){    sec_PKCS12SafeBag *safeBag;    PRBool setName = PR_TRUE;    void *mark = NULL;    SECStatus rv = SECSuccess;    SECOidData *oidData = NULL;    if(!p12ctxt) {	return NULL;    }    mark = PORT_ArenaMark(p12ctxt->arena);    if(!mark) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    safeBag = (sec_PKCS12SafeBag *)PORT_ArenaZAlloc(p12ctxt->arena,     						    sizeof(sec_PKCS12SafeBag));    if(!safeBag) {	PORT_ArenaRelease(p12ctxt->arena, mark);	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    /* set the bags content based upon bag type */    switch(bagType) {	case SEC_OID_PKCS12_V1_KEY_BAG_ID:	    safeBag->safeBagContent.pkcs8KeyBag =	        (SECKEYPrivateKeyInfo *)bagData;	    break;	case SEC_OID_PKCS12_V1_CERT_BAG_ID:	    safeBag->safeBagContent.certBag = (sec_PKCS12CertBag *)bagData;	    break;	case SEC_OID_PKCS12_V1_CRL_BAG_ID:	    safeBag->safeBagContent.crlBag = (sec_PKCS12CRLBag *)bagData;	    break;	case SEC_OID_PKCS12_V1_SECRET_BAG_ID:	    safeBag->safeBagContent.secretBag = (sec_PKCS12SecretBag *)bagData;	    break;	case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:	    safeBag->safeBagContent.pkcs8ShroudedKeyBag = 	        (SECKEYEncryptedPrivateKeyInfo *)bagData;	    break;	case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID:	    safeBag->safeBagContent.safeContents = 	        (sec_PKCS12SafeContents *)bagData;	    setName = PR_FALSE;	    break;	default:	    goto loser;    }    oidData = SECOID_FindOIDByTag(bagType);    if(oidData) {	rv = SECITEM_CopyItem(p12ctxt->arena, &safeBag->safeBagType, &oidData->oid);	if(rv != SECSuccess) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    goto loser;	}    } else {	goto loser;    }        safeBag->arena = p12ctxt->arena;    PORT_ArenaUnmark(p12ctxt->arena, mark);    return safeBag;loser:    if(mark) {	PORT_ArenaRelease(p12ctxt->arena, mark);    }    return NULL;}/* Creates a new certificate bag and returns a pointer to it.  If an error * occurs NULL is returned. */sec_PKCS12CertBag *sec_PKCS12NewCertBag(PRArenaPool *arena, SECOidTag certType){    sec_PKCS12CertBag *certBag = NULL;    SECOidData *bagType = NULL;    SECStatus rv;    void *mark = NULL;    if(!arena) {	return NULL;    }    mark = PORT_ArenaMark(arena);    certBag = (sec_PKCS12CertBag *)PORT_ArenaZAlloc(arena,     						    sizeof(sec_PKCS12CertBag));    if(!certBag) {	PORT_ArenaRelease(arena, mark);	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    bagType = SECOID_FindOIDByTag(certType);    if(!bagType) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    rv = SECITEM_CopyItem(arena, &certBag->bagID, &bagType->oid);    if(rv != SECSuccess) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }	    PORT_ArenaUnmark(arena, mark);    return certBag;loser:    PORT_ArenaRelease(arena, mark);    return NULL;}/* Creates a new CRL bag and returns a pointer to it.  If an error * occurs NULL is returned. */sec_PKCS12CRLBag *sec_PKCS12NewCRLBag(PRArenaPool *arena, SECOidTag crlType){    sec_PKCS12CRLBag *crlBag = NULL;    SECOidData *bagType = NULL;    SECStatus rv;    void *mark = NULL;    if(!arena) {	return NULL;    }    mark = PORT_ArenaMark(arena);    crlBag = (sec_PKCS12CRLBag *)PORT_ArenaZAlloc(arena,     						  sizeof(sec_PKCS12CRLBag));    if(!crlBag) {	PORT_ArenaRelease(arena, mark);	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    bagType = SECOID_FindOIDByTag(crlType);    if(!bagType) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    rv = SECITEM_CopyItem(arena, &crlBag->bagID, &bagType->oid);    if(rv != SECSuccess) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }	    PORT_ArenaUnmark(arena, mark);    return crlBag;loser:    PORT_ArenaRelease(arena, mark);    return NULL;}/* sec_PKCS12AddAttributeToBag * adds an attribute to a safeBag.  currently, the only attributes supported * are those which are specified within PKCS 12.   * *	p12ctxt - the export context  *	safeBag - the safeBag to which attributes are appended *	attrType - the attribute type * 	attrData - the attribute data */SECStatussec_PKCS12AddAttributeToBag(SEC_PKCS12ExportContext *p12ctxt, 			    sec_PKCS12SafeBag *safeBag, SECOidTag attrType,			    SECItem *attrData){    sec_PKCS12Attribute *attribute;    void *mark = NULL, *dummy = NULL;    SECOidData *oiddata = NULL;    SECItem unicodeName = { siBuffer, NULL, 0};    void *src = NULL;    unsigned int nItems = 0;    SECStatus rv;    if(!safeBag || !p12ctxt) {	return SECFailure;    }    mark = PORT_ArenaMark(safeBag->arena);    /* allocate the attribute */    attribute = (sec_PKCS12Attribute *)PORT_ArenaZAlloc(safeBag->arena,     						sizeof(sec_PKCS12Attribute));    if(!attribute) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    /* set up the attribute */    oiddata = SECOID_FindOIDByTag(attrType);    if(!oiddata) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    if(SECITEM_CopyItem(p12ctxt->arena, &attribute->attrType, &oiddata->oid) !=    		SECSuccess) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    nItems = 1;    switch(attrType) {	case SEC_OID_PKCS9_LOCAL_KEY_ID:	    {		src = attrData;		break;	    }	case SEC_OID_PKCS9_FRIENDLY_NAME:	    {		if(!sec_pkcs12_convert_item_to_unicode(p12ctxt->arena, 					&unicodeName, attrData, PR_FALSE, 					PR_FALSE, PR_TRUE)) {		    goto loser;		}		src = &unicodeName;		break;	    }	default:	    goto loser;    }    /* append the attribute to the attribute value list  */    attribute->attrValue = (SECItem **)PORT_ArenaZAlloc(p12ctxt->arena,     					    ((nItems + 1) * sizeof(SECItem *)));    if(!attribute->attrValue) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    /* XXX this will need to be changed if attributes requiring more than     * one element are ever used.     */    attribute->attrValue[0] = (SECItem *)PORT_ArenaZAlloc(p12ctxt->arena,     							  sizeof(SECItem));    if(!attribute->attrValue[0]) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    attribute->attrValue[1] = NULL;    rv = SECITEM_CopyItem(p12ctxt->arena, attribute->attrValue[0], 			  (SECItem*)src);    if(rv != SECSuccess) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    /* append the attribute to the safeBag attributes */    if(safeBag->nAttribs) {	dummy = PORT_ArenaGrow(p12ctxt->arena, safeBag->attribs, 			((safeBag->nAttribs + 1) * sizeof(sec_PKCS12Attribute *)),			((safeBag->nAttribs + 2) * sizeof(sec_PKCS12Attribute *)));	safeBag->attribs = (sec_PKCS12Attribute **)dummy;    } else {	safeBag->attribs = (sec_PKCS12Attribute **)PORT_ArenaZAlloc(p12ctxt->arena, 						2 * sizeof(sec_PKCS12Attribute *));	dummy = safeBag->attribs;    }    if(!dummy) {	goto loser;    }    safeBag->attribs[safeBag->nAttribs] = attribute;    safeBag->attribs[++safeBag->nAttribs] = NULL;    PORT_ArenaUnmark(p12ctxt->arena, mark);    return SECSuccess;loser:    if(mark) {	PORT_ArenaRelease(p12ctxt->arena, mark);    }    return SECFailure;}/* SEC_PKCS12AddCert * 	Adds a certificate to the data being exported.   * *	p12ctxt - the export context *	safe - the safeInfo to which the certificate is placed  *	nestedDest - if the cert is to be placed within a nested safeContents then, *		     this value is to be specified with the destination *	cert - the cert to export *	certDb - the certificate database handle *	keyId - a unique identifier to associate a certificate/key pair *	includeCertChain - PR_TRUE if the certificate chain is to be included. */SECStatusSEC_PKCS12AddCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *safe, 		  void *nestedDest, CERTCertificate *cert, 		  CERTCertDBHandle *certDb, SECItem *keyId,		  PRBool includeCertChain){    sec_PKCS12CertBag *certBag;    sec_PKCS12SafeBag *safeBag;    void *mark;    SECStatus rv;    SECItem nick = {siBuffer, NULL,0};    if(!p12ctxt || !cert) {	return SECFailure;    }    mark = PORT_ArenaMark(p12ctxt->arena);    /* allocate the cert bag */    certBag = sec_PKCS12NewCertBag(p12ctxt->arena,     				   SEC_OID_PKCS9_X509_CERT);    if(!certBag) {	goto loser;    }    if(SECITEM_CopyItem(p12ctxt->arena, &certBag->value.x509Cert,     			&cert->derCert) != SECSuccess) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    /* if the cert chain is to be included, we should only be exporting     * the cert from our internal database.     */    if(includeCertChain) {	CERTCertificateList *certList = CERT_CertChainFromCert(cert,							       certUsageSSLClient,							       PR_TRUE);	unsigned int count = 0;	if(!certList) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    goto loser;	}	/* add cert chain */	for(count = 0; count < (unsigned int)certList->len; count++) {	    if(SECITEM_CompareItem(&certList->certs[count], &cert->derCert)	    			!= SECEqual) {	    	CERTCertificate *tempCert;		/* decode the certificate */	    	tempCert = CERT_NewTempCertificate(certDb, 	    					&certList->certs[count], NULL,	    					PR_FALSE, PR_TRUE);	    	if(!tempCert) {		    CERT_DestroyCertificateList(certList);		    goto loser;		}		/* add the certificate */	    	if(SEC_PKCS12AddCert(p12ctxt, safe, nestedDest, tempCert, certDb,				     NULL, PR_FALSE) != SECSuccess) {		    CERT_DestroyCertificate(tempCert);		    CERT_DestroyCertificateList(certList);		    goto loser;		}		CERT_DestroyCertificate(tempCert);	    }	}	CERT_DestroyCertificateList(certList);    }    /* if the certificate has a nickname, we will set the friendly name     * to that.     */    if(cert->nickname) {        if (cert->slot && !PK11_IsInternal(cert->slot)) {	  /*	   * The cert is coming off of an external token, 	   * let's strip the token name from the nickname	   * and only add what comes after the colon as the	   * nickname. -javi	   */	    char *delimit;	    	    delimit = PORT_Strchr(cert->nickname,':');	    if (delimit == NULL) {	        nick.data = (unsigned char *)cert->nickname;		nick.len = PORT_Strlen(cert->nickname);	    } else {	        delimit++;	        nick.data = (unsigned char *)PORT_ArenaStrdup(p12ctxt->arena,							      delimit);		nick.len = PORT_Strlen(delimit);	    }	} else {	    nick.data = (unsigned char *)cert->nickname;	    nick.len = PORT_Strlen(cert->nickname);	}    }    safeBag = sec_PKCS12CreateSafeBag(p12ctxt, SEC_OID_PKCS12_V1_CERT_BAG_ID,     				      certBag);    if(!safeBag) {	goto loser;    }    /* add the friendly name and keyId attributes, if necessary */    if(nick.data) {	if(sec_PKCS12AddAttributeToBag(p12ctxt, safeBag, 				       SEC_OID_PKCS9_FRIENDLY_NAME, &nick) 				       != SECSuccess) {	    goto loser;	}    }	       if(keyId) {	if(sec_PKCS12AddAttributeToBag(p12ctxt, safeBag, SEC_OID_PKCS9_LOCAL_KEY_ID,				       keyId) != SECSuccess) {	    goto loser;	}    }    /* append the cert safeBag */    if(nestedDest) {	rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, 					  (sec_PKCS12SafeContents*)nestedDest, 					   safeBag);    } else {	rv = sec_pkcs12_append_bag(p12ctxt, safe, safeBag);    }    if(rv != SECSuccess) {	goto loser;    }    PORT_ArenaUnmark(p12ctxt->arena, mark);    return SECSuccess;loser:    if(mark) {	PORT_ArenaRelease(p12ctxt->arena, mark);    }    return SECFailure;}/* SEC_PKCS12AddEncryptedKey *	Extracts the key associated with a particular certificate and exports

⌨️ 快捷键说明

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