summaryrefslogtreecommitdiff
path: root/security/nss/lib/pki/pki3hack.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/pki/pki3hack.c')
-rw-r--r--security/nss/lib/pki/pki3hack.c1228
1 files changed, 0 insertions, 1228 deletions
diff --git a/security/nss/lib/pki/pki3hack.c b/security/nss/lib/pki/pki3hack.c
deleted file mode 100644
index bbbeb5d4b..000000000
--- a/security/nss/lib/pki/pki3hack.c
+++ /dev/null
@@ -1,1228 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * 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 the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifdef DEBUG
-static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
-#endif /* DEBUG */
-
-/*
- * Hacks to integrate NSS 3.4 and NSS 4.0 certificates.
- */
-
-#ifndef NSSPKI_H
-#include "nsspki.h"
-#endif /* NSSPKI_H */
-
-#ifndef PKI_H
-#include "pki.h"
-#endif /* PKI_H */
-
-#ifndef PKIM_H
-#include "pkim.h"
-#endif /* PKIM_H */
-
-#ifndef DEV_H
-#include "dev.h"
-#endif /* DEV_H */
-
-#ifndef DEVNSS3HACK_H
-#include "dev3hack.h"
-#endif /* DEVNSS3HACK_H */
-
-#ifndef PKINSS3HACK_H
-#include "pki3hack.h"
-#endif /* PKINSS3HACK_H */
-
-#include "secitem.h"
-#include "certdb.h"
-#include "certt.h"
-#include "cert.h"
-#include "pk11func.h"
-#include "pkistore.h"
-#include "secmod.h"
-#include "nssrwlk.h"
-
-NSSTrustDomain *g_default_trust_domain = NULL;
-
-NSSCryptoContext *g_default_crypto_context = NULL;
-
-NSSTrustDomain *
-STAN_GetDefaultTrustDomain()
-{
- return g_default_trust_domain;
-}
-
-NSSCryptoContext *
-STAN_GetDefaultCryptoContext()
-{
- return g_default_crypto_context;
-}
-
-extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
-extern const NSSError NSS_ERROR_INTERNAL_ERROR;
-
-NSS_IMPLEMENT PRStatus
-STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot)
-{
- NSSToken *token;
- if (!td) {
- td = g_default_trust_domain;
- }
- token = nssToken_CreateFromPK11SlotInfo(td, slot);
- PK11Slot_SetNSSToken(slot, token);
- NSSRWLock_LockWrite(td->tokensLock);
- nssList_Add(td->tokenList, token);
- NSSRWLock_UnlockWrite(td->tokensLock);
- return PR_SUCCESS;
-}
-
-NSS_IMPLEMENT PRStatus
-STAN_ResetTokenInterator(NSSTrustDomain *td)
-{
- if (!td) {
- td = g_default_trust_domain;
- }
- NSSRWLock_LockWrite(td->tokensLock);
- nssListIterator_Destroy(td->tokens);
- td->tokens = nssList_CreateIterator(td->tokenList);
- NSSRWLock_UnlockWrite(td->tokensLock);
- return PR_SUCCESS;
-}
-
-NSS_IMPLEMENT PRStatus
-STAN_LoadDefaultNSS3TrustDomain (
- void
-)
-{
- NSSTrustDomain *td;
- SECMODModuleList *mlp;
- SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
- int i;
-
- if (g_default_trust_domain || g_default_crypto_context) {
- /* Stan is already initialized or a previous shutdown failed. */
- nss_SetError(NSS_ERROR_ALREADY_INITIALIZED);
- return PR_FAILURE;
- }
- td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL);
- if (!td) {
- return PR_FAILURE;
- }
- /*
- * Deadlock warning: we should never acquire the moduleLock while
- * we hold the tokensLock. We can use the NSSRWLock Rank feature to
- * guarrentee this. tokensLock have a higher rank than module lock.
- */
- SECMOD_GetReadLock(moduleLock);
- NSSRWLock_LockWrite(td->tokensLock);
- td->tokenList = nssList_Create(td->arena, PR_TRUE);
- for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp=mlp->next) {
- for (i=0; i < mlp->module->slotCount; i++) {
- STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]);
- }
- }
- td->tokens = nssList_CreateIterator(td->tokenList);
- NSSRWLock_UnlockWrite(td->tokensLock);
- SECMOD_ReleaseReadLock(moduleLock);
- g_default_trust_domain = td;
- g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL);
- return PR_SUCCESS;
-}
-
-/*
- * must be called holding the ModuleListLock (either read or write).
- */
-NSS_IMPLEMENT SECStatus
-STAN_AddModuleToDefaultTrustDomain (
- SECMODModule *module
-)
-{
- NSSTrustDomain *td;
- int i;
- td = STAN_GetDefaultTrustDomain();
- for (i=0; i<module->slotCount; i++) {
- STAN_InitTokenForSlotInfo(td, module->slots[i]);
- }
- STAN_ResetTokenInterator(td);
- return SECSuccess;
-}
-
-/*
- * must be called holding the ModuleListLock (either read or write).
- */
-NSS_IMPLEMENT SECStatus
-STAN_RemoveModuleFromDefaultTrustDomain (
- SECMODModule *module
-)
-{
- NSSToken *token;
- NSSTrustDomain *td;
- int i;
- td = STAN_GetDefaultTrustDomain();
- NSSRWLock_LockWrite(td->tokensLock);
- for (i=0; i<module->slotCount; i++) {
- token = PK11Slot_GetNSSToken(module->slots[i]);
- if (token) {
- nssToken_NotifyCertsNotVisible(token);
- nssList_Remove(td->tokenList, token);
- PK11Slot_SetNSSToken(module->slots[i], NULL);
- nssToken_Destroy(token);
- }
- }
- nssListIterator_Destroy(td->tokens);
- td->tokens = nssList_CreateIterator(td->tokenList);
- NSSRWLock_UnlockWrite(td->tokensLock);
- return SECSuccess;
-}
-
-NSS_IMPLEMENT PRStatus
-STAN_Shutdown()
-{
- PRStatus status = PR_SUCCESS;
- if (g_default_trust_domain) {
- if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) {
- g_default_trust_domain = NULL;
- } else {
- status = PR_FAILURE;
- }
- }
- if (g_default_crypto_context) {
- if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) {
- g_default_crypto_context = NULL;
- } else {
- status = PR_FAILURE;
- }
- }
- return status;
-}
-
-/* this function should not be a hack; it will be needed in 4.0 (rename) */
-NSS_IMPLEMENT NSSItem *
-STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der)
-{
- NSSItem *rvKey;
- SECItem secDER;
- SECItem secKey = { 0 };
- SECStatus secrv;
- PRArenaPool *arena;
-
- SECITEM_FROM_NSSITEM(&secDER, der);
-
- /* nss3 call uses nss3 arena's */
- arena = PORT_NewArena(256);
- if (!arena) {
- return NULL;
- }
- secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey);
- if (secrv != SECSuccess) {
- return NULL;
- }
- rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data);
- PORT_FreeArena(arena,PR_FALSE);
- return rvKey;
-}
-
-NSS_IMPLEMENT PRStatus
-nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der, NSSArena *arena,
- NSSDER *issuer, NSSDER *serial)
-{
- SECStatus secrv;
- SECItem derCert;
- SECItem derIssuer = { 0 };
- SECItem derSerial = { 0 };
- SECITEM_FROM_NSSITEM(&derCert, der);
- secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial);
- if (secrv != SECSuccess) {
- return PR_FAILURE;
- }
- (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
- secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer);
- if (secrv != SECSuccess) {
- PORT_Free(derSerial.data);
- return PR_FAILURE;
- }
- (void)nssItem_Create(arena, issuer, derIssuer.len, derIssuer.data);
- PORT_Free(derSerial.data);
- PORT_Free(derIssuer.data);
- return PR_SUCCESS;
-}
-
-static NSSItem *
-nss3certificate_getIdentifier(nssDecodedCert *dc)
-{
- NSSItem *rvID;
- CERTCertificate *c = (CERTCertificate *)dc->data;
- rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data);
- return rvID;
-}
-
-static void *
-nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
-{
- CERTCertificate *c = (CERTCertificate *)dc->data;
- return (void *)c->authKeyID;
-}
-
-static nssCertIDMatch
-nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id)
-{
- CERTCertificate *c = (CERTCertificate *)dc->data;
- CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
- SECItem skid;
- nssCertIDMatch match = nssCertIDMatch_Unknown;
-
- /* keyIdentifier */
- if (authKeyID->keyID.len > 0) {
- if (CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) {
- PRBool skiEqual;
- skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
- PORT_Free(skid.data);
- if (skiEqual) {
- /* change the state to positive match, but keep going */
- match = nssCertIDMatch_Yes;
- } else {
- /* exit immediately on failure */
- return nssCertIDMatch_No;
- }
- } /* else fall through */
- }
-
- /* issuer/serial (treated as pair) */
- if (authKeyID->authCertIssuer) {
- SECItem *caName = NULL;
- SECItem *caSN = &authKeyID->authCertSerialNumber;
-
- caName = (SECItem *)CERT_GetGeneralNameByType(
- authKeyID->authCertIssuer,
- certDirectoryName, PR_TRUE);
- if (caName == NULL) {
- /* this is some kind of error, so treat it as unknown */
- return nssCertIDMatch_Unknown;
- }
- if (SECITEM_ItemsAreEqual(&c->derIssuer, caName) &&
- SECITEM_ItemsAreEqual(&c->serialNumber, caSN))
- {
- /* change the state to positive match, but keep going */
- match = nssCertIDMatch_Yes;
- } else {
- /* exit immediately on failure */
- return nssCertIDMatch_No;
- }
- }
-
- /* If the issued cert has a keyIdentifier field with a value, but
- * this issuer cert does not have a subjectKeyID extension, and
- * the issuer/serial number fields of the authKeyID extension
- * are empty, the state will be Unknown. Otherwise it should have
- * been set to Yes.
- */
- return match;
-}
-
-static PRBool
-nss3certificate_isValidIssuer(nssDecodedCert *dc)
-{
- CERTCertificate *c = (CERTCertificate *)dc->data;
- unsigned int ignore;
- return CERT_IsCACert(c, &ignore);
-}
-
-static NSSUsage *
-nss3certificate_getUsage(nssDecodedCert *dc)
-{
- /* CERTCertificate *c = (CERTCertificate *)dc->data; */
- return NULL;
-}
-
-static PRBool
-nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time)
-{
- SECCertTimeValidity validity;
- CERTCertificate *c = (CERTCertificate *)dc->data;
- validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE);
- if (validity == secCertTimeValid) {
- return PR_TRUE;
- }
- return PR_FALSE;
-}
-
-static PRBool
-nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc)
-{
- /* I know this isn't right, but this is glue code anyway */
- if (cmpdc->type == dc->type) {
- CERTCertificate *certa = (CERTCertificate *)dc->data;
- CERTCertificate *certb = (CERTCertificate *)cmpdc->data;
- return CERT_IsNewer(certa, certb);
- }
- return PR_FALSE;
-}
-
-/* CERT_FilterCertListByUsage */
-static PRBool
-nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage)
-{
- CERTCertificate *cc;
- unsigned int requiredKeyUsage = 0;
- unsigned int requiredCertType = 0;
- SECStatus secrv;
- PRBool match;
- PRBool ca;
-
- /* This is for NSS 3.3 functions that do not specify a usage */
- if (usage->anyUsage) {
- return PR_TRUE;
- }
- ca = usage->nss3lookingForCA;
- secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca,
- &requiredKeyUsage,
- &requiredCertType);
- if (secrv != SECSuccess) {
- return PR_FALSE;
- }
- cc = (CERTCertificate *)dc->data;
- secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage);
- match = (PRBool)(secrv == SECSuccess);
- if (match) {
- unsigned int certType = 0;
- if (ca) {
- (void)CERT_IsCACert(cc, &certType);
- } else {
- certType = cc->nsCertType;
- }
- if (!(certType & requiredCertType)) {
- match = PR_FALSE;
- }
- }
- return match;
-}
-
-static NSSASCII7 *
-nss3certificate_getEmailAddress(nssDecodedCert *dc)
-{
- CERTCertificate *cc = (CERTCertificate *)dc->data;
- return (cc && cc->emailAddr && cc->emailAddr[0])
- ? (NSSASCII7 *)cc->emailAddr : NULL;
-}
-
-static PRStatus
-nss3certificate_getDERSerialNumber(nssDecodedCert *dc,
- NSSDER *serial, NSSArena *arena)
-{
- CERTCertificate *cc = (CERTCertificate *)dc->data;
- SECItem derSerial = { 0 };
- SECStatus secrv;
- secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
- if (secrv == SECSuccess) {
- (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
- PORT_Free(derSerial.data);
- return PR_SUCCESS;
- }
- return PR_FAILURE;
-}
-
-/* Returns NULL if "encoding" cannot be decoded. */
-NSS_IMPLEMENT nssDecodedCert *
-nssDecodedPKIXCertificate_Create (
- NSSArena *arenaOpt,
- NSSDER *encoding
-)
-{
- nssDecodedCert *rvDC = NULL;
- CERTCertificate *cert;
- SECItem secDER;
-
- SECITEM_FROM_NSSITEM(&secDER, encoding);
- cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL);
- if (cert) {
- rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
- if (rvDC) {
- rvDC->type = NSSCertificateType_PKIX;
- rvDC->data = (void *)cert;
- rvDC->getIdentifier = nss3certificate_getIdentifier;
- rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
- rvDC->matchIdentifier = nss3certificate_matchIdentifier;
- rvDC->isValidIssuer = nss3certificate_isValidIssuer;
- rvDC->getUsage = nss3certificate_getUsage;
- rvDC->isValidAtTime = nss3certificate_isValidAtTime;
- rvDC->isNewerThan = nss3certificate_isNewerThan;
- rvDC->matchUsage = nss3certificate_matchUsage;
- rvDC->getEmailAddress = nss3certificate_getEmailAddress;
- rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
- } else {
- CERT_DestroyCertificate(cert);
- }
- }
- return rvDC;
-}
-
-static nssDecodedCert *
-create_decoded_pkix_cert_from_nss3cert (
- NSSArena *arenaOpt,
- CERTCertificate *cc
-)
-{
- nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
- if (rvDC) {
- rvDC->type = NSSCertificateType_PKIX;
- rvDC->data = (void *)cc;
- rvDC->getIdentifier = nss3certificate_getIdentifier;
- rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
- rvDC->matchIdentifier = nss3certificate_matchIdentifier;
- rvDC->isValidIssuer = nss3certificate_isValidIssuer;
- rvDC->getUsage = nss3certificate_getUsage;
- rvDC->isValidAtTime = nss3certificate_isValidAtTime;
- rvDC->isNewerThan = nss3certificate_isNewerThan;
- rvDC->matchUsage = nss3certificate_matchUsage;
- rvDC->getEmailAddress = nss3certificate_getEmailAddress;
- }
- return rvDC;
-}
-
-NSS_IMPLEMENT PRStatus
-nssDecodedPKIXCertificate_Destroy (
- nssDecodedCert *dc
-)
-{
- CERTCertificate *cert = (CERTCertificate *)dc->data;
-
- /* The decoder may only be half initialized (the case where we find we
- * could not decode the certificate). In this case, there is not cert to
- * free, just free the dc structure. */
- if (cert) {
- PRBool freeSlot = cert->ownSlot;
- PK11SlotInfo *slot = cert->slot;
- PRArenaPool *arena = cert->arena;
- /* zero cert before freeing. Any stale references to this cert
- * after this point will probably cause an exception. */
- PORT_Memset(cert, 0, sizeof *cert);
- /* free the arena that contains the cert. */
- PORT_FreeArena(arena, PR_FALSE);
- if (slot && freeSlot) {
- PK11_FreeSlot(slot);
- }
- }
- nss_ZFreeIf(dc);
- return PR_SUCCESS;
-}
-
-/* see pk11cert.c:pk11_HandleTrustObject */
-static unsigned int
-get_nss3trust_from_nss4trust(CK_TRUST t)
-{
- unsigned int rt = 0;
- if (t == nssTrustLevel_Trusted) {
- rt |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
- }
- if (t == nssTrustLevel_TrustedDelegator) {
- rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA /*| CERTDB_NS_TRUSTED_CA*/;
- }
- if (t == nssTrustLevel_Valid) {
- rt |= CERTDB_VALID_PEER;
- }
- if (t == nssTrustLevel_ValidDelegator) {
- rt |= CERTDB_VALID_CA;
- }
- return rt;
-}
-
-static CERTCertTrust *
-cert_trust_from_stan_trust(NSSTrust *t, PRArenaPool *arena)
-{
- CERTCertTrust *rvTrust;
- unsigned int client;
- if (!t) {
- return NULL;
- }
- rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust));
- if (!rvTrust) return NULL;
- rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth);
- client = get_nss3trust_from_nss4trust(t->clientAuth);
- if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) {
- client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA);
- rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA;
- }
- rvTrust->sslFlags |= client;
- rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection);
- rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning);
- /* The cert is a valid step-up cert (in addition to/lieu of trust above */
- if (t->stepUpApproved) {
- rvTrust->sslFlags |= CERTDB_GOVT_APPROVED_CA;
- }
- return rvTrust;
-}
-
-CERTCertTrust *
-nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc)
-{
- CERTCertTrust *rvTrust = NULL;
- NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
- NSSTrust *t;
- t = nssTrustDomain_FindTrustForCertificate(td, c);
- if (t) {
- rvTrust = cert_trust_from_stan_trust(t, cc->arena);
- if (!rvTrust) {
- nssTrust_Destroy(t);
- return NULL;
- }
- nssTrust_Destroy(t);
- } else {
- rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
- if (!rvTrust) {
- return NULL;
- }
- memset(rvTrust, 0, sizeof(*rvTrust));
- }
- if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) {
- rvTrust->sslFlags |= CERTDB_USER;
- rvTrust->emailFlags |= CERTDB_USER;
- rvTrust->objectSigningFlags |= CERTDB_USER;
- }
- return rvTrust;
-}
-
-static nssCryptokiInstance *
-get_cert_instance(NSSCertificate *c)
-{
- nssCryptokiObject *instance, **ci;
- nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
- if (!instances) {
- return NULL;
- }
- instance = NULL;
- for (ci = instances; *ci; ci++) {
- if (!instance) {
- instance = nssCryptokiObject_Clone(*ci);
- } else {
- /* This only really works for two instances... But 3.4 can't
- * handle more anyway. The logic is, if there are multiple
- * instances, prefer the one that is not internal (e.g., on
- * a hardware device.
- */
- if (PK11_IsInternal(instance->token->pk11slot)) {
- nssCryptokiObject_Destroy(instance);
- instance = nssCryptokiObject_Clone(*ci);
- }
- }
- }
- nssCryptokiObjectArray_Destroy(instances);
- return instance;
-}
-
-char *
-STAN_GetCERTCertificateNameForInstance (
- PLArenaPool *arenaOpt,
- NSSCertificate *c,
- nssCryptokiInstance *instance
-)
-{
- NSSCryptoContext *context = c->object.cryptoContext;
- PRStatus nssrv;
- int nicklen, tokenlen, len;
- NSSUTF8 *tokenName = NULL;
- NSSUTF8 *stanNick = NULL;
- char *nickname = NULL;
- char *nick;
-
- if (instance) {
- stanNick = instance->label;
- } else if (context) {
- stanNick = c->object.tempName;
- }
- if (stanNick) {
- /* fill other fields needed by NSS3 functions using CERTCertificate */
- if (instance && !PK11_IsInternal(instance->token->pk11slot)) {
- tokenName = nssToken_GetName(instance->token);
- tokenlen = nssUTF8_Size(tokenName, &nssrv);
- } else {
- /* don't use token name for internal slot; 3.3 didn't */
- tokenlen = 0;
- }
- nicklen = nssUTF8_Size(stanNick, &nssrv);
- len = tokenlen + nicklen;
- if (arenaOpt) {
- nickname = PORT_ArenaAlloc(arenaOpt, len);
- } else {
- nickname = PORT_Alloc(len);
- }
- nick = nickname;
- if (tokenName) {
- memcpy(nick, tokenName, tokenlen-1);
- nick += tokenlen-1;
- *nick++ = ':';
- }
- memcpy(nick, stanNick, nicklen-1);
- nickname[len-1] = '\0';
- }
- return nickname;
-}
-
-char *
-STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c)
-{
- nssCryptokiInstance *instance = get_cert_instance(c);
- return STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance);
-}
-
-static void
-fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced)
-{
- NSSTrust *nssTrust;
- NSSCryptoContext *context = c->object.cryptoContext;
- nssCryptokiInstance *instance = get_cert_instance(c);
- NSSUTF8 *stanNick = NULL;
- if (instance) {
- stanNick = instance->label;
- } else if (context) {
- stanNick = c->object.tempName;
- }
- /* fill other fields needed by NSS3 functions using CERTCertificate */
- if ((!cc->nickname && stanNick) || forced) {
- PRStatus nssrv;
- int nicklen, tokenlen, len;
- NSSUTF8 *tokenName = NULL;
- char *nick;
- if (instance && !PK11_IsInternal(instance->token->pk11slot)) {
- tokenName = nssToken_GetName(instance->token);
- tokenlen = nssUTF8_Size(tokenName, &nssrv);
- } else {
- /* don't use token name for internal slot; 3.3 didn't */
- tokenlen = 0;
- }
- if (stanNick) {
- nicklen = nssUTF8_Size(stanNick, &nssrv);
- len = tokenlen + nicklen;
- cc->nickname = PORT_ArenaAlloc(cc->arena, len);
- nick = cc->nickname;
- if (tokenName) {
- memcpy(nick, tokenName, tokenlen-1);
- nick += tokenlen-1;
- *nick++ = ':';
- }
- memcpy(nick, stanNick, nicklen-1);
- cc->nickname[len-1] = '\0';
- } else {
- cc->nickname = NULL;
- }
- }
- if (context) {
- /* trust */
- nssTrust = nssCryptoContext_FindTrustForCertificate(context, c);
- if (nssTrust) {
- cc->trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
- nssTrust_Destroy(nssTrust);
- }
- } else if (instance) {
- /* slot */
- if (cc->slot != instance->token->pk11slot) {
- if (cc->slot) {
- PK11_FreeSlot(cc->slot);
- }
- cc->slot = PK11_ReferenceSlot(instance->token->pk11slot);
- }
- cc->ownSlot = PR_TRUE;
- /* pkcs11ID */
- cc->pkcs11ID = instance->handle;
- /* trust */
- cc->trust = nssTrust_GetCERTCertTrustForCert(c, cc);
- nssCryptokiObject_Destroy(instance);
- }
- /* database handle is now the trust domain */
- cc->dbhandle = c->object.trustDomain;
- /* subjectList ? */
- /* istemp and isperm are supported in NSS 3.4 */
- cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */
- cc->isperm = PR_TRUE; /* by default */
- /* pointer back */
- cc->nssCertificate = c;
-}
-
-static CERTCertificate *
-stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate)
-{
- nssDecodedCert *dc = c->decoding;
- CERTCertificate *cc;
-
- /* There is a race in assigning c->decoding.
- ** This is a workaround. Bugzilla bug 225525.
- */
- if (!dc) {
- dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
- if (!dc)
- return NULL;
- cc = (CERTCertificate *)dc->data;
- PORT_Assert(cc); /* software error */
- if (!cc) {
- nssDecodedPKIXCertificate_Destroy(dc);
- nss_SetError(NSS_ERROR_INTERNAL_ERROR);
- return NULL;
- }
- /* Once this race is fixed, an assertion should be put
- ** here to detect any regressions.
- PORT_Assert(!c->decoding);
- */
- if (!c->decoding) {
- c->decoding = dc;
- } else {
- /* Reduce the leaks here, until the race is fixed. */
- nssDecodedPKIXCertificate_Destroy(dc);
- dc = c->decoding;
- }
- }
- cc = (CERTCertificate *)dc->data;
- PORT_Assert(cc);
- /* When c->decoding is non-NULL on input, but dc->data is
- * NULL, we don't destroy dc because some other errant
- * code allocated it .
- */
- if (cc) {
- if (!cc->nssCertificate || forceUpdate) {
- fill_CERTCertificateFields(c, cc, forceUpdate);
- } else if (!cc->trust && !c->object.cryptoContext) {
- /* if it's a perm cert, it might have been stored before the
- * trust, so look for the trust again. But a temp cert can be
- * ignored.
- */
- cc->trust = nssTrust_GetCERTCertTrustForCert(c, cc);
- }
- }
- return cc;
-}
-
-NSS_IMPLEMENT CERTCertificate *
-STAN_ForceCERTCertificateUpdate(NSSCertificate *c)
-{
- if (c->decoding) {
- return stan_GetCERTCertificate(c, PR_TRUE);
- }
- return NULL;
-}
-
-NSS_IMPLEMENT CERTCertificate *
-STAN_GetCERTCertificate(NSSCertificate *c)
-{
- return stan_GetCERTCertificate(c, PR_FALSE);
-}
-/*
- * many callers of STAN_GetCERTCertificate() intend that
- * the CERTCertificate returned inherits the reference to the
- * NSSCertificate. For these callers it's convenient to have
- * this function 'own' the reference and either return a valid
- * CERTCertificate structure which inherits the reference or
- * destroy the reference to NSSCertificate and returns NULL.
- */
-NSS_IMPLEMENT CERTCertificate *
-STAN_GetCERTCertificateOrRelease(NSSCertificate *c)
-{
- CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE);
- if (!nss3cert) {
- nssCertificate_Destroy(c);
- }
- return nss3cert;
-}
-
-static nssTrustLevel
-get_stan_trust(unsigned int t, PRBool isClientAuth)
-{
- if (isClientAuth) {
- if (t & CERTDB_TRUSTED_CLIENT_CA) {
- return nssTrustLevel_TrustedDelegator;
- }
- } else {
- if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) {
- return nssTrustLevel_TrustedDelegator;
- }
- }
- if (t & CERTDB_TRUSTED) {
- return nssTrustLevel_Trusted;
- }
- if (t & CERTDB_VALID_CA) {
- return nssTrustLevel_ValidDelegator;
- }
- if (t & CERTDB_VALID_PEER) {
- return nssTrustLevel_Valid;
- }
- return nssTrustLevel_NotTrusted;
-}
-
-NSS_EXTERN NSSCertificate *
-STAN_GetNSSCertificate(CERTCertificate *cc)
-{
- NSSCertificate *c;
- nssCryptokiInstance *instance;
- nssPKIObject *pkiob;
- NSSArena *arena;
- c = cc->nssCertificate;
- if (c) {
- return c;
- }
- /* i don't think this should happen. but if it can, need to create
- * NSSCertificate from CERTCertificate values here. */
- /* Yup, it can happen. */
- arena = NSSArena_Create();
- if (!arena) {
- return NULL;
- }
- c = nss_ZNEW(arena, NSSCertificate);
- if (!c) {
- nssArena_Destroy(arena);
- return NULL;
- }
- NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
- c->type = NSSCertificateType_PKIX;
- pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL);
- if (!pkiob) {
- nssArena_Destroy(arena);
- return NULL;
- }
- c->object = *pkiob;
- nssItem_Create(arena,
- &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
- nssItem_Create(arena,
- &c->subject, cc->derSubject.len, cc->derSubject.data);
- if (PR_TRUE) {
- /* CERTCertificate stores serial numbers decoded. I need the DER
- * here. sigh.
- */
- SECItem derSerial;
- SECStatus secrv;
- secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
- if (secrv == SECFailure) {
- nssArena_Destroy(arena);
- return NULL;
- }
- nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data);
- PORT_Free(derSerial.data);
- }
- if (cc->emailAddr && cc->emailAddr[0]) {
- c->email = nssUTF8_Create(arena,
- nssStringType_PrintableString,
- (NSSUTF8 *)cc->emailAddr,
- PORT_Strlen(cc->emailAddr));
- }
- if (cc->slot) {
- instance = nss_ZNEW(arena, nssCryptokiInstance);
- instance->token = nssToken_AddRef(PK11Slot_GetNSSToken(cc->slot));
- instance->handle = cc->pkcs11ID;
- instance->isTokenObject = PR_TRUE;
- if (cc->nickname) {
- instance->label = nssUTF8_Create(arena,
- nssStringType_UTF8String,
- (NSSUTF8 *)cc->nickname,
- PORT_Strlen(cc->nickname));
- }
- nssPKIObject_AddInstance(&c->object, instance);
- }
- c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc);
- cc->nssCertificate = c;
- return c;
-}
-
-static NSSToken*
-stan_GetTrustToken (
- NSSCertificate *c
-)
-{
- NSSToken *ttok = NULL;
- NSSToken *rtok = NULL;
- NSSToken *tok = NULL;
- nssCryptokiObject **ip;
- nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
- if (!instances) {
- return PR_FALSE;
- }
- for (ip = instances; *ip; ip++) {
- nssCryptokiObject *instance = *ip;
- nssCryptokiObject *to =
- nssToken_FindTrustForCertificate(instance->token, NULL,
- &c->encoding, &c->issuer, &c->serial,
- nssTokenSearchType_TokenOnly);
- NSSToken *ctok = instance->token;
- PRBool ro = PK11_IsReadOnly(ctok->pk11slot);
-
- if (to) {
- nssCryptokiObject_Destroy(to);
- ttok = ctok;
- if (!ro) {
- break;
- }
- } else {
- if (!rtok && ro) {
- rtok = ctok;
- }
- if (!tok && !ro) {
- tok = ctok;
- }
- }
- }
- nssCryptokiObjectArray_Destroy(instances);
- return ttok ? ttok : (tok ? tok : rtok);
-}
-
-NSS_EXTERN PRStatus
-STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
-{
- PRStatus nssrv;
- NSSCertificate *c = STAN_GetNSSCertificate(cc);
- NSSToken *tok;
- NSSTrustDomain *td;
- NSSTrust *nssTrust;
- NSSArena *arena;
- CERTCertTrust *oldTrust;
- nssListIterator *tokens;
- PRBool moving_object;
- nssCryptokiObject *newInstance;
- nssPKIObject *pkiob;
- oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc);
- if (oldTrust) {
- if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) {
- /* ... and the new trust is no different, done) */
- return PR_SUCCESS;
- } else {
- /* take over memory already allocated in cc's arena */
- cc->trust = oldTrust;
- }
- } else {
- cc->trust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
- }
- memcpy(cc->trust, trust, sizeof(CERTCertTrust));
- /* Set the NSSCerticate's trust */
- arena = nssArena_Create();
- if (!arena) return PR_FAILURE;
- nssTrust = nss_ZNEW(arena, NSSTrust);
- pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL);
- if (!pkiob) {
- nssArena_Destroy(arena);
- return PR_FAILURE;
- }
- nssTrust->object = *pkiob;
- nssTrust->certificate = c;
- nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
- nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
- nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
- nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE);
- nssTrust->stepUpApproved =
- (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
- if (c->object.cryptoContext != NULL) {
- /* The cert is in a context, set the trust there */
- NSSCryptoContext *cc = c->object.cryptoContext;
- nssrv = nssCryptoContext_ImportTrust(cc, nssTrust);
- if (nssrv != PR_SUCCESS) {
- goto done;
- }
- if (c->object.numInstances == 0) {
- /* The context is the only instance, finished */
- goto done;
- }
- }
- td = STAN_GetDefaultTrustDomain();
- tok = stan_GetTrustToken(c);
- moving_object = PR_FALSE;
- if (tok && PK11_IsReadOnly(tok->pk11slot)) {
- NSSRWLock_LockRead(td->tokensLock);
- tokens = nssList_CreateIterator(td->tokenList);
- if (!tokens) {
- nssrv = PR_FAILURE;
- NSSRWLock_UnlockRead(td->tokensLock);
- goto done;
- }
- for (tok = (NSSToken *)nssListIterator_Start(tokens);
- tok != (NSSToken *)NULL;
- tok = (NSSToken *)nssListIterator_Next(tokens))
- {
- if (!PK11_IsReadOnly(tok->pk11slot)) break;
- }
- nssListIterator_Finish(tokens);
- nssListIterator_Destroy(tokens);
- NSSRWLock_UnlockRead(td->tokensLock);
- moving_object = PR_TRUE;
- }
- if (tok) {
- if (moving_object) {
- /* this is kind of hacky. the softoken needs the cert
- * object in order to store trust. forcing it to be perm
- */
- NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
- NSSASCII7 *email = NULL;
-
- if (PK11_IsInternal(tok->pk11slot)) {
- email = c->email;
- }
- newInstance = nssToken_ImportCertificate(tok, NULL,
- NSSCertificateType_PKIX,
- &c->id,
- nickname,
- &c->encoding,
- &c->issuer,
- &c->subject,
- &c->serial,
- email,
- PR_TRUE);
- if (!newInstance) {
- nssrv = PR_FAILURE;
- goto done;
- }
- nssPKIObject_AddInstance(&c->object, newInstance);
- }
- newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
- &c->issuer, &c->serial,
- nssTrust->serverAuth,
- nssTrust->clientAuth,
- nssTrust->codeSigning,
- nssTrust->emailProtection,
- nssTrust->stepUpApproved, PR_TRUE);
- /* If the selected token can't handle trust, dump the trust on
- * the internal token */
- if (!newInstance && !PK11_IsInternal(tok->pk11slot)) {
- PK11SlotInfo *slot = PK11_GetInternalKeySlot();
- NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
- NSSASCII7 *email = c->email;
- tok = PK11Slot_GetNSSToken(slot);
- PK11_FreeSlot(slot);
-
- newInstance = nssToken_ImportCertificate(tok, NULL,
- NSSCertificateType_PKIX,
- &c->id,
- nickname,
- &c->encoding,
- &c->issuer,
- &c->subject,
- &c->serial,
- email,
- PR_TRUE);
- if (!newInstance) {
- nssrv = PR_FAILURE;
- goto done;
- }
- nssPKIObject_AddInstance(&c->object, newInstance);
- newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
- &c->issuer, &c->serial,
- nssTrust->serverAuth,
- nssTrust->clientAuth,
- nssTrust->codeSigning,
- nssTrust->emailProtection,
- nssTrust->stepUpApproved, PR_TRUE);
- }
- if (newInstance) {
- nssCryptokiObject_Destroy(newInstance);
- nssrv = PR_SUCCESS;
- } else {
- nssrv = PR_FAILURE;
- }
- } else {
- nssrv = PR_FAILURE;
- }
-done:
- (void)nssTrust_Destroy(nssTrust);
- return nssrv;
-}
-
-/* CERT_TraversePermCertsForSubject */
-NSS_IMPLEMENT PRStatus
-nssTrustDomain_TraverseCertificatesBySubject (
- NSSTrustDomain *td,
- NSSDER *subject,
- PRStatus (*callback)(NSSCertificate *c, void *arg),
- void *arg
-)
-{
- PRStatus nssrv = PR_SUCCESS;
- NSSArena *tmpArena;
- NSSCertificate **subjectCerts;
- NSSCertificate *c;
- PRIntn i;
- tmpArena = NSSArena_Create();
- subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
- 0, tmpArena);
- if (subjectCerts) {
- for (i=0, c = subjectCerts[i]; c; i++) {
- nssrv = callback(c, arg);
- if (nssrv != PR_SUCCESS) break;
- }
- }
- nssArena_Destroy(tmpArena);
- return nssrv;
-}
-
-/* CERT_TraversePermCertsForNickname */
-NSS_IMPLEMENT PRStatus
-nssTrustDomain_TraverseCertificatesByNickname (
- NSSTrustDomain *td,
- NSSUTF8 *nickname,
- PRStatus (*callback)(NSSCertificate *c, void *arg),
- void *arg
-)
-{
- PRStatus nssrv = PR_SUCCESS;
- NSSArena *tmpArena;
- NSSCertificate **nickCerts;
- NSSCertificate *c;
- PRIntn i;
- tmpArena = NSSArena_Create();
- nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
- 0, tmpArena);
- if (nickCerts) {
- for (i=0, c = nickCerts[i]; c; i++) {
- nssrv = callback(c, arg);
- if (nssrv != PR_SUCCESS) break;
- }
- }
- nssArena_Destroy(tmpArena);
- return nssrv;
-}
-
-static void cert_dump_iter(const void *k, void *v, void *a)
-{
- NSSCertificate *c = (NSSCertificate *)k;
- CERTCertificate *cert = STAN_GetCERTCertificate(c);
- printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName);
-}
-
-void
-nss_DumpCertificateCacheInfo()
-{
- NSSTrustDomain *td;
- NSSCryptoContext *cc;
- td = STAN_GetDefaultTrustDomain();
- cc = STAN_GetDefaultCryptoContext();
- printf("\n\nCertificates in the cache:\n");
- nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL);
- printf("\n\nCertificates in the temporary store:\n");
- if (cc->certStore) {
- nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL);
- }
-}
-