Skip to content

Commit

Permalink
fix: Fix PSD2 based cabfOrganizationIdentifier check (#880)
Browse files Browse the repository at this point in the history
* fix: Fix PSD2 based cabfOrganizationIdentifier check

* fix: Fix PSD2 based cabfOrganizationIdentifier check

* code refactor

* fix lints

---------

Co-authored-by: Christopher Henderson <chris@chenderson.org>
  • Loading branch information
XolphinMartijn and christopher-henderson authored Sep 22, 2024
1 parent 372cdc6 commit 77a6468
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 29 deletions.
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-----

0 comments on commit 77a6468

Please sign in to comment.