Index: nss_pkcs12/p12exp.c |
=================================================================== |
--- nss_pkcs12/p12exp.c (revision 26000) |
+++ nss_pkcs12/p12exp.c (working copy) |
@@ -1,1378 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
- |
-#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 void |
-sec_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 void |
-sec_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 void |
-sec_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 void |
-sec_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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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; |
- int i, j; |
- SECComparison rv = SECEqual; |
- SECItem *t_name; |
- SEC_PKCS12BaggageItem *bag; |
- |
- if((luggage == NULL) || (name == NULL)) { |
- return NULL; |
- } |
- |
- i = 0; |
- while((found == PR_FALSE) && (i < luggage->luggage_size)) { |
- j = 0; |
- bag = luggage->bags[i]; |
- while((found == PR_FALSE) && (j < bag->nEspvks)) { |
- espvk = bag->espvks[j]; |
- if(espvk->poolp == NULL) { |
- espvk->poolp = luggage->poolp; |
- } |
- t_name = SECITEM_DupItem(&espvk->espvkData.nickname); |
- if(t_name != NULL) { |
- rv = SECITEM_CompareItem(name, t_name); |
- if(rv == SECEqual) { |
- found = PR_TRUE; |
- } |
- SECITEM_FreeItem(t_name, PR_TRUE); |
- } else { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- j++; |
- } |
- i++; |
- } |
- |
- if(found != PR_TRUE) { |
- PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME); |
- return NULL; |
- } |
- |
- return espvk; |
-} |
- |
-/* locates a certificate and copies the thumbprint to the |
- * appropriate private key |
- */ |
-static SECStatus |
-sec_pkcs12_propagate_thumbprints(SECItem **nicknames, |
- CERTCertificate **ref_certs, |
- SEC_PKCS12SafeContents *safe, |
- SEC_PKCS12Baggage *baggage) |
-{ |
- SEC_PKCS12CertAndCRL *cert; |
- SEC_PKCS12PrivateKey *key; |
- SEC_PKCS12ESPVKItem *espvk; |
- int i; |
- PRBool error = PR_FALSE; |
- SECStatus rv = SECFailure; |
- |
- if((nicknames == NULL) || (safe == NULL)) { |
- return SECFailure; |
- } |
- |
- i = 0; |
- while((nicknames[i] != NULL) && (error == PR_FALSE)) { |
- /* process all certs */ |
- cert = (SEC_PKCS12CertAndCRL *)sec_pkcs12_find_object(safe, baggage, |
- SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID, |
- nicknames[i], NULL); |
- if(cert != NULL) { |
- /* locate key and copy thumbprint */ |
- key = (SEC_PKCS12PrivateKey *)sec_pkcs12_find_object(safe, baggage, |
- SEC_OID_PKCS12_KEY_BAG_ID, |
- nicknames[i], NULL); |
- if(key != NULL) { |
- key->pvkData.poolp = key->poolp; |
- rv = sec_pkcs12_add_thumbprint(&key->pvkData, |
- &cert->value.x509->thumbprint); |
- if(rv == SECFailure) |
- error = PR_TRUE; /* XXX Set error? */ |
- } |
- |
- /* look in the baggage as well...*/ |
- if((baggage != NULL) && (error == PR_FALSE)) { |
- espvk = sec_pkcs12_get_espvk_by_name(baggage, nicknames[i]); |
- if(espvk != NULL) { |
- espvk->espvkData.poolp = espvk->poolp; |
- rv = sec_pkcs12_add_thumbprint(&espvk->espvkData, |
- &cert->value.x509->thumbprint); |
- if(rv == SECFailure) |
- error = PR_TRUE; /* XXX Set error? */ |
- } |
- } |
- } |
- i++; |
- } |
- |
- if(error == PR_TRUE) { |
- return SECFailure; |
- } |
- |
- return SECSuccess; |
-} |
- |
-/* append a safe bag to the end of the safe contents list */ |
-SECStatus |
-sec_pkcs12_append_safe_bag(SEC_PKCS12SafeContents *safe, |
- SEC_PKCS12SafeBag *bag) |
-{ |
- int size; |
- void *mark = NULL, *dummy = NULL; |
- |
- if((bag == NULL) || (safe == NULL)) |
- return SECFailure; |
- |
- mark = PORT_ArenaMark(safe->poolp); |
- |
- size = (safe->safe_size * sizeof(SEC_PKCS12SafeBag *)); |
- |
- if(safe->safe_size > 0) { |
- dummy = (SEC_PKCS12SafeBag **)PORT_ArenaGrow(safe->poolp, |
- safe->contents, |
- size, |
- (size + sizeof(SEC_PKCS12SafeBag *))); |
- safe->contents = dummy; |
- } else { |
- safe->contents = (SEC_PKCS12SafeBag **)PORT_ArenaZAlloc(safe->poolp, |
- (2 * sizeof(SEC_PKCS12SafeBag *))); |
- dummy = safe->contents; |
- } |
- |
- if(dummy == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- goto loser; |
- } |
- |
- safe->contents[safe->safe_size] = bag; |
- safe->safe_size++; |
- safe->contents[safe->safe_size] = NULL; |
- |
- PORT_ArenaUnmark(safe->poolp, mark); |
- return SECSuccess; |
- |
-loser: |
- PORT_ArenaRelease(safe->poolp, mark); |
- return SECFailure; |
-} |
- |
-/* append a certificate onto the end of a cert bag */ |
-static SECStatus |
-sec_pkcs12_append_cert_to_bag(PLArenaPool *arena, |
- SEC_PKCS12SafeBag *safebag, |
- CERTCertificate *cert, |
- SECItem *nickname) |
-{ |
- int size; |
- void *dummy = NULL, *mark = NULL; |
- SEC_PKCS12CertAndCRL *p12cert; |
- SEC_PKCS12CertAndCRLBag *bag; |
- |
- if((arena == NULL) || (safebag == NULL) || |
- (cert == NULL) || (nickname == NULL)) { |
- return SECFailure; |
- } |
- |
- bag = safebag->safeContent.certAndCRLBag; |
- if(bag == NULL) { |
- return SECFailure; |
- } |
- |
- mark = PORT_ArenaMark(arena); |
- |
- p12cert = sec_pkcs12_get_cert(arena, cert, nickname); |
- if(p12cert == NULL) { |
- PORT_ArenaRelease(bag->poolp, mark); |
- return SECFailure; |
- } |
- |
- size = bag->bag_size * sizeof(SEC_PKCS12CertAndCRL *); |
- if(bag->bag_size > 0) { |
- dummy = (SEC_PKCS12CertAndCRL **)PORT_ArenaGrow(bag->poolp, |
- bag->certAndCRLs, size, size + sizeof(SEC_PKCS12CertAndCRL *)); |
- bag->certAndCRLs = dummy; |
- } else { |
- bag->certAndCRLs = (SEC_PKCS12CertAndCRL **)PORT_ArenaZAlloc(bag->poolp, |
- (2 * sizeof(SEC_PKCS12CertAndCRL *))); |
- dummy = bag->certAndCRLs; |
- } |
- |
- if(dummy == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- goto loser; |
- } |
- |
- bag->certAndCRLs[bag->bag_size] = p12cert; |
- bag->bag_size++; |
- bag->certAndCRLs[bag->bag_size] = NULL; |
- |
- PORT_ArenaUnmark(bag->poolp, mark); |
- return SECSuccess; |
- |
-loser: |
- PORT_ArenaRelease(bag->poolp, mark); |
- return SECFailure; |
-} |
- |
-/* append a key onto the end of a list of keys in a key bag */ |
-SECStatus |
-sec_pkcs12_append_key_to_bag(SEC_PKCS12SafeBag *safebag, |
- SEC_PKCS12PrivateKey *pk) |
-{ |
- void *mark, *dummy; |
- SEC_PKCS12PrivateKeyBag *bag; |
- int size; |
- |
- if((safebag == NULL) || (pk == NULL)) |
- return SECFailure; |
- |
- bag = safebag->safeContent.keyBag; |
- if(bag == NULL) { |
- return SECFailure; |
- } |
- |
- mark = PORT_ArenaMark(bag->poolp); |
- |
- size = (bag->bag_size * sizeof(SEC_PKCS12PrivateKey *)); |
- |
- if(bag->bag_size > 0) { |
- dummy = (SEC_PKCS12PrivateKey **)PORT_ArenaGrow(bag->poolp, |
- bag->privateKeys, |
- size, |
- size + sizeof(SEC_PKCS12PrivateKey *)); |
- bag->privateKeys = dummy; |
- } else { |
- bag->privateKeys = (SEC_PKCS12PrivateKey **)PORT_ArenaZAlloc(bag->poolp, |
- (2 * sizeof(SEC_PKCS12PrivateKey *))); |
- dummy = bag->privateKeys; |
- } |
- |
- if(dummy == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- goto loser; |
- } |
- |
- bag->privateKeys[bag->bag_size] = pk; |
- bag->bag_size++; |
- bag->privateKeys[bag->bag_size] = NULL; |
- |
- PORT_ArenaUnmark(bag->poolp, mark); |
- return SECSuccess; |
- |
-loser: |
- /* XXX Free memory? */ |
- PORT_ArenaRelease(bag->poolp, mark); |
- return SECFailure; |
-} |
- |
-/* append a safe bag to the baggage area */ |
-static SECStatus |
-sec_pkcs12_append_unshrouded_bag(SEC_PKCS12BaggageItem *bag, |
- SEC_PKCS12SafeBag *u_bag) |
-{ |
- int size; |
- void *mark = NULL, *dummy = NULL; |
- |
- if((bag == NULL) || (u_bag == NULL)) |
- return SECFailure; |
- |
- mark = PORT_ArenaMark(bag->poolp); |
- |
- /* dump things into the first bag */ |
- size = (bag->nSecrets + 1) * sizeof(SEC_PKCS12SafeBag *); |
- dummy = PORT_ArenaGrow(bag->poolp, |
- bag->unencSecrets, size, |
- size + sizeof(SEC_PKCS12SafeBag *)); |
- bag->unencSecrets = dummy; |
- if(dummy == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- goto loser; |
- } |
- |
- bag->unencSecrets[bag->nSecrets] = u_bag; |
- bag->nSecrets++; |
- bag->unencSecrets[bag->nSecrets] = NULL; |
- |
- PORT_ArenaUnmark(bag->poolp, mark); |
- return SECSuccess; |
- |
-loser: |
- PORT_ArenaRelease(bag->poolp, mark); |
- return SECFailure; |
-} |
- |
-/* gather up all certificates and keys and package them up |
- * in the safe, baggage, or both. |
- * nicknames is the list of nicknames and corresponding certs in ref_certs |
- * ref_certs a null terminated list of certificates |
- * rSafe, rBaggage -- return areas for safe and baggage |
- * shroud_keys -- store keys externally |
- * pwitem -- password for computing integrity mac and encrypting contents |
- * wincx -- window handle |
- * |
- * if a failure occurs, an error is set and SECFailure returned. |
- */ |
-static SECStatus |
-sec_pkcs12_package_certs_and_keys(SECItem **nicknames, |
- CERTCertificate **ref_certs, |
- PRBool unencryptedCerts, |
- SEC_PKCS12SafeContents **rSafe, |
- SEC_PKCS12Baggage **rBaggage, |
- PRBool shroud_keys, |
- SECOidTag shroud_alg, |
- SECItem *pwitem, |
- PKCS12UnicodeConvertFunction unicodeFn, |
- void *wincx) |
-{ |
- PLArenaPool *permArena; |
- SEC_PKCS12SafeContents *safe = NULL; |
- SEC_PKCS12Baggage *baggage = NULL; |
- |
- SECStatus rv = SECFailure; |
- PRBool problem = PR_FALSE; |
- |
- SEC_PKCS12ESPVKItem *espvk = NULL; |
- SEC_PKCS12PrivateKey *pk = NULL; |
- CERTCertificate *add_cert = NULL; |
- SEC_PKCS12SafeBag *certbag = NULL, *keybag = NULL; |
- SEC_PKCS12BaggageItem *external_bag = NULL; |
- int ncerts = 0, nkeys = 0; |
- int i; |
- |
- if((nicknames == NULL) || (rSafe == NULL) || (rBaggage == NULL)) { |
- return SECFailure; |
- } |
- |
- *rBaggage = baggage; |
- *rSafe = safe; |
- |
- permArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); |
- if(permArena == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return SECFailure; |
- } |
- |
- /* allocate structures */ |
- safe = sec_pkcs12_create_safe_contents(permArena); |
- if(safe == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- rv = SECFailure; |
- goto loser; |
- } |
- |
- certbag = sec_pkcs12_create_safe_bag(permArena, |
- SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID); |
- if(certbag == NULL) { |
- rv = SECFailure; |
- goto loser; |
- } |
- |
- if(shroud_keys != PR_TRUE) { |
- keybag = sec_pkcs12_create_safe_bag(permArena, |
- SEC_OID_PKCS12_KEY_BAG_ID); |
- if(keybag == NULL) { |
- rv = SECFailure; |
- goto loser; |
- } |
- } |
- |
- if((shroud_keys == PR_TRUE) || (unencryptedCerts == PR_TRUE)) { |
- baggage = sec_pkcs12_create_baggage(permArena); |
- if(baggage == NULL) { |
- rv = SECFailure; |
- goto loser; |
- } |
- external_bag = sec_pkcs12_create_external_bag(baggage); |
- } |
- |
- /* package keys and certs */ |
- i = 0; |
- while((nicknames[i] != NULL) && (problem == PR_FALSE)) { |
- if(ref_certs[i] != NULL) { |
- /* append cert to bag o certs */ |
- rv = sec_pkcs12_append_cert_to_bag(permArena, certbag, |
- ref_certs[i], |
- nicknames[i]); |
- if(rv == SECFailure) { |
- problem = PR_FALSE; |
- } else { |
- ncerts++; |
- } |
- |
- if(rv == SECSuccess) { |
- /* package up them keys */ |
- if(shroud_keys == PR_TRUE) { |
- espvk = sec_pkcs12_get_shrouded_key(permArena, |
- nicknames[i], |
- ref_certs[i], |
- shroud_alg, |
- pwitem, unicodeFn, |
- wincx); |
- if(espvk != NULL) { |
- rv = sec_pkcs12_append_shrouded_key(external_bag, espvk); |
- SECITEM_CopyItem(permArena, &espvk->derCert, |
- &ref_certs[i]->derCert); |
- } else { |
- rv = SECFailure; |
- } |
- } else { |
- pk = sec_pkcs12_get_private_key(permArena, nicknames[i], |
- ref_certs[i], wincx); |
- if(pk != NULL) { |
- rv = sec_pkcs12_append_key_to_bag(keybag, pk); |
- SECITEM_CopyItem(permArena, &espvk->derCert, |
- &ref_certs[i]->derCert); |
- } else { |
- rv = SECFailure; |
- } |
- } |
- |
- if(rv == SECFailure) { |
- problem = PR_TRUE; |
- } else { |
- nkeys++; |
- } |
- } |
- } else { |
- /* handle only keys here ? */ |
- problem = PR_TRUE; |
- } |
- i++; |
- } |
- |
- /* let success fall through */ |
-loser: |
- if(problem == PR_FALSE) { |
- /* if we have certs, we want to append the cert bag to the |
- * appropriate area |
- */ |
- if(ncerts > 0) { |
- if(unencryptedCerts != PR_TRUE) { |
- rv = sec_pkcs12_append_safe_bag(safe, certbag); |
- } else { |
- rv = sec_pkcs12_append_unshrouded_bag(external_bag, certbag); |
- } |
- } else { |
- rv = SECSuccess; |
- } |
- |
- /* append key bag, if they are stored in safe contents */ |
- if((rv == SECSuccess) && (shroud_keys == PR_FALSE) && (nkeys > 0)) { |
- rv = sec_pkcs12_append_safe_bag(safe, keybag); |
- } |
- } else { |
- rv = SECFailure; |
- } |
- |
- /* if baggage not used, NULLify it */ |
- if((shroud_keys == PR_TRUE) || (unencryptedCerts == PR_TRUE)) { |
- if(((unencryptedCerts == PR_TRUE) && (ncerts == 0)) && |
- ((shroud_keys == PR_TRUE) && (nkeys == 0))) |
- baggage = NULL; |
- } else { |
- baggage = NULL; |
- } |
- |
- if((problem == PR_TRUE) || (rv == SECFailure)) { |
- PORT_FreeArena(permArena, PR_TRUE); |
- rv = SECFailure; |
- baggage = NULL; |
- safe = NULL; |
- } |
- |
- *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; |
- PLArenaPool *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; |
- PLArenaPool *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; |
-} |