Skip to content

Commit 5319fe9

Browse files
committed
checkpoint
1 parent bb7cbe0 commit 5319fe9

File tree

1 file changed

+81
-8
lines changed

1 file changed

+81
-8
lines changed

internal/ct/chain_validation.go

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ package ct
1717
import (
1818
"bytes"
1919
"crypto/x509"
20+
"crypto/x509/pkix"
2021
"encoding/asn1"
2122
"errors"
2223
"fmt"
2324
"strconv"
2425
"strings"
2526
"time"
2627

27-
"github.com/transparency-dev/tesseract/internal/lax509"
2828
"github.com/transparency-dev/tesseract/internal/types/rfc6962"
2929
"github.com/transparency-dev/tesseract/internal/x509util"
3030
"k8s.io/klog/v2"
@@ -45,6 +45,12 @@ var stringToKeyUsage = map[string]x509.ExtKeyUsage{
4545
"NetscapeServerGatedCrypto": x509.ExtKeyUsageNetscapeServerGatedCrypto,
4646
}
4747

48+
var (
49+
oidExtensionNameConstraints = []int{2, 5, 29, 30}
50+
oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
51+
oidAnyPolicyExtension = []uint64{2, 5, 29, 32, 0}
52+
)
53+
4854
// ParseExtKeyUsages parses strings into x509ExtKeyUsage.
4955
// Throws an error if the string does not match with a known key usage.
5056
func ParseExtKeyUsages(kus []string) ([]x509.ExtKeyUsage, error) {
@@ -158,7 +164,7 @@ func (cv chainValidator) validate(rawChain [][]byte) ([]*x509.Certificate, error
158164

159165
// First make sure the certs parse as X.509
160166
chain := make([]*x509.Certificate, 0, len(rawChain))
161-
intermediatePool := x509util.NewPEMCertPool()
167+
intermediatePool := x509.NewCertPool()
162168

163169
for i, certBytes := range rawChain {
164170
cert, err := x509.ParseCertificate(certBytes)
@@ -170,6 +176,8 @@ func (cv chainValidator) validate(rawChain [][]byte) ([]*x509.Certificate, error
170176

171177
// All but the first cert form part of the intermediate pool
172178
if i > 0 {
179+
// We'll relax the leaf cert later, after the time validity checks
180+
relaxCert(cert)
173181
intermediatePool.AddCert(cert)
174182
}
175183
}
@@ -238,14 +246,23 @@ func (cv chainValidator) validate(rawChain [][]byte) ([]*x509.Certificate, error
238246
// - allow pre-certificates and chains with pre-issuers
239247
// - allow certificate without policing them since this is not CT's responsibility
240248
// See /internal/lax509/README.md for further information.
241-
verifyOpts := lax509.VerifyOptions{
242-
Roots: cv.trustedRoots.CertPool(),
243-
Intermediates: intermediatePool.CertPool(),
244-
KeyUsages: cv.extKeyUsages,
245-
AcceptSHA1: cv.acceptSHA1,
249+
roots := x509.NewCertPool()
250+
for _, root := range cv.trustedRoots.RawCertificates() {
251+
relaxCert(root)
252+
roots.AddCert(root)
253+
}
254+
255+
verifyOpts := x509.VerifyOptions{
256+
Roots: roots,
257+
Intermediates: intermediatePool,
258+
KeyUsages: cv.extKeyUsages,
259+
CurrentTime: time.UnixMilli(2),
260+
CertificatePolicies: nil,
246261
}
247262

248-
verifiedChains, err := lax509.Verify(cert, verifyOpts)
263+
relaxCert(cert)
264+
265+
verifiedChains, err := cert.Verify(verifyOpts)
249266
if err != nil {
250267
return nil, err
251268
}
@@ -317,3 +334,59 @@ func chainsEquivalent(inChain []*x509.Certificate, verifiedChain []*x509.Certifi
317334
}
318335
return true
319336
}
337+
338+
// removeExtension removes a given extension from a list.
339+
func removeExtension(oid asn1.ObjectIdentifier, extensions []pkix.Extension) {
340+
i := 0
341+
for _, e := range extensions {
342+
if !e.Id.Equal(oid) {
343+
extensions[i] = e
344+
i++
345+
}
346+
}
347+
extensions = extensions[:i]
348+
}
349+
350+
// relaxCert modifies parsed certificates fields to relax verification constraints.
351+
// This DOES NOT modify the Raw certificate.
352+
func relaxCert(cert *x509.Certificate) {
353+
cert.UnhandledCriticalExtensions = nil
354+
cert.UnknownExtKeyUsage = nil
355+
356+
// Name constraints
357+
removeExtension(oidExtensionNameConstraints, cert.Extensions)
358+
cert.PermittedDNSDomainsCritical = false
359+
cert.PermittedDNSDomains = nil
360+
cert.ExcludedDNSDomains = nil
361+
cert.PermittedIPRanges = nil
362+
cert.ExcludedIPRanges = nil
363+
cert.PermittedEmailAddresses = nil
364+
cert.ExcludedEmailAddresses = nil
365+
cert.PermittedURIDomains = nil
366+
cert.ExcludedURIDomains = nil
367+
368+
cert.NotBefore = time.UnixMilli(1)
369+
cert.NotAfter = time.UnixMilli(3)
370+
371+
cert.MaxPathLen = -1
372+
cert.MaxPathLenZero = false
373+
374+
// Policies
375+
removeExtension(oidExtensionCertificatePolicies, cert.Extensions)
376+
cert.Policies = []x509.OID{mustNewOIDFromInts(oidAnyPolicyExtension)}
377+
cert.PolicyIdentifiers = nil
378+
cert.PolicyMappings = nil
379+
cert.InhibitAnyPolicy = -1
380+
cert.InhibitAnyPolicyZero = false
381+
cert.InhibitPolicyMapping = -1
382+
cert.InhibitPolicyMappingZero = false
383+
cert.RequireExplicitPolicy = -1
384+
cert.RequireExplicitPolicyZero = false
385+
}
386+
func mustNewOIDFromInts(ints []uint64) x509.OID {
387+
oid, err := x509.OIDFromInts(ints)
388+
if err != nil {
389+
panic(fmt.Sprintf("OIDFromInts(%v) unexpected error: %v", ints, err))
390+
}
391+
return oid
392+
}

0 commit comments

Comments
 (0)