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

fix: Fix PSD2 based cabfOrganizationIdentifier check #880

Merged
merged 5 commits into from
Sep 22, 2024
Merged
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
6 changes: 6 additions & 0 deletions v3/cmd/genTestCerts/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
Expand All @@ -65,6 +66,7 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand All @@ -85,6 +87,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
Expand All @@ -93,6 +97,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
Expand Down
83 changes: 54 additions & 29 deletions v3/lints/cabf_ev/lint_ev_orgid_inconsistent_subj_and_ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
package cabf_ev

import (
"fmt"

"github.com/zmap/zcrypto/x509"
"github.com/zmap/zlint/v3/lint"
"github.com/zmap/zlint/v3/util"

"errors"
"regexp"
)

Expand All @@ -43,42 +44,46 @@ func init() {

// According to EVGs 9.2.8
type OrganizationIdentifier struct {
Scheme string
Country string
State string
Reference string
ParseAsPSD bool
Scheme string
Country string
State string
Reference string
}

// This is according to the EVG (stricter than ETSI EN 319 412-1)
var OrgIdPattern = `^(?P<scheme>[A-Z]{3})(?P<country>[A-Z]{2})(?:\+(?P<state>[A-Z]{2}))?\-(?P<reference>.+)$`

func ParseOrgId(orgIdString string, orgId *OrganizationIdentifier) error {

re := regexp.MustCompile(OrgIdPattern)

if !re.MatchString(orgIdString) {
return errors.New("Cannot parse organizationIdentifier: it is probably invalid")
func (o OrganizationIdentifier) Parse(orgId string) (OrganizationIdentifier, error) {
re := o.regexForOrgID()
if !re.MatchString(orgId) {
return o, fmt.Errorf("Cannot parse organizationIdentifier ('%s'): it is probably invalid", orgId)
}

names := re.SubexpNames()
match := re.FindStringSubmatch(orgIdString)

match := re.FindStringSubmatch(orgId)
// Initialize a map to hold group names and values
result := make(map[string]string)

// Populate the map
for i, name := range names {
if i != 0 && name != "" { // Skip the whole match and unnamed groups
result[name] = match[i]
}
}
o.Scheme = result["scheme"]
o.Country = result["country"]
o.State = result["state"]
o.Reference = result["reference"]
return o, nil
}

orgId.Scheme = result["scheme"]
orgId.Country = result["country"]
orgId.State = result["state"]
orgId.Reference = result["reference"]

return nil
func (o OrganizationIdentifier) regexForOrgID() *regexp.Regexp {
// This is according to the EVG (stricter than ETSI EN 319 412-1)
const OrgIdPattern = `^(?P<scheme>[A-Z]{3})(?P<country>[A-Z]{2})(?:\+(?P<state>[A-Z]{2}))?\-(?P<reference>.+)$`
const PsdOrgIdPattern = `^(?P<scheme>[A-Z]{3})(?P<country>[A-Z]{2})(?:\+(?P<state>[A-Z]{2}))?\-(?P<nca>[A-Z]*)\-(?P<reference>.+)$`
var pattern string
if o.ParseAsPSD {
pattern = PsdOrgIdPattern
} else {
pattern = OrgIdPattern
}
return regexp.MustCompile(pattern)
}

type orgIdInconsistentSubjAndExt struct{}
Expand All @@ -96,8 +101,7 @@ func (l *orgIdInconsistentSubjAndExt) CheckApplies(c *x509.Certificate) bool {

func (l *orgIdInconsistentSubjAndExt) Execute(c *x509.Certificate) *lint.LintResult {
// It should be safe to assume there is only one element in OrganizationIDs
var orgId OrganizationIdentifier
err := ParseOrgId(c.Subject.OrganizationIDs[0], &orgId)
orgId, err := OrganizationIdentifier{ParseAsPSD: false}.Parse(c.Subject.OrganizationIDs[0])
if err != nil {
return &lint.LintResult{
Status: lint.Error,
Expand All @@ -109,9 +113,30 @@ func (l *orgIdInconsistentSubjAndExt) Execute(c *x509.Certificate) *lint.LintRes
(c.CABFOrganizationIdentifier.State != orgId.State) ||
(c.CABFOrganizationIdentifier.Reference != orgId.Reference) {

return &lint.LintResult{
Status: lint.Error,
Details: "CABFOrganizationIdentifier is NOT consistent with organizationIdentifier"}
if orgId.Scheme != "PSD" {

return &lint.LintResult{
Status: lint.Error,
Details: "CABFOrganizationIdentifier is NOT consistent with organizationIdentifier"}
}

psdOrgId, err := OrganizationIdentifier{ParseAsPSD: true}.Parse(c.Subject.OrganizationIDs[0])
if err != nil {
return &lint.LintResult{
Status: lint.Error,
Details: "the organizationIdentifier Subject attribute probably has an invalid value"}
}

if (c.CABFOrganizationIdentifier.Scheme != psdOrgId.Scheme) ||
(c.CABFOrganizationIdentifier.Country != psdOrgId.Country) ||
(c.CABFOrganizationIdentifier.State != psdOrgId.State) ||
(c.CABFOrganizationIdentifier.Reference != psdOrgId.Reference) {

return &lint.LintResult{
Status: lint.Error,
Details: "CABFOrganizationIdentifier is NOT consistent with organizationIdentifier"}
}

}

return &lint.LintResult{Status: lint.Pass}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ func TestOrgIdInconsistentSubjAndExt(t *testing.T) {
input: "orgid_subj_and_ext_ok_05.pem",
want: lint.NA,
},
{
input: "orgid_subj_and_ext_ok_06.pem",
want: lint.Pass,
},
{
input: "orgid_subj_and_ext_ko_01.pem",
want: lint.Error,
Expand Down
84 changes: 84 additions & 0 deletions v3/testdata/orgid_subj_and_ext_ok_06.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1726042924 (0x66e1532c)
Signature Algorithm: sha256WithRSAEncryption
Issuer: organizationIdentifier=PSDIT-BI-1234, CN=example.com
Validity
Not Before: Sep 11 08:22:03 2024 GMT
Not After : Sep 11 08:22:03 2025 GMT
Subject: organizationIdentifier=PSDIT-BI-1234, CN=example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:a4:73:99:8a:7c:9a:49:9b:91:5b:dd:d3:34:22:
a9:04:97:29:41:6f:d1:dd:34:30:28:d1:8c:8a:5a:
4d:48:cd:27:63:38:53:85:77:cf:82:6b:4b:b4:cb:
32:53:04:20:ae:98:7d:51:05:cd:fe:80:f4:ed:df:
7d:c9:89:ed:70:bd:7c:a1:d7:b9:75:d9:5f:06:05:
6a:18:f3:80:17:d6:b6:d6:ea:71:10:db:e7:68:d3:
57:94:1f:79:0e:f4:72:99:66:ef:a8:e2:63:67:4b:
f0:1d:98:75:4c:62:7b:6a:18:5e:4e:60:d4:cc:19:
93:26:0e:a1:de:d7:47:84:36:10:99:ac:9a:4f:23:
03:67:5e:34:ff:d5:f2:7b:df:39:e7:26:71:bd:8d:
13:da:72:b2:76:65:a3:d0:7e:ab:8d:e6:e3:bd:cc:
56:59:0b:17:e0:41:fb:a5:10:01:23:1e:c8:24:9e:
7c:29:15:40:cd:6e:54:3b:54:99:8c:51:49:77:82:
13:ee:63:b7:90:76:3e:9c:1d:4d:b7:13:dd:b5:f8:
1f:62:bb:d4:cd:32:a2:61:fd:11:1f:4d:75:97:22:
3a:76:cf:e0:65:0d:39:40:8e:7a:7c:48:6c:42:f0:
7b:f9:fd:e0:82:df:53:d4:53:40:87:81:a0:c0:df:
ca:99
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Certificate Policies:
Policy: 2.23.140.1.1
X509v3 Subject Key Identifier:
55:E4:74:FC:B6:EF:25:AB:4E:B9:C8:7E:EB:3C:9F:8B:A8:00:9C:1B
2.23.140.3.1:
0...PSD..IT..1234
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
11:34:72:b8:bb:52:71:78:11:93:ef:a4:09:c5:1a:17:18:32:
6d:34:e6:e6:58:be:42:65:bd:2e:1e:2e:c2:c7:bc:ab:21:a1:
12:88:d3:85:80:9d:5e:0a:77:c4:67:b8:fc:09:54:c0:4d:e0:
cb:6d:d8:80:9b:6f:f8:26:92:96:7c:55:ba:a4:85:66:f1:d1:
8f:ae:59:e0:8e:53:90:06:f1:ff:4a:66:a0:18:ee:da:84:ec:
3d:9c:7a:14:8f:65:c6:ae:84:02:b9:81:ba:75:0e:3e:47:f1:
8f:2e:06:cb:be:2b:97:2a:02:19:05:89:6c:d7:8c:f5:b2:96:
be:7d:62:14:8c:fa:34:37:9b:55:5d:ba:f9:a3:78:a5:c7:5f:
85:bb:c9:30:bf:d7:d2:72:16:a4:0f:10:a4:c9:37:66:9a:60:
a1:1d:23:5c:e5:cc:10:66:1f:55:56:82:86:1a:f4:ae:33:53:
c0:02:51:c5:23:0e:21:e3:d3:1c:6f:2a:73:fe:14:47:77:11:
e9:c2:f5:05:b6:ea:69:e6:9c:b7:a9:0d:7d:e7:e5:5f:9c:45:
12:de:1b:a8:6e:80:5f:33:c9:68:85:8e:d9:04:8f:36:87:f2:
fc:73:f6:0d:a4:67:85:05:7c:1d:df:ec:cd:cd:54:47:9d:e7:
7a:d2:30:41
-----BEGIN CERTIFICATE-----
MIIDajCCAlKgAwIBAgIEZuFTLDANBgkqhkiG9w0BAQsFADAuMRYwFAYDVQRhDA1Q
U0RJVC1CSS0xMjM0MRQwEgYDVQQDDAtleGFtcGxlLmNvbTAeFw0yNDA5MTEwODIy
MDNaFw0yNTA5MTEwODIyMDNaMC4xFjAUBgNVBGEMDVBTRElULUJJLTEyMzQxFDAS
BgNVBAMMC2V4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEApHOZinyaSZuRW93TNCKpBJcpQW/R3TQwKNGMilpNSM0nYzhThXfPgmtLtMsy
UwQgrph9UQXN/oD07d99yYntcL18ode5ddlfBgVqGPOAF9a21upxENvnaNNXlB95
DvRymWbvqOJjZ0vwHZh1TGJ7ahheTmDUzBmTJg6h3tdHhDYQmayaTyMDZ140/9Xy
e9855yZxvY0T2nKydmWj0H6rjebjvcxWWQsX4EH7pRABIx7IJJ58KRVAzW5UO1SZ
jFFJd4IT7mO3kHY+nB1NtxPdtfgfYrvUzTKiYf0RH011lyI6ds/gZQ05QI56fEhs
QvB7+f3ggt9T1FNAh4GgwN/KmQIDAQABo4GPMIGMMAwGA1UdEwEB/wQCMAAwDgYD
VR0PAQH/BAQDAgWgMBIGA1UdIAQLMAkwBwYFZ4EMAQEwHQYDVR0OBBYEFFXkdPy2
7yWrTrnIfus8n4uoAJwbMBoGBWeBDAMBBBEwDxMDUFNEEwJJVAwEMTIzNDAdBgNV
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABE0
cri7UnF4EZPvpAnFGhcYMm005uZYvkJlvS4eLsLHvKshoRKI04WAnV4Kd8RnuPwJ
VMBN4Mtt2ICbb/gmkpZ8VbqkhWbx0Y+uWeCOU5AG8f9KZqAY7tqE7D2cehSPZcau
hAK5gbp1Dj5H8Y8uBsu+K5cqAhkFiWzXjPWylr59YhSM+jQ3m1VduvmjeKXHX4W7
yTC/19JyFqQPEKTJN2aaYKEdI1zlzBBmH1VWgoYa9K4zU8ACUcUjDiHj0xxvKnP+
FEd3EenC9QW26mnmnLepDX3n5V+cRRLeG6hugF8zyWiFjtkEjzaH8vxz9g2kZ4UF
fB3f7M3NVEed53rSMEE=
-----END CERTIFICATE-----
Loading