Skip to content

Commit e45de5e

Browse files
authored
Migrate away from c-t-go/x509 and c-t-go/asn1 (#198)
* use local BuildPrecertTBS instead of ctgo * sed ctgo/x509 - crypto/x509 # Conflicts: # internal/scti/storage.go # Conflicts: # internal/scti/ctlog.go # Conflicts: # internal/scti/chain_validation.go # internal/scti/handlers_test.go # internal/scti/signatures_test.go # Conflicts: # ctlog.go * fix requestLog: implements stringer # Conflicts: # internal/scti/requestlog.go * move pem_cert_pool to x509 package * fix a bunch of things # Conflicts: # ctlog.go # Conflicts: # ctlog.go # Conflicts: # internal/scti/chain_validation_test.go * migrate x509util to standard librairies * drop dep on c-t-go/x509 in x509util and delete print funcs # Conflicts: # internal/x509util/x509util.go # Conflicts: # internal/x509util/x509util.go * remove last IsFatal * edit isPreIssuer # Conflicts: # internal/scti/handlers.go * remove unused PreCertificate method * migrate x509/ct.go away from c-t-go # Conflicts: # internal/x509util/ct.go # internal/x509util/ct_test.go * migrate from x509 to x509fork * undeprecate Subject * Add comments * migrate hammer * better comments * edit comment and log message
1 parent 071a272 commit e45de5e

19 files changed

+623
-907
lines changed

ctlog.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ package sctfe
1717
import (
1818
"context"
1919
"crypto"
20+
"crypto/x509"
21+
"encoding/asn1"
2022
"errors"
2123
"fmt"
2224
"net/http"
2325
"strings"
2426
"time"
2527

26-
"github.com/google/certificate-transparency-go/asn1"
27-
"github.com/google/certificate-transparency-go/x509"
2828
"github.com/transparency-dev/static-ct/internal/scti"
2929
"github.com/transparency-dev/static-ct/internal/x509util"
3030
"github.com/transparency-dev/static-ct/storage"

internal/hammer/loadtest/workers.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,20 @@ package loadtest
1717
import (
1818
"context"
1919
"crypto/sha256"
20+
"crypto/x509"
2021
"encoding/base64"
2122
"encoding/json"
2223
"errors"
2324
"fmt"
2425
"math/rand/v2"
2526
"time"
2627

27-
"slices"
28-
29-
"github.com/google/certificate-transparency-go/x509"
3028
"github.com/transparency-dev/formats/log"
3129
"github.com/transparency-dev/merkle/proof"
3230
"github.com/transparency-dev/merkle/rfc6962"
3331
"github.com/transparency-dev/static-ct/internal/client"
3432
"github.com/transparency-dev/static-ct/internal/types"
33+
"github.com/transparency-dev/static-ct/internal/x509util"
3534
"github.com/transparency-dev/trillian-tessera/api/layout"
3635
"github.com/transparency-dev/trillian-tessera/ctonly"
3736
"k8s.io/klog/v2"
@@ -427,7 +426,7 @@ func entryFromChain(chain []*x509.Certificate, isPrecert bool, timestamp uint64)
427426

428427
// Next, post-process the DER-encoded TBSCertificate, to remove the CT poison
429428
// extension and possibly update the issuer field.
430-
defangedTBS, err := x509.BuildPrecertTBS(cert.RawTBSCertificate, preIssuer)
429+
defangedTBS, err := x509util.BuildPrecertTBS(cert.RawTBSCertificate, preIssuer)
431430
if err != nil {
432431
return nil, fmt.Errorf("failed to remove poison extension: %v", err)
433432
}
@@ -445,6 +444,14 @@ func entryFromChain(chain []*x509.Certificate, isPrecert bool, timestamp uint64)
445444
// isPreIssuer indicates whether a certificate is a pre-cert issuer with the specific
446445
// certificate transparency extended key usage.
447446
// Copied from certificate-transparency-go/serialization.go and internal/scti/handlers.go.
448-
func isPreIssuer(issuer *x509.Certificate) bool {
449-
return slices.Contains(issuer.ExtKeyUsage, x509.ExtKeyUsageCertificateTransparency)
447+
// TODO(phboneff): unify these.
448+
func isPreIssuer(cert *x509.Certificate) bool {
449+
// Look for the extension in the Extensions field and not ExtKeyUsage
450+
// since crypto/x509 does not recognize this extension as an ExtKeyUsage.
451+
for _, ext := range cert.Extensions {
452+
if types.OIDExtKeyUsageCertificateTransparency.Equal(ext.Id) {
453+
return true
454+
}
455+
}
456+
return false
450457
}

internal/scti/chain_validation.go

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@ package scti
1616

1717
import (
1818
"bytes"
19+
"crypto/x509"
20+
"encoding/asn1"
1921
"errors"
2022
"fmt"
2123
"strconv"
2224
"strings"
2325
"time"
2426

25-
"github.com/google/certificate-transparency-go/asn1"
26-
"github.com/google/certificate-transparency-go/x509"
27+
"github.com/transparency-dev/static-ct/internal/types"
28+
"github.com/transparency-dev/static-ct/internal/x509fork"
2729
"github.com/transparency-dev/static-ct/internal/x509util"
2830
"k8s.io/klog/v2"
2931
)
@@ -129,7 +131,7 @@ func isPrecertificate(cert *x509.Certificate) (bool, error) {
129131
}
130132

131133
for _, ext := range cert.Extensions {
132-
if x509.OIDExtensionCTPoison.Equal(ext.Id) {
134+
if types.OIDExtensionCTPoison.Equal(ext.Id) {
133135
if !ext.Critical || !bytes.Equal(asn1.NullBytes, ext.Value) {
134136
return false, fmt.Errorf("CT poison ext is not critical or invalid: %v", ext)
135137
}
@@ -158,8 +160,8 @@ func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x5
158160

159161
for i, certBytes := range rawChain {
160162
cert, err := x509.ParseCertificate(certBytes)
161-
if x509.IsFatal(err) {
162-
return nil, err
163+
if err != nil {
164+
return nil, fmt.Errorf("x509.ParseCertificate(): %v", err)
163165
}
164166

165167
chain = append(chain, cert)
@@ -229,32 +231,18 @@ func validateChain(rawChain [][]byte, validationOpts ChainValidationOpts) ([]*x5
229231
}
230232
}
231233

232-
// We can now do the verification. Use fairly lax options for verification, as
233-
// CT is intended to observe certificates rather than police them.
234-
verifyOpts := x509.VerifyOptions{
235-
Roots: validationOpts.trustedRoots.CertPool(),
236-
CurrentTime: now,
237-
Intermediates: intermediatePool.CertPool(),
238-
DisableTimeChecks: true,
239-
// Precertificates have the poison extension; also the Go library code does not
240-
// support the standard PolicyConstraints extension (which is required to be marked
241-
// critical, RFC 5280 s4.2.1.11), so never check unhandled critical extensions.
242-
DisableCriticalExtensionChecks: true,
243-
// Pre-issued precertificates have the Certificate Transparency EKU; also some
244-
// leaves have unknown EKUs that should not be bounced just because the intermediate
245-
// does not also have them (cf. https://github.com/golang/go/issues/24590) so
246-
// disable EKU checks inside the x509 library, but we've already done our own check
247-
// on the leaf above.
248-
DisableEKUChecks: true,
249-
// Path length checks get confused by the presence of an additional
250-
// pre-issuer intermediate, so disable them.
251-
DisablePathLenChecks: true,
252-
DisableNameConstraintChecks: true,
253-
DisableNameChecks: false,
254-
KeyUsages: validationOpts.extKeyUsages,
234+
// We can now do the verification. Use x509fork with looser verification
235+
// constraints to:
236+
// - allow pre-certificates and chains with pre-issuers
237+
// - allow certificate without policing them since this is not CT's responsibility
238+
// See /internal/x509fork/README.md for further information.
239+
verifyOpts := x509fork.VerifyOptions{
240+
Roots: validationOpts.trustedRoots.CertPool(),
241+
Intermediates: intermediatePool.CertPool(),
242+
KeyUsages: validationOpts.extKeyUsages,
255243
}
256244

257-
verifiedChains, err := cert.Verify(verifyOpts)
245+
verifiedChains, err := x509fork.Verify(cert, verifyOpts)
258246
if err != nil {
259247
return nil, err
260248
}

internal/scti/chain_validation_test.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@
1515
package scti
1616

1717
import (
18+
"crypto/x509"
19+
"crypto/x509/pkix"
20+
"encoding/asn1"
1821
"encoding/pem"
1922
"strings"
2023
"testing"
2124
"time"
2225

23-
"github.com/google/certificate-transparency-go/asn1"
24-
"github.com/google/certificate-transparency-go/x509"
25-
"github.com/google/certificate-transparency-go/x509/pkix"
2626
"github.com/transparency-dev/static-ct/internal/testdata"
27+
"github.com/transparency-dev/static-ct/internal/types"
2728
"github.com/transparency-dev/static-ct/internal/x509util"
2829
)
2930

@@ -168,13 +169,13 @@ func wipeExtensions(cert *x509.Certificate) *x509.Certificate {
168169

169170
func makePoisonNonCritical(cert *x509.Certificate) *x509.Certificate {
170171
// Invalid as a pre-cert because poison extension needs to be marked as critical.
171-
cert.Extensions = []pkix.Extension{{Id: x509.OIDExtensionCTPoison, Critical: false, Value: asn1.NullBytes}}
172+
cert.Extensions = []pkix.Extension{{Id: types.OIDExtensionCTPoison, Critical: false, Value: asn1.NullBytes}}
172173
return cert
173174
}
174175

175176
func makePoisonNonNull(cert *x509.Certificate) *x509.Certificate {
176177
// Invalid as a pre-cert because poison extension is not ASN.1 NULL value.
177-
cert.Extensions = []pkix.Extension{{Id: x509.OIDExtensionCTPoison, Critical: false, Value: []byte{0x42, 0x42, 0x42}}}
178+
cert.Extensions = []pkix.Extension{{Id: types.OIDExtensionCTPoison, Critical: false, Value: []byte{0x42, 0x42, 0x42}}}
178179
return cert
179180
}
180181

@@ -420,7 +421,7 @@ func TestValidateChain(t *testing.T) {
420421
if len(gotPath) != test.wantPathLen {
421422
t.Errorf("|ValidateChain()|=%d; want %d", len(gotPath), test.wantPathLen)
422423
for _, c := range gotPath {
423-
t.Logf("Subject: %s Issuer: %s", x509util.NameToString(c.Subject), x509util.NameToString(c.Issuer))
424+
t.Logf("Subject: %s Issuer: %s", c.Subject, c.Issuer)
424425
}
425426
}
426427
})
@@ -624,8 +625,8 @@ func pemToCert(t *testing.T, pemData string) *x509.Certificate {
624625
}
625626

626627
cert, err := x509.ParseCertificate(bytes.Bytes)
627-
if x509.IsFatal(err) {
628-
t.Fatal(err)
628+
if err != nil {
629+
t.Fatalf("x509.ParseCertificate(): %v", err)
629630
}
630631

631632
return cert
@@ -696,7 +697,7 @@ func TestPreIssuedCert(t *testing.T) {
696697
t.Fatalf("failed to ValidateChain: %v", err)
697698
}
698699
for i, c := range chain {
699-
t.Logf("chain[%d] = \n%s", i, x509util.CertificateToString(c))
700+
t.Logf("chain[%d] = \n%s", i, c.Subject)
700701
}
701702
})
702703
}

internal/scti/ctlog.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import (
44
"context"
55
"crypto"
66
"crypto/ecdsa"
7+
"crypto/x509"
78
"errors"
89
"fmt"
910

10-
"github.com/google/certificate-transparency-go/x509"
1111
"github.com/transparency-dev/static-ct/internal/types"
1212
"github.com/transparency-dev/static-ct/modules/dedup"
1313
"github.com/transparency-dev/static-ct/storage"

internal/scti/handlers.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package scti
1717
import (
1818
"context"
1919
"crypto/sha256"
20+
"crypto/x509"
2021
"encoding/base64"
2122
"encoding/json"
2223
"errors"
@@ -28,13 +29,11 @@ import (
2829
"sync"
2930
"time"
3031

31-
"slices"
32-
3332
"github.com/google/certificate-transparency-go/tls"
34-
"github.com/google/certificate-transparency-go/x509"
3533
"github.com/prometheus/client_golang/prometheus"
3634
"github.com/prometheus/client_golang/prometheus/promauto"
3735
"github.com/transparency-dev/static-ct/internal/types"
36+
"github.com/transparency-dev/static-ct/internal/x509util"
3837
"github.com/transparency-dev/static-ct/modules/dedup"
3938
tessera "github.com/transparency-dev/trillian-tessera"
4039
"github.com/transparency-dev/trillian-tessera/ctonly"
@@ -493,7 +492,7 @@ func entryFromChain(chain []*x509.Certificate, isPrecert bool, timestamp uint64)
493492

494493
// Next, post-process the DER-encoded TBSCertificate, to remove the CT poison
495494
// extension and possibly update the issuer field.
496-
defangedTBS, err := x509.BuildPrecertTBS(cert.RawTBSCertificate, preIssuer)
495+
defangedTBS, err := x509util.BuildPrecertTBS(cert.RawTBSCertificate, preIssuer)
497496
if err != nil {
498497
return nil, fmt.Errorf("failed to remove poison extension: %v", err)
499498
}
@@ -510,7 +509,13 @@ func entryFromChain(chain []*x509.Certificate, isPrecert bool, timestamp uint64)
510509

511510
// isPreIssuer indicates whether a certificate is a pre-cert issuer with the specific
512511
// certificate transparency extended key usage.
513-
// copied form certificate-transparency-go/serialization.go
514-
func isPreIssuer(issuer *x509.Certificate) bool {
515-
return slices.Contains(issuer.ExtKeyUsage, x509.ExtKeyUsageCertificateTransparency)
512+
func isPreIssuer(cert *x509.Certificate) bool {
513+
// Look for the extension in the Extensions field and not ExtKeyUsage
514+
// since crypto/x509 does not recognize this extension as an ExtKeyUsage.
515+
for _, ext := range cert.Extensions {
516+
if types.OIDExtKeyUsageCertificateTransparency.Equal(ext.Id) {
517+
return true
518+
}
519+
}
520+
return false
516521
}

internal/scti/handlers_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"bytes"
2020
"context"
2121
"crypto"
22+
"crypto/x509"
2223
"encoding/hex"
2324
"encoding/json"
2425
"fmt"
@@ -30,7 +31,6 @@ import (
3031
"time"
3132

3233
"github.com/golang/mock/gomock"
33-
"github.com/google/certificate-transparency-go/x509"
3434
"github.com/google/go-cmp/cmp"
3535
"github.com/google/go-cmp/cmp/cmpopts"
3636
"github.com/transparency-dev/static-ct/internal/testdata"

internal/scti/requestlog.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@ package scti
1616

1717
import (
1818
"context"
19+
"crypto/x509"
1920
"encoding/hex"
2021
"time"
2122

22-
"github.com/google/certificate-transparency-go/x509"
23-
"github.com/google/certificate-transparency-go/x509util"
2423
"k8s.io/klog/v2"
2524
)
2625

@@ -86,8 +85,8 @@ func (dlr *DefaultRequestLog) addDERToChain(_ context.Context, d []byte) {
8685
// certificate that is part of a submitted chain.
8786
func (dlr *DefaultRequestLog) addCertToChain(_ context.Context, cert *x509.Certificate) {
8887
klog.V(vLevel).Infof("RL: Cert: Sub: %s Iss: %s notBef: %s notAft: %s",
89-
x509util.NameToString(cert.Subject),
90-
x509util.NameToString(cert.Issuer),
88+
cert.Subject,
89+
cert.Issuer,
9190
cert.NotBefore.Format(time.RFC1123Z),
9291
cert.NotAfter.Format(time.RFC1123Z))
9392
}

internal/scti/signatures.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ import (
1818
"crypto"
1919
"crypto/rand"
2020
"crypto/sha256"
21+
"crypto/x509"
2122
"encoding/binary"
2223
"fmt"
2324
"time"
2425

2526
"github.com/google/certificate-transparency-go/tls"
26-
"github.com/google/certificate-transparency-go/x509"
2727
tfl "github.com/transparency-dev/formats/log"
2828
"github.com/transparency-dev/static-ct/internal/types"
2929
"golang.org/x/mod/sumdb/note"

internal/scti/signatures_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ import (
1818
"bytes"
1919
"crypto"
2020
"crypto/sha256"
21+
"crypto/x509"
2122
"encoding/hex"
2223
"encoding/pem"
2324
"testing"
2425
"time"
2526

2627
"github.com/google/certificate-transparency-go/tls"
27-
"github.com/google/certificate-transparency-go/x509"
2828
"github.com/kylelemons/godebug/pretty"
2929
"github.com/transparency-dev/static-ct/internal/testdata"
3030
"github.com/transparency-dev/static-ct/internal/types"
@@ -245,7 +245,7 @@ func TestSerializeV1STHSignatureKAT(t *testing.T) {
245245

246246
func TestBuildV1MerkleTreeLeafForCert(t *testing.T) {
247247
cert, err := x509util.CertificateFromPEM([]byte(testdata.LeafSignedByFakeIntermediateCertPEM))
248-
if x509.IsFatal(err) {
248+
if err != nil {
249249
t.Fatalf("failed to set up test cert: %v", err)
250250
}
251251

@@ -308,7 +308,7 @@ func TestBuildV1MerkleTreeLeafForCert(t *testing.T) {
308308

309309
func TestSignV1SCTForPrecertificate(t *testing.T) {
310310
cert, err := x509util.CertificateFromPEM([]byte(testdata.PrecertPEMValid))
311-
if x509.IsFatal(err) {
311+
if err != nil {
312312
t.Fatalf("failed to set up test precert: %v", err)
313313
}
314314

@@ -367,7 +367,7 @@ func TestSignV1SCTForPrecertificate(t *testing.T) {
367367
if got, want := keyHash[:], leaf.TimestampedEntry.PrecertEntry.IssuerKeyHash[:]; !bytes.Equal(got, want) {
368368
t.Fatalf("Issuer key hash bytes mismatch, got %v, expected %v", got, want)
369369
}
370-
defangedTBS, _ := x509.RemoveCTPoison(cert.RawTBSCertificate)
370+
defangedTBS, _ := x509util.RemoveCTPoison(cert.RawTBSCertificate)
371371
if got, want := leaf.TimestampedEntry.PrecertEntry.TBSCertificate, defangedTBS; !bytes.Equal(got, want) {
372372
t.Fatalf("TBS cert mismatch, got %v, expected %v", got, want)
373373
}

0 commit comments

Comments
 (0)