Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge TLS1.3 Feature Branch into Main #406

Merged
merged 50 commits into from
Mar 17, 2025
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a6d702c
Port TLS 1.3 from Go (#300)
dissoupov Jul 15, 2021
dc3e3bd
tls 1.3: added missing ciphers (#305)
dissoupov Jul 18, 2021
62d29d3
tls 1.3: common.go: ported missing fields in Config (#306)
dissoupov Jul 19, 2021
54fce8d
TLS 1.3: Handshake logs (#307)
dissoupov Aug 9, 2021
61204b5
Merge from master (#312)
dissoupov Aug 19, 2021
82767f2
TLS 1.3: Add handshake tests (#315)
dissoupov Sep 6, 2021
e5a0c22
TLS 1.3: fix exception in processServerKeyExchange (#316)
dissoupov Sep 8, 2021
11cb43a
TLS1.3: added test for negociated Cipher Suite (#318)
dissoupov Sep 20, 2021
794a43c
TLS1.3 Feature Branch: Add back in SessionTicket support (#323)
codyprime Dec 15, 2021
d265230
TLS 1.3: don't create skx log if processing server key exchange faile…
codyprime Dec 16, 2021
d08a277
tls 1.3: Add support for SupportedVersions Extension in log (#327)
codyprime Dec 17, 2021
52b63a6
TLS 1.3, X509: stub out darwin root stores (#328)
codyprime Feb 21, 2022
5590405
handshake_client: do not overwrite server certs (#329)
Feb 22, 2022
e5412fa
Added extension identifiers for Server Hello messages to Handshake Lo…
nakulbajaj Apr 20, 2022
dbbfb1c
Updated TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 = 0xD001 = 53249 (#333)
nakulbajaj Apr 21, 2022
1b9a864
Make jsonifyExtensions public and add grouped CertificatesPolicies Us…
May 5, 2022
817b9ce
standardize unsupported elliptic curve error
elliotcubit Aug 11, 2022
e7d0b65
ct: allow publishing certificates with parsing errors
elliotcubit Aug 15, 2022
3fbd2be
Merge pull request #344 from elliotcubit/ecubit/elliptic-curve
elliotcubit Aug 22, 2022
1912d07
tls: perform type assertion on cert publickey (#345)
codyprime Sep 22, 2022
894d0f8
Expose 'validSignature' field
elliotcubit Jan 31, 2023
4c02f2b
Merge pull request #348 from elliotcubit/ecubit/expose-valid-signature
elliotcubit Jan 31, 2023
a3f90a5
verifier: set ValidSignature field
elliotcubit Feb 21, 2023
2ba506e
run go fmt
elliotcubit Feb 21, 2023
4eadde1
Merge pull request #350 from elliotcubit/ecubit/verifier-valid-signature
elliotcubit Feb 21, 2023
0f155df
Merge pull request #351 from elliotcubit/ecubit/gofmt
elliotcubit Feb 22, 2023
b1f1309
verifier: add AppendFromPEMErr method
elliotcubit Apr 13, 2023
13ae606
Merge pull request #358 from elliotcubit/ecubit/verifier-errors
elliotcubit Apr 13, 2023
f9aa5b9
verifier: set ValidSignature for certificates in the graph
elliotcubit Apr 28, 2023
c6c18cc
Merge pull request #360 from elliotcubit/ecubit/intermediates-signatures
elliotcubit May 3, 2023
84259cd
pkix: marshal nonstandard name attributes only once
elliotcubit Sep 7, 2023
4ba27e9
Merge pull request #365 from elliotcubit/ecubit/dupe-dn-fields
elliotcubit Sep 8, 2023
c093b7d
make extension parsing more permissive (#387)
iJustErikk Sep 11, 2024
7fe312f
ignore permissive errors
iJustErikk Oct 25, 2024
8ea4fd6
Merge pull request #388 from iJustErikk/erik/just-ignore-permissive
elliotcubit Oct 29, 2024
90dd94c
fix: regenerate ECDSA test flows
developStorm Feb 18, 2025
5413c5e
Merge branch 'feature/TLSv1.3' into refactor/tls13-merge-attempt-3
developStorm Feb 18, 2025
d5e1856
fix: configurable server random w/ downgrade canary
developStorm Feb 18, 2025
d3e579a
fix: Config.Time in tests using expired certificates
developStorm Feb 18, 2025
3f733db
Revert "fix: regenerate ECDSA test flows"
developStorm Feb 18, 2025
e0d9751
fix: regenerate ECDSA test flows
developStorm Feb 18, 2025
e9e96f1
Merge branch 'feature/TLSv1.3' into refactor/tls13-merge-attempt-3
developStorm Feb 18, 2025
97e834c
style: reformat merged file
developStorm Feb 18, 2025
68960d5
fix(tls): preMasterSecret for TLS12
developStorm Mar 7, 2025
e41bc99
fix(tls): TLS12 sig and digest
developStorm Mar 9, 2025
9eda340
fix(tls): TLS12 ecdh params
developStorm Mar 9, 2025
11895e0
fix(tls): ignore y coord in json output for x25519
developStorm Mar 9, 2025
f983195
fix: x509 error message for the new self-signed certificates error
developStorm Mar 16, 2025
7d3b1a2
fix: remove misleading RFC reference and add new TLS signature algori…
developStorm Mar 16, 2025
6576108
fix: update rsaKeyAgreement methods to use pointer receivers
developStorm Mar 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 120 additions & 25 deletions ct/scanner/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,20 @@ import (
"github.com/zmap/zcrypto/ct"
"github.com/zmap/zcrypto/ct/client"
"github.com/zmap/zcrypto/ct/x509"
"github.com/zmap/zcrypto/encoding/asn1"
"github.com/zmap/zcrypto/x509/pkix"
)

// ASN1Certificate holds the top-level asn1 fields in a certificate.
//
// It is used to determine if a certificate contains well-formed asn1 data or is corrupted.
type ASN1Certificate struct {
Raw asn1.RawContent
TBSCertificate asn1.RawValue
SignatureAlgorithm pkix.AlgorithmIdentifier
SignatureValue asn1.BitString
}

// Clients wishing to implement their own Matchers should implement this interface:
type Matcher interface {
// CertificateMatches is called by the scanner for each X509 Certificate found in the log.
Expand Down Expand Up @@ -137,6 +149,9 @@ type ScannerOptions struct {
Name string

MaximumIndex int64

// Always output encountered certificates, so long as they are valid ASN.1
IgnoreParsingErrors bool
}

// Creates a new ScannerOptions struct with sensible defaults
Expand Down Expand Up @@ -188,30 +203,87 @@ type fetchRange struct {
end int64
}

// Takes the error returned by either x509.ParseCertificate() or
// x509.ParseTBSCertificate() and determines if it's non-fatal or otherwise.
// In the case of non-fatal errors, the error will be logged,
// entriesWithNonFatalErrors will be incremented, and the return value will be
// nil.
// Fatal errors will be logged, unparsableEntires will be incremented, and the
// parseCertificate takes a raw certificate, parses it, and if there is an error,
// determines if it is fatal. In the case of non-fatal errors, the error will be logged,
// entriesWithNonFatalErrors will be incremented, and the returned error will be nil.
//
// Fatal parse errors will be logged, unparsableEntries will be incremented, and the
// fatal error itself will be returned.
// When |err| is nil, this method does nothing.
func (s *Scanner) handleParseEntryError(err error, entryType ct.LogEntryType, index int64) error {
//
// This function does NOT promise that the returned certificate will be non-nil
// whenever err is non-nil.
func (s *Scanner) parseCertificate(
precert bool,
entryType ct.LogEntryType,
index int64,
raw []byte,
) (*x509.Certificate, error) {
var cert *x509.Certificate
var err error
if precert {
cert, err = x509.ParseTBSCertificate(raw)
} else {
cert, err = x509.ParseCertificate(raw)
}

if err == nil {
// No error to handle
return nil
return cert, nil
}

var isFatal bool

switch err.(type) {
case x509.NonFatalErrors:
s.entriesWithNonFatalErrors++
// We'll make a note, but continue.
s.logger.Warnf("Non-fatal error in %+v at index %d of log at %s: %s", entryType, index, s.logClient.Uri, err)
default:
s.unparsableEntries++
s.logger.Warnf("Failed to parse in %+v at index %d of log at %s: %s", entryType, index, s.logClient.Uri, err)
return err
isFatal = true
}

if !isFatal {
s.logger.Warnf(
"Ignored non-fatal error in %+v at index %d of log at %s: %s",
entryType,
index,
s.logClient.Uri,
err,
)
return cert, nil
}

if !s.opts.IgnoreParsingErrors {
s.logger.Errorf(
"Fatal parse error in %+v at index %d of log at %s: %s",
entryType,
index,
s.logClient.Uri,
err,
)
return nil, err
}
return nil

var asn1cert ASN1Certificate
if _, perr := asn1.Unmarshal(raw, &asn1cert); perr != nil {
s.logger.Warnf(
"Corrupted cert ASN.1 in %+v at index %d of log %s: %s",
entryType,
index,
s.logClient.Uri,
perr,
)
return nil, perr
}

s.logger.Warnf(
"Ignored fatal parse error in %+v at index %d of log %s: %s",
entryType,
index,
s.logClient.Uri,
err,
)

return cert, nil
}

// Processes the given |entry| in the specified log.
Expand All @@ -223,29 +295,52 @@ func (s *Scanner) processEntry(entry ct.LogEntry, foundCert func(*ct.LogEntry, s
// Only interested in precerts and this is an X.509 cert, early-out.
return
}
cert, err := x509.ParseCertificate(entry.Leaf.TimestampedEntry.X509Entry)
if err = s.handleParseEntryError(err, entry.Leaf.TimestampedEntry.EntryType, entry.Index); err != nil {
// We hit an unparseable entry, already logged inside handleParseEntryError()
cert, err := s.parseCertificate(
false,
entry.Leaf.TimestampedEntry.EntryType,
entry.Index,
entry.Leaf.TimestampedEntry.X509Entry,
)
if err != nil {
return
}
if s.opts.Matcher.CertificateMatches(cert) {
entry.X509Cert = cert
if cert != nil {
if s.opts.Matcher.CertificateMatches(cert) {
entry.RawCert = entry.Leaf.TimestampedEntry.X509Entry
entry.X509Cert = cert
foundCert(&entry, s.opts.Name)
}
} else {
entry.RawCert = entry.Leaf.TimestampedEntry.X509Entry
foundCert(&entry, s.opts.Name)
}
case ct.PrecertLogEntryType:
c, err := x509.ParseTBSCertificate(entry.Leaf.TimestampedEntry.PrecertEntry.TBSCertificate)
if err = s.handleParseEntryError(err, entry.Leaf.TimestampedEntry.EntryType, entry.Index); err != nil {
// We hit an unparseable entry, already logged inside handleParseEntryError()
cert, err := s.parseCertificate(
true,
entry.Leaf.TimestampedEntry.EntryType,
entry.Index,
entry.Leaf.TimestampedEntry.PrecertEntry.TBSCertificate,
)
if err != nil {
return
}
precert := &ct.Precertificate{
Raw: entry.Chain[0],
TBSCertificate: *c,
TBSCertificate: cert,
IssuerKeyHash: entry.Leaf.TimestampedEntry.PrecertEntry.IssuerKeyHash}
if s.opts.Matcher.PrecertificateMatches(precert) {
entry.Precert = precert

entry.IsPrecert = true
entry.RawCert = entry.Leaf.TimestampedEntry.PrecertEntry.TBSCertificate
entry.Precert = precert

if cert != nil {
if s.opts.Matcher.PrecertificateMatches(precert) {
foundPrecert(&entry, s.opts.Name)
}
} else {
foundPrecert(&entry, s.opts.Name)
}

s.precertsSeen++
}
}
Expand Down
16 changes: 10 additions & 6 deletions ct/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,16 @@ func (d *DigitallySigned) UnmarshalJSON(b []byte) error {

// LogEntry represents the contents of an entry in a CT log, see section 3.1.
type LogEntry struct {
Index int64
Leaf MerkleTreeLeaf
Index int64
Leaf MerkleTreeLeaf
RawCert []byte
IsPrecert bool
Chain []ASN1Cert
Server string
// When the raw cert is parseable, and not a precert,
// X509Cert contains the parsed certificate for convenience.
X509Cert *x509.Certificate
Precert *Precertificate
Chain []ASN1Cert
Server string
}

// SHA256Hash represents the output from the SHA256 hash function.
Expand Down Expand Up @@ -348,8 +352,8 @@ type Precertificate struct {
// SHA256 hash of the issuing key
IssuerKeyHash [issuerKeyHashLength]byte
// Parsed TBSCertificate structure (held in an x509.Certificate for ease of
// access.
TBSCertificate x509.Certificate
// access), when possible.
TBSCertificate *x509.Certificate
}

// X509Certificate returns the X.509 Certificate contained within the
Expand Down
1 change: 1 addition & 0 deletions ct/x509/sec1.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package x509
import (
"crypto/ecdsa"
"crypto/elliptic"

// START CT CHANGES
"github.com/zmap/zcrypto/ct/asn1"
// START CT CHANGES
Expand Down
25 changes: 25 additions & 0 deletions data/test/certificates/fpki.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,31 @@ fOs/QbP1b0s6Xq5vk3aY0vGZnUXEjnI=
-----END CERTIFICATE-----
`

// CorruptCertificate is a mangled certificate which is not valid ASN.1
const CorruptCertificate = `
-----BEGIN CERTIFICATE-----
MIFDczCCAlugAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY
MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT
A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xMjAzMjAxODQ2NDFaFw0y
OTEyMzAxODQ2NDFaMFsxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy
bm1lbnQFFFFFFFNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRYwFAYDVQQDEw1Eb0Qg
Um9vdCBDQSAzMIIBIjANBgQQQQQQQQQQQQQQAAOCAQ8AMIIBCgKCAQEAqewUcoro
S3Cj2hADhKb7pzYNKjpSFr8wFVKGBUcgz6qmzXXEZG7v8WAjywpmQK60yGgqAFFo
STfpWTJNlbxDJ+lAjToQzhS8Qxih+d7M54V2c14YGiNbvT8f8u2NGcwD0UCkj6cg
AkwnWnk29qM3IY4AWgYWytNVlm8xKbtyDsviSFHy1DekNdZv7hezsQarCxmG6CNt
MRsoeGXF3mJSvMF96+6gIHOPETHISWORKSGCTPC/unRAOwwERYBnXMXrolfDGn8K
Lb1/udzBmbDIB+QMhjaUOiUv8n3mlzwblLSXWQbJOuQL2erp/DtzNG/955jk86HC
kF8c9T8u1xnTfwIDAQABo0IwQDAdBgNVHQ4EFgQUbIqUonexgHIdgXoWqvLczmbu
RcAwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADggEBAJ9xpMC2ltKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASDFLiH+H
9Jj1qMYJyR/wLB/sgrj0pUc4wTMr30x+mr4LC7HLD3xQKBDPio2i6bqshtfUsZNf
Io+WBbRODHWRfdPy55TClBR2T48MqxCHWDKFB3WGEgte6lO0CshMhJIf6+hBhjy6
9E5BStFsWEdBw4Za8u7p8pgnguouNtb4Bl6C8aBSk0QJutKpGVpYo6hdIG1PZPgw
hxuQE0iBzcqQxw3B1Jg/jvIOV2gzEo6ZCbHw5PYQ9DbySb3qozjIVkEjg5rfoRs1
fOs/QbP1b0s6Xq5vk3aY0vGZnUXEjnI=
-----END CERTIFICATE-----
`

// HexHashDoDRootCA3SignedBySelf is the hex SHA256 fingerprint of
// DoDRootCA3SignedBySelf.
const HexHashDoDRootCA3SignedBySelf = "b107b33f453e5510f68e513110c6f6944bacc263df0137f821c1b3c2f8f863d2"
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.10.0
github.com/weppos/publicsuffix-go v0.40.3-0.20250127173806-e489a31678ca
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248
github.com/zmap/zcertificate v0.0.1
golang.org/x/crypto v0.32.0
golang.org/x/net v0.34.0
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ github.com/weppos/publicsuffix-go v0.40.3-0.20250127173806-e489a31678ca h1:Cno+V
github.com/weppos/publicsuffix-go v0.40.3-0.20250127173806-e489a31678ca/go.mod h1:43Dfyxu2dpmLg56at26Q4k9gwf3yWSUiwk8kGnwzULk=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 h1:Nzukz5fNOBIHOsnP+6I79kPx3QhLv8nBy2mfFhBRq30=
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is=
github.com/zmap/zcertificate v0.0.1 h1:2X15TRx4Fr6qzKItfwUdww294OeRSmHILLa+Xn2Uv+s=
github.com/zmap/zcertificate v0.0.1/go.mod h1:q0dlN54Jm4NVSSuzisusQY0hqDWvu92C+TWveAxiVWk=
Expand Down
65 changes: 65 additions & 0 deletions internal/cfg/cfg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package cfg holds configuration shared by the Go command and internal/testenv.
// Definitions that don't need to be exposed outside of cmd/go should be in
// cmd/go/internal/cfg instead of this package.
package cfg

// KnownEnv is a list of environment variables that affect the operation
// of the Go command.
const KnownEnv = `
AR
CC
CGO_CFLAGS
CGO_CFLAGS_ALLOW
CGO_CFLAGS_DISALLOW
CGO_CPPFLAGS
CGO_CPPFLAGS_ALLOW
CGO_CPPFLAGS_DISALLOW
CGO_CXXFLAGS
CGO_CXXFLAGS_ALLOW
CGO_CXXFLAGS_DISALLOW
CGO_ENABLED
CGO_FFLAGS
CGO_FFLAGS_ALLOW
CGO_FFLAGS_DISALLOW
CGO_LDFLAGS
CGO_LDFLAGS_ALLOW
CGO_LDFLAGS_DISALLOW
CXX
FC
GCCGO
GO111MODULE
GO386
GOARCH
GOARM
GOBIN
GOCACHE
GOENV
GOEXE
GOFLAGS
GOGCCFLAGS
GOHOSTARCH
GOHOSTOS
GOINSECURE
GOMIPS
GOMIPS64
GOMODCACHE
GONOPROXY
GONOSUMDB
GOOS
GOPATH
GOPPC64
GOPRIVATE
GOPROXY
GOROOT
GOSUMDB
GOTMPDIR
GOTOOLDIR
GOVCS
GOWASM
GO_EXTLINK_ENABLED
PKG_CONFIG
`
Loading
Loading