Source file
src/crypto/x509/platform_test.go
1
2
3
4
5 package x509
6
7 import (
8 "crypto/ecdsa"
9 "crypto/elliptic"
10 "crypto/rand"
11 "encoding/pem"
12 "math/big"
13 "os"
14 "runtime"
15 "strings"
16 "testing"
17 "time"
18 )
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 const (
34 rootCertPath = "platform_root_cert.pem"
35 rootKeyPath = "platform_root_key.pem"
36 )
37
38 func TestPlatformVerifier(t *testing.T) {
39 if runtime.GOOS != "windows" && runtime.GOOS != "darwin" {
40 t.Skip("only tested on windows and darwin")
41 }
42
43 der, err := os.ReadFile(rootCertPath)
44 if err != nil {
45 t.Fatalf("failed to read test root: %s", err)
46 }
47 b, _ := pem.Decode(der)
48 testRoot, err := ParseCertificate(b.Bytes)
49 if err != nil {
50 t.Fatalf("failed to parse test root: %s", err)
51 }
52
53 der, err = os.ReadFile(rootKeyPath)
54 if err != nil {
55 t.Fatalf("failed to read test key: %s", err)
56 }
57 b, _ = pem.Decode(der)
58 testRootKey, err := ParseECPrivateKey(b.Bytes)
59 if err != nil {
60 t.Fatalf("failed to parse test key: %s", err)
61 }
62
63 if _, err := testRoot.Verify(VerifyOptions{}); err != nil {
64 t.Skipf("test root is not in trust store, skipping (err: %q)", err)
65 }
66
67 now := time.Now()
68
69 tests := []struct {
70 name string
71 cert *Certificate
72 selfSigned bool
73 dnsName string
74 time time.Time
75 eku []ExtKeyUsage
76
77 expectedErr string
78 windowsErr string
79 macosErr string
80 }{
81 {
82 name: "valid",
83 cert: &Certificate{
84 SerialNumber: big.NewInt(1),
85 DNSNames: []string{"valid.testing.golang.invalid"},
86 NotBefore: now.Add(-time.Hour),
87 NotAfter: now.Add(time.Hour),
88 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
89 },
90 },
91 {
92 name: "valid (with name)",
93 cert: &Certificate{
94 SerialNumber: big.NewInt(1),
95 DNSNames: []string{"valid.testing.golang.invalid"},
96 NotBefore: now.Add(-time.Hour),
97 NotAfter: now.Add(time.Hour),
98 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
99 },
100 dnsName: "valid.testing.golang.invalid",
101 },
102 {
103 name: "valid (with time)",
104 cert: &Certificate{
105 SerialNumber: big.NewInt(1),
106 DNSNames: []string{"valid.testing.golang.invalid"},
107 NotBefore: now.Add(-time.Hour),
108 NotAfter: now.Add(time.Hour),
109 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
110 },
111 time: now.Add(time.Minute * 30),
112 },
113 {
114 name: "valid (with eku)",
115 cert: &Certificate{
116 SerialNumber: big.NewInt(1),
117 DNSNames: []string{"valid.testing.golang.invalid"},
118 NotBefore: now.Add(-time.Hour),
119 NotAfter: now.Add(time.Hour),
120 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
121 },
122 eku: []ExtKeyUsage{ExtKeyUsageServerAuth},
123 },
124 {
125 name: "wrong name",
126 cert: &Certificate{
127 SerialNumber: big.NewInt(1),
128 DNSNames: []string{"valid.testing.golang.invalid"},
129 NotBefore: now.Add(-time.Hour),
130 NotAfter: now.Add(time.Hour),
131 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
132 },
133 dnsName: "invalid.testing.golang.invalid",
134 expectedErr: "x509: certificate is valid for valid.testing.golang.invalid, not invalid.testing.golang.invalid",
135 },
136 {
137 name: "expired (future)",
138 cert: &Certificate{
139 SerialNumber: big.NewInt(1),
140 DNSNames: []string{"valid.testing.golang.invalid"},
141 NotBefore: now.Add(-time.Hour),
142 NotAfter: now.Add(time.Hour),
143 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
144 },
145 time: now.Add(time.Hour * 2),
146 expectedErr: "x509: certificate has expired or is not yet valid",
147 },
148 {
149 name: "expired (past)",
150 cert: &Certificate{
151 SerialNumber: big.NewInt(1),
152 DNSNames: []string{"valid.testing.golang.invalid"},
153 NotBefore: now.Add(-time.Hour),
154 NotAfter: now.Add(time.Hour),
155 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
156 },
157 time: now.Add(time.Hour * 2),
158 expectedErr: "x509: certificate has expired or is not yet valid",
159 },
160 {
161 name: "self-signed",
162 cert: &Certificate{
163 SerialNumber: big.NewInt(1),
164 DNSNames: []string{"valid.testing.golang.invalid"},
165 NotBefore: now.Add(-time.Hour),
166 NotAfter: now.Add(time.Hour),
167 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
168 },
169 selfSigned: true,
170 macosErr: "x509: “valid.testing.golang.invalid” certificate is not trusted",
171 windowsErr: "x509: certificate signed by unknown authority",
172 },
173 {
174 name: "non-specified KU",
175 cert: &Certificate{
176 SerialNumber: big.NewInt(1),
177 DNSNames: []string{"valid.testing.golang.invalid"},
178 NotBefore: now.Add(-time.Hour),
179 NotAfter: now.Add(time.Hour),
180 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
181 },
182 eku: []ExtKeyUsage{ExtKeyUsageEmailProtection},
183 expectedErr: "x509: certificate specifies an incompatible key usage",
184 },
185 {
186 name: "non-nested KU",
187 cert: &Certificate{
188 SerialNumber: big.NewInt(1),
189 DNSNames: []string{"valid.testing.golang.invalid"},
190 NotBefore: now.Add(-time.Hour),
191 NotAfter: now.Add(time.Hour),
192 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageEmailProtection},
193 },
194 macosErr: "x509: “valid.testing.golang.invalid” certificate is not permitted for this usage",
195 windowsErr: "x509: certificate specifies an incompatible key usage",
196 },
197 }
198
199 leafKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
200 if err != nil {
201 t.Fatalf("ecdsa.GenerateKey failed: %s", err)
202 }
203
204 for _, tc := range tests {
205 tc := tc
206 t.Run(tc.name, func(t *testing.T) {
207 t.Parallel()
208 parent := testRoot
209 if tc.selfSigned {
210 parent = tc.cert
211 }
212 certDER, err := CreateCertificate(rand.Reader, tc.cert, parent, leafKey.Public(), testRootKey)
213 if err != nil {
214 t.Fatalf("CreateCertificate failed: %s", err)
215 }
216 cert, err := ParseCertificate(certDER)
217 if err != nil {
218 t.Fatalf("ParseCertificate failed: %s", err)
219 }
220
221 var opts VerifyOptions
222 if tc.dnsName != "" {
223 opts.DNSName = tc.dnsName
224 }
225 if !tc.time.IsZero() {
226 opts.CurrentTime = tc.time
227 }
228 if len(tc.eku) > 0 {
229 opts.KeyUsages = tc.eku
230 }
231
232 expectedErr := tc.expectedErr
233 if runtime.GOOS == "darwin" && tc.macosErr != "" {
234 expectedErr = tc.macosErr
235 } else if runtime.GOOS == "windows" && tc.windowsErr != "" {
236 expectedErr = tc.windowsErr
237 }
238
239 _, err = cert.Verify(opts)
240 if err != nil && expectedErr == "" {
241 t.Errorf("unexpected verification error: %s", err)
242 } else if err != nil && !strings.HasPrefix(err.Error(), expectedErr) {
243 t.Errorf("unexpected verification error: got %q, want %q", err.Error(), expectedErr)
244 } else if err == nil && expectedErr != "" {
245 t.Errorf("unexpected verification success: want %q", expectedErr)
246 }
247 })
248 }
249 }
250
View as plain text