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

CABF SMIME BR 7.1.2.3.m - Adobe Extensions #763

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* ZLint Copyright 2023 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_smime_br

import (
"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_adobe_extensions_legacy_multipurpose_criticality",
Description: "If present, Adobe Time‐stamp X509 extension (1.2.840.113583.1.1.9.1) or the Adobe ArchiveRevInfo extension (1.2.840.113583.1.1.9.2) SHALL NOT be marked as critical for multipurpose/legacy SMIME certificates",
Citation: "7.1.2.3.m",
Source: lint.CABFSMIMEBaselineRequirements,
EffectiveDate: util.CABF_SMIME_BRs_1_0_0_Date,
},
Lint: NewAdobeExtensionsLegacyMultipurposeCriticality,
})
}

type adobeExtensionsLegacyMultipurposeCriticality struct{}

// NewAdobeExtensionsLegacyMultipurposeCriticality creates a new linter to enforce adobe x509 extensions requirements for multipurpose or legacy SMIME certs
func NewAdobeExtensionsLegacyMultipurposeCriticality() lint.CertificateLintInterface {
return &adobeExtensionsLegacyMultipurposeCriticality{}
}

// CheckApplies returns true if for any subscriber certificate the certificate's policies assert that it conforms to the multipurpose or legacy policy requirements defined in the SMIME BRs
// and the certificate contains one of the adobe x509 extensions
func (l *adobeExtensionsLegacyMultipurposeCriticality) CheckApplies(c *x509.Certificate) bool {
return util.IsSubscriberCert(c) && (util.IsLegacySMIMECertificate(c) || util.IsMultipurposeSMIMECertificate(c)) && hasAdobeX509Extensions(c)
}

// Execute applies the requirements of adobe x509 extensions not being marked as critical, if present, for multipurpose or legacy SMIME certificates
func (l *adobeExtensionsLegacyMultipurposeCriticality) Execute(c *x509.Certificate) *lint.LintResult {
adobeTimeStampExt := util.GetExtFromCert(c, util.AdobeTimeStampOID)
if adobeTimeStampExt != nil && adobeTimeStampExt.Critical {
return &lint.LintResult{Status: lint.Error}
}

adobeArchRevInfoExt := util.GetExtFromCert(c, util.AdobeArchiveRevInfoOID)
if adobeArchRevInfoExt != nil && adobeArchRevInfoExt.Critical {
return &lint.LintResult{Status: lint.Error}
}

return &lint.LintResult{Status: lint.Pass}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cabf_smime_br

import (
"testing"

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

func TestAdobeExtensionsLegacyMultipurposeCriticality(t *testing.T) {
testCases := []struct {
Name string
InputFilename string
ExpectedResult lint.LintStatus
}{
{
Name: "pass - mailbox legacy cert with non critical adobe time-stamp extension",
InputFilename: "smime/mailboxValidatedLegacyWithNonCriticalAdobeTimeStampExtension.pem",
ExpectedResult: lint.Pass,
},
{
Name: "pass - organization multipurpose cert with non critical adobe archive rev info extension",
InputFilename: "smime/organizationValidatedMultipurposeWithNonCriticalAdobeArchRevInfoExtension.pem",
ExpectedResult: lint.Pass,
},
{
Name: "NA - non-SMIME BR cert",
InputFilename: "smime/domainValidatedWithEmailCommonName.pem",
ExpectedResult: lint.NA,
},
{
Name: "NA - non-legacy/multipurpose SMIME BR cert",
InputFilename: "smime/organizationValidatedStrictWithAdobeTimeStampExtension.pem",
ExpectedResult: lint.NA,
},
{
Name: "NE - certificate dated before effective date",
InputFilename: "smime/organizationValidatedLegacyWithAdobeTimeStampExtensionMay2023.pem",
ExpectedResult: lint.NE,
},
{
Name: "Error - sponsor multipurpose certificate with adobe time-stamp extension marked as critical",
InputFilename: "smime/sponsorValidatedMultipurposeWithCriticalAdobeTimeStampExtension.pem",
ExpectedResult: lint.Error,
},
{
Name: "Error - legacy certificate with adobe archive rev info extension marked as critical",
InputFilename: "smime/individualValidatedLegacyWithCriticalAdobeArchRevInfoExtension.pem",
ExpectedResult: lint.Error,
},
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
result := test.TestLint("e_adobe_extensions_legacy_multipurpose_criticality", tc.InputFilename)
if result.Status != tc.ExpectedResult {
t.Errorf("expected result %v was %v - details: %v", tc.ExpectedResult, result.Status, result.Details)
}
})
}
}
60 changes: 60 additions & 0 deletions v3/lints/cabf_smime_br/lint_adobe_extensions_strict_presence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* ZLint Copyright 2023 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_smime_br

