diff --git a/v3/integration/config.json b/v3/integration/config.json index 408387c32..1807608a9 100644 --- a/v3/integration/config.json +++ b/v3/integration/config.json @@ -383,7 +383,7 @@ "e_cert_unique_identifier_version_not_2_or_3": {}, "e_distribution_point_incomplete": {}, "e_dnsname_bad_character_in_label": { - "ErrCount": 55927 + "ErrCount": 55930 }, "e_dnsname_contains_bare_iana_suffix": { "ErrCount": 8 @@ -400,7 +400,7 @@ "ErrCount": 17 }, "e_dnsname_not_valid_tld": { - "ErrCount": 86371 + "ErrCount": 86374 }, "e_dnsname_underscore_in_sld": { "ErrCount": 5 @@ -491,7 +491,7 @@ "ErrCount": 2 }, "e_ext_san_missing": { - "ErrCount": 52385 + "ErrCount": 52388 }, "e_ext_san_no_entries": { "ErrCount": 3 @@ -576,7 +576,7 @@ "ErrCount": 370 }, "e_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth": { - "ErrCount": 93 + "ErrCount": 95 }, "e_old_root_ca_rsa_mod_less_than_2048_bits": { "ErrCount": 1 @@ -711,7 +711,7 @@ "ErrCount": 81098 }, "e_sub_cert_eku_server_auth_client_auth_missing": { - "ErrCount": 4934 + "ErrCount": 4943 }, "e_sub_cert_given_name_surname_contains_correct_policy": { "ErrCount": 1793 @@ -751,7 +751,7 @@ "ErrCount": 2 }, "e_subject_common_name_not_from_san": { - "ErrCount": 94976 + "ErrCount": 94979 }, "e_subject_contains_noninformational_value": { "ErrCount": 338 @@ -818,7 +818,7 @@ }, "e_cab_dv_subject_invalid_values": {}, "n_ca_digital_signature_not_set": { - "NoticeCount": 1409 + "NoticeCount": 1411 }, "n_contains_redacted_dnsname": { "NoticeCount": 464 @@ -845,10 +845,10 @@ "NoticeCount": 1415 }, "n_sub_ca_eku_not_technically_constrained": { - "NoticeCount": 10 + "NoticeCount": 12 }, "n_subject_common_name_included": { - "NoticeCount": 712639 + "NoticeCount": 712866 }, "w_ct_sct_policy_count_unsatisfied": { "NoticeCount": 5003 @@ -935,17 +935,17 @@ "WarnCount": 9 }, "w_sub_ca_name_constraints_not_critical": { - "WarnCount": 115 + "WarnCount": 116 }, "w_sub_cert_aia_contains_internal_names": { "WarnCount": 210 }, "w_sub_cert_aia_does_not_contain_issuing_ca_url": { - "WarnCount": 48465 + "WarnCount": 48469 }, "w_sub_cert_certificate_policies_marked_critical": {}, "w_sub_cert_eku_extra_values": { - "WarnCount": 25405 + "WarnCount": 25412 }, "w_sub_cert_sha1_expiration_too_long": { "WarnCount": 11058 diff --git a/v3/integration/small.config.json b/v3/integration/small.config.json index 621242602..7f85f0159 100644 --- a/v3/integration/small.config.json +++ b/v3/integration/small.config.json @@ -349,7 +349,7 @@ }, "n_sub_ca_eku_not_technically_constrained": {}, "n_subject_common_name_included": { - "NoticeCount": 19776 + "NoticeCount": 19785 }, "w_ct_sct_policy_count_unsatisfied": { "NoticeCount": 176 diff --git a/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields_test.go b/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields_test.go index f8ba80654..b08b50399 100644 --- a/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields_test.go +++ b/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields_test.go @@ -32,7 +32,7 @@ func TestSubCAEKUValidFields(t *testing.T) { func TestSubCAEKUNotValidFields(t *testing.T) { inputPath := "subCAEKUNotValidFields.pem" - expected := lint.NA + expected := lint.Notice out := test.TestLint("n_sub_ca_eku_not_technically_constrained", inputPath) if out.Status != expected { t.Errorf("%s: expected %s, got %s", inputPath, expected, out.Status) diff --git a/v3/lints/cabf_br/lint_sub_cert_eku_check.go b/v3/lints/cabf_br/lint_sub_cert_eku_check.go new file mode 100644 index 000000000..c5ef84c39 --- /dev/null +++ b/v3/lints/cabf_br/lint_sub_cert_eku_check.go @@ -0,0 +1,81 @@ +package cabf_br + +/* + * ZLint Copyright 2024 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subExtKeyUsageCheck struct{} + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_sub_cert_eku_check", + Description: "Subscriber certificates MUST have id-kp-serverAuth and MAY have id-kp-clientAuth present in extKeyUsage", + Citation: "BRs: 7.1.2.7.10 Subscriber Certificate Extended Key Usage", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABFBRs_2_0_0_Date, + }, + Lint: NewSubExtKeyUsageCheck, + }) +} + +func NewSubExtKeyUsageCheck() lint.LintInterface { + return &subExtKeyUsageCheck{} +} + +func (l *subExtKeyUsageCheck) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.IsExtInCert(c, util.EkuSynOid) +} + +func (l *subExtKeyUsageCheck) Execute(c *x509.Certificate) *lint.LintResult { + var hasClientAuthEKU, hasServerAuthEKU bool + + for _, eku := range c.ExtKeyUsage { + switch eku { + case x509.ExtKeyUsageServerAuth: + hasServerAuthEKU = true + + case x509.ExtKeyUsageClientAuth: + hasClientAuthEKU = true + + case x509.ExtKeyUsageAny, x509.ExtKeyUsageCodeSigning, x509.ExtKeyUsageTimeStamping, + x509.ExtKeyUsageOcspSigning, x509.ExtKeyUsageEmailProtection: + + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("%s MUST NOT be present", util.GetEKUString(eku))} + } + } + + if !hasServerAuthEKU { + return &lint.LintResult{Status: lint.Error, Details: "id-kp-serverAuth MUST be present"} + } + + for _, eku := range c.UnknownExtKeyUsage { + if eku.Equal(util.PreCertificateSigningCertificateEKU) { + return &lint.LintResult{Status: lint.Error, Details: "Precertificate Signing Certificate extKeyUsage MUST NOT be present"} + } + } + + if (len(c.ExtKeyUsage) > 2 && !hasClientAuthEKU) || len(c.UnknownExtKeyUsage) > 0 { + return &lint.LintResult{Status: lint.Warn, Details: "any other value than id-kp-serverAuth and id-kp-clientAuth is NOT RECOMMENDED"} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/v3/lints/cabf_br/lint_sub_cert_eku_check_test.go b/v3/lints/cabf_br/lint_sub_cert_eku_check_test.go new file mode 100644 index 000000000..dae8bca4c --- /dev/null +++ b/v3/lints/cabf_br/lint_sub_cert_eku_check_test.go @@ -0,0 +1,75 @@ +package cabf_br + +/* + * ZLint Copyright 2024 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "testing" + + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/test" +) + +func TestSubExtKeyUsageCheck(t *testing.T) { + testCases := []struct { + Name string + InputFilename string + ExpectedResult lint.LintStatus + }{ + { + Name: "pass - serverAuth EKU", + InputFilename: "subExtKeyUsageServerAuth.pem", + ExpectedResult: lint.Pass, + }, + { + Name: "pass - serverAuth and clientAuth EKU", + InputFilename: "subExtKeyUSageServerAndClientAuth.pem", + ExpectedResult: lint.Pass, + }, + { + Name: "error - only clientAuth EKU with CA/B TLS BR policy OID", + InputFilename: "subExtKeyUsageClientAuth.pem", + ExpectedResult: lint.Error, + }, + { + Name: "ne - only clientAuth EKU, with CA/B TLS BR policy OID, NotBefore before effective date", + InputFilename: "subExtKeyUsageClientAuthPreBRv2.pem", + ExpectedResult: lint.NE, + }, + { + Name: "error - serverAuth and timeStamping EKU", + InputFilename: "subExtKeyUsageServerAuthAndTimeStamping.pem", + ExpectedResult: lint.Error, + }, + { + Name: "error - serverAuth and unknown PreCertSigCert EKU", + InputFilename: "subExtKeyUsageServerAuthAndPreCertSigCert.pem", + ExpectedResult: lint.Error, + }, + { + Name: "warn - serverAuth and MicrosoftDocumentSigning EKU", + InputFilename: "subExtKeyUsageServerAuthAndUnknown.pem", + ExpectedResult: lint.Warn, + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + result := test.TestLint("e_sub_cert_eku_check", tc.InputFilename) + if result.Status != tc.ExpectedResult { + t.Errorf("expected result %v was %v - details: %v", tc.ExpectedResult, result.Status, result.Details) + } + }) + } +} diff --git a/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go b/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go index 2febde6fe..c7d1f182c 100644 --- a/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go +++ b/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go @@ -34,11 +34,12 @@ present. func init() { lint.RegisterCertificateLint(&lint.CertificateLint{ LintMetadata: lint.LintMetadata{ - Name: "w_sub_cert_eku_extra_values", - Description: "Subscriber Certificate: extKeyUsage values other than id-kp-serverAuth, id-kp-clientAuth, and id-kp-emailProtection SHOULD NOT be present.", - Citation: "BRs: 7.1.2.3", - Source: lint.CABFBaselineRequirements, - EffectiveDate: util.CABEffectiveDate, + Name: "w_sub_cert_eku_extra_values", + Description: "Subscriber Certificate: extKeyUsage values other than id-kp-serverAuth, id-kp-clientAuth, and id-kp-emailProtection SHOULD NOT be present.", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + IneffectiveDate: util.CABFBRs_2_0_0_Date, }, Lint: NewSubExtKeyUsageLegalUsage, }) diff --git a/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go b/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go index 3ef75c2b0..adb67b4d0 100644 --- a/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go +++ b/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go @@ -34,11 +34,12 @@ present. func init() { lint.RegisterCertificateLint(&lint.CertificateLint{ LintMetadata: lint.LintMetadata{ - Name: "e_sub_cert_eku_server_auth_client_auth_missing", - Description: "Subscriber certificates MUST have either id-kp-serverAuth or id-kp-clientAuth or both present in extKeyUsage", - Citation: "BRs: 7.1.2.3", - Source: lint.CABFBaselineRequirements, - EffectiveDate: util.CABEffectiveDate, + Name: "e_sub_cert_eku_server_auth_client_auth_missing", + Description: "Subscriber certificates MUST have either id-kp-serverAuth or id-kp-clientAuth or both present in extKeyUsage", + Citation: "BRs: 7.1.2.3", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + IneffectiveDate: util.CABFBRs_2_0_0_Date, }, Lint: NewSubExtKeyUsageClientOrServer, }) diff --git a/v3/testdata/subExtKeyUSageServerAndClientAuth.pem b/v3/testdata/subExtKeyUSageServerAndClientAuth.pem new file mode 100644 index 000000000..e14b8a000 --- /dev/null +++ b/v3/testdata/subExtKeyUSageServerAndClientAuth.pem @@ -0,0 +1,38 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Sep 15 12:00:00 2023 GMT + Not After : Sep 15 12:00:00 2024 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:f1:d5:c1:b1:f9:0f:63:d7:c2:ba:83:a3:c6:b7: + fb:cf:07:bb:c7:33:03:61:4d:13:0f:45:46:8d:47: + 7f:41:ce:8f:9f:1f:85:37:ee:ff:30:00:37:3c:53: + 8b:60:aa:38:48:a8:5c:ca:c7:0c:78:12:f4:2e:ca: + 62:d8:f7:6c:b5 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:45:02:20:79:05:6d:37:0a:db:85:a5:6f:54:68:1d:37:50: + 33:ce:4a:97:d6:59:77:d3:98:1b:df:89:43:f9:02:d8:e2:91: + 02:21:00:83:cd:55:a0:54:f1:88:be:71:23:96:7b:4c:38:6a: + d6:14:2c:dc:e0:75:e8:51:c3:bd:bc:09:74:63:5e:3d:7b +-----BEGIN CERTIFICATE----- +MIIBDzCBtqADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMjMwOTE1MTIwMDAwWhcN +MjQwOTE1MTIwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8dXBsfkP +Y9fCuoOjxrf7zwe7xzMDYU0TD0VGjUd/Qc6Pnx+FN+7/MAA3PFOLYKo4SKhcyscM +eBL0Lspi2PdstaMhMB8wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAoG +CCqGSM49BAMCA0gAMEUCIHkFbTcK24Wlb1RoHTdQM85Kl9ZZd9OYG9+JQ/kC2OKR +AiEAg81VoFTxiL5xI5Z7TDhq1hQs3OB16FHDvbwJdGNePXs= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/v3/testdata/subExtKeyUsageClientAuth.pem b/v3/testdata/subExtKeyUsageClientAuth.pem new file mode 100644 index 000000000..4f55aa176 --- /dev/null +++ b/v3/testdata/subExtKeyUsageClientAuth.pem @@ -0,0 +1,40 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Sep 15 12:00:00 2023 GMT + Not After : Sep 15 12:00:00 2024 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:04:3b:ca:38:58:01:84:3c:49:f1:45:a8:b6:02: + 18:00:dc:f3:3d:78:2b:d0:ff:3d:16:62:07:4d:2e: + 63:e0:92:0b:45:fc:f8:90:90:ce:bf:b6:db:ba:60: + e5:d2:fb:b0:f7:d1:39:18:7a:40:a9:7d:e3:22:ac: + ef:e9:f6:70:4c + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + TLS Web Client Authentication + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:44:02:20:25:79:7b:74:45:0d:29:f9:24:f0:81:4d:03:e4: + e0:b6:01:19:31:ee:dc:81:e6:bb:2a:88:91:ae:cd:d5:8e:5a: + 02:20:03:2f:9a:da:62:e6:d4:8f:96:99:f4:ea:22:0d:23:e0: + a4:9b:eb:42:08:9f:47:ff:50:ba:e7:f1:e7:9f:15:39 +-----BEGIN CERTIFICATE----- +MIIBGTCBwaADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMjMwOTE1MTIwMDAwWhcN +MjQwOTE1MTIwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBDvKOFgB +hDxJ8UWotgIYANzzPXgr0P89FmIHTS5j4JILRfz4kJDOv7bbumDl0vuw99E5GHpA +qX3jIqzv6fZwTKMsMCowEwYDVR0lBAwwCgYIKwYBBQUHAwIwEwYDVR0gBAwwCjAI +BgZngQwBAgEwCgYIKoZIzj0EAwIDRwAwRAIgJXl7dEUNKfkk8IFNA+TgtgEZMe7c +gea7KoiRrs3VjloCIAMvmtpi5tSPlpn06iINI+Ckm+tCCJ9H/1C65/HnnxU5 +-----END CERTIFICATE----- \ No newline at end of file diff --git a/v3/testdata/subExtKeyUsageClientAuthPreBRv2.pem b/v3/testdata/subExtKeyUsageClientAuthPreBRv2.pem new file mode 100644 index 000000000..aa90d6f59 --- /dev/null +++ b/v3/testdata/subExtKeyUsageClientAuthPreBRv2.pem @@ -0,0 +1,40 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Sep 15 12:00:00 2021 GMT + Not After : Sep 15 12:00:00 2022 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:9f:35:d5:be:59:9a:3f:da:a9:43:64:45:37:85: + 6c:c2:71:2b:4f:49:21:d6:b0:b8:79:c8:54:48:d6: + 41:50:e3:3c:d6:2d:69:8a:c9:a1:95:c3:32:50:3c: + 63:d1:72:05:01:79:b7:cd:be:ea:29:d5:06:6a:31: + 5b:82:2d:e9:4b + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + TLS Web Client Authentication + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:45:02:21:00:b2:f6:57:3c:fe:4b:32:52:2d:33:44:61:50: + 4b:0e:e7:0c:62:1e:d7:25:e3:e2:68:ff:a2:fc:0b:b4:a7:fa: + 99:02:20:4a:63:d3:ea:6d:dd:eb:e4:45:71:ea:91:e2:28:9b: + 85:86:8e:3c:ce:8a:e1:4f:ac:ab:48:87:da:86:b6:f0:f2 +-----BEGIN CERTIFICATE----- +MIIBGjCBwaADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMjEwOTE1MTIwMDAwWhcN +MjIwOTE1MTIwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnzXVvlma +P9qpQ2RFN4VswnErT0kh1rC4echUSNZBUOM81i1pismhlcMyUDxj0XIFAXm3zb7q +KdUGajFbgi3pS6MsMCowEwYDVR0lBAwwCgYIKwYBBQUHAwIwEwYDVR0gBAwwCjAI +BgZngQwBAgEwCgYIKoZIzj0EAwIDSAAwRQIhALL2Vzz+SzJSLTNEYVBLDucMYh7X +JePiaP+i/Au0p/qZAiBKY9Pqbd3r5EVx6pHiKJuFho48zorhT6yrSIfahrbw8g== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/v3/testdata/subExtKeyUsageServerAuth.pem b/v3/testdata/subExtKeyUsageServerAuth.pem new file mode 100644 index 000000000..93479efef --- /dev/null +++ b/v3/testdata/subExtKeyUsageServerAuth.pem @@ -0,0 +1,38 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Sep 15 12:00:00 2023 GMT + Not After : Sep 15 12:00:00 2024 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:02:25:25:0c:0d:7d:04:c1:30:d2:e7:91:73:20: + 3c:e5:d3:eb:cb:20:44:94:fc:6c:8b:66:f5:8f:c5: + 80:81:9e:0a:f5:63:98:9c:3b:90:bc:b9:06:b2:fa: + 59:0c:3f:d6:24:b9:6b:70:cb:34:c7:c7:84:0d:90: + 24:66:07:a1:54 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + TLS Web Server Authentication + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:44:02:20:71:fe:58:b0:cd:6f:5f:25:9f:16:d0:14:0d:f8: + 6e:e7:16:a0:83:d5:ad:a1:d7:c3:2a:00:af:eb:a0:33:c1:92: + 02:20:44:c7:39:54:49:bb:2e:f7:2c:7d:06:a9:d3:26:0a:03: + 7b:68:c7:6d:93:55:5e:da:7e:38:7e:cf:fd:14:b5:1e +-----BEGIN CERTIFICATE----- +MIIBBDCBrKADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMjMwOTE1MTIwMDAwWhcN +MjQwOTE1MTIwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAiUlDA19 +BMEw0ueRcyA85dPryyBElPxsi2b1j8WAgZ4K9WOYnDuQvLkGsvpZDD/WJLlrcMs0 +x8eEDZAkZgehVKMXMBUwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZIzj0EAwID +RwAwRAIgcf5YsM1vXyWfFtAUDfhu5xagg9WtodfDKgCv66AzwZICIETHOVRJuy73 +LH0GqdMmCgN7aMdtk1Ve2n44fs/9FLUe +-----END CERTIFICATE----- \ No newline at end of file diff --git a/v3/testdata/subExtKeyUsageServerAuthAndPreCertSigCert.pem b/v3/testdata/subExtKeyUsageServerAuthAndPreCertSigCert.pem new file mode 100644 index 000000000..507427519 --- /dev/null +++ b/v3/testdata/subExtKeyUsageServerAuthAndPreCertSigCert.pem @@ -0,0 +1,38 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Sep 15 12:00:00 2023 GMT + Not After : Sep 15 12:00:00 2024 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:3d:7b:20:95:ed:81:70:b3:ac:cb:c7:df:97:11: + c3:54:ce:c8:a2:1e:41:8f:95:31:d6:cc:a0:7b:52: + 31:ca:5f:62:b3:d3:cc:23:d3:db:e2:4b:6a:20:30: + 18:60:84:e8:9d:d0:cf:f7:b5:7a:30:96:62:11:6d: + 8b:f8:41:9e:9e + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + TLS Web Server Authentication, CT Precertificate Signer + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:46:02:21:00:a6:72:ed:5b:9a:ea:ff:63:9a:2b:36:c2:f9: + e5:24:a8:2a:d8:4e:6f:b2:47:0c:8d:0c:ec:41:15:f4:5d:96: + e0:02:21:00:d0:02:c2:da:af:40:5f:cb:71:25:50:e3:2e:eb: + d9:00:50:ad:67:64:99:f2:2f:24:5c:9f:05:84:6b:df:47:7c +-----BEGIN CERTIFICATE----- +MIIBEjCBuKADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMjMwOTE1MTIwMDAwWhcN +MjQwOTE1MTIwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPXsgle2B +cLOsy8fflxHDVM7Ioh5Bj5Ux1syge1Ixyl9is9PMI9Pb4ktqIDAYYITondDP97V6 +MJZiEW2L+EGenqMjMCEwHwYDVR0lBBgwFgYIKwYBBQUHAwEGCisGAQQB1nkCBAQw +CgYIKoZIzj0EAwIDSQAwRgIhAKZy7Vua6v9jmis2wvnlJKgq2E5vskcMjQzsQRX0 +XZbgAiEA0ALC2q9AX8txJVDjLuvZAFCtZ2SZ8i8kXJ8FhGvfR3w= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/v3/testdata/subExtKeyUsageServerAuthAndTimeStamping.pem b/v3/testdata/subExtKeyUsageServerAuthAndTimeStamping.pem new file mode 100644 index 000000000..5d0ab0c19 --- /dev/null +++ b/v3/testdata/subExtKeyUsageServerAuthAndTimeStamping.pem @@ -0,0 +1,38 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Sep 15 12:00:00 2023 GMT + Not After : Sep 15 12:00:00 2024 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:74:62:e0:75:bb:1c:6b:a5:13:67:14:fd:f2:e6: + 72:15:31:e7:b3:09:89:a9:d9:33:d4:13:e9:44:90: + 71:d1:64:8d:02:d6:8a:e6:07:f8:7a:67:49:e7:92: + 90:95:ee:a8:a8:30:38:7a:fa:4c:c7:12:0a:eb:fd: + 4e:49:e0:7e:27 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + TLS Web Server Authentication, Time Stamping + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:45:02:20:62:b8:36:87:dc:aa:85:c6:f6:ae:86:04:ab:4b: + 46:58:9c:ae:84:57:bd:3f:45:94:e3:3f:9d:17:56:d1:18:5c: + 02:21:00:bc:c0:72:12:39:c7:47:07:75:7b:25:88:a4:6d:6c: + af:ce:6e:a4:32:3b:6c:58:04:cb:1a:f5:6b:85:dd:69:c7 +-----BEGIN CERTIFICATE----- +MIIBDzCBtqADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMjMwOTE1MTIwMDAwWhcN +MjQwOTE1MTIwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdGLgdbsc +a6UTZxT98uZyFTHnswmJqdkz1BPpRJBx0WSNAtaK5gf4emdJ55KQle6oqDA4evpM +xxIK6/1OSeB+J6MhMB8wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMIMAoG +CCqGSM49BAMCA0gAMEUCIGK4NofcqoXG9q6GBKtLRlicroRXvT9FlOM/nRdW0Rhc +AiEAvMByEjnHRwd1eyWIpG1sr85upDI7bFgEyxr1a4Xdacc= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/v3/testdata/subExtKeyUsageServerAuthAndUnknown.pem b/v3/testdata/subExtKeyUsageServerAuthAndUnknown.pem new file mode 100644 index 000000000..e3ab89086 --- /dev/null +++ b/v3/testdata/subExtKeyUsageServerAuthAndUnknown.pem @@ -0,0 +1,38 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Sep 15 12:00:00 2023 GMT + Not After : Sep 15 12:00:00 2024 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:dc:6a:77:08:a6:fb:8d:f4:ef:32:79:42:ed:26: + 85:93:77:a8:55:43:4e:83:24:21:08:08:d6:a3:c5: + a2:3d:dc:99:4f:5f:d1:24:57:3a:b9:ca:38:5f:0e: + 19:06:14:15:ae:e7:b2:9f:11:a1:1e:f3:30:65:ae: + ad:de:25:0d:20 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + TLS Web Server Authentication, 1.2.3.4.5.6.7.8.9 + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:44:02:20:53:6f:cb:e7:46:a0:d3:b4:1b:d5:4e:26:33:d1: + 8d:05:c0:6b:a9:e2:f2:f2:49:e9:2f:a0:b2:94:d6:27:83:ef: + 02:20:57:20:c7:04:ef:32:b1:38:86:4e:d2:94:ff:f2:11:14: + 2e:dd:33:6c:da:3a:a0:c7:56:93:d8:73:9d:1b:9c:f3 +-----BEGIN CERTIFICATE----- +MIIBDjCBtqADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMjMwOTE1MTIwMDAwWhcN +MjQwOTE1MTIwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3Gp3CKb7 +jfTvMnlC7SaFk3eoVUNOgyQhCAjWo8WiPdyZT1/RJFc6uco4Xw4ZBhQVrueynxGh +HvMwZa6t3iUNIKMhMB8wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCoDBAUGBwgJMAoG +CCqGSM49BAMCA0cAMEQCIFNvy+dGoNO0G9VOJjPRjQXAa6ni8vJJ6S+gspTWJ4Pv +AiBXIMcE7zKxOIZO0pT/8hEULt0zbNo6oMdWk9hznRuc8w== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/v3/util/ca.go b/v3/util/ca.go index c5cac2a54..2a7318735 100644 --- a/v3/util/ca.go +++ b/v3/util/ca.go @@ -60,6 +60,12 @@ func IsServerAuthCert(cert *x509.Certificate) bool { return true } } + for _, policy := range cert.PolicyIdentifiers { + if policy.Equal(BRDomainValidatedOID) || policy.Equal(BROrganizationValidatedOID) || + policy.Equal(BRIndividualValidatedOID) || policy.Equal(BRExtendedValidatedOID) { + return true + } + } return false } diff --git a/v3/util/oid.go b/v3/util/oid.go index 5ded05d68..0abb384a8 100644 --- a/v3/util/oid.go +++ b/v3/util/oid.go @@ -53,10 +53,13 @@ var ( SubjectInfoAccessOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 11} // Subject Info Access Syntax SubjectKeyIdentityOID = asn1.ObjectIdentifier{2, 5, 29, 14} // Subject Key Identifier ReasonCodeOID = asn1.ObjectIdentifier{2, 5, 29, 21} // CRL Reason Code - // CA/B reserved policies - BRDomainValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1} // CA/B BR Domain-Validated - BROrganizationValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 2, 2} // CA/B BR Organization-Validated - BRIndividualValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 2, 3} // CA/B BR Individual-Validated + // Extended Key Usage OIDs + PreCertificateSigningCertificateEKU = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 4} + // CA/B Reserved Certificate Policy Identifiers + BRExtendedValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 1} // CA/B BR Reserved Certificate Policy Identifiers - Extended Validation + BRDomainValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1} // CA/B BR Reserved Certificate Policy Identifiers - Domain-Validated + BROrganizationValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 2, 2} // CA/B BR Reserved Certificate Policy Identifiers - Organization-Validated + BRIndividualValidatedOID = asn1.ObjectIdentifier{2, 23, 140, 1, 2, 3} // CA/B BR Reserved Certificate Policy Identifiers - Individual-Validated BRTorServiceDescriptor = asn1.ObjectIdentifier{2, 23, 140, 1, 31} // CA/B BR Tor Service Descriptor CabfExtensionOrganizationIdentifier = asn1.ObjectIdentifier{2, 23, 140, 3, 1} // CA/B EV 9.8.2 cabfOrganizationIdentifier SMIMEBRMailboxValidatedLegacyOID = asn1.ObjectIdentifier{2, 23, 140, 1, 5, 1, 1} // CA/B SMIME BR Mailbox Validated, Legacy