Skip to content

Commit

Permalink
lints: lint for upcoming Apple max cert lifetime policy. (#417)
Browse files Browse the repository at this point in the history
A new `e_tls_server_cert_valid_time_longer_than_398_days` lint is added for the
Apple source category (presently named `lint.AppleCTPolicy`, see
#418).

This lint returns an error lint result if a server-auth certificate issued after
Sept 1st, 2020 has a lifetime > 398 days. The lifetime is calculated as Apple
specifies, e.g. "398 days is measured with a day being equal to 86,400
seconds.".

A warning result is returned if a certificate issued after Sept 1st, 2020 has
a lifetime > 397 days and < 398 days. This matches Apple's SHOULD-equivalent
recommendation to use a validity period <= 397 days in length.

See https://support.apple.com/en-us/HT211025 for more information.

Resolves #407
  • Loading branch information
cpu authored Mar 17, 2020
1 parent cfbfdec commit 83d24bd
Show file tree
Hide file tree
Showing 8 changed files with 353 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* ZLint Copyright 2020 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 apple

import (
"time"

"github.com/zmap/zcrypto/x509"
"github.com/zmap/zlint/v2/lint"
"github.com/zmap/zlint/v2/util"
)

type serverCertValidityTooLong struct{}

func (l *serverCertValidityTooLong) Initialize() error {
return nil
}

func (l *serverCertValidityTooLong) CheckApplies(c *x509.Certificate) bool {
return util.IsServerAuthCert(c)
}

func (l *serverCertValidityTooLong) Execute(c *x509.Certificate) *lint.LintResult {
// "398 days is measured with a day being equal to 86,400 seconds. Any time
// greater than this indicates an additional day of validity."
dayLength := 86400 * time.Second
// "TLS server certificates issued on or after September 1, 2020 00:00 GMT/UTC
// must not have a validity period greater than 398 days."
maxValidity := 398 * dayLength
// "We recommend that certificates be issued with a maximum validity of 397 days."
warnValidity := 397 * dayLength

// Calculate the date that the certificate NotAfter must be less than
errEndDate := c.NotBefore.Add(maxValidity)
warnEndDate := c.NotBefore.Add(warnValidity)

if c.NotAfter.After(errEndDate) {
return &lint.LintResult{Status: lint.Error}
} else if c.NotAfter.After(warnEndDate) {
return &lint.LintResult{
// RFC 2119 has SHOULD and RECOMMENDED as equal. Since Apple recommends
// 397 days we treat this as a lint.Warn result as a violation of
// a SHOULD.
Status: lint.Warn,
Details: "Apple recommends that certificates be issued with a maximum " +
"validity of 397 days.",
}
}

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

func init() {
lint.RegisterLint(&lint.Lint{
Name: "e_tls_server_cert_valid_time_longer_than_398_days",
Description: "TLS server certificates issued on or after September 1, 2020 " +
"00:00 GMT/UTC must not have a validity period greater than 398 days",
Citation: "https://support.apple.com/en-us/HT211025",
// TODO(@cpu): The Source should be `lint.ApplePolicy` or something similar.
// The "CT" bit is too specific. Unfortunately since the constant is
// exported by the `util` package we can't change it without bumping the
// major version. See https://github.com/zmap/zlint/issues/418
Source: lint.AppleCTPolicy,
EffectiveDate: util.AppleReducedLifetimeDate,
Lint: &serverCertValidityTooLong{},
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package apple

import (
"testing"

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

func TestServerCertValidityTooLong(t *testing.T) {
// Test certificates were created using a small Go program:
// See https://gist.github.com/cpu/96fad159e6e4db891ee69d225e8a61bc
testCases := []struct {
testCert string
expected lint.LintStatus
}{
{
// Cert issued before Sept 1, 2020 lifetime > 398 days.
testCert: "eeServerCertValidOver398OldNotBefore.pem",
expected: lint.NE,
},
{
// Cert issued after Sept 1, 2020 with lifetime <= 397 days.
testCert: "eeServerCertValidEqual397.pem",
expected: lint.Pass,
},
{
// Cert issued after Sept 1, 2020 with lifetime > 397 and < 398 days.
testCert: "eeServerCertValidOver397.pem",
expected: lint.Warn,
},
{
// Cert issued after Sept 1, 2020 with lifetime == 398 days.
testCert: "eeServerCertValidEqual398.pem",
expected: lint.Warn,
},
{
// Cert issued after Sept 1, 2020 with lifetime > 398 days.
testCert: "eeServerCertValidOver398.pem",
expected: lint.Error,
},
}

for _, tc := range testCases {
t.Run(tc.testCert, func(t *testing.T) {
if result := test.TestLint(
"e_tls_server_cert_valid_time_longer_than_398_days",
tc.testCert); result.Status != tc.expected {
t.Errorf("expected result %v was %v", tc.expected, result.Status)
}
})
}
}
44 changes: 44 additions & 0 deletions v2/testdata/eeServerCertValidEqual397.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 161187849540477949 (0x23ca77ec1f823fd)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = ZLint Test CA
Validity
Not Before: Sep 1 01:00:00 2020 GMT
Not After : Oct 3 01:00:00 2021 GMT
Subject: CN = zmap.io
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (512 bit)
Modulus:
00:e6:ce:f2:0e:3a:ca:cd:df:4c:d2:c3:79:71:7c:
cd:4a:e3:cf:e8:46:e4:55:93:cc:a2:34:16:95:68:
35:37:b6:20:b3:14:2a:71:d4:0f:e9:e3:f3:1a:b8:
66:1c:97:e5:02:88:64:fd:25:b3:d4:cb:f9:89:ef:
73:4c:df:e9:77
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name:
DNS:zmap.io
Signature Algorithm: sha256WithRSAEncryption
6a:ff:a1:35:5b:ab:ff:4b:8d:7c:9d:d0:de:a3:a7:17:32:c5:
b0:7b:4e:43:1f:ce:3b:04:93:c8:a3:02:2a:c4:1e:41:15:40:
08:73:19:43:e1:86:61:1b:f8:c4:ca:5a:7e:69:e5:ba:ff:06:
49:94:6e:df:d0:17:08:63:46:a1
-----BEGIN CERTIFICATE-----
MIIBdTCCAR+gAwIBAgIIAjynfsH4I/0wDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UE
AxMNWkxpbnQgVGVzdCBDQTAeFw0yMDA5MDEwMTAwMDBaFw0yMTEwMDMwMTAwMDBa
MBIxEDAOBgNVBAMTB3ptYXAuaW8wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA5s7y
DjrKzd9M0sN5cXzNSuPP6EbkVZPMojQWlWg1N7YgsxQqcdQP6ePzGrhmHJflAohk
/SWz1Mv5ie9zTN/pdwIDAQABo1MwUTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw
FAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwEgYDVR0RBAswCYIH
em1hcC5pbzANBgkqhkiG9w0BAQsFAANBAGr/oTVbq/9LjXyd0N6jpxcyxbB7TkMf
zjsEk8ijAirEHkEVQAhzGUPhhmEb+MTKWn5p5br/BkmUbt/QFwhjRqE=
-----END CERTIFICATE-----
44 changes: 44 additions & 0 deletions v2/testdata/eeServerCertValidEqual398.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 766376178642781113 (0xaa2b712f45303b9)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = ZLint Test CA
Validity
Not Before: Sep 1 01:00:00 2020 GMT
Not After : Oct 4 01:00:00 2021 GMT
Subject: CN = zmap.io
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (512 bit)
Modulus:
00:b0:b3:10:d6:27:ab:c7:fb:97:7b:a2:8a:f9:c0:
d5:bc:e7:df:90:a2:f8:8e:41:c5:a1:1a:80:a9:25:
a0:cb:a1:06:cf:5b:ff:cb:74:75:0a:80:5c:f2:d9:
0a:de:63:52:3f:59:82:78:25:7a:26:b9:fb:f4:44:
41:44:53:33:a3
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name:
DNS:zmap.io
Signature Algorithm: sha256WithRSAEncryption
5f:e5:da:10:d2:48:6f:86:22:ac:d4:d4:f2:fc:87:14:07:eb:
51:67:5f:0d:9a:55:b3:f4:0f:34:d2:da:e8:5d:6e:17:4c:52:
32:ff:89:4b:08:b7:09:c7:cf:96:6b:2f:0f:30:cb:75:8e:ee:
c4:fd:cb:09:1b:41:7a:ee:c8:aa
-----BEGIN CERTIFICATE-----
MIIBdTCCAR+gAwIBAgIICqK3EvRTA7kwDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UE
AxMNWkxpbnQgVGVzdCBDQTAeFw0yMDA5MDEwMTAwMDBaFw0yMTEwMDQwMTAwMDBa
MBIxEDAOBgNVBAMTB3ptYXAuaW8wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAsLMQ
1ierx/uXe6KK+cDVvOffkKL4jkHFoRqAqSWgy6EGz1v/y3R1CoBc8tkK3mNSP1mC
eCV6Jrn79ERBRFMzowIDAQABo1MwUTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw
FAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwEgYDVR0RBAswCYIH
em1hcC5pbzANBgkqhkiG9w0BAQsFAANBAF/l2hDSSG+GIqzU1PL8hxQH61FnXw2a
VbP0DzTS2uhdbhdMUjL/iUsItwnHz5ZrLw8wy3WO7sT9ywkbQXruyKo=
-----END CERTIFICATE-----
44 changes: 44 additions & 0 deletions v2/testdata/eeServerCertValidOver397.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3515253396569930287 (0x30c8b056ee093a2f)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = ZLint Test CA
Validity
Not Before: Sep 1 01:00:00 2020 GMT
Not After : Oct 3 01:01:00 2021 GMT
Subject: CN = zmap.io
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (512 bit)
Modulus:
00:c3:5b:cc:1d:05:af:92:28:5b:c4:43:11:c1:05:
3c:1a:e3:1b:3d:3e:4f:fb:c9:bc:7d:28:d1:45:b0:
e2:dd:54:2b:ee:c9:1f:07:a3:2b:a6:93:7b:bb:ee:
38:09:e5:94:cf:8b:74:38:19:90:09:3d:7c:bc:28:
45:73:e1:40:1d
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name:
DNS:zmap.io
Signature Algorithm: sha256WithRSAEncryption
a6:eb:24:f8:8f:c7:ef:1b:2c:f4:70:d2:5d:9e:de:7b:54:b8:
58:b0:d4:12:68:97:8b:36:3c:a8:e0:f5:60:dd:b4:2e:e9:43:
98:0d:32:4f:a1:e4:26:ee:b0:6e:09:14:da:07:5f:00:98:66:
d6:e2:3b:ba:42:6f:c1:38:e1:53
-----BEGIN CERTIFICATE-----
MIIBdTCCAR+gAwIBAgIIMMiwVu4JOi8wDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UE
AxMNWkxpbnQgVGVzdCBDQTAeFw0yMDA5MDEwMTAwMDBaFw0yMTEwMDMwMTAxMDBa
MBIxEDAOBgNVBAMTB3ptYXAuaW8wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAw1vM
HQWvkihbxEMRwQU8GuMbPT5P+8m8fSjRRbDi3VQr7skfB6MrppN7u+44CeWUz4t0
OBmQCT18vChFc+FAHQIDAQABo1MwUTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw
FAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwEgYDVR0RBAswCYIH
em1hcC5pbzANBgkqhkiG9w0BAQsFAANBAKbrJPiPx+8bLPRw0l2e3ntUuFiw1BJo
l4s2PKjg9WDdtC7pQ5gNMk+h5CbusG4JFNoHXwCYZtbiO7pCb8E44VM=
-----END CERTIFICATE-----
44 changes: 44 additions & 0 deletions v2/testdata/eeServerCertValidOver398.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 5930884994093112911 (0x524ebc7a9c9d5e4f)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = ZLint Test CA
Validity
Not Before: Sep 1 01:00:00 2020 GMT
Not After : Oct 4 01:01:00 2021 GMT
Subject: CN = zmap.io
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (512 bit)
Modulus:
00:c0:1f:74:20:9e:5a:40:6b:0d:da:2d:a2:3d:b5:
4d:ab:31:5a:cb:98:b2:3b:8a:3d:e4:98:2f:81:d4:
fd:d9:4e:57:b2:47:5a:49:d6:f5:b0:68:d4:a7:99:
61:90:a3:fc:3c:bd:26:68:7f:c4:ae:e2:aa:ca:a9:
aa:e9:38:46:95
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name:
DNS:zmap.io
Signature Algorithm: sha256WithRSAEncryption
a2:bb:7f:0f:46:03:8b:ca:0e:90:60:13:5f:ff:86:9a:ae:94:
ba:71:68:30:18:77:dc:7e:ae:d9:32:3e:3b:70:20:ca:44:9b:
7d:97:aa:72:c4:ca:2e:dc:6a:f8:08:18:1d:d8:78:fd:f5:59:
3c:cc:6c:b7:d2:bb:5c:f5:1d:b4
-----BEGIN CERTIFICATE-----
MIIBdTCCAR+gAwIBAgIIUk68epydXk8wDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UE
AxMNWkxpbnQgVGVzdCBDQTAeFw0yMDA5MDEwMTAwMDBaFw0yMTEwMDQwMTAxMDBa
MBIxEDAOBgNVBAMTB3ptYXAuaW8wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAwB90
IJ5aQGsN2i2iPbVNqzFay5iyO4o95JgvgdT92U5XskdaSdb1sGjUp5lhkKP8PL0m
aH/EruKqyqmq6ThGlQIDAQABo1MwUTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw
FAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwEgYDVR0RBAswCYIH
em1hcC5pbzANBgkqhkiG9w0BAQsFAANBAKK7fw9GA4vKDpBgE1//hpqulLpxaDAY
d9x+rtkyPjtwIMpEm32XqnLEyi7cavgIGB3YeP31WTzMbLfSu1z1HbQ=
-----END CERTIFICATE-----
44 changes: 44 additions & 0 deletions v2/testdata/eeServerCertValidOver398OldNotBefore.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4951827648663421118 (0x44b86d02b38a80be)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = ZLint Test CA
Validity
Not Before: Jan 1 01:00:00 2020 GMT
Not After : Feb 2 01:01:00 2021 GMT
Subject: CN = zmap.io
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (512 bit)
Modulus:
00:ae:b7:3d:25:09:52:6a:6d:b3:82:6a:38:64:ee:
95:e1:a4:40:6c:56:34:b5:8d:30:76:df:a0:7d:11:
7d:ab:52:c9:eb:d3:ba:ef:16:a3:ff:e0:f4:71:c7:
16:3e:21:33:8d:6a:82:58:6f:06:37:29:72:4c:46:
e2:b4:00:7d:4b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name:
DNS:zmap.io
Signature Algorithm: sha256WithRSAEncryption
47:c6:22:dd:57:18:2d:ab:8a:30:fd:de:db:9b:64:7d:15:4f:
31:44:77:b0:b9:c5:d5:6c:06:c1:a8:20:22:77:ac:f0:39:e5:
b9:25:2b:21:6f:52:99:98:2a:c7:ff:4f:b4:55:f4:fb:de:f3:
6a:28:58:b9:38:af:3e:e0:99:21
-----BEGIN CERTIFICATE-----
MIIBdTCCAR+gAwIBAgIIRLhtArOKgL4wDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UE
AxMNWkxpbnQgVGVzdCBDQTAeFw0yMDAxMDEwMTAwMDBaFw0yMTAyMDIwMTAxMDBa
MBIxEDAOBgNVBAMTB3ptYXAuaW8wXDANBgkqhkiG9w0BAQEFAANLADBIAkEArrc9
JQlSam2zgmo4ZO6V4aRAbFY0tY0wdt+gfRF9q1LJ69O67xaj/+D0cccWPiEzjWqC
WG8GNylyTEbitAB9SwIDAQABo1MwUTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw
FAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwEgYDVR0RBAswCYIH
em1hcC5pbzANBgkqhkiG9w0BAQsFAANBAEfGIt1XGC2rijD93tubZH0VTzFEd7C5
xdVsBsGoICJ3rPA55bklKyFvUpmYKsf/T7RV9Pve82ooWLk4rz7gmSE=
-----END CERTIFICATE-----
1 change: 1 addition & 0 deletions v2/util/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var (
MozillaPolicy22Date = time.Date(2013, time.July, 26, 0, 0, 0, 0, time.UTC)
MozillaPolicy24Date = time.Date(2017, time.February, 28, 0, 0, 0, 0, time.UTC)
MozillaPolicy27Date = time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC)
AppleReducedLifetimeDate = time.Date(2020, time.September, 1, 0, 0, 0, 0, time.UTC)
)

func FindTimeType(firstDate, secondDate asn1.RawValue) (int, int) {
Expand Down

0 comments on commit 83d24bd

Please sign in to comment.