summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix_pl_nss/pki
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/libpkix/pkix_pl_nss/pki')
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile47
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp41
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn50
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp39
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c407
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h47
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c3734
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h107
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c371
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h50
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c386
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h49
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c365
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h52
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c1068
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h48
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c151
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h53
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c880
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h46
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c466
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h55
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c873
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h49
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c874
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h49
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c1279
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h68
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c251
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h53
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c441
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h61
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c1069
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h106
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c489
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h38
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c667
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h74
38 files changed, 14953 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile
new file mode 100644
index 0000000000..2b4b1574ab
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp b/security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp
new file mode 100644
index 0000000000..616f94fd46
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp
@@ -0,0 +1,41 @@
+# 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/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_pl_nss_pki_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_pl_basicconstraints.h',
+ 'pkix_pl_cert.h',
+ 'pkix_pl_certpolicyinfo.h',
+ 'pkix_pl_certpolicymap.h',
+ 'pkix_pl_certpolicyqualifier.h',
+ 'pkix_pl_crl.h',
+ 'pkix_pl_crldp.h',
+ 'pkix_pl_crlentry.h',
+ 'pkix_pl_date.h',
+ 'pkix_pl_generalname.h',
+ 'pkix_pl_infoaccess.h',
+ 'pkix_pl_nameconstraints.h',
+ 'pkix_pl_ocspcertid.h',
+ 'pkix_pl_ocsprequest.h',
+ 'pkix_pl_ocspresponse.h',
+ 'pkix_pl_publickey.h',
+ 'pkix_pl_x500name.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn
new file mode 100644
index 0000000000..aba1367e56
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn
@@ -0,0 +1,50 @@
+#
+# 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/.
+CORE_DEPTH = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_pl_basicconstraints.h \
+ pkix_pl_cert.h \
+ pkix_pl_certpolicyinfo.h \
+ pkix_pl_certpolicymap.h \
+ pkix_pl_certpolicyqualifier.h \
+ pkix_pl_crl.h \
+ pkix_pl_crldp.h \
+ pkix_pl_crlentry.h \
+ pkix_pl_date.h \
+ pkix_pl_generalname.h \
+ pkix_pl_infoaccess.h \
+ pkix_pl_nameconstraints.h \
+ pkix_pl_ocsprequest.h \
+ pkix_pl_ocspresponse.h \
+ pkix_pl_publickey.h \
+ pkix_pl_x500name.h \
+ pkix_pl_ocspcertid.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_pl_basicconstraints.c \
+ pkix_pl_cert.c \
+ pkix_pl_certpolicyinfo.c \
+ pkix_pl_certpolicymap.c \
+ pkix_pl_certpolicyqualifier.c \
+ pkix_pl_crl.c \
+ pkix_pl_crldp.c \
+ pkix_pl_crlentry.c \
+ pkix_pl_date.c \
+ pkix_pl_generalname.c \
+ pkix_pl_infoaccess.c \
+ pkix_pl_nameconstraints.c \
+ pkix_pl_ocsprequest.c \
+ pkix_pl_ocspresponse.c \
+ pkix_pl_publickey.c \
+ pkix_pl_x500name.c \
+ pkix_pl_ocspcertid.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixpki
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp b/security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp
new file mode 100644
index 0000000000..af7730c0bf
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp
@@ -0,0 +1,39 @@
+# 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/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixpki',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_pl_basicconstraints.c',
+ 'pkix_pl_cert.c',
+ 'pkix_pl_certpolicyinfo.c',
+ 'pkix_pl_certpolicymap.c',
+ 'pkix_pl_certpolicyqualifier.c',
+ 'pkix_pl_crl.c',
+ 'pkix_pl_crldp.c',
+ 'pkix_pl_crlentry.c',
+ 'pkix_pl_date.c',
+ 'pkix_pl_generalname.c',
+ 'pkix_pl_infoaccess.c',
+ 'pkix_pl_nameconstraints.c',
+ 'pkix_pl_ocspcertid.c',
+ 'pkix_pl_ocsprequest.c',
+ 'pkix_pl_ocspresponse.c',
+ 'pkix_pl_publickey.c',
+ 'pkix_pl_x500name.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c
new file mode 100644
index 0000000000..81615da37a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c
@@ -0,0 +1,407 @@
+/* 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/. */
+/*
+ * pkix_pl_basicconstraints.c
+ *
+ * BasicConstraints Object Functions
+ *
+ */
+
+#include "pkix_pl_basicconstraints.h"
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CertBasicConstraints object whose CA Flag has the value
+ * given by the Boolean value of "isCA" and whose path length field has the
+ * value given by the "pathLen" argument and stores it at "pObject".
+ *
+ * PARAMETERS
+ * "isCA"
+ * Boolean value with the desired value of CA Flag.
+ * "pathLen"
+ * a PKIX_Int32 with the desired value of path length
+ * "pObject"
+ * Address of object pointer's destination. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertBasicConstraints Error if the function fails
+ * in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertBasicConstraints_Create(
+ PKIX_Boolean isCA,
+ PKIX_Int32 pathLen,
+ PKIX_PL_CertBasicConstraints **pObject,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basic = NULL;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_Create");
+ PKIX_NULLCHECK_ONE(pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTBASICCONSTRAINTS_TYPE,
+ sizeof (PKIX_PL_CertBasicConstraints),
+ (PKIX_PL_Object **)&basic,
+ plContext),
+ PKIX_COULDNOTCREATECERTBASICCONSTRAINTSOBJECT);
+
+ basic->isCA = isCA;
+
+ /* pathLen has meaning only for CAs, but it's not worth checking */
+ basic->pathLen = pathLen;
+
+ *pObject = basic;
+
+cleanup:
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertBasicConstraints_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *certB = NULL;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTBASICCONSTRAINTS);
+
+ certB = (PKIX_PL_CertBasicConstraints*)object;
+
+ certB->isCA = PKIX_FALSE;
+ certB->pathLen = 0;
+
+cleanup:
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertBasicConstraints_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *certBasicConstraintsString = NULL;
+ PKIX_PL_CertBasicConstraints *certB = NULL;
+ PKIX_Boolean isCA = PKIX_FALSE;
+ PKIX_Int32 pathLen = 0;
+ PKIX_PL_String *outString = NULL;
+ char *fmtString = NULL;
+ PKIX_Boolean pathlenArg = PKIX_FALSE;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
+ PKIX_FIRSTARGUMENTNOTCERTBASICCONSTRAINTSOBJECT);
+
+ certB = (PKIX_PL_CertBasicConstraints *)object;
+
+ /*
+ * if CA == TRUE
+ * if pathLen == CERT_UNLIMITED_PATH_CONSTRAINT
+ * print "CA(-1)"
+ * else print "CA(nnn)"
+ * if CA == FALSE, print "~CA"
+ */
+
+ isCA = certB->isCA;
+
+ if (isCA) {
+ pathLen = certB->pathLen;
+
+ if (pathLen == CERT_UNLIMITED_PATH_CONSTRAINT) {
+ /* print "CA(-1)" */
+ fmtString = "CA(-1)";
+ pathlenArg = PKIX_FALSE;
+ } else {
+ /* print "CA(pathLen)" */
+ fmtString = "CA(%d)";
+ pathlenArg = PKIX_TRUE;
+ }
+ } else {
+ /* print "~CA" */
+ fmtString = "~CA";
+ pathlenArg = PKIX_FALSE;
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ fmtString,
+ 0,
+ &certBasicConstraintsString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ if (pathlenArg) {
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString,
+ plContext,
+ certBasicConstraintsString,
+ pathLen),
+ PKIX_SPRINTFFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString,
+ plContext,
+ certBasicConstraintsString),
+ PKIX_SPRINTFFAILED);
+ }
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(certBasicConstraintsString);
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertBasicConstraints_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *certB = NULL;
+ PKIX_Boolean isCA = PKIX_FALSE;
+ PKIX_Int32 pathLen = 0;
+ PKIX_Int32 hashInput = 0;
+ PKIX_UInt32 cbcHash = 0;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTBASICCONSTRAINTS);
+
+ certB = (PKIX_PL_CertBasicConstraints *)object;
+
+ /*
+ * if CA == TRUE
+ * hash(pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT)
+ * if CA == FALSE, hash(0)
+ */
+
+ isCA = certB->isCA;
+
+ if (isCA) {
+ pathLen = certB->pathLen;
+
+ hashInput = pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT;
+ }
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)&hashInput,
+ sizeof (hashInput),
+ &cbcHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = cbcHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertBasicConstraints_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *firstCBC = NULL;
+ PKIX_PL_CertBasicConstraints *secondCBC = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean firstIsCA = PKIX_FALSE;
+ PKIX_Boolean secondIsCA = PKIX_FALSE;
+ PKIX_Int32 firstPathLen = 0;
+ PKIX_Int32 secondPathLen = 0;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertBasicConstraints */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTBASICCONSTRAINTS);
+
+ /*
+ * Since we know firstObject is a CertBasicConstraints,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a CertBasicConstraints, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERTBASICCONSTRAINTS_TYPE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ firstCBC = (PKIX_PL_CertBasicConstraints *)firstObject;
+ secondCBC = (PKIX_PL_CertBasicConstraints *)secondObject;
+
+ /*
+ * Compare the value of the CAFlag components
+ */
+
+ firstIsCA = firstCBC->isCA;
+
+ /*
+ * Failure here would be an error, not merely a miscompare,
+ * since we know second is a CertBasicConstraints.
+ */
+ secondIsCA = secondCBC->isCA;
+
+ /*
+ * If isCA flags differ, the objects are not equal.
+ */
+ if (secondIsCA != firstIsCA) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ /*
+ * If isCA was FALSE, the objects are equal, because
+ * pathLen is meaningless in that case.
+ */
+ if (!firstIsCA) {
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ firstPathLen = firstCBC->pathLen;
+ secondPathLen = secondCBC->pathLen;
+
+ *pResult = (secondPathLen == firstPathLen);
+
+cleanup:
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTBASICCONSTRAINTS_TYPE and its related
+ * functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertBasicConstraints_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_RegisterSelf");
+
+ entry.description = "CertBasicConstraints";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertBasicConstraints);
+ entry.destructor = pkix_pl_CertBasicConstraints_Destroy;
+ entry.equalsFunction = pkix_pl_CertBasicConstraints_Equals;
+ entry.hashcodeFunction = pkix_pl_CertBasicConstraints_Hashcode;
+ entry.toStringFunction = pkix_pl_CertBasicConstraints_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTBASICCONSTRAINTS_TYPE] = entry;
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_BasicConstraints_GetCAFlag
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_BasicConstraints_GetCAFlag(
+ PKIX_PL_CertBasicConstraints *basicConstraints,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "PKIX_PL_BasicConstraintsGetCAFlag");
+ PKIX_NULLCHECK_TWO(basicConstraints, pResult);
+
+ *pResult = basicConstraints->isCA;
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: PKIX_PL_BasicConstraints_GetPathLenConstraint
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_BasicConstraints_GetPathLenConstraint(
+ PKIX_PL_CertBasicConstraints *basicConstraints,
+ PKIX_Int32 *pPathLenConstraint,
+ void *plContext)
+{
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "PKIX_PL_BasicConstraintsGetPathLenConstraint");
+ PKIX_NULLCHECK_TWO(basicConstraints, pPathLenConstraint);
+
+ *pPathLenConstraint = basicConstraints->pathLen;
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h
new file mode 100644
index 0000000000..857529c95c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h
@@ -0,0 +1,47 @@
+/* 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/. */
+/*
+ * pkix_pl_basicconstraints.h
+ *
+ * BasicConstraints Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_BASICCONSTRAINTS_H
+#define _PKIX_PL_BASICCONSTRAINTS_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This structure reflects the contents of the basic constraints
+ * extension as described in Section 4.2.1.10 of RFC 3280.
+ * The cA flag indicates whether the public key in this certificate
+ * belongs to a certification authority. The pathLen constraint
+ * gives the maximum number of non-self-issued intermediate certificates
+ * that may follow this certificate in a valid certification path.
+ */
+struct PKIX_PL_CertBasicConstraintsStruct {
+ PKIX_Boolean isCA;
+ PKIX_Int32 pathLen;
+};
+
+PKIX_Error *
+pkix_pl_CertBasicConstraints_Create(
+ PKIX_Boolean isCA,
+ PKIX_Int32 pathLen,
+ PKIX_PL_CertBasicConstraints **object,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertBasicConstraints_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_BASICCONSTRAINTS_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c
new file mode 100644
index 0000000000..9dddd2e40f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c
@@ -0,0 +1,3734 @@
+/* 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/. */
+/*
+ * pkix_pl_cert.c
+ *
+ * Certificate Object Functions
+ *
+ */
+
+#include "pkix_pl_cert.h"
+
+extern PKIX_PL_HashTable *cachedCertSigTable;
+
+/* --Private-Cert-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Cert_IsExtensionCritical
+ * DESCRIPTION:
+ *
+ * Checks the Cert specified by "cert" to determine whether the extension
+ * whose tag is the UInt32 value given by "tag" is marked as a critical
+ * extension, and stores the result in "pCritical".
+ *
+ * Tags are the index into the table "oids" of SECOidData defined in the
+ * file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are
+ * are defined in secoidt.h for most of the table entries.
+ *
+ * If the specified tag is invalid (not in the list of tags) or if the
+ * extension is not found in the certificate, PKIX_FALSE is stored.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of Cert whose extensions are to be examined. Must be non-NULL.
+ * "tag"
+ * The UInt32 value of the tag for the extension whose criticality is
+ * to be determined
+ * "pCritical"
+ * Address where the Boolean value will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_IsExtensionCritical(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 tag,
+ PKIX_Boolean *pCritical,
+ void *plContext)
+{
+ PKIX_Boolean criticality = PKIX_FALSE;
+ CERTCertExtension **extensions = NULL;
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical);
+
+ extensions = cert->nssCert->extensions;
+ PKIX_NULLCHECK_ONE(extensions);
+
+ PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n");
+ rv = CERT_GetExtenCriticality(extensions, tag, &criticality);
+ if (SECSuccess == rv) {
+ *pCritical = criticality;
+ } else {
+ *pCritical = PKIX_FALSE;
+ }
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_DecodePolicyInfo
+ * DESCRIPTION:
+ *
+ * Decodes the contents of the CertificatePolicy extension in the
+ * CERTCertificate pointed to by "nssCert", to create a List of
+ * CertPolicyInfos, which is stored at the address "pCertPolicyInfos".
+ * A CERTCertificate contains the DER representation of the Cert.
+ * If this certificate does not have a CertificatePolicy extension,
+ * NULL will be stored. If a List is returned, it will be immutable.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of the Cert data whose extension is to be examined. Must be
+ * non-NULL.
+ * "pCertPolicyInfos"
+ * Address where the List of CertPolicyInfos will be stored. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_DecodePolicyInfo(
+ CERTCertificate *nssCert,
+ PKIX_List **pCertPolicyInfos,
+ void *plContext)
+{
+
+ SECStatus rv;
+ SECItem encodedCertPolicyInfo;
+
+ /* Allocated in the arena; freed in CERT_Destroy... */
+ CERTCertificatePolicies *certPol = NULL;
+ CERTPolicyInfo **policyInfos = NULL;
+
+ /* Holder for the return value */
+ PKIX_List *infos = NULL;
+
+ PKIX_PL_OID *pkixOID = NULL;
+ PKIX_List *qualifiers = NULL;
+ PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL;
+ PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL;
+ PKIX_PL_ByteArray *qualifierArray = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo");
+ PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos);
+
+ /* get PolicyInfo as a SECItem */
+ PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
+ rv = CERT_FindCertExtension
+ (nssCert,
+ SEC_OID_X509_CERTIFICATE_POLICIES,
+ &encodedCertPolicyInfo);
+ if (SECSuccess != rv) {
+ *pCertPolicyInfos = NULL;
+ goto cleanup;
+ }
+
+ /* translate PolicyInfo to CERTCertificatePolicies */
+ PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n");
+ certPol = CERT_DecodeCertificatePoliciesExtension
+ (&encodedCertPolicyInfo);
+
+ PORT_Free(encodedCertPolicyInfo.data);
+
+ if (NULL == certPol) {
+ PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED);
+ }
+
+ /*
+ * Check whether there are any policyInfos, so we can
+ * avoid creating an unnecessary List
+ */
+ policyInfos = certPol->policyInfos;
+ if (!policyInfos) {
+ *pCertPolicyInfos = NULL;
+ goto cleanup;
+ }
+
+ /* create a List of CertPolicyInfo Objects */
+ PKIX_CHECK(PKIX_List_Create(&infos, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /*
+ * Traverse the CERTCertificatePolicies structure,
+ * building each PKIX_PL_CertPolicyInfo object in turn
+ */
+ while (*policyInfos != NULL) {
+ CERTPolicyInfo *policyInfo = *policyInfos;
+ CERTPolicyQualifier **policyQualifiers =
+ policyInfo->policyQualifiers;
+ if (policyQualifiers) {
+ /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */
+ PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ while (*policyQualifiers != NULL) {
+ CERTPolicyQualifier *policyQualifier =
+ *policyQualifiers;
+
+ /* create the qualifier's OID object */
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (&policyQualifier->qualifierID,
+ &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* create qualifier's ByteArray object */
+
+ PKIX_CHECK(PKIX_PL_ByteArray_Create
+ (policyQualifier->qualifierValue.data,
+ policyQualifier->qualifierValue.len,
+ &qualifierArray,
+ plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ /* create a CertPolicyQualifier object */
+
+ PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create
+ (pkixOID,
+ qualifierArray,
+ &certPolicyQualifier,
+ plContext),
+ PKIX_CERTPOLICYQUALIFIERCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (qualifiers,
+ (PKIX_PL_Object *)certPolicyQualifier,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(pkixOID);
+ PKIX_DECREF(qualifierArray);
+ PKIX_DECREF(certPolicyQualifier);
+
+ policyQualifiers++;
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (qualifiers, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+ }
+
+
+ /*
+ * Create an OID object pkixOID from policyInfo->policyID.
+ * (The CERTPolicyInfo structure has an oid field, but it
+ * is of type SECOidTag. This function wants a SECItem.)
+ */
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (&policyInfo->policyID, &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* Create a CertPolicyInfo object */
+ PKIX_CHECK(pkix_pl_CertPolicyInfo_Create
+ (pkixOID, qualifiers, &certPolicyInfo, plContext),
+ PKIX_CERTPOLICYINFOCREATEFAILED);
+
+ /* Append the new CertPolicyInfo object to the list */
+ PKIX_CHECK(PKIX_List_AppendItem
+ (infos, (PKIX_PL_Object *)certPolicyInfo, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(pkixOID);
+ PKIX_DECREF(qualifiers);
+ PKIX_DECREF(certPolicyInfo);
+
+ policyInfos++;
+ }
+
+ /*
+ * If there were no policies, we went straight to
+ * cleanup, so we don't have to NULLCHECK infos.
+ */
+ PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pCertPolicyInfos = infos;
+ infos = NULL;
+
+cleanup:
+ if (certPol) {
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n");
+ CERT_DestroyCertificatePoliciesExtension(certPol);
+ }
+
+ PKIX_DECREF(infos);
+ PKIX_DECREF(pkixOID);
+ PKIX_DECREF(qualifiers);
+ PKIX_DECREF(certPolicyInfo);
+ PKIX_DECREF(certPolicyQualifier);
+ PKIX_DECREF(qualifierArray);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_DecodePolicyMapping
+ * DESCRIPTION:
+ *
+ * Decodes the contents of the PolicyMapping extension of the CERTCertificate
+ * pointed to by "nssCert", storing the resulting List of CertPolicyMaps at
+ * the address pointed to by "pCertPolicyMaps". If this certificate does not
+ * have a PolicyMapping extension, NULL will be stored. If a List is returned,
+ * it will be immutable.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of the Cert data whose extension is to be examined. Must be
+ * non-NULL.
+ * "pCertPolicyMaps"
+ * Address where the List of CertPolicyMaps will be stored. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_DecodePolicyMapping(
+ CERTCertificate *nssCert,
+ PKIX_List **pCertPolicyMaps,
+ void *plContext)
+{
+ SECStatus rv;
+ SECItem encodedCertPolicyMaps;
+
+ /* Allocated in the arena; freed in CERT_Destroy... */
+ CERTCertificatePolicyMappings *certPolMaps = NULL;
+ CERTPolicyMap **policyMaps = NULL;
+
+ /* Holder for the return value */
+ PKIX_List *maps = NULL;
+
+ PKIX_PL_OID *issuerDomainOID = NULL;
+ PKIX_PL_OID *subjectDomainOID = NULL;
+ PKIX_PL_CertPolicyMap *certPolicyMap = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping");
+ PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps);
+
+ /* get PolicyMappings as a SECItem */
+ PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
+ rv = CERT_FindCertExtension
+ (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps);
+ if (SECSuccess != rv) {
+ *pCertPolicyMaps = NULL;
+ goto cleanup;
+ }
+
+ /* translate PolicyMaps to CERTCertificatePolicyMappings */
+ certPolMaps = CERT_DecodePolicyMappingsExtension
+ (&encodedCertPolicyMaps);
+
+ PORT_Free(encodedCertPolicyMaps.data);
+
+ if (!certPolMaps) {
+ PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED);
+ }
+
+ PKIX_NULLCHECK_ONE(certPolMaps->policyMaps);
+
+ policyMaps = certPolMaps->policyMaps;
+
+ /* create a List of CertPolicyMap Objects */
+ PKIX_CHECK(PKIX_List_Create(&maps, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /*
+ * Traverse the CERTCertificatePolicyMappings structure,
+ * building each CertPolicyMap object in turn
+ */
+ do {
+ CERTPolicyMap *policyMap = *policyMaps;
+
+ /* create the OID for the issuer Domain Policy */
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (&policyMap->issuerDomainPolicy,
+ &issuerDomainOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* create the OID for the subject Domain Policy */
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (&policyMap->subjectDomainPolicy,
+ &subjectDomainOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* create the CertPolicyMap */
+
+ PKIX_CHECK(pkix_pl_CertPolicyMap_Create
+ (issuerDomainOID,
+ subjectDomainOID,
+ &certPolicyMap,
+ plContext),
+ PKIX_CERTPOLICYMAPCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (maps, (PKIX_PL_Object *)certPolicyMap, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(issuerDomainOID);
+ PKIX_DECREF(subjectDomainOID);
+ PKIX_DECREF(certPolicyMap);
+
+ policyMaps++;
+ } while (*policyMaps != NULL);
+
+ PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pCertPolicyMaps = maps;
+ maps = NULL;
+
+cleanup:
+ if (certPolMaps) {
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n");
+ CERT_DestroyPolicyMappingsExtension(certPolMaps);
+ }
+
+ PKIX_DECREF(maps);
+ PKIX_DECREF(issuerDomainOID);
+ PKIX_DECREF(subjectDomainOID);
+ PKIX_DECREF(certPolicyMap);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints
+ * DESCRIPTION:
+ *
+ * Decodes the contents of the PolicyConstraints extension in the
+ * CERTCertificate pointed to by "nssCert", to obtain SkipCerts values
+ * which are stored at the addresses "pExplicitPolicySkipCerts" and
+ * "pInhibitMappingSkipCerts", respectively. If this certificate does
+ * not have an PolicyConstraints extension, or if either of the optional
+ * components is not supplied, this function stores a value of -1 for any
+ * missing component.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of the Cert data whose extension is to be examined. Must be
+ * non-NULL.
+ * "pExplicitPolicySkipCerts"
+ * Address where the SkipCert value for the requireExplicitPolicy
+ * component will be stored. Must be non-NULL.
+ * "pInhibitMappingSkipCerts"
+ * Address where the SkipCert value for the inhibitPolicyMapping
+ * component will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_DecodePolicyConstraints(
+ CERTCertificate *nssCert,
+ PKIX_Int32 *pExplicitPolicySkipCerts,
+ PKIX_Int32 *pInhibitMappingSkipCerts,
+ void *plContext)
+{
+ CERTCertificatePolicyConstraints policyConstraints;
+ SECStatus rv;
+ SECItem encodedCertPolicyConstraints;
+ PKIX_Int32 explicitPolicySkipCerts = -1;
+ PKIX_Int32 inhibitMappingSkipCerts = -1;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints");
+ PKIX_NULLCHECK_THREE
+ (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts);
+
+ /* get the two skipCert values as SECItems */
+ PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
+ rv = CERT_FindCertExtension
+ (nssCert,
+ SEC_OID_X509_POLICY_CONSTRAINTS,
+ &encodedCertPolicyConstraints);
+
+ if (rv == SECSuccess) {
+
+ policyConstraints.explicitPolicySkipCerts.data =
+ (unsigned char *)&explicitPolicySkipCerts;
+ policyConstraints.inhibitMappingSkipCerts.data =
+ (unsigned char *)&inhibitMappingSkipCerts;
+
+ /* translate DER to CERTCertificatePolicyConstraints */
+ rv = CERT_DecodePolicyConstraintsExtension
+ (&policyConstraints, &encodedCertPolicyConstraints);
+
+ PORT_Free(encodedCertPolicyConstraints.data);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR
+ (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED);
+ }
+ }
+
+ *pExplicitPolicySkipCerts = explicitPolicySkipCerts;
+ *pInhibitMappingSkipCerts = inhibitMappingSkipCerts;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy
+ * DESCRIPTION:
+ *
+ * Decodes the contents of the InhibitAnyPolicy extension in the
+ * CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value,
+ * which is stored at the address "pSkipCerts". If this certificate does
+ * not have an InhibitAnyPolicy extension, -1 will be stored.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of the Cert data whose InhibitAnyPolicy extension is to be
+ * processed. Must be non-NULL.
+ * "pSkipCerts"
+ * Address where the SkipCert value from the InhibitAnyPolicy extension
+ * will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_DecodeInhibitAnyPolicy(
+ CERTCertificate *nssCert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext)
+{
+ CERTCertificateInhibitAny inhibitAny;
+ SECStatus rv;
+ SECItem encodedCertInhibitAny;
+ PKIX_Int32 skipCerts = -1;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy");
+ PKIX_NULLCHECK_TWO(nssCert, pSkipCerts);
+
+ /* get InhibitAny as a SECItem */
+ PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
+ rv = CERT_FindCertExtension
+ (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAny);
+
+ if (rv == SECSuccess) {
+ inhibitAny.inhibitAnySkipCerts.data =
+ (unsigned char *)&skipCerts;
+
+ /* translate DER to CERTCertificateInhibitAny */
+ rv = CERT_DecodeInhibitAnyExtension
+ (&inhibitAny, &encodedCertInhibitAny);
+
+ PORT_Free(encodedCertInhibitAny.data);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED);
+ }
+ }
+
+ *pSkipCerts = skipCerts;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames
+ * DESCRIPTION:
+ *
+ * Retrieves the Subject Alternative Names of the certificate specified by
+ * "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative
+ * Name extension is not present, NULL is returned at "pNssSubjAltNames".
+ * If the Subject Alternative Names has not been previously decoded, it is
+ * decoded here with lock on the "cert" unless the flag "hasLock" indicates
+ * the lock had been obtained at a higher call level.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of the certificate whose Subject Alternative Names extensions
+ * is retrieved. Must be non-NULL.
+ * "hasLock"
+ * Boolean indicates caller has acquired a lock.
+ * Must be non-NULL.
+ * "pNssSubjAltNames"
+ * Address where the returned Subject Alternative Names will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_GetNssSubjectAltNames(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean hasLock,
+ CERTGeneralName **pNssSubjAltNames,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ CERTGeneralName *nssOriginalAltName = NULL;
+ PLArenaPool *arena = NULL;
+ SECItem altNameExtension = {siBuffer, NULL, 0};
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames");
+ PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert);
+
+ nssCert = cert->nssCert;
+
+ if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
+
+ if (!hasLock) {
+ PKIX_OBJECT_LOCK(cert);
+ }
+
+ if ((cert->nssSubjAltNames == NULL) &&
+ (!cert->subjAltNamesAbsent)){
+
+ PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
+ (nssCert,
+ SEC_OID_X509_SUBJECT_ALT_NAME,
+ &altNameExtension));
+
+ if (rv != SECSuccess) {
+ *pNssSubjAltNames = NULL;
+ cert->subjAltNamesAbsent = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ if (cert->arenaNameConstraints == NULL) {
+ PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
+ (DER_DEFAULT_CHUNKSIZE));
+
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ cert->arenaNameConstraints = arena;
+ }
+
+ PKIX_PL_NSSCALLRV
+ (CERT,
+ nssOriginalAltName,
+ (CERTGeneralName *) CERT_DecodeAltNameExtension,
+ (cert->arenaNameConstraints, &altNameExtension));
+
+ PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data));
+
+ if (nssOriginalAltName == NULL) {
+ PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED);
+ }
+ cert->nssSubjAltNames = nssOriginalAltName;
+
+ }
+
+ if (!hasLock) {
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+ }
+
+ *pNssSubjAltNames = cert->nssSubjAltNames;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage
+ * DESCRIPTION:
+ *
+ * For each of the ON bit in "requiredExtendedKeyUsages" that represents its
+ * SECCertUsageEnum type, this function checks "cert"'s certType (extended
+ * key usage) and key usage with what is required for SECCertUsageEnum type.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of the certificate whose Extended Key Usage extensions
+ * is retrieved. Must be non-NULL.
+ * "requiredExtendedKeyUsages"
+ * An unsigned integer, its bit location is ON based on the required key
+ * usage value representing in SECCertUsageEnum.
+ * "pPass"
+ * Address where the return value, indicating key usage check passed, is
+ * stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_CheckExtendedKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 requiredExtendedKeyUsages,
+ PKIX_Boolean *pPass,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ PKIX_UInt32 certType = 0;
+ PKIX_UInt32 requiredKeyUsage = 0;
+ PKIX_UInt32 requiredCertType = 0;
+ PKIX_UInt32 requiredExtendedKeyUsage = 0;
+ PKIX_UInt32 i;
+ PKIX_Boolean isCA = PKIX_FALSE;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage");
+ PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert);
+
+ *pPass = PKIX_FALSE;
+
+ PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n");
+ cert_GetCertType(cert->nssCert);
+ certType = cert->nssCert->nsCertType;
+
+ PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
+ (cert,
+ &basicConstraints,
+ plContext),
+ PKIX_CERTGETBASICCONSTRAINTFAILED);
+
+ if (basicConstraints != NULL) {
+ PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
+ (basicConstraints, &isCA, plContext),
+ PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
+ }
+
+ i = 0;
+ while (requiredExtendedKeyUsages != 0) {
+
+ /* Find the bit location of the right-most non-zero bit */
+ while (requiredExtendedKeyUsages != 0) {
+ if (((1 << i) & requiredExtendedKeyUsages) != 0) {
+ requiredExtendedKeyUsage = 1 << i;
+ break;
+ }
+ i++;
+ }
+ requiredExtendedKeyUsages ^= requiredExtendedKeyUsage;
+
+ requiredExtendedKeyUsage = i;
+
+ PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage,
+ (requiredExtendedKeyUsage,
+ isCA,
+ &requiredKeyUsage,
+ &requiredCertType));
+
+ if (!(certType & requiredCertType)) {
+ goto cleanup;
+ }
+
+ PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage,
+ (cert->nssCert, requiredKeyUsage));
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ i++;
+
+ }
+
+ *pPass = PKIX_TRUE;
+
+cleanup:
+ PKIX_DECREF(basicConstraints);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the Cert pointed
+ * to by "cert" and stores it at "pString", where the value of
+ * "partialString" determines whether a full or partial representation of
+ * the Cert is stored.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of Cert whose string representation is desired.
+ * Must be non-NULL.
+ * "partialString"
+ * Boolean indicating whether a partial Cert representation is desired.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_ToString_Helper(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean partialString,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *certString = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_UInt32 certVersion;
+ PKIX_PL_BigInt *certSN = NULL;
+ PKIX_PL_String *certSNString = NULL;
+ PKIX_PL_X500Name *certIssuer = NULL;
+ PKIX_PL_String *certIssuerString = NULL;
+ PKIX_PL_X500Name *certSubject = NULL;
+ PKIX_PL_String *certSubjectString = NULL;
+ PKIX_PL_String *notBeforeString = NULL;
+ PKIX_PL_String *notAfterString = NULL;
+ PKIX_List *subjAltNames = NULL;
+ PKIX_PL_String *subjAltNamesString = NULL;
+ PKIX_PL_ByteArray *authKeyId = NULL;
+ PKIX_PL_String *authKeyIdString = NULL;
+ PKIX_PL_ByteArray *subjKeyId = NULL;
+ PKIX_PL_String *subjKeyIdString = NULL;
+ PKIX_PL_PublicKey *nssPubKey = NULL;
+ PKIX_PL_String *nssPubKeyString = NULL;
+ PKIX_List *critExtOIDs = NULL;
+ PKIX_PL_String *critExtOIDsString = NULL;
+ PKIX_List *extKeyUsages = NULL;
+ PKIX_PL_String *extKeyUsagesString = NULL;
+ PKIX_PL_CertBasicConstraints *basicConstraint = NULL;
+ PKIX_PL_String *certBasicConstraintsString = NULL;
+ PKIX_List *policyInfo = NULL;
+ PKIX_PL_String *certPolicyInfoString = NULL;
+ PKIX_List *certPolicyMappings = NULL;
+ PKIX_PL_String *certPolicyMappingsString = NULL;
+ PKIX_Int32 certExplicitPolicy = 0;
+ PKIX_Int32 certInhibitMapping = 0;
+ PKIX_Int32 certInhibitAnyPolicy = 0;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ PKIX_PL_String *nameConstraintsString = NULL;
+ PKIX_List *authorityInfoAccess = NULL;
+ PKIX_PL_String *authorityInfoAccessString = NULL;
+ PKIX_List *subjectInfoAccess = NULL;
+ PKIX_PL_String *subjectInfoAccessString = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString);
+
+ /*
+ * XXX Add to this format as certificate components are developed.
+ */
+
+ if (partialString){
+ asciiFormat =
+ "\t[Issuer: %s\n"
+ "\t Subject: %s]";
+ } else {
+ asciiFormat =
+ "[\n"
+ "\tVersion: v%d\n"
+ "\tSerialNumber: %s\n"
+ "\tIssuer: %s\n"
+ "\tSubject: %s\n"
+ "\tValidity: [From: %s\n"
+ "\t To: %s]\n"
+ "\tSubjectAltNames: %s\n"
+ "\tAuthorityKeyId: %s\n"
+ "\tSubjectKeyId: %s\n"
+ "\tSubjPubKeyAlgId: %s\n"
+ "\tCritExtOIDs: %s\n"
+ "\tExtKeyUsages: %s\n"
+ "\tBasicConstraint: %s\n"
+ "\tCertPolicyInfo: %s\n"
+ "\tPolicyMappings: %s\n"
+ "\tExplicitPolicy: %d\n"
+ "\tInhibitMapping: %d\n"
+ "\tInhibitAnyPolicy:%d\n"
+ "\tNameConstraints: %s\n"
+ "\tAuthorityInfoAccess: %s\n"
+ "\tSubjectInfoAccess: %s\n"
+ "\tCacheFlag: %d\n"
+ "]\n";
+ }
+
+
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Issuer */
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer
+ (cert, &certIssuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext),
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ /* Subject */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ PKIX_TOSTRING(certSubject, &certSubjectString, plContext,
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ if (partialString){
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&certString,
+ plContext,
+ formatString,
+ certIssuerString,
+ certSubjectString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = certString;
+ goto cleanup;
+ }
+
+ /* Version */
+ PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext),
+ PKIX_CERTGETVERSIONFAILED);
+
+ /* SerialNumber */
+ PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext),
+ PKIX_CERTGETSERIALNUMBERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)certSN, &certSNString, plContext),
+ PKIX_BIGINTTOSTRINGFAILED);
+
+ /* Validity: NotBefore */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(cert->nssCert->validity.notBefore),
+ &notBeforeString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* Validity: NotAfter */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(cert->nssCert->validity.notAfter),
+ &notAfterString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* SubjectAltNames */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
+ (cert, &subjAltNames, plContext),
+ PKIX_CERTGETSUBJECTALTNAMESFAILED);
+
+ PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* AuthorityKeyIdentifier */
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
+ (cert, &authKeyId, plContext),
+ PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
+
+ PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext,
+ PKIX_BYTEARRAYTOSTRINGFAILED);
+
+ /* SubjectKeyIdentifier */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier
+ (cert, &subjKeyId, plContext),
+ PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED);
+
+ PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext,
+ PKIX_BYTEARRAYTOSTRINGFAILED);
+
+ /* SubjectPublicKey */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (cert, &nssPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext),
+ PKIX_PUBLICKEYTOSTRINGFAILED);
+
+ /* CriticalExtensionOIDs */
+ PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
+ (cert, &critExtOIDs, plContext),
+ PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
+
+ PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* ExtendedKeyUsages */
+ PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
+ (cert, &extKeyUsages, plContext),
+ PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+
+ PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* CertBasicConstraints */
+ PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
+ (cert, &basicConstraint, plContext),
+ PKIX_CERTGETBASICCONSTRAINTSFAILED);
+
+ PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext,
+ PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED);
+
+ /* CertPolicyInfo */
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &policyInfo, plContext),
+ PKIX_CERTGETPOLICYINFORMATIONFAILED);
+
+ PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Advanced Policies */
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings
+ (cert, &certPolicyMappings, plContext),
+ PKIX_CERTGETPOLICYMAPPINGSFAILED);
+
+ PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
+ (cert, &certExplicitPolicy, plContext),
+ PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited
+ (cert, &certInhibitMapping, plContext),
+ PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy
+ (cert, &certInhibitAnyPolicy, plContext),
+ PKIX_CERTGETINHIBITANYPOLICYFAILED);
+
+ /* Name Constraints */
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (cert, &nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+ PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Authority Information Access */
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess
+ (cert, &authorityInfoAccess, plContext),
+ PKIX_CERTGETAUTHORITYINFOACCESSFAILED);
+
+ PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Subject Information Access */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess
+ (cert, &subjectInfoAccess, plContext),
+ PKIX_CERTGETSUBJECTINFOACCESSFAILED);
+
+ PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&certString,
+ plContext,
+ formatString,
+ certVersion + 1,
+ certSNString,
+ certIssuerString,
+ certSubjectString,
+ notBeforeString,
+ notAfterString,
+ subjAltNamesString,
+ authKeyIdString,
+ subjKeyIdString,
+ nssPubKeyString,
+ critExtOIDsString,
+ extKeyUsagesString,
+ certBasicConstraintsString,
+ certPolicyInfoString,
+ certPolicyMappingsString,
+ certExplicitPolicy, /* an Int32, not a String */
+ certInhibitMapping, /* an Int32, not a String */
+ certInhibitAnyPolicy, /* an Int32, not a String */
+ nameConstraintsString,
+ authorityInfoAccessString,
+ subjectInfoAccessString,
+ cert->cacheFlag), /* a boolean */
+ PKIX_SPRINTFFAILED);
+
+ *pString = certString;
+
+cleanup:
+ PKIX_DECREF(certSN);
+ PKIX_DECREF(certSNString);
+ PKIX_DECREF(certIssuer);
+ PKIX_DECREF(certIssuerString);
+ PKIX_DECREF(certSubject);
+ PKIX_DECREF(certSubjectString);
+ PKIX_DECREF(notBeforeString);
+ PKIX_DECREF(notAfterString);
+ PKIX_DECREF(subjAltNames);
+ PKIX_DECREF(subjAltNamesString);
+ PKIX_DECREF(authKeyId);
+ PKIX_DECREF(authKeyIdString);
+ PKIX_DECREF(subjKeyId);
+ PKIX_DECREF(subjKeyIdString);
+ PKIX_DECREF(nssPubKey);
+ PKIX_DECREF(nssPubKeyString);
+ PKIX_DECREF(critExtOIDs);
+ PKIX_DECREF(critExtOIDsString);
+ PKIX_DECREF(extKeyUsages);
+ PKIX_DECREF(extKeyUsagesString);
+ PKIX_DECREF(basicConstraint);
+ PKIX_DECREF(certBasicConstraintsString);
+ PKIX_DECREF(policyInfo);
+ PKIX_DECREF(certPolicyInfoString);
+ PKIX_DECREF(certPolicyMappings);
+ PKIX_DECREF(certPolicyMappingsString);
+ PKIX_DECREF(nameConstraints);
+ PKIX_DECREF(nameConstraintsString);
+ PKIX_DECREF(authorityInfoAccess);
+ PKIX_DECREF(authorityInfoAccessString);
+ PKIX_DECREF(subjectInfoAccess);
+ PKIX_DECREF(subjectInfoAccessString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Cert_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+
+ cert = (PKIX_PL_Cert*)object;
+
+ PKIX_DECREF(cert->subject);
+ PKIX_DECREF(cert->issuer);
+ PKIX_DECREF(cert->subjAltNames);
+ PKIX_DECREF(cert->publicKeyAlgId);
+ PKIX_DECREF(cert->publicKey);
+ PKIX_DECREF(cert->serialNumber);
+ PKIX_DECREF(cert->critExtOids);
+ PKIX_DECREF(cert->authKeyId);
+ PKIX_DECREF(cert->subjKeyId);
+ PKIX_DECREF(cert->extKeyUsages);
+ PKIX_DECREF(cert->certBasicConstraints);
+ PKIX_DECREF(cert->certPolicyInfos);
+ PKIX_DECREF(cert->certPolicyMappings);
+ PKIX_DECREF(cert->nameConstraints);
+ PKIX_DECREF(cert->store);
+ PKIX_DECREF(cert->authorityInfoAccess);
+ PKIX_DECREF(cert->subjectInfoAccess);
+ PKIX_DECREF(cert->crldpList);
+
+ if (cert->arenaNameConstraints){
+ /* This arena was allocated for SubjectAltNames */
+ PKIX_PL_NSSCALL(CERT, PORT_FreeArena,
+ (cert->arenaNameConstraints, PR_FALSE));
+
+ cert->arenaNameConstraints = NULL;
+ cert->nssSubjAltNames = NULL;
+ }
+
+ CERT_DestroyCertificate(cert->nssCert);
+ cert->nssCert = NULL;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Cert_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *certString = NULL;
+ PKIX_PL_Cert *pkixCert = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+
+ pkixCert = (PKIX_PL_Cert *)object;
+
+ PKIX_CHECK(pkix_pl_Cert_ToString_Helper
+ (pkixCert, PKIX_FALSE, &certString, plContext),
+ PKIX_CERTTOSTRINGHELPERFAILED);
+
+ *pString = certString;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Cert_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_Cert *pkixCert = NULL;
+ CERTCertificate *nssCert = NULL;
+ unsigned char *derBytes = NULL;
+ PKIX_UInt32 derLength;
+ PKIX_UInt32 certHash;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+
+ pkixCert = (PKIX_PL_Cert *)object;
+
+ nssCert = pkixCert->nssCert;
+ derBytes = (nssCert->derCert).data;
+ derLength = (nssCert->derCert).len;
+
+ PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = certHash;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_Cert_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Cert_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ CERTCertificate *firstCert = NULL;
+ CERTCertificate *secondCert = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a Cert */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERT);
+
+ /*
+ * Since we know firstObject is a Cert, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a Cert, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERT_TYPE) goto cleanup;
+
+ firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert;
+ secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert;
+
+ PKIX_NULLCHECK_TWO(firstCert, secondCert);
+
+ /* CERT_CompareCerts does byte comparison on DER encodings of certs */
+ PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n");
+ cmpResult = CERT_CompareCerts(firstCert, secondCert);
+
+ *pResult = cmpResult;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_Cert_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf");
+
+ entry.description = "Cert";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_Cert);
+ entry.destructor = pkix_pl_Cert_Destroy;
+ entry.equalsFunction = pkix_pl_Cert_Equals;
+ entry.hashcodeFunction = pkix_pl_Cert_Hashcode;
+ entry.toStringFunction = pkix_pl_Cert_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERT_TYPE] = entry;
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_CreateWithNSSCert
+ * DESCRIPTION:
+ *
+ * Creates a new certificate using the CERTCertificate pointed to by "nssCert"
+ * and stores it at "pCert". Once created, a Cert is immutable.
+ *
+ * This function is primarily used as a convenience function for the
+ * performance tests that have easy access to a CERTCertificate.
+ *
+ * PARAMETERS:
+ * "nssCert"
+ * Address of CERTCertificate representing the NSS certificate.
+ * Must be non-NULL.
+ * "pCert"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_CreateWithNSSCert(
+ CERTCertificate *nssCert,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert");
+ PKIX_NULLCHECK_TWO(pCert, nssCert);
+
+ /* create a PKIX_PL_Cert object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERT_TYPE,
+ sizeof (PKIX_PL_Cert),
+ (PKIX_PL_Object **)&cert,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* populate the nssCert field */
+ cert->nssCert = nssCert;
+
+ /* initialize remaining fields */
+ /*
+ * Fields ending with Absent are initialized to PKIX_FALSE so that the
+ * first time we need the value we will look for it. If we find it is
+ * actually absent, the flag will at that time be set to PKIX_TRUE to
+ * prevent searching for it later.
+ * Fields ending with Processed are those where a value is defined
+ * for the Absent case, and a value of zero is possible. When the
+ * flag is still true we have to look for the field, set the default
+ * value if necessary, and set the Processed flag to PKIX_TRUE.
+ */
+ cert->subject = NULL;
+ cert->issuer = NULL;
+ cert->subjAltNames = NULL;
+ cert->subjAltNamesAbsent = PKIX_FALSE;
+ cert->publicKeyAlgId = NULL;
+ cert->publicKey = NULL;
+ cert->serialNumber = NULL;
+ cert->critExtOids = NULL;
+ cert->subjKeyId = NULL;
+ cert->subjKeyIdAbsent = PKIX_FALSE;
+ cert->authKeyId = NULL;
+ cert->authKeyIdAbsent = PKIX_FALSE;
+ cert->extKeyUsages = NULL;
+ cert->extKeyUsagesAbsent = PKIX_FALSE;
+ cert->certBasicConstraints = NULL;
+ cert->basicConstraintsAbsent = PKIX_FALSE;
+ cert->certPolicyInfos = NULL;
+ cert->policyInfoAbsent = PKIX_FALSE;
+ cert->policyMappingsAbsent = PKIX_FALSE;
+ cert->certPolicyMappings = NULL;
+ cert->policyConstraintsProcessed = PKIX_FALSE;
+ cert->policyConstraintsExplicitPolicySkipCerts = 0;
+ cert->policyConstraintsInhibitMappingSkipCerts = 0;
+ cert->inhibitAnyPolicyProcessed = PKIX_FALSE;
+ cert->inhibitAnySkipCerts = 0;
+ cert->nameConstraints = NULL;
+ cert->nameConstraintsAbsent = PKIX_FALSE;
+ cert->arenaNameConstraints = NULL;
+ cert->nssSubjAltNames = NULL;
+ cert->cacheFlag = PKIX_FALSE;
+ cert->store = NULL;
+ cert->authorityInfoAccess = NULL;
+ cert->subjectInfoAccess = NULL;
+ cert->isUserTrustAnchor = PKIX_FALSE;
+ cert->crldpList = NULL;
+
+ *pCert = cert;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_CreateToList
+ * DESCRIPTION:
+ *
+ * Creates a new certificate using the DER-encoding pointed to by "derCertItem"
+ * and appends it to the list pointed to by "certList". If Cert creation fails,
+ * the function returns with certList unchanged, but any decoding Error is
+ * discarded.
+ *
+ * PARAMETERS:
+ * "derCertItem"
+ * Address of SECItem containing the DER representation of a certificate.
+ * Must be non-NULL.
+ * "certList"
+ * Address of List to which the Cert will be appended, if successfully
+ * created. May be empty, but must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_CreateToList(
+ SECItem *derCertItem,
+ PKIX_List *certList,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ CERTCertDBHandle *handle;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList");
+ PKIX_NULLCHECK_TWO(derCertItem, certList);
+
+ handle = CERT_GetDefaultCertDB();
+ nssCert = CERT_NewTempCertificate(handle, derCertItem,
+ /* nickname */ NULL,
+ /* isPerm */ PR_FALSE,
+ /* copyDer */ PR_TRUE);
+ if (!nssCert) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
+ (nssCert, &cert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+
+ nssCert = NULL;
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (certList, (PKIX_PL_Object *) cert, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+cleanup:
+ if (nssCert) {
+ CERT_DestroyCertificate(nssCert);
+ }
+
+ PKIX_DECREF(cert);
+ PKIX_RETURN(CERT);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h)
+ * XXX We may want to cache the cert after parsing it, so it can be reused
+ * XXX Are the NSS/NSPR functions thread safe
+ */
+PKIX_Error *
+PKIX_PL_Cert_Create(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ SECItem *derCertItem = NULL;
+ void *derBytes = NULL;
+ PKIX_UInt32 derLength;
+ PKIX_PL_Cert *cert = NULL;
+ CERTCertDBHandle *handle;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_Create");
+ PKIX_NULLCHECK_TWO(pCert, byteArray);
+
+ PKIX_CHECK(PKIX_PL_ByteArray_GetPointer
+ (byteArray, &derBytes, plContext),
+ PKIX_BYTEARRAYGETPOINTERFAILED);
+
+ PKIX_CHECK(PKIX_PL_ByteArray_GetLength
+ (byteArray, &derLength, plContext),
+ PKIX_BYTEARRAYGETLENGTHFAILED);
+
+ derCertItem = SECITEM_AllocItem(NULL, NULL, derLength);
+ if (derCertItem == NULL){
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ (void) PORT_Memcpy(derCertItem->data, derBytes, derLength);
+
+ /*
+ * setting copyDER to true forces NSS to make its own copy of the DER,
+ * allowing us to free our copy without worrying about whether NSS
+ * is still using it
+ */
+ handle = CERT_GetDefaultCertDB();
+ nssCert = CERT_NewTempCertificate(handle, derCertItem,
+ /* nickname */ NULL,
+ /* isPerm */ PR_FALSE,
+ /* copyDer */ PR_TRUE);
+ if (!nssCert){
+ PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED);
+ }
+
+ PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
+ (nssCert, &cert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+
+ *pCert = cert;
+
+cleanup:
+ if (derCertItem){
+ SECITEM_FreeItem(derCertItem, PKIX_TRUE);
+ }
+
+ if (nssCert && PKIX_ERROR_RECEIVED){
+ PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
+ CERT_DestroyCertificate(nssCert);
+ nssCert = NULL;
+ }
+
+ PKIX_FREE(derBytes);
+ PKIX_RETURN(CERT);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_CreateFromCERTCertificate(
+ const CERTCertificate *nssCert,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ PKIX_PL_ByteArray *byteArray = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert");
+ PKIX_NULLCHECK_TWO(pCert, nssCert);
+
+ buf = (void*)nssCert->derCert.data;
+ len = nssCert->derCert.len;
+
+ PKIX_CHECK(
+ PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_Create(byteArray, pCert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+
+#ifdef PKIX_UNDEF
+ /* will be tested and used as a patch for bug 391612 */
+ nssCert = CERT_DupCertificate(nssInCert);
+
+ PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
+ (nssCert, &cert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+#endif /* PKIX_UNDEF */
+
+cleanup:
+
+#ifdef PKIX_UNDEF
+ if (nssCert && PKIX_ERROR_RECEIVED){
+ PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
+ CERT_DestroyCertificate(nssCert);
+ nssCert = NULL;
+ }
+#endif /* PKIX_UNDEF */
+
+ PKIX_DECREF(byteArray);
+ PKIX_RETURN(CERT);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetVersion(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 *pVersion,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ PKIX_UInt32 myVersion = 0; /* v1 */
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion);
+
+ nssCert = cert->nssCert;
+ if (nssCert->version.len != 0) {
+ myVersion = *(nssCert->version.data);
+ }
+
+ if (myVersion > 2){
+ PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3);
+ }
+
+ *pVersion = myVersion;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSerialNumber(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_BigInt **pSerialNumber,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ SECItem serialNumItem;
+ PKIX_PL_BigInt *serialNumber = NULL;
+ char *bytes = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber);
+
+ if (cert->serialNumber == NULL){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->serialNumber == NULL){
+
+ nssCert = cert->nssCert;
+ serialNumItem = nssCert->serialNumber;
+
+ length = serialNumItem.len;
+ bytes = (char *)serialNumItem.data;
+
+ PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
+ (bytes, length, &serialNumber, plContext),
+ PKIX_BIGINTCREATEWITHBYTESFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->serialNumber = serialNumber;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->serialNumber);
+ *pSerialNumber = cert->serialNumber;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubject(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_X500Name **pCertSubject,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixSubject = NULL;
+ CERTName *subjName = NULL;
+ SECItem *derSubjName = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->subject == NULL){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->subject == NULL){
+
+ subjName = &cert->nssCert->subject;
+ derSubjName = &cert->nssCert->derSubject;
+
+ /* if there is no subject name */
+ if (derSubjName->data == NULL) {
+
+ pkixSubject = NULL;
+
+ } else {
+ PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
+ (derSubjName, subjName, &pkixSubject,
+ plContext),
+ PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
+
+ }
+ /* save a cached copy in case it is asked for again */
+ cert->subject = pkixSubject;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->subject);
+ *pCertSubject = cert->subject;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetIssuer(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_X500Name **pCertIssuer,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixIssuer = NULL;
+ SECItem *derIssuerName = NULL;
+ CERTName *issuerName = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->issuer == NULL){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->issuer == NULL){
+
+ issuerName = &cert->nssCert->issuer;
+ derIssuerName = &cert->nssCert->derIssuer;
+
+ /* if there is no subject name */
+ PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
+ (derIssuerName, issuerName,
+ &pkixIssuer, plContext),
+ PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->issuer = pkixIssuer;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->issuer);
+ *pCertIssuer = cert->issuer;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectAltNames(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_PL_GeneralName *pkixAltName = NULL;
+ PKIX_List *altNamesList = NULL;
+
+ CERTGeneralName *nssOriginalAltName = NULL;
+ CERTGeneralName *nssTempAltName = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames");
+ PKIX_NULLCHECK_TWO(cert, pSubjectAltNames);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->subjAltNames == NULL) &&
+ (!cert->subjAltNamesAbsent)){
+
+ PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
+ (cert,
+ PKIX_TRUE,
+ &nssOriginalAltName,
+ plContext),
+ PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
+
+ if (nssOriginalAltName == NULL) {
+ cert->subjAltNamesAbsent = PKIX_TRUE;
+ pSubjectAltNames = NULL;
+ goto cleanup;
+ }
+
+ nssTempAltName = nssOriginalAltName;
+
+ PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ do {
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (nssTempAltName, &pkixAltName, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (altNamesList,
+ (PKIX_PL_Object *)pkixAltName,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(pkixAltName);
+
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_GetNextGeneralName).\n");
+ nssTempAltName = CERT_GetNextGeneralName
+ (nssTempAltName);
+
+ } while (nssTempAltName != nssOriginalAltName);
+
+ /* save a cached copy in case it is asked for again */
+ cert->subjAltNames = altNamesList;
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (cert->subjAltNames, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->subjAltNames);
+
+ *pSubjectAltNames = cert->subjAltNames;
+
+cleanup:
+ PKIX_DECREF(pkixAltName);
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(altNamesList);
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetAllSubjectNames(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ CERTGeneralName *nssOriginalSubjectName = NULL;
+ CERTGeneralName *nssTempSubjectName = NULL;
+ PKIX_List *allSubjectNames = NULL;
+ PKIX_PL_GeneralName *pkixSubjectName = NULL;
+ PLArenaPool *arena = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames);
+
+
+ if (cert->nssCert->subjectName == NULL){
+ /* if there is no subject DN, just get altnames */
+
+ PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
+ (cert,
+ PKIX_FALSE, /* hasLock */
+ &nssOriginalSubjectName,
+ plContext),
+ PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
+
+ } else { /* get subject DN and altnames */
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ /* This NSS call returns both Subject and Subject Alt Names */
+ PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n");
+ nssOriginalSubjectName =
+ CERT_GetCertificateNames(cert->nssCert, arena);
+ }
+
+ if (nssOriginalSubjectName == NULL) {
+ pAllSubjectNames = NULL;
+ goto cleanup;
+ }
+
+ nssTempSubjectName = nssOriginalSubjectName;
+
+ PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ do {
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (nssTempSubjectName, &pkixSubjectName, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (allSubjectNames,
+ (PKIX_PL_Object *)pkixSubjectName,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(pkixSubjectName);
+
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_GetNextGeneralName).\n");
+ nssTempSubjectName = CERT_GetNextGeneralName
+ (nssTempSubjectName);
+ } while (nssTempSubjectName != nssOriginalSubjectName);
+
+ *pAllSubjectNames = allSubjectNames;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(allSubjectNames);
+ }
+
+ if (arena){
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ PKIX_DECREF(pkixSubjectName);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectPublicKeyAlgId(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_OID **pSubjKeyAlgId,
+ void *plContext)
+{
+ PKIX_PL_OID *pubKeyAlgId = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->publicKeyAlgId == NULL){
+ PKIX_OBJECT_LOCK(cert);
+ if (cert->publicKeyAlgId == NULL){
+ CERTCertificate *nssCert = cert->nssCert;
+ SECAlgorithmID *algorithm;
+ SECItem *algBytes;
+
+ algorithm = &nssCert->subjectPublicKeyInfo.algorithm;
+ algBytes = &algorithm->algorithm;
+ if (!algBytes->data || !algBytes->len) {
+ PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0);
+ }
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (algBytes, &pubKeyAlgId, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->publicKeyAlgId = pubKeyAlgId;
+ pubKeyAlgId = NULL;
+ }
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->publicKeyAlgId);
+ *pSubjKeyAlgId = cert->publicKeyAlgId;
+
+cleanup:
+ PKIX_DECREF(pubKeyAlgId);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectPublicKey(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_PublicKey **pPublicKey,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *pkixPubKey = NULL;
+ SECStatus rv;
+
+ CERTSubjectPublicKeyInfo *from = NULL;
+ CERTSubjectPublicKeyInfo *to = NULL;
+ SECItem *fromItem = NULL;
+ SECItem *toItem = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->publicKey == NULL){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->publicKey == NULL){
+
+ /* create a PKIX_PL_PublicKey object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_PUBLICKEY_TYPE,
+ sizeof (PKIX_PL_PublicKey),
+ (PKIX_PL_Object **)&pkixPubKey,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* initialize fields */
+ pkixPubKey->nssSPKI = NULL;
+
+ /* populate the SPKI field */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (CERTSubjectPublicKeyInfo),
+ (void **)&pkixPubKey->nssSPKI,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ to = pkixPubKey->nssSPKI;
+ from = &cert->nssCert->subjectPublicKeyInfo;
+
+ PKIX_NULLCHECK_TWO(to, from);
+
+ PKIX_CERT_DEBUG
+ ("\t\tCalling SECOID_CopyAlgorithmID).\n");
+ rv = SECOID_CopyAlgorithmID
+ (NULL, &to->algorithm, &from->algorithm);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED);
+ }
+
+ /*
+ * NSS stores the length of subjectPublicKey in bits.
+ * Therefore, we use that length converted to bytes
+ * using ((length+7)>>3) before calling PORT_Memcpy
+ * in order to avoid "read from uninitialized memory"
+ * errors.
+ */
+
+ toItem = &to->subjectPublicKey;
+ fromItem = &from->subjectPublicKey;
+
+ PKIX_NULLCHECK_TWO(toItem, fromItem);
+
+ toItem->type = fromItem->type;
+
+ toItem->data =
+ (unsigned char*) PORT_ZAlloc(fromItem->len);
+ if (!toItem->data){
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ (void) PORT_Memcpy(toItem->data,
+ fromItem->data,
+ (fromItem->len + 7)>>3);
+ toItem->len = fromItem->len;
+
+ /* save a cached copy in case it is asked for again */
+ cert->publicKey = pkixPubKey;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->publicKey);
+ *pPublicKey = cert->publicKey;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && pkixPubKey){
+ PKIX_DECREF(pkixPubKey);
+ cert->publicKey = NULL;
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCriticalExtensionOIDs(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pList, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_List *oidsList = NULL;
+ CERTCertExtension **extensions = NULL;
+ CERTCertificate *nssCert = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->critExtOids == NULL) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->critExtOids == NULL) {
+
+ nssCert = cert->nssCert;
+
+ /*
+ * ASN.1 for Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnID OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ *
+ */
+
+ extensions = nssCert->extensions;
+
+ PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
+ (extensions, &oidsList, plContext),
+ PKIX_GETCRITICALEXTENSIONOIDSFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->critExtOids = oidsList;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ /* We should return a copy of the List since this list changes */
+ PKIX_DUPLICATE(cert->critExtOids, pList, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetAuthorityKeyIdentifier(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_ByteArray **pAuthKeyId,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *authKeyId = NULL;
+ CERTCertificate *nssCert = NULL;
+ CERTAuthKeyID *authKeyIdExtension = NULL;
+ PLArenaPool *arena = NULL;
+ SECItem retItem;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ nssCert = cert->nssCert;
+
+ authKeyIdExtension =
+ CERT_FindAuthKeyIDExten(arena, nssCert);
+ if (authKeyIdExtension == NULL){
+ cert->authKeyIdAbsent = PKIX_TRUE;
+ *pAuthKeyId = NULL;
+ goto cleanup;
+ }
+
+ retItem = authKeyIdExtension->keyID;
+
+ if (retItem.len == 0){
+ cert->authKeyIdAbsent = PKIX_TRUE;
+ *pAuthKeyId = NULL;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_ByteArray_Create
+ (retItem.data,
+ retItem.len,
+ &authKeyId,
+ plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->authKeyId = authKeyId;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->authKeyId);
+ *pAuthKeyId = cert->authKeyId;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (arena){
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectKeyIdentifier(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_ByteArray **pSubjKeyId,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *subjKeyId = NULL;
+ CERTCertificate *nssCert = NULL;
+ SECItem *retItem = NULL;
+ SECStatus status;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
+
+ retItem = SECITEM_AllocItem(NULL, NULL, 0);
+ if (retItem == NULL){
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ nssCert = cert->nssCert;
+
+ status = CERT_FindSubjectKeyIDExtension
+ (nssCert, retItem);
+ if (status != SECSuccess) {
+ cert->subjKeyIdAbsent = PKIX_TRUE;
+ *pSubjKeyId = NULL;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_ByteArray_Create
+ (retItem->data,
+ retItem->len,
+ &subjKeyId,
+ plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->subjKeyId = subjKeyId;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->subjKeyId);
+ *pSubjKeyId = cert->subjKeyId;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (retItem){
+ SECITEM_FreeItem(retItem, PKIX_TRUE);
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetExtendedKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ CERTOidSequence *extKeyUsage = NULL;
+ CERTCertificate *nssCert = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+ PKIX_List *oidsList = NULL;
+ SECItem **oids = NULL;
+ SECItem encodedExtKeyUsage;
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->extKeyUsages == NULL) &&
+ (!cert->extKeyUsagesAbsent)){
+
+ nssCert = cert->nssCert;
+
+ rv = CERT_FindCertExtension
+ (nssCert, SEC_OID_X509_EXT_KEY_USAGE,
+ &encodedExtKeyUsage);
+ if (rv != SECSuccess){
+ cert->extKeyUsagesAbsent = PKIX_TRUE;
+ *pKeyUsage = NULL;
+ goto cleanup;
+ }
+
+ extKeyUsage =
+ CERT_DecodeOidSequence(&encodedExtKeyUsage);
+ if (extKeyUsage == NULL){
+ PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED);
+ }
+
+ PORT_Free(encodedExtKeyUsage.data);
+
+ oids = extKeyUsage->oids;
+
+ if (!oids){
+ /* no extended key usage extensions found */
+ cert->extKeyUsagesAbsent = PKIX_TRUE;
+ *pKeyUsage = NULL;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&oidsList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ while (*oids){
+ SECItem *oid = *oids++;
+
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (oid, &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (oidsList,
+ (PKIX_PL_Object *)pkixOID,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(pkixOID);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (oidsList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->extKeyUsages = oidsList;
+ oidsList = NULL;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->extKeyUsages);
+ *pKeyUsage = cert->extKeyUsages;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+
+ PKIX_DECREF(pkixOID);
+ PKIX_DECREF(oidsList);
+ CERT_DestroyOidSequence(extKeyUsage);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetBasicConstraints
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetBasicConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertBasicConstraints **pBasicConstraints,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ CERTBasicConstraints nssBasicConstraint;
+ SECStatus rv;
+ PKIX_PL_CertBasicConstraints *basic;
+ PKIX_Int32 pathLen = 0;
+ PKIX_Boolean isCA = PKIX_FALSE;
+ enum {
+ realBC, synthBC, absentBC
+ } constraintSource = absentBC;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->certBasicConstraints == NULL) &&
+ (!cert->basicConstraintsAbsent)) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->certBasicConstraints == NULL) &&
+ (!cert->basicConstraintsAbsent)) {
+
+ nssCert = cert->nssCert;
+
+ PKIX_CERT_DEBUG(
+ "\t\tCalling Cert_FindBasicConstraintExten\n");
+ rv = CERT_FindBasicConstraintExten
+ (nssCert, &nssBasicConstraint);
+ if (rv == SECSuccess) {
+ constraintSource = realBC;
+ }
+
+ if (constraintSource == absentBC) {
+ /* can we deduce it's a CA and create a
+ synthetic constraint?
+ */
+ CERTCertTrust trust;
+ rv = CERT_GetCertTrust(nssCert, &trust);
+ if (rv == SECSuccess) {
+ int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_VALID_CA;
+ if ((trust.sslFlags & anyWantedFlag)
+ || (trust.emailFlags & anyWantedFlag)
+ || (trust.objectSigningFlags & anyWantedFlag)) {
+
+ constraintSource = synthBC;
+ }
+ }
+ }
+
+ if (constraintSource == absentBC) {
+ cert->basicConstraintsAbsent = PKIX_TRUE;
+ *pBasicConstraints = NULL;
+ goto cleanup;
+ }
+ }
+
+ if (constraintSource == synthBC) {
+ isCA = PKIX_TRUE;
+ pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT;
+ } else {
+ isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE;
+
+ /* The pathLen has meaning only for CAs */
+ if (isCA) {
+ if (CERT_UNLIMITED_PATH_CONSTRAINT ==
+ nssBasicConstraint.pathLenConstraint) {
+ pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT;
+ } else {
+ pathLen = nssBasicConstraint.pathLenConstraint;
+ }
+ }
+ }
+
+ PKIX_CHECK(pkix_pl_CertBasicConstraints_Create
+ (isCA, pathLen, &basic, plContext),
+ PKIX_CERTBASICCONSTRAINTSCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->certBasicConstraints = basic;
+ }
+
+ PKIX_INCREF(cert->certBasicConstraints);
+ *pBasicConstraints = cert->certBasicConstraints;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetPolicyInformation
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetPolicyInformation(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pPolicyInfo,
+ void *plContext)
+{
+ PKIX_List *policyList = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->certPolicyInfos == NULL) &&
+ (!cert->policyInfoAbsent)) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->certPolicyInfos == NULL) &&
+ (!cert->policyInfoAbsent)) {
+
+ PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo
+ (cert->nssCert, &policyList, plContext),
+ PKIX_CERTDECODEPOLICYINFOFAILED);
+
+ if (!policyList) {
+ cert->policyInfoAbsent = PKIX_TRUE;
+ *pPolicyInfo = NULL;
+ goto cleanup;
+ }
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+
+ /* save a cached copy in case it is asked for again */
+ cert->certPolicyInfos = policyList;
+ policyList = NULL;
+ }
+
+ PKIX_INCREF(cert->certPolicyInfos);
+ *pPolicyInfo = cert->certPolicyInfos;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+
+ PKIX_DECREF(policyList);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetPolicyMappings(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */
+ void *plContext)
+{
+ PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (!(cert->certPolicyMappings) &&
+ !(cert->policyMappingsAbsent)) {
+
+ PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping
+ (cert->nssCert, &policyMappings, plContext),
+ PKIX_CERTDECODEPOLICYMAPPINGFAILED);
+
+ if (!policyMappings) {
+ cert->policyMappingsAbsent = PKIX_TRUE;
+ *pPolicyMappings = NULL;
+ goto cleanup;
+ }
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+
+ /* save a cached copy in case it is asked for again */
+ cert->certPolicyMappings = policyMappings;
+ policyMappings = NULL;
+ }
+
+ PKIX_INCREF(cert->certPolicyMappings);
+ *pPolicyMappings = cert->certPolicyMappings;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+
+ PKIX_DECREF(policyMappings);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetRequireExplicitPolicy(
+ PKIX_PL_Cert *cert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext)
+{
+ PKIX_Int32 explicitPolicySkipCerts = 0;
+ PKIX_Int32 inhibitMappingSkipCerts = 0;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
+
+ if (!(cert->policyConstraintsProcessed)) {
+ PKIX_OBJECT_LOCK(cert);
+
+ if (!(cert->policyConstraintsProcessed)) {
+
+ /*
+ * If we can't process it now, we probably will be
+ * unable to process it later. Set the default value.
+ */
+ cert->policyConstraintsProcessed = PKIX_TRUE;
+ cert->policyConstraintsExplicitPolicySkipCerts = -1;
+ cert->policyConstraintsInhibitMappingSkipCerts = -1;
+
+ PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
+ (cert->nssCert,
+ &explicitPolicySkipCerts,
+ &inhibitMappingSkipCerts,
+ plContext),
+ PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
+
+ cert->policyConstraintsExplicitPolicySkipCerts =
+ explicitPolicySkipCerts;
+ cert->policyConstraintsInhibitMappingSkipCerts =
+ inhibitMappingSkipCerts;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetPolicyMappingInhibited(
+ PKIX_PL_Cert *cert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext)
+{
+ PKIX_Int32 explicitPolicySkipCerts = 0;
+ PKIX_Int32 inhibitMappingSkipCerts = 0;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
+
+ if (!(cert->policyConstraintsProcessed)) {
+ PKIX_OBJECT_LOCK(cert);
+
+ if (!(cert->policyConstraintsProcessed)) {
+
+ /*
+ * If we can't process it now, we probably will be
+ * unable to process it later. Set the default value.
+ */
+ cert->policyConstraintsProcessed = PKIX_TRUE;
+ cert->policyConstraintsExplicitPolicySkipCerts = -1;
+ cert->policyConstraintsInhibitMappingSkipCerts = -1;
+
+ PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
+ (cert->nssCert,
+ &explicitPolicySkipCerts,
+ &inhibitMappingSkipCerts,
+ plContext),
+ PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
+
+ cert->policyConstraintsExplicitPolicySkipCerts =
+ explicitPolicySkipCerts;
+ cert->policyConstraintsInhibitMappingSkipCerts =
+ inhibitMappingSkipCerts;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetInhibitAnyPolicy(
+ PKIX_PL_Cert *cert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext)
+{
+ PKIX_Int32 skipCerts = 0;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
+
+ if (!(cert->inhibitAnyPolicyProcessed)) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (!(cert->inhibitAnyPolicyProcessed)) {
+
+ /*
+ * If we can't process it now, we probably will be
+ * unable to process it later. Set the default value.
+ */
+ cert->inhibitAnyPolicyProcessed = PKIX_TRUE;
+ cert->inhibitAnySkipCerts = -1;
+
+ PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy
+ (cert->nssCert, &skipCerts, plContext),
+ PKIX_CERTDECODEINHIBITANYPOLICYFAILED);
+
+ cert->inhibitAnySkipCerts = skipCerts;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ *pSkipCerts = cert->inhibitAnySkipCerts;
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_AreCertPoliciesCritical(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pCritical,
+ void *plContext)
+{
+ PKIX_Boolean criticality = PKIX_FALSE;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical");
+ PKIX_NULLCHECK_TWO(cert, pCritical);
+
+ PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical(
+ cert,
+ SEC_OID_X509_CERTIFICATE_POLICIES,
+ &criticality,
+ plContext),
+ PKIX_CERTISEXTENSIONCRITICALFAILED);
+
+ *pCritical = criticality;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_VerifySignature(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_PublicKey *pubKey,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ SECKEYPublicKey *nssPubKey = NULL;
+ CERTSignedData *tbsCert = NULL;
+ PKIX_PL_Cert *cachedCert = NULL;
+ PKIX_Error *verifySig = NULL;
+ PKIX_Error *cachedSig = NULL;
+ PKIX_Error *checkSig = NULL;
+ SECStatus status;
+ PKIX_Boolean certEqual = PKIX_FALSE;
+ PKIX_Boolean certInHash = PKIX_FALSE;
+ PKIX_Boolean checkCertSig = PKIX_TRUE;
+ void* wincx = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey);
+
+ /* if the cert check flag is off, skip the check */
+ checkSig = pkix_pl_NssContext_GetCertSignatureCheck(
+ (PKIX_PL_NssContext *)plContext, &checkCertSig);
+ if ((checkCertSig == PKIX_FALSE) && (checkSig == NULL)) {
+ goto cleanup;
+ }
+
+ verifySig = PKIX_PL_HashTable_Lookup
+ (cachedCertSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object **) &cachedCert,
+ plContext);
+
+ if (cachedCert != NULL && verifySig == NULL) {
+ /* Cached Signature Table lookup succeed */
+ PKIX_EQUALS(cert, cachedCert, &certEqual, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ if (certEqual == PKIX_TRUE) {
+ goto cleanup;
+ }
+ /* Different PubKey may hash to same value, skip add */
+ certInHash = PKIX_TRUE;
+ }
+
+ nssCert = cert->nssCert;
+ tbsCert = &nssCert->signatureWrap;
+
+ PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n");
+ nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
+ if (!nssPubKey){
+ PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
+ }
+
+ PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n");
+
+ PKIX_CHECK(pkix_pl_NssContext_GetWincx
+ ((PKIX_PL_NssContext *)plContext, &wincx),
+ PKIX_NSSCONTEXTGETWINCXFAILED);
+
+ status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx);
+
+ if (status != SECSuccess) {
+ if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ }
+ PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
+ }
+
+ if (certInHash == PKIX_FALSE) {
+ cachedSig = PKIX_PL_HashTable_Add
+ (cachedCertSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object *) cert,
+ plContext);
+
+ if (cachedSig != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
+ }
+ }
+
+cleanup:
+ if (nssPubKey){
+ PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n");
+ SECKEY_DestroyPublicKey(nssPubKey);
+ }
+
+ PKIX_DECREF(cachedCert);
+ PKIX_DECREF(checkSig);
+ PKIX_DECREF(verifySig);
+ PKIX_DECREF(cachedSig);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_CheckValidity(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date *date,
+ void *plContext)
+{
+ SECCertTimeValidity val;
+ PRTime timeToCheck;
+ PKIX_Boolean allowOverride;
+ SECCertificateUsage requiredUsages;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity");
+ PKIX_NULLCHECK_ONE(cert);
+
+ /* if the caller supplies a date, we use it; else, use current time */
+ if (date != NULL){
+ PKIX_CHECK(pkix_pl_Date_GetPRTime
+ (date, &timeToCheck, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ } else {
+ timeToCheck = PR_Now();
+ }
+
+ requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
+ allowOverride =
+ (PRBool)((requiredUsages & certificateUsageSSLServer) ||
+ (requiredUsages & certificateUsageSSLServerWithStepUp) ||
+ (requiredUsages & certificateUsageIPsec));
+ val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride);
+ if (val != secCertTimeValid){
+ PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED);
+ }
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetValidityNotAfter(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PRTime prtime;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter");
+ PKIX_NULLCHECK_TWO(cert, pDate);
+
+ PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n");
+ rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter));
+ if (rv != SECSuccess){
+ PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED);
+ }
+
+ PKIX_CHECK(pkix_pl_Date_CreateFromPRTime
+ (prtime, pDate, plContext),
+ PKIX_DATECREATEFROMPRTIMEFAILED);
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_VerifyCertAndKeyType(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean isChainCert,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ SECCertificateUsage certificateUsage;
+ SECCertUsage certUsage = 0;
+ unsigned int requiredKeyUsage;
+ unsigned int requiredCertType;
+ unsigned int certType;
+ SECStatus rv = SECSuccess;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType");
+ PKIX_NULLCHECK_TWO(cert, plContext);
+
+ certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
+
+ /* ensure we obtained a single usage bit only */
+ PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
+
+ /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
+ while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
+
+ /* check key usage and netscape cert type */
+ cert_GetCertType(cert->nssCert);
+ certType = cert->nssCert->nsCertType;
+ if (isChainCert ||
+ (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) {
+ rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert,
+ &requiredKeyUsage,
+ &requiredCertType);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE);
+ }
+ } else {
+ /* use this key usage and cert type for certUsageAnyCA and
+ * certUsageVerifyCA. */
+ requiredKeyUsage = KU_KEY_CERT_SIGN;
+ requiredCertType = NS_CERT_TYPE_CA;
+ }
+ if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
+ }
+ if (!(certType & requiredCertType)) {
+ PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED);
+ }
+cleanup:
+ PKIX_DECREF(basicConstraints);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_VerifyKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 keyUsage,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ PKIX_UInt32 nssKeyUsage = 0;
+ SECStatus status;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage");
+ PKIX_NULLCHECK_TWO(cert, cert->nssCert);
+
+ nssCert = cert->nssCert;
+
+ /* if cert doesn't have keyUsage extension, all keyUsages are valid */
+ if (!nssCert->keyUsagePresent){
+ goto cleanup;
+ }
+
+ if (keyUsage & PKIX_DIGITAL_SIGNATURE){
+ nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE;
+ }
+
+ if (keyUsage & PKIX_NON_REPUDIATION){
+ nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION;
+ }
+
+ if (keyUsage & PKIX_KEY_ENCIPHERMENT){
+ nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT;
+ }
+
+ if (keyUsage & PKIX_DATA_ENCIPHERMENT){
+ nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT;
+ }
+
+ if (keyUsage & PKIX_KEY_AGREEMENT){
+ nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT;
+ }
+
+ if (keyUsage & PKIX_KEY_CERT_SIGN){
+ nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN;
+ }
+
+ if (keyUsage & PKIX_CRL_SIGN){
+ nssKeyUsage = nssKeyUsage | KU_CRL_SIGN;
+ }
+
+ if (keyUsage & PKIX_ENCIPHER_ONLY){
+ nssKeyUsage = nssKeyUsage | 0x01;
+ }
+
+ if (keyUsage & PKIX_DECIPHER_ONLY){
+ /* XXX we should support this once it is fixed in NSS */
+ PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED);
+ }
+
+ status = CERT_CheckKeyUsage(nssCert, nssKeyUsage);
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
+ }
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetNameConstraints
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetNameConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->nameConstraints == NULL &&
+ !cert->nameConstraintsAbsent) {
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_Create
+ (cert->nssCert, &nameConstraints, plContext),
+ PKIX_CERTNAMECONSTRAINTSCREATEFAILED);
+
+ if (nameConstraints == NULL) {
+ cert->nameConstraintsAbsent = PKIX_TRUE;
+ }
+
+ cert->nameConstraints = nameConstraints;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+
+ }
+
+ PKIX_INCREF(cert->nameConstraints);
+
+ *pNameConstraints = cert->nameConstraints;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_CheckNameConstraints
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_CheckNameConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean treatCommonNameAsDNSName,
+ void *plContext)
+{
+ PKIX_Boolean checkPass = PKIX_TRUE;
+ CERTGeneralName *nssSubjectNames = NULL;
+ PLArenaPool *arena = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints");
+ PKIX_NULLCHECK_ONE(cert);
+
+ if (nameConstraints != NULL) {
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ /* only check common Name if the usage requires it */
+ if (treatCommonNameAsDNSName) {
+ SECCertificateUsage certificateUsage;
+ certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
+ if ((certificateUsage != certificateUsageSSLServer) &&
+ (certificateUsage != certificateUsageIPsec)) {
+ treatCommonNameAsDNSName = PKIX_FALSE;
+ }
+ }
+
+ /* This NSS call returns Subject Alt Names. If
+ * treatCommonNameAsDNSName is true, it also returns the
+ * Subject Common Name
+ */
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_GetConstrainedCertificateNames\n");
+ nssSubjectNames = CERT_GetConstrainedCertificateNames
+ (cert->nssCert, arena, treatCommonNameAsDNSName);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames
+ (nssSubjectNames,
+ nameConstraints,
+ &checkPass,
+ plContext),
+ PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED);
+
+ if (checkPass != PKIX_TRUE) {
+ PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING);
+ }
+ }
+
+cleanup:
+ if (arena){
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_MergeNameConstraints
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_MergeNameConstraints(
+ PKIX_PL_CertNameConstraints *firstNC,
+ PKIX_PL_CertNameConstraints *secondNC,
+ PKIX_PL_CertNameConstraints **pResultNC,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *mergedNC = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints");
+ PKIX_NULLCHECK_TWO(firstNC, pResultNC);
+
+ if (secondNC == NULL) {
+
+ PKIX_INCREF(firstNC);
+ *pResultNC = firstNC;
+
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_Merge
+ (firstNC, secondNC, &mergedNC, plContext),
+ PKIX_CERTNAMECONSTRAINTSMERGEFAILED);
+
+ *pResultNC = mergedNC;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * Find out the state of the NSS trust bits for the requested usage.
+ * Returns SECFailure if the cert is explicitly distrusted.
+ * Returns SECSuccess if the cert can be used to form a chain (normal case),
+ * or it is explicitly trusted. The trusted bool is set to true if it is
+ * explicitly trusted.
+ */
+static SECStatus
+pkix_pl_Cert_GetTrusted(void *plContext,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *trusted,
+ PKIX_Boolean isCA)
+{
+ SECStatus rv;
+ CERTCertificate *nssCert = NULL;
+ SECCertUsage certUsage = 0;
+ SECCertificateUsage certificateUsage;
+ SECTrustType trustType;
+ unsigned int trustFlags;
+ unsigned int requiredFlags;
+ CERTCertTrust trust;
+
+ *trusted = PKIX_FALSE;
+
+ /* no key usage information */
+ if (plContext == NULL) {
+ return SECSuccess;
+ }
+
+ certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
+
+ /* ensure we obtained a single usage bit only */
+ PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
+
+ /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
+ while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
+
+ nssCert = cert->nssCert;
+
+ if (!isCA) {
+ PRBool prTrusted;
+ unsigned int failedFlags;
+ rv = cert_CheckLeafTrust(nssCert, certUsage,
+ &failedFlags, &prTrusted);
+ *trusted = (PKIX_Boolean) prTrusted;
+ return rv;
+ }
+ rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
+ &trustType);
+ if (rv != SECSuccess) {
+ return SECSuccess;
+ }
+
+ rv = CERT_GetCertTrust(nssCert, &trust);
+ if (rv != SECSuccess) {
+ return SECSuccess;
+ }
+ trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
+ /* normally trustTypeNone usages accept any of the given trust bits
+ * being on as acceptable. If any are distrusted (and none are trusted),
+ * then we will also distrust the cert */
+ if ((trustFlags == 0) && (trustType == trustTypeNone)) {
+ trustFlags = trust.sslFlags | trust.emailFlags |
+ trust.objectSigningFlags;
+ }
+ if ((trustFlags & requiredFlags) == requiredFlags) {
+ *trusted = PKIX_TRUE;
+ return SECSuccess;
+ }
+ if ((trustFlags & CERTDB_TERMINAL_RECORD) &&
+ ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) {
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_IsCertTrusted
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_IsCertTrusted(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_TrustAnchorMode trustAnchorMode,
+ PKIX_Boolean *pTrusted,
+ void *plContext)
+{
+ PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted");
+ PKIX_NULLCHECK_TWO(cert, pTrusted);
+
+ /* Call GetTrusted first to see if we are going to distrust the
+ * certificate */
+ rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE);
+ if (rv != SECSuccess) {
+ /* Failure means the cert is explicitly distrusted,
+ * let the next level know not to use it. */
+ *pTrusted = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED);
+ }
+
+ if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive ||
+ (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive &&
+ cert->isUserTrustAnchor)) {
+ /* Use the trust anchor's |trusted| value */
+ *pTrusted = cert->isUserTrustAnchor;
+ goto cleanup;
+ }
+
+ /* no key usage information or store is not trusted */
+ if (plContext == NULL || cert->store == NULL) {
+ *pTrusted = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_CertStore_GetTrustCallback
+ (cert->store, &trustCallback, plContext),
+ PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(trustCallback
+ (cert->store, cert, &trusted, plContext),
+ PKIX_CHECKTRUSTCALLBACKFAILED);
+
+ /* allow trust store to override if we can trust the trust
+ * bits */
+ if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) {
+ *pTrusted = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ *pTrusted = trusted;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_IsLeafCertTrusted(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pTrusted,
+ void *plContext)
+{
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted");
+ PKIX_NULLCHECK_TWO(cert, pTrusted);
+
+ *pTrusted = PKIX_FALSE;
+
+ rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE);
+ if (rv != SECSuccess) {
+ /* Failure means the cert is explicitly distrusted,
+ * let the next level know not to use it. */
+ *pTrusted = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED);
+ }
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */
+PKIX_Error*
+PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor");
+ PKIX_NULLCHECK_ONE(cert);
+
+ cert->isUserTrustAnchor = PKIX_TRUE;
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCacheFlag(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pCacheFlag,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag");
+ PKIX_NULLCHECK_TWO(cert, pCacheFlag);
+
+ *pCacheFlag = cert->cacheFlag;
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_SetCacheFlag(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean cacheFlag,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag");
+ PKIX_NULLCHECK_ONE(cert);
+
+ cert->cacheFlag = cacheFlag;
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetTrustCertStore(
+ PKIX_PL_Cert *cert,
+ PKIX_CertStore **pTrustCertStore,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore");
+ PKIX_NULLCHECK_TWO(cert, pTrustCertStore);
+
+ PKIX_INCREF(cert->store);
+ *pTrustCertStore = cert->store;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_SetTrustCertStore(
+ PKIX_PL_Cert *cert,
+ PKIX_CertStore *trustCertStore,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore");
+ PKIX_NULLCHECK_TWO(cert, trustCertStore);
+
+ PKIX_INCREF(trustCertStore);
+ cert->store = trustCertStore;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetAuthorityInfoAccess(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */
+ void *plContext)
+{
+ PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */
+ SECItem *encodedAIA = NULL;
+ CERTAuthInfoAccess **aia = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->authorityInfoAccess == NULL) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->authorityInfoAccess == NULL) {
+
+ PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem,
+ (NULL, NULL, 0));
+
+ if (encodedAIA == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
+ (cert->nssCert,
+ SEC_OID_X509_AUTH_INFO_ACCESS,
+ encodedAIA));
+
+ if (rv == SECFailure) {
+ goto cleanup;
+ }
+
+ PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
+ (DER_DEFAULT_CHUNKSIZE));
+
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_PL_NSSCALLRV
+ (CERT, aia, CERT_DecodeAuthInfoAccessExtension,
+ (arena, encodedAIA));
+
+ PKIX_CHECK(pkix_pl_InfoAccess_CreateList
+ (aia, &aiaList, plContext),
+ PKIX_INFOACCESSCREATELISTFAILED);
+
+ cert->authorityInfoAccess = aiaList;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->authorityInfoAccess);
+
+ *pAiaList = cert->authorityInfoAccess;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (arena != NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ if (encodedAIA != NULL) {
+ SECITEM_FreeItem(encodedAIA, PR_TRUE);
+ }
+
+ PKIX_RETURN(CERT);
+}
+
+/* XXX Following defines belongs to NSS */
+static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x0b};
+#define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectInfoAccess(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */
+ void *plContext)
+{
+ PKIX_List *siaList; /* of PKIX_PL_InfoAccess */
+ SECItem siaOID = OI(siaOIDString);
+ SECItem *encodedSubjInfoAccess = NULL;
+ CERTAuthInfoAccess **subjInfoAccess = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList);
+
+ /* XXX
+ * Codes to deal with SubjectInfoAccess OID should be moved to
+ * NSS soon. I implemented them here so we don't touch NSS
+ * source tree, from JP's suggestion.
+ */
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->subjectInfoAccess == NULL) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->subjectInfoAccess == NULL) {
+
+ encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
+ if (encodedSubjInfoAccess == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_FindCertExtensionByOID).\n");
+ rv = CERT_FindCertExtensionByOID
+ (cert->nssCert, &siaOID, encodedSubjInfoAccess);
+
+ if (rv == SECFailure) {
+ goto cleanup;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ /* XXX
+ * Decode Subject Information Access -
+ * since its type is the same as Authority Information
+ * Access, reuse the call. NSS- change name to avoid
+ * confusion.
+ */
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n");
+ subjInfoAccess = CERT_DecodeAuthInfoAccessExtension
+ (arena, encodedSubjInfoAccess);
+
+ PKIX_CHECK(pkix_pl_InfoAccess_CreateList
+ (subjInfoAccess, &siaList, plContext),
+ PKIX_INFOACCESSCREATELISTFAILED);
+
+ cert->subjectInfoAccess = siaList;
+
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->subjectInfoAccess);
+ *pSiaList = cert->subjectInfoAccess;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (arena != NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ if (encodedSubjInfoAccess != NULL) {
+ SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE);
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCrlDp
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCrlDp(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pDpList,
+ void *plContext)
+{
+ PKIX_UInt32 dpIndex = 0;
+ pkix_pl_CrlDp *dp = NULL;
+ CERTCrlDistributionPoints *dpoints = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->crldpList == NULL) {
+ PKIX_OBJECT_LOCK(cert);
+ if (cert->crldpList != NULL) {
+ goto cleanup;
+ }
+ PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext),
+ PKIX_LISTCREATEFAILED);
+ dpoints = CERT_FindCRLDistributionPoints(cert->nssCert);
+ if (!dpoints || !dpoints->distPoints) {
+ goto cleanup;
+ }
+ for (;dpoints->distPoints[dpIndex];dpIndex++) {
+ PKIX_CHECK(
+ pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex],
+ &cert->nssCert->issuer,
+ &dp, plContext),
+ PKIX_CRLDPCREATEFAILED);
+ /* Create crldp list in reverse order in attempt to get
+ * to the whole crl first. */
+ PKIX_CHECK(
+ PKIX_List_InsertItem(cert->crldpList, 0,
+ (PKIX_PL_Object*)dp,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(dp);
+ }
+ }
+cleanup:
+ PKIX_INCREF(cert->crldpList);
+ *pDpList = cert->crldpList;
+
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_DECREF(dp);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCERTCertificate
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCERTCertificate(
+ PKIX_PL_Cert *cert,
+ CERTCertificate **pnssCert,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert");
+ PKIX_NULLCHECK_TWO(cert, pnssCert);
+
+ *pnssCert = CERT_DupCertificate(cert->nssCert);
+
+ PKIX_RETURN(CERT);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h
new file mode 100644
index 0000000000..56fe64228d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h
@@ -0,0 +1,107 @@
+/* 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/. */
+/*
+ * pkix_pl_cert.h
+ *
+ * Certificate Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_CERT_H
+#define _PKIX_PL_CERT_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_CertStruct {
+ CERTCertificate *nssCert; /* Must be the first field. The
+ * cert_NSSCertFromPKIXCert function in
+ * lib/certhigh/certvfypkix.c depends on
+ * this. */
+ CERTGeneralName *nssSubjAltNames;
+ PLArenaPool *arenaNameConstraints;
+ PKIX_PL_X500Name *issuer;
+ PKIX_PL_X500Name *subject;
+ PKIX_List *subjAltNames;
+ PKIX_Boolean subjAltNamesAbsent;
+ PKIX_PL_OID *publicKeyAlgId;
+ PKIX_PL_PublicKey *publicKey;
+ PKIX_PL_BigInt *serialNumber;
+ PKIX_List *critExtOids;
+ PKIX_PL_ByteArray *subjKeyId;
+ PKIX_Boolean subjKeyIdAbsent;
+ PKIX_PL_ByteArray *authKeyId;
+ PKIX_Boolean authKeyIdAbsent;
+ PKIX_List *extKeyUsages;
+ PKIX_Boolean extKeyUsagesAbsent;
+ PKIX_PL_CertBasicConstraints *certBasicConstraints;
+ PKIX_Boolean basicConstraintsAbsent;
+ PKIX_List *certPolicyInfos;
+ PKIX_Boolean policyInfoAbsent;
+ PKIX_Boolean policyMappingsAbsent;
+ PKIX_List *certPolicyMappings; /* List of PKIX_PL_CertPolicyMap */
+ PKIX_Boolean policyConstraintsProcessed;
+ PKIX_Int32 policyConstraintsExplicitPolicySkipCerts;
+ PKIX_Int32 policyConstraintsInhibitMappingSkipCerts;
+ PKIX_Boolean inhibitAnyPolicyProcessed;
+ PKIX_Int32 inhibitAnySkipCerts;
+ PKIX_PL_CertNameConstraints *nameConstraints;
+ PKIX_Boolean nameConstraintsAbsent;
+ PKIX_Boolean cacheFlag;
+ PKIX_CertStore *store;
+ PKIX_List *authorityInfoAccess; /* list of PKIX_PL_InfoAccess */
+ PKIX_List *subjectInfoAccess; /* list of PKIX_PL_InfoAccess */
+ PKIX_Boolean isUserTrustAnchor;
+ PKIX_List *crldpList; /* list of CRL DPs based on der in nssCert arena.
+ * Destruction is needed for pkix object and
+ * not for undelying der as it is a part
+ * nssCert arena. */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_Cert_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_CreateWithNSSCert(
+ CERTCertificate *nssCert,
+ PKIX_PL_Cert **pCert,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_CreateToList(
+ SECItem *derCertItem,
+ PKIX_List *certList,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_CheckSubjectAltNameConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean matchAll,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_ToString_Helper(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean partialString,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_CheckExtendedKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 requiredExtendedKeyUsages,
+ PKIX_Boolean *pPass,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CERT_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c
new file mode 100644
index 0000000000..a44ac65900
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c
@@ -0,0 +1,371 @@
+/* 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/. */
+/*
+ * pkix_pl_certpolicyinfo.c
+ *
+ * CertPolicyInfo Type Functions
+ *
+ */
+
+#include "pkix_pl_certpolicyinfo.h"
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CertPolicyInfo Object using the OID pointed to by "oid" and
+ * the List of CertPolicyQualifiers pointed to by "qualifiers", and stores it
+ * at "pObject". If a non-NULL list is provided, the caller is expected to
+ * have already set it to be immutable. The caller may provide an empty List,
+ * but a NULL List is preferable so a user does not need to call
+ * List_GetLength to get the number of qualifiers.
+ *
+ * PARAMETERS
+ * "oid"
+ * OID of the desired PolicyInfo ID; must be non-NULL
+ * "qualifiers"
+ * List of CertPolicyQualifiers; may be NULL or empty
+ * "pObject"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyInfo_Create(
+ PKIX_PL_OID *oid,
+ PKIX_List *qualifiers,
+ PKIX_PL_CertPolicyInfo **pObject,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *policyInfo = NULL;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Create");
+
+ PKIX_NULLCHECK_TWO(oid, pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYINFO_TYPE,
+ sizeof (PKIX_PL_CertPolicyInfo),
+ (PKIX_PL_Object **)&policyInfo,
+ plContext),
+ PKIX_COULDNOTCREATECERTPOLICYINFOOBJECT);
+
+ PKIX_INCREF(oid);
+ policyInfo->cpID = oid;
+
+ PKIX_INCREF(qualifiers);
+ policyInfo->policyQualifiers = qualifiers;
+
+ *pObject = policyInfo;
+ policyInfo = NULL;
+
+cleanup:
+ PKIX_DECREF(policyInfo);
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyInfo_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *certPI = NULL;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYINFO_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYINFO);
+
+ certPI = (PKIX_PL_CertPolicyInfo*)object;
+
+ PKIX_DECREF(certPI->cpID);
+ PKIX_DECREF(certPI->policyQualifiers);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyInfo_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *certPI = NULL;
+ PKIX_PL_String *oidString = NULL;
+ PKIX_PL_String *listString = NULL;
+ PKIX_PL_String *format = NULL;
+ PKIX_PL_String *outString = NULL;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYINFO_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYINFO);
+
+ certPI = (PKIX_PL_CertPolicyInfo *)object;
+
+ PKIX_NULLCHECK_ONE(certPI->cpID);
+
+ PKIX_TOSTRING
+ (certPI->cpID,
+ &oidString,
+ plContext,
+ PKIX_OIDTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (certPI->policyQualifiers,
+ &listString,
+ plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Put them together in the form OID[Qualifiers] */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s[%s]", 0, &format, plContext),
+ PKIX_ERRORINSTRINGCREATE);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString, plContext, format, oidString, listString),
+ PKIX_ERRORINSPRINTF);
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(oidString);
+ PKIX_DECREF(listString);
+ PKIX_DECREF(format);
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyInfo_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *certPI = NULL;
+ PKIX_UInt32 oidHash = 0;
+ PKIX_UInt32 listHash = 0;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Hashcode");
+
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYINFO_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYINFO);
+
+ certPI = (PKIX_PL_CertPolicyInfo *)object;
+
+ PKIX_NULLCHECK_ONE(certPI->cpID);
+
+ PKIX_HASHCODE
+ (certPI->cpID,
+ &oidHash,
+ plContext,
+ PKIX_ERRORINOIDHASHCODE);
+
+ PKIX_HASHCODE
+ (certPI->policyQualifiers,
+ &listHash,
+ plContext,
+ PKIX_ERRORINLISTHASHCODE);
+
+ *pHashcode = (31 * oidHash) + listHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyInfo_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *firstCPI = NULL;
+ PKIX_PL_CertPolicyInfo *secondCPI = NULL;
+ PKIX_UInt32 secondType = 0;
+ PKIX_Boolean compare = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertPolicyInfo */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTPOLICYINFO_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTPOLICYINFO);
+
+ /*
+ * Since we know firstObject is a CertPolicyInfo,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a CertPolicyInfo, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERTPOLICYINFO_TYPE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ firstCPI = (PKIX_PL_CertPolicyInfo *)firstObject;
+ secondCPI = (PKIX_PL_CertPolicyInfo *)secondObject;
+
+ /*
+ * Compare the value of the OID components
+ */
+
+ PKIX_NULLCHECK_TWO(firstCPI->cpID, secondCPI->cpID);
+
+ PKIX_EQUALS
+ (firstCPI->cpID,
+ secondCPI->cpID,
+ &compare,
+ plContext,
+ PKIX_OIDEQUALSFAILED);
+
+ /*
+ * If the OIDs did not match, we don't need to
+ * compare the Lists. If the OIDs did match,
+ * the return value is the value of the
+ * List comparison.
+ */
+ if (compare) {
+ PKIX_EQUALS
+ (firstCPI->policyQualifiers,
+ secondCPI->policyQualifiers,
+ &compare,
+ plContext,
+ PKIX_LISTEQUALSFAILED);
+ }
+
+ *pResult = compare;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTPOLICYINFO_TYPE and its related
+ * functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyInfo_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_RegisterSelf");
+
+ entry.description = "CertPolicyInfo";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertPolicyInfo);
+ entry.destructor = pkix_pl_CertPolicyInfo_Destroy;
+ entry.equalsFunction = pkix_pl_CertPolicyInfo_Equals;
+ entry.hashcodeFunction = pkix_pl_CertPolicyInfo_Hashcode;
+ entry.toStringFunction = pkix_pl_CertPolicyInfo_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTPOLICYINFO_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/* --Public-CertPolicyInfo-Functions------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolicyId
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyInfo_GetPolicyId(
+ PKIX_PL_CertPolicyInfo *policyInfo,
+ PKIX_PL_OID **pPolicyId,
+ void *plContext)
+{
+ PKIX_ENTER(CERTPOLICYINFO, "PKIX_PL_CertPolicyInfo_GetPolicyId");
+
+ PKIX_NULLCHECK_TWO(policyInfo, pPolicyId);
+
+ PKIX_INCREF(policyInfo->cpID);
+
+ *pPolicyId = policyInfo->cpID;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolQualifiers
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyInfo_GetPolQualifiers(
+ PKIX_PL_CertPolicyInfo *policyInfo,
+ PKIX_List **pQuals,
+ void *plContext)
+{
+ PKIX_ENTER(CERTPOLICYINFO, "PKIX_PL_CertPolicyInfo_GetPolQualifiers");
+
+ PKIX_NULLCHECK_TWO(policyInfo, pQuals);
+
+ PKIX_INCREF(policyInfo->policyQualifiers);
+
+ /*
+ * This List is created in PKIX_PL_Cert_DecodePolicyInfo
+ * and is set immutable immediately after being created.
+ */
+ *pQuals = policyInfo->policyQualifiers;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYINFO);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h
new file mode 100644
index 0000000000..5c324e6cd2
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h
@@ -0,0 +1,50 @@
+/* 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/. */
+/*
+ * pkix_pl_certpolicyinfo.h
+ *
+ * PolicyInfo Type Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_POLICYINFO_H
+#define _PKIX_PL_POLICYINFO_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure reflects the contents of the policy info extension as
+ * described in Section 4.2.1.5 of RFC3280.
+ *
+ * PolicyInformation ::= SEQUENCE {
+ * policyIdentifier CertPolicyId,
+ * PolicyQualifiers SEQUENCE SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ *
+ */
+struct PKIX_PL_CertPolicyInfoStruct {
+ PKIX_PL_OID *cpID;
+ PKIX_List *policyQualifiers; /* LIST of PKIX_PL_CertPolicyQualifier */
+};
+
+PKIX_Error *
+pkix_pl_CertPolicyInfo_Create(
+ PKIX_PL_OID *oid,
+ PKIX_List *qualifiers,
+ PKIX_PL_CertPolicyInfo **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertPolicyInfo_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_POLICYINFO_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c
new file mode 100644
index 0000000000..08b1ca9df1
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c
@@ -0,0 +1,386 @@
+/* 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/. */
+/*
+ * pkix_pl_certpolicymap.c
+ *
+ * CertPolicyMap Type Functions
+ *
+ */
+
+#include "pkix_pl_certpolicymap.h"
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CertPolicyMap Object pairing the OID given by
+ * "issuerDomainPolicy" with the OID given by "subjectDomainPolicy", and
+ * stores the result at "pCertPolicyMap".
+ *
+ * PARAMETERS
+ * "issuerDomainPolicy"
+ * Address of the OID of the IssuerDomainPolicy. Must be non-NULL.
+ * "subjectDomainPolicy"
+ * Address of the OID of the SubjectDomainPolicy. Must be non-NULL.
+ * "pCertPolicyMap"
+ * Address where CertPolicyMap pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertPolicyMap Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyMap_Create(
+ PKIX_PL_OID *issuerDomainPolicy,
+ PKIX_PL_OID *subjectDomainPolicy,
+ PKIX_PL_CertPolicyMap **pCertPolicyMap,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *policyMap = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Create");
+
+ PKIX_NULLCHECK_THREE
+ (issuerDomainPolicy, subjectDomainPolicy, pCertPolicyMap);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYMAP_TYPE,
+ sizeof (PKIX_PL_CertPolicyMap),
+ (PKIX_PL_Object **)&policyMap,
+ plContext),
+ PKIX_COULDNOTCREATECERTPOLICYMAPOBJECT);
+
+ PKIX_INCREF(issuerDomainPolicy);
+ policyMap->issuerDomainPolicy = issuerDomainPolicy;
+
+ PKIX_INCREF(subjectDomainPolicy);
+ policyMap->subjectDomainPolicy = subjectDomainPolicy;
+
+ *pCertPolicyMap = policyMap;
+ policyMap = NULL;
+
+cleanup:
+ PKIX_DECREF(policyMap);
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *certMap = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYMAP);
+
+ certMap = (PKIX_PL_CertPolicyMap*)object;
+
+ PKIX_DECREF(certMap->issuerDomainPolicy);
+ PKIX_DECREF(certMap->subjectDomainPolicy);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *certMap = NULL;
+ PKIX_PL_String *format = NULL;
+ PKIX_PL_String *outString = NULL;
+ PKIX_PL_String *issuerString = NULL;
+ PKIX_PL_String *subjectString = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYMAP);
+
+ certMap = (PKIX_PL_CertPolicyMap *)object;
+
+ PKIX_TOSTRING
+ (certMap->issuerDomainPolicy,
+ &issuerString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (certMap->subjectDomainPolicy,
+ &subjectString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ /* Put them together in the form issuerPolicy=>subjectPolicy */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s=>%s", 0, &format, plContext),
+ PKIX_ERRORINSTRINGCREATE);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString, plContext, format, issuerString, subjectString),
+ PKIX_ERRORINSPRINTF);
+
+ *pString = outString;
+
+cleanup:
+ PKIX_DECREF(format);
+ PKIX_DECREF(issuerString);
+ PKIX_DECREF(subjectString);
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 issuerHash = 0;
+ PKIX_UInt32 subjectHash = 0;
+ PKIX_PL_CertPolicyMap *certMap = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Hashcode");
+
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYMAP);
+
+ certMap = (PKIX_PL_CertPolicyMap *)object;
+
+ PKIX_HASHCODE
+ (certMap->issuerDomainPolicy,
+ &issuerHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE
+ (certMap->subjectDomainPolicy,
+ &subjectHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ *pHashcode = issuerHash*31 + subjectHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *firstCertMap = NULL;
+ PKIX_PL_CertPolicyMap *secondCertMap = NULL;
+ PKIX_UInt32 secondType = 0;
+ PKIX_Boolean compare = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertPolicyMap */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTPOLICYMAP);
+
+ /*
+ * Since we know firstObject is a CertPolicyMap,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a CertPolicyMap, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERTPOLICYMAP_TYPE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ firstCertMap = (PKIX_PL_CertPolicyMap *)firstObject;
+ secondCertMap = (PKIX_PL_CertPolicyMap *)secondObject;
+
+ PKIX_EQUALS
+ (firstCertMap->issuerDomainPolicy,
+ secondCertMap->issuerDomainPolicy,
+ &compare,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (compare) {
+ PKIX_EQUALS
+ (firstCertMap->subjectDomainPolicy,
+ secondCertMap->subjectDomainPolicy,
+ &compare,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ }
+
+ *pResult = compare;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *original = NULL;
+ PKIX_PL_CertPolicyMap *copy = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Duplicate");
+
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_OBJECTARGUMENTNOTPOLICYMAP);
+
+ original = (PKIX_PL_CertPolicyMap *)object;
+
+ PKIX_CHECK(pkix_pl_CertPolicyMap_Create
+ (original->issuerDomainPolicy,
+ original->subjectDomainPolicy,
+ &copy,
+ plContext),
+ PKIX_CERTPOLICYMAPCREATEFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)copy;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTPOLICYMAP_TYPE and its related
+ * functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyMap_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_RegisterSelf");
+
+ entry.description = "CertPolicyMap";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertPolicyMap);
+ entry.destructor = pkix_pl_CertPolicyMap_Destroy;
+ entry.equalsFunction = pkix_pl_CertPolicyMap_Equals;
+ entry.hashcodeFunction = pkix_pl_CertPolicyMap_Hashcode;
+ entry.toStringFunction = pkix_pl_CertPolicyMap_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_pl_CertPolicyMap_Duplicate;
+
+ systemClasses[PKIX_CERTPOLICYMAP_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/* --Public-CertPolicyMap-Functions------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy(
+ PKIX_PL_CertPolicyMap *policyMapping,
+ PKIX_PL_OID **pIssuerDomainPolicy,
+ void *plContext)
+{
+ PKIX_ENTER
+ (CERTPOLICYMAP, "PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy");
+
+ PKIX_NULLCHECK_TWO(policyMapping, pIssuerDomainPolicy);
+
+ PKIX_INCREF(policyMapping->issuerDomainPolicy);
+ *pIssuerDomainPolicy = policyMapping->issuerDomainPolicy;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy(
+ PKIX_PL_CertPolicyMap *policyMapping,
+ PKIX_PL_OID **pSubjectDomainPolicy,
+ void *plContext)
+{
+ PKIX_ENTER
+ (CERTPOLICYMAP, "PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy");
+
+ PKIX_NULLCHECK_TWO(policyMapping, pSubjectDomainPolicy);
+
+ PKIX_INCREF(policyMapping->subjectDomainPolicy);
+ *pSubjectDomainPolicy = policyMapping->subjectDomainPolicy;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYMAP);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h
new file mode 100644
index 0000000000..a03bce2c8c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h
@@ -0,0 +1,49 @@
+/* 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/. */
+/*
+ * pkix_pl_certpolicymap.h
+ *
+ * CertPolicyMap Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_CERTPOLICYMAP_H
+#define _PKIX_PL_CERTPOLICYMAP_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure reflects the contents of the policy mapping extension as
+ * described in Section 4.2.1.6 of RFC3280.
+ *
+ * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+ * issuerDomainPolicy CertPolicyId,
+ * subjectDomainPolicy CertPolicyId }
+ *
+ */
+struct PKIX_PL_CertPolicyMapStruct {
+ PKIX_PL_OID *issuerDomainPolicy;
+ PKIX_PL_OID *subjectDomainPolicy;
+};
+
+PKIX_Error *
+pkix_pl_CertPolicyMap_Create(
+ PKIX_PL_OID *issuerDomainPolicy,
+ PKIX_PL_OID *subjectDomainPolicy,
+ PKIX_PL_CertPolicyMap **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertPolicyMap_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CERTPOLICYMAP_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c
new file mode 100644
index 0000000000..b57623d269
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c
@@ -0,0 +1,365 @@
+/* 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/. */
+/*
+ * pkix_pl_certpolicyqualifier.c
+ *
+ * CertPolicyQualifier Type Functions
+ *
+ */
+
+#include "pkix_pl_certpolicyqualifier.h"
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_Create
+ * DESCRIPTION:
+ *
+ * Creates a CertPolicyQualifier object with the OID given by "oid"
+ * and the ByteArray given by "qualifier", and stores it at "pObject".
+ *
+ * PARAMETERS
+ * "oid"
+ * Address of OID of the desired policyQualifierId; must be non-NULL
+ * "qualifier"
+ * Address of ByteArray with the desired value of the qualifier;
+ * must be non-NULL
+ * "pObject"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyQualifier_Create(
+ PKIX_PL_OID *oid,
+ PKIX_PL_ByteArray *qualifier,
+ PKIX_PL_CertPolicyQualifier **pObject,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *qual = NULL;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Create");
+
+ PKIX_NULLCHECK_THREE(oid, qualifier, pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYQUALIFIER_TYPE,
+ sizeof (PKIX_PL_CertPolicyQualifier),
+ (PKIX_PL_Object **)&qual,
+ plContext),
+ PKIX_COULDNOTCREATECERTPOLICYQUALIFIEROBJECT);
+
+ PKIX_INCREF(oid);
+ qual->policyQualifierId = oid;
+
+ PKIX_INCREF(qualifier);
+ qual->qualifier = qualifier;
+
+ *pObject = qual;
+ qual = NULL;
+
+cleanup:
+ PKIX_DECREF(qual);
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyQualifier_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *certPQ = NULL;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYQUALIFIER);
+
+ certPQ = (PKIX_PL_CertPolicyQualifier*)object;
+
+ PKIX_DECREF(certPQ->policyQualifierId);
+ PKIX_DECREF(certPQ->qualifier);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyQualifier_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *certPQ = NULL;
+ char *asciiFormat = "%s:%s";
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *pqIDString = NULL;
+ PKIX_PL_String *pqValString = NULL;
+ PKIX_PL_String *outString = NULL;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYQUALIFIER);
+
+ certPQ = (PKIX_PL_CertPolicyQualifier *)object;
+
+ /*
+ * The policyQualifierId is required. If there is no qualifier,
+ * we should have a ByteArray of zero length.
+ */
+ PKIX_NULLCHECK_TWO(certPQ->policyQualifierId, certPQ->qualifier);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING(certPQ->policyQualifierId, &pqIDString, plContext,
+ PKIX_OIDTOSTRINGFAILED);
+
+ PKIX_CHECK(pkix_pl_ByteArray_ToHexString
+ (certPQ->qualifier, &pqValString, plContext),
+ PKIX_BYTEARRAYTOHEXSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString, plContext, formatString, pqIDString, pqValString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(pqIDString);
+ PKIX_DECREF(pqValString);
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyQualifier_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *certPQ = NULL;
+ PKIX_UInt32 cpidHash = 0;
+ PKIX_UInt32 cpqHash = 0;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYQUALIFIER);
+
+ certPQ = (PKIX_PL_CertPolicyQualifier *)object;
+
+ PKIX_NULLCHECK_TWO(certPQ->policyQualifierId, certPQ->qualifier);
+
+ PKIX_HASHCODE(certPQ->policyQualifierId, &cpidHash, plContext,
+ PKIX_ERRORINOIDHASHCODE);
+
+ PKIX_HASHCODE(certPQ->qualifier, &cpqHash, plContext,
+ PKIX_ERRORINBYTEARRAYHASHCODE);
+
+ *pHashcode = cpidHash*31 + cpqHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyQualifier_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *firstCPQ = NULL;
+ PKIX_PL_CertPolicyQualifier *secondCPQ = NULL;
+ PKIX_UInt32 secondType = 0;
+ PKIX_Boolean compare = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertPolicyQualifier */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTPOLICYQUALIFIER);
+
+ /*
+ * Since we know firstObject is a CertPolicyQualifier,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a CertPolicyQualifier, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERTPOLICYQUALIFIER_TYPE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ firstCPQ = (PKIX_PL_CertPolicyQualifier *)firstObject;
+ secondCPQ = (PKIX_PL_CertPolicyQualifier *)secondObject;
+
+ /*
+ * Compare the value of the OID components
+ */
+
+ PKIX_NULLCHECK_TWO
+ (firstCPQ->policyQualifierId, secondCPQ->policyQualifierId);
+
+ PKIX_EQUALS
+ (firstCPQ->policyQualifierId,
+ secondCPQ->policyQualifierId,
+ &compare,
+ plContext,
+ PKIX_OIDEQUALSFAILED);
+
+ /*
+ * If the OIDs did not match, we don't need to
+ * compare the ByteArrays. If the OIDs did match,
+ * the return value is the value of the
+ * ByteArray comparison.
+ */
+ if (compare) {
+ PKIX_NULLCHECK_TWO(firstCPQ->qualifier, secondCPQ->qualifier);
+
+ PKIX_EQUALS
+ (firstCPQ->qualifier,
+ secondCPQ->qualifier,
+ &compare,
+ plContext,
+ PKIX_BYTEARRAYEQUALSFAILED);
+ }
+
+ *pResult = compare;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTPOLICYQUALIFIER_TYPE and its related
+ * functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyQualifier_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER,
+ "pkix_pl_CertPolicyQualifier_RegisterSelf");
+
+ entry.description = "CertPolicyQualifier";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertPolicyQualifier);
+ entry.destructor = pkix_pl_CertPolicyQualifier_Destroy;
+ entry.equalsFunction = pkix_pl_CertPolicyQualifier_Equals;
+ entry.hashcodeFunction = pkix_pl_CertPolicyQualifier_Hashcode;
+ entry.toStringFunction = pkix_pl_CertPolicyQualifier_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTPOLICYQUALIFIER_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/* --Public-CertPolicyQualifier-Functions------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_PolicyQualifier_GetPolicyQualifierId
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_PolicyQualifier_GetPolicyQualifierId(
+ PKIX_PL_CertPolicyQualifier *policyQualifierInfo,
+ PKIX_PL_OID **pPolicyQualifierId,
+ void *plContext)
+{
+ PKIX_ENTER(CERTPOLICYQUALIFIER,
+ "PKIX_PL_PolicyQualifier_GetPolicyQualifierId");
+
+ PKIX_NULLCHECK_TWO(policyQualifierInfo, pPolicyQualifierId);
+
+ PKIX_INCREF(policyQualifierInfo->policyQualifierId);
+
+ *pPolicyQualifierId = policyQualifierInfo->policyQualifierId;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: PKIX_PL_PolicyQualifier_GetQualifier
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_PolicyQualifier_GetQualifier(
+ PKIX_PL_CertPolicyQualifier *policyQualifierInfo,
+ PKIX_PL_ByteArray **pQualifier,
+ void *plContext)
+{
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "PKIX_PL_PolicyQualifier_GetQualifier");
+
+ PKIX_NULLCHECK_TWO(policyQualifierInfo, pQualifier);
+
+ PKIX_INCREF(policyQualifierInfo->qualifier);
+
+ *pQualifier = policyQualifierInfo->qualifier;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h
new file mode 100644
index 0000000000..4c6c8a21ba
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h
@@ -0,0 +1,52 @@
+/* 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/. */
+/*
+ * pkix_pl_certpolicyqualifier.h
+ *
+ * PolicyQualifier Type Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_POLICYQUALIFIER_H
+#define _PKIX_PL_POLICYQUALIFIER_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure reflects the contents of the policy qualifier extension as
+ * described in Section 4.2.1.5 of RFC3280.
+ *
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ *
+ * PolicyQualifierId ::=
+ * OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice)
+ *
+ */
+struct PKIX_PL_CertPolicyQualifierStruct {
+ PKIX_PL_OID *policyQualifierId;
+ PKIX_PL_ByteArray *qualifier;
+};
+
+PKIX_Error *
+pkix_pl_CertPolicyQualifier_Create(
+ PKIX_PL_OID *oid,
+ PKIX_PL_ByteArray *qualifierArray,
+ PKIX_PL_CertPolicyQualifier **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertPolicyQualifier_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_POLICYQUALIFIER_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c
new file mode 100644
index 0000000000..b83db357ac
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c
@@ -0,0 +1,1068 @@
+/* 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/. */
+/*
+ * pkix_pl_crl.c
+ *
+ * CRL Function Definitions
+ *
+ */
+
+#include "pkix_pl_crl.h"
+#include "certxutl.h"
+
+extern PKIX_PL_HashTable *cachedCrlSigTable;
+
+/* --Private-CRL-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_CRL_GetVersion
+ * DESCRIPTION:
+ *
+ * Retrieves the version of the CRL pointed to by "crl" and stores it at
+ * "pVersion". The version number will either be 0 or 1 (corresponding to
+ * v1 or v2, respectively).
+ *
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose version is to be stored. Must be non-NULL.
+ * "pVersion"
+ * Address where a version will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_GetVersion(
+ PKIX_PL_CRL *crl,
+ PKIX_UInt32 *pVersion,
+ void *plContext)
+{
+ PKIX_UInt32 myVersion;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_GetVersion");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pVersion);
+
+ PKIX_NULLCHECK_ONE(crl->nssSignedCrl->crl.version.data);
+
+ myVersion = *(crl->nssSignedCrl->crl.version.data);
+
+ if (myVersion > 1) {
+ PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1ORV2);
+ }
+
+ *pVersion = myVersion;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetCRLNumber (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetCRLNumber(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_BigInt **pCrlNumber,
+ void *plContext)
+{
+ PKIX_PL_BigInt *crlNumber = NULL;
+ SECItem nssCrlNumber;
+ PLArenaPool *arena = NULL;
+ SECStatus status;
+ PKIX_UInt32 length = 0;
+ char *bytes = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLNumber");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlNumber);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
+
+ PKIX_OBJECT_LOCK(crl);
+
+ if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
+
+ nssCrlNumber.type = 0;
+ nssCrlNumber.len = 0;
+ nssCrlNumber.data = NULL;
+
+ PKIX_CRL_DEBUG("\t\tCalling PORT_NewArena).\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CRL_DEBUG("\t\tCalling CERT_FindCRLNumberExten\n");
+ status = CERT_FindCRLNumberExten
+ (arena, &crl->nssSignedCrl->crl, &nssCrlNumber);
+
+ if (status == SECSuccess) {
+ /* Get data in bytes then convert to bigint */
+ length = nssCrlNumber.len;
+ bytes = (char *)nssCrlNumber.data;
+
+ PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
+ (bytes, length, &crlNumber, plContext),
+ PKIX_BIGINTCREATEWITHBYTESFAILED);
+
+ /* arena release does the job
+ PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n");
+ SECITEM_FreeItem(&nssCrlNumber, PKIX_FALSE);
+ */
+ crl->crlNumber = crlNumber;
+
+ } else {
+
+ crl->crlNumberAbsent = PKIX_TRUE;
+ }
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ PKIX_INCREF(crl->crlNumber);
+
+ *pCrlNumber = crl->crlNumber;
+
+cleanup:
+
+ if (arena){
+ PKIX_CRL_DEBUG("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_GetSignatureAlgId
+ *
+ * DESCRIPTION:
+ * Retrieves a pointer to the OID that represents the signature algorithm of
+ * the CRL pointed to by "crl" and stores it at "pSignatureAlgId".
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose signature algorithm OID is to be stored.
+ * Must be non-NULL.
+ * "pSignatureAlgId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_GetSignatureAlgId(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_OID **pSignatureAlgId,
+ void *plContext)
+{
+ PKIX_PL_OID *signatureAlgId = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->signatureAlgId == NULL){
+ PKIX_OBJECT_LOCK(crl);
+ if (crl->signatureAlgId == NULL){
+ CERTCrl *nssCrl = &(crl->nssSignedCrl->crl);
+ SECAlgorithmID *algorithm = &nssCrl->signatureAlg;
+ SECItem *algBytes = &algorithm->algorithm;
+
+ if (!algBytes->data || !algBytes->len) {
+ PKIX_ERROR(PKIX_OIDBYTESLENGTH0);
+ }
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (algBytes, &signatureAlgId, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ crl->signatureAlgId = signatureAlgId;
+ signatureAlgId = NULL;
+ }
+ PKIX_OBJECT_UNLOCK(crl);
+ }
+ PKIX_INCREF(crl->signatureAlgId);
+ *pSignatureAlgId = crl->signatureAlgId;
+cleanup:
+ PKIX_DECREF(signatureAlgId);
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_GetCRLEntries
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of CRLEntries found in the CRL pointed to
+ * by "crl" and stores it at "pCRLEntries". If there are no CRLEntries,
+ * this functions stores NULL at "pCRLEntries".
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose CRL Entries are to be retrieved. Must be non-NULL.
+ * "pCRLEntries"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_GetCRLEntries(
+ PKIX_PL_CRL *crl,
+ PKIX_List **pCrlEntries,
+ void *plContext)
+{
+ PKIX_List *entryList = NULL;
+ CERTCrl *nssCrl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_GetCRLEntries");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlEntries);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->crlEntryList == NULL) {
+
+ PKIX_OBJECT_LOCK(crl);
+
+ if (crl->crlEntryList == NULL){
+
+ nssCrl = &(crl->nssSignedCrl->crl);
+
+ PKIX_CHECK(pkix_pl_CRLEntry_Create
+ (nssCrl->entries, &entryList, plContext),
+ PKIX_CRLENTRYCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (entryList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ crl->crlEntryList = entryList;
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ PKIX_INCREF(crl->crlEntryList);
+
+ *pCrlEntries = crl->crlEntryList;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
+ PKIX_OBJECTNOTCRL);
+
+ crl = (PKIX_PL_CRL*)object;
+
+ PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n");
+ if (crl->nssSignedCrl) {
+ CERT_DestroyCrl(crl->nssSignedCrl);
+ }
+ if (crl->adoptedDerCrl) {
+ SECITEM_FreeItem(crl->adoptedDerCrl, PR_TRUE);
+ }
+ crl->nssSignedCrl = NULL;
+ crl->adoptedDerCrl = NULL;
+ crl->crlNumberAbsent = PKIX_FALSE;
+
+ PKIX_DECREF(crl->issuer);
+ PKIX_DECREF(crl->signatureAlgId);
+ PKIX_DECREF(crl->crlNumber);
+ PKIX_DECREF(crl->crlEntryList);
+ PKIX_DECREF(crl->critExtOids);
+ if (crl->derGenName) {
+ SECITEM_FreeItem(crl->derGenName, PR_TRUE);
+ }
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the CRL pointed
+ * to by "crl" and stores it at "pString".
+ *
+ * PARAMETERS
+ * "crl"
+ * Address of CRL whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_ToString_Helper(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *asciiFormat = NULL;
+ PKIX_UInt32 crlVersion = 0;
+ PKIX_PL_X500Name *crlIssuer = NULL;
+ PKIX_PL_OID *nssSignatureAlgId = NULL;
+ PKIX_PL_BigInt *crlNumber = NULL;
+ PKIX_List *crlEntryList = NULL;
+ PKIX_List *critExtOIDs = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *crlIssuerString = NULL;
+ PKIX_PL_String *lastUpdateString = NULL;
+ PKIX_PL_String *nextUpdateString = NULL;
+ PKIX_PL_String *nssSignatureAlgIdString = NULL;
+ PKIX_PL_String *crlNumberString = NULL;
+ PKIX_PL_String *crlEntryListString = NULL;
+ PKIX_PL_String *critExtOIDsString = NULL;
+ PKIX_PL_String *crlString = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_ToString_Helper");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pString);
+
+ asciiFormat =
+ "[\n"
+ "\tVersion: v%d\n"
+ "\tIssuer: %s\n"
+ "\tUpdate: [Last: %s\n"
+ "\t Next: %s]\n"
+ "\tSignatureAlgId: %s\n"
+ "\tCRL Number : %s\n"
+ "\n"
+ "\tEntry List: %s\n"
+ "\n"
+ "\tCritExtOIDs: %s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Version */
+ PKIX_CHECK(pkix_pl_CRL_GetVersion(crl, &crlVersion, plContext),
+ PKIX_CRLGETVERSIONFAILED);
+
+ /* Issuer */
+ PKIX_CHECK(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext),
+ PKIX_CRLGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)crlIssuer, &crlIssuerString, plContext),
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ /* This update - No Date object created, use nss data directly */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(crl->nssSignedCrl->crl.lastUpdate),
+ &lastUpdateString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* Next update - No Date object created, use nss data directly */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(crl->nssSignedCrl->crl.nextUpdate),
+ &nextUpdateString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* Signature Algorithm Id */
+ PKIX_CHECK(pkix_pl_CRL_GetSignatureAlgId
+ (crl, &nssSignatureAlgId, plContext),
+ PKIX_CRLGETSIGNATUREALGIDFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)nssSignatureAlgId,
+ &nssSignatureAlgIdString,
+ plContext),
+ PKIX_OIDTOSTRINGFAILED);
+
+ /* CRL Number */
+ PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber
+ (crl, &crlNumber, plContext),
+ PKIX_CRLGETCRLNUMBERFAILED);
+
+ PKIX_TOSTRING(crlNumber, &crlNumberString, plContext,
+ PKIX_BIGINTTOSTRINGFAILED);
+
+ /* CRL Entries */
+ PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext),
+ PKIX_CRLGETCRLENTRIESFAILED);
+
+ PKIX_TOSTRING(crlEntryList, &crlEntryListString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* CriticalExtensionOIDs */
+ PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs
+ (crl, &critExtOIDs, plContext),
+ PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED);
+
+ PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&crlString,
+ plContext,
+ formatString,
+ crlVersion + 1,
+ crlIssuerString,
+ lastUpdateString,
+ nextUpdateString,
+ nssSignatureAlgIdString,
+ crlNumberString,
+ crlEntryListString,
+ critExtOIDsString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = crlString;
+
+cleanup:
+
+ PKIX_DECREF(crlIssuer);
+ PKIX_DECREF(nssSignatureAlgId);
+ PKIX_DECREF(crlNumber);
+ PKIX_DECREF(crlEntryList);
+ PKIX_DECREF(critExtOIDs);
+ PKIX_DECREF(crlIssuerString);
+ PKIX_DECREF(lastUpdateString);
+ PKIX_DECREF(nextUpdateString);
+ PKIX_DECREF(nssSignatureAlgIdString);
+ PKIX_DECREF(crlNumberString);
+ PKIX_DECREF(crlEntryListString);
+ PKIX_DECREF(critExtOIDsString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlString = NULL;
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
+ PKIX_OBJECTNOTCRL);
+
+ crl = (PKIX_PL_CRL *) object;
+
+ PKIX_CHECK(pkix_pl_CRL_ToString_Helper(crl, &crlString, plContext),
+ PKIX_CRLTOSTRINGHELPERFAILED);
+
+ *pString = crlString;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_UInt32 certHash;
+ SECItem *crlDer = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
+ PKIX_OBJECTNOTCRL);
+
+ crl = (PKIX_PL_CRL *)object;
+ if (crl->adoptedDerCrl) {
+ crlDer = crl->adoptedDerCrl;
+ } else if (crl->nssSignedCrl && crl->nssSignedCrl->derCrl) {
+ crlDer = crl->nssSignedCrl->derCrl;
+ }
+ if (!crlDer || !crlDer->data) {
+ PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
+ }
+
+ PKIX_CHECK(pkix_hash(crlDer->data, crlDer->len,
+ &certHash, plContext),
+ PKIX_ERRORINHASH);
+
+ *pHashcode = certHash;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CRL *firstCrl = NULL;
+ PKIX_PL_CRL *secondCrl = NULL;
+ SECItem *crlDerOne = NULL, *crlDerTwo = NULL;
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CRL */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRL_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCRL);
+
+ firstCrl = (PKIX_PL_CRL *)firstObject;
+ secondCrl = (PKIX_PL_CRL *)secondObject;
+
+ /*
+ * Since we know firstObject is a CRL, if both references are
+ * identical, they must be equal
+ */
+ if (firstCrl == secondCrl){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondCrl isn't a CRL, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondCrl, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CRL_TYPE) goto cleanup;
+
+ if (firstCrl->adoptedDerCrl) {
+ crlDerOne = firstCrl->adoptedDerCrl;
+ } else if (firstCrl->nssSignedCrl && firstCrl->nssSignedCrl->derCrl) {
+ crlDerOne = firstCrl->nssSignedCrl->derCrl;
+ }
+
+ if (secondCrl->adoptedDerCrl) {
+ crlDerTwo = secondCrl->adoptedDerCrl;
+ } else if (secondCrl->nssSignedCrl && secondCrl->nssSignedCrl->derCrl) {
+ crlDerTwo = secondCrl->nssSignedCrl->derCrl;
+ }
+
+ if (SECITEM_CompareItem(crlDerOne, crlDerTwo) == SECEqual) {
+ *pResult = PKIX_TRUE;
+ }
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CRL_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ *
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CRL_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_CRL_TYPE];
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_RegisterSelf");
+
+ entry->description = "CRL";
+ entry->typeObjectSize = sizeof(PKIX_PL_CRL);
+ entry->destructor = pkix_pl_CRL_Destroy;
+ entry->equalsFunction = pkix_pl_CRL_Equals;
+ entry->hashcodeFunction = pkix_pl_CRL_Hashcode;
+ entry->toStringFunction = pkix_pl_CRL_ToString;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_VerifyUpdateTime(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_Date *date,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PRTime timeToCheck;
+ PRTime nextUpdate;
+ PRTime lastUpdate;
+ SECStatus status;
+ CERTCrl *nssCrl = NULL;
+ SECItem *nextUpdateDer = NULL;
+ PKIX_Boolean haveNextUpdate = PR_FALSE;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime");
+ PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ nssCrl = &(crl->nssSignedCrl->crl);
+ timeToCheck = date->nssTime;
+
+ /* nextUpdate can be NULL. Checking before using it */
+ nextUpdateDer = &nssCrl->nextUpdate;
+ if (nextUpdateDer->data && nextUpdateDer->len) {
+ haveNextUpdate = PR_TRUE;
+ status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer);
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED);
+ }
+ }
+
+ status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate));
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED);
+ }
+
+ if (!haveNextUpdate || nextUpdate < timeToCheck) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ if (lastUpdate <= timeToCheck) {
+ *pResult = PKIX_TRUE;
+ } else {
+ *pResult = PKIX_FALSE;
+ }
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL
+ * DESCRIPTION:
+ *
+ * Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl"
+ * and stores it at "pCRL". If the decoding of the CERTSignedCrl fails,
+ * a PKIX_Error is returned.
+ *
+ * PARAMETERS:
+ * "nssSignedCrl"
+ * Address of CERTSignedCrl. Must be non-NULL.
+ * "adoptedDerCrl"
+ * SECItem ponter that if not NULL is indicating that memory used
+ * for der should be adopted by crl that is about to be created.
+ * "pCRL"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CRL_CreateWithSignedCRL(
+ CERTSignedCrl *nssSignedCrl,
+ SECItem *adoptedDerCrl,
+ SECItem *derGenName,
+ PKIX_PL_CRL **pCrl,
+ void *plContext)
+{
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL");
+ PKIX_NULLCHECK_ONE(pCrl);
+
+ /* create a PKIX_PL_CRL object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRL_TYPE,
+ sizeof (PKIX_PL_CRL),
+ (PKIX_PL_Object **)&crl,
+ plContext),
+ PKIX_COULDNOTCREATECRLOBJECT);
+
+ /* populate the nssSignedCrl field */
+ crl->nssSignedCrl = nssSignedCrl;
+ crl->adoptedDerCrl = adoptedDerCrl;
+ crl->issuer = NULL;
+ crl->signatureAlgId = NULL;
+ crl->crlNumber = NULL;
+ crl->crlNumberAbsent = PKIX_FALSE;
+ crl->crlEntryList = NULL;
+ crl->critExtOids = NULL;
+ if (derGenName) {
+ crl->derGenName =
+ SECITEM_DupItem(derGenName);
+ if (!crl->derGenName) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ }
+
+ *pCrl = crl;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(crl);
+ }
+
+ PKIX_RETURN(CRL);
+}
+
+/* --Public-CRL-Functions------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_Create(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_PL_CRL **pCrl,
+ void *plContext)
+{
+ CERTSignedCrl *nssSignedCrl = NULL;
+ SECItem derItem, *derCrl = NULL;
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_Create");
+ PKIX_NULLCHECK_TWO(byteArray, pCrl);
+
+ if (byteArray->length == 0){
+ PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING);
+ }
+ derItem.type = siBuffer;
+ derItem.data = byteArray->array;
+ derItem.len = byteArray->length;
+ derCrl = SECITEM_DupItem(&derItem);
+ if (!derCrl) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ nssSignedCrl =
+ CERT_DecodeDERCrlWithFlags(NULL, derCrl, SEC_CRL_TYPE,
+ CRL_DECODE_DONT_COPY_DER |
+ CRL_DECODE_SKIP_ENTRIES);
+ if (!nssSignedCrl) {
+ PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED);
+ }
+ PKIX_CHECK(
+ pkix_pl_CRL_CreateWithSignedCRL(nssSignedCrl, derCrl, NULL,
+ &crl, plContext),
+ PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
+ nssSignedCrl = NULL;
+ derCrl = NULL;
+ *pCrl = crl;
+
+cleanup:
+ if (derCrl) {
+ SECITEM_FreeItem(derCrl, PR_TRUE);
+ }
+ if (nssSignedCrl) {
+ SEC_DestroyCrl(nssSignedCrl);
+ }
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetIssuer (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetIssuer(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_X500Name **pCRLIssuer,
+ void *plContext)
+{
+ PKIX_PL_String *crlString = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ SECItem *derIssuerName = NULL;
+ CERTName *issuerName = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_GetIssuer");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCRLIssuer);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->issuer == NULL){
+
+ PKIX_OBJECT_LOCK(crl);
+
+ if (crl->issuer == NULL) {
+
+ issuerName = &crl->nssSignedCrl->crl.name;
+ derIssuerName = &crl->nssSignedCrl->crl.derName;
+
+ PKIX_CHECK(
+ PKIX_PL_X500Name_CreateFromCERTName(derIssuerName,
+ issuerName,
+ &issuer,
+ plContext),
+ PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ crl->issuer = issuer;
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ PKIX_INCREF(crl->issuer);
+
+ *pCRLIssuer = crl->issuer;
+
+cleanup:
+
+ PKIX_DECREF(crlString);
+
+ PKIX_RETURN(CRL);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetCriticalExtensionOIDs(
+ PKIX_PL_CRL *crl,
+ PKIX_List **pExtensions, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_List *oidsList = NULL;
+ CERTCertExtension **extensions = NULL;
+ CERTCrl *nssSignedCrl = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCriticalExtensionOIDs");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pExtensions);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->critExtOids == NULL) {
+
+ PKIX_OBJECT_LOCK(crl);
+
+ nssSignedCrl = &(crl->nssSignedCrl->crl);
+ extensions = nssSignedCrl->extensions;
+
+ if (crl->critExtOids == NULL) {
+
+ PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
+ (extensions, &oidsList, plContext),
+ PKIX_GETCRITICALEXTENSIONOIDSFAILED);
+
+ crl->critExtOids = oidsList;
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ /* We should return a copy of the List since this list changes */
+ PKIX_DUPLICATE(crl->critExtOids, pExtensions, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_VerifySignature (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_VerifySignature(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_PublicKey *pubKey,
+ void *plContext)
+{
+ PKIX_PL_CRL *cachedCrl = NULL;
+ PKIX_Error *verifySig = NULL;
+ PKIX_Error *cachedSig = NULL;
+ PKIX_Boolean crlEqual = PKIX_FALSE;
+ PKIX_Boolean crlInHash= PKIX_FALSE;
+ CERTSignedCrl *nssSignedCrl = NULL;
+ SECKEYPublicKey *nssPubKey = NULL;
+ CERTSignedData *tbsCrl = NULL;
+ void* wincx = NULL;
+ SECStatus status;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifySignature");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pubKey);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ verifySig = PKIX_PL_HashTable_Lookup
+ (cachedCrlSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object **) &cachedCrl,
+ plContext);
+
+ if (cachedCrl != NULL && verifySig == NULL) {
+ /* Cached Signature Table lookup succeed */
+ PKIX_EQUALS(crl, cachedCrl, &crlEqual, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ if (crlEqual == PKIX_TRUE) {
+ goto cleanup;
+ }
+ /* Different PubKey may hash to same value, skip add */
+ crlInHash = PKIX_TRUE;
+ }
+
+ nssSignedCrl = crl->nssSignedCrl;
+ tbsCrl = &nssSignedCrl->signatureWrap;
+
+ PKIX_CRL_DEBUG("\t\tCalling SECKEY_ExtractPublicKey\n");
+ nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
+ if (!nssPubKey){
+ PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
+ }
+
+ PKIX_CHECK(pkix_pl_NssContext_GetWincx
+ ((PKIX_PL_NssContext *)plContext, &wincx),
+ PKIX_NSSCONTEXTGETWINCXFAILED);
+
+ PKIX_CRL_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey\n");
+ status = CERT_VerifySignedDataWithPublicKey(tbsCrl, nssPubKey, wincx);
+
+ if (status != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
+ }
+
+ if (crlInHash == PKIX_FALSE) {
+ cachedSig = PKIX_PL_HashTable_Add
+ (cachedCrlSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object *) crl,
+ plContext);
+
+ if (cachedSig != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
+ }
+ }
+
+cleanup:
+
+ if (nssPubKey){
+ PKIX_CRL_DEBUG("\t\tCalling SECKEY_DestroyPublicKey\n");
+ SECKEY_DestroyPublicKey(nssPubKey);
+ nssPubKey = NULL;
+ }
+
+ PKIX_DECREF(cachedCrl);
+ PKIX_DECREF(verifySig);
+ PKIX_DECREF(cachedSig);
+
+ PKIX_RETURN(CRL);
+}
+
+PKIX_Error*
+PKIX_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL *crl,
+ SECItem **derCrl,
+ void *plContext)
+{
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_ReleaseDerCrl");
+ *derCrl = crl->adoptedDerCrl;
+ crl->adoptedDerCrl = NULL;
+
+ PKIX_RETURN(CRL);
+}
+
+PKIX_Error*
+PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl,
+ SECItem *derCrl,
+ void *plContext)
+{
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_AquireDerCrl");
+ if (crl->adoptedDerCrl) {
+ PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
+ }
+ crl->adoptedDerCrl = derCrl;
+cleanup:
+ PKIX_RETURN(CRL);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h
new file mode 100644
index 0000000000..a45059ea0d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h
@@ -0,0 +1,48 @@
+/* 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/. */
+/*
+ * pkix_pl_crl.h
+ *
+ * CRL Object Type Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_CRL_H
+#define _PKIX_PL_CRL_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_CRLStruct {
+ CERTSignedCrl *nssSignedCrl;
+ PKIX_PL_X500Name *issuer;
+ PKIX_PL_OID *signatureAlgId;
+ PKIX_PL_BigInt *crlNumber;
+ PKIX_Boolean crlNumberAbsent;
+ PKIX_List *crlEntryList; /* list of PKIX_PL_CRLEntry */
+ PKIX_List *critExtOids;
+ SECItem *adoptedDerCrl;
+ SECItem *derGenName; /* der of general name which was used
+ * to download the crl. */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_CRL_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_CRL_CreateWithSignedCRL(CERTSignedCrl *nssSignedCrl,
+ SECItem *derCrl,
+ SECItem *derGenName,
+ PKIX_PL_CRL **pCrl,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CRL_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c
new file mode 100644
index 0000000000..4f29de2849
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c
@@ -0,0 +1,151 @@
+/* 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/. */
+/*
+ * pkix_pl_crldp.c
+ *
+ * Crl DP Object Functions
+ *
+ */
+
+#include "pkix_pl_crldp.h"
+
+static PKIX_Error *
+pkix_pl_CrlDp_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_pl_CrlDp *crldp = NULL;
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a default CRL checker state */
+ PKIX_CHECK(
+ pkix_CheckType(object, PKIX_CRLDP_TYPE, plContext),
+ PKIX_OBJECTNOTCRLCHECKER);
+
+ crldp = (pkix_pl_CrlDp *)object;
+ if (crldp->distPointType == relativeDistinguishedName) {
+ CERT_DestroyName(crldp->name.issuerName);
+ crldp->name.issuerName = NULL;
+ }
+ crldp->nssdp = NULL;
+cleanup:
+ PKIX_RETURN(CRLCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CrlDp_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CRLDP_TYPE and its related functions
+ * with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CrlDp_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLDP_TYPE];
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_RegisterSelf");
+
+ entry->description = "CrlDistPoint";
+ entry->typeObjectSize = sizeof(pkix_pl_CrlDp);
+ entry->destructor = pkix_pl_CrlDp_Destroy;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(CRLCHECKER);
+}
+
+
+
+PKIX_Error *
+pkix_pl_CrlDp_Create(
+ const CRLDistributionPoint *dp,
+ const CERTName *certIssuerName,
+ pkix_pl_CrlDp **pPkixDP,
+ void *plContext)
+{
+ PLArenaPool *rdnArena = NULL;
+ CERTName *issuerNameCopy = NULL;
+ pkix_pl_CrlDp *dpl = NULL;
+
+ /* Need to save the following info to update crl cache:
+ * - reasons if partitioned(but can not return revocation check
+ * success if not all crl are downloaded)
+ * - issuer name if different from issuer of the cert
+ * - url to upload a crl if needed.
+ * */
+ PKIX_ENTER(CRLDP, "pkix_pl_CrlDp_Create");
+ PKIX_NULLCHECK_ONE(dp);
+
+ PKIX_CHECK(
+ PKIX_PL_Object_Alloc(PKIX_CRLDP_TYPE,
+ sizeof (pkix_pl_CrlDp),
+ (PKIX_PL_Object **)&dpl,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ dpl->nssdp = dp;
+ dpl->isPartitionedByReasonCode = PKIX_FALSE;
+ if (dp->reasons.data) {
+ dpl->isPartitionedByReasonCode = PKIX_TRUE;
+ }
+ if (dp->distPointType == generalName) {
+ dpl->distPointType = generalName;
+ dpl->name.fullName = dp->distPoint.fullName;
+ } else {
+ SECStatus rv;
+ const CERTName *issuerName = NULL;
+ const CERTRDN *relName = &dp->distPoint.relativeName;
+
+ if (dp->crlIssuer) {
+ if (dp->crlIssuer->l.next) {
+ /* Violate RFC 5280: in this case crlIssuer
+ * should have only one name and should be
+ * a distinguish name. */
+ PKIX_ERROR(PKIX_NOTCONFORMINGCRLDP);
+ }
+ issuerName = &dp->crlIssuer->name.directoryName;
+ } else {
+ issuerName = certIssuerName;
+ }
+ rdnArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!rdnArena) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+ issuerNameCopy = (CERTName *)PORT_ArenaZNew(rdnArena, CERTName);
+ if (!issuerNameCopy) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ rv = CERT_CopyName(rdnArena, issuerNameCopy, (CERTName*)issuerName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ rv = CERT_AddRDN(issuerNameCopy, (CERTRDN*)relName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ dpl->distPointType = relativeDistinguishedName;
+ dpl->name.issuerName = issuerNameCopy;
+ rdnArena = NULL;
+ }
+ *pPkixDP = dpl;
+ dpl = NULL;
+
+cleanup:
+ if (rdnArena) {
+ PORT_FreeArena(rdnArena, PR_FALSE);
+ }
+ PKIX_DECREF(dpl);
+
+ PKIX_RETURN(CRLDP);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h
new file mode 100644
index 0000000000..49cd9d2cdf
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h
@@ -0,0 +1,53 @@
+/* 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/. */
+/*
+ * pkix_pl_crldp.h
+ *
+ * Crp DP Object Definitions
+ *
+ */
+#include "pkix_pl_common.h"
+
+#ifndef _PKIX_PL_CRLDP_H
+#define _PKIX_PL_CRLDP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* CRLDP object can not be used without holding a reference
+ * to the pkix certificate they belong to. The memory for dp der
+ * object is allocated on nssCert certificate - a member of
+ * PKIX_PL_Cert struct. */
+typedef struct pkix_pl_CrlDpStruct {
+ /* reference to decoded crldp that allocated on nssCert arena. */
+ const CRLDistributionPoint *nssdp;
+ DistributionPointTypes distPointType;
+ union {
+ CERTGeneralName *fullName;
+ /* if dp is a relative name, the issuerName is a merged value
+ * of crlIssuer and a relative name. Must be destroyed by CrlDp
+ * destructor. */
+ CERTName *issuerName;
+ } name;
+ PKIX_Boolean isPartitionedByReasonCode;
+} pkix_pl_CrlDp;
+
+
+PKIX_Error *
+pkix_pl_CrlDp_RegisterSelf(void *plContext);
+
+/* Parses CRLDistributionPoint structure and creaetes
+ * pkix_pl_CrlDp object. */
+PKIX_Error *
+pkix_pl_CrlDp_Create(const CRLDistributionPoint *dp,
+ const CERTName *certIssuerName,
+ pkix_pl_CrlDp **pPkixDP,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CRLDP_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c
new file mode 100644
index 0000000000..e2b3e02688
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c
@@ -0,0 +1,880 @@
+/* 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/. */
+/*
+ * pkix_pl_crlentry.c
+ *
+ * CRLENTRY Function Definitions
+ *
+ */
+
+#include "pkix_pl_crlentry.h"
+
+/* --Private-CRLEntry-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
+ PKIX_OBJECTNOTCRLENTRY);
+
+ crlEntry = (PKIX_PL_CRLEntry*)object;
+
+ /* crlEntry->nssCrlEntry is freed by NSS when freeing CRL */
+ crlEntry->userReasonCode = 0;
+ crlEntry->userReasonCodeAbsent = PKIX_FALSE;
+ crlEntry->nssCrlEntry = NULL;
+ PKIX_DECREF(crlEntry->serialNumber);
+ PKIX_DECREF(crlEntry->critExtOids);
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_ToString_Helper
+ *
+ * DESCRIPTION:
+ * Helper function that creates a string representation of the CRLEntry
+ * pointed to by "crlEntry" and stores it at "pString".
+ *
+ * PARAMETERS
+ * "crlEntry"
+ * Address of CRLEntry whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLEntry Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CRLEntry_ToString_Helper(
+ PKIX_PL_CRLEntry *crlEntry,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *asciiFormat = NULL;
+ PKIX_List *critExtOIDs = NULL;
+ PKIX_PL_String *crlEntryString = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *crlSerialNumberString = NULL;
+ PKIX_PL_String *crlRevocationDateString = NULL;
+ PKIX_PL_String *critExtOIDsString = NULL;
+ PKIX_Int32 reasonCode = 0;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString_Helper");
+ PKIX_NULLCHECK_FOUR
+ (crlEntry,
+ crlEntry->serialNumber,
+ crlEntry->nssCrlEntry,
+ pString);
+
+ asciiFormat =
+ "\n\t[\n"
+ "\tSerialNumber: %s\n"
+ "\tReasonCode: %d\n"
+ "\tRevocationDate: %s\n"
+ "\tCritExtOIDs: %s\n"
+ "\t]\n\t";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* SerialNumber */
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)crlEntry->serialNumber,
+ &crlSerialNumberString,
+ plContext),
+ PKIX_BIGINTTOSTRINGHELPERFAILED);
+
+ /* RevocationDate - No Date object created, use nss data directly */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(crlEntry->nssCrlEntry->revocationDate),
+ &crlRevocationDateString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* CriticalExtensionOIDs */
+ PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
+ (crlEntry, &critExtOIDs, plContext),
+ PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED);
+
+ PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Revocation Reason Code */
+ PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
+ (crlEntry, &reasonCode, plContext),
+ PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&crlEntryString,
+ plContext,
+ formatString,
+ crlSerialNumberString,
+ reasonCode,
+ crlRevocationDateString,
+ critExtOIDsString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = crlEntryString;
+
+cleanup:
+
+ PKIX_DECREF(critExtOIDs);
+ PKIX_DECREF(crlSerialNumberString);
+ PKIX_DECREF(crlRevocationDateString);
+ PKIX_DECREF(critExtOIDsString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlEntryString = NULL;
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
+ PKIX_OBJECTNOTCRLENTRY);
+
+ crlEntry = (PKIX_PL_CRLEntry *) object;
+
+ PKIX_CHECK(pkix_pl_CRLEntry_ToString_Helper
+ (crlEntry, &crlEntryString, plContext),
+ PKIX_CRLENTRYTOSTRINGHELPERFAILED);
+
+ *pString = crlEntryString;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Extensions_Hashcode
+ * DESCRIPTION:
+ *
+ * For each CRL Entry extension stored at NSS structure CERTCertExtension,
+ * get its derbyte data and do the hash.
+ *
+ * PARAMETERS
+ * "extensions"
+ * Address of arrray of CERTCertExtension whose hash value is desired.
+ * Must be non-NULL.
+ * "pHashValue"
+ * Address where the final hash value is returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditional Thread Safe
+ * Though the value of extensions once created is not supposed to change,
+ * it may be de-allocated while we are accessing it. But since we are
+ * validating the object, it is unlikely we or someone is de-allocating
+ * at the moment.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Extensions_Hashcode(
+ CERTCertExtension **extensions,
+ PKIX_UInt32 *pHashValue,
+ void *plContext)
+{
+ CERTCertExtension *extension = NULL;
+ PLArenaPool *arena = NULL;
+ PKIX_UInt32 extHash = 0;
+ PKIX_UInt32 hashValue = 0;
+ SECItem *derBytes = NULL;
+ SECItem *resultSecItem = NULL;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Hashcode");
+ PKIX_NULLCHECK_TWO(extensions, pHashValue);
+
+ if (extensions) {
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ while (*extensions) {
+
+ extension = *extensions++;
+
+ PKIX_NULLCHECK_ONE(extension);
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
+ derBytes = PORT_ArenaZNew(arena, SECItem);
+ if (derBytes == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG
+ ("\t\tCalling SEC_ASN1EncodeItem\n");
+ resultSecItem = SEC_ASN1EncodeItem
+ (arena,
+ derBytes,
+ extension,
+ CERT_CertExtensionTemplate);
+
+ if (resultSecItem == NULL){
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ PKIX_CHECK(pkix_hash
+ (derBytes->data,
+ derBytes->len,
+ &extHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ hashValue += (extHash << 7);
+
+ }
+ }
+
+ *pHashValue = hashValue;
+
+cleanup:
+
+ if (arena){
+ /* Note that freeing the arena also frees derBytes */
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ arena = NULL;
+ }
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ SECItem *nssDate = NULL;
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+ PKIX_UInt32 crlEntryHash;
+ PKIX_UInt32 hashValue;
+ PKIX_Int32 reasonCode = 0;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
+ PKIX_OBJECTNOTCRLENTRY);
+
+ crlEntry = (PKIX_PL_CRLEntry *)object;
+
+ PKIX_NULLCHECK_ONE(crlEntry->nssCrlEntry);
+ nssDate = &(crlEntry->nssCrlEntry->revocationDate);
+
+ PKIX_NULLCHECK_ONE(nssDate->data);
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)nssDate->data,
+ nssDate->len,
+ &crlEntryHash,
+ plContext),
+ PKIX_ERRORGETTINGHASHCODE);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)crlEntry->serialNumber,
+ &hashValue,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ crlEntryHash += (hashValue << 7);
+
+ hashValue = 0;
+
+ if (crlEntry->nssCrlEntry->extensions) {
+
+ PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Hashcode
+ (crlEntry->nssCrlEntry->extensions, &hashValue, plContext),
+ PKIX_CRLENTRYEXTENSIONSHASHCODEFAILED);
+ }
+
+ crlEntryHash += (hashValue << 7);
+
+ PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
+ (crlEntry, &reasonCode, plContext),
+ PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
+
+ crlEntryHash += (reasonCode + 777) << 3;
+
+ *pHashcode = crlEntryHash;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLENTRY_Extensions_Equals
+ * DESCRIPTION:
+ *
+ * Compare each extension's DERbyte data in "firstExtensions" with extension
+ * in "secondExtensions" in sequential order and store the result in
+ * "pResult".
+ *
+ * PARAMETERS
+ * "firstExtensions"
+ * Address of first NSS structure CERTCertExtension to be compared.
+ * Must be non-NULL.
+ * "secondExtensions"
+ * Address of second NSS structure CERTCertExtension to be compared.
+ * Must be non-NULL.
+ * "pResult"
+ * Address where the comparison result is returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * Though the value of extensions once created is not supposed to change,
+ * it may be de-allocated while we are accessing it. But since we are
+ * validating the object, it is unlikely we or someone is de-allocating
+ * at the moment.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Extensions_Equals(
+ CERTCertExtension **extensions1,
+ CERTCertExtension **extensions2,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ CERTCertExtension **firstExtensions;
+ CERTCertExtension **secondExtensions;
+ CERTCertExtension *firstExtension = NULL;
+ CERTCertExtension *secondExtension = NULL;
+ PLArenaPool *arena = NULL;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+ SECItem *firstDerBytes = NULL;
+ SECItem *secondDerBytes = NULL;
+ SECItem *firstResultSecItem = NULL;
+ SECItem *secondResultSecItem = NULL;
+ PKIX_UInt32 firstNumExt = 0;
+ PKIX_UInt32 secondNumExt = 0;
+ SECComparison secResult;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Equals");
+ PKIX_NULLCHECK_THREE(extensions1, extensions2, pResult);
+
+ firstExtensions = extensions1;
+ secondExtensions = extensions2;
+
+ if (firstExtensions) {
+ while (*firstExtensions) {
+ firstExtension = *firstExtensions++;
+ firstNumExt++;
+ }
+ }
+
+ if (secondExtensions) {
+ while (*secondExtensions) {
+ secondExtension = *secondExtensions++;
+ secondNumExt++;
+ }
+ }
+
+ if (firstNumExt != secondNumExt) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ if (firstNumExt == 0 && secondNumExt == 0) {
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /* now have equal number, but non-zero extension items to compare */
+
+ firstExtensions = extensions1;
+ secondExtensions = extensions2;
+
+ cmpResult = PKIX_TRUE;
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE*2);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ while (firstNumExt--) {
+
+ firstExtension = *firstExtensions++;
+ secondExtension = *secondExtensions++;
+
+ PKIX_NULLCHECK_TWO(firstExtension, secondExtension);
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
+ firstDerBytes = PORT_ArenaZNew(arena, SECItem);
+ if (firstDerBytes == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
+ secondDerBytes = PORT_ArenaZNew(arena, SECItem);
+ if (secondDerBytes == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG
+ ("\t\tCalling SEC_ASN1EncodeItem\n");
+ firstResultSecItem = SEC_ASN1EncodeItem
+ (arena,
+ firstDerBytes,
+ firstExtension,
+ CERT_CertExtensionTemplate);
+
+ if (firstResultSecItem == NULL){
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG
+ ("\t\tCalling SEC_ASN1EncodeItem\n");
+ secondResultSecItem = SEC_ASN1EncodeItem
+ (arena,
+ secondDerBytes,
+ secondExtension,
+ CERT_CertExtensionTemplate);
+
+ if (secondResultSecItem == NULL){
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
+ secResult = SECITEM_CompareItem
+ (firstResultSecItem, secondResultSecItem);
+
+ if (secResult != SECEqual) {
+ cmpResult = PKIX_FALSE;
+ break;
+ }
+
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ if (arena){
+ /* Note that freeing the arena also frees derBytes */
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ arena = NULL;
+ }
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CRLEntry *firstCrlEntry = NULL;
+ PKIX_PL_CRLEntry *secondCrlEntry = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CRLEntry */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRLENTRY_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCRLENTRY);
+
+ firstCrlEntry = (PKIX_PL_CRLEntry *)firstObject;
+ secondCrlEntry = (PKIX_PL_CRLEntry *)secondObject;
+
+ PKIX_NULLCHECK_TWO
+ (firstCrlEntry->nssCrlEntry, secondCrlEntry->nssCrlEntry);
+
+ /*
+ * Since we know firstObject is a CRLEntry, if both references are
+ * identical, they must be equal
+ */
+ if (firstCrlEntry == secondCrlEntry){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondCrlEntry isn't a CRL Entry, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondCrlEntry, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CRLENTRY_TYPE) goto cleanup;
+
+ /* Compare userSerialNumber */
+ PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
+ if (SECITEM_CompareItem(
+ &(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->serialNumber),
+ &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->serialNumber))
+ != SECEqual) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ /* Compare revocationDate */
+ PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
+ if (SECITEM_CompareItem
+ (&(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->
+ revocationDate),
+ &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->
+ revocationDate))
+ != SECEqual) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ /* Compare Critical Extension List */
+ PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Equals
+ (firstCrlEntry->nssCrlEntry->extensions,
+ secondCrlEntry->nssCrlEntry->extensions,
+ &cmpResult,
+ plContext),
+ PKIX_CRLENTRYEXTENSIONSEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE){
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ cmpResult = (firstCrlEntry->userReasonCode ==
+ secondCrlEntry->userReasonCode);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CRLEntry_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CRLEntry_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_RegisterSelf");
+
+ entry.description = "CRLEntry";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CRLEntry);
+ entry.destructor = pkix_pl_CRLEntry_Destroy;
+ entry.equalsFunction = pkix_pl_CRLEntry_Equals;
+ entry.hashcodeFunction = pkix_pl_CRLEntry_Hashcode;
+ entry.toStringFunction = pkix_pl_CRLEntry_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CRLENTRY_TYPE] = entry;
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_CreateEntry
+ * DESCRIPTION:
+ *
+ * Creates a new CRLEntry using the CertCrlEntry pointed to by "nssCrlEntry"
+ * and stores it at "pCrlEntry". Once created, a CRLEntry is immutable.
+ *
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, MUST be v2
+ *
+ * PARAMETERS:
+ * "nssCrlEntry"
+ * Address of CERTCrlEntry representing an NSS CRL entry.
+ * Must be non-NULL.
+ * "pCrlEntry"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLEntry Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_CreateEntry(
+ CERTCrlEntry *nssCrlEntry, /* entry data to be created from */
+ PKIX_PL_CRLEntry **pCrlEntry,
+ void *plContext)
+{
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_CreateEntry");
+ PKIX_NULLCHECK_TWO(nssCrlEntry, pCrlEntry);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRLENTRY_TYPE,
+ sizeof (PKIX_PL_CRLEntry),
+ (PKIX_PL_Object **)&crlEntry,
+ plContext),
+ PKIX_COULDNOTCREATECRLENTRYOBJECT);
+
+ crlEntry->nssCrlEntry = nssCrlEntry;
+ crlEntry->serialNumber = NULL;
+ crlEntry->critExtOids = NULL;
+ crlEntry->userReasonCode = 0;
+ crlEntry->userReasonCodeAbsent = PKIX_FALSE;
+
+ *pCrlEntry = crlEntry;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Create
+ * DESCRIPTION:
+ *
+ * Creates a List of CRLEntries using the array of CERTCrlEntries pointed to
+ * by "nssCrlEntries" and stores it at "pCrlEntryList". If "nssCrlEntries" is
+ * NULL, this function stores an empty List at "pCrlEntryList".
+ * }
+ * PARAMETERS:
+ * "nssCrlEntries"
+ * Address of array of CERTCrlEntries representing NSS CRL entries.
+ * Can be NULL if CRL has no NSS CRL entries.
+ * "pCrlEntryList"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLEntry Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CRLEntry_Create(
+ CERTCrlEntry **nssCrlEntries, /* head of entry list */
+ PKIX_List **pCrlEntryList,
+ void *plContext)
+{
+ PKIX_List *entryList = NULL;
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+ CERTCrlEntry **entries = NULL;
+ SECItem serialNumberItem;
+ PKIX_PL_BigInt *serialNumber;
+ char *bytes = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Create");
+ PKIX_NULLCHECK_ONE(pCrlEntryList);
+
+ entries = nssCrlEntries;
+
+ PKIX_CHECK(PKIX_List_Create(&entryList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ if (entries) {
+ while (*entries){
+ PKIX_CHECK(pkix_pl_CRLEntry_CreateEntry
+ (*entries, &crlEntry, plContext),
+ PKIX_COULDNOTCREATECRLENTRYOBJECT);
+
+ /* Get Serial Number */
+ serialNumberItem = (*entries)->serialNumber;
+ length = serialNumberItem.len;
+ bytes = (char *)serialNumberItem.data;
+
+ PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
+ (bytes, length, &serialNumber, plContext),
+ PKIX_BIGINTCREATEWITHBYTESFAILED);
+
+ crlEntry->serialNumber = serialNumber;
+ crlEntry->nssCrlEntry = *entries;
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (entryList, (PKIX_PL_Object *)crlEntry, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(crlEntry);
+
+ entries++;
+ }
+ }
+
+ *pCrlEntryList = entryList;
+
+cleanup:
+ PKIX_DECREF(crlEntry);
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(entryList);
+ }
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/* --Public-CRLENTRY-Functions------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRLEntry_GetCRLEntryReasonCode (
+ PKIX_PL_CRLEntry *crlEntry,
+ PKIX_Int32 *pReason,
+ void *plContext)
+{
+ SECStatus status;
+ CERTCRLEntryReasonCode nssReasonCode;
+
+ PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCRLEntryReasonCode");
+ PKIX_NULLCHECK_TWO(crlEntry, pReason);
+
+ if (!crlEntry->userReasonCodeAbsent && crlEntry->userReasonCode == 0) {
+
+ PKIX_OBJECT_LOCK(crlEntry);
+
+ if (!crlEntry->userReasonCodeAbsent &&
+ crlEntry->userReasonCode == 0) {
+
+ /* reason code has not been cached in */
+ PKIX_CRLENTRY_DEBUG("\t\tCERT_FindCRLEntryReasonExten.\n");
+ status = CERT_FindCRLEntryReasonExten
+ (crlEntry->nssCrlEntry, &nssReasonCode);
+
+ if (status == SECSuccess) {
+ crlEntry->userReasonCode = (PKIX_Int32) nssReasonCode;
+ } else {
+ crlEntry->userReasonCodeAbsent = PKIX_TRUE;
+ }
+ }
+
+ PKIX_OBJECT_UNLOCK(crlEntry);
+
+ }
+
+ *pReason = crlEntry->userReasonCode;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRLEntry_GetCriticalExtensionOIDs (
+ PKIX_PL_CRLEntry *crlEntry,
+ PKIX_List **pList, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_List *oidsList = NULL;
+ CERTCertExtension **extensions;
+
+ PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCriticalExtensionOIDs");
+ PKIX_NULLCHECK_THREE(crlEntry, crlEntry->nssCrlEntry, pList);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crlEntry->critExtOids == NULL) {
+
+ PKIX_OBJECT_LOCK(crlEntry);
+
+ if (crlEntry->critExtOids == NULL) {
+
+ extensions = crlEntry->nssCrlEntry->extensions;
+
+ PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
+ (extensions, &oidsList, plContext),
+ PKIX_GETCRITICALEXTENSIONOIDSFAILED);
+
+ crlEntry->critExtOids = oidsList;
+ }
+
+ PKIX_OBJECT_UNLOCK(crlEntry);
+
+ }
+
+ /* We should return a copy of the List since this list changes */
+ PKIX_DUPLICATE(crlEntry->critExtOids, pList, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h
new file mode 100644
index 0000000000..9cdb6bc927
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h
@@ -0,0 +1,46 @@
+/* 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/. */
+/*
+ * pkix_pl_crlentry.h
+ *
+ * CRL Entry Type Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_CRLENTRY_H
+#define _PKIX_PL_CRLENTRY_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PKIX_PL_CRL_REASONCODE_NOTSET (-1)
+
+struct PKIX_PL_CRLEntryStruct {
+ CERTCrlEntry *nssCrlEntry;
+ PKIX_PL_BigInt *serialNumber;
+ PKIX_List *critExtOids;
+ PKIX_Int32 userReasonCode;
+ PKIX_Boolean userReasonCodeAbsent;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_CRLEntry_RegisterSelf(void *plContext);
+
+/* following functions are called by CRL only hence not public */
+
+PKIX_Error *
+pkix_pl_CRLEntry_Create(
+ CERTCrlEntry **nssCrlEntry, /* head of entry list */
+ PKIX_List **pCrlEntryList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CRLENTRY_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c
new file mode 100644
index 0000000000..4b5016bd01
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c
@@ -0,0 +1,466 @@
+/* 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/. */
+/*
+ * pkix_pl_date.c
+ *
+ * Date Object Definitions
+ *
+ */
+
+#include "pkix_pl_date.h"
+
+/* --Private-Date-Functions------------------------------------- */
+/*
+ * FUNCTION: pkix_pl_Date_GetPRTime
+ * DESCRIPTION:
+ *
+ * Translates into a PRTime the Date embodied by the Date object pointed to
+ * by "date", and stores it at "pPRTime".
+ *
+ * PARAMETERS
+ * "date"
+ * Address of Date whose PRTime representation is desired. Must be
+ * non-NULL.
+ * "pPRTime"
+ * Address where PRTime value will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Date Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Date_GetPRTime(
+ PKIX_PL_Date *date,
+ PRTime *pPRTime,
+ void *plContext)
+{
+ PKIX_ENTER(DATE, "PKIX_PL_Date_GetPRTime");
+ PKIX_NULLCHECK_TWO(date, pPRTime);
+
+ *pPRTime = date->nssTime;
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_CreateFromPRTime
+ * DESCRIPTION:
+ *
+ * Creates a new Date from the PRTime whose value is "prtime", and stores the
+ * result at "pDate".
+ *
+ * PARAMETERS
+ * "prtime"
+ * The PRTime value to be embodied in the new Date object.
+ * "pDate"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Date Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Date_CreateFromPRTime(
+ PRTime prtime,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+
+ PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime");
+ PKIX_NULLCHECK_ONE(pDate);
+
+ /* create a PKIX_PL_Date object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_DATE_TYPE,
+ sizeof (PKIX_PL_Date),
+ (PKIX_PL_Object **)&date,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+ /* populate the nssTime field */
+ date->nssTime = prtime;
+ *pDate = date;
+cleanup:
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the SECItem pointed
+ * to by "nssTime" (which represents a date) and stores it at "pString".
+ *
+ * PARAMETERS
+ * "nssTime"
+ * Address of SECItem whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Date Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Date_ToString_Helper(
+ SECItem *nssTime,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *asciiDate = NULL;
+
+ PKIX_ENTER(DATE, "pkix_pl_Date_ToString_Helper");
+ PKIX_NULLCHECK_TWO(nssTime, pString);
+
+ switch (nssTime->type) {
+ case siUTCTime:
+ PKIX_PL_NSSCALLRV
+ (DATE, asciiDate, DER_UTCDayToAscii, (nssTime));
+ if (!asciiDate){
+ PKIX_ERROR(PKIX_DERUTCTIMETOASCIIFAILED);
+ }
+ break;
+ case siGeneralizedTime:
+ /*
+ * we don't currently have any way to create GeneralizedTime.
+ * this code is only here so that it will be in place when
+ * we do have the capability to create GeneralizedTime.
+ */
+ PKIX_PL_NSSCALLRV
+ (DATE, asciiDate, DER_GeneralizedDayToAscii, (nssTime));
+ if (!asciiDate){
+ PKIX_ERROR(PKIX_DERGENERALIZEDDAYTOASCIIFAILED);
+ }
+ break;
+ default:
+ PKIX_ERROR(PKIX_UNRECOGNIZEDTIMETYPE);
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiDate, 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+ PR_Free(asciiDate);
+
+ PKIX_RETURN(DATE);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_Date_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ENTER(DATE, "pkix_pl_Date_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
+ PKIX_OBJECTNOTDATE);
+cleanup:
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ SECItem nssTime = {siBuffer, NULL, 0};
+ SECStatus rv;
+
+ PKIX_ENTER(DATE, "pkix_pl_Date_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
+ PKIX_OBJECTNOTDATE);
+
+ date = (PKIX_PL_Date *)object;
+ rv = DER_EncodeTimeChoice(NULL, &nssTime, date->nssTime);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_DERENCODETIMECHOICEFAILED);
+ }
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&nssTime, pString, plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+cleanup:
+ if (nssTime.data) {
+ SECITEM_FreeItem(&nssTime, PR_FALSE);
+ }
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ PKIX_UInt32 dateHash;
+
+ PKIX_ENTER(DATE, "pkix_pl_Date_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
+ PKIX_OBJECTNOTDATE);
+
+ date = (PKIX_PL_Date *)object;
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)&date->nssTime,
+ sizeof(date->nssTime),
+ &dateHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = dateHash;
+
+cleanup:
+
+ PKIX_RETURN(DATE);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_Comparator(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PRTime firstTime;
+ PRTime secondTime;
+ SECComparison cmpResult;
+
+ PKIX_ENTER(DATE, "pkix_pl_Date_Comparator");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_DATE_TYPE, plContext),
+ PKIX_ARGUMENTSNOTDATES);
+
+ firstTime = ((PKIX_PL_Date *)firstObject)->nssTime;
+ secondTime = ((PKIX_PL_Date *)secondObject)->nssTime;
+
+ if (firstTime == secondTime)
+ cmpResult = SECEqual;
+ else if (firstTime < secondTime)
+ cmpResult = SECLessThan;
+ else
+ cmpResult = SECGreaterThan;
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_ENTER(DATE, "pkix_pl_Date_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a Date */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_DATE_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTDATE);
+
+ /*
+ * Since we know firstObject is a Date, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ *pResult = PKIX_FALSE;
+ pkixErrorResult =
+ pkix_pl_Date_Comparator(firstObject, secondObject,
+ pResult, plContext);
+ if (pkixErrorResult) {
+ PKIX_DECREF(pkixErrorResult);
+ }
+
+cleanup:
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_DATE_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_Date_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_DATE_TYPE];
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_RegisterSelf");
+
+ entry->description = "Date";
+ entry->typeObjectSize = sizeof(PKIX_PL_Date);
+ entry->destructor = pkix_pl_Date_Destroy;
+ entry->equalsFunction = pkix_pl_Date_Equals;
+ entry->hashcodeFunction = pkix_pl_Date_Hashcode;
+ entry->toStringFunction = pkix_pl_Date_ToString;
+ entry->comparator = pkix_pl_Date_Comparator;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(DATE);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_Date_Create_UTCTime (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Date_Create_UTCTime(
+ PKIX_PL_String *stringRep,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ char *asciiString = NULL;
+ PKIX_UInt32 escAsciiLength;
+ SECStatus rv;
+ PRTime time;
+
+ PKIX_ENTER(DATE, "PKIX_PL_Date_Create_UTCTime");
+ PKIX_NULLCHECK_ONE(pDate);
+
+ if (stringRep == NULL){
+ PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n");
+ time = PR_Now();
+ } else {
+ /* convert the input PKIX_PL_String to PKIX_ESCASCII */
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stringRep,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &escAsciiLength,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DATE_DEBUG("\t\tCalling DER_AsciiToTime).\n");
+ /* DER_AsciiToTime only supports UTCTime (2-digit years) */
+ rv = DER_AsciiToTime(&time, asciiString);
+ if (rv != SECSuccess){
+ PKIX_ERROR(PKIX_DERASCIITOTIMEFAILED);
+ }
+ }
+
+ /* create a PKIX_PL_Date object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_DATE_TYPE,
+ sizeof (PKIX_PL_Date),
+ (PKIX_PL_Object **)&date,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* populate the nssTime field */
+ date->nssTime = time;
+ *pDate = date;
+
+cleanup:
+ PKIX_FREE(asciiString);
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Date_Create_CurrentOffBySeconds(
+ PKIX_Int32 secondsOffset,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ PRTime time;
+
+ PKIX_ENTER(DATE, "PKIX_PL_Date_Create_CurrentOffBySeconds");
+ PKIX_NULLCHECK_ONE(pDate);
+
+ time = PR_Now() + PR_SecondsToInterval(secondsOffset);
+ /* create a PKIX_PL_Date object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_DATE_TYPE,
+ sizeof (PKIX_PL_Date),
+ (PKIX_PL_Object **)&date,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* populate the nssTime field */
+ date->nssTime = time;
+ *pDate = date;
+
+cleanup:
+ PKIX_RETURN(DATE);
+}
+
+PKIX_Error *
+PKIX_PL_Date_CreateFromPRTime(
+ PRTime prtime,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime");
+ PKIX_CHECK(
+ pkix_pl_Date_CreateFromPRTime(prtime, pDate, plContext),
+ PKIX_DATECREATEFROMPRTIMEFAILED);
+
+cleanup:
+ PKIX_RETURN(DATE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h
new file mode 100644
index 0000000000..415597580a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h
@@ -0,0 +1,55 @@
+/* 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/. */
+/*
+ * pkix_pl_date.h
+ *
+ * Date Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_DATE_H
+#define _PKIX_PL_DATE_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_DateStruct{
+ PRTime nssTime;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_Date_ToString_Helper(
+ SECItem *nssTime,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *pkix_pl_Date_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_Date_GetPRTime(
+ PKIX_PL_Date *date,
+ PRTime *pPRTime,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Date_CreateFromPRTime(
+ PRTime prtime,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+PKIX_Error *
+PKIX_PL_Date_CreateFromPRTime(
+ PRTime prtime,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_DATE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c
new file mode 100644
index 0000000000..9e9a74c783
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c
@@ -0,0 +1,873 @@
+/* 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/. */
+/*
+ * pkix_pl_generalname.c
+ *
+ * GeneralName Object Definitions
+ *
+ */
+
+#include "pkix_pl_generalname.h"
+
+/* --Private-GeneralName-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_GetNssGeneralName
+ * DESCRIPTION:
+ *
+ * Retrieves the NSS representation of the PKIX_PL_GeneralName pointed by
+ * "genName" and stores it at "pNssGenName". The NSS data type CERTGeneralName
+ * is stored in this object when the object was created.
+ *
+ * PARAMETERS:
+ * "genName"
+ * Address of PKIX_PL_GeneralName. Must be non-NULL.
+ * "pNssGenName"
+ * Address where CERTGeneralName will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_GeneralName_GetNssGeneralName(
+ PKIX_PL_GeneralName *genName,
+ CERTGeneralName **pNssGenName,
+ void *plContext)
+{
+ CERTGeneralName *nssGenName = NULL;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_GetNssGeneralName");
+ PKIX_NULLCHECK_THREE(genName, pNssGenName, genName->nssGeneralNameList);
+
+ nssGenName = genName->nssGeneralNameList->name;
+
+ *pNssGenName = nssGenName;
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_OtherName_Create
+ * DESCRIPTION:
+ *
+ * Creates new OtherName which represents the CERTGeneralName pointed to by
+ * "nssAltName" and stores it at "pOtherName".
+ *
+ * PARAMETERS:
+ * "nssAltName"
+ * Address of CERTGeneralName. Must be non-NULL.
+ * "pOtherName"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_OtherName_Create(
+ CERTGeneralName *nssAltName,
+ OtherName **pOtherName,
+ void *plContext)
+{
+ OtherName *otherName = NULL;
+ SECItem secItemName;
+ SECItem secItemOID;
+ SECStatus rv;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_OtherName_Create");
+ PKIX_NULLCHECK_TWO(nssAltName, pOtherName);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (OtherName), (void **)&otherName, plContext),
+ PKIX_MALLOCFAILED);
+
+ /* make a copy of the name field */
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
+ rv = SECITEM_CopyItem
+ (NULL, &otherName->name, &nssAltName->name.OthName.name);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ /* make a copy of the oid field */
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
+ rv = SECITEM_CopyItem
+ (NULL, &otherName->oid, &nssAltName->name.OthName.oid);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ *pOtherName = otherName;
+
+cleanup:
+
+ if (otherName && PKIX_ERROR_RECEIVED){
+ secItemName = otherName->name;
+ secItemOID = otherName->oid;
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&secItemName, PR_FALSE);
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&secItemOID, PR_FALSE);
+
+ PKIX_FREE(otherName);
+ otherName = NULL;
+ }
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_DirectoryName_Create
+ * DESCRIPTION:
+ *
+ * Creates a new X500Name which represents the directoryName component of the
+ * CERTGeneralName pointed to by "nssAltName" and stores it at "pX500Name".
+ *
+ * PARAMETERS:
+ * "nssAltName"
+ * Address of CERTGeneralName. Must be non-NULL.
+ * "pX500Name"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_DirectoryName_Create(
+ CERTGeneralName *nssAltName,
+ PKIX_PL_X500Name **pX500Name,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixDN = NULL;
+ CERTName *dirName = NULL;
+ PKIX_PL_String *pkixDNString = NULL;
+ char *utf8String = NULL;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_DirectoryName_Create");
+ PKIX_NULLCHECK_TWO(nssAltName, pX500Name);
+
+ dirName = &nssAltName->name.directoryName;
+
+ PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName(NULL, dirName,
+ &pkixDN, plContext),
+ PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
+
+ *pX500Name = pkixDN;
+
+cleanup:
+
+ PR_Free(utf8String);
+ PKIX_DECREF(pkixDNString);
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_Create
+ * DESCRIPTION:
+ *
+ * Creates new GeneralName which represents the CERTGeneralName pointed to by
+ * "nssAltName" and stores it at "pGenName".
+ *
+ * PARAMETERS:
+ * "nssAltName"
+ * Address of CERTGeneralName. Must be non-NULL.
+ * "pGenName"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_GeneralName_Create(
+ CERTGeneralName *nssAltName,
+ PKIX_PL_GeneralName **pGenName,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *genName = NULL;
+ PKIX_PL_X500Name *pkixDN = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+ OtherName *otherName = NULL;
+ CERTGeneralNameList *nssGenNameList = NULL;
+ CERTGeneralNameType nameType;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Create");
+ PKIX_NULLCHECK_TWO(nssAltName, pGenName);
+
+ /* create a PKIX_PL_GeneralName object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_GENERALNAME_TYPE,
+ sizeof (PKIX_PL_GeneralName),
+ (PKIX_PL_Object **)&genName,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ nameType = nssAltName->type;
+
+ /*
+ * We use CERT_CreateGeneralNameList to create just one CERTGeneralName
+ * item for memory allocation reason. If we want to just create one
+ * item, we have to use the calling path CERT_NewGeneralName, then
+ * CERT_CopyOneGeneralName. With this calling path, if we pass
+ * the arena argument as NULL, in CERT_CopyOneGeneralName's subsequent
+ * call to CERT_CopyName, it assumes arena should be valid, hence
+ * segmentation error (not sure this is a NSS bug, certainly it is
+ * not consistent). But on the other hand, we don't want to keep an
+ * arena record here explicitely for every PKIX_PL_GeneralName.
+ * So I concluded it is better to use CERT_CreateGeneralNameList,
+ * which keeps an arena pointer in its data structure and also masks
+ * out details calls from this libpkix level.
+ */
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
+ nssGenNameList = CERT_CreateGeneralNameList(nssAltName);
+
+ if (nssGenNameList == NULL) {
+ PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
+ }
+
+ genName->nssGeneralNameList = nssGenNameList;
+
+ /* initialize fields */
+ genName->type = nameType;
+ genName->directoryName = NULL;
+ genName->OthName = NULL;
+ genName->other = NULL;
+ genName->oid = NULL;
+
+ switch (nameType){
+ case certOtherName:
+
+ PKIX_CHECK(pkix_pl_OtherName_Create
+ (nssAltName, &otherName, plContext),
+ PKIX_OTHERNAMECREATEFAILED);
+
+ genName->OthName = otherName;
+ break;
+
+ case certDirectoryName:
+
+ PKIX_CHECK(pkix_pl_DirectoryName_Create
+ (nssAltName, &pkixDN, plContext),
+ PKIX_DIRECTORYNAMECREATEFAILED);
+
+ genName->directoryName = pkixDN;
+ break;
+ case certRegisterID:
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem(&nssAltName->name.other,
+ &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ genName->oid = pkixOID;
+ break;
+ case certDNSName:
+ case certEDIPartyName:
+ case certIPAddress:
+ case certRFC822Name:
+ case certX400Address:
+ case certURI:
+ genName->other = SECITEM_DupItem(&nssAltName->name.other);
+ if (!genName->other) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ break;
+ default:
+ PKIX_ERROR(PKIX_NAMETYPENOTSUPPORTED);
+ }
+
+ *pGenName = genName;
+ genName = NULL;
+
+cleanup:
+ PKIX_DECREF(genName);
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the GeneralName
+ * pointed to by "name" and stores it at "pString" Different mechanisms are
+ * used to create the string, depending on the type of the GeneralName.
+ *
+ * PARAMETERS
+ * "name"
+ * Address of GeneralName whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_ToString_Helper(
+ PKIX_PL_GeneralName *name,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixDN = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+ char *x400AsciiName = NULL;
+ char *ediPartyName = NULL;
+ char *asciiName = NULL;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_ToString_Helper");
+ PKIX_NULLCHECK_TWO(name, pString);
+
+ switch (name->type) {
+ case certRFC822Name:
+ case certDNSName:
+ case certURI:
+ /*
+ * Note that we can't use PKIX_ESCASCII here because
+ * name->other->data is not guaranteed to be null-terminated.
+ */
+
+ PKIX_NULLCHECK_ONE(name->other);
+
+ PKIX_CHECK(PKIX_PL_String_Create(PKIX_UTF8,
+ (name->other)->data,
+ (name->other)->len,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certEDIPartyName:
+ /* XXX print out the actual bytes */
+ ediPartyName = "EDIPartyName: <DER-encoded value>";
+ PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
+ ediPartyName,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certX400Address:
+ /* XXX print out the actual bytes */
+ x400AsciiName = "X400Address: <DER-encoded value>";
+ PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
+ x400AsciiName,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certIPAddress:
+ PKIX_CHECK(pkix_pl_ipAddrBytes2Ascii
+ (name->other, &asciiName, plContext),
+ PKIX_IPADDRBYTES2ASCIIFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
+ asciiName,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certOtherName:
+ PKIX_NULLCHECK_ONE(name->OthName);
+
+ /* we only print type-id - don't know how to print value */
+ /* XXX print out the bytes of the value */
+ PKIX_CHECK(pkix_pl_oidBytes2Ascii
+ (&name->OthName->oid, &asciiName, plContext),
+ PKIX_OIDBYTES2ASCIIFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiName,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certRegisterID:
+ pkixOID = name->oid;
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)pkixOID, pString, plContext),
+ PKIX_OIDTOSTRINGFAILED);
+ break;
+ case certDirectoryName:
+ pkixDN = name->directoryName;
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)pkixDN, pString, plContext),
+ PKIX_X500NAMETOSTRINGFAILED);
+ break;
+ default:
+ PKIX_ERROR
+ (PKIX_TOSTRINGFORTHISGENERALNAMETYPENOTSUPPORTED);
+ }
+
+cleanup:
+
+ PKIX_FREE(asciiName);
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *name = NULL;
+ SECItem secItemName;
+ SECItem secItemOID;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
+ PKIX_OBJECTNOTGENERALNAME);
+
+ name = (PKIX_PL_GeneralName *)object;
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(name->other, PR_TRUE);
+ name->other = NULL;
+
+ if (name->OthName){
+ secItemName = name->OthName->name;
+ secItemOID = name->OthName->oid;
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&secItemName, PR_FALSE);
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&secItemOID, PR_FALSE);
+
+ PKIX_FREE(name->OthName);
+ name->OthName = NULL;
+ }
+
+ if (name->nssGeneralNameList != NULL) {
+ PKIX_GENERALNAME_DEBUG
+ ("\t\tCalling CERT_DestroyGeneralNameList).\n");
+ CERT_DestroyGeneralNameList(name->nssGeneralNameList);
+ }
+
+ PKIX_DECREF(name->directoryName);
+ PKIX_DECREF(name->oid);
+
+cleanup:
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *nameString = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
+ PKIX_OBJECTNOTGENERALNAME);
+
+ name = (PKIX_PL_GeneralName *)object;
+
+ PKIX_CHECK(pkix_pl_GeneralName_ToString_Helper
+ (name, &nameString, plContext),
+ PKIX_GENERALNAMETOSTRINGHELPERFAILED);
+
+ *pString = nameString;
+
+cleanup:
+
+
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 firstHash, secondHash, nameHash;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
+ PKIX_OBJECTNOTGENERALNAME);
+
+ name = (PKIX_PL_GeneralName *)object;
+
+ switch (name->type) {
+ case certRFC822Name:
+ case certDNSName:
+ case certX400Address:
+ case certEDIPartyName:
+ case certURI:
+ case certIPAddress:
+ PKIX_NULLCHECK_ONE(name->other);
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)
+ name->other->data,
+ name->other->len,
+ &nameHash,
+ plContext),
+ PKIX_HASHFAILED);
+ break;
+ case certRegisterID:
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)name->oid,
+ &nameHash,
+ plContext),
+ PKIX_OIDHASHCODEFAILED);
+ break;
+ case certOtherName:
+ PKIX_NULLCHECK_ONE(name->OthName);
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)
+ name->OthName->oid.data,
+ name->OthName->oid.len,
+ &firstHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)
+ name->OthName->name.data,
+ name->OthName->name.len,
+ &secondHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ nameHash = firstHash + secondHash;
+ break;
+ case certDirectoryName:
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)
+ name->directoryName,
+ &nameHash,
+ plContext),
+ PKIX_X500NAMEHASHCODEFAILED);
+ break;
+ }
+
+ *pHashcode = nameHash;
+
+cleanup:
+
+ PKIX_RETURN(GENERALNAME);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *firstName = NULL;
+ PKIX_PL_GeneralName *secondName = NULL;
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a GeneralName */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_GENERALNAME_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTGENERALNAME);
+
+ /*
+ * Since we know firstObject is a GeneralName, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a GeneralName, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_GENERALNAME_TYPE){
+ goto cleanup;
+ }
+
+ firstName = (PKIX_PL_GeneralName *)firstObject;
+ secondName = (PKIX_PL_GeneralName *)secondObject;
+
+ if (firstName->type != secondName->type){
+ goto cleanup;
+ }
+
+ switch (firstName->type) {
+ case certRFC822Name:
+ case certDNSName:
+ case certX400Address:
+ case certEDIPartyName:
+ case certURI:
+ case certIPAddress:
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
+ if (SECITEM_CompareItem(firstName->other,
+ secondName->other) != SECEqual) {
+ goto cleanup;
+ }
+ break;
+ case certRegisterID:
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstName->oid,
+ (PKIX_PL_Object *)secondName->oid,
+ pResult,
+ plContext),
+ PKIX_OIDEQUALSFAILED);
+ goto cleanup;
+ case certOtherName:
+ PKIX_NULLCHECK_TWO(firstName->OthName, secondName->OthName);
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
+ if (SECITEM_CompareItem(&firstName->OthName->oid,
+ &secondName->OthName->oid)
+ != SECEqual ||
+ SECITEM_CompareItem(&firstName->OthName->name,
+ &secondName->OthName->name)
+ != SECEqual) {
+ goto cleanup;
+ }
+ break;
+ case certDirectoryName:
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstName->directoryName,
+ (PKIX_PL_Object *)secondName->directoryName,
+ pResult,
+ plContext),
+ PKIX_X500NAMEEQUALSFAILED);
+ goto cleanup;
+ }
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_GENERALNAME_TYPE and related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_GeneralName_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_RegisterSelf");
+
+ entry.description = "GeneralName";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_GeneralName);
+ entry.destructor = pkix_pl_GeneralName_Destroy;
+ entry.equalsFunction = pkix_pl_GeneralName_Equals;
+ entry.hashcodeFunction = pkix_pl_GeneralName_Hashcode;
+ entry.toStringFunction = pkix_pl_GeneralName_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_GENERALNAME_TYPE] = entry;
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: PKIX_PL_GeneralName_Create (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_GeneralName_Create(
+ PKIX_UInt32 nameType,
+ PKIX_PL_String *stringRep,
+ PKIX_PL_GeneralName **pGName,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixDN = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+ SECItem *secItem = NULL;
+ char *asciiString = NULL;
+ PKIX_UInt32 length = 0;
+ PKIX_PL_GeneralName *genName = NULL;
+ CERTGeneralName *nssGenName = NULL;
+ CERTGeneralNameList *nssGenNameList = NULL;
+ CERTName *nssCertName = NULL;
+ PLArenaPool *arena = NULL;
+
+ PKIX_ENTER(GENERALNAME, "PKIX_PL_GeneralName_Create");
+ PKIX_NULLCHECK_TWO(pGName, stringRep);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stringRep,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ /* Create a temporary CERTGeneralName */
+ PKIX_GENERALNAME_DEBUG("\t\tCalling PL_strlen).\n");
+ length = PL_strlen(asciiString);
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_AllocItem).\n");
+ secItem = SECITEM_AllocItem(NULL, NULL, length);
+ PKIX_GENERALNAME_DEBUG("\t\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy(secItem->data, asciiString, length);
+ PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena).\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_NewGeneralName).\n");
+ nssGenName = CERT_NewGeneralName(arena, nameType);
+ if (nssGenName == NULL) {
+ PKIX_ERROR(PKIX_ALLOCATENEWCERTGENERALNAMEFAILED);
+ }
+
+ switch (nameType) {
+ case certRFC822Name:
+ case certDNSName:
+ case certURI:
+ nssGenName->name.other = *secItem;
+ break;
+
+ case certDirectoryName:
+
+ PKIX_CHECK(PKIX_PL_X500Name_Create
+ (stringRep, &pkixDN, plContext),
+ PKIX_X500NAMECREATEFAILED);
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_AsciiToName).\n");
+ nssCertName = CERT_AsciiToName(asciiString);
+ nssGenName->name.directoryName = *nssCertName;
+ break;
+
+ case certRegisterID:
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (asciiString, &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+ nssGenName->name.other = *secItem;
+ break;
+ default:
+ /* including IPAddress, EDIPartyName, OtherName, X400Address */
+ PKIX_ERROR(PKIX_UNABLETOCREATEGENERALNAMEOFTHISTYPE);
+ }
+
+ /* create a PKIX_PL_GeneralName object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_GENERALNAME_TYPE,
+ sizeof (PKIX_PL_GeneralName),
+ (PKIX_PL_Object **)&genName,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* create a CERTGeneralNameList */
+ nssGenName->type = nameType;
+ PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
+ nssGenNameList = CERT_CreateGeneralNameList(nssGenName);
+ if (nssGenNameList == NULL) {
+ PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
+ }
+ genName->nssGeneralNameList = nssGenNameList;
+
+ /* initialize fields */
+ genName->type = nameType;
+ genName->directoryName = pkixDN;
+ genName->OthName = NULL;
+ genName->other = secItem;
+ genName->oid = pkixOID;
+
+ *pGName = genName;
+cleanup:
+
+ PKIX_FREE(asciiString);
+
+ if (nssCertName != NULL) {
+ PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyName).\n");
+ CERT_DestroyName(nssCertName);
+ }
+
+ if (arena){ /* will free nssGenName */
+ PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(pkixDN);
+ PKIX_DECREF(pkixOID);
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ if (secItem){
+ SECITEM_FreeItem(secItem, PR_TRUE);
+ secItem = NULL;
+ }
+ }
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+#endif /* BUILD_LIBPKIX_TESTS */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h
new file mode 100644
index 0000000000..3cb5264d51
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h
@@ -0,0 +1,49 @@
+/* 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/. */
+/*
+ * pkix_pl_generalname.h
+ *
+ * GeneralName Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_GENERALNAME_H
+#define _PKIX_PL_GENERALNAME_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_GeneralNameStruct{
+ CERTGeneralNameList *nssGeneralNameList;
+ CERTGeneralNameType type;
+ PKIX_PL_X500Name *directoryName;
+ PKIX_PL_OID *oid;
+ OtherName *OthName;
+ SECItem *other;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_GeneralName_Create(
+ CERTGeneralName *nssAltName,
+ PKIX_PL_GeneralName **pGenName,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_GeneralName_GetNssGeneralName(
+ PKIX_PL_GeneralName *genName,
+ CERTGeneralName **pNssGenName,
+ void *plContext);
+
+PKIX_Error *pkix_pl_GeneralName_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_GENERALNAME_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c
new file mode 100644
index 0000000000..09b54a2be3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c
@@ -0,0 +1,874 @@
+/* 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/. */
+/*
+ * pkix_pl_infoaccess.c
+ *
+ * InfoAccess Object Definitions
+ *
+ */
+
+#include "pkix_pl_infoaccess.h"
+
+/* --Private-InfoAccess-Functions----------------------------------*/
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_Create
+ * DESCRIPTION:
+ *
+ * This function creates an InfoAccess from the method provided in "method" and
+ * the GeneralName provided in "generalName" and stores the result at
+ * "pInfoAccess".
+ *
+ * PARAMETERS
+ * "method"
+ * The UInt32 value to be stored as the method field of the InfoAccess.
+ * "gName"
+ * The GeneralName to be stored as the gName field of the InfoAccess.
+ * Must be non-NULL.
+ * "pInfoAccess"
+ * Address where the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_Create(
+ PKIX_UInt32 method,
+ PKIX_PL_GeneralName *gName,
+ PKIX_PL_InfoAccess **pInfoAccess,
+ void *plContext)
+{
+
+ PKIX_PL_InfoAccess *infoAccess = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Create");
+ PKIX_NULLCHECK_TWO(gName, pInfoAccess);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_INFOACCESS_TYPE,
+ sizeof (PKIX_PL_InfoAccess),
+ (PKIX_PL_Object **)&infoAccess,
+ plContext),
+ PKIX_COULDNOTCREATEINFOACCESSOBJECT);
+
+ infoAccess->method = method;
+
+ PKIX_INCREF(gName);
+ infoAccess->location = gName;
+
+ *pInfoAccess = infoAccess;
+ infoAccess = NULL;
+
+cleanup:
+ PKIX_DECREF(infoAccess);
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_InfoAccess *infoAccess = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_INFOACCESS_TYPE, plContext),
+ PKIX_OBJECTNOTANINFOACCESS);
+
+ infoAccess = (PKIX_PL_InfoAccess *)object;
+
+ PKIX_DECREF(infoAccess->location);
+
+cleanup:
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_InfoAccess *infoAccess;
+ PKIX_PL_String *infoAccessString = NULL;
+ char *asciiFormat = NULL;
+ char *asciiMethod = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *methodString = NULL;
+ PKIX_PL_String *locationString = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_INFOACCESS_TYPE, plContext),
+ PKIX_OBJECTNOTINFOACCESS);
+
+ infoAccess = (PKIX_PL_InfoAccess *)object;
+
+ asciiFormat =
+ "["
+ "method:%s, "
+ "location:%s"
+ "]";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ switch(infoAccess->method) {
+ case PKIX_INFOACCESS_CA_ISSUERS:
+ asciiMethod = "caIssuers";
+ break;
+ case PKIX_INFOACCESS_OCSP:
+ asciiMethod = "ocsp";
+ break;
+ case PKIX_INFOACCESS_TIMESTAMPING:
+ asciiMethod = "timestamping";
+ break;
+ case PKIX_INFOACCESS_CA_REPOSITORY:
+ asciiMethod = "caRepository";
+ break;
+ default:
+ asciiMethod = "unknown";
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiMethod,
+ 0,
+ &methodString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING(infoAccess->location, &locationString, plContext,
+ PKIX_GENERALNAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&infoAccessString,
+ plContext,
+ formatString,
+ methodString,
+ locationString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = infoAccessString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(methodString);
+ PKIX_DECREF(locationString);
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_InfoAccess *infoAccess = NULL;
+ PKIX_UInt32 infoAccessHash;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_INFOACCESS_TYPE, plContext),
+ PKIX_OBJECTNOTINFOACCESS);
+
+ infoAccess = (PKIX_PL_InfoAccess *)object;
+
+ PKIX_HASHCODE(infoAccess->location, &infoAccessHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ infoAccessHash += (infoAccess->method << 7);
+
+ *pHashcode = infoAccessHash;
+
+cleanup:
+
+ PKIX_RETURN(INFOACCESS);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_InfoAccess *firstInfoAccess = NULL;
+ PKIX_PL_InfoAccess *secondInfoAccess = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a InfoAccess */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_INFOACCESS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTINFOACCESS);
+
+ /*
+ * Since we know firstObject is a InfoAccess, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a InfoAccess, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_INFOACCESS_TYPE) goto cleanup;
+
+ firstInfoAccess = (PKIX_PL_InfoAccess *)firstObject;
+ secondInfoAccess = (PKIX_PL_InfoAccess *)secondObject;
+
+ *pResult = PKIX_FALSE;
+
+ if (firstInfoAccess->method != secondInfoAccess->method) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS(firstInfoAccess, secondInfoAccess, &cmpResult, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_INFOACCESS_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_InfoAccess_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(INFOACCESS,
+ "pkix_pl_InfoAccess_RegisterSelf");
+
+ entry.description = "InfoAccess";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_InfoAccess);
+ entry.destructor = pkix_pl_InfoAccess_Destroy;
+ entry.equalsFunction = pkix_pl_InfoAccess_Equals;
+ entry.hashcodeFunction = pkix_pl_InfoAccess_Hashcode;
+ entry.toStringFunction = pkix_pl_InfoAccess_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_INFOACCESS_TYPE] = entry;
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_CreateList
+ * DESCRIPTION:
+ *
+ * Based on data in CERTAuthInfoAccess array "nssInfoAccess", this function
+ * creates and returns a PKIX_List of PKIX_PL_InfoAccess at "pInfoAccessList".
+ *
+ * PARAMETERS
+ * "nssInfoAccess"
+ * The pointer array of CERTAuthInfoAccess that contains access data.
+ * May be NULL.
+ * "pInfoAccessList"
+ * Address where a list of PKIX_PL_InfoAccess is returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_InfoAccess_CreateList(
+ CERTAuthInfoAccess **nssInfoAccess,
+ PKIX_List **pInfoAccessList, /* of PKIX_PL_InfoAccess */
+ void *plContext)
+{
+ PKIX_List *infoAccessList = NULL;
+ PKIX_PL_InfoAccess *infoAccess = NULL;
+ PKIX_PL_GeneralName *location = NULL;
+ PKIX_UInt32 method;
+ int i;
+
+ PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_CreateList");
+ PKIX_NULLCHECK_ONE(pInfoAccessList);
+
+ PKIX_CHECK(PKIX_List_Create(&infoAccessList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ if (nssInfoAccess == NULL) {
+ goto cleanup;
+ }
+
+ for (i = 0; nssInfoAccess[i] != NULL; i++) {
+
+ if (nssInfoAccess[i]->location == NULL) {
+ continue;
+ }
+
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (nssInfoAccess[i]->location, &location, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CERT_DEBUG("\t\tCalling SECOID_FindOIDTag).\n");
+ method = SECOID_FindOIDTag(&nssInfoAccess[i]->method);
+ /* Map NSS access method value into PKIX constant */
+ switch(method) {
+ case SEC_OID_PKIX_CA_ISSUERS:
+ method = PKIX_INFOACCESS_CA_ISSUERS;
+ break;
+ case SEC_OID_PKIX_OCSP:
+ method = PKIX_INFOACCESS_OCSP;
+ break;
+ case SEC_OID_PKIX_TIMESTAMPING:
+ method = PKIX_INFOACCESS_TIMESTAMPING;
+ break;
+ case SEC_OID_PKIX_CA_REPOSITORY:
+ method = PKIX_INFOACCESS_CA_REPOSITORY;
+ break;
+ default:
+ PKIX_ERROR(PKIX_UNKNOWNINFOACCESSMETHOD);
+ }
+
+ PKIX_CHECK(pkix_pl_InfoAccess_Create
+ (method, location, &infoAccess, plContext),
+ PKIX_INFOACCESSCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (infoAccessList,
+ (PKIX_PL_Object *)infoAccess,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(infoAccess);
+ PKIX_DECREF(location);
+ }
+
+ *pInfoAccessList = infoAccessList;
+ infoAccessList = NULL;
+
+cleanup:
+
+ PKIX_DECREF(infoAccessList);
+ PKIX_DECREF(infoAccess);
+ PKIX_DECREF(location);
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_InfoAccess_GetMethod (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_InfoAccess_GetMethod(
+ PKIX_PL_InfoAccess *infoAccess,
+ PKIX_UInt32 *pMethod,
+ void *plContext)
+{
+ PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetMethod");
+ PKIX_NULLCHECK_TWO(infoAccess, pMethod);
+
+ *pMethod = infoAccess->method;
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: PKIX_PL_InfoAccess_GetLocation (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_InfoAccess_GetLocation(
+ PKIX_PL_InfoAccess *infoAccess,
+ PKIX_PL_GeneralName **pLocation,
+ void *plContext)
+{
+ PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetLocation");
+ PKIX_NULLCHECK_TWO(infoAccess, pLocation);
+
+ PKIX_INCREF(infoAccess->location);
+
+ *pLocation = infoAccess->location;
+
+cleanup:
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: PKIX_PL_InfoAccess_GetLocationType (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_InfoAccess_GetLocationType(
+ PKIX_PL_InfoAccess *infoAccess,
+ PKIX_UInt32 *pType,
+ void *plContext)
+{
+ PKIX_PL_String *locationString = NULL;
+ PKIX_UInt32 type = PKIX_INFOACCESS_LOCATION_UNKNOWN;
+ PKIX_UInt32 len = 0;
+ void *location = NULL;
+
+ PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetLocationType");
+ PKIX_NULLCHECK_TWO(infoAccess, pType);
+
+ if (infoAccess->location != NULL) {
+
+ PKIX_TOSTRING(infoAccess->location, &locationString, plContext,
+ PKIX_GENERALNAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (locationString, PKIX_ESCASCII, &location, &len, plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n");
+#ifndef NSS_PKIX_NO_LDAP
+ if (PORT_Strncmp(location, "ldap:", 5) == 0){
+ type = PKIX_INFOACCESS_LOCATION_LDAP;
+ } else
+#endif
+ if (PORT_Strncmp(location, "http:", 5) == 0){
+ type = PKIX_INFOACCESS_LOCATION_HTTP;
+ }
+ }
+
+ *pType = type;
+
+cleanup:
+
+ PKIX_PL_Free(location, plContext);
+ PKIX_DECREF(locationString);
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+#ifndef NSS_PKIX_NO_LDAP
+/*
+ * FUNCTION: pkix_pl_InfoAccess_ParseTokens
+ * DESCRIPTION:
+ *
+ * This function parses the string beginning at "startPos" into tokens using
+ * the separator contained in "separator" and the terminator contained in
+ * "terminator", copying the tokens into space allocated from the arena
+ * pointed to by "arena". It stores in "tokens" a null-terminated array of
+ * pointers to those tokens.
+ *
+ * PARAMETERS
+ * "arena"
+ * Address of a PLArenaPool to be used in populating the LDAPLocation.
+ * Must be non-NULL.
+ * "startPos"
+ * The address of char string that contains a subset of ldap location.
+ * "tokens"
+ * The address of an array of char string for storing returned tokens.
+ * Must be non-NULL.
+ * "separator"
+ * The character that is taken as token separator. Must be non-NULL.
+ * "terminator"
+ * The character that is taken as parsing terminator. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an InfoAccess Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_ParseTokens(
+ PLArenaPool *arena,
+ char **startPos, /* return update */
+ char ***tokens,
+ char separator,
+ char terminator,
+ void *plContext)
+{
+ PKIX_UInt32 numFilters = 0;
+ char *endPos = NULL;
+ char **filterP = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseTokens");
+ PKIX_NULLCHECK_THREE(arena, startPos, tokens);
+
+ endPos = *startPos;
+
+ /* First pass: parse to <terminator> to count number of components */
+ numFilters = 0;
+ while (*endPos != terminator && *endPos != '\0') {
+ endPos++;
+ if (*endPos == separator) {
+ numFilters++;
+ }
+ }
+
+ if (*endPos != terminator) {
+ PKIX_ERROR(PKIX_LOCATIONSTRINGNOTPROPERLYTERMINATED);
+ }
+
+ /* Last component doesn't need a separator, although we allow it */
+ if (endPos > *startPos && *(endPos-1) != separator) {
+ numFilters++;
+ }
+
+ /*
+ * If string is a=xx, b=yy, c=zz, etc., use a=xx for filter,
+ * and everything else for the base
+ */
+ if (numFilters > 2) numFilters = 2;
+
+ filterP = PORT_ArenaZNewArray(arena, char*, numFilters+1);
+ if (filterP == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ /* Second pass: parse to fill in components in token array */
+ *tokens = filterP;
+ endPos = *startPos;
+
+ while (numFilters) {
+ if (*endPos == separator || *endPos == terminator) {
+ PKIX_UInt32 len = endPos - *startPos;
+ char *p = PORT_ArenaZAlloc(arena, len+1);
+ if (p == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PORT_Memcpy(p, *startPos, len);
+ p[len] = '\0';
+
+ *filterP = p;
+ filterP++;
+ numFilters--;
+
+ separator = terminator;
+
+ if (*endPos == '\0') {
+ *startPos = endPos;
+ break;
+ } else {
+ endPos++;
+ *startPos = endPos;
+ continue;
+ }
+ }
+ endPos++;
+ }
+
+ *filterP = NULL;
+
+cleanup:
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+static int
+pkix_pl_HexDigitToInt(
+ int ch)
+{
+ if (isdigit(ch)) {
+ ch = ch - '0';
+ } else if (isupper(ch)) {
+ ch = ch - 'A' + 10;
+ } else {
+ ch = ch - 'a' + 10;
+ }
+ return ch;
+}
+
+/*
+ * Convert the "%" hex hex escape sequences in the URL 'location' in place.
+ */
+static void
+pkix_pl_UnescapeURL(
+ char *location)
+{
+ const char *src;
+ char *dst;
+
+ for (src = dst = location; *src != '\0'; src++, dst++) {
+ if (*src == '%' && isxdigit((unsigned char)*(src+1)) &&
+ isxdigit((unsigned char)*(src+2))) {
+ *dst = pkix_pl_HexDigitToInt((unsigned char)*(src+1));
+ *dst *= 16;
+ *dst += pkix_pl_HexDigitToInt((unsigned char)*(src+2));
+ src += 2;
+ } else {
+ *dst = *src;
+ }
+ }
+ *dst = *src; /* the terminating null */
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_ParseLocation
+ * DESCRIPTION:
+ *
+ * This function parses the GeneralName pointed to by "generalName" into the
+ * fields of the LDAPRequestParams pointed to by "request" and a domainName
+ * pointed to by "pDomainName", using the PLArenaPool pointed to by "arena" to
+ * allocate storage for the request components and for the domainName string.
+ *
+ * The expected GeneralName string should be in the format described by the
+ * following BNF:
+ *
+ * ldap://<ldap-server-site>/[cn=<cname>][,o=<org>][,c=<country>]?
+ * [caCertificate|crossCertificatPair|certificateRevocationList];
+ * [binary|<other-type>]
+ * [[,caCertificate|crossCertificatPair|certificateRevocationList]
+ * [binary|<other-type>]]*
+ *
+ * PARAMETERS
+ * "gName"
+ * Address of the GeneralName whose LDAPLocation is to be parsed. Must be
+ * non-NULL.
+ * "arena"
+ * Address of PLArenaPool to be used for the domainName and for components
+ * of the LDAPRequest. Must be non-NULL.
+ * "request"
+ * Address of the LDAPRequestParams into which request components are
+ * stored. Must be non-NULL.
+ * *pDomainName"
+ * Address at which the domainName is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an InfoAccess Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_InfoAccess_ParseLocation(
+ PKIX_PL_GeneralName *gName,
+ PLArenaPool *arena,
+ LDAPRequestParams *request,
+ char **pDomainName,
+ void *plContext)
+{
+ PKIX_PL_String *locationString = NULL;
+ PKIX_UInt32 len = 0;
+ PKIX_UInt32 ncIndex = 0;
+ char *domainName = NULL;
+ char **avaArray = NULL;
+ char **attrArray = NULL;
+ char *attr = NULL;
+ char *locationAscii = NULL;
+ char *startPos = NULL;
+ char *endPos = NULL;
+ char *avaPtr = NULL;
+ LdapAttrMask attrBit = 0;
+ LDAPNameComponent **setOfNameComponent = NULL;
+ LDAPNameComponent *nameComponent = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseLocation");
+ PKIX_NULLCHECK_FOUR(gName, arena, request, pDomainName);
+
+ PKIX_TOSTRING(gName, &locationString, plContext,
+ PKIX_GENERALNAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (locationString,
+ PKIX_ESCASCII,
+ (void **)&locationAscii,
+ &len,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ pkix_pl_UnescapeURL(locationAscii);
+
+ /* Skip "ldap:" */
+ endPos = locationAscii;
+ while (*endPos != ':' && *endPos != '\0') {
+ endPos++;
+ }
+ if (*endPos == '\0') {
+ PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGLOCATIONTYPE);
+ }
+
+ /* Skip "//" */
+ endPos++;
+ if (*endPos != '\0' && *(endPos+1) != '0' &&
+ *endPos == '/' && *(endPos+1) == '/') {
+ endPos += 2;
+ } else {
+ PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGDOUBLESLASH);
+ }
+
+ /* Get the server-site */
+ startPos = endPos;
+ while(*endPos != '/' && *(endPos) != '\0') {
+ endPos++;
+ }
+ if (*endPos == '\0') {
+ PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGSERVERSITE);
+ }
+
+ len = endPos - startPos;
+ endPos++;
+
+ domainName = PORT_ArenaZAlloc(arena, len + 1);
+ if (!domainName) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PORT_Memcpy(domainName, startPos, len);
+
+ domainName[len] = '\0';
+
+ *pDomainName = domainName;
+
+ /*
+ * Get a list of AttrValueAssertions (such as
+ * "cn=CommonName, o=Organization, c=US" into a null-terminated array
+ */
+ startPos = endPos;
+ PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
+ (arena,
+ &startPos,
+ (char ***) &avaArray,
+ ',',
+ '?',
+ plContext),
+ PKIX_INFOACCESSPARSETOKENSFAILED);
+
+ /* Count how many AVAs we have */
+ for (len = 0; avaArray[len] != NULL; len++) {}
+
+ if (len < 2) {
+ PKIX_ERROR(PKIX_NOTENOUGHNAMECOMPONENTSINGENERALNAME);
+ }
+
+ /* Use last name component for baseObject */
+ request->baseObject = avaArray[len - 1];
+
+ /* Use only one component for filter. LDAP servers aren't too smart. */
+ len = 2; /* Eliminate this when servers get smarter. */
+
+ avaArray[len - 1] = NULL;
+
+ /* Get room for null-terminated array of (LdapNameComponent *) */
+ setOfNameComponent = PORT_ArenaZNewArray(arena, LDAPNameComponent *, len);
+ if (setOfNameComponent == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ /* Get room for the remaining LdapNameComponents */
+ nameComponent = PORT_ArenaZNewArray(arena, LDAPNameComponent, --len);
+ if (nameComponent == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ /* Convert remaining AVAs to LDAPNameComponents */
+ for (ncIndex = 0; ncIndex < len; ncIndex ++) {
+ setOfNameComponent[ncIndex] = nameComponent;
+ avaPtr = avaArray[ncIndex];
+ nameComponent->attrType = (unsigned char *)avaPtr;
+ while ((*avaPtr != '=') && (*avaPtr != '\0')) {
+ avaPtr++;
+ if (*avaPtr == '\0') {
+ PKIX_ERROR(PKIX_NAMECOMPONENTWITHNOEQ);
+ }
+ }
+ *(avaPtr++) = '\0';
+ nameComponent->attrValue = (unsigned char *)avaPtr;
+ nameComponent++;
+ }
+
+ setOfNameComponent[len] = NULL;
+ request->nc = setOfNameComponent;
+
+ /*
+ * Get a list of AttrTypes (such as
+ * "caCertificate;binary, crossCertificatePair;binary") into
+ * a null-terminated array
+ */
+
+ PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
+ (arena,
+ (char **) &startPos,
+ (char ***) &attrArray,
+ ',',
+ '\0',
+ plContext),
+ PKIX_INFOACCESSPARSETOKENSFAILED);
+
+ /* Convert array of Attr Types into a bit mask */
+ request->attributes = 0;
+ attr = attrArray[0];
+ while (attr != NULL) {
+ PKIX_CHECK(pkix_pl_LdapRequest_AttrStringToBit
+ (attr, &attrBit, plContext),
+ PKIX_LDAPREQUESTATTRSTRINGTOBITFAILED);
+ request->attributes |= attrBit;
+ attr = *(++attrArray);
+ }
+
+cleanup:
+
+ PKIX_PL_Free(locationAscii, plContext);
+ PKIX_DECREF(locationString);
+
+ PKIX_RETURN(INFOACCESS);
+}
+#endif /* !NSS_PKIX_NO_LDAP */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h
new file mode 100644
index 0000000000..e69d7b4139
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h
@@ -0,0 +1,49 @@
+/* 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/. */
+/*
+ * pkix_pl_infoaccess.h
+ *
+ * InfoAccess Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_INFOACCESS_H
+#define _PKIX_PL_INFOACCESS_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_InfoAccessStruct{
+ PKIX_UInt32 method;
+ PKIX_PL_GeneralName *location;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_InfoAccess_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_InfoAccess_CreateList(
+ CERTAuthInfoAccess **authInfoAccess,
+ PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */
+ void *plContext);
+
+#ifndef NSS_PKIX_NO_LDAP
+PKIX_Error *
+pkix_pl_InfoAccess_ParseLocation(
+ PKIX_PL_GeneralName *generalName,
+ PLArenaPool *arena,
+ LDAPRequestParams *request,
+ char **pDomainName,
+ void *plContext);
+#endif /* !NSS_PKIX_NO_LDAP */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_INFOACCESS_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c
new file mode 100644
index 0000000000..1d0b61bb44
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c
@@ -0,0 +1,1279 @@
+/* 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/. */
+/*
+ * pkix_pl_nameconstraints.c
+ *
+ * Name Constraints Object Functions Definitions
+ *
+ */
+
+#include "pkix_pl_nameconstraints.h"
+
+
+/* --Private-NameConstraints-Functions----------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_GetPermitted
+ * DESCRIPTION:
+ *
+ * This function retrieve name constraints permitted list from NSS
+ * data in "nameConstraints" and returns a PKIX_PL_GeneralName list
+ * in "pPermittedList".
+ *
+ * PARAMETERS
+ * "nameConstraints"
+ * Address of CertNameConstraints which has a pointer to
+ * CERTNameConstraints data. Must be non-NULL.
+ * "pPermittedList"
+ * Address where returned permitted name list is stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_GetPermitted(
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_List **pPermittedList,
+ void *plContext)
+{
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTNameConstraints **nssNameConstraintsList = NULL;
+ CERTNameConstraint *nssPermitted = NULL;
+ CERTNameConstraint *firstPermitted = NULL;
+ PKIX_List *permittedList = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_GetPermitted");
+ PKIX_NULLCHECK_TWO(nameConstraints, pPermittedList);
+
+ /*
+ * nssNameConstraints is an array of CERTNameConstraints
+ * pointers where CERTNameConstraints keep its permitted and excluded
+ * lists as pointer array of CERTNameConstraint.
+ */
+
+ if (nameConstraints->permittedList == NULL) {
+
+ PKIX_OBJECT_LOCK(nameConstraints);
+
+ if (nameConstraints->permittedList == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&permittedList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ numItems = nameConstraints->numNssNameConstraints;
+ nssNameConstraintsList =
+ nameConstraints->nssNameConstraintsList;
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_NULLCHECK_ONE(nssNameConstraintsList);
+ nssNameConstraints = *(nssNameConstraintsList + i);
+ PKIX_NULLCHECK_ONE(nssNameConstraints);
+
+ if (nssNameConstraints->permited != NULL) {
+
+ nssPermitted = nssNameConstraints->permited;
+ firstPermitted = nssPermitted;
+
+ do {
+
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (&nssPermitted->name, &name, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (permittedList,
+ (PKIX_PL_Object *)name,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(name);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextNameConstraint\n");
+ nssPermitted = CERT_GetNextNameConstraint
+ (nssPermitted);
+
+ } while (nssPermitted != firstPermitted);
+
+ }
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(permittedList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ nameConstraints->permittedList = permittedList;
+
+ }
+
+ PKIX_OBJECT_UNLOCK(nameConstraints);
+
+ }
+
+ PKIX_INCREF(nameConstraints->permittedList);
+
+ *pPermittedList = nameConstraints->permittedList;
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_GetExcluded
+ * DESCRIPTION:
+ *
+ * This function retrieve name constraints excluded list from NSS
+ * data in "nameConstraints" and returns a PKIX_PL_GeneralName list
+ * in "pExcludedList".
+ *
+ * PARAMETERS
+ * "nameConstraints"
+ * Address of CertNameConstraints which has a pointer to NSS data.
+ * Must be non-NULL.
+ * "pPermittedList"
+ * Address where returned excluded name list is stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_GetExcluded(
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_List **pExcludedList,
+ void *plContext)
+{
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTNameConstraints **nssNameConstraintsList = NULL;
+ CERTNameConstraint *nssExcluded = NULL;
+ CERTNameConstraint *firstExcluded = NULL;
+ PKIX_List *excludedList = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_GetExcluded");
+ PKIX_NULLCHECK_TWO(nameConstraints, pExcludedList);
+
+ if (nameConstraints->excludedList == NULL) {
+
+ PKIX_OBJECT_LOCK(nameConstraints);
+
+ if (nameConstraints->excludedList == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&excludedList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ numItems = nameConstraints->numNssNameConstraints;
+ nssNameConstraintsList =
+ nameConstraints->nssNameConstraintsList;
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_NULLCHECK_ONE(nssNameConstraintsList);
+ nssNameConstraints = *(nssNameConstraintsList + i);
+ PKIX_NULLCHECK_ONE(nssNameConstraints);
+
+ if (nssNameConstraints->excluded != NULL) {
+
+ nssExcluded = nssNameConstraints->excluded;
+ firstExcluded = nssExcluded;
+
+ do {
+
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (&nssExcluded->name, &name, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (excludedList,
+ (PKIX_PL_Object *)name,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(name);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextNameConstraint\n");
+ nssExcluded = CERT_GetNextNameConstraint
+ (nssExcluded);
+
+ } while (nssExcluded != firstExcluded);
+
+ }
+
+ }
+ PKIX_CHECK(PKIX_List_SetImmutable(excludedList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ nameConstraints->excludedList = excludedList;
+
+ }
+
+ PKIX_OBJECT_UNLOCK(nameConstraints);
+ }
+
+ PKIX_INCREF(nameConstraints->excludedList);
+
+ *pExcludedList = nameConstraints->excludedList;
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_CheckNameSpaceNssNames
+ * DESCRIPTION:
+ *
+ * This function checks if CERTGeneralNames in "nssSubjectNames" comply
+ * with the permitted and excluded names in "nameConstraints". It returns
+ * PKIX_TRUE in "pCheckPass", if the Names satify the name space of the
+ * permitted list and if the Names are not in the excluded list. Otherwise,
+ * it returns PKIX_FALSE.
+ *
+ * PARAMETERS
+ * "nssSubjectNames"
+ * List of CERTGeneralName that nameConstraints verification is based on.
+ * "nameConstraints"
+ * Address of CertNameConstraints that provides lists of permitted
+ * and excluded names. Must be non-NULL.
+ * "pCheckPass"
+ * Address where PKIX_TRUE is returned if the all names in "nameList" are
+ * valid.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertNameConstraints_CheckNameSpaceNssNames(
+ CERTGeneralName *nssSubjectNames,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean *pCheckPass,
+ void *plContext)
+{
+ CERTNameConstraints **nssNameConstraintsList = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTGeneralName *nssMatchName = NULL;
+ PLArenaPool *arena = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+ SECStatus status = SECSuccess;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_CheckNameSpaceNssNames");
+ PKIX_NULLCHECK_THREE(nssSubjectNames, nameConstraints, pCheckPass);
+
+ *pCheckPass = PKIX_TRUE;
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ nssMatchName = nssSubjectNames;
+ nssNameConstraintsList = nameConstraints->nssNameConstraintsList;
+
+ /*
+ * CERTNameConstraint items in each permitted or excluded list
+ * is verified as OR condition. That means, if one item matched,
+ * then the checking on the remaining items on the list is skipped.
+ * (see NSS cert_CompareNameWithConstraints(...)).
+ * Items on PKIX_PL_NameConstraint's nssNameConstraints are verified
+ * as AND condition. PKIX_PL_NameConstraint keeps an array of pointers
+ * of CERTNameConstraints resulting from merging multiple
+ * PKIX_PL_NameConstraints. Since each CERTNameConstraint are created
+ * for different entity, a union condition of these entities then is
+ * performed.
+ */
+
+ do {
+
+ numItems = nameConstraints->numNssNameConstraints;
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_NULLCHECK_ONE(nssNameConstraintsList);
+ nssNameConstraints = *(nssNameConstraintsList + i);
+ PKIX_NULLCHECK_ONE(nssNameConstraints);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_CheckNameSpace\n");
+ status = CERT_CheckNameSpace
+ (arena, nssNameConstraints, nssMatchName);
+ if (status != SECSuccess) {
+ break;
+ }
+
+ }
+
+ if (status != SECSuccess) {
+ break;
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextGeneralName\n");
+ nssMatchName = CERT_GetNextGeneralName(nssMatchName);
+
+ } while (nssMatchName != nssSubjectNames);
+
+ if (status == SECFailure) {
+
+ *pCheckPass = PKIX_FALSE;
+ }
+
+cleanup:
+
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_NameConstraints_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTNAMECONSTRAINTS);
+
+ nameConstraints = (PKIX_PL_CertNameConstraints *)object;
+
+ PKIX_CHECK(PKIX_PL_Free
+ (nameConstraints->nssNameConstraintsList, plContext),
+ PKIX_FREEFAILED);
+
+ if (nameConstraints->arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(nameConstraints->arena, PR_FALSE);
+ nameConstraints->arena = NULL;
+ }
+
+ PKIX_DECREF(nameConstraints->permittedList);
+ PKIX_DECREF(nameConstraints->excludedList);
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the object
+ * NameConstraints and stores it at "pString".
+ *
+ * PARAMETERS
+ * "nameConstraints"
+ * Address of CertNameConstraints whose string representation is
+ * desired. Must be non-NULL.
+ * "pString"
+ * Address where string object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_ToString_Helper(
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_List *permittedList = NULL;
+ PKIX_List *excludedList = NULL;
+ PKIX_PL_String *permittedListString = NULL;
+ PKIX_PL_String *excludedListString = NULL;
+ PKIX_PL_String *nameConstraintsString = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_ToString_Helper");
+ PKIX_NULLCHECK_TWO(nameConstraints, pString);
+
+ asciiFormat =
+ "[\n"
+ "\t\tPermitted Name: %s\n"
+ "\t\tExcluded Name: %s\n"
+ "\t]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
+ (nameConstraints, &permittedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
+
+ PKIX_TOSTRING(permittedList, &permittedListString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
+ (nameConstraints, &excludedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
+
+ PKIX_TOSTRING(excludedList, &excludedListString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&nameConstraintsString,
+ plContext,
+ formatString,
+ permittedListString,
+ excludedListString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = nameConstraintsString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(permittedList);
+ PKIX_DECREF(excludedList);
+ PKIX_DECREF(permittedListString);
+ PKIX_DECREF(excludedListString);
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *nameConstraintsString = NULL;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(
+ object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTNAMECONSTRAINTS);
+
+ nameConstraints = (PKIX_PL_CertNameConstraints *)object;
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_ToString_Helper
+ (nameConstraints, &nameConstraintsString, plContext),
+ PKIX_CERTNAMECONSTRAINTSTOSTRINGHELPERFAILED);
+
+ *pString = nameConstraintsString;
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ PKIX_List *permittedList = NULL;
+ PKIX_List *excludedList = NULL;
+ PKIX_UInt32 permitHash = 0;
+ PKIX_UInt32 excludeHash = 0;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTNAMECONSTRAINTS);
+
+ nameConstraints = (PKIX_PL_CertNameConstraints *)object;
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
+ (nameConstraints, &permittedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
+
+ PKIX_HASHCODE(permittedList, &permitHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
+ (nameConstraints, &excludedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
+
+ PKIX_HASHCODE(excludedList, &excludeHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ *pHashcode = (((permitHash << 7) + excludeHash) << 7) +
+ nameConstraints->numNssNameConstraints;
+
+cleanup:
+
+ PKIX_DECREF(permittedList);
+ PKIX_DECREF(excludedList);
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *firstNC = NULL;
+ PKIX_PL_CertNameConstraints *secondNC = NULL;
+ PKIX_List *firstPermittedList = NULL;
+ PKIX_List *secondPermittedList = NULL;
+ PKIX_List *firstExcludedList = NULL;
+ PKIX_List *secondExcludedList = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertNameConstraints */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTNAMECONSTRAINTS);
+
+ firstNC = (PKIX_PL_CertNameConstraints *)firstObject;
+ secondNC = (PKIX_PL_CertNameConstraints *)secondObject;
+
+ /*
+ * Since we know firstObject is a CertNameConstraints, if both
+ * references are identical, they must be equal
+ */
+ if (firstNC == secondNC){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondNC isn't a CertNameConstraints, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondNC, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_CERTNAMECONSTRAINTS_TYPE) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
+ (firstNC, &firstPermittedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
+ (secondNC, &secondPermittedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
+
+ PKIX_EQUALS
+ (firstPermittedList, secondPermittedList, &cmpResult, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
+ (firstNC, &firstExcludedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
+ (secondNC, &secondExcludedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
+
+ PKIX_EQUALS
+ (firstExcludedList, secondExcludedList, &cmpResult, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /*
+ * numNssNameConstraints is not checked because it is basically a
+ * merge count, it cannot determine the data equality.
+ */
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_DECREF(firstPermittedList);
+ PKIX_DECREF(secondPermittedList);
+ PKIX_DECREF(firstExcludedList);
+ PKIX_DECREF(secondExcludedList);
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTNAMECONSTRAINTS_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertNameConstraints_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_RegisterSelf");
+
+ entry.description = "CertNameConstraints";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertNameConstraints);
+ entry.destructor = pkix_pl_CertNameConstraints_Destroy;
+ entry.equalsFunction = pkix_pl_CertNameConstraints_Equals;
+ entry.hashcodeFunction = pkix_pl_CertNameConstraints_Hashcode;
+ entry.toStringFunction = pkix_pl_CertNameConstraints_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTNAMECONSTRAINTS_TYPE] = entry;
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Create_Helper
+ *
+ * DESCRIPTION:
+ * This function retrieves name constraints in "nssNameConstraints",
+ * converts and stores the result in a PKIX_PL_CertNameConstraints object.
+ *
+ * PARAMETERS
+ * "nssNameConstraints"
+ * Address of CERTNameConstraints that contains this object's data.
+ * Must be non-NULL.
+ * "pNameConstraints"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * A NULL value will be returned if there is no Name Constraints extension.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_Create_Helper(
+ CERTNameConstraints *nssNameConstraints,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ CERTNameConstraints **nssNameConstraintPtr = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_Create_Helper");
+ PKIX_NULLCHECK_TWO(nssNameConstraints, pNameConstraints);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTNAMECONSTRAINTS_TYPE,
+ sizeof (PKIX_PL_CertNameConstraints),
+ (PKIX_PL_Object **)&nameConstraints,
+ plContext),
+ PKIX_COULDNOTCREATECERTNAMECONSTRAINTSOBJECT);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (CERTNameConstraint *),
+ (void *)&nssNameConstraintPtr,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ nameConstraints->numNssNameConstraints = 1;
+ nameConstraints->nssNameConstraintsList = nssNameConstraintPtr;
+ *nssNameConstraintPtr = nssNameConstraints;
+
+ nameConstraints->permittedList = NULL;
+ nameConstraints->excludedList = NULL;
+ nameConstraints->arena = NULL;
+
+ *pNameConstraints = nameConstraints;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(nameConstraints);
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Create
+ *
+ * DESCRIPTION:
+ * function that allocates and initialize the object CertNameConstraints.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of CERT that contains this object's data.
+ * Must be non-NULL.
+ * "pNameConstraints"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * A NULL value will be returned if there is no Name Constraints extension.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertNameConstraints_Create(
+ CERTCertificate *nssCert,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus status;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Create");
+ PKIX_NULLCHECK_THREE(nssCert, pNameConstraints, nssCert->arena);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena).\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_FindNameConstraintsExten\n");
+ status = CERT_FindNameConstraintsExten
+ (arena, nssCert, &nssNameConstraints);
+
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_DECODINGCERTNAMECONSTRAINTSFAILED);
+ }
+
+ if (nssNameConstraints == NULL) {
+ *pNameConstraints = NULL;
+ /* we free the arnea here because PKIX_ERROR_RECEIVED
+ * may not be set. Setting arena to NULL makes sure
+ * we don't try to free it again (and makes scanners
+ * happy). */
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ arena = NULL;
+ }
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_Create_Helper
+ (nssNameConstraints, &nameConstraints, plContext),
+ PKIX_CERTNAMECONSTRAINTSCREATEHELPERFAILED);
+
+ nameConstraints->arena = arena;
+
+ *pNameConstraints = nameConstraints;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_CreateByMerge
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates and creates a PKIX_PL_NameConstraint object
+ * for merging. It also allocates CERTNameConstraints data space for the
+ * merged NSS NameConstraints data.
+ *
+ * PARAMETERS
+ * "pNameConstraints"
+ * Address where object pointer will be stored and returned.
+ * Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_CreateByMerge(
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ PLArenaPool *arena = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_CreateByMerge");
+ PKIX_NULLCHECK_ONE(pNameConstraints);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena).\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_ArenaZNew).\n");
+ nssNameConstraints = PORT_ArenaZNew(arena, CERTNameConstraints);
+ if (nssNameConstraints == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ nssNameConstraints->permited = NULL;
+ nssNameConstraints->excluded = NULL;
+ nssNameConstraints->DERPermited = NULL;
+ nssNameConstraints->DERExcluded = NULL;
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_Create_Helper
+ (nssNameConstraints, &nameConstraints, plContext),
+ PKIX_CERTNAMECONSTRAINTSCREATEHELPERFAILED);
+
+ nameConstraints->arena = arena;
+
+ *pNameConstraints = nameConstraints;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_CopyNssNameConstraints
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates and copies data to a NSS CERTNameConstraints from
+ * the NameConstraints given by "srcNC" and stores the result at "pDestNC". It
+ * copies items on both the permitted and excluded lists, but not the
+ * DERPermited and DERExcluded.
+ *
+ * PARAMETERS
+ * "arena"
+ * Memory pool where object data is allocated from. Must be non-NULL.
+ * "srcNC"
+ * Address of the NameConstraints to copy from. Must be non-NULL.
+ * "pDestNC"
+ * Address where new copied object is stored and returned.
+ * Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_CopyNssNameConstraints(
+ PLArenaPool *arena,
+ CERTNameConstraints *srcNC,
+ CERTNameConstraints **pDestNC,
+ void *plContext)
+{
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTNameConstraint *nssNameConstraintHead = NULL;
+ CERTNameConstraint *nssCurrent = NULL;
+ CERTNameConstraint *nssCopyTo = NULL;
+ CERTNameConstraint *nssCopyFrom = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_CopyNssNameConstraints");
+ PKIX_NULLCHECK_THREE(arena, srcNC, pDestNC);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_ArenaZNew).\n");
+ nssNameConstraints = PORT_ArenaZNew(arena, CERTNameConstraints);
+ if (nssNameConstraints == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ if (srcNC->permited) {
+
+ nssCopyFrom = srcNC->permited;
+
+ do {
+
+ nssCopyTo = NULL;
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_CopyNameConstraint).\n");
+ nssCopyTo = CERT_CopyNameConstraint
+ (arena, nssCopyTo, nssCopyFrom);
+ if (nssCopyTo == NULL) {
+ PKIX_ERROR(PKIX_CERTCOPYNAMECONSTRAINTFAILED);
+ }
+ if (nssCurrent == NULL) {
+ nssCurrent = nssNameConstraintHead = nssCopyTo;
+ } else {
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_AddNameConstraint).\n");
+ nssCurrent = CERT_AddNameConstraint
+ (nssCurrent, nssCopyTo);
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextNameConstrain).\n");
+ nssCopyFrom = CERT_GetNextNameConstraint(nssCopyFrom);
+
+ } while (nssCopyFrom != srcNC->permited);
+
+ nssNameConstraints->permited = nssNameConstraintHead;
+ }
+
+ if (srcNC->excluded) {
+
+ nssCurrent = NULL;
+ nssCopyFrom = srcNC->excluded;
+
+ do {
+
+ /*
+ * Cannot use CERT_DupGeneralNameList, which just increments
+ * refcount. We need our own copy since arena is for each
+ * PKIX_PL_NameConstraints. Perhaps contribute this code
+ * as CERT_CopyGeneralNameList (in the future).
+ */
+ nssCopyTo = NULL;
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_CopyNameConstraint).\n");
+ nssCopyTo = CERT_CopyNameConstraint
+ (arena, nssCopyTo, nssCopyFrom);
+ if (nssCopyTo == NULL) {
+ PKIX_ERROR(PKIX_CERTCOPYNAMECONSTRAINTFAILED);
+ }
+ if (nssCurrent == NULL) {
+ nssCurrent = nssNameConstraintHead = nssCopyTo;
+ } else {
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_AddNameConstraint).\n");
+ nssCurrent = CERT_AddNameConstraint
+ (nssCurrent, nssCopyTo);
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextNameConstrain).\n");
+ nssCopyFrom = CERT_GetNextNameConstraint(nssCopyFrom);
+
+ } while (nssCopyFrom != srcNC->excluded);
+
+ nssNameConstraints->excluded = nssNameConstraintHead;
+ }
+
+ *pDestNC = nssNameConstraints;
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Merge
+ *
+ * DESCRIPTION:
+ *
+ * This function merges two NameConstraints pointed to by "firstNC" and
+ * "secondNC" and stores the result in "pMergedNC".
+ *
+ * PARAMETERS
+ * "firstNC"
+ * Address of the first NameConstraints to be merged. Must be non-NULL.
+ * "secondNC"
+ * Address of the second NameConstraints to be merged. Must be non-NULL.
+ * "pMergedNC"
+ * Address where the merge result is stored and returned. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertNameConstraints_Merge(
+ PKIX_PL_CertNameConstraints *firstNC,
+ PKIX_PL_CertNameConstraints *secondNC,
+ PKIX_PL_CertNameConstraints **pMergedNC,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ CERTNameConstraints **nssNCto = NULL;
+ CERTNameConstraints **nssNCfrom = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ PKIX_UInt32 numNssItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Merge");
+ PKIX_NULLCHECK_THREE(firstNC, secondNC, pMergedNC);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_CreateByMerge
+ (&nameConstraints, plContext),
+ PKIX_CERTNAMECONSTRAINTSCREATEBYMERGEFAILED);
+
+ /* Merge NSSCertConstraint lists */
+
+ numNssItems = firstNC->numNssNameConstraints +
+ secondNC->numNssNameConstraints;
+
+ /* Free the default space (only one entry) allocated by create */
+ PKIX_CHECK(PKIX_PL_Free
+ (nameConstraints->nssNameConstraintsList, plContext),
+ PKIX_FREEFAILED);
+
+ /* Reallocate the size we need */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (numNssItems * sizeof (CERTNameConstraint *),
+ (void *)&nssNCto,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ nameConstraints->nssNameConstraintsList = nssNCto;
+
+ nssNCfrom = firstNC->nssNameConstraintsList;
+
+ for (i = 0; i < firstNC->numNssNameConstraints; i++) {
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_CopyNssNameConstraints
+ (nameConstraints->arena,
+ *nssNCfrom,
+ &nssNameConstraints,
+ plContext),
+ PKIX_CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED);
+
+ *nssNCto = nssNameConstraints;
+
+ nssNCto++;
+ nssNCfrom++;
+ }
+
+ nssNCfrom = secondNC->nssNameConstraintsList;
+
+ for (i = 0; i < secondNC->numNssNameConstraints; i++) {
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_CopyNssNameConstraints
+ (nameConstraints->arena,
+ *nssNCfrom,
+ &nssNameConstraints,
+ plContext),
+ PKIX_CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED);
+
+ *nssNCto = nssNameConstraints;
+
+ nssNCto++;
+ nssNCfrom++;
+ }
+
+ nameConstraints->numNssNameConstraints = numNssItems;
+ nameConstraints->permittedList = NULL;
+ nameConstraints->excludedList = NULL;
+
+ *pMergedNC = nameConstraints;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(nameConstraints);
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/* --Public-NameConstraints-Functions-------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
+ * (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_CertNameConstraints_CheckNamesInNameSpace(
+ PKIX_List *nameList, /* List of PKIX_PL_GeneralName */
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean *pCheckPass,
+ void *plContext)
+{
+ CERTNameConstraints **nssNameConstraintsList = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTGeneralName *nssMatchName = NULL;
+ PLArenaPool *arena = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 numNameItems = 0;
+ PKIX_UInt32 numNCItems = 0;
+ PKIX_UInt32 i, j;
+ SECStatus status = SECSuccess;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "PKIX_PL_CertNameConstraints_CheckNamesInNameSpace");
+ PKIX_NULLCHECK_TWO(nameConstraints, pCheckPass);
+
+ *pCheckPass = PKIX_TRUE;
+
+ if (nameList != NULL) {
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ nssNameConstraintsList =
+ nameConstraints->nssNameConstraintsList;
+ PKIX_NULLCHECK_ONE(nssNameConstraintsList);
+ numNCItems = nameConstraints->numNssNameConstraints;
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (nameList, &numNameItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numNameItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (nameList,
+ i,
+ (PKIX_PL_Object **) &name,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_pl_GeneralName_GetNssGeneralName
+ (name, &nssMatchName, plContext),
+ PKIX_GENERALNAMEGETNSSGENERALNAMEFAILED);
+
+ PKIX_DECREF(name);
+
+ for (j = 0; j < numNCItems; j++) {
+
+ nssNameConstraints = *(nssNameConstraintsList + j);
+ PKIX_NULLCHECK_ONE(nssNameConstraints);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_CheckNameSpace\n");
+ status = CERT_CheckNameSpace
+ (arena, nssNameConstraints, nssMatchName);
+ if (status != SECSuccess) {
+ break;
+ }
+
+ }
+
+ if (status != SECSuccess) {
+ break;
+ }
+
+ }
+ }
+
+ if (status == SECFailure) {
+ *pCheckPass = PKIX_FALSE;
+ }
+
+cleanup:
+
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h
new file mode 100644
index 0000000000..2f305ac10a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h
@@ -0,0 +1,68 @@
+/* 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/. */
+/*
+ * pkix_pl_nameconstraints.h
+ *
+ * Name Constraints Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_NAMECONSTRAINTS_H
+#define _PKIX_PL_NAMECONSTRAINTS_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_CertNameConstraintsStruct {
+ PLArenaPool *arena;
+ CERTNameConstraints **nssNameConstraintsList;
+ PKIX_UInt32 numNssNameConstraints;
+ PKIX_List *permittedList; /* list of PKIX_PL_GeneralName */
+ PKIX_List *excludedList; /* list of PKIX_PL_GeneralName */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_CertNameConstraints_RegisterSelf(void *plContext);
+
+PKIX_Error *pkix_pl_CertNameConstraints_Create(
+ CERTCertificate *nssCert,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertNameConstraints_CreateWithNames(
+ PKIX_List *names, /* List of PKIX_PL_GeneralName */
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertNameConstraints_CheckNameSpaceNssNames(
+ CERTGeneralName *nssSubjectNames,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean *pCheckPass,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertNameConstraints_CheckNameSpacePkixNames(
+ PKIX_List *nameList,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean *pCheckPass,
+ void *plContext);
+
+
+PKIX_Error *pkix_pl_CertNameConstraints_Merge(
+ PKIX_PL_CertNameConstraints *firstNC,
+ PKIX_PL_CertNameConstraints *secondNC,
+ PKIX_PL_CertNameConstraints **pMergedNC,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_NAMECONSTRAINTS_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c
new file mode 100644
index 0000000000..679811dec1
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c
@@ -0,0 +1,251 @@
+/* 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/. */
+/*
+ * pkix_pl_ocspcertid.c
+ *
+ * Certificate ID Object for OCSP
+ *
+ */
+
+#include "pkix_pl_ocspcertid.h"
+
+/* --Private-Cert-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspCertID_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspCertID_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_OcspCertID *certID = NULL;
+
+ PKIX_ENTER(OCSPCERTID, "pkix_pl_OcspCertID_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPCERTID_TYPE, plContext),
+ PKIX_OBJECTNOTOCSPCERTID);
+
+ certID = (PKIX_PL_OcspCertID *)object;
+
+ if (certID->certID) {
+ CERT_DestroyOCSPCertID(certID->certID);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OCSPCERTID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspCertID_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_PUBLICKEY_TYPE and its related functions
+ * with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_OcspCertID_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(OCSPCERTID, "pkix_pl_OcspCertID_RegisterSelf");
+
+ entry.description = "OcspCertID";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_OcspCertID);
+ entry.destructor = pkix_pl_OcspCertID_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+ systemClasses[PKIX_OCSPCERTID_TYPE] = entry;
+
+ PKIX_RETURN(OCSPCERTID);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_OcspCertID_Create
+ * DESCRIPTION:
+ *
+ * This function creates an OcspCertID for a given certificate,
+ * to be used with OCSP transactions.
+ *
+ * If a Date is provided in "validity" it may be used in the search for the
+ * issuer of "cert" but has no effect on the request itself.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of the Cert for which an OcspCertID is to be created. Must be
+ * non-NULL.
+ * "validity"
+ * Address of the Date for which the Cert's validity is to be determined.
+ * May be NULL.
+ * "object"
+ * Address at which the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspCertID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_OcspCertID_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date *validity,
+ PKIX_PL_OcspCertID **object,
+ void *plContext)
+{
+ PKIX_PL_OcspCertID *cid = NULL;
+ PRTime time = 0;
+
+ PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_Create");
+ PKIX_NULLCHECK_TWO(cert, object);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OCSPCERTID_TYPE,
+ sizeof (PKIX_PL_OcspCertID),
+ (PKIX_PL_Object **)&cid,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ if (validity != NULL) {
+ PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ } else {
+ time = PR_Now();
+ }
+
+ cid->certID = CERT_CreateOCSPCertID(cert->nssCert, time);
+ if (!cid->certID) {
+ PKIX_ERROR(PKIX_COULDNOTCREATEOBJECT);
+ }
+
+ *object = cid;
+ cid = NULL;
+cleanup:
+ PKIX_DECREF(cid);
+ PKIX_RETURN(OCSPCERTID);
+}
+
+/*
+ * FUNCTION: PKIX_PL_OcspCertID_GetFreshCacheStatus
+ * DESCRIPTION:
+ *
+ * This function may return cached OCSP results for the provided
+ * certificate, but only if stored information is still considered to be
+ * fresh.
+ *
+ * PARAMETERS
+ * "cid"
+ * A certificate ID as used by OCSP
+ * "validity"
+ * Optional date parameter to request validity for a specifc time.
+ * "hasFreshStatus"
+ * Output parameter, if the function successed to find fresh cached
+ * information, this will be set to true. Must be non-NULL.
+ * "statusIsGood"
+ * The good/bad result stored in the cache. Must be non-NULL.
+ * "missingResponseError"
+ * If OCSP status is "bad", this variable may indicate the exact
+ * reason why the previous OCSP request had failed.
+ * "plContext"
+ * Platform-specific context pointer.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspCertID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_OcspCertID_GetFreshCacheStatus(
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_Date *validity,
+ PKIX_Boolean *hasFreshStatus,
+ PKIX_Boolean *statusIsGood,
+ SECErrorCodes *missingResponseError,
+ void *plContext)
+{
+ PRTime time = 0;
+ SECStatus rv;
+ SECStatus rvOcsp;
+ OCSPFreshness freshness;
+
+ PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_GetFreshCacheStatus");
+ PKIX_NULLCHECK_THREE(cid, hasFreshStatus, statusIsGood);
+
+ if (validity != NULL) {
+ PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ } else {
+ time = PR_Now();
+ }
+
+ rv = ocsp_GetCachedOCSPResponseStatus(
+ cid->certID, time, PR_TRUE, /*ignoreGlobalOcspFailureSetting*/
+ &rvOcsp, missingResponseError, &freshness);
+
+ *hasFreshStatus = (rv == SECSuccess && freshness == ocspFresh);
+ if (*hasFreshStatus) {
+ *statusIsGood = (rvOcsp == SECSuccess);
+ }
+cleanup:
+ PKIX_RETURN(OCSPCERTID);
+}
+
+/*
+ * FUNCTION: PKIX_PL_OcspCertID_RememberOCSPProcessingFailure
+ * DESCRIPTION:
+ *
+ * Information about the current failure associated to the given certID
+ * will be remembered in the cache, potentially allowing future calls
+ * to prevent repetitive OCSP requests.
+ * After this function got called, it may no longer be safe to
+ * use the provided cid parameter, because ownership might have been
+ * transfered to the cache. This status will be recorded inside the
+ * cid object.
+ *
+ * PARAMETERS
+ * "cid"
+ * The certificate ID associated to a failed OCSP processing.
+ * "plContext"
+ * Platform-specific context pointer.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspCertID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
+ PKIX_PL_OcspCertID *cid,
+ void *plContext)
+{
+ PRBool certIDWasConsumed = PR_FALSE;
+
+ PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_RememberOCSPProcessingFailure");
+ PKIX_NULLCHECK_TWO(cid, cid->certID);
+
+ cert_RememberOCSPProcessingFailure(cid->certID, &certIDWasConsumed);
+
+ if (certIDWasConsumed) {
+ cid->certID = NULL;
+ }
+
+ PKIX_RETURN(OCSPCERTID);
+}
+
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h
new file mode 100644
index 0000000000..772a12b25f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h
@@ -0,0 +1,53 @@
+/* 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/. */
+/*
+ * pkix_pl_ocspcertid.h
+ *
+ * Public Key Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OCSPCERTID_H
+#define _PKIX_PL_OCSPCERTID_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_OcspCertIDStruct {
+ CERTOCSPCertID *certID;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_OcspCertID_RegisterSelf(void *plContext);
+
+PKIX_Error *
+PKIX_PL_OcspCertID_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date *validity,
+ PKIX_PL_OcspCertID **object,
+ void *plContext);
+
+PKIX_Error *
+PKIX_PL_OcspCertID_GetFreshCacheStatus(
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_Date *validity,
+ PKIX_Boolean *hasFreshStatus,
+ PKIX_Boolean *statusIsGood,
+ SECErrorCodes *missingResponseError,
+ void *plContext);
+
+PKIX_Error *
+PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
+ PKIX_PL_OcspCertID *cid,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OCSPCERTID_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c
new file mode 100644
index 0000000000..28b6953a76
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c
@@ -0,0 +1,441 @@
+/* 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/. */
+/*
+ * pkix_pl_ocsprequest.c
+ *
+ */
+
+#include "pkix_pl_ocsprequest.h"
+
+/* --Private-OcspRequest-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspRequest_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_OcspRequest *ocspReq = NULL;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext),
+ PKIX_OBJECTNOTOCSPREQUEST);
+
+ ocspReq = (PKIX_PL_OcspRequest *)object;
+
+ if (ocspReq->decoded != NULL) {
+ CERT_DestroyOCSPRequest(ocspReq->decoded);
+ }
+
+ if (ocspReq->encoded != NULL) {
+ SECITEM_FreeItem(ocspReq->encoded, PR_TRUE);
+ }
+
+ if (ocspReq->location != NULL) {
+ PORT_Free(ocspReq->location);
+ }
+
+ PKIX_DECREF(ocspReq->cert);
+ PKIX_DECREF(ocspReq->validity);
+ PKIX_DECREF(ocspReq->signerCert);
+
+cleanup:
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspRequest_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 certHash = 0;
+ PKIX_UInt32 dateHash = 0;
+ PKIX_UInt32 extensionHash = 0;
+ PKIX_UInt32 signerHash = 0;
+ PKIX_PL_OcspRequest *ocspRq = NULL;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext),
+ PKIX_OBJECTNOTOCSPREQUEST);
+
+ ocspRq = (PKIX_PL_OcspRequest *)object;
+
+ *pHashcode = 0;
+
+ PKIX_HASHCODE(ocspRq->cert, &certHash, plContext,
+ PKIX_CERTHASHCODEFAILED);
+
+ PKIX_HASHCODE(ocspRq->validity, &dateHash, plContext,
+ PKIX_DATEHASHCODEFAILED);
+
+ if (ocspRq->addServiceLocator == PKIX_TRUE) {
+ extensionHash = 0xff;
+ }
+
+ PKIX_HASHCODE(ocspRq->signerCert, &signerHash, plContext,
+ PKIX_CERTHASHCODEFAILED);
+
+ *pHashcode = (((((extensionHash << 8) | certHash) << 8) |
+ dateHash) << 8) | signerHash;
+
+cleanup:
+
+ PKIX_RETURN(OCSPREQUEST);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspRequest_Equals(
+ PKIX_PL_Object *firstObj,
+ PKIX_PL_Object *secondObj,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_UInt32 secondType = 0;
+ PKIX_PL_OcspRequest *firstReq = NULL;
+ PKIX_PL_OcspRequest *secondReq = NULL;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Equals");
+ PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
+
+ /* test that firstObj is a OcspRequest */
+ PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPREQUEST_TYPE, plContext),
+ PKIX_FIRSTOBJARGUMENTNOTOCSPREQUEST);
+
+ /*
+ * Since we know firstObj is a OcspRequest, if both references are
+ * identical, they must be equal
+ */
+ if (firstObj == secondObj){
+ match = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObj isn't a OcspRequest, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObj, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_OCSPREQUEST_TYPE) {
+ goto cleanup;
+ }
+
+ firstReq = (PKIX_PL_OcspRequest *)firstObj;
+ secondReq = (PKIX_PL_OcspRequest *)secondObj;
+
+ if (firstReq->addServiceLocator != secondReq->addServiceLocator) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS(firstReq->cert, secondReq->cert, &match, plContext,
+ PKIX_CERTEQUALSFAILED);
+
+ if (match == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS(firstReq->validity, secondReq->validity, &match, plContext,
+ PKIX_DATEEQUALSFAILED);
+
+ if (match == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstReq->signerCert, secondReq->signerCert, &match, plContext,
+ PKIX_CERTEQUALSFAILED);
+
+cleanup:
+
+ *pResult = match;
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OCSPREQUEST_TYPE and its related functions with
+ * systemClasses[]
+ * PARAMETERS:
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_OcspRequest_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_RegisterSelf");
+
+ entry.description = "OcspRequest";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_OcspRequest);
+ entry.destructor = pkix_pl_OcspRequest_Destroy;
+ entry.equalsFunction = pkix_pl_OcspRequest_Equals;
+ entry.hashcodeFunction = pkix_pl_OcspRequest_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_OCSPREQUEST_TYPE] = entry;
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_Create
+ * DESCRIPTION:
+ *
+ * This function creates an OcspRequest to be used in validating the Cert
+ * pointed to by "cert" and storing the result at "pRequest". If a URI
+ * is found for an OCSP responder, PKIX_TRUE is stored at "pURIFound". If no
+ * URI is found, PKIX_FALSE is stored.
+ *
+ * If a Date is provided in "validity" it may be used in the search for the
+ * issuer of "cert" but has no effect on the request itself. If
+ * "addServiceLocator" is TRUE, the AddServiceLocator extension will be
+ * included in the Request. If "signerCert" is provided it will be used to sign
+ * the Request. (Note: this signed request feature is not currently supported.)
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of the Cert for which an OcspRequest is to be created. Must be
+ * non-NULL.
+ * "validity"
+ * Address of the Date for which the Cert's validity is to be determined.
+ * May be NULL.
+ * "signerCert"
+ * Address of the Cert to be used, if present, in signing the request.
+ * May be NULL.
+ * "pRequest"
+ * Address at which the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspRequest_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_Date *validity,
+ PKIX_PL_Cert *signerCert,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean *pURIFound,
+ PKIX_PL_OcspRequest **pRequest,
+ void *plContext)
+{
+ PKIX_PL_OcspRequest *ocspRequest = NULL;
+
+ CERTCertDBHandle *handle = NULL;
+ SECStatus rv = SECFailure;
+ SECItem *encoding = NULL;
+ CERTOCSPRequest *certRequest = NULL;
+ PRTime time = 0;
+ PRBool addServiceLocatorExtension = PR_FALSE;
+ CERTCertificate *nssCert = NULL;
+ CERTCertificate *nssSignerCert = NULL;
+ char *location = NULL;
+ PRErrorCode locError = 0;
+ PKIX_Boolean canUseDefaultSource = PKIX_FALSE;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Create");
+ PKIX_NULLCHECK_TWO(cert, pRequest);
+
+ /* create a PKIX_PL_OcspRequest object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OCSPREQUEST_TYPE,
+ sizeof (PKIX_PL_OcspRequest),
+ (PKIX_PL_Object **)&ocspRequest,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ PKIX_INCREF(cert);
+ ocspRequest->cert = cert;
+
+ PKIX_INCREF(validity);
+ ocspRequest->validity = validity;
+
+ PKIX_INCREF(signerCert);
+ ocspRequest->signerCert = signerCert;
+
+ ocspRequest->decoded = NULL;
+ ocspRequest->encoded = NULL;
+
+ ocspRequest->location = NULL;
+
+ nssCert = cert->nssCert;
+
+ /*
+ * Does this Cert have an Authority Information Access extension with
+ * the URI of an OCSP responder?
+ */
+ handle = CERT_GetDefaultCertDB();
+
+ if (!(methodFlags & PKIX_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE)) {
+ canUseDefaultSource = PKIX_TRUE;
+ }
+ location = ocsp_GetResponderLocation(handle, nssCert,
+ canUseDefaultSource,
+ &addServiceLocatorExtension);
+ if (location == NULL) {
+ locError = PORT_GetError();
+ if (locError == SEC_ERROR_EXTENSION_NOT_FOUND ||
+ locError == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
+ PORT_SetError(0);
+ *pURIFound = PKIX_FALSE;
+ goto cleanup;
+ }
+ PKIX_ERROR(PKIX_ERRORFINDINGORPROCESSINGURI);
+ }
+
+ ocspRequest->location = location;
+ *pURIFound = PKIX_TRUE;
+
+ if (signerCert != NULL) {
+ nssSignerCert = signerCert->nssCert;
+ }
+
+ if (validity != NULL) {
+ PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ } else {
+ time = PR_Now();
+ }
+
+ certRequest = cert_CreateSingleCertOCSPRequest(
+ cid->certID, cert->nssCert, time,
+ addServiceLocatorExtension, nssSignerCert);
+
+ ocspRequest->decoded = certRequest;
+
+ if (certRequest == NULL) {
+ PKIX_ERROR(PKIX_UNABLETOCREATECERTOCSPREQUEST);
+ }
+
+ rv = CERT_AddOCSPAcceptableResponses(
+ certRequest, SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
+
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_UNABLETOADDACCEPTABLERESPONSESTOREQUEST);
+ }
+
+ encoding = CERT_EncodeOCSPRequest(NULL, certRequest, NULL);
+
+ ocspRequest->encoded = encoding;
+
+ *pRequest = ocspRequest;
+ ocspRequest = NULL;
+
+cleanup:
+ PKIX_DECREF(ocspRequest);
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_GetEncoded
+ * DESCRIPTION:
+ *
+ * This function obtains the encoded message from the OcspRequest pointed to
+ * by "request", storing the result at "pRequest".
+ *
+ * PARAMETERS
+ * "request"
+ * The address of the OcspRequest whose encoded message is to be
+ * retrieved. Must be non-NULL.
+ * "pRequest"
+ * The address at which is stored the address of the encoded message. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspRequest_GetEncoded(
+ PKIX_PL_OcspRequest *request,
+ SECItem **pRequest,
+ void *plContext)
+{
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetEncoded");
+ PKIX_NULLCHECK_TWO(request, pRequest);
+
+ *pRequest = request->encoded;
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_GetLocation
+ * DESCRIPTION:
+ *
+ * This function obtains the location from the OcspRequest pointed to
+ * by "request", storing the result at "pLocation".
+ *
+ * PARAMETERS
+ * "request"
+ * The address of the OcspRequest whose encoded message is to be
+ * retrieved. Must be non-NULL.
+ * "pLocation"
+ * The address at which is stored the address of the location. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspRequest_GetLocation(
+ PKIX_PL_OcspRequest *request,
+ char **pLocation,
+ void *plContext)
+{
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetLocation");
+ PKIX_NULLCHECK_TWO(request, pLocation);
+
+ *pLocation = request->location;
+
+ PKIX_RETURN(OCSPREQUEST);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h
new file mode 100644
index 0000000000..fa79266eec
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h
@@ -0,0 +1,61 @@
+/* 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/. */
+/*
+ * pkix_pl_ocsprequest.h
+ *
+ * OcspRequest Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OCSPREQUEST_H
+#define _PKIX_PL_OCSPREQUEST_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_OcspRequestStruct{
+ PKIX_PL_Cert *cert;
+ PKIX_PL_Date *validity;
+ PKIX_Boolean addServiceLocator;
+ PKIX_PL_Cert *signerCert;
+ CERTOCSPRequest *decoded;
+ SECItem *encoded;
+ char *location;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_OcspRequest_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_Date *validity,
+ PKIX_PL_Cert *signerCert,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean *pURIFound,
+ PKIX_PL_OcspRequest **pRequest,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspRequest_GetEncoded(
+ PKIX_PL_OcspRequest *request,
+ SECItem **pRequest,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspRequest_GetLocation(
+ PKIX_PL_OcspRequest *request,
+ char **pLocation,
+ void *plContext);
+
+PKIX_Error *pkix_pl_OcspRequest_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OCSPREQUEST_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c
new file mode 100644
index 0000000000..fa41f8102e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c
@@ -0,0 +1,1069 @@
+/* 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/. */
+/*
+ * pkix_pl_ocspresponse.c
+ *
+ */
+
+#include "pkix_pl_ocspresponse.h"
+
+/* ----Public functions------------------------------------- */
+/*
+ * This is the libpkix replacement for CERT_VerifyOCSPResponseSignature.
+ * It is used if it has been set as the verifyFcn member of ocspChecker.
+ */
+PKIX_Error *
+PKIX_PL_OcspResponse_UseBuildChain(
+ PKIX_PL_Cert *signerCert,
+ PKIX_PL_Date *producedAt,
+ PKIX_ProcessingParams *procParams,
+ void **pNBIOContext,
+ void **pState,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+ PKIX_ProcessingParams *caProcParams = NULL;
+ PKIX_PL_Date *date = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ void *nbioContext = NULL;
+ PKIX_Error *buildError = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_OcspResponse_UseBuildChain");
+ PKIX_NULLCHECK_THREE(signerCert, producedAt, procParams);
+ PKIX_NULLCHECK_THREE(pNBIOContext, pState, pBuildResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
+ if (nbioContext == NULL) {
+ /* Starting anew */
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)procParams,
+ (PKIX_PL_Object **)&caProcParams,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_SetDate(procParams, date, plContext),
+ PKIX_PROCESSINGPARAMSSETDATEFAILED);
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_Create
+ (&certSelParams, plContext),
+ PKIX_COMCERTSELPARAMSCREATEFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetCertificate
+ (certSelParams, signerCert, plContext),
+ PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext),
+ PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_SetTargetCertConstraints
+ (caProcParams, certSelector, plContext),
+ PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED);
+ }
+
+ buildError = PKIX_BuildChain
+ (caProcParams,
+ &nbioContext,
+ pState,
+ pBuildResult,
+ pVerifyTree,
+ plContext);
+
+ /* non-null nbioContext means the build would block */
+ if (nbioContext != NULL) {
+
+ *pNBIOContext = nbioContext;
+
+ /* no buildResult means the build has failed */
+ } else if (buildError) {
+ pkixErrorResult = buildError;
+ buildError = NULL;
+ } else {
+ PKIX_DECREF(*pState);
+ }
+
+cleanup:
+
+ PKIX_DECREF(caProcParams);
+ PKIX_DECREF(date);
+ PKIX_DECREF(certSelParams);
+ PKIX_DECREF(certSelector);
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/* --Private-OcspResponse-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspResponse_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_OcspResponse *ocspRsp = NULL;
+ const SEC_HttpClientFcn *httpClient = NULL;
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPRESPONSE_TYPE, plContext),
+ PKIX_OBJECTNOTANOCSPRESPONSE);
+
+ ocspRsp = (PKIX_PL_OcspResponse *)object;
+
+ if (ocspRsp->nssOCSPResponse != NULL) {
+ CERT_DestroyOCSPResponse(ocspRsp->nssOCSPResponse);
+ ocspRsp->nssOCSPResponse = NULL;
+ }
+
+ if (ocspRsp->signerCert != NULL) {
+ CERT_DestroyCertificate(ocspRsp->signerCert);
+ ocspRsp->signerCert = NULL;
+ }
+
+ httpClient = (const SEC_HttpClientFcn *)(ocspRsp->httpClient);
+
+ if (httpClient && (httpClient->version == 1)) {
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+
+ if (ocspRsp->sessionRequest != NULL) {
+ (*hcv1->freeFcn)(ocspRsp->sessionRequest);
+ ocspRsp->sessionRequest = NULL;
+ }
+
+ if (ocspRsp->serverSession != NULL) {
+ (*hcv1->freeSessionFcn)(ocspRsp->serverSession);
+ ocspRsp->serverSession = NULL;
+ }
+ }
+
+ if (ocspRsp->arena != NULL) {
+ PORT_FreeArena(ocspRsp->arena, PR_FALSE);
+ ocspRsp->arena = NULL;
+ }
+
+ PKIX_DECREF(ocspRsp->producedAtDate);
+ PKIX_DECREF(ocspRsp->pkixSignerCert);
+ PKIX_DECREF(ocspRsp->request);
+
+cleanup:
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspResponse_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_OcspResponse *ocspRsp = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPRESPONSE_TYPE, plContext),
+ PKIX_OBJECTNOTANOCSPRESPONSE);
+
+ ocspRsp = (PKIX_PL_OcspResponse *)object;
+
+ if (ocspRsp->encodedResponse->data == NULL) {
+ *pHashcode = 0;
+ } else {
+ PKIX_CHECK(pkix_hash
+ (ocspRsp->encodedResponse->data,
+ ocspRsp->encodedResponse->len,
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspResponse_Equals(
+ PKIX_PL_Object *firstObj,
+ PKIX_PL_Object *secondObj,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType = 0;
+ PKIX_UInt32 firstLen = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_PL_OcspResponse *rsp1 = NULL;
+ PKIX_PL_OcspResponse *rsp2 = NULL;
+ const unsigned char *firstData = NULL;
+ const unsigned char *secondData = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Equals");
+ PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
+
+ /* test that firstObj is a OcspResponse */
+ PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPRESPONSE_TYPE, plContext),
+ PKIX_FIRSTOBJARGUMENTNOTANOCSPRESPONSE);
+
+ /*
+ * Since we know firstObj is a OcspResponse, if both references are
+ * identical, they must be equal
+ */
+ if (firstObj == secondObj){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObj isn't a OcspResponse, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType(secondObj, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_OCSPRESPONSE_TYPE) {
+ goto cleanup;
+ }
+
+ rsp1 = (PKIX_PL_OcspResponse *)firstObj;
+ rsp2 = (PKIX_PL_OcspResponse *)secondObj;
+
+ /* If either lacks an encoded string, they cannot be compared */
+ firstData = (const unsigned char *)rsp1->encodedResponse->data;
+ secondData = (const unsigned char *)rsp2->encodedResponse->data;
+ if ((firstData == NULL) || (secondData == NULL)) {
+ goto cleanup;
+ }
+
+ firstLen = rsp1->encodedResponse->len;
+
+ if (firstLen != rsp2->encodedResponse->len) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < firstLen; i++) {
+ if (*firstData++ != *secondData++) {
+ goto cleanup;
+ }
+ }
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OCSPRESPONSE_TYPE and its related functions with
+ * systemClasses[]
+ * PARAMETERS:
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_OcspResponse_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_OCSPRESPONSE_TYPE];
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_RegisterSelf");
+
+ entry->description = "OcspResponse";
+ entry->typeObjectSize = sizeof(PKIX_PL_OcspResponse);
+ entry->destructor = pkix_pl_OcspResponse_Destroy;
+ entry->equalsFunction = pkix_pl_OcspResponse_Equals;
+ entry->hashcodeFunction = pkix_pl_OcspResponse_Hashcode;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Create
+ * DESCRIPTION:
+ *
+ * This function transmits the OcspRequest pointed to by "request" and obtains
+ * an OcspResponse, which it stores at "pOcspResponse". If the HTTPClient
+ * supports non-blocking I/O this function may store a non-NULL value at
+ * "pNBIOContext" (the WOULDBLOCK condition). In that case the caller should
+ * make a subsequent call with the same value in "pNBIOContext" and
+ * "pOcspResponse" to resume the operation. Additional WOULDBLOCK returns may
+ * occur; the caller should persist until a return occurs with NULL stored at
+ * "pNBIOContext".
+ *
+ * If a SEC_HttpClientFcn "responder" is supplied, it is used as the client
+ * to which the OCSP query is sent. If none is supplied, the default responder
+ * is used.
+ *
+ * If an OcspResponse_VerifyCallback "verifyFcn" is supplied, it is used to
+ * verify the Cert received from the responder as the signer. If none is
+ * supplied, the default verification function is used.
+ *
+ * The contents of "request" are ignored on calls subsequent to a WOULDBLOCK
+ * return, and the caller is permitted to supply NULL.
+ *
+ * PARAMETERS
+ * "request"
+ * Address of the OcspRequest for which a response is desired.
+ * "httpMethod"
+ * GET or POST
+ * "responder"
+ * Address, if non-NULL, of the SEC_HttpClientFcn to be sent the OCSP
+ * query.
+ * "verifyFcn"
+ * Address, if non-NULL, of the OcspResponse_VerifyCallback function to be
+ * used to verify the Cert of the OCSP responder.
+ * "pNBIOContext"
+ * Address at which platform-dependent information is stored for handling
+ * of non-blocking I/O. Must be non-NULL.
+ * "pOcspResponse"
+ * The address where the created OcspResponse is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspResponse_Create(
+ PKIX_PL_OcspRequest *request,
+ const char *httpMethod,
+ void *responder,
+ PKIX_PL_VerifyCallback verifyFcn,
+ void **pNBIOContext,
+ PKIX_PL_OcspResponse **pResponse,
+ void *plContext)
+{
+ void *nbioContext = NULL;
+ PKIX_PL_OcspResponse *ocspResponse = NULL;
+ const SEC_HttpClientFcn *httpClient = NULL;
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ SECStatus rv = SECFailure;
+ char *location = NULL;
+ char *hostname = NULL;
+ char *path = NULL;
+ char *responseContentType = NULL;
+ PRUint16 port = 0;
+ SEC_HTTP_SERVER_SESSION serverSession = NULL;
+ SEC_HTTP_REQUEST_SESSION sessionRequest = NULL;
+ SECItem *encodedRequest = NULL;
+ PRUint16 responseCode = 0;
+ char *responseData = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Create");
+ PKIX_NULLCHECK_TWO(pNBIOContext, pResponse);
+
+ if (!strcmp(httpMethod, "GET") && !strcmp(httpMethod, "POST")) {
+ PKIX_ERROR(PKIX_INVALIDOCSPHTTPMETHOD);
+ }
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ if (nbioContext != NULL) {
+
+ ocspResponse = *pResponse;
+ PKIX_NULLCHECK_ONE(ocspResponse);
+
+ httpClient = ocspResponse->httpClient;
+ serverSession = ocspResponse->serverSession;
+ sessionRequest = ocspResponse->sessionRequest;
+ PKIX_NULLCHECK_THREE(httpClient, serverSession, sessionRequest);
+
+ } else {
+ PKIX_UInt32 timeout =
+ ((PKIX_PL_NssContext*)plContext)->timeoutSeconds;
+
+ PKIX_NULLCHECK_ONE(request);
+
+ PKIX_CHECK(pkix_pl_OcspRequest_GetEncoded
+ (request, &encodedRequest, plContext),
+ PKIX_OCSPREQUESTGETENCODEDFAILED);
+
+ /* prepare initial message to HTTPClient */
+
+ /* Is there a default responder and is it enabled? */
+ if (responder) {
+ httpClient = (const SEC_HttpClientFcn *)responder;
+ } else {
+ httpClient = SEC_GetRegisteredHttpClient();
+ }
+
+ if (httpClient && (httpClient->version == 1)) {
+ char *fullGetPath = NULL;
+ const char *sessionPath = NULL;
+ PRBool usePOST = !strcmp(httpMethod, "POST");
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+
+ PKIX_CHECK(pkix_pl_OcspRequest_GetLocation
+ (request, &location, plContext),
+ PKIX_OCSPREQUESTGETLOCATIONFAILED);
+
+ /* parse location -> hostname, port, path */
+ rv = CERT_ParseURL(location, &hostname, &port, &path);
+ if (rv == SECFailure || hostname == NULL || path == NULL) {
+ PKIX_ERROR(PKIX_URLPARSINGFAILED);
+ }
+
+ rv = (*hcv1->createSessionFcn)(hostname, port,
+ &serverSession);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+
+ if (usePOST) {
+ sessionPath = path;
+ } else {
+ /* calculate, are we allowed to use GET? */
+ enum { max_get_request_size = 255 }; /* defined by RFC2560 */
+ char b64ReqBuf[max_get_request_size+1];
+ size_t base64size;
+ size_t slashLengthIfNeeded = 0;
+ size_t pathLength;
+ PRInt32 urlEncodedBufLength;
+ size_t getURLLength;
+ char *walkOutput = NULL;
+
+ pathLength = strlen(path);
+ if (path[pathLength-1] != '/') {
+ slashLengthIfNeeded = 1;
+ }
+ base64size = (((encodedRequest->len +2)/3) * 4);
+ if (base64size > max_get_request_size) {
+ PKIX_ERROR(PKIX_OCSPGETREQUESTTOOBIG);
+ }
+ memset(b64ReqBuf, 0, sizeof(b64ReqBuf));
+ PL_Base64Encode((const char *)encodedRequest->data, encodedRequest->len, b64ReqBuf);
+ urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL);
+ getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded;
+ fullGetPath = (char*)PORT_Alloc(getURLLength);
+ if (!fullGetPath) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ strcpy(fullGetPath, path);
+ walkOutput = fullGetPath + pathLength;
+ if (walkOutput > fullGetPath && slashLengthIfNeeded) {
+ strcpy(walkOutput, "/");
+ ++walkOutput;
+ }
+ ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput);
+ sessionPath = fullGetPath;
+ }
+
+ rv = (*hcv1->createFcn)(serverSession, "http",
+ sessionPath, httpMethod,
+ PR_SecondsToInterval(timeout),
+ &sessionRequest);
+ sessionPath = NULL;
+ if (fullGetPath) {
+ PORT_Free(fullGetPath);
+ fullGetPath = NULL;
+ }
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+
+ if (usePOST) {
+ rv = (*hcv1->setPostDataFcn)(sessionRequest,
+ (char *)encodedRequest->data,
+ encodedRequest->len,
+ "application/ocsp-request");
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+ }
+
+ /* create a PKIX_PL_OcspResponse object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OCSPRESPONSE_TYPE,
+ sizeof (PKIX_PL_OcspResponse),
+ (PKIX_PL_Object **)&ocspResponse,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ PKIX_INCREF(request);
+ ocspResponse->request = request;
+ ocspResponse->httpClient = httpClient;
+ ocspResponse->serverSession = serverSession;
+ serverSession = NULL;
+ ocspResponse->sessionRequest = sessionRequest;
+ sessionRequest = NULL;
+ ocspResponse->verifyFcn = verifyFcn;
+ ocspResponse->handle = CERT_GetDefaultCertDB();
+ ocspResponse->encodedResponse = NULL;
+ ocspResponse->arena = NULL;
+ ocspResponse->producedAt = 0;
+ ocspResponse->producedAtDate = NULL;
+ ocspResponse->pkixSignerCert = NULL;
+ ocspResponse->nssOCSPResponse = NULL;
+ ocspResponse->signerCert = NULL;
+ }
+ }
+
+ /* begin or resume IO to HTTPClient */
+ if (httpClient && (httpClient->version == 1)) {
+ PRUint32 responseDataLen =
+ ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+
+ rv = (*hcv1->trySendAndReceiveFcn)(ocspResponse->sessionRequest,
+ (PRPollDesc **)&nbioContext,
+ &responseCode,
+ (const char **)&responseContentType,
+ NULL, /* responseHeaders */
+ (const char **)&responseData,
+ &responseDataLen);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+ /* responseContentType is a pointer to the null-terminated
+ * string returned by httpclient. Memory allocated for context
+ * type will be freed with freeing of the HttpClient struct. */
+ if (PORT_Strcasecmp(responseContentType,
+ "application/ocsp-response")) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+ if (nbioContext != NULL) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ if (responseCode != 200) {
+ PKIX_ERROR(PKIX_OCSPBADHTTPRESPONSE);
+ }
+ ocspResponse->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (ocspResponse->arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ ocspResponse->encodedResponse = SECITEM_AllocItem
+ (ocspResponse->arena, NULL, responseDataLen);
+ if (ocspResponse->encodedResponse == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ PORT_Memcpy(ocspResponse->encodedResponse->data,
+ responseData, responseDataLen);
+ }
+ *pResponse = ocspResponse;
+ ocspResponse = NULL;
+
+cleanup:
+
+ if (path != NULL) {
+ PORT_Free(path);
+ }
+ if (hostname != NULL) {
+ PORT_Free(hostname);
+ }
+ if (ocspResponse) {
+ PKIX_DECREF(ocspResponse);
+ }
+ if (serverSession) {
+ hcv1->freeSessionFcn(serverSession);
+ }
+ if (sessionRequest) {
+ hcv1->freeFcn(sessionRequest);
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Decode
+ * DESCRIPTION:
+ *
+ * This function decodes the DER data contained in the OcspResponse pointed to
+ * by "response", storing PKIX_TRUE at "pPassed" if the decoding was
+ * successful, and PKIX_FALSE otherwise.
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the OcspResponse whose DER data is to be decoded. Must
+ * be non-NULL.
+ * "pPassed"
+ * Address at which the Boolean result is stored. Must be non-NULL.
+ * "pReturnCode"
+ * Address at which the SECErrorCodes result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+
+PKIX_Error *
+pkix_pl_OcspResponse_Decode(
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean *pPassed,
+ SECErrorCodes *pReturnCode,
+ void *plContext)
+{
+
+ PKIX_ENTER(OCSPRESPONSE, "PKIX_PL_OcspResponse_Decode");
+ PKIX_NULLCHECK_TWO(response, response->encodedResponse);
+
+ response->nssOCSPResponse =
+ CERT_DecodeOCSPResponse(response->encodedResponse);
+
+ if (response->nssOCSPResponse != NULL) {
+ *pPassed = PKIX_TRUE;
+ *pReturnCode = 0;
+ } else {
+ *pPassed = PKIX_FALSE;
+ *pReturnCode = PORT_GetError();
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_GetStatus
+ * DESCRIPTION:
+ *
+ * This function checks the response status of the OcspResponse pointed to
+ * by "response", storing PKIX_TRUE at "pPassed" if the responder understood
+ * the request and considered it valid, and PKIX_FALSE otherwise.
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the OcspResponse whose status is to be retrieved. Must
+ * be non-NULL.
+ * "pPassed"
+ * Address at which the Boolean result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+
+PKIX_Error *
+pkix_pl_OcspResponse_GetStatus(
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean *pPassed,
+ SECErrorCodes *pReturnCode,
+ void *plContext)
+{
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(OCSPRESPONSE, "PKIX_PL_OcspResponse_GetStatus");
+ PKIX_NULLCHECK_FOUR(response, response->nssOCSPResponse, pPassed, pReturnCode);
+
+ rv = CERT_GetOCSPResponseStatus(response->nssOCSPResponse);
+
+ if (rv == SECSuccess) {
+ *pPassed = PKIX_TRUE;
+ *pReturnCode = 0;
+ } else {
+ *pPassed = PKIX_FALSE;
+ *pReturnCode = PORT_GetError();
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+
+static PKIX_Error*
+pkix_pl_OcspResponse_VerifyResponse(
+ PKIX_PL_OcspResponse *response,
+ PKIX_ProcessingParams *procParams,
+ SECCertUsage certUsage,
+ void **state,
+ PKIX_BuildResult **buildResult,
+ void **pNBIOContext,
+ void *plContext)
+{
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifyResponse");
+
+ if (response->verifyFcn != NULL) {
+ void *lplContext = NULL;
+
+ PKIX_CHECK(
+ PKIX_PL_NssContext_Create(((SECCertificateUsage)1) << certUsage,
+ PKIX_FALSE, NULL, &lplContext),
+ PKIX_NSSCONTEXTCREATEFAILED);
+
+ PKIX_CHECK(
+ (response->verifyFcn)((PKIX_PL_Object*)response->pkixSignerCert,
+ NULL, response->producedAtDate,
+ procParams, pNBIOContext,
+ state, buildResult,
+ NULL, lplContext),
+ PKIX_CERTVERIFYKEYUSAGEFAILED);
+ rv = SECSuccess;
+ } else {
+ /* checkSig is !isRoot */
+ PRBool checkSig = response->signerCert->isRoot ? PR_FALSE : PR_TRUE;
+ rv = CERT_VerifyCert(response->handle, response->signerCert, checkSig,
+ certUsage, response->producedAt, NULL, NULL);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTVERIFYKEYUSAGEFAILED);
+ }
+ }
+
+cleanup:
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_VerifySignature
+ * DESCRIPTION:
+ *
+ * This function verifies the ocspResponse signature field in the OcspResponse
+ * pointed to by "response", storing PKIX_TRUE at "pPassed" if verification
+ * is successful and PKIX_FALSE otherwise. If verification is unsuccessful an
+ * error code (an enumeration of type SECErrorCodes) is stored at *pReturnCode.
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the OcspResponse whose signature field is to be
+ * retrieved. Must be non-NULL.
+ * "cert"
+ * The address of the Cert for which the OCSP query was made. Must be
+ * non-NULL.
+ * "procParams"
+ * Address of ProcessingParams used to initialize the ExpirationChecker
+ * and TargetCertChecker. Must be non-NULL.
+ * "pPassed"
+ * Address at which the Boolean result is stored. Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * checking is complete. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspResponse_VerifySignature(
+ PKIX_PL_OcspResponse *response,
+ PKIX_PL_Cert *cert,
+ PKIX_ProcessingParams *procParams,
+ PKIX_Boolean *pPassed,
+ void **pNBIOContext,
+ void *plContext)
+{
+ SECStatus rv = SECFailure;
+ CERTOCSPResponse *nssOCSPResponse = NULL;
+ CERTCertificate *issuerCert = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ void *nbio = NULL;
+ void *state = NULL;
+
+ ocspSignature *signature = NULL;
+ ocspResponseData *tbsData = NULL;
+ SECItem *tbsResponseDataDER = NULL;
+
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifySignature");
+ PKIX_NULLCHECK_FOUR(response, cert, pPassed, pNBIOContext);
+
+ nbio = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ nssOCSPResponse = response->nssOCSPResponse;
+ if (nssOCSPResponse == NULL) {
+ PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
+ goto cleanup;
+ }
+
+ tbsData =
+ ocsp_GetResponseData(nssOCSPResponse, &tbsResponseDataDER);
+
+ signature = ocsp_GetResponseSignature(nssOCSPResponse);
+
+
+ /* Are we resuming after a WOULDBLOCK response? */
+ if (nbio == NULL) {
+ /* No, this is a new query */
+
+ issuerCert = CERT_FindCertIssuer(cert->nssCert, PR_Now(),
+ certUsageAnyCA);
+
+ /*
+ * If this signature has already gone through verification,
+ * just return the cached result.
+ */
+ if (signature->wasChecked) {
+ if (signature->status == SECSuccess) {
+ response->signerCert =
+ CERT_DupCertificate(signature->cert);
+ } else {
+ PORT_SetError(signature->failureReason);
+ goto cleanup;
+ }
+ }
+
+ response->signerCert =
+ ocsp_GetSignerCertificate(response->handle, tbsData,
+ signature, issuerCert);
+
+ if (response->signerCert == NULL) {
+ if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) {
+ /* Make the error a little more specific. */
+ PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
+ }
+ goto cleanup;
+ }
+ PKIX_CHECK(
+ PKIX_PL_Cert_CreateFromCERTCertificate(response->signerCert,
+ &(response->pkixSignerCert),
+ plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+
+ /*
+ * We could mark this true at the top of this function, or
+ * always below at "finish", but if the problem was just that
+ * we could not find the signer's cert, leave that as if the
+ * signature hasn't been checked. Maybe a subsequent call will
+ * have better luck.
+ */
+ signature->wasChecked = PR_TRUE;
+
+ /*
+ * We are about to verify the signer certificate; we need to
+ * specify *when* that certificate must be valid -- for our
+ * purposes we expect it to be valid when the response was
+ * signed. The value of "producedAt" is the signing time.
+ */
+ rv = DER_GeneralizedTimeToTime(&response->producedAt,
+ &tbsData->producedAt);
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
+ goto cleanup;
+ }
+
+ /*
+ * We need producedAtDate and pkixSignerCert if we are calling a
+ * user-supplied verification function. Let's put their
+ * creation before the code that gets repeated when
+ * non-blocking I/O is used.
+ */
+
+ PKIX_CHECK(
+ pkix_pl_Date_CreateFromPRTime((PRTime)response->producedAt,
+ &(response->producedAtDate),
+ plContext),
+ PKIX_DATECREATEFROMPRTIMEFAILED);
+
+ }
+
+ /*
+ * Just because we have a cert does not mean it is any good; check
+ * it for validity, trust and usage. Use the caller-supplied
+ * verification function, if one was supplied.
+ */
+ if (ocsp_CertIsOCSPDefaultResponder(response->handle,
+ response->signerCert)) {
+ rv = SECSuccess;
+ } else {
+ SECCertUsage certUsage;
+ if (CERT_IsCACert(response->signerCert, NULL)) {
+ certUsage = certUsageAnyCA;
+ } else {
+ certUsage = certUsageStatusResponder;
+ }
+ PKIX_CHECK_ONLY_FATAL(
+ pkix_pl_OcspResponse_VerifyResponse(response, procParams,
+ certUsage, &state,
+ &buildResult, &nbio,
+ plContext),
+ PKIX_CERTVERIFYKEYUSAGEFAILED);
+ if (pkixTempErrorReceived) {
+ rv = SECFailure;
+ goto cleanup;
+ }
+ if (nbio != NULL) {
+ *pNBIOContext = nbio;
+ goto cleanup;
+ }
+ }
+
+ rv = ocsp_VerifyResponseSignature(response->signerCert, signature,
+ tbsResponseDataDER, NULL);
+
+cleanup:
+ if (rv == SECSuccess) {
+ *pPassed = PKIX_TRUE;
+ } else {
+ *pPassed = PKIX_FALSE;
+ }
+
+ if (signature) {
+ if (signature->wasChecked) {
+ signature->status = rv;
+ }
+
+ if (rv != SECSuccess) {
+ signature->failureReason = PORT_GetError();
+ if (response->signerCert != NULL) {
+ CERT_DestroyCertificate(response->signerCert);
+ response->signerCert = NULL;
+ }
+ } else {
+ /* Save signer's certificate in signature. */
+ signature->cert = CERT_DupCertificate(response->signerCert);
+ }
+ }
+
+ if (issuerCert)
+ CERT_DestroyCertificate(issuerCert);
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_GetStatusForCert
+ * DESCRIPTION:
+ *
+ * This function checks the revocation status of the Cert for which the
+ * OcspResponse was obtained, storing PKIX_TRUE at "pPassed" if the Cert has
+ * not been revoked and PKIX_FALSE otherwise.
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the OcspResponse whose certificate status is to be
+ * retrieved. Must be non-NULL.
+ * "pPassed"
+ * Address at which the Boolean result is stored. Must be non-NULL.
+ * "pReturnCode"
+ * Address at which the SECErrorCodes result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspResponse_GetStatusForCert(
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean allowCachingOfFailures,
+ PKIX_PL_Date *validity,
+ PKIX_Boolean *pPassed,
+ SECErrorCodes *pReturnCode,
+ void *plContext)
+{
+ PRTime time = 0;
+ SECStatus rv = SECFailure;
+ CERTOCSPSingleResponse *single = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_GetStatusForCert");
+ PKIX_NULLCHECK_THREE(response, pPassed, pReturnCode);
+
+ /*
+ * It is an error to call this function except following a successful
+ * return from pkix_pl_OcspResponse_VerifySignature, which would have
+ * set response->signerCert.
+ */
+ PKIX_NULLCHECK_TWO(response->signerCert, response->request);
+ PKIX_NULLCHECK_TWO(cid, cid->certID);
+
+ if (validity != NULL) {
+ PKIX_Error *er = pkix_pl_Date_GetPRTime(validity, &time, plContext);
+ PKIX_DECREF(er);
+ }
+ if (!time) {
+ time = PR_Now();
+ }
+
+ rv = ocsp_GetVerifiedSingleResponseForCertID(response->handle,
+ response->nssOCSPResponse,
+ cid->certID,
+ response->signerCert,
+ time, &single);
+ if (rv == SECSuccess) {
+ /*
+ * Check whether the status says revoked, and if so
+ * how that compares to the time value passed into this routine.
+ */
+ rv = ocsp_CertHasGoodStatus(single->certStatus, time);
+ }
+
+ if (rv == SECSuccess || allowCachingOfFailures) {
+ /* allowed to update the cache */
+ PRBool certIDWasConsumed = PR_FALSE;
+
+ if (single) {
+ ocsp_CacheSingleResponse(cid->certID,single,
+ &certIDWasConsumed);
+ } else {
+ cert_RememberOCSPProcessingFailure(cid->certID,
+ &certIDWasConsumed);
+ }
+
+ if (certIDWasConsumed) {
+ cid->certID = NULL;
+ }
+ }
+
+ if (rv == SECSuccess) {
+ *pPassed = PKIX_TRUE;
+ *pReturnCode = 0;
+ } else {
+ *pPassed = PKIX_FALSE;
+ *pReturnCode = PORT_GetError();
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h
new file mode 100644
index 0000000000..dcf88c9603
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h
@@ -0,0 +1,106 @@
+/* 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/. */
+/*
+ * pkix_pl_ocspresponse.h
+ *
+ * OcspResponse Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OCSPRESPONSE_H
+#define _PKIX_PL_OCSPRESPONSE_H
+
+#include "pkix_pl_common.h"
+#include "pkix_pl_ocspcertid.h"
+#include "hasht.h"
+#include "cryptohi.h"
+#include "ocspti.h"
+#include "ocspi.h"
+#include "plbase64.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_OCSP_RESPONSE_LEN (64*1024)
+
+struct PKIX_PL_OcspResponseStruct{
+ PLArenaPool *arena;
+ const PKIX_PL_OcspRequest *request;
+ const SEC_HttpClientFcn *httpClient;
+ SEC_HTTP_SERVER_SESSION serverSession;
+ SEC_HTTP_REQUEST_SESSION sessionRequest;
+ PKIX_PL_VerifyCallback verifyFcn;
+ SECItem *encodedResponse;
+ CERTCertDBHandle *handle;
+ PRTime producedAt;
+ PKIX_PL_Date *producedAtDate;
+ PKIX_PL_Cert *pkixSignerCert;
+ CERTOCSPResponse *nssOCSPResponse;
+ CERTCertificate *signerCert;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_OcspResponse_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_Create(
+ PKIX_PL_OcspRequest *request,
+ const char *httpMechanism,
+ void *responder,
+ PKIX_PL_VerifyCallback verifyFcn,
+ void **pNBIOContext,
+ PKIX_PL_OcspResponse **pResponse,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_Decode(
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean *passed,
+ SECErrorCodes *pReturnCode,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_GetStatus(
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean *passed,
+ SECErrorCodes *pReturnCode,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_VerifySignature(
+ PKIX_PL_OcspResponse *response,
+ PKIX_PL_Cert *cert,
+ PKIX_ProcessingParams *procParams,
+ PKIX_Boolean *pPassed,
+ void **pNBIOContext,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_GetStatusForCert(
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean allowCachingOfFailures,
+ PKIX_PL_Date *validity,
+ PKIX_Boolean *pPassed,
+ SECErrorCodes *pReturnCode,
+ void *plContext);
+
+PKIX_Error *
+PKIX_PL_OcspResponse_UseBuildChain(
+ PKIX_PL_Cert *signerCert,
+ PKIX_PL_Date *producedAt,
+ PKIX_ProcessingParams *procParams,
+ void **pNBIOContext,
+ void **pState,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OCSPRESPONSE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c
new file mode 100644
index 0000000000..2dfe9a9c2c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c
@@ -0,0 +1,489 @@
+/* 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/. */
+/*
+ * pkix_pl_publickey.c
+ *
+ * Certificate Object Functions
+ *
+ */
+
+#include "pkix_pl_publickey.h"
+
+/* --Private-Cert-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the PublicKey
+ * pointed to by "pkixPubKey" and stores it at "pString".
+ *
+ * PARAMETERS
+ * "pkixPubKey"
+ * Address of PublicKey whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PublicKey Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_ToString_Helper(
+ PKIX_PL_PublicKey *pkixPubKey,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ SECAlgorithmID algorithm;
+ SECOidTag pubKeyTag;
+ char *asciiOID = NULL;
+ PKIX_Boolean freeAsciiOID = PKIX_FALSE;
+ SECItem oidBytes;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_ToString_Helper");
+ PKIX_NULLCHECK_THREE(pkixPubKey, pkixPubKey->nssSPKI, pString);
+
+ /*
+ * XXX for now, we print out public key algorithm's
+ * description - add params and bytes later
+ */
+
+ /*
+ * If the algorithm OID is known to NSS,
+ * we print out the ASCII description that is
+ * registered with NSS. Otherwise, if unknown,
+ * we print out the OID numbers (eg. "1.2.840.3")
+ */
+
+ algorithm = pkixPubKey->nssSPKI->algorithm;
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_GetAlgorithmTag).\n");
+ pubKeyTag = SECOID_GetAlgorithmTag(&algorithm);
+ if (pubKeyTag != SEC_OID_UNKNOWN){
+ PKIX_PUBLICKEY_DEBUG
+ ("\t\tCalling SECOID_FindOIDTagDescription).\n");
+ asciiOID = (char *)SECOID_FindOIDTagDescription(pubKeyTag);
+ if (!asciiOID){
+ PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED);
+ }
+ } else { /* pubKeyTag == SEC_OID_UNKNOWN */
+ oidBytes = algorithm.algorithm;
+ PKIX_CHECK(pkix_pl_oidBytes2Ascii
+ (&oidBytes, &asciiOID, plContext),
+ PKIX_OIDBYTES2ASCIIFAILED);
+ freeAsciiOID = PKIX_TRUE;
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, (void *)asciiOID, 0, pString, plContext),
+ PKIX_UNABLETOCREATEPSTRING);
+
+cleanup:
+
+ /*
+ * we only free asciiOID if it was malloc'ed by pkix_pl_oidBytes2Ascii
+ */
+ if (freeAsciiOID){
+ PKIX_FREE(asciiOID);
+ }
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_DestroySPKI
+ * DESCRIPTION:
+ * Frees all memory associated with the CERTSubjectPublicKeyInfo pointed to
+ * by "nssSPKI".
+ * PARAMETERS
+ * "nssSPKI"
+ * Address of CERTSubjectPublicKeyInfo. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_DestroySPKI(
+ CERTSubjectPublicKeyInfo *nssSPKI,
+ void *plContext)
+{
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_DestroySPKI");
+
+ PKIX_NULLCHECK_ONE(nssSPKI);
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_DestroyAlgorithmID).\n");
+ SECOID_DestroyAlgorithmID(&nssSPKI->algorithm, PKIX_FALSE);
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&nssSPKI->subjectPublicKey, PKIX_FALSE);
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *pubKey = NULL;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext),
+ PKIX_OBJECTNOTPUBLICKEY);
+
+ pubKey = (PKIX_PL_PublicKey *)object;
+
+ if (pubKey->nssSPKI) {
+
+ PKIX_CHECK(pkix_pl_DestroySPKI(pubKey->nssSPKI, plContext),
+ PKIX_DESTROYSPKIFAILED);
+
+ PKIX_FREE(pubKey->nssSPKI);
+ }
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *pkixPubKey = NULL;
+ PKIX_PL_String *pubKeyString = NULL;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext),
+ PKIX_OBJECTNOTPUBLICKEY);
+
+ pkixPubKey = (PKIX_PL_PublicKey *)object;
+
+ PKIX_CHECK(pkix_pl_PublicKey_ToString_Helper
+ (pkixPubKey, &pubKeyString, plContext),
+ PKIX_PUBLICKEYTOSTRINGHELPERFAILED);
+
+ *pString = pubKeyString;
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *pkixPubKey = NULL;
+ SECItem algOID;
+ SECItem algParams;
+ SECItem nssPubKey;
+ PKIX_UInt32 algOIDHash;
+ PKIX_UInt32 algParamsHash;
+ PKIX_UInt32 pubKeyHash;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext),
+ PKIX_OBJECTNOTPUBLICKEY);
+
+ pkixPubKey = (PKIX_PL_PublicKey *)object;
+
+ PKIX_NULLCHECK_ONE(pkixPubKey->nssSPKI);
+
+ algOID = pkixPubKey->nssSPKI->algorithm.algorithm;
+ algParams = pkixPubKey->nssSPKI->algorithm.parameters;
+ nssPubKey = pkixPubKey->nssSPKI->subjectPublicKey;
+
+ PKIX_CHECK(pkix_hash
+ (algOID.data, algOID.len, &algOIDHash, plContext),
+ PKIX_HASHFAILED);
+
+ PKIX_CHECK(pkix_hash
+ (algParams.data, algParams.len, &algParamsHash, plContext),
+ PKIX_HASHFAILED);
+
+ PKIX_CHECK(pkix_hash
+ (nssPubKey.data, nssPubKey.len, &pubKeyHash, plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = pubKeyHash;
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *firstPKIXPubKey = NULL;
+ PKIX_PL_PublicKey *secondPKIXPubKey = NULL;
+ CERTSubjectPublicKeyInfo *firstSPKI = NULL;
+ CERTSubjectPublicKeyInfo *secondSPKI = NULL;
+ SECComparison cmpResult;
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a PublicKey */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_PUBLICKEY_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTPUBLICKEY);
+
+ /*
+ * Since we know firstObject is a PublicKey, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a PublicKey, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_PUBLICKEY_TYPE) goto cleanup;
+
+ firstPKIXPubKey = ((PKIX_PL_PublicKey *)firstObject);
+ secondPKIXPubKey = (PKIX_PL_PublicKey *)secondObject;
+
+ firstSPKI = firstPKIXPubKey->nssSPKI;
+ secondSPKI = secondPKIXPubKey->nssSPKI;
+
+ PKIX_NULLCHECK_TWO(firstSPKI, secondSPKI);
+
+ PKIX_PL_NSSCALLRV(PUBLICKEY, cmpResult, SECOID_CompareAlgorithmID,
+ (&firstSPKI->algorithm, &secondSPKI->algorithm));
+
+ if (cmpResult == SECEqual){
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
+ cmpResult = SECITEM_CompareItem
+ (&firstSPKI->subjectPublicKey,
+ &secondSPKI->subjectPublicKey);
+ }
+
+ *pResult = (cmpResult == SECEqual)?PKIX_TRUE:PKIX_FALSE;
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_PUBLICKEY_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_PublicKey_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_RegisterSelf");
+
+ entry.description = "PublicKey";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_PublicKey);
+ entry.destructor = pkix_pl_PublicKey_Destroy;
+ entry.equalsFunction = pkix_pl_PublicKey_Equals;
+ entry.hashcodeFunction = pkix_pl_PublicKey_Hashcode;
+ entry.toStringFunction = pkix_pl_PublicKey_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+ systemClasses[PKIX_PUBLICKEY_TYPE] = entry;
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_PublicKey_NeedsDSAParameters
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_PublicKey_NeedsDSAParameters(
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_Boolean *pNeedsParams,
+ void *plContext)
+{
+ CERTSubjectPublicKeyInfo *nssSPKI = NULL;
+ KeyType pubKeyType;
+ PKIX_Boolean needsParams = PKIX_FALSE;
+
+ PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_NeedsDSAParameters");
+ PKIX_NULLCHECK_TWO(pubKey, pNeedsParams);
+
+ nssSPKI = pubKey->nssSPKI;
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n");
+ pubKeyType = CERT_GetCertKeyType(nssSPKI);
+ if (!pubKeyType){
+ PKIX_ERROR(PKIX_PUBKEYTYPENULLKEY);
+ }
+
+ if ((pubKeyType == dsaKey) &&
+ (nssSPKI->algorithm.parameters.len == 0)){
+ needsParams = PKIX_TRUE;
+ }
+
+ *pNeedsParams = needsParams;
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_PublicKey_MakeInheritedDSAPublicKey(
+ PKIX_PL_PublicKey *firstKey,
+ PKIX_PL_PublicKey *secondKey,
+ PKIX_PL_PublicKey **pResultKey,
+ void *plContext)
+{
+ CERTSubjectPublicKeyInfo *firstSPKI = NULL;
+ CERTSubjectPublicKeyInfo *secondSPKI = NULL;
+ CERTSubjectPublicKeyInfo *thirdSPKI = NULL;
+ PKIX_PL_PublicKey *resultKey = NULL;
+ KeyType firstPubKeyType;
+ KeyType secondPubKeyType;
+ SECStatus rv;
+
+ PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_MakeInheritedDSAPublicKey");
+ PKIX_NULLCHECK_THREE(firstKey, secondKey, pResultKey);
+ PKIX_NULLCHECK_TWO(firstKey->nssSPKI, secondKey->nssSPKI);
+
+ firstSPKI = firstKey->nssSPKI;
+ secondSPKI = secondKey->nssSPKI;
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n");
+ firstPubKeyType = CERT_GetCertKeyType(firstSPKI);
+ if (!firstPubKeyType){
+ PKIX_ERROR(PKIX_FIRSTPUBKEYTYPENULLKEY);
+ }
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n");
+ secondPubKeyType = CERT_GetCertKeyType(secondSPKI);
+ if (!secondPubKeyType){
+ PKIX_ERROR(PKIX_SECONDPUBKEYTYPENULLKEY);
+ }
+
+ if ((firstPubKeyType == dsaKey) &&
+ (firstSPKI->algorithm.parameters.len == 0)){
+ if (secondPubKeyType != dsaKey) {
+ PKIX_ERROR(PKIX_SECONDKEYNOTDSAPUBLICKEY);
+ } else if (secondSPKI->algorithm.parameters.len == 0) {
+ PKIX_ERROR
+ (PKIX_SECONDKEYDSAPUBLICKEY);
+ } else {
+ PKIX_CHECK(PKIX_PL_Calloc
+ (1,
+ sizeof (CERTSubjectPublicKeyInfo),
+ (void **)&thirdSPKI,
+ plContext),
+ PKIX_CALLOCFAILED);
+
+ PKIX_PUBLICKEY_DEBUG
+ ("\t\tCalling"
+ "SECKEY_CopySubjectPublicKeyInfo).\n");
+ rv = SECKEY_CopySubjectPublicKeyInfo
+ (NULL, thirdSPKI, firstSPKI);
+ if (rv != SECSuccess) {
+ PKIX_ERROR
+ (PKIX_SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED);
+ }
+
+ PKIX_PUBLICKEY_DEBUG
+ ("\t\tCalling SECITEM_CopyItem).\n");
+ rv = SECITEM_CopyItem(NULL,
+ &thirdSPKI->algorithm.parameters,
+ &secondSPKI->algorithm.parameters);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ /* create a PKIX_PL_PublicKey object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_PUBLICKEY_TYPE,
+ sizeof (PKIX_PL_PublicKey),
+ (PKIX_PL_Object **)&resultKey,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* populate the SPKI field */
+ resultKey->nssSPKI = thirdSPKI;
+ *pResultKey = resultKey;
+ }
+ } else {
+ *pResultKey = NULL;
+ }
+
+cleanup:
+
+ if (thirdSPKI && PKIX_ERROR_RECEIVED){
+ PKIX_CHECK(pkix_pl_DestroySPKI(thirdSPKI, plContext),
+ PKIX_DESTROYSPKIFAILED);
+ PKIX_FREE(thirdSPKI);
+ }
+
+ PKIX_RETURN(PUBLICKEY);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h
new file mode 100644
index 0000000000..8918859d2d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h
@@ -0,0 +1,38 @@
+/* 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/. */
+/*
+ * pkix_pl_publickey.h
+ *
+ * Public Key Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_PUBLICKEY_H
+#define _PKIX_PL_PUBLICKEY_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_PublicKeyStruct {
+ CERTSubjectPublicKeyInfo *nssSPKI;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_PublicKey_RegisterSelf(void *plContext);
+
+PKIX_Error *
+PKIX_PL_PublicKey_NeedsDSAParameters(
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_Boolean *pNeedsParams,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_PUBLICKEY_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c
new file mode 100644
index 0000000000..e37439cf01
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c
@@ -0,0 +1,667 @@
+/* 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/. */
+/*
+ * pkix_pl_x500name.c
+ *
+ * X500Name Object Functions
+ *
+ */
+
+#include "pkix_pl_x500name.h"
+
+/* --Private-X500Name-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_X500Name_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_X500Name *name = NULL;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext),
+ PKIX_OBJECTNOTANX500NAME);
+
+ name = (PKIX_PL_X500Name *)object;
+
+ /* PORT_FreeArena will destroy arena, and, allocated on it, CERTName
+ * and SECItem */
+ if (name->arena) {
+ PORT_FreeArena(name->arena, PR_FALSE);
+ name->arena = NULL;
+ }
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_X500Name *name = NULL;
+ char *string = NULL;
+ PKIX_UInt32 strLength = 0;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext),
+ PKIX_OBJECTNOTANX500NAME);
+
+ name = (PKIX_PL_X500Name *)object;
+ string = CERT_NameToAscii(&name->nssDN);
+ if (!string){
+ PKIX_ERROR(PKIX_CERTNAMETOASCIIFAILED);
+ }
+ strLength = PL_strlen(string);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, string, strLength, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_X500Name *name = NULL;
+ SECItem *derBytes = NULL;
+ PKIX_UInt32 nameHash;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext),
+ PKIX_OBJECTNOTANX500NAME);
+
+ name = (PKIX_PL_X500Name *)object;
+
+ /* we hash over the bytes in the DER encoding */
+
+ derBytes = &name->derName;
+
+ PKIX_CHECK(pkix_hash
+ (derBytes->data, derBytes->len, &nameHash, plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = nameHash;
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_X500Name_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is an X500Name */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_X500NAME_TYPE, plContext),
+ PKIX_FIRSTOBJECTARGUMENTNOTANX500NAME);
+
+ /*
+ * Since we know firstObject is an X500Name, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't an X500Name, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_X500NAME_TYPE) goto cleanup;
+
+ PKIX_CHECK(
+ PKIX_PL_X500Name_Match((PKIX_PL_X500Name *)firstObject,
+ (PKIX_PL_X500Name *)secondObject,
+ pResult, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_X500NAME_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_X500Name_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_RegisterSelf");
+
+ entry.description = "X500Name";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_X500Name);
+ entry.destructor = pkix_pl_X500Name_Destroy;
+ entry.equalsFunction = pkix_pl_X500Name_Equals;
+ entry.hashcodeFunction = pkix_pl_X500Name_Hashcode;
+ entry.toStringFunction = pkix_pl_X500Name_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_X500NAME_TYPE] = entry;
+
+ PKIX_RETURN(X500NAME);
+}
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: pkix_pl_X500Name_CreateFromUtf8
+ *
+ * DESCRIPTION:
+ * Creates an X500Name object from the RFC1485 string representation pointed
+ * to by "stringRep", and stores the result at "pName". If the string cannot
+ * be successfully converted, a non-fatal error is returned.
+ *
+ * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed to be
+ * called only by pkix tests programs.
+ *
+ * PARAMETERS:
+ * "stringRep"
+ * Address of the RFC1485 string to be converted. Must be non-NULL.
+ * "pName"
+ * Address where the X500Name result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an X500NAME Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_CreateFromUtf8(
+ char *stringRep,
+ PKIX_PL_X500Name **pName,
+ void *plContext)
+{
+ PKIX_PL_X500Name *x500Name = NULL;
+ PLArenaPool *arena = NULL;
+ CERTName *nssDN = NULL;
+ SECItem *resultSecItem = NULL;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_CreateFromUtf8");
+ PKIX_NULLCHECK_TWO(pName, stringRep);
+
+ nssDN = CERT_AsciiToName(stringRep);
+ if (nssDN == NULL) {
+ PKIX_ERROR(PKIX_COULDNOTCREATENSSDN);
+ }
+
+ arena = nssDN->arena;
+
+ /* create a PKIX_PL_X500Name object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_X500NAME_TYPE,
+ sizeof (PKIX_PL_X500Name),
+ (PKIX_PL_Object **)&x500Name,
+ plContext),
+ PKIX_COULDNOTCREATEX500NAMEOBJECT);
+
+ /* populate the nssDN field */
+ x500Name->arena = arena;
+ x500Name->nssDN.arena = arena;
+ x500Name->nssDN.rdns = nssDN->rdns;
+
+ resultSecItem =
+ SEC_ASN1EncodeItem(arena, &x500Name->derName, nssDN,
+ CERT_NameTemplate);
+
+ if (resultSecItem == NULL){
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ *pName = x500Name;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ if (x500Name) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name,
+ plContext);
+ } else if (nssDN) {
+ CERT_DestroyName(nssDN);
+ }
+ }
+
+ PKIX_RETURN(X500NAME);
+}
+#endif /* BUILD_LIBPKIX_TESTS */
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetCERTName
+ *
+ * DESCRIPTION:
+ *
+ * Returns the pointer to CERTName member of X500Name structure.
+ *
+ * Returned pointed should not be freed.2
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose OrganizationName is to be extracted. Must be
+ * non-NULL.
+ * "pCERTName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetCERTName(
+ PKIX_PL_X500Name *xname,
+ CERTName **pCERTName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCERTName");
+ PKIX_NULLCHECK_TWO(xname, pCERTName);
+
+ *pCERTName = &xname->nssDN;
+
+ PKIX_RETURN(X500NAME);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_X500Name_CreateFromCERTName (see comments in pkix_pl_pki.h)
+ */
+
+PKIX_Error *
+PKIX_PL_X500Name_CreateFromCERTName(
+ SECItem *derName,
+ CERTName *name,
+ PKIX_PL_X500Name **pName,
+ void *plContext)
+{
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECFailure;
+ PKIX_PL_X500Name *x500Name = NULL;
+
+ PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_CreateFromCERTName");
+ PKIX_NULLCHECK_ONE(pName);
+ if (derName == NULL && name == NULL) {
+ PKIX_ERROR(PKIX_NULLARGUMENT);
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_X500NAME_TYPE,
+ sizeof (PKIX_PL_X500Name),
+ (PKIX_PL_Object **)&x500Name,
+ plContext),
+ PKIX_COULDNOTCREATEX500NAMEOBJECT);
+
+ x500Name->arena = arena;
+ x500Name->nssDN.arena = NULL;
+
+ if (derName != NULL) {
+ rv = SECITEM_CopyItem(arena, &x500Name->derName, derName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ }
+
+ if (name != NULL) {
+ rv = CERT_CopyName(arena, &x500Name->nssDN, name);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_CERTCOPYNAMEFAILED);
+ }
+ } else {
+ rv = SEC_QuickDERDecodeItem(arena, &x500Name->nssDN,
+ CERT_NameTemplate,
+ &x500Name->derName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_SECQUICKDERDECODERFAILED);
+ }
+ }
+
+ *pName = x500Name;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ if (x500Name) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name,
+ plContext);
+ } else if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+
+ PKIX_RETURN(X500NAME);
+}
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: PKIX_PL_X500Name_Create (see comments in pkix_pl_pki.h)
+ *
+ * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed
+ * to be called only by pkix tests programs.
+ */
+PKIX_Error *
+PKIX_PL_X500Name_Create(
+ PKIX_PL_String *stringRep,
+ PKIX_PL_X500Name **pName,
+ void *plContext)
+{
+ char *utf8String = NULL;
+ PKIX_UInt32 utf8Length = 0;
+
+ PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Create");
+ PKIX_NULLCHECK_TWO(pName, stringRep);
+
+ /*
+ * convert the input PKIX_PL_String to PKIX_UTF8_NULL_TERM.
+ * we need to use this format specifier because
+ * CERT_AsciiToName expects a NULL-terminated UTF8 string.
+ * Since UTF8 allow NUL characters in the middle of the
+ * string, this is buggy. However, as a workaround, using
+ * PKIX_UTF8_NULL_TERM gives us a NULL-terminated UTF8 string.
+ */
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stringRep,
+ PKIX_UTF8_NULL_TERM,
+ (void **)&utf8String,
+ &utf8Length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_CHECK(
+ pkix_pl_X500Name_CreateFromUtf8(utf8String,
+ pName, plContext),
+ PKIX_X500NAMECREATEFROMUTF8FAILED);
+
+cleanup:
+ PKIX_FREE(utf8String);
+
+ PKIX_RETURN(X500NAME);
+}
+#endif /* BUILD_LIBPKIX_TESTS */
+
+/*
+ * FUNCTION: PKIX_PL_X500Name_Match (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_X500Name_Match(
+ PKIX_PL_X500Name *firstX500Name,
+ PKIX_PL_X500Name *secondX500Name,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ SECItem *firstDerName = NULL;
+ SECItem *secondDerName = NULL;
+ SECComparison cmpResult;
+
+ PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Match");
+ PKIX_NULLCHECK_THREE(firstX500Name, secondX500Name, pResult);
+
+ if (firstX500Name == secondX500Name){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ firstDerName = &firstX500Name->derName;
+ secondDerName = &secondX500Name->derName;
+
+ PKIX_NULLCHECK_TWO(firstDerName->data, secondDerName->data);
+
+ cmpResult = SECITEM_CompareItem(firstDerName, secondDerName);
+ if (cmpResult != SECEqual) {
+ cmpResult = CERT_CompareName(&firstX500Name->nssDN,
+ &secondX500Name->nssDN);
+ }
+
+ *pResult = (cmpResult == SECEqual);
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetSECName
+ *
+ * DESCRIPTION:
+ * Returns a copy of CERTName DER representation allocated on passed in arena.
+ * If allocation on arena can not be done, NULL is stored at "pSECName".
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose CERTName flag is to be encoded. Must be
+ * non-NULL.
+ * "arena"
+ * Address of the PLArenaPool to be used in the encoding, and in which
+ * "pSECName" will be allocated. Must be non-NULL.
+ * "pSECName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetDERName(
+ PKIX_PL_X500Name *xname,
+ PLArenaPool *arena,
+ SECItem **pDERName,
+ void *plContext)
+{
+ SECItem *derName = NULL;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetDERName");
+
+ PKIX_NULLCHECK_THREE(xname, arena, pDERName);
+
+ /* Return NULL is X500Name was not created from DER */
+ if (xname->derName.data == NULL) {
+ *pDERName = NULL;
+ goto cleanup;
+ }
+
+ derName = SECITEM_ArenaDupItem(arena, &xname->derName);
+ if (derName == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ *pDERName = derName;
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetCommonName
+ *
+ * DESCRIPTION:
+ * Extracts the CommonName component of the X500Name object pointed to by
+ * "xname", and stores the result at "pCommonName". If the CommonName cannot
+ * be successfully extracted, NULL is stored at "pCommonName".
+ *
+ * The returned string must be freed with PORT_Free.
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose CommonName is to be extracted. Must be
+ * non-NULL.
+ * "pCommonName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetCommonName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCommonName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCommonName");
+ PKIX_NULLCHECK_TWO(xname, pCommonName);
+
+ *pCommonName = (unsigned char *)CERT_GetCommonName(&xname->nssDN);
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetCountryName
+ *
+ * DESCRIPTION:
+ * Extracts the CountryName component of the X500Name object pointed to by
+ * "xname", and stores the result at "pCountryName". If the CountryName cannot
+ * be successfully extracted, NULL is stored at "pCountryName".
+ *
+ * The returned string must be freed with PORT_Free.
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose CountryName is to be extracted. Must be
+ * non-NULL.
+ * "pCountryName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetCountryName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCountryName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCountryName");
+ PKIX_NULLCHECK_TWO(xname, pCountryName);
+
+ *pCountryName = (unsigned char*)CERT_GetCountryName(&xname->nssDN);
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetOrgName
+ *
+ * DESCRIPTION:
+ * Extracts the OrganizationName component of the X500Name object pointed to by
+ * "xname", and stores the result at "pOrgName". If the OrganizationName cannot
+ * be successfully extracted, NULL is stored at "pOrgName".
+ *
+ * The returned string must be freed with PORT_Free.
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose OrganizationName is to be extracted. Must be
+ * non-NULL.
+ * "pOrgName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetOrgName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pOrgName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetOrgName");
+ PKIX_NULLCHECK_TWO(xname, pOrgName);
+
+ *pOrgName = (unsigned char*)CERT_GetOrgName(&xname->nssDN);
+
+ PKIX_RETURN(X500NAME);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h
new file mode 100644
index 0000000000..a62bdb82d5
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h
@@ -0,0 +1,74 @@
+/* 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/. */
+/*
+ * pkix_pl_x500name.h
+ *
+ * X500Name Object Type Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_X500NAME_H
+#define _PKIX_PL_X500NAME_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct PKIX_PL_X500NameStruct{
+ PLArenaPool *arena; /* X500Name arena. Shared arena with nssDN
+ * and derName */
+ CERTName nssDN;
+ SECItem derName; /* adding DER encoded CERTName to the structure
+ * to avoid unnecessary name encoding when pass
+ * der name to cert finder */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_X500Name_RegisterSelf(void *plContext);
+
+PKIX_Error *pkix_pl_X500Name_GetDERName(
+ PKIX_PL_X500Name *xname,
+ PLArenaPool *arena,
+ SECItem **pSECName,
+ void *plContext);
+
+#ifdef BUILD_LIBPKIX_TESTS
+PKIX_Error * pkix_pl_X500Name_CreateFromUtf8(
+ char *stringRep,
+ PKIX_PL_X500Name **pName,
+ void *plContext);
+#endif /* BUILD_LIBPKIX_TESTS */
+
+PKIX_Error *pkix_pl_X500Name_GetCommonName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCommonName,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_X500Name_GetCountryName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCountryName,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_X500Name_GetOrgName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pOrgName,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_X500Name_GetCERTName(
+ PKIX_PL_X500Name *xname,
+ CERTName **pCERTName,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_X500NAME_H */