Skip to content

Commit e8fde3f

Browse files
committed
estimate_tile_size: Add a flag to simulate PQ embedded SCTs
Due to quirks of how CT got layered atop X.509, CT logs in practice log up to two copies of every certificate, a precertificate and a final certificate. When they log the final certificate, they have to log embedded SCTs. A hypothetical PQ CT would inflate those too. If we run that simulation, the estimated 5x increase from PQ goes up to 8.5x.
1 parent 0012b78 commit e8fde3f

1 file changed

Lines changed: 57 additions & 9 deletions

File tree

estimate_tile_size.go

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@ const (
3838
)
3939

4040
var (
41-
flagURL = flag.String("url", "", "the URL of the log to sample")
42-
flagSamples = flag.Int("samples", 5, "number of samples to run")
43-
flagFilterKeyIDs = flag.Bool("filter-key-id", false, "filter out SKID and AKID extensions")
44-
flagFilterAIA = flag.Bool("filter-aia", false, "filter out AIA extension")
41+
flagURL = flag.String("url", "", "the URL of the log to sample")
42+
flagSamples = flag.Int("samples", 5, "number of samples to run")
43+
flagFilterKeyIDs = flag.Bool("filter-key-id", false, "filter out SKID and AKID extensions")
44+
flagFilterAIA = flag.Bool("filter-aia", false, "filter out AIA extension")
45+
flagPQEmbeddedSCTs = flag.Bool("pq-embedded-scts", false, "simulate embedded SCTs getting upgraded to post-quantum")
4546

4647
// Put together some placeholder value based on https://www.ietf.org/archive/id/draft-davidben-tls-merkle-tree-certs-06.html#name-log-ids
4748
placeholderIssuer = []byte{0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x00, 0x0d, 0x04, 0xd6, 0x79, 0x09, 0x01}
@@ -152,6 +153,47 @@ func tbsCertLogEntryFromCert(cert *x509.Certificate) []byte {
152153
return b.BytesOrPanic()
153154
}
154155

156+
type embeddedSCTInfo struct {
157+
numSCTs int
158+
totSig int
159+
}
160+
161+
func parseEmbeddedSCTs(cert *x509.Certificate) (embeddedSCTInfo, error) {
162+
var info embeddedSCTInfo
163+
var ext *pkix.Extension
164+
for i := range cert.Extensions {
165+
if cert.Extensions[i].Id.Equal(oidSCTExtension) {
166+
ext = &cert.Extensions[i]
167+
break
168+
}
169+
}
170+
if ext == nil {
171+
return info, nil
172+
}
173+
174+
value := cryptobyte.String(ext.Value)
175+
var sctList, scts cryptobyte.String
176+
if !value.ReadASN1(&sctList, cbasn1.OCTET_STRING) || !value.Empty() ||
177+
!sctList.ReadUint16LengthPrefixed(&scts) || !sctList.Empty() ||
178+
scts.Empty() {
179+
return embeddedSCTInfo{}, fmt.Errorf("error parsing SCT extension")
180+
}
181+
for !scts.Empty() {
182+
var sct, ctExts, sig cryptobyte.String
183+
if !scts.ReadUint16LengthPrefixed(&sct) ||
184+
!sct.Skip(1+32+8) || // version, id, timestamp
185+
!sct.ReadUint16LengthPrefixed(&ctExts) ||
186+
!sct.Skip(2) || // sigalg
187+
!sct.ReadUint16LengthPrefixed(&sig) ||
188+
!sct.Empty() {
189+
return embeddedSCTInfo{}, fmt.Errorf("error parsing SCT extension")
190+
}
191+
info.numSCTs++
192+
info.totSig += len(sig)
193+
}
194+
return info, nil
195+
}
196+
155197
func fetchTreeSize(baseURL *url.URL) (int, error) {
156198
resp, err := http.Get(baseURL.JoinPath("checkpoint").String())
157199
if err != nil {
@@ -244,6 +286,7 @@ func do() error {
244286
fmt.Printf("Sampling from log %s\n", *flagURL)
245287
fmt.Printf("Filtering AIA in simulated MTC tiles: %t\n", *flagFilterAIA)
246288
fmt.Printf("Filtering SKID/AKID in simulated MTC tiles: %t\n", *flagFilterKeyIDs)
289+
fmt.Printf("Including embedded SCTs in PQ simulation: %t\n", *flagPQEmbeddedSCTs)
247290

248291
treeSize, err := fetchTreeSize(baseURL)
249292
if err != nil {
@@ -278,14 +321,19 @@ func do() error {
278321
pqIncrease := 0
279322
b := cryptobyte.NewBuilder(nil)
280323
for _, cert := range certs {
324+
scts, err := parseEmbeddedSCTs(cert)
325+
if err != nil {
326+
return err
327+
}
328+
281329
// As a very, very rough estimate of the status quo with PQ,
282-
// subtract the size of the SPKI and the signature, then replace
283-
// them with ML-DSA-44.
284-
//
285-
// This is actually an underestimate because embedded SCTs end up in
286-
// logs today.
330+
// simulate replacing the leaf SPKI, leaf signature, and embedded
331+
// SCT signatures with ML-DSA-44.
287332
pqIncrease += mldsaPublicKey - len(cert.RawSubjectPublicKeyInfo)
288333
pqIncrease += mldsaSignature - len(cert.Signature)
334+
if *flagPQEmbeddedSCTs {
335+
pqIncrease += scts.numSCTs*mldsaSignature - scts.totSig
336+
}
289337

290338
// Construct the new tiles.
291339
entry := tbsCertLogEntryFromCert(cert)

0 commit comments

Comments
 (0)