@@ -85,9 +85,9 @@ func ParseOIDs(oids []string) ([]asn1.ObjectIdentifier, error) {
85
85
return ret , nil
86
86
}
87
87
88
- // ChainValidationOpts contains various parameters for certificate chain validation
89
- type ChainValidationOpts struct {
90
- // trustedRoots is a pool of certificates that defines the roots the CT log will accept
88
+ // chainValidator contains various parameters for certificate chain validation.
89
+ type chainValidator struct {
90
+ // trustedRoots is a pool of certificates that defines the roots the CT log will accept.
91
91
trustedRoots * x509util.PEMCertPool
92
92
// currentTime is the time used for checking a certificate's validity period
93
93
// against. If it's zero then time.Now() is used. Only for testing.
@@ -104,14 +104,14 @@ type ChainValidationOpts struct {
104
104
// dates strictly *before* notAfterLimit will be accepted.
105
105
// nil means no upper bound on the accepted range.
106
106
notAfterLimit * time.Time
107
- // extKeyUsages contains the list of EKUs to use during chain verification
107
+ // extKeyUsages contains the list of EKUs to use during chain verification.
108
108
extKeyUsages []x509.ExtKeyUsage
109
109
// rejectExtIds contains a list of X.509 extension IDs to reject during chain verification.
110
110
rejectExtIds []asn1.ObjectIdentifier
111
111
}
112
112
113
- func NewChainValidationOpts (trustedRoots * x509util.PEMCertPool , rejectExpired , rejectUnexpired bool , notAfterStart , notAfterLimit * time.Time , extKeyUsages []x509.ExtKeyUsage , rejectExtIds []asn1.ObjectIdentifier ) ChainValidationOpts {
114
- return ChainValidationOpts {
113
+ func NewChainValidator (trustedRoots * x509util.PEMCertPool , rejectExpired , rejectUnexpired bool , notAfterStart , notAfterLimit * time.Time , extKeyUsages []x509.ExtKeyUsage , rejectExtIds []asn1.ObjectIdentifier ) chainValidator {
114
+ return chainValidator {
115
115
trustedRoots : trustedRoots ,
116
116
rejectExpired : rejectExpired ,
117
117
rejectUnexpired : rejectUnexpired ,
@@ -143,13 +143,12 @@ func isPrecertificate(cert *x509.Certificate) (bool, error) {
143
143
return false , nil
144
144
}
145
145
146
- // validateChain takes the certificate chain as it was parsed from a JSON request. Ensures all
146
+ // validate takes the certificate chain as it was parsed from a JSON request. Ensures all
147
147
// elements in the chain decode as X.509 certificates. Ensures that there is a valid path from the
148
148
// end entity certificate in the chain to a trusted root cert, possibly using the intermediates
149
149
// supplied in the chain. Then applies the RFC requirement that the path must involve all
150
150
// the submitted chain in the order of submission.
151
- // TODO(phboneff): make this a method func([][]byte) ([]*x509.Certificate, error)
152
- func (opts ChainValidationOpts ) validateChain (rawChain [][]byte ) ([]* x509.Certificate , error ) {
151
+ func (cv chainValidator ) validate (rawChain [][]byte ) ([]* x509.Certificate , error ) {
153
152
if len (rawChain ) == 0 {
154
153
return nil , errors .New ("empty certificate chain" )
155
154
}
@@ -172,8 +171,8 @@ func (opts ChainValidationOpts) validateChain(rawChain [][]byte) ([]*x509.Certif
172
171
}
173
172
}
174
173
175
- naStart := opts .notAfterStart
176
- naLimit := opts .notAfterLimit
174
+ naStart := cv .notAfterStart
175
+ naLimit := cv .notAfterLimit
177
176
cert := chain [0 ]
178
177
179
178
// Check whether the expiry date of the cert is within the acceptable range.
@@ -184,24 +183,24 @@ func (opts ChainValidationOpts) validateChain(rawChain [][]byte) ([]*x509.Certif
184
183
return nil , fmt .Errorf ("certificate NotAfter (%v) >= %v" , cert .NotAfter , * naLimit )
185
184
}
186
185
187
- now := opts .currentTime
186
+ now := cv .currentTime
188
187
if now .IsZero () {
189
188
now = time .Now ()
190
189
}
191
190
expired := now .After (cert .NotAfter )
192
- if opts .rejectExpired && expired {
191
+ if cv .rejectExpired && expired {
193
192
return nil , errors .New ("rejecting expired certificate" )
194
193
}
195
- if opts .rejectUnexpired && ! expired {
194
+ if cv .rejectUnexpired && ! expired {
196
195
return nil , errors .New ("rejecting unexpired certificate" )
197
196
}
198
197
199
198
// Check for unwanted extension types, if required.
200
199
// TODO(al): Refactor CertValidationOpts c'tor to a builder pattern and
201
200
// pre-calc this in there
202
- if len (opts .rejectExtIds ) != 0 {
201
+ if len (cv .rejectExtIds ) != 0 {
203
202
badIDs := make (map [string ]bool )
204
- for _ , id := range opts .rejectExtIds {
203
+ for _ , id := range cv .rejectExtIds {
205
204
badIDs [id .String ()] = true
206
205
}
207
206
for idx , ext := range cert .Extensions {
@@ -214,9 +213,9 @@ func (opts ChainValidationOpts) validateChain(rawChain [][]byte) ([]*x509.Certif
214
213
215
214
// TODO(al): Refactor CertValidationOpts c'tor to a builder pattern and
216
215
// pre-calc this in there too.
217
- if len (opts .extKeyUsages ) > 0 {
216
+ if len (cv .extKeyUsages ) > 0 {
218
217
acceptEKUs := make (map [x509.ExtKeyUsage ]bool )
219
- for _ , eku := range opts .extKeyUsages {
218
+ for _ , eku := range cv .extKeyUsages {
220
219
acceptEKUs [eku ] = true
221
220
}
222
221
good := false
@@ -227,7 +226,7 @@ func (opts ChainValidationOpts) validateChain(rawChain [][]byte) ([]*x509.Certif
227
226
}
228
227
}
229
228
if ! good {
230
- return nil , fmt .Errorf ("rejecting certificate without EKU in %v" , opts .extKeyUsages )
229
+ return nil , fmt .Errorf ("rejecting certificate without EKU in %v" , cv .extKeyUsages )
231
230
}
232
231
}
233
232
@@ -237,9 +236,9 @@ func (opts ChainValidationOpts) validateChain(rawChain [][]byte) ([]*x509.Certif
237
236
// - allow certificate without policing them since this is not CT's responsibility
238
237
// See /internal/lax509/README.md for further information.
239
238
verifyOpts := lax509.VerifyOptions {
240
- Roots : opts .trustedRoots .CertPool (),
239
+ Roots : cv .trustedRoots .CertPool (),
241
240
Intermediates : intermediatePool .CertPool (),
242
- KeyUsages : opts .extKeyUsages ,
241
+ KeyUsages : cv .extKeyUsages ,
243
242
}
244
243
245
244
verifiedChains , err := lax509 .Verify (cert , verifyOpts )
@@ -263,16 +262,18 @@ func (opts ChainValidationOpts) validateChain(rawChain [][]byte) ([]*x509.Certif
263
262
return nil , errors .New ("no RFC compliant path to root found when trying to validate chain" )
264
263
}
265
264
266
- // verifyAddChain is used by add-chain and add-pre-chain. It does the checks that the supplied
267
- // cert is of the correct type and chains to a trusted root.
265
+ // Validate is used by add-chain and add-pre-chain. It checks that the supplied
266
+ // cert is of the correct type, chains to a trusted root and satisties time
267
+ // constraints.
268
268
// TODO(phbnf): add tests
269
- func (opts ChainValidationOpts ) verifyAddChain (req rfc6962.AddChainRequest , expectingPrecert bool ) ([]* x509.Certificate , error ) {
270
- // We already checked that the chain is not empty so can move on to verification
271
- validPath , err := opts .validateChain (req .Chain )
269
+ // TODO(phbnf): merge with validate
270
+ func (cv chainValidator ) Validate (req rfc6962.AddChainRequest , expectingPrecert bool ) ([]* x509.Certificate , error ) {
271
+ // We already checked that the chain is not empty so can move on to validation.
272
+ validPath , err := cv .validate (req .Chain )
272
273
if err != nil {
273
274
// We rejected it because the cert failed checks or we could not find a path to a root etc.
274
275
// Lots of possible causes for errors
275
- return nil , fmt .Errorf ("chain failed to verify : %s" , err )
276
+ return nil , fmt .Errorf ("chain failed to validate : %s" , err )
276
277
}
277
278
278
279
isPrecert , err := isPrecertificate (validPath [0 ])
@@ -293,6 +294,10 @@ func (opts ChainValidationOpts) verifyAddChain(req rfc6962.AddChainRequest, expe
293
294
return validPath , nil
294
295
}
295
296
297
+ func (cv chainValidator ) Roots () []* x509.Certificate {
298
+ return cv .trustedRoots .RawCertificates ()
299
+ }
300
+
296
301
func chainsEquivalent (inChain []* x509.Certificate , verifiedChain []* x509.Certificate ) bool {
297
302
// The verified chain includes a root, but the input chain may or may not include a
298
303
// root (RFC 6962 s4.1/ s4.2 "the last [certificate] is either the root certificate
0 commit comments