Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lint for EV Guidelines section 9.7.3 #815

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions v3/lints/cabf_ev/lint_ev_certificate_policies.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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.
*/

package cabf_ev

import (
"fmt"
"net/url"
"time"

"github.com/zmap/zcrypto/x509"

"github.com/zmap/zlint/v3/lint"
"github.com/zmap/zlint/v3/util"
)

func init() {
lint.RegisterCertificateLint(&lint.CertificateLint{
LintMetadata: lint.LintMetadata{
Name: "e_ev_certificate_policies",
Description: "EV Certificates issued to Subscribers MUST include a CPS URI policy qualifier",
Citation: "CA/Browser Forum EV Guidelines v1.8.1, Sec. 9.7.3",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Source: lint.CABFEVGuidelines,
EffectiveDate: util.CABFEV_1_2,
},
Lint: NewEvTechnicalRequirements,
})
}

type EvCertificatePolicies struct{}

func NewEvTechnicalRequirements() lint.LintInterface {
return &EvCertificatePolicies{}
}

func (l *EvCertificatePolicies) CheckApplies(c *x509.Certificate) bool {
return c.ValidationLevel == x509.EV
}

func (l *EvCertificatePolicies) Execute(c *x509.Certificate) *lint.LintResult {
for _, uris := range c.CPSuri {
if uris != nil {
// Policy i is the CPS URI.
// c.CPSuri[i] is populated only if the policyQualifierID is the correct { id-qt 1 }
if len(uris) != 1 {
return &lint.LintResult{Status: lint.Error}
}
uri := uris[0]

// The CPS URI is a "HTTP URL for the Root CA’s Certification Practice Statement"
cps, err := url.Parse(uri)
if err != nil {
return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("Error parsing CPS URI: %v", err)}
}
if cps.Scheme != "http" && cps.Scheme != "https" {
return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("CPS URI scheme not http(s): %s", cps.Scheme)}
}

if !util.HasValidTLD(cps.Hostname(), time.Now()) {
return &lint.LintResult{Status: lint.Error}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably fill the details here too

}

return &lint.LintResult{Status: lint.Pass}
}
}

return &lint.LintResult{Status: lint.Error}
}
50 changes: 50 additions & 0 deletions v3/lints/cabf_ev/lint_ev_certificate_policies_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.
*/

package cabf_ev

import (
"testing"

"github.com/zmap/zlint/v3/lint"
"github.com/zmap/zlint/v3/test"
)

