3636 useSystemRoots = flag .Bool ("system_roots" , false , "Use system roots" )
3737 verbose = flag .Bool ("verbose" , false , "Verbose output" )
3838 strict = flag .Bool ("strict" , true , "Set non-zero exit code for non-fatal errors in parsing" )
39- validate = flag .Bool ("validate" , false , "Validate certificate signatures" )
39+ validate = flag .Bool ("validate" , false , "Validate certificate signatures (leaf to root) " )
4040 checkTime = flag .Bool ("check_time" , false , "Check current validity of certificate" )
4141 checkName = flag .Bool ("check_name" , true , "Check certificate name validity" )
4242 checkEKU = flag .Bool ("check_eku" , true , "Check EKU nesting validity" )
4646 checkRevoked = flag .Bool ("check_revocation" , false , "Check revocation status of certificate" )
4747)
4848
49- func addCerts (filename string , pool * x509.CertPool ) {
49+ func addCerts (filename string , pool * x509.CertPool , validateSelfSigned bool ) {
5050 if filename != "" {
5151 dataList , err := x509util .ReadPossiblePEMFile (filename , "CERTIFICATE" )
5252 if err != nil {
@@ -58,6 +58,12 @@ func addCerts(filename string, pool *x509.CertPool) {
5858 glog .Exitf ("Failed to parse certificate from %s: %v" , filename , err )
5959 }
6060 for _ , cert := range certs {
61+ if validateSelfSigned {
62+ err := cert .CheckSignature (cert .SignatureAlgorithm , cert .RawTBSCertificate , cert .Signature )
63+ if err != nil {
64+ glog .Exitf ("Failed to verify self-signature on root cert from %s: %v" , filename , err )
65+ }
66+ }
6167 pool .AddCert (cert )
6268 }
6369 }
@@ -105,6 +111,7 @@ func main() {
105111 }
106112 if * validate && len (chain ) > 0 {
107113 opts := x509.VerifyOptions {
114+ KeyUsages : []x509.ExtKeyUsage {x509 .ExtKeyUsageAny },
108115 DisableTimeChecks : ! * checkTime ,
109116 DisableCriticalExtensionChecks : ! * checkUnknownCriticalExts ,
110117 DisableNameChecks : ! * checkName ,
@@ -220,11 +227,10 @@ func validateChain(chain []*x509.Certificate, opts x509.VerifyOptions, rootsFile
220227 }
221228 roots = systemRoots
222229 }
223- opts .KeyUsages = []x509.ExtKeyUsage {x509 .ExtKeyUsageAny }
224230 opts .Roots = roots
225231 opts .Intermediates = x509 .NewCertPool ()
226- addCerts (rootsFile , opts .Roots )
227- addCerts (intermediatesFile , opts .Intermediates )
232+ addCerts (rootsFile , opts .Roots /* validate_self_signed= */ , true )
233+ addCerts (intermediatesFile , opts .Intermediates /* validate_self_signed= */ , false )
228234
229235 if ! useSystemRoots && len (rootsFile ) == 0 {
230236 // No root CA certs provided, so assume the chain is self-contained.
@@ -241,6 +247,32 @@ func validateChain(chain []*x509.Certificate, opts x509.VerifyOptions, rootsFile
241247 opts .Intermediates .AddCert (chain [i ])
242248 }
243249 }
250+
251+ failed := false
252+ for i , cert := range chain {
253+ var msg string
254+ var signer * x509.Certificate
255+ if i == len (chain )- 1 {
256+ signer = cert
257+ msg = "self-signature"
258+ } else {
259+ signer = chain [i + 1 ]
260+ msg = fmt .Sprintf ("signature from cert [%d]" , i + 1 )
261+ }
262+
263+ err := signer .CheckSignature (cert .SignatureAlgorithm , cert .RawTBSCertificate , cert .Signature )
264+ if err != nil {
265+ glog .Errorf ("Failed to verify %s on certificate [%d]: %v" , msg , i , err )
266+ failed = true
267+ } else if * verbose {
268+ fmt .Printf ("Certificate [%d] with subject %q has valid %s\n " , i , cert .Subject , msg )
269+ }
270+ }
271+ if failed {
272+ glog .Exitf ("Signature verification failed" )
273+ }
274+
275+ // Also do full x509 verification according to the options.
244276 _ , err := chain [0 ].Verify (opts )
245277 return err
246278}
0 commit comments