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