func TestEvCertificatePolicies(t *testing.T) {
tests := []struct {
inputPath string
expected lint.LintStatus
}{
{
inputPath: "evAllGood.pem",
expected: lint.Pass,
},
{
inputPath: "evNoCPSURI.pem",
expected: lint.Error,
},
{
inputPath: "dnsNameValidTLD.pem",
expected: lint.NA,
},
}
for _, tt := range tests {
t.Run(tt.inputPath, func(t *testing.T) {
out := test.TestLint("e_ev_certificate_policies", tt.inputPath)
if out.Status != tt.expected {
t.Errorf("%s: expected %s, got %s", tt.inputPath, tt.expected, out.Status)
}
})
}
}
167 changes: 167 additions & 0 deletions v3/testdata/evNoCPSURI.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
32:2f:2e:ee:d4:19:ab:b5:f6:f9:ce:92:08:c2:e3:90
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2014 Entrust, Inc. - for authorized use only", CN = Entrust Certification Authority - L1M
Validity
Not Before: Feb 8 22:19:05 2024 GMT
Not After : Feb 8 22:19:04 2025 GMT
Subject: C = US, ST = Minnesota, L = Shakopee, jurisdictionC = US, jurisdictionST = Delaware, O = Entrust Corporation, businessCategory = Private Organization, serialNumber = 705421, CN = entrust.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:dd:8d:51:bb:e1:d9:b2:dd:50:41:8a:7f:33:2c:
0f:37:f0:68:c6:3b:ec:47:12:7e:97:35:4a:8a:03:
20:a2:69:ca:d4:5f:ff:07:51:6d:13:ec:73:24:e7:
56:19:26:fd:d9:3f:82:78:87:28:61:03:e3:da:c7:
1e:38:50:8b:d2:11:f4:66:e8:ea:79:c0:32:24:74:
39:b8:1b:42:aa:24:e4:71:e4:9f:78:38:5a:c7:8e:
f3:bc:b4:c8:2d:a4:86:97:75:65:3e:04:28:28:87:
d4:57:f6:ac:8a:86:41:e3:5a:5a:28:b1:8c:d2:8a:
3d:d6:a6:97:61:7e:00:4a:95:4d:a6:1b:31:12:94:
51:05:9b:8c:b5:4a:fb:2e:95:a2:b9:f6:56:9e:44:
8e:d0:55:60:f8:fd:ac:70:49:86:5b:19:0f:04:c2:
06:32:0d:5a:e1:6c:b8:d0:e6:7a:2f:0d:a5:60:12:
d4:32:e0:5b:03:29:b7:2e:96:aa:f7:e1:cd:f3:10:
7d:8c:a7:85:be:ca:9e:6c:13:9c:77:7c:17:02:43:
bd:37:40:68:9f:27:b9:a5:ba:b4:1a:51:bf:8e:53:
49:c5:29:b4:7b:e3:13:d2:73:ce:37:74:3a:80:68:
86:73:28:c6:df:05:7a:91:be:ee:ba:e0:58:7a:f3:
91:21
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
80:23:9A:50:45:09:5B:3C:2D:00:98:1C:50:EF:E0:79:4B:9A:C9:7A
X509v3 Authority Key Identifier:
C3:F7:D0:B5:2A:30:AD:AF:0D:91:21:70:39:54:DD:BC:89:70:C7:3A
Authority Information Access:
OCSP - URI:http://ocsp.entrust.net
CA Issuers - URI:http://aia.entrust.net/l1m-chain256.cer
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.entrust.net/level1m.crl
X509v3 Subject Alternative Name:
DNS:entrust.com, DNS:www.entrust.com, DNS:www.sumaidmzprx.entrust.com, DNS:www.kiteworks.entrust.com, DNS:www.drupal.entrust.com, DNS:web.entrust.com, DNS:w2.entrust.com, DNS:translate.entrust.com, DNS:testtranslate.entrust.com, DNS:testonline.entrust.com, DNS:test.entrust.com, DNS:sumaidmzprx.entrust.com, DNS:plm.entrust.com, DNS:outlook.entrust.com, DNS:new.entrust.com, DNS:mail.entrust.com, DNS:licensing.entrust.com, DNS:kiteworks.entrust.com, DNS:in.entrust.com, DNS:firmwarestg.entrust.com, DNS:firmwaredev.entrust.com, DNS:firmware.entrust.com, DNS:drupalw.entrust.com, DNS:drupalstgw.entrust.com, DNS:drupalstg.entrust.com, DNS:drupaldevw.entrust.com, DNS:drupaldev.entrust.com, DNS:drupal.entrust.com, DNS:china-proxy.entrust.com, DNS:china-proxy-test.entrust.com, DNS:autodiscover.entrust.com, DNS:adp.entrust.com, DNS:activation.licensing.entrust.com, DNS:wd.entrust.com, DNS:fd.entrust.com, DNS:ws.entrust.com, DNS:fs.entrust.com, DNS:wdw.entrust.com, DNS:wsw.entrust.com, DNS:plmtest.entrust.com
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Certificate Policies:
Policy: 2.23.140.1.1
Policy: 2.16.840.1.114028.10.1.2
CT Precertificate SCTs:
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : E6:D2:31:63:40:77:8C:C1:10:41:06:D7:71:B9:CE:C1:
D2:40:F6:96:84:86:FB:BA:87:32:1D:FD:1E:37:8E:50
Timestamp : Feb 8 22:19:05.976 2024 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:45:02:20:09:32:16:2C:C2:4A:7E:82:17:FF:FA:71:
7D:BF:6A:CF:40:84:E6:1A:78:F4:54:D9:72:86:5F:96:
CC:54:61:D4:02:21:00:F2:A5:81:FB:A7:AF:A4:5A:B7:
9C:F0:57:E4:A1:6E:CE:EE:19:86:B0:3F:C5:07:85:3C:
41:80:6B:99:35:76:4D
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : A2:E3:0A:E4:45:EF:BD:AD:9B:7E:38:ED:47:67:77:53:
D7:82:5B:84:94:D7:2B:5E:1B:2C:C4:B9:50:A4:47:E7
Timestamp : Feb 8 22:19:06.005 2024 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:44:02:20:3F:EC:E9:63:68:1D:0E:03:CA:54:64:2C:
AF:C8:D4:D6:7B:02:02:64:C5:81:48:BF:83:0F:08:A3:
D9:06:B8:D4:02:20:31:20:52:17:E5:B6:13:66:39:79:
1F:B0:C1:CE:A4:F2:FA:EB:CB:CD:2B:53:75:78:1C:77:
92:A6:3B:CD:E5:FE
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : 4E:75:A3:27:5C:9A:10:C3:38:5B:6C:D4:DF:3F:52:EB:
1D:F0:E0:8E:1B:8D:69:C0:B1:FA:64:B1:62:9A:39:DF
Timestamp : Feb 8 22:19:05.990 2024 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:45:02:20:18:59:3B:1E:78:40:18:53:84:07:E0:71:
25:2E:6F:C1:45:32:29:DC:73:03:E1:ED:F3:23:28:7F:
E6:5C:BD:E6:02:21:00:9B:9A:0F:5C:67:25:69:F6:A4:
3E:AD:FB:82:BD:16:E4:77:A9:1E:01:4A:96:14:3D:DF:
94:0D:5B:B7:87:11:44
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
2b:73:4c:31:7f:80:54:56:85:ed:2b:f6:05:ad:70:0d:3a:6d:
fe:e8:b6:46:d9:ee:fc:02:8f:4c:64:fb:cc:f9:0c:b6:74:41:
e3:b8:ca:72:c8:2d:5b:56:d8:eb:85:1a:09:36:6d:92:79:ce:
3a:03:d3:ec:12:e6:89:f5:44:d6:ab:9d:bd:90:d6:d1:c7:5c:
83:d4:1e:7b:47:97:99:09:5e:8e:57:35:99:fb:6a:dd:05:9c:
e6:39:a4:7c:a3:6f:ea:5f:a7:31:bf:90:09:33:26:6b:49:d5:
5d:a6:e9:f6:9a:bb:85:29:b0:df:7e:be:1d:6f:6a:ba:b0:c8:
94:ae:fe:da:93:59:4a:6c:d8:fb:e8:da:8b:17:b0:09:49:ce:
a4:25:61:f2:67:05:d0:6d:00:56:cf:d1:33:0f:28:a1:79:10:
db:17:56:d6:cb:9e:b4:28:8b:cf:c1:eb:c7:e7:ee:9b:a8:e7:
08:2e:d8:6b:87:80:d9:22:2b:72:58:91:8e:c8:5b:38:4b:0d:
05:98:9d:4e:9b:69:f0:b1:fe:3c:57:4d:2c:d2:e1:da:b2:53:
b5:fc:5c:d0:06:df:9b:9e:10:71:c0:21:a1:6d:cf:e5:71:53:
c0:cc:b8:82:1f:de:46:d3:18:cb:c4:9c:e6:97:d8:e6:81:7c:
50:d4:d6:13
-----BEGIN CERTIFICATE-----
MIIKOTCCCSGgAwIBAgIQMi8u7tQZq7X2+c6SCMLjkDANBgkqhkiG9w0BAQsFADCB
ujELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsT
H1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAy
MDE0IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEuMCwG
A1UEAxMlRW50cnVzdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEwxTTAeFw0y
NDAyMDgyMjE5MDVaFw0yNTAyMDgyMjE5MDRaMIHIMQswCQYDVQQGEwJVUzESMBAG
A1UECBMJTWlubmVzb3RhMREwDwYDVQQHEwhTaGFrb3BlZTETMBEGCysGAQQBgjc8
AgEDEwJVUzEZMBcGCysGAQQBgjc8AgECEwhEZWxhd2FyZTEcMBoGA1UEChMTRW50
cnVzdCBDb3Jwb3JhdGlvbjEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24x
DzANBgNVBAUTBjcwNTQyMTEUMBIGA1UEAxMLZW50cnVzdC5jb20wggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdjVG74dmy3VBBin8zLA838GjGO+xHEn6X
NUqKAyCiacrUX/8HUW0T7HMk51YZJv3ZP4J4hyhhA+Paxx44UIvSEfRm6Op5wDIk
dDm4G0KqJORx5J94OFrHjvO8tMgtpIaXdWU+BCgoh9RX9qyKhkHjWloosYzSij3W
ppdhfgBKlU2mGzESlFEFm4y1SvsulaK59laeRI7QVWD4/axwSYZbGQ8EwgYyDVrh
bLjQ5novDaVgEtQy4FsDKbculqr34c3zEH2Mp4W+yp5sE5x3fBcCQ703QGifJ7ml
urQaUb+OU0nFKbR74xPSc843dDqAaIZzKMbfBXqRvu664Fh685EhAgMBAAGjggYp
MIIGJTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSAI5pQRQlbPC0AmBxQ7+B5S5rJ
ejAfBgNVHSMEGDAWgBTD99C1KjCtrw2RIXA5VN28iXDHOjBoBggrBgEFBQcBAQRc
MFowIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmVudHJ1c3QubmV0MDMGCCsGAQUF
BzAChidodHRwOi8vYWlhLmVudHJ1c3QubmV0L2wxbS1jaGFpbjI1Ni5jZXIwMwYD
VR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9sZXZlbDFtLmNy
bDCCA2IGA1UdEQSCA1kwggNVggtlbnRydXN0LmNvbYIPd3d3LmVudHJ1c3QuY29t
ght3d3cuc3VtYWlkbXpwcnguZW50cnVzdC5jb22CGXd3dy5raXRld29ya3MuZW50
cnVzdC5jb22CFnd3dy5kcnVwYWwuZW50cnVzdC5jb22CD3dlYi5lbnRydXN0LmNv
bYIOdzIuZW50cnVzdC5jb22CFXRyYW5zbGF0ZS5lbnRydXN0LmNvbYIZdGVzdHRy
YW5zbGF0ZS5lbnRydXN0LmNvbYIWdGVzdG9ubGluZS5lbnRydXN0LmNvbYIQdGVz
dC5lbnRydXN0LmNvbYIXc3VtYWlkbXpwcnguZW50cnVzdC5jb22CD3BsbS5lbnRy
dXN0LmNvbYITb3V0bG9vay5lbnRydXN0LmNvbYIPbmV3LmVudHJ1c3QuY29tghBt
YWlsLmVudHJ1c3QuY29tghVsaWNlbnNpbmcuZW50cnVzdC5jb22CFWtpdGV3b3Jr
cy5lbnRydXN0LmNvbYIOaW4uZW50cnVzdC5jb22CF2Zpcm13YXJlc3RnLmVudHJ1
c3QuY29tghdmaXJtd2FyZWRldi5lbnRydXN0LmNvbYIUZmlybXdhcmUuZW50cnVz
dC5jb22CE2RydXBhbHcuZW50cnVzdC5jb22CFmRydXBhbHN0Z3cuZW50cnVzdC5j
b22CFWRydXBhbHN0Zy5lbnRydXN0LmNvbYIWZHJ1cGFsZGV2dy5lbnRydXN0LmNv
bYIVZHJ1cGFsZGV2LmVudHJ1c3QuY29tghJkcnVwYWwuZW50cnVzdC5jb22CF2No
aW5hLXByb3h5LmVudHJ1c3QuY29tghxjaGluYS1wcm94eS10ZXN0LmVudHJ1c3Qu
Y29tghhhdXRvZGlzY292ZXIuZW50cnVzdC5jb22CD2FkcC5lbnRydXN0LmNvbYIg
YWN0aXZhdGlvbi5saWNlbnNpbmcuZW50cnVzdC5jb22CDndkLmVudHJ1c3QuY29t
gg5mZC5lbnRydXN0LmNvbYIOd3MuZW50cnVzdC5jb22CDmZzLmVudHJ1c3QuY29t
gg93ZHcuZW50cnVzdC5jb22CD3dzdy5lbnRydXN0LmNvbYITcGxtdGVzdC5lbnRy
dXN0LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMCAGA1UdIAQZMBcwBwYFZ4EMAQEwDAYKYIZIAYb6bAoBAjCCAX0GCisG
AQQB1nkCBAIEggFtBIIBaQFnAHYA5tIxY0B3jMEQQQbXcbnOwdJA9paEhvu6hzId
/R43jlAAAAGNis2XeAAABAMARzBFAiAJMhYswkp+ghf/+nF9v2rPQITmGnj0VNly
hl+WzFRh1AIhAPKlgfunr6Rat5zwV+Shbs7uGYawP8UHhTxBgGuZNXZNAHUAouMK
5EXvva2bfjjtR2d3U9eCW4SU1yteGyzEuVCkR+cAAAGNis2XlQAABAMARjBEAiA/
7OljaB0OA8pUZCyvyNTWewICZMWBSL+DDwij2Qa41AIgMSBSF+W2E2Y5eR+wwc6k
8vrry80rU3V4HHeSpjvN5f4AdgBOdaMnXJoQwzhbbNTfP1LrHfDgjhuNacCx+mSx
Ypo53wAAAY2KzZeGAAAEAwBHMEUCIBhZOx54QBhThAfgcSUub8FFMinccwPh7fMj
KH/mXL3mAiEAm5oPXGclafakPq37gr0W5HepHgFKlhQ935QNW7eHEUQwDQYJKoZI
hvcNAQELBQADggEBACtzTDF/gFRWhe0r9gWtcA06bf7otkbZ7vwCj0xk+8z5DLZ0
QeO4ynLILVtW2OuFGgk2bZJ5zjoD0+wS5on1RNarnb2Q1tHHXIPUHntHl5kJXo5X
NZn7at0FnOY5pHyjb+pfpzG/kAkzJmtJ1V2m6faau4UpsN9+vh1varqwyJSu/tqT
WUps2Pvo2osXsAlJzqQlYfJnBdBtAFbP0TMPKKF5ENsXVtbLnrQoi8/B68fn7puo
5wgu2GuHgNkiK3JYkY7IWzhLDQWYnU6bafCx/jxXTSzS4dqyU7X8XNAG35ueEHHA
IaFtz+VxU8DMuIIf3kbTGMvEnOaX2OaBfFDU1hM=
-----END CERTIFICATE-----
1 change: 1 addition & 0 deletions v3/util/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ var (
)

var (
CABFEV_1_2 = time.Date(2008, time.April, 10, 0, 0, 0, 0, time.UTC)
CABFEV_9_8_2 = CABV170Date
)

Expand Down
Loading