-
Notifications
You must be signed in to change notification settings - Fork 21
/
getCertificateChain.go
136 lines (114 loc) · 3.89 KB
/
getCertificateChain.go
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
// Licensed under the Apache-2.0 license
package verification
import (
"crypto/x509"
"encoding/pem"
"fmt"
"testing"
"github.com/chipsalliance/caliptra-dpe/verification/client"
zx509 "github.com/zmap/zcrypto/x509"
zlint "github.com/zmap/zlint/v3"
"github.com/zmap/zlint/v3/lint"
)
// TestGetCertificateChain tests calling GetCertificateChain
func TestGetCertificateChain(d client.TestDPEInstance, client client.DPEClient, t *testing.T) {
certChain, err := client.GetCertificateChain()
if err != nil {
t.Fatalf("[FATAL]: Could not get Certificate Chain: %v", err)
}
checkCertificateChain(t, certChain)
}
func checkCertificateChain(t *testing.T, certData []byte) []*x509.Certificate {
t.Helper()
failed := false
var x509Certs []*x509.Certificate
var err error
// Check whether certificate chain is DER encoded.
if x509Certs, err = x509.ParseCertificates(certData); err != nil {
t.Fatalf("[FATAL]: Could not parse certificate using crypto/x509: %v", err)
}
// Parse the cert with zcrypto so we can lint it.
certs, err := zx509.ParseCertificates(certData)
if err != nil {
t.Errorf("[ERROR]: Could not parse certificate using zcrypto/x509: %v", err)
failed = true
}
// zlint provides a lot of linter sources. Limit results to just the relevant RFCs.
// For a full listing of supported linter sources, see https://github.com/zmap/zlint/blob/master/v3/lint/source.go
registry, err := lint.GlobalRegistry().Filter(lint.FilterOptions{
IncludeSources: lint.SourceList{
lint.RFC3279,
lint.RFC5280,
lint.RFC5480,
lint.RFC5891,
lint.RFC8813,
},
ExcludeNames: []string{
// It is fine for cert chains to always use GeneralizedTime, UTCTime is
// strictly worse and mixing the two formats does not lend itself well
// to fixed-sized X.509 templating.
"e_wrong_time_format_pre2050",
// Certs in the Caliptra cert chain fail this lint currently.
// We will need to truncate the serial numbers for those certs and
// then enable this lint.
"e_subject_dn_serial_number_max_length",
},
})
if err != nil {
t.Fatalf("[FATAL]: Could not set up zlint registry: %v", err)
}
for _, cert := range certs {
results := zlint.LintCertificateEx(cert, registry)
for id, result := range results.Results {
var level string
switch result.Status {
case lint.Error:
level = "ERROR"
case lint.Warn:
level = "WARN"
default:
continue
}
details := result.Details
if details != "" {
details = fmt.Sprintf("%s. ", details)
}
l := registry.ByName(id)
t.Errorf("[LINT %s] %s: %s%s (%s)", level, l.Source, details, l.Description, l.Citation)
failed = true
}
if failed {
// Dump the cert in PEM for use with various tools
t.Logf("[LINT]: Offending certificate: %s\n", cert.Subject.String())
t.Logf("[LINT]: Offending certificate (PEM):\n%s", (string)(pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
})))
t.Fatalf("Certificate lint failed!")
}
}
validateCertChain(t, x509Certs)
return x509Certs
}
// Build certificate chain and calls to validateSignature on each chain.
func validateCertChain(t *testing.T, certChain []*x509.Certificate) {
t.Helper()
certsToProcess := certChain
// Remove unhandled critical extensions reported by x509 but defined in spec
removeTcgDiceCriticalExtensions(t, certsToProcess)
// Remove unhandled extended key usages reported by x509 but defined in spec
removeTcgDiceExtendedKeyUsages(t, certsToProcess)
// Build verify options
opts := buildVerifyOptions(t, certChain)
// Certificate chain validation for each intermediate certificate
for _, cert := range certChain {
chains, err := cert.Verify(opts)
if err != nil {
t.Errorf("[ERROR]: Error in Certificate Chain of %s: %s", cert.Subject, err.Error())
}
// Log certificate chains linked to each certificate in chain
if len(chains) != 1 {
t.Errorf("[ERROR]: validateCertChain certificate chain is empty")
}
}
}