diff nss/lib/pki/certificate.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nss/lib/pki/certificate.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,1172 @@
+/* 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/. */
+
+#ifndef NSSPKI_H
+#include "nsspki.h"
+#endif /* NSSPKI_H */
+
+#ifndef PKIT_H
+#include "pkit.h"
+#endif /* PKIT_H */
+
+#ifndef PKIM_H
+#include "pkim.h"
+#endif /* PKIM_H */
+
+#ifndef DEV_H
+#include "dev.h"
+#endif /* DEV_H */
+
+#include "pkistore.h"
+
+#include "pki3hack.h"
+#include "pk11func.h"
+#include "hasht.h"
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+extern const NSSError NSS_ERROR_NOT_FOUND;
+
+/* Creates a certificate from a base object */
+NSS_IMPLEMENT NSSCertificate *
+nssCertificate_Create (
+  nssPKIObject *object
+)
+{
+    PRStatus status;
+    NSSCertificate *rvCert;
+    nssArenaMark * mark;
+    NSSArena *arena = object->arena;
+    PR_ASSERT(object->instances != NULL && object->numInstances > 0);
+    PR_ASSERT(object->lockType == nssPKIMonitor);
+    mark = nssArena_Mark(arena);
+    rvCert = nss_ZNEW(arena, NSSCertificate);
+    if (!rvCert) {
+	return (NSSCertificate *)NULL;
+    }
+    rvCert->object = *object;
+    /* XXX should choose instance based on some criteria */
+    status = nssCryptokiCertificate_GetAttributes(object->instances[0],
+                                                  NULL,  /* XXX sessionOpt */
+                                                  arena,
+                                                  &rvCert->type,
+                                                  &rvCert->id,
+                                                  &rvCert->encoding,
+                                                  &rvCert->issuer,
+                                                  &rvCert->serial,
+                                                  &rvCert->subject);
+    if (status != PR_SUCCESS ||
+	!rvCert->encoding.data ||
+	!rvCert->encoding.size ||
+	!rvCert->issuer.data ||
+	!rvCert->issuer.size ||
+	!rvCert->serial.data ||
+	!rvCert->serial.size) {
+	if (mark)
+	    nssArena_Release(arena, mark);
+	return (NSSCertificate *)NULL;
+    }
+    if (mark)
+	nssArena_Unmark(arena, mark);
+    return rvCert;
+}
+
+NSS_IMPLEMENT NSSCertificate *
+nssCertificate_AddRef (
+  NSSCertificate *c
+)
+{
+    if (c) {
+	nssPKIObject_AddRef(&c->object);
+    }
+    return c;
+}
+
+NSS_IMPLEMENT PRStatus
+nssCertificate_Destroy (
+  NSSCertificate *c
+)
+{
+    nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
+    nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
+
+    if (c) {
+	PRUint32 i;
+	nssDecodedCert *dc = c->decoding;
+	NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
+	NSSCryptoContext *cc = c->object.cryptoContext;
+
+	PR_ASSERT(c->object.refCount > 0);
+
+	/* --- LOCK storage --- */
+	if (cc) {
+	    nssCertificateStore_Lock(cc->certStore, &lockTrace);
+	} else {
+	    nssTrustDomain_LockCertCache(td);
+	}
+	if (PR_ATOMIC_DECREMENT(&c->object.refCount) == 0) {
+	    /* --- remove cert and UNLOCK storage --- */
+	    if (cc) {
+		nssCertificateStore_RemoveCertLOCKED(cc->certStore, c);
+		nssCertificateStore_Unlock(cc->certStore, &lockTrace,
+                                           &unlockTrace);
+	    } else {
+		nssTrustDomain_RemoveCertFromCacheLOCKED(td, c);
+		nssTrustDomain_UnlockCertCache(td);
+	    }
+	    /* free cert data */
+	    for (i=0; i<c->object.numInstances; i++) {
+		nssCryptokiObject_Destroy(c->object.instances[i]);
+	    }
+	    nssPKIObject_DestroyLock(&c->object);
+	    nssArena_Destroy(c->object.arena);
+	    nssDecodedCert_Destroy(dc);
+	} else {
+	    /* --- UNLOCK storage --- */
+	    if (cc) {
+		nssCertificateStore_Unlock(cc->certStore,
+					   &lockTrace,
+					   &unlockTrace);
+	    } else {
+		nssTrustDomain_UnlockCertCache(td);
+	    }
+	}
+    }
+    return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT PRStatus
+NSSCertificate_Destroy (
+  NSSCertificate *c
+)
+{
+    return nssCertificate_Destroy(c);
+}
+
+NSS_IMPLEMENT NSSDER *
+nssCertificate_GetEncoding (
+  NSSCertificate *c
+)
+{
+    if (c->encoding.size > 0 && c->encoding.data) {
+	return &c->encoding;
+    } else {
+	return (NSSDER *)NULL;
+    }
+}
+
+NSS_IMPLEMENT NSSDER *
+nssCertificate_GetIssuer (
+  NSSCertificate *c
+)
+{
+    if (c->issuer.size > 0 && c->issuer.data) {
+	return &c->issuer;
+    } else {
+	return (NSSDER *)NULL;
+    }
+}
+
+NSS_IMPLEMENT NSSDER *
+nssCertificate_GetSerialNumber (
+  NSSCertificate *c
+)
+{
+    if (c->serial.size > 0 && c->serial.data) {
+	return &c->serial;
+    } else {
+	return (NSSDER *)NULL;
+    }
+}
+
+NSS_IMPLEMENT NSSDER *
+nssCertificate_GetSubject (
+  NSSCertificate *c
+)
+{
+    if (c->subject.size > 0 && c->subject.data) {
+	return &c->subject;
+    } else {
+	return (NSSDER *)NULL;
+    }
+}
+
+/* Returns a copy, Caller must free using nss_ZFreeIf */
+NSS_IMPLEMENT NSSUTF8 *
+nssCertificate_GetNickname (
+  NSSCertificate *c,
+  NSSToken *tokenOpt
+)
+{
+    return nssPKIObject_GetNicknameForToken(&c->object, tokenOpt);
+}
+
+NSS_IMPLEMENT NSSASCII7 *
+nssCertificate_GetEmailAddress (
+  NSSCertificate *c
+)
+{
+    return c->email;
+}
+
+NSS_IMPLEMENT PRStatus
+NSSCertificate_DeleteStoredObject (
+  NSSCertificate *c,
+  NSSCallback *uhh
+)
+{
+    return nssPKIObject_DeleteStoredObject(&c->object, uhh, PR_TRUE);
+}
+
+NSS_IMPLEMENT PRStatus
+NSSCertificate_Validate (
+  NSSCertificate *c,
+  NSSTime *timeOpt, /* NULL for "now" */
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt /* NULL for none */
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return PR_FAILURE;
+}
+
+NSS_IMPLEMENT void ** /* void *[] */
+NSSCertificate_ValidateCompletely (
+  NSSCertificate *c,
+  NSSTime *timeOpt, /* NULL for "now" */
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt, /* NULL for none */
+  void **rvOpt, /* NULL for allocate */
+  PRUint32 rvLimit, /* zero for no limit */
+  NSSArena *arenaOpt /* NULL for heap */
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT PRStatus
+NSSCertificate_ValidateAndDiscoverUsagesAndPolicies (
+  NSSCertificate *c,
+  NSSTime **notBeforeOutOpt,
+  NSSTime **notAfterOutOpt,
+  void *allowedUsages,
+  void *disallowedUsages,
+  void *allowedPolicies,
+  void *disallowedPolicies,
+  /* more args.. work on this fgmr */
+  NSSArena *arenaOpt
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return PR_FAILURE;
+}
+
+NSS_IMPLEMENT NSSDER *
+NSSCertificate_Encode (
+  NSSCertificate *c,
+  NSSDER *rvOpt,
+  NSSArena *arenaOpt
+)
+{
+    /* Item, DER, BER are all typedefs now... */
+    return nssItem_Duplicate((NSSItem *)&c->encoding, arenaOpt, rvOpt);
+}
+
+NSS_IMPLEMENT nssDecodedCert *
+nssCertificate_GetDecoding (
+  NSSCertificate *c
+)
+{
+    nssDecodedCert* deco = NULL;
+    if (c->type == NSSCertificateType_PKIX) {
+        (void)STAN_GetCERTCertificate(c);
+    }
+    nssPKIObject_Lock(&c->object);
+    if (!c->decoding) {
+	deco = nssDecodedCert_Create(NULL, &c->encoding, c->type);
+    	PORT_Assert(!c->decoding); 
+        c->decoding = deco;
+    } else {
+        deco = c->decoding;
+    }
+    nssPKIObject_Unlock(&c->object);
+    return deco;
+}
+
+static NSSCertificate **
+filter_subject_certs_for_id (
+  NSSCertificate **subjectCerts, 
+  void *id
+)
+{
+    NSSCertificate **si;
+    nssDecodedCert *dcp;
+    int nextOpenSlot = 0;
+    int i;
+    nssCertIDMatch matchLevel = nssCertIDMatch_Unknown;
+    nssCertIDMatch match;
+
+    /* walk the subject certs */
+    for (si = subjectCerts; *si; si++) {
+	dcp = nssCertificate_GetDecoding(*si);
+	if (!dcp) {
+	    NSSCertificate_Destroy(*si);
+	    continue;
+	}
+	match = dcp->matchIdentifier(dcp, id);
+	switch (match) {
+	case nssCertIDMatch_Yes:
+	    if (matchLevel == nssCertIDMatch_Unknown) {
+		/* we have non-definitive matches, forget them */
+		for (i = 0; i < nextOpenSlot; i++) {
+		    NSSCertificate_Destroy(subjectCerts[i]);
+		    subjectCerts[i] = NULL;
+		}
+		nextOpenSlot = 0;
+		/* only keep definitive matches from now on */
+		matchLevel = nssCertIDMatch_Yes;
+	    }
+	    /* keep the cert */
+	    subjectCerts[nextOpenSlot++] = *si;
+	    break;
+	case nssCertIDMatch_Unknown:
+	    if (matchLevel == nssCertIDMatch_Unknown) {
+		/* only have non-definitive matches so far, keep it */
+		subjectCerts[nextOpenSlot++] = *si;
+		break;
+	    }
+	    /* else fall through, we have a definitive match already */
+	case nssCertIDMatch_No:
+	default:
+	    NSSCertificate_Destroy(*si);
+	    *si = NULL;
+	}
+    }
+    subjectCerts[nextOpenSlot] = NULL;
+    return subjectCerts;
+}
+
+static NSSCertificate **
+filter_certs_for_valid_issuers (
+  NSSCertificate **certs
+)
+{
+    NSSCertificate **cp;
+    nssDecodedCert *dcp;
+    int nextOpenSlot = 0;
+
+    for (cp = certs; *cp; cp++) {
+	dcp = nssCertificate_GetDecoding(*cp);
+	if (dcp && dcp->isValidIssuer(dcp)) {
+	    certs[nextOpenSlot++] = *cp;
+	} else {
+	    NSSCertificate_Destroy(*cp);
+	}
+    }
+    certs[nextOpenSlot] = NULL;
+    return certs;
+}
+
+static NSSCertificate *
+find_cert_issuer (
+  NSSCertificate *c,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSTrustDomain *td,
+  NSSCryptoContext *cc
+)
+{
+    NSSArena *arena;
+    NSSCertificate **certs = NULL;
+    NSSCertificate **ccIssuers = NULL;
+    NSSCertificate **tdIssuers = NULL;
+    NSSCertificate *issuer = NULL;
+
+    if (!cc)
+	cc = c->object.cryptoContext;
+    if (!td)
+	td = NSSCertificate_GetTrustDomain(c);
+    arena = nssArena_Create();
+    if (!arena) {
+	return (NSSCertificate *)NULL;
+    }
+    if (cc) {
+	ccIssuers = nssCryptoContext_FindCertificatesBySubject(cc,
+	                                                       &c->issuer,
+	                                                       NULL,
+	                                                       0,
+	                                                       arena);
+    }
+    if (td)
+	tdIssuers = nssTrustDomain_FindCertificatesBySubject(td,
+                                                         &c->issuer,
+                                                         NULL,
+                                                         0,
+                                                         arena);
+    certs = nssCertificateArray_Join(ccIssuers, tdIssuers);
+    if (certs) {
+	nssDecodedCert *dc = NULL;
+	void *issuerID = NULL;
+	dc = nssCertificate_GetDecoding(c);
+	if (dc) {
+	    issuerID = dc->getIssuerIdentifier(dc);
+	}
+	/* XXX review based on CERT_FindCertIssuer
+	 * this function is not using the authCertIssuer field as a fallback
+	 * if authority key id does not exist
+	 */
+	if (issuerID) {
+	    certs = filter_subject_certs_for_id(certs, issuerID);
+	}
+	certs = filter_certs_for_valid_issuers(certs);
+	issuer = nssCertificateArray_FindBestCertificate(certs,
+	                                                 timeOpt,
+	                                                 usage,
+	                                                 policiesOpt);
+	nssCertificateArray_Destroy(certs);
+    }
+    nssArena_Destroy(arena);
+    return issuer;
+}
+
+/* This function returns the built chain, as far as it gets,
+** even if/when it fails to find an issuer, and returns PR_FAILURE
+*/
+NSS_IMPLEMENT NSSCertificate **
+nssCertificate_BuildChain (
+  NSSCertificate *c,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCertificate **rvOpt,
+  PRUint32 rvLimit,
+  NSSArena *arenaOpt,
+  PRStatus *statusOpt,
+  NSSTrustDomain *td,
+  NSSCryptoContext *cc 
+)
+{
+    NSSCertificate **rvChain = NULL;
+    NSSUsage issuerUsage = *usage;
+    nssPKIObjectCollection *collection = NULL;
+    PRUint32  rvCount = 0;
+    PRStatus  st;
+    PRStatus  ret = PR_SUCCESS;
+
+    if (!c || !cc ||
+        (!td && (td = NSSCertificate_GetTrustDomain(c)) == NULL)) {
+	goto loser;
+    }
+    /* bump the usage up to CA level */
+    issuerUsage.nss3lookingForCA = PR_TRUE;
+    collection = nssCertificateCollection_Create(td, NULL);
+    if (!collection)
+	goto loser;
+    st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c);
+    if (st != PR_SUCCESS)
+    	goto loser;
+    for (rvCount = 1; (!rvLimit || rvCount < rvLimit); ++rvCount) {
+	CERTCertificate *cCert = STAN_GetCERTCertificate(c);
+	if (cCert->isRoot) {
+	    /* not including the issuer of the self-signed cert, which is,
+	     * of course, itself
+	     */
+	    break;
+	}
+	c = find_cert_issuer(c, timeOpt, &issuerUsage, policiesOpt, td, cc);
+	if (!c) {
+	    ret = PR_FAILURE;
+	    break;
+	}
+	st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c);
+	nssCertificate_Destroy(c); /* collection has it */
+	if (st != PR_SUCCESS)
+	    goto loser;
+    }
+    rvChain = nssPKIObjectCollection_GetCertificates(collection, 
+                                                     rvOpt, 
+                                                     rvLimit, 
+                                                     arenaOpt);
+    if (rvChain) {
+	nssPKIObjectCollection_Destroy(collection);
+	if (statusOpt) 
+	    *statusOpt = ret;
+	if (ret != PR_SUCCESS)
+	    nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND);
+	return rvChain;
+    }
+
+loser:
+    if (collection)
+	nssPKIObjectCollection_Destroy(collection);
+    if (statusOpt) 
+	*statusOpt = PR_FAILURE;
+    nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND);
+    return rvChain;
+}
+
+NSS_IMPLEMENT NSSCertificate **
+NSSCertificate_BuildChain (
+  NSSCertificate *c,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCertificate **rvOpt,
+  PRUint32 rvLimit, /* zero for no limit */
+  NSSArena *arenaOpt,
+  PRStatus *statusOpt,
+  NSSTrustDomain *td,
+  NSSCryptoContext *cc 
+)
+{
+    return nssCertificate_BuildChain(c, timeOpt, usage, policiesOpt,
+                                     rvOpt, rvLimit, arenaOpt, statusOpt,
+				     td, cc);
+}
+
+NSS_IMPLEMENT NSSCryptoContext *
+nssCertificate_GetCryptoContext (
+  NSSCertificate *c
+)
+{
+    return c->object.cryptoContext;
+}
+
+NSS_IMPLEMENT NSSTrustDomain *
+nssCertificate_GetTrustDomain (
+  NSSCertificate *c
+)
+{
+    return c->object.trustDomain;
+}
+
+NSS_IMPLEMENT NSSTrustDomain *
+NSSCertificate_GetTrustDomain (
+  NSSCertificate *c
+)
+{
+    return nssCertificate_GetTrustDomain(c);
+}
+
+NSS_IMPLEMENT NSSToken *
+NSSCertificate_GetToken (
+  NSSCertificate *c,
+  PRStatus *statusOpt
+)
+{
+    return (NSSToken *)NULL;
+}
+
+NSS_IMPLEMENT NSSSlot *
+NSSCertificate_GetSlot (
+  NSSCertificate *c,
+  PRStatus *statusOpt
+)
+{
+    return (NSSSlot *)NULL;
+}
+
+NSS_IMPLEMENT NSSModule *
+NSSCertificate_GetModule (
+  NSSCertificate *c,
+  PRStatus *statusOpt
+)
+{
+    return (NSSModule *)NULL;
+}
+
+NSS_IMPLEMENT NSSItem *
+NSSCertificate_Encrypt (
+  NSSCertificate *c,
+  NSSAlgorithmAndParameters *apOpt,
+  NSSItem *data,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCallback *uhh,
+  NSSItem *rvOpt,
+  NSSArena *arenaOpt
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT PRStatus
+NSSCertificate_Verify (
+  NSSCertificate *c,
+  NSSAlgorithmAndParameters *apOpt,
+  NSSItem *data,
+  NSSItem *signature,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCallback *uhh
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return PR_FAILURE;
+}
+
+NSS_IMPLEMENT NSSItem *
+NSSCertificate_VerifyRecover (
+  NSSCertificate *c,
+  NSSAlgorithmAndParameters *apOpt,
+  NSSItem *signature,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCallback *uhh,
+  NSSItem *rvOpt,
+  NSSArena *arenaOpt
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT NSSItem *
+NSSCertificate_WrapSymmetricKey (
+  NSSCertificate *c,
+  NSSAlgorithmAndParameters *apOpt,
+  NSSSymmetricKey *keyToWrap,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCallback *uhh,
+  NSSItem *rvOpt,
+  NSSArena *arenaOpt
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT NSSCryptoContext *
+NSSCertificate_CreateCryptoContext (
+  NSSCertificate *c,
+  NSSAlgorithmAndParameters *apOpt,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCallback *uhh  
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT NSSPublicKey *
+NSSCertificate_GetPublicKey (
+  NSSCertificate *c
+)
+{
+#if 0
+    CK_ATTRIBUTE pubktemplate[] = {
+	{ CKA_CLASS,   NULL, 0 },
+	{ CKA_ID,      NULL, 0 },
+	{ CKA_SUBJECT, NULL, 0 }
+    };
+    PRStatus nssrv;
+    CK_ULONG count = sizeof(pubktemplate) / sizeof(pubktemplate[0]);
+    NSS_CK_SET_ATTRIBUTE_ITEM(pubktemplate, 0, &g_ck_class_pubkey);
+    if (c->id.size > 0) {
+	/* CKA_ID */
+	NSS_CK_ITEM_TO_ATTRIBUTE(&c->id, &pubktemplate[1]);
+    } else {
+	/* failure, yes? */
+	return (NSSPublicKey *)NULL;
+    }
+    if (c->subject.size > 0) {
+	/* CKA_SUBJECT */
+	NSS_CK_ITEM_TO_ATTRIBUTE(&c->subject, &pubktemplate[2]);
+    } else {
+	/* failure, yes? */
+	return (NSSPublicKey *)NULL;
+    }
+    /* Try the cert's token first */
+    if (c->token) {
+	nssrv = nssToken_FindObjectByTemplate(c->token, pubktemplate, count);
+    }
+#endif
+    /* Try all other key tokens */
+    return (NSSPublicKey *)NULL;
+}
+
+NSS_IMPLEMENT NSSPrivateKey *
+NSSCertificate_FindPrivateKey (
+  NSSCertificate *c,
+  NSSCallback *uhh
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT PRBool
+NSSCertificate_IsPrivateKeyAvailable (
+  NSSCertificate *c,
+  NSSCallback *uhh,
+  PRStatus *statusOpt
+)
+{
+    PRBool isUser = PR_FALSE;
+    nssCryptokiObject **ip;
+    nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
+    if (!instances) {
+	return PR_FALSE;
+    }
+    for (ip = instances; *ip; ip++) {
+	nssCryptokiObject *instance = *ip;
+	if (nssToken_IsPrivateKeyAvailable(instance->token, c, instance)) {
+	    isUser = PR_TRUE;
+	}
+    }
+    nssCryptokiObjectArray_Destroy(instances);
+    return isUser;
+}
+
+/* sort the subject cert list from newest to oldest */
+PRIntn
+nssCertificate_SubjectListSort (
+  void *v1,
+  void *v2
+)
+{
+    NSSCertificate *c1 = (NSSCertificate *)v1;
+    NSSCertificate *c2 = (NSSCertificate *)v2;
+    nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1);
+    nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2);
+    if (!dc1) {
+	return dc2 ? 1 : 0;
+    } else if (!dc2) {
+	return -1;
+    } else {
+	return dc1->isNewerThan(dc1, dc2) ? -1 : 1;
+    }
+}
+
+NSS_IMPLEMENT PRBool
+NSSUserCertificate_IsStillPresent (
+  NSSUserCertificate *uc,
+  PRStatus *statusOpt
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return PR_FALSE;
+}
+
+NSS_IMPLEMENT NSSItem *
+NSSUserCertificate_Decrypt (
+  NSSUserCertificate *uc,
+  NSSAlgorithmAndParameters *apOpt,
+  NSSItem *data,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCallback *uhh,
+  NSSItem *rvOpt,
+  NSSArena *arenaOpt
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT NSSItem *
+NSSUserCertificate_Sign (
+  NSSUserCertificate *uc,
+  NSSAlgorithmAndParameters *apOpt,
+  NSSItem *data,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCallback *uhh,
+  NSSItem *rvOpt,
+  NSSArena *arenaOpt
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT NSSItem *
+NSSUserCertificate_SignRecover (
+  NSSUserCertificate *uc,
+  NSSAlgorithmAndParameters *apOpt,
+  NSSItem *data,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCallback *uhh,
+  NSSItem *rvOpt,
+  NSSArena *arenaOpt
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT NSSSymmetricKey *
+NSSUserCertificate_UnwrapSymmetricKey (
+  NSSUserCertificate *uc,
+  NSSAlgorithmAndParameters *apOpt,
+  NSSItem *wrappedKey,
+  NSSTime *timeOpt,
+  NSSUsage *usage,
+  NSSPolicies *policiesOpt,
+  NSSCallback *uhh,
+  NSSItem *rvOpt,
+  NSSArena *arenaOpt
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT NSSSymmetricKey *
+NSSUserCertificate_DeriveSymmetricKey (
+  NSSUserCertificate *uc, /* provides private key */
+  NSSCertificate *c, /* provides public key */
+  NSSAlgorithmAndParameters *apOpt,
+  NSSOID *target,
+  PRUint32 keySizeOpt, /* zero for best allowed */
+  NSSOperations operations,
+  NSSCallback *uhh
+)
+{
+    nss_SetError(NSS_ERROR_NOT_FOUND);
+    return NULL;
+}
+
+NSS_IMPLEMENT nssSMIMEProfile *
+nssSMIMEProfile_Create (
+  NSSCertificate *cert,
+  NSSItem *profileTime,
+  NSSItem *profileData
+)
+{
+    NSSArena *arena;
+    nssSMIMEProfile *rvProfile;
+    nssPKIObject *object;
+    NSSTrustDomain *td = nssCertificate_GetTrustDomain(cert);
+    NSSCryptoContext *cc = nssCertificate_GetCryptoContext(cert);
+    arena = nssArena_Create();
+    if (!arena) {
+	return NULL;
+    }
+    object = nssPKIObject_Create(arena, NULL, td, cc, nssPKILock);
+    if (!object) {
+	goto loser;
+    }
+    rvProfile = nss_ZNEW(arena, nssSMIMEProfile);
+    if (!rvProfile) {
+	goto loser;
+    }
+    rvProfile->object = *object;
+    rvProfile->certificate = cert;
+    rvProfile->email = nssUTF8_Duplicate(cert->email, arena);
+    rvProfile->subject = nssItem_Duplicate(&cert->subject, arena, NULL);
+    if (profileTime) {
+	rvProfile->profileTime = nssItem_Duplicate(profileTime, arena, NULL);
+    }
+    if (profileData) {
+	rvProfile->profileData = nssItem_Duplicate(profileData, arena, NULL);
+    }
+    return rvProfile;
+loser:
+    if (object) nssPKIObject_Destroy(object);
+    else if (arena)  nssArena_Destroy(arena);
+    return (nssSMIMEProfile *)NULL;
+}
+
+/* execute a callback function on all members of a cert list */
+NSS_EXTERN PRStatus
+nssCertificateList_DoCallback (
+  nssList *certList, 
+  PRStatus (* callback)(NSSCertificate *c, void *arg),
+  void *arg
+)
+{
+    nssListIterator *certs;
+    NSSCertificate *cert;
+    PRStatus nssrv;
+    certs = nssList_CreateIterator(certList);
+    if (!certs) {
+        return PR_FAILURE;
+    }
+    for (cert  = (NSSCertificate *)nssListIterator_Start(certs);
+         cert != (NSSCertificate *)NULL;
+         cert  = (NSSCertificate *)nssListIterator_Next(certs))
+    {
+	nssrv = (*callback)(cert, arg);
+    }
+    nssListIterator_Finish(certs);
+    nssListIterator_Destroy(certs);
+    return PR_SUCCESS;
+}
+
+static PRStatus add_ref_callback(NSSCertificate *c, void *a)
+{
+    nssCertificate_AddRef(c);
+    return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT void
+nssCertificateList_AddReferences (
+  nssList *certList
+)
+{
+    (void)nssCertificateList_DoCallback(certList, add_ref_callback, NULL);
+}
+
+
+/*
+ * Is this trust record safe to apply to all certs of the same issuer/SN 
+ * independent of the cert matching the hash. This is only true is the trust 
+ * is unknown or distrusted. In general this feature is only useful to 
+ * explicitly distrusting certs. It is not safe to use to trust certs, so 
+ * only allow unknown and untrusted trust types.
+ */
+PRBool
+nssTrust_IsSafeToIgnoreCertHash(nssTrustLevel serverAuth, 
+		nssTrustLevel clientAuth, nssTrustLevel codeSigning, 
+		nssTrustLevel email, PRBool stepup)
+{
+    /* step up is a trust type, if it's on, we must have a hash for the cert */
+    if (stepup) {
+	return PR_FALSE;
+    }
+    if ((serverAuth != nssTrustLevel_Unknown) && 
+	(serverAuth != nssTrustLevel_NotTrusted)) {
+	return PR_FALSE;
+    }
+    if ((clientAuth != nssTrustLevel_Unknown) && 
+	(clientAuth != nssTrustLevel_NotTrusted)) {
+	return PR_FALSE;
+    }
+    if ((codeSigning != nssTrustLevel_Unknown) && 
+	(codeSigning != nssTrustLevel_NotTrusted)) {
+	return PR_FALSE;
+    }
+    if ((email != nssTrustLevel_Unknown) && 
+	(email != nssTrustLevel_NotTrusted)) {
+	return PR_FALSE;
+    }
+    /* record only has Unknown and Untrusted entries, ok to accept without a 
+     * hash */
+    return PR_TRUE;
+}
+
+NSS_IMPLEMENT NSSTrust *
+nssTrust_Create (
+  nssPKIObject *object,
+  NSSItem *certData
+)
+{
+    PRStatus status;
+    PRUint32 i;
+    PRUint32 lastTrustOrder, myTrustOrder;
+    unsigned char sha1_hashcmp[SHA1_LENGTH];
+    unsigned char sha1_hashin[SHA1_LENGTH];
+    NSSItem sha1_hash;
+    NSSTrust *rvt;
+    nssCryptokiObject *instance;
+    nssTrustLevel serverAuth, clientAuth, codeSigning, emailProtection;
+    SECStatus rv; /* Should be stan flavor */
+    PRBool stepUp;
+
+    lastTrustOrder = 1<<16; /* just make it big */
+    PR_ASSERT(object->instances != NULL && object->numInstances > 0);
+    rvt = nss_ZNEW(object->arena, NSSTrust);
+    if (!rvt) {
+	return (NSSTrust *)NULL;
+    }
+    rvt->object = *object;
+
+    /* should be stan flavor of Hashbuf */
+    rv = PK11_HashBuf(SEC_OID_SHA1,sha1_hashcmp,certData->data,certData->size);
+    if (rv != SECSuccess) {
+	return (NSSTrust *)NULL;
+    }
+    sha1_hash.data = sha1_hashin;
+    sha1_hash.size = sizeof (sha1_hashin);
+    /* trust has to peek into the base object members */
+    nssPKIObject_Lock(object);
+    for (i=0; i<object->numInstances; i++) {
+	instance = object->instances[i];
+	myTrustOrder = nssToken_GetTrustOrder(instance->token);
+	status = nssCryptokiTrust_GetAttributes(instance, NULL,
+						&sha1_hash,
+	                                        &serverAuth,
+	                                        &clientAuth,
+	                                        &codeSigning,
+	                                        &emailProtection,
+	                                        &stepUp);
+	if (status != PR_SUCCESS) {
+	    nssPKIObject_Unlock(object);
+	    return (NSSTrust *)NULL;
+	}
+	/* if no hash is specified, then trust applies to all certs with
+	 * this issuer/SN. NOTE: This is only true for entries that
+	 * have distrust and unknown record */
+	if (!(
+            /* we continue if there is no hash, and the trust type is
+	     * safe to accept without a hash ... or ... */
+	     ((sha1_hash.size == 0)  && 
+		nssTrust_IsSafeToIgnoreCertHash(serverAuth,clientAuth,
+		codeSigning, emailProtection,stepUp)) 
+	   ||
+            /* we have a hash of the correct size, and it matches */
+            ((sha1_hash.size == SHA1_LENGTH) && (PORT_Memcmp(sha1_hashin,
+	        sha1_hashcmp,SHA1_LENGTH) == 0))   )) {
+	    nssPKIObject_Unlock(object);
+	    return (NSSTrust *)NULL;
+	}
+	if (rvt->serverAuth == nssTrustLevel_Unknown ||
+	    myTrustOrder < lastTrustOrder) 
+	{
+	    rvt->serverAuth = serverAuth;
+	}
+	if (rvt->clientAuth == nssTrustLevel_Unknown ||
+	    myTrustOrder < lastTrustOrder) 
+	{
+	    rvt->clientAuth = clientAuth;
+	}
+	if (rvt->emailProtection == nssTrustLevel_Unknown ||
+	    myTrustOrder < lastTrustOrder) 
+	{
+	    rvt->emailProtection = emailProtection;
+	}
+	if (rvt->codeSigning == nssTrustLevel_Unknown ||
+	    myTrustOrder < lastTrustOrder) 
+	{
+	    rvt->codeSigning = codeSigning;
+	}
+	rvt->stepUpApproved = stepUp;
+	lastTrustOrder = myTrustOrder;
+    }
+    nssPKIObject_Unlock(object);
+    return rvt;
+}
+
+NSS_IMPLEMENT NSSTrust *
+nssTrust_AddRef (
+  NSSTrust *trust
+)
+{
+    if (trust) {
+	nssPKIObject_AddRef(&trust->object);
+    }
+    return trust;
+}
+
+NSS_IMPLEMENT PRStatus
+nssTrust_Destroy (
+  NSSTrust *trust
+)
+{
+    if (trust) {
+	(void)nssPKIObject_Destroy(&trust->object);
+    }
+    return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT nssSMIMEProfile *
+nssSMIMEProfile_AddRef (
+  nssSMIMEProfile *profile
+)
+{
+    if (profile) {
+	nssPKIObject_AddRef(&profile->object);
+    }
+    return profile;
+}
+
+NSS_IMPLEMENT PRStatus
+nssSMIMEProfile_Destroy (
+  nssSMIMEProfile *profile
+)
+{
+    if (profile) {
+	(void)nssPKIObject_Destroy(&profile->object);
+    }
+    return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT NSSCRL *
+nssCRL_Create (
+  nssPKIObject *object
+)
+{
+    PRStatus status;
+    NSSCRL *rvCRL;
+    NSSArena *arena = object->arena;
+    PR_ASSERT(object->instances != NULL && object->numInstances > 0);
+    rvCRL = nss_ZNEW(arena, NSSCRL);
+    if (!rvCRL) {
+	return (NSSCRL *)NULL;
+    }
+    rvCRL->object = *object;
+    /* XXX should choose instance based on some criteria */
+    status = nssCryptokiCRL_GetAttributes(object->instances[0],
+                                          NULL,  /* XXX sessionOpt */
+                                          arena,
+                                          &rvCRL->encoding,
+                                          NULL, /* subject */
+                                          NULL, /* class */
+                                          &rvCRL->url,
+                                          &rvCRL->isKRL);
+    if (status != PR_SUCCESS) {
+	return (NSSCRL *)NULL;
+    }
+    return rvCRL;
+}
+
+NSS_IMPLEMENT NSSCRL *
+nssCRL_AddRef (
+  NSSCRL *crl
+)
+{
+    if (crl) {
+	nssPKIObject_AddRef(&crl->object);
+    }
+    return crl;
+}
+
+NSS_IMPLEMENT PRStatus
+nssCRL_Destroy (
+  NSSCRL *crl
+)
+{
+    if (crl) {
+	(void)nssPKIObject_Destroy(&crl->object);
+    }
+    return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT PRStatus
+nssCRL_DeleteStoredObject (
+  NSSCRL *crl,
+  NSSCallback *uhh
+)
+{
+    return nssPKIObject_DeleteStoredObject(&crl->object, uhh, PR_TRUE);
+}
+
+NSS_IMPLEMENT NSSDER *
+nssCRL_GetEncoding (
+  NSSCRL *crl
+)
+{
+    if (crl && crl->encoding.data != NULL && crl->encoding.size > 0) {
+	return &crl->encoding;
+    } else {
+	return (NSSDER *)NULL;
+    }
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)