import (
"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_adobe_extensions_strict_presence",
Description: "Adobe Time‐stamp X509 extension (1.2.840.113583.1.1.9.1) and the Adobe ArchiveRevInfo extension (1.2.840.113583.1.1.9.2) are prohibited for strict SMIME certificates",
Citation: "7.1.2.3.m",
Source: lint.CABFSMIMEBaselineRequirements,
EffectiveDate: util.CABF_SMIME_BRs_1_0_0_Date,
},
Lint: NewAdobeExtensionsStrictPresence,
})
}

type adobeExtensionsStrictPresence struct{}

// NewAdobeExtensionsStrictPresence creates a new linter to enforce adobe x509 extensions requirements for strict SMIME certs
func NewAdobeExtensionsStrictPresence() lint.CertificateLintInterface {
return &adobeExtensionsStrictPresence{}
}

// CheckApplies returns true if for any subscriber certificate the certificate's policies assert that it conforms to the strict policy requirements defined in the SMIME BRs
func (l *adobeExtensionsStrictPresence) CheckApplies(c *x509.Certificate) bool {
return util.IsSubscriberCert(c) && util.IsStrictSMIMECertificate(c)
}

// Execute applies the requirements of adobe x509 extensions not being allowed for strict SMIME certificates
func (l *adobeExtensionsStrictPresence) Execute(c *x509.Certificate) *lint.LintResult {
if hasAdobeX509Extensions(c) {
return &lint.LintResult{Status: lint.Error}
}

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

func hasAdobeX509Extensions(c *x509.Certificate) bool {
return util.IsExtInCert(c, util.AdobeTimeStampOID) || util.IsExtInCert(c, util.AdobeArchiveRevInfoOID)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* ZLint Copyright 2023 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_smime_br

import (
"testing"

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

func TestAdobeExtensionsStrictPresence(t *testing.T) {
testCases := []struct {
Name string
InputFilename string
ExpectedResult lint.LintStatus
}{
{
Name: "pass - cert without adobe extensions",
InputFilename: "smime/mailboxValidatedStrictWithoutAdobeExtensions.pem",
ExpectedResult: lint.Pass,
},
{
Name: "NA - non-SMIME BR cert",
InputFilename: "smime/domainValidatedWithEmailCommonName.pem",
ExpectedResult: lint.NA,
},
{
Name: "NA - non-strict SMIME BR cert",
InputFilename: "smime/mailboxValidatedLegacyWithCommonName.pem",
ExpectedResult: lint.NA,
},
{
Name: "NE - certificate dated before effective date",
InputFilename: "smime/mailboxValidatedStrictMay2023.pem",
ExpectedResult: lint.NE,
},
{
Name: "Error - certificate with adobe time-stamp extension",
InputFilename: "smime/organizationValidatedStrictWithAdobeTimeStampExtension.pem",
ExpectedResult: lint.Error,
},
{
Name: "Error - certificate with adobe archive rev info extension",
InputFilename: "smime/sponsorValidatedStrictWithAdobeArchRevInfoExtension.pem",
ExpectedResult: lint.Error,
},
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
result := test.TestLint("e_adobe_extensions_strict_presence", tc.InputFilename)
if result.Status != tc.ExpectedResult {
t.Errorf("expected result %v was %v - details: %v", tc.ExpectedResult, result.Status, result.Details)
}
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: ecdsa-with-SHA256
Issuer:
Validity
Not Before: Sep 1 00:00:00 2023 GMT
Not After : Nov 30 00:00:00 9998 GMT
Subject: CN = johnsmith@example.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:20:15:8f:1c:cc:42:e2:21:d2:67:3e:33:3f:dd:
4c:c0:60:06:fc:71:36:4a:8c:aa:32:20:c4:3b:63:
2d:fe:aa:90:35:c6:92:5a:df:b8:ca:8b:c9:93:cf:
7e:1c:df:99:50:ba:7c:23:2a:15:06:80:ac:6b:9f:
14:21:93:8e:e9
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Certificate Policies:
Policy: 2.23.140.1.5.4.1
1.2.840.113583.1.1.9.2: critical
test
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:45:02:21:00:82:27:50:f6:c0:c5:36:4c:73:ba:fc:53:71:
db:db:57:fc:80:b4:6d:60:4e:21:e9:6d:e8:01:06:ea:bc:ab:
26:02:20:2c:45:95:97:a5:e3:cc:89:88:cf:70:47:94:94:8e:
6c:df:03:ac:4e:49:00:19:53:a0:f8:11:de:a5:e3:5b:a7
-----BEGIN CERTIFICATE-----
MIIBPzCB5qADAgECAgEDMAoGCCqGSM49BAMCMAAwIBcNMjMwOTAxMDAwMDAwWhgP
OTk5ODExMzAwMDAwMDBaMCAxHjAcBgNVBAMMFWpvaG5zbWl0aEBleGFtcGxlLmNv
bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCAVjxzMQuIh0mc+Mz/dTMBgBvxx
NkqMqjIgxDtjLf6qkDXGklrfuMqLyZPPfhzfmVC6fCMqFQaArGufFCGTjumjLzAt
MBQGA1UdIAQNMAswCQYHZ4EMAQUEATAVBgoqhkiG9y8BAQkCAQH/BAR0ZXN0MAoG
CCqGSM49BAMCA0gAMEUCIQCCJ1D2wMU2THO6/FNx29tX/IC0bWBOIelt6AEG6ryr
JgIgLEWVl6XjzImIz3BHlJSObN8DrE5JABlToPgR3qXjW6c=
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: ecdsa-with-SHA256
Issuer:
Validity
Not Before: Sep 1 00:00:00 2023 GMT
Not After : Nov 30 00:00:00 9998 GMT
Subject: CN = johnsmith@example.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:bf:fe:7d:bd:d9:c5:7c:d2:16:d5:5b:d0:ac:a1:
61:25:90:f3:da:2b:a4:5f:ab:6b:a6:72:64:6e:37:
29:3f:be:4d:f0:91:e1:b5:9d:12:b9:24:26:40:4e:
b2:6b:57:d7:d7:f2:94:1e:e3:1b:1b:8f:8b:ed:84:
43:a4:84:13:f0
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Certificate Policies:
Policy: 2.23.140.1.5.1.1
1.2.840.113583.1.1.9.1:
test
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:46:02:21:00:a5:ad:3b:a8:8a:d0:0e:3d:d0:79:b0:e0:c1:
cf:20:02:67:9b:dd:5e:b6:7a:2b:a4:d9:c0:f1:c3:9c:b3:96:
bc:02:21:00:9b:c6:ca:a6:7b:16:6f:97:3a:01:9d:c6:c5:dc:
a2:ec:56:dd:2c:e8:a6:e8:9d:f3:a7:99:e7:b3:a7:ac:6a:e5
-----BEGIN CERTIFICATE-----
MIIBPTCB46ADAgECAgEDMAoGCCqGSM49BAMCMAAwIBcNMjMwOTAxMDAwMDAwWhgP
OTk5ODExMzAwMDAwMDBaMCAxHjAcBgNVBAMMFWpvaG5zbWl0aEBleGFtcGxlLmNv
bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL/+fb3ZxXzSFtVb0KyhYSWQ89or
pF+ra6ZyZG43KT++TfCR4bWdErkkJkBOsmtX19fylB7jGxuPi+2EQ6SEE/CjLDAq
MBQGA1UdIAQNMAswCQYHZ4EMAQUBATASBgoqhkiG9y8BAQkBBAR0ZXN0MAoGCCqG
SM49BAMCA0kAMEYCIQClrTuoitAOPdB5sODBzyACZ5vdXrZ6K6TZwPHDnLOWvAIh
AJvGyqZ7Fm+XOgGdxsXcouxW3Szopuid86eZ57OnrGrl
-----END CERTIFICATE-----
39 changes: 39 additions & 0 deletions v3/testdata/smime/mailboxValidatedStrictWithoutAdobeExtensions.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: ecdsa-with-SHA256
Issuer:
Validity
Not Before: Sep 1 00:00:00 2023 GMT
Not After : Nov 30 00:00:00 9998 GMT
Subject: CN = johnsmith@example.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:04:24:34:bb:ef:b9:85:d0:eb:ba:6e:a8:3c:98:
48:45:b1:29:3e:99:42:f5:ce:0f:43:55:11:35:68:
d9:44:ee:5a:25:d9:24:e9:47:b1:bf:e5:12:92:6d:
cc:46:58:46:f7:3e:17:e7:d2:01:a8:ba:09:69:e2:
01:88:0e:d8:33
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Certificate Policies:
Policy: 2.23.140.1.5.1.3
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:45:02:20:2b:20:74:33:3e:f4:2d:49:4b:ef:9a:47:1c:f6:
45:59:d0:4d:47:5c:83:5c:f8:5f:34:1a:96:1f:27:1f:fd:d8:
02:21:00:9d:40:17:4a:8d:ee:ad:fd:77:0b:52:cb:fb:99:40:
fb:55:41:13:10:b8:58:be:ea:9b:42:78:21:55:6d:08:67
-----BEGIN CERTIFICATE-----
MIIBKDCBz6ADAgECAgEDMAoGCCqGSM49BAMCMAAwIBcNMjMwOTAxMDAwMDAwWhgP
OTk5ODExMzAwMDAwMDBaMCAxHjAcBgNVBAMMFWpvaG5zbWl0aEBleGFtcGxlLmNv
bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAQkNLvvuYXQ67puqDyYSEWxKT6Z
QvXOD0NVETVo2UTuWiXZJOlHsb/lEpJtzEZYRvc+F+fSAai6CWniAYgO2DOjGDAW
MBQGA1UdIAQNMAswCQYHZ4EMAQUBAzAKBggqhkjOPQQDAgNIADBFAiArIHQzPvQt
SUvvmkcc9kVZ0E1HXINc+F80GpYfJx/92AIhAJ1AF0qN7q39dwtSy/uZQPtVQRMQ
uFi+6ptCeCFVbQhn
-----END CERTIFICATE-----
Loading
Loading