File: sha1.go

package info (click to toggle)
golang-github-cloudflare-cfssl 1.2.0%2Bgit20160825.89.7fb22c8-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 4,916 kB
  • ctags: 2,827
  • sloc: sh: 146; sql: 62; python: 11; makefile: 8
file content (153 lines) | stat: -rw-r--r-- 5,628 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package ubiquity

import (
	"crypto/x509"
	"fmt"
	"time"

	"github.com/cloudflare/cfssl/helpers"
)

// DeprecationSeverity encodes the severity of a deprecation policy
type DeprecationSeverity int

const (
	// None indicates there is no deprecation
	None DeprecationSeverity = iota
	// Low indicates the deprecation policy won't affect user experience
	Low
	// Medium indicates the deprecation policy will affect user experience
	// either in a minor way or for a limited scope of users.
	Medium
	// High indicates the deprecation policy will strongly affect user experience
	High
)

// SHA1DeprecationPolicy encodes how a platform deprecates the support of SHA1
type SHA1DeprecationPolicy struct {
	// the name of platform
	Platform string `json:"platform"`
	// policy severity, policies of the same platform will only trigger the one of highest severity
	Severity DeprecationSeverity `json:"severity"`
	// a human readable message describing the deprecation effects
	Description string `json:"description"`
	// the date when the policy is effective. zero value means effective immediately
	EffectiveDate time.Time `json:"effective_date"`
	// the expiry deadline indicates the latest date which a end-entity
	// certificate with SHA1 can be valid through.
	ExpiryDeadline time.Time `json:"expiry_deadline"`
	// the date beyond which SHA1 cert should not be issued.
	NeverIssueAfter time.Time `json:"never_issue_after"`
}

// SHA1DeprecationPolicys ia a list of various SHA1DeprecationPolicy's
// proposed by major browser producers
var SHA1DeprecationPolicys = []SHA1DeprecationPolicy{
	// Chrome:
	//   if the leaf certificate expires between 01-01-2016 and 01-01-2017
	//   and the chain (excluding root) contains SHA-1 cert, show "minor errors".
	{
		Platform:       "Google Chrome",
		Description:    "shows the SSL connection has minor problems",
		Severity:       Medium,
		ExpiryDeadline: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
	},
	// Chrome:
	//   if the leaf certificate expires after Jan. 1st 2017
	//   and the chain (excluding root) contains SHA-1 cert, show "untrusted SSL".
	{
		Platform:       "Google Chrome",
		Description:    "shows the SSL connection is untrusted",
		Severity:       High,
		ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
	},
	// Mozilla Firefox:
	//   if the leaf certificate expires after Jan. 1st 2017, and
	//   the chain (excluding root) contains SHA-1 cert, show a warning in the developer console.
	{
		Platform:       "Mozilla Firefox",
		Description:    "gives warning in the developer console",
		Severity:       Low,
		ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
	},
	// Mozilla Firefox:
	//   if a new certificate is issued after Jan. 1st 2016, and
	//   it is a SHA-1 cert, reject it.
	{
		Platform:        "Mozilla Firefox",
		Description:     "shows the SSL connection is untrusted",
		Severity:        Medium,
		EffectiveDate:   time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
		NeverIssueAfter: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
	},
	// Mozilla Firefox:
	//   deprecate all valid SHA-1 cert chain on Jan. 1st 2017
	{
		Platform:       "Mozilla Firefox",
		Description:    "shows the SSL connection is untrusted",
		Severity:       High,
		EffectiveDate:  time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
		ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
	},
	// Microsoft Windows:
	//   deprecate all valid SHA-1 cert chain on Jan. 1st 2017
	{
		Platform:       "Microsoft Windows Vista and later",
		Description:    "shows the SSL connection is untrusted",
		Severity:       High,
		EffectiveDate:  time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
		ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
	},
}

// Flag returns whether the policy flags the cert chain as deprecated for matching its deprecation criteria
func (p SHA1DeprecationPolicy) Flag(chain []*x509.Certificate) bool {
	leaf := chain[0]
	if time.Now().After(p.EffectiveDate) {

		// Reject newly issued leaf certificate with SHA-1 after the specified deadline.
		if !p.NeverIssueAfter.IsZero() && leaf.NotBefore.After(p.NeverIssueAfter) {
			// Check hash algorithm of non-root leaf cert.
			if len(chain) > 1 && helpers.HashAlgoString(leaf.SignatureAlgorithm) == "SHA1" {
				return true
			}
		}

		// Reject certificate chain with SHA-1 that are still valid after expiry deadline.
		if !p.ExpiryDeadline.IsZero() && leaf.NotAfter.After(p.ExpiryDeadline) {
			// Check hash algorithm of non-root certs.
			for i, cert := range chain {
				if i < len(chain)-1 {
					if helpers.HashAlgoString(cert.SignatureAlgorithm) == "SHA1" {
						return true
					}
				}
			}
		}
	}

	return false
}

// SHA1DeprecationMessages returns a list of human-readable messages. Each message describes
// how one platform rejects the chain based on SHA1 deprecation policies.
func SHA1DeprecationMessages(chain []*x509.Certificate) []string {
	// record the most severe deprecation policy by each platform
	selectedPolicies := map[string]SHA1DeprecationPolicy{}
	for _, policy := range SHA1DeprecationPolicys {
		if policy.Flag(chain) {
			// only keep the policy with highest severity
			if selectedPolicies[policy.Platform].Severity < policy.Severity {
				selectedPolicies[policy.Platform] = policy
			}
		}
	}
	// build the message list
	list := []string{}
	for _, policy := range selectedPolicies {
		if policy.Severity > None {
			list = append(list, fmt.Sprintf("%s %s due to SHA-1 deprecation", policy.Platform, policy.Description))
		}
	}
	return list
}