p12exp.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,408 行 · 第 1/3 页
C
1,408 行
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "plarena.h"#include "secitem.h"#include "secoid.h"#include "seccomon.h"#include "secport.h"#include "cert.h"#include "pkcs12.h"#include "p12local.h"#include "secpkcs7.h"#include "secasn1.h"#include "secerr.h"#include "p12plcy.h"/* release the memory taken up by the list of nicknames */static voidsec_pkcs12_destroy_nickname_list(SECItem **nicknames){ int i = 0; if(nicknames == NULL) { return; } while(nicknames[i] != NULL) { SECITEM_FreeItem(nicknames[i], PR_FALSE); i++; } PORT_Free(nicknames);} /* release the memory taken up by the list of certificates */ static voidsec_pkcs12_destroy_certificate_list(CERTCertificate **ref_certs){ int i = 0; if(ref_certs == NULL) { return; } while(ref_certs[i] != NULL) { CERT_DestroyCertificate(ref_certs[i]); i++; }}static voidsec_pkcs12_destroy_cinfos_for_cert_bags(SEC_PKCS12CertAndCRLBag *certBag){ int j = 0; j = 0; while(certBag->certAndCRLs[j] != NULL) { SECOidTag certType = SECOID_FindOIDTag(&certBag->certAndCRLs[j]->BagID); if(certType == SEC_OID_PKCS12_X509_CERT_CRL_BAG) { SEC_PKCS12X509CertCRL *x509; x509 = certBag->certAndCRLs[j]->value.x509; SEC_PKCS7DestroyContentInfo(&x509->certOrCRL); } j++; }}/* destroy all content infos since they were not allocated in common * pool */static voidsec_pkcs12_destroy_cert_content_infos(SEC_PKCS12SafeContents *safe, SEC_PKCS12Baggage *baggage){ int i, j; if((safe != NULL) && (safe->contents != NULL)) { i = 0; while(safe->contents[i] != NULL) { SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType); if(bagType == SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID) { SEC_PKCS12CertAndCRLBag *certBag; certBag = safe->contents[i]->safeContent.certAndCRLBag; sec_pkcs12_destroy_cinfos_for_cert_bags(certBag); } i++; } } if((baggage != NULL) && (baggage->bags != NULL)) { i = 0; while(baggage->bags[i] != NULL) { if(baggage->bags[i]->unencSecrets != NULL) { j = 0; while(baggage->bags[i]->unencSecrets[j] != NULL) { SECOidTag bagType; bagType = SECOID_FindOIDTag(&baggage->bags[i]->unencSecrets[j]->safeBagType); if(bagType == SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID) { SEC_PKCS12CertAndCRLBag *certBag; certBag = baggage->bags[i]->unencSecrets[j]->safeContent.certAndCRLBag; sec_pkcs12_destroy_cinfos_for_cert_bags(certBag); } j++; } } i++; } }}/* convert the nickname list from a NULL termincated Char list * to a NULL terminated SECItem list */static SECItem **sec_pkcs12_convert_nickname_list(char **nicknames){ SECItem **nicks; int i, j; PRBool error = PR_FALSE; if(nicknames == NULL) { return NULL; } i = j = 0; while(nicknames[i] != NULL) { i++; } /* allocate the space and copy the data */ nicks = (SECItem **)PORT_ZAlloc(sizeof(SECItem *) * (i + 1)); if(nicks != NULL) { for(j = 0; ((j < i) && (error == PR_FALSE)); j++) { nicks[j] = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); if(nicks[j] != NULL) { nicks[j]->data = (unsigned char *)PORT_ZAlloc(PORT_Strlen(nicknames[j])+1); if(nicks[j]->data != NULL) { nicks[j]->len = PORT_Strlen(nicknames[j]); PORT_Memcpy(nicks[j]->data, nicknames[j], nicks[j]->len); nicks[j]->data[nicks[j]->len] = 0; } else { error = PR_TRUE; } } else { error = PR_TRUE; } } } if(error == PR_TRUE) { for(i = 0; i < j; i++) { SECITEM_FreeItem(nicks[i], PR_TRUE); } PORT_Free(nicks); nicks = NULL; } return nicks;}/* package the certificate add_cert into PKCS12 structures, * retrieve the certificate chain for the cert and return * the packaged contents. * poolp -- common memory pool; * add_cert -- certificate to package up * nickname for the certificate * a return of NULL indicates an error */static SEC_PKCS12CertAndCRL *sec_pkcs12_get_cert(PRArenaPool *poolp, CERTCertificate *add_cert, SECItem *nickname){ SEC_PKCS12CertAndCRL *cert; SEC_PKCS7ContentInfo *cinfo; SGNDigestInfo *t_di; void *mark; SECStatus rv; if((poolp == NULL) || (add_cert == NULL) || (nickname == NULL)) { return NULL; } mark = PORT_ArenaMark(poolp); cert = sec_pkcs12_new_cert_crl(poolp, SEC_OID_PKCS12_X509_CERT_CRL_BAG); if(cert != NULL) { /* copy the nickname */ rv = SECITEM_CopyItem(poolp, &cert->nickname, nickname); if(rv != SECSuccess) { PORT_SetError(SEC_ERROR_NO_MEMORY); cert = NULL; } else { /* package the certificate and cert chain into a NULL signer * PKCS 7 SignedData content Info and prepare it for encoding * since we cannot use DER_ANY_TEMPLATE */ cinfo = SEC_PKCS7CreateCertsOnly(add_cert, PR_TRUE, NULL); rv = SEC_PKCS7PrepareForEncode(cinfo, NULL, NULL, NULL); /* thumbprint the certificate */ if((cinfo != NULL) && (rv == SECSuccess)) { PORT_Memcpy(&cert->value.x509->certOrCRL, cinfo, sizeof(*cinfo)); t_di = sec_pkcs12_compute_thumbprint(&add_cert->derCert); if(t_di != NULL) { /* test */ rv = SGN_CopyDigestInfo(poolp, &cert->value.x509->thumbprint, t_di); if(rv != SECSuccess) { cert = NULL; PORT_SetError(SEC_ERROR_NO_MEMORY); } SGN_DestroyDigestInfo(t_di); } else cert = NULL; } } } if (cert == NULL) { PORT_ArenaRelease(poolp, mark); } else { PORT_ArenaUnmark(poolp, mark); } return cert;}/* package the private key associated with the certificate and * return the appropriate PKCS 12 structure * poolp common memory pool * nickname key nickname * cert -- cert to look up * wincx -- window handle * an error is indicated by a return of NULL */static SEC_PKCS12PrivateKey *sec_pkcs12_get_private_key(PRArenaPool *poolp, SECItem *nickname, CERTCertificate *cert, void *wincx){ SECKEYPrivateKeyInfo *pki; SEC_PKCS12PrivateKey *pk; SECStatus rv; void *mark; if((poolp == NULL) || (nickname == NULL)) { return NULL; } mark = PORT_ArenaMark(poolp); /* retrieve key from the data base */ pki = PK11_ExportPrivateKeyInfo(nickname, cert, wincx); if(pki == NULL) { PORT_ArenaRelease(poolp, mark); PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); return NULL; } pk = (SEC_PKCS12PrivateKey *)PORT_ArenaZAlloc(poolp, sizeof(SEC_PKCS12PrivateKey)); if(pk != NULL) { rv = sec_pkcs12_init_pvk_data(poolp, &pk->pvkData); if(rv == SECSuccess) { /* copy the key into poolp memory space */ rv = SECKEY_CopyPrivateKeyInfo(poolp, &pk->pkcs8data, pki); if(rv == SECSuccess) { rv = SECITEM_CopyItem(poolp, &pk->pvkData.nickname, nickname); } } if(rv != SECSuccess) { PORT_SetError(SEC_ERROR_NO_MEMORY); pk = NULL; } } else { PORT_SetError(SEC_ERROR_NO_MEMORY); } /* destroy private key, zeroing out data */ SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE); if (pk == NULL) { PORT_ArenaRelease(poolp, mark); } else { PORT_ArenaUnmark(poolp, mark); } return pk;}/* get a shrouded key item associated with a certificate * return the appropriate PKCS 12 structure * poolp common memory pool * nickname key nickname * cert -- cert to look up * wincx -- window handle * an error is indicated by a return of NULL */static SEC_PKCS12ESPVKItem *sec_pkcs12_get_shrouded_key(PRArenaPool *poolp, SECItem *nickname, CERTCertificate *cert, SECOidTag algorithm, SECItem *pwitem, PKCS12UnicodeConvertFunction unicodeFn, void *wincx){ SECKEYEncryptedPrivateKeyInfo *epki; SEC_PKCS12ESPVKItem *pk; void *mark; SECStatus rv; PK11SlotInfo *slot = NULL; PRBool swapUnicodeBytes = PR_FALSE;#ifdef IS_LITTLE_ENDIAN swapUnicodeBytes = PR_TRUE;#endif if((poolp == NULL) || (nickname == NULL)) return NULL; mark = PORT_ArenaMark(poolp); /* use internal key slot */ slot = PK11_GetInternalKeySlot(); /* retrieve encrypted prviate key */ epki = PK11_ExportEncryptedPrivateKeyInfo(slot, algorithm, pwitem, nickname, cert, 1, 0, NULL); PK11_FreeSlot(slot); if(epki == NULL) { PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); PORT_ArenaRelease(poolp, mark); return NULL; } /* create a private key and store the data into the poolp memory space */ pk = sec_pkcs12_create_espvk(poolp, SEC_OID_PKCS12_PKCS8_KEY_SHROUDING); if(pk != NULL) { rv = sec_pkcs12_init_pvk_data(poolp, &pk->espvkData); rv = SECITEM_CopyItem(poolp, &pk->espvkData.nickname, nickname); pk->espvkCipherText.pkcs8KeyShroud = (SECKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp, sizeof(SECKEYEncryptedPrivateKeyInfo)); if((pk->espvkCipherText.pkcs8KeyShroud != NULL) && (rv == SECSuccess)) { rv = SECKEY_CopyEncryptedPrivateKeyInfo(poolp, pk->espvkCipherText.pkcs8KeyShroud, epki); if(rv == SECSuccess) { rv = (*unicodeFn)(poolp, &pk->espvkData.uniNickName, nickname, PR_TRUE, swapUnicodeBytes); } } if(rv != SECSuccess) { PORT_SetError(SEC_ERROR_NO_MEMORY); pk = NULL; } } SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE); if(pk == NULL) { PORT_ArenaRelease(poolp, mark); } else { PORT_ArenaUnmark(poolp, mark); } return pk;}/* add a thumbprint to a private key associated certs list * pvk is the area where the list is stored * thumb is the thumbprint to copy * a return of SECFailure indicates an error */static SECStatus sec_pkcs12_add_thumbprint(SEC_PKCS12PVKSupportingData *pvk, SGNDigestInfo *thumb){ SGNDigestInfo **thumb_list = NULL; int nthumbs, size; void *mark, *dummy; SECStatus rv = SECFailure; if((pvk == NULL) || (thumb == NULL)) { return SECFailure; } mark = PORT_ArenaMark(pvk->poolp); thumb_list = pvk->assocCerts; nthumbs = pvk->nThumbs; /* allocate list space needed -- either growing or allocating * list must be NULL terminated */ size = sizeof(SGNDigestInfo *); dummy = PORT_ArenaGrow(pvk->poolp, thumb_list, (size * (nthumbs + 1)), (size * (nthumbs + 2))); thumb_list = dummy; if(dummy != NULL) { thumb_list[nthumbs] = (SGNDigestInfo *)PORT_ArenaZAlloc(pvk->poolp, sizeof(SGNDigestInfo)); if(thumb_list[nthumbs] != NULL) { SGN_CopyDigestInfo(pvk->poolp, thumb_list[nthumbs], thumb); nthumbs += 1; thumb_list[nthumbs] = 0; } else { dummy = NULL; } } if(dummy == NULL) { PORT_ArenaRelease(pvk->poolp, mark); return SECFailure; } pvk->assocCerts = thumb_list; pvk->nThumbs = nthumbs; PORT_ArenaUnmark(pvk->poolp, mark); return SECSuccess;}/* search the list of shrouded keys in the baggage for the desired * name. return a pointer to the item. a return of NULL indicates * that no match was present or that an error occurred. */static SEC_PKCS12ESPVKItem *sec_pkcs12_get_espvk_by_name(SEC_PKCS12Baggage *luggage, SECItem *name){ PRBool found = PR_FALSE; SEC_PKCS12ESPVKItem *espvk = NULL;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?