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