summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Barnes <rbarnes@mozilla.com>2015-04-11 22:26:44 +0200
committerRichard Barnes <rbarnes@mozilla.com>2015-04-11 22:26:44 +0200
commit8d4dc5a8d19120e272d6f0a7915785d7532b18f7 (patch)
tree522be30cab4a9a2296514679b152e6c36b9497c1
parent34372b35e32584d40d2be2ad9ca889c481a4c771 (diff)
downloadnss-hg-8d4dc5a8d19120e272d6f0a7915785d7532b18f7.tar.gz
Bug 991783 - Add generic mechanism to add name constraints to built-in certificates r=wtc
-rw-r--r--lib/certdb/cert.h17
-rw-r--r--lib/certdb/genname.c155
-rw-r--r--lib/nss/nss.def6
3 files changed, 112 insertions, 66 deletions
diff --git a/lib/certdb/cert.h b/lib/certdb/cert.h
index 6e0bdb089..4564dc2dd 100644
--- a/lib/certdb/cert.h
+++ b/lib/certdb/cert.h
@@ -1172,6 +1172,20 @@ CERT_GetNextGeneralName(CERTGeneralName *current);
extern CERTGeneralName *
CERT_GetPrevGeneralName(CERTGeneralName *current);
+/*
+ * Look up name constraints for some certs that do not include name constraints
+ * (Most importantly, root certificates)
+ *
+ * If a matching subject is found, |extensions| will be populated with a copy of the
+ * DER-encoded name constraints extension. The data in |extensions| will point to
+ * memory that the caller owns.
+ *
+ * There is no mechanism to configure imposed name constraints right now. All
+ * imposed name constraints are built into NSS.
+ */
+SECStatus
+CERT_GetImposedNameConstraints(const SECItem *derSubject, SECItem *extensions);
+
CERTNameConstraint *
CERT_GetNextNameConstraint(CERTNameConstraint *current);
@@ -1543,6 +1557,9 @@ CERT_CheckNameSpace(PLArenaPool *arena,
/*
* Extract and allocate the name constraints extension from the CA cert.
+ * If the certificate contains no name constraints extension, but
+ * CERT_GetImposedNameConstraints returns a name constraints extension
+ * for the subject of the certificate, then that extension will be returned.
*/
extern SECStatus
CERT_FindNameConstraintsExten(PLArenaPool *arena,
diff --git a/lib/certdb/genname.c b/lib/certdb/genname.c
index 1b0cc9704..e3bc11d59 100644
--- a/lib/certdb/genname.c
+++ b/lib/certdb/genname.c
@@ -1556,76 +1556,98 @@ done:
return rv;
}
-/* Add name constraints to certain certs that do not include name constraints
- * This is the core of the implementation for bug 952572.
+/*
+ * Here we define a list of name constraints to be imposed on
+ * certain certificates, most importantly root certificates.
+ *
+ * Each entry in the name constraints list is constructed with this
+ * macro. An entry contains two SECItems, which have names in
+ * specific forms to make the macro work:
+ *
+ * * ${CA}_SUBJECT_DN - The subject DN for which the constraints
+ * should be applied
+ * * ${CA}_NAME_CONSTRAINTS - The name constraints extension
+ *
+ * Entities subject to name constraints are identified by subject name
+ * so that we can cover all certificates for that entity, including, e.g.,
+ * cross-certificates. We use subject rather than public key because
+ * calling methods often have easy access to that field (vs., say, a key ID),
+ * and in practice, subject names and public keys are usually in one-to-one
+ * correspondence anyway.
+ *
*/
-static SECStatus
-getNameExtensionsBuiltIn(CERTCertificate *cert,
- SECItem *extensions)
+#define STRING_TO_SECITEM(str) \
+{ siBuffer, (unsigned char*) str, sizeof(str) - 1 }
+
+#define NAME_CONSTRAINTS_ENTRY(CA) \
+ { \
+ STRING_TO_SECITEM(CA ## _SUBJECT_DN), \
+ STRING_TO_SECITEM(CA ## _NAME_CONSTRAINTS) \
+ }
+
+/* Agence Nationale de la Securite des Systemes d'Information (ANSSI) */
+
+#define ANSSI_SUBJECT_DN \
+ "\x30\x81\x85" \
+ "\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02" "FR" /* C */ \
+ "\x31\x0F\x30\x0D\x06\x03\x55\x04\x08\x13\x06" "France" /* ST */ \
+ "\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05" "Paris" /* L */ \
+ "\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07" "PM/SGDN" /* O */ \
+ "\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13\x05" "DCSSI" /* OU */ \
+ "\x31\x0E\x30\x0C\x06\x03\x55\x04\x03\x13\x05" "IGC/A" /* CN */ \
+ "\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01" \
+ "\x16\x14" "igca@sgdn.pm.gouv.fr" /* emailAddress */ \
+
+#define ANSSI_NAME_CONSTRAINTS \
+ "\x30\x5D\xA0\x5B" \
+ "\x30\x05\x82\x03" ".fr" \
+ "\x30\x05\x82\x03" ".gp" \
+ "\x30\x05\x82\x03" ".gf" \
+ "\x30\x05\x82\x03" ".mq" \
+ "\x30\x05\x82\x03" ".re" \
+ "\x30\x05\x82\x03" ".yt" \
+ "\x30\x05\x82\x03" ".pm" \
+ "\x30\x05\x82\x03" ".bl" \
+ "\x30\x05\x82\x03" ".mf" \
+ "\x30\x05\x82\x03" ".wf" \
+ "\x30\x05\x82\x03" ".pf" \
+ "\x30\x05\x82\x03" ".nc" \
+ "\x30\x05\x82\x03" ".tf" \
+
+static const SECItem builtInNameConstraints[][2] = {
+ NAME_CONSTRAINTS_ENTRY(ANSSI)
+};
+
+SECStatus
+CERT_GetImposedNameConstraints(const SECItem *derSubject,
+ SECItem *extensions)
{
- const char constraintFranceGov[] = "\x30\x5D" /* sequence len = 93*/
- "\xA0\x5B" /* element len =91 */
- "\x30\x05" /* sequence len 5 */
- "\x82\x03" /* entry len 3 */
- ".fr"
- "\x30\x05\x82\x03" /* sequence len5, entry len 3 */
- ".gp"
- "\x30\x05\x82\x03"
- ".gf"
- "\x30\x05\x82\x03"
- ".mq"
- "\x30\x05\x82\x03"
- ".re"
- "\x30\x05\x82\x03"
- ".yt"
- "\x30\x05\x82\x03"
- ".pm"
- "\x30\x05\x82\x03"
- ".bl"
- "\x30\x05\x82\x03"
- ".mf"
- "\x30\x05\x82\x03"
- ".wf"
- "\x30\x05\x82\x03"
- ".pf"
- "\x30\x05\x82\x03"
- ".nc"
- "\x30\x05\x82\x03"
- ".tf";
-
- /* The stringified value for the subject is:
- E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
- */
- const char rawANSSISubject[] = "\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04"
- "\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03"
- "\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65"
- "\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05"
- "\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03"
- "\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44"
- "\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13"
- "\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06"
- "\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41"
- "\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7"
- "\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40"
- "\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75"
- "\x76\x2E\x66\x72";
-
- const SECItem anssi_subject = {0, (unsigned char *) rawANSSISubject,
- sizeof(rawANSSISubject)-1};
- const SECItem permitFranceGovNC = {0, (unsigned char *) constraintFranceGov,
- sizeof(constraintFranceGov)-1};
-
- if (SECITEM_ItemsAreEqual(&cert->derSubject, &anssi_subject)) {
- SECStatus rv;
- rv = SECITEM_CopyItem(NULL, extensions, &permitFranceGovNC);
- return rv;
- }
- PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
- return SECFailure;
+ size_t i;
+
+ if (!extensions) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ for (i = 0; i < PR_ARRAY_SIZE(builtInNameConstraints); ++i) {
+ if (SECITEM_ItemsAreEqual(derSubject, &builtInNameConstraints[i][0])) {
+ return SECITEM_CopyItem(NULL,
+ extensions,
+ &builtInNameConstraints[i][1]);
+ }
+ }
+
+ PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
+ return SECFailure;
}
-/* Extract the name constraints extension from the CA cert. */
+/*
+ * Extract the name constraints extension from the CA cert.
+ * If the certificate contains no name constraints extension, but
+ * CERT_GetImposedNameConstraints returns a name constraints extension
+ * for the subject of the certificate, then that extension will be returned.
+ */
SECStatus
CERT_FindNameConstraintsExten(PLArenaPool *arena,
CERTCertificate *cert,
@@ -1643,7 +1665,8 @@ CERT_FindNameConstraintsExten(PLArenaPool *arena,
if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
return rv;
}
- rv = getNameExtensionsBuiltIn(cert, &constraintsExtension);
+ rv = CERT_GetImposedNameConstraints(&cert->derSubject,
+ &constraintsExtension);
if (rv != SECSuccess) {
if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
return SECSuccess;
diff --git a/lib/nss/nss.def b/lib/nss/nss.def
index abe0604f5..fdc8a8a15 100644
--- a/lib/nss/nss.def
+++ b/lib/nss/nss.def
@@ -1070,3 +1070,9 @@ SEC_GetCrlTimes;
;+ local:
;+ *;
;+};
+;+NSS_3.18.1 { # NSS 3.18.1 release
+;+ global:
+CERT_GetImposedNameConstraints;
+;+ local:
+;+ *;
+;+};