diff options
Diffstat (limited to 'security/nss/lib/pkcs12/p12exp.c')
-rw-r--r-- | security/nss/lib/pkcs12/p12exp.c | 1407 |
1 files changed, 0 insertions, 1407 deletions
diff --git a/security/nss/lib/pkcs12/p12exp.c b/security/nss/lib/pkcs12/p12exp.c deleted file mode 100644 index 242d98288..000000000 --- a/security/nss/lib/pkcs12/p12exp.c +++ /dev/null @@ -1,1407 +0,0 @@ -/* - * 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 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(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; - 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(PRArenaPool *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) -{ - PRArenaPool *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; - PRArenaPool *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; - PRArenaPool *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; -} |