1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ct
16
17 import (
18 "bytes"
19 "encoding/hex"
20 "encoding/pem"
21 "os"
22 "reflect"
23 "strings"
24 "testing"
25
26 "github.com/google/certificate-transparency-go/tls"
27 )
28
29 func dh(h string) []byte {
30 r, err := hex.DecodeString(h)
31 if err != nil {
32 panic(err)
33 }
34 return r
35 }
36
37 const (
38 defaultSCTLogIDString string = "iamapublickeyshatwofivesixdigest"
39 defaultSCTTimestamp uint64 = 1234
40 defaultSCTSignatureString string = "\x04\x03\x00\x09signature"
41 defaultCertifictateString string = "certificate"
42 defaultPrecertIssuerHashString string = "iamapublickeyshatwofivesixdigest"
43 defaultPrecertTBSString string = "tbs"
44
45 defaultCertificateSCTSignatureInputHexString string =
46
47 "00" +
48
49 "00" +
50
51 "00000000000004d2" +
52
53 "0000" +
54
55 "00000b" +
56
57 "6365727469666963617465" +
58
59 "0000" +
60
61 ""
62
63 defaultPrecertSCTSignatureInputHexString string =
64
65 "00" +
66
67 "00" +
68
69 "00000000000004d2" +
70
71 "0001" +
72
73 "69616d617075626c69636b657973686174776f66697665736978646967657374" +
74
75 "000003" +
76
77 "746273" +
78
79 "0000" +
80
81 ""
82
83 defaultSTHSignedHexString string =
84
85 "00" +
86
87 "01" +
88
89 "0000000000000929" +
90
91 "0000000000000006" +
92
93 "696d757374626565786163746c7974686972747974776f62797465736c6f6e67"
94
95 defaultSCTHexString string =
96
97 "00" +
98
99 "69616d617075626c69636b657973686174776f66697665736978646967657374" +
100
101 "00000000000004d2" +
102
103 "0000" +
104
105
106 "0403" +
107
108 "0009" +
109
110 "7369676e6174757265"
111 )
112
113 func defaultSCTLogID() LogID {
114 var id LogID
115 copy(id.KeyID[:], defaultSCTLogIDString)
116 return id
117 }
118
119 func defaultSCTSignature() DigitallySigned {
120 var ds DigitallySigned
121 if _, err := tls.Unmarshal([]byte(defaultSCTSignatureString), &ds); err != nil {
122 panic(err)
123 }
124 return ds
125 }
126
127 func defaultSCT() SignedCertificateTimestamp {
128 return SignedCertificateTimestamp{
129 SCTVersion: V1,
130 LogID: defaultSCTLogID(),
131 Timestamp: defaultSCTTimestamp,
132 Extensions: []byte{},
133 Signature: defaultSCTSignature()}
134 }
135
136 func defaultCertificate() []byte {
137 return []byte(defaultCertifictateString)
138 }
139
140 func defaultCertificateSCTSignatureInput(t *testing.T) []byte {
141 t.Helper()
142 r, err := hex.DecodeString(defaultCertificateSCTSignatureInputHexString)
143 if err != nil {
144 t.Fatalf("failed to decode defaultCertificateSCTSignatureInputHexString: %v", err)
145 }
146 return r
147 }
148
149 func defaultCertificateLogEntry() LogEntry {
150 return LogEntry{
151 Index: 1,
152 Leaf: MerkleTreeLeaf{
153 Version: V1,
154 LeafType: TimestampedEntryLeafType,
155 TimestampedEntry: &TimestampedEntry{
156 Timestamp: defaultSCTTimestamp,
157 EntryType: X509LogEntryType,
158 X509Entry: &ASN1Cert{Data: defaultCertificate()},
159 },
160 },
161 }
162 }
163
164 func defaultPrecertSCTSignatureInput(t *testing.T) []byte {
165 t.Helper()
166 r, err := hex.DecodeString(defaultPrecertSCTSignatureInputHexString)
167 if err != nil {
168 t.Fatalf("failed to decode defaultPrecertSCTSignatureInputHexString: %v", err)
169 }
170 return r
171 }
172
173 func defaultPrecertTBS() []byte {
174 return []byte(defaultPrecertTBSString)
175 }
176
177 func defaultPrecertIssuerHash() [32]byte {
178 var b [32]byte
179 copy(b[:], []byte(defaultPrecertIssuerHashString))
180 return b
181 }
182
183 func defaultPrecertLogEntry() LogEntry {
184 return LogEntry{
185 Index: 1,
186 Leaf: MerkleTreeLeaf{
187 Version: V1,
188 LeafType: TimestampedEntryLeafType,
189 TimestampedEntry: &TimestampedEntry{
190 Timestamp: defaultSCTTimestamp,
191 EntryType: PrecertLogEntryType,
192 PrecertEntry: &PreCert{
193 IssuerKeyHash: defaultPrecertIssuerHash(),
194 TBSCertificate: defaultPrecertTBS(),
195 },
196 },
197 },
198 }
199 }
200
201 func defaultSTH() SignedTreeHead {
202 var root SHA256Hash
203 copy(root[:], "imustbeexactlythirtytwobyteslong")
204 return SignedTreeHead{
205 TreeSize: 6,
206 Timestamp: 2345,
207 SHA256RootHash: root,
208 TreeHeadSignature: DigitallySigned{
209 Algorithm: tls.SignatureAndHashAlgorithm{
210 Hash: tls.SHA256,
211 Signature: tls.ECDSA},
212 Signature: []byte("tree_signature"),
213 },
214 }
215 }
216
217
218
219
220
221 func TestSerializeV1SCTSignatureInputForCertificateKAT(t *testing.T) {
222 serialized, err := SerializeSCTSignatureInput(defaultSCT(), defaultCertificateLogEntry())
223 if err != nil {
224 t.Fatalf("Failed to serialize SCT for signing: %v", err)
225 }
226 if !bytes.Equal(serialized, defaultCertificateSCTSignatureInput(t)) {
227 t.Fatalf("Serialized certificate signature input doesn't match expected answer:\n%v\n%v", serialized, defaultCertificateSCTSignatureInput(t))
228 }
229 }
230
231 func TestSerializeV1SCTSignatureInputForPrecertKAT(t *testing.T) {
232 serialized, err := SerializeSCTSignatureInput(defaultSCT(), defaultPrecertLogEntry())
233 if err != nil {
234 t.Fatalf("Failed to serialize SCT for signing: %v", err)
235 }
236 if !bytes.Equal(serialized, defaultPrecertSCTSignatureInput(t)) {
237 t.Fatalf("Serialized precertificate signature input doesn't match expected answer:\n%v\n%v", serialized, defaultPrecertSCTSignatureInput(t))
238 }
239 }
240
241 func TestSerializeV1STHSignatureKAT(t *testing.T) {
242 b, err := SerializeSTHSignatureInput(defaultSTH())
243 if err != nil {
244 t.Fatalf("Failed to serialize defaultSTH: %v", err)
245 }
246 if !bytes.Equal(b, mustDehex(t, defaultSTHSignedHexString)) {
247 t.Fatalf("defaultSTH incorrectly serialized, expected:\n%v\ngot:\n%v", mustDehex(t, defaultSTHSignedHexString), b)
248 }
249 }
250
251 func TestMarshalDigitallySigned(t *testing.T) {
252 b, err := tls.Marshal(
253 DigitallySigned{
254 Algorithm: tls.SignatureAndHashAlgorithm{
255 Hash: tls.SHA512,
256 Signature: tls.ECDSA},
257 Signature: []byte("signature")})
258 if err != nil {
259 t.Fatalf("Failed to marshal DigitallySigned struct: %v", err)
260 }
261 if b[0] != byte(tls.SHA512) {
262 t.Fatalf("Expected b[0] == SHA512, but found %v", tls.HashAlgorithm(b[0]))
263 }
264 if b[1] != byte(tls.ECDSA) {
265 t.Fatalf("Expected b[1] == ECDSA, but found %v", tls.SignatureAlgorithm(b[1]))
266 }
267 if b[2] != 0x00 || b[3] != 0x09 {
268 t.Fatalf("Found incorrect length bytes, expected (0x00, 0x09) found %v", b[2:3])
269 }
270 if string(b[4:]) != "signature" {
271 t.Fatalf("Found incorrect signature bytes, expected %v, found %v", []byte("signature"), b[4:])
272 }
273 }
274
275 func TestUnmarshalDigitallySigned(t *testing.T) {
276 var ds DigitallySigned
277 if _, err := tls.Unmarshal([]byte("\x01\x02\x00\x0aSiGnAtUrE!"), &ds); err != nil {
278 t.Fatalf("Failed to unmarshal DigitallySigned: %v", err)
279 }
280 if ds.Algorithm.Hash != tls.MD5 {
281 t.Fatalf("Expected HashAlgorithm %v, but got %v", tls.MD5, ds.Algorithm.Hash)
282 }
283 if ds.Algorithm.Signature != tls.DSA {
284 t.Fatalf("Expected SignatureAlgorithm %v, but got %v", tls.DSA, ds.Algorithm.Signature)
285 }
286 if string(ds.Signature) != "SiGnAtUrE!" {
287 t.Fatalf("Expected Signature %v, but got %v", []byte("SiGnAtUrE!"), ds.Signature)
288 }
289 }
290
291 func TestMarshalUnmarshalSCTRoundTrip(t *testing.T) {
292 sctIn := defaultSCT()
293 b, err := tls.Marshal(sctIn)
294 if err != nil {
295 t.Fatalf("tls.Marshal(SCT)=nil,%v; want no error", err)
296 }
297 var sctOut SignedCertificateTimestamp
298 if _, err := tls.Unmarshal(b, &sctOut); err != nil {
299 t.Errorf("tls.Unmarshal(%s)=nil,%v; want %+v,nil", hex.EncodeToString(b), err, sctIn)
300 } else if !reflect.DeepEqual(sctIn, sctOut) {
301 t.Errorf("tls.Unmarshal(%s)=%v,nil; want %+v,nil", hex.EncodeToString(b), sctOut, sctIn)
302 }
303 }
304
305 func TestMarshalSCT(t *testing.T) {
306 b, err := tls.Marshal(defaultSCT())
307 if err != nil {
308 t.Errorf("tls.Marshal(defaultSCT)=nil,%v; want %s", err, defaultSCTHexString)
309 } else if !bytes.Equal(dh(defaultSCTHexString), b) {
310 t.Errorf("tls.Marshal(defaultSCT)=%s,nil; want %s", hex.EncodeToString(b), defaultSCTHexString)
311 }
312 }
313
314 func TestUnmarshalSCT(t *testing.T) {
315 want := defaultSCT()
316 var got SignedCertificateTimestamp
317 if _, err := tls.Unmarshal(dh(defaultSCTHexString), &got); err != nil {
318 t.Errorf("tls.Unmarshal(%s)=nil,%v; want %+v,nil", defaultSCTHexString, err, want)
319 } else if !reflect.DeepEqual(got, want) {
320 t.Errorf("tls.Unmarshal(%s)=%+v,nil; want %+v,nil", defaultSCTHexString, got, want)
321 }
322 }
323
324 func TestX509MerkleTreeLeafHash(t *testing.T) {
325 certFile := "./testdata/test-cert.pem"
326 sctFile := "./testdata/test-cert.proof"
327 certB, err := os.ReadFile(certFile)
328 if err != nil {
329 t.Fatalf("Failed to read file %s: %v", certFile, err)
330 }
331 certDER, _ := pem.Decode(certB)
332
333 sctB, err := os.ReadFile(sctFile)
334 if err != nil {
335 t.Fatalf("Failed to read file %s: %v", sctFile, err)
336 }
337 var sct SignedCertificateTimestamp
338 if _, err := tls.Unmarshal(sctB, &sct); err != nil {
339 t.Fatalf("Failed to deserialize SCT: %v", err)
340 }
341
342 leaf := CreateX509MerkleTreeLeaf(ASN1Cert{Data: certDER.Bytes}, sct.Timestamp)
343 b, err := tls.Marshal(*leaf)
344 if err != nil {
345 t.Fatalf("Failed to Serialize x509 leaf: %v", err)
346 }
347
348 leafBytes := dh("00000000013ddb27ded900000002ce308202ca30820233a003020102020106300d06092a864886f70d01010505003055310b300906035504061302474231243022060355040a131b4365727469666963617465205472616e73706172656e6379204341310e300c0603550408130557616c65733110300e060355040713074572772057656e301e170d3132303630313030303030305a170d3232303630313030303030305a3052310b30090603550406130247423121301f060355040a13184365727469666963617465205472616e73706172656e6379310e300c0603550408130557616c65733110300e060355040713074572772057656e30819f300d06092a864886f70d010101050003818d0030818902818100b1fa37936111f8792da2081c3fe41925008531dc7f2c657bd9e1de4704160b4c9f19d54ada4470404c1c51341b8f1f7538dddd28d9aca48369fc5646ddcc7617f8168aae5b41d43331fca2dadfc804d57208949061f9eef902ca47ce88c644e000f06eeeccabdc9dd2f68a22ccb09dc76e0dbc73527765b1a37a8c676253dcc10203010001a381ac3081a9301d0603551d0e041604146a0d982a3b62c44b6d2ef4e9bb7a01aa9cb798e2307d0603551d230476307480145f9d880dc873e654d4f80dd8e6b0c124b447c355a159a4573055310b300906035504061302474231243022060355040a131b4365727469666963617465205472616e73706172656e6379204341310e300c0603550408130557616c65733110300e060355040713074572772057656e82010030090603551d1304023000300d06092a864886f70d010105050003818100171cd84aac414a9a030f22aac8f688b081b2709b848b4e5511406cd707fed028597a9faefc2eee2978d633aaac14ed3235197da87e0f71b8875f1ac9e78b281749ddedd007e3ecf50645f8cbf667256cd6a1647b5e13203bb8582de7d6696f656d1c60b95f456b7fcf338571908f1c69727d24c4fccd249295795814d1dac0e60000")
349 if !bytes.Equal(b, leafBytes) {
350 t.Errorf("CreateX509MerkleTreeLeaf(): got\n %x, want\n%x", b, sctB)
351 }
352
353 }
354
355 func TestLogEntryFromLeaf(t *testing.T) {
356 const (
357
358 leafDER = "308204ef308202d7a00302010202070556658a503cca300d06092a864886f70d01010b0500307f310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793123302106035504030c1a4d657267652044656c617920496e7465726d6564696174652031301e170d3137303831303132343331355a170d3138303333313038333231375a3063310b3009060355040613024742310f300d06035504070c064c6f6e646f6e31283026060355040a0c1f476f6f676c65204365727469666963617465205472616e73706172656e637931193017060355040513103135303233363839393537353331363230820122300d06092a864886f70d01010105000382010f003082010a0282010100a2fb53365dfbcefea77e1d65bc40f34f7919fcae85d82d3003428199f0c893fca95ba139156fd5e9a3bd84dc6dab8e74151fde6dd25b31526c85719bbf8990f3d6b21bb7f321306f6ddc50b96e8917fa103b388a00e1e954ee0232a9f9fb2efa8c9f9196a7fe84dad1f66b5d36127c71c9dcf25a04acd7bfda7866dfb77498c63a7ae9e7d0772fe9ba938a9ff6c0209196988158e6ea055fe967dd7599ef4bd7f306ded231cca10d89b4d6de40916e615d1d4cc6032585822a650743e34735d464fc0d544d1fad8c293df22f4a55ce3fbfb55d90cdc5ab84695a5a13d46f3176f143d9d28f60dca841eac603d30cec830a62feec091c927e6c781df330f14ca10203010001a3818b30818830130603551d25040c300a06082b0601050507030130230603551d11041c301a8218666c6f776572732d746f2d7468652d776f726c642e636f6d300c0603551d130101ff04023000301f0603551d23041830168014e93c04e1802fc284132d26709ef2fd1acfaafec6301d0603551d0e041604142f3948061fe546939f5e8dbc3fe4c0a1fbaab6b7300d06092a864886f70d01010b0500038202010052a2480c754c51cfdc9f99a82a8eb7c34e5e2bdcdfdd7543fadadb578083416d34ebb87fea3c90baf97f06be5baf5c41101ad1bdd2a2f554de6a3e8cd5ff3d78354badad01032a007d2eaf03590ee5397e223b2936f0c8b59c0407079c8975ffb34eb1cfe784cf3bc45e198a601473537f1ef382e0b5311d2ddf430ade7cfd28900ec9d91c1db49a6b2fb1b9e13b94135fed978d646e048b2fa9dc36ef5821cea8ebbed38d4c2d7811e9660f23d7636b295caccdc945a010a4c364fd7e7480aa5282d28fc46ce7f4f636ef2cc57c8bb1aee5da79bc6107205d4abcd3fb09a1db023ba4e8e9f34ae36ff5b2672fc2a14af8d23d67a437b3eb507ca90f73121841ab1498ab712d18063244dc3514bfffbaf6d45acdfc5316a248589a04b79b2abbca454e2e21f9b487e21eea21565c99ebc1013b87253c91f43ac6d2d2dea7090877c2a7404bce2545662ce005dc12eb57b1efe7145af8070b5dfa86736664a644a9c0f7e7c38d715cf874b818d519927eddc69b55c781b6e0a6eef8f3e46b9e059105b7932a978704e924904dbaa9583f3dd606467f4cc41589b702f1a02d517d3cd93b55d67d0b379e2527fded951be9dfb86d473613e6d9b8399ef5174d3e03185bd3cb4ea859b465c6c49010d4119d613a60878c0e453f17cfa3ce925e10f6e0a5adb745cebe218c3c82627a120e2907eeb9ec5307664474093cbc92d65fc7"
359 leafCA = "308205c8308203b0a00302010202021001300d06092a864886f70d0101050500307d310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793121301f06035504030c184d657267652044656c6179204d6f6e69746f7220526f6f74301e170d3134303731373132323633305a170d3139303731363132323633305a307f310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793123302106035504030c1a4d657267652044656c617920496e7465726d656469617465203130820222300d06092a864886f70d01010105000382020f003082020a0282020100c1e874feff9aeef303bbfa63453881faaf8dc1c22c09641daf430381f33bc157bf6c4c8a8d57b1abc792859d20f2191509c597c437b14673dea5af4bea14396dd436dc620555d7953e0ede01f7ffb44f3ff7cde64ed245634e0df0aafce9c3ac5eb63d8de1d969cac8854195403a9f9d1d4c3dceedf1351edd945743bc54ab745b204fb5259fe3edf695c2cf90b886c48ff680b744fec2691b4345242b31c36f3118b727c5de5c25ec1aa30a4c2461c5119ef6bb90d816e6e44c5b9955bfa2ed3416bf6e4a53c92fafac0d1f0b8bf3d35be0d4f61ca05d28fc662dfa588fba3ee0380470c012ded9e51bbf1e7a25efa745784c49d05eaf8dcee0527361ec913126005e972cf4b863914f8361582ed24563ff9e03c52e8a9ca3264c56c186b4ec52b7e695ce42ae17ec7ae0257131e1dbf48f2dde242e6e91ea304988135a15482b05fc091355328b39e586e8dd3a4a3a14cb97eef68f9f69728c291f2195d2cce73d4ae90845b1bfc5fae040b94fc359a29511981b9966aeb56d3a7c5e48f8eca815e5be86b3d36e6a27e0e2c4dee6e30f12a7c936b8c98cad5928aca238dfc39cf9f2c5246cbbbb280cb6f99eb49bfd1d78089539072c164c7083371746dedbc4dec1cb9439073af3f2e60f8c505f067961a8c539454fc5341158eccc78532f3e39c3187c9439fc0ff88ee957131d478df063dd50b2ad3fe7a070e905e3868b0203010001a350304e301d0603551d0e04160414e93c04e1802fc284132d26709ef2fd1acfaafec6301f0603551d23041830168014f35f7b7549e37841396a20b67c6b4c5cc93d5841300c0603551d13040530030101ff300d06092a864886f70d010105050003820201000858cbd545f2e92e09906ac39f3d55c13607a651436386c6e90f128773a0eb3f4725d8af35fb7f880436b481f2cf47801825de54f13f8f5920bf3d916e753141de5e59d2debbfc3fc226721f15a16d3b7a4618ea0551639f1d2cb7b9faad1b7e070f23a6e8197c3d7549bba6553fd5db419ce399477f6a0481b90f51c9d307d82cb05cf967828a1ace65207cf86b6d16792245dcf24b4c179f91184736e7e2fcb863a4b5c89b0ac2f368390a10594b95c856e259c77564316898cf87a6817d18585fc976d681d9d510ef2ad37e8ad0e49f5bd499c9ec7fe8f43b17dffb9b7d0dfd8300c1c5389c9ea0be4370dcbf78bd3efc2308d250b866bbca031c0c49ff77a7a5420daa1f1b6a444d366653974c2d179c3009871ee6c89140fca9efdf23bd4b88c6ebaeb9286f58f3cfc21e4874f182d1ecd6058919b03b18db7b795be9cb25fc5166a945ef8e1133cd60312a3234f4649df6166407cbb5ecc838e9e118c05dee7c896a9987655ae7e349cd8166e68d34dea3b4ae892a9f2385053271e860b542be3650503974f3bb6f2688375ab28487da6751d0f2c3a35e78efe30b19d57808ebea2c4453990ad81eb96289c0f99c5080f82092bc6123a340c63a617f3bc4adc1298d88a278a693ef93688611d3b4eded0b6d023ed9f6c2ea8836483197525b1b1bce70a90c3403b094d5f412aa1141b9965ab8314c52f772deffc1008c"
360 rootCA = "308205cd308203b5a0030201020209009ed3ccb1d12ca272300d06092a864886f70d0101050500307d310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793121301f06035504030c184d657267652044656c6179204d6f6e69746f7220526f6f74301e170d3134303731373132303534335a170d3431313230323132303534335a307d310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793121301f06035504030c184d657267652044656c6179204d6f6e69746f7220526f6f7430820222300d06092a864886f70d01010105000382020f003082020a0282020100aa161cf2205ed81ac565483cda426a3db2e588fdb758b17b93ea8d68495d534a01ba4f6cd1c0fc0a128af79c066dc54c3f437e05ba275ee61dbf9cbdb2928183738139397b6189ae738fef2b9b609a6dd8e0b0d0e20b243db936c029cdc2220af2c0e1a5e4aa41a006af458957e2b1178d27156ef0cb717e16d54025d97f43e9916fb240fb85f7d579462fa0ac76c76256843750bf1ccdfeb76c8c47886477644d5ec3235628adf6a09c8488bfa5036de717908151a6b585f273dd9fb5332b9af76e8fbfa91eaf4311816dde27c5c44f2fd06cc2204d7147f77ba6b16a2a5fca470023614729538bee6b3cb07264713832aec161550eb501906802215223acc2564ad1f98bb5934924eb56d383fc7598be45c89d995281c0efb0d206d29a6d25a10a48fe235332379c5ca69e83599faa677dd20823f5c84a961255eca5d4871d54ca1df0774aa117b0f42cd6e9fda7e8a48a53923c5f94043353544e644b5a6562e5cef9fc2bd2fcfcce3323335cf7fe7c4d83c1b7f839c4790192d3ba9aa9f32093aa8ee7cbe708059d538dc663cca1b825331aa836754a0d13de63bf65b6e2044dcdf041f1a0c5a9c3c38fe74cf576d451c23eaa519db32ef9e039bd848a194c3b5e41a55642dc283ddbd73d1dd97ae6951de18ad89d005007fae7e88bc7a3cce8b7ccc49603a0db67c76d58a28d4b77aa7460801e34377d0c5e4606c2e25b0203010001a350304e301d0603551d0e04160414f35f7b7549e37841396a20b67c6b4c5cc93d5841301f0603551d23041830168014f35f7b7549e37841396a20b67c6b4c5cc93d5841300c0603551d13040530030101ff300d06092a864886f70d01010505000382020100771cfea34579a97520d8c2423d68ecd07891f8c7f1c38bf3cd30ea9d3637bfc5d373532ec7656558bef4950646750c6fe085c52d9ffc09e66ebfa2b067de7727cb381d2b25db58b9c2197fd5eb53e020f429b86a3b1f37a07a761a66a5b3ecd797c46695a37ff2d47c54126be6bd28a2a103357227c6b73f7f689b09b48927e6e9a52267a728a115d4bcbb477533dc28f3fc57da735a3ec54fbc36990b17febb7e46b324208c1fa7425a0cba48bdc0381ea8285215261c3c483f2fa6d1da0dba4949107189f32d728a7ff395d43430af3b8ce4be5075bcf67d66661941dc8be37340f8f9282b2d2aadd69065932ad49769f8bc7fc9e5f6e79ff392420ba78de3172778e2b67e4df18440dd561e5a7844c8efa06c0e5f5b8695fa069114a00518fb4c19f9d7855831b5eeebced14b8598daffa49f2dcf505bff6417d84b28e83599d4e0371ef64b2d82ffa068a31044f7322fee2f654ec357c9c121f3458a509728c37f5673412ad0d5e76aa6b4eb1582181a8be404d3dc35e71edd83ee388087d6147c4d86f1cacacface0104df1f4b100c2ceb1be4d1851c4f31e7c4409262185878f23cceb30790143f0d5bd80d2c0ed4260aaa312597d950aaf3c8bcfc812d9a56e8d160dd772a494743710a7e478a046d8a5d505ee6b8cc37fec09dfd4cb57c6c4d8e8ef2a22e1d9e50957852633138d722253e51ba77b0069d38812207a"
361 noExts = "0000"
362
363 issuerKeyHash = "e37689003073a0c649cc656de946c03174d25c566fe3c3805b846f5236943798"
364 precertTBS = "0002db308202d7a0030201020207055667377e8bcc300d06092a864886f70d01010b0500307f310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793123302106035504030c1a4d657267652044656c617920496e7465726d6564696174652031301e170d3137303831303134343331365a170d3138303432363134323430315a3063310b3009060355040613024742310f300d06035504070c064c6f6e646f6e31283026060355040a0c1f476f6f676c65204365727469666963617465205472616e73706172656e637931193017060355040513103135303233373631393632313337303830820122300d06092a864886f70d01010105000382010f003082010a0282010100dea100ff02f31ae6f76f9c26525afcdd0ef6eef780d72b4b1c0ff14fc7ac021852d6f34af20713d05fea2c2e1a4b488b3849c2511cf30fcd2e61d9e7392557498a4ff600c8fdc912f05c8a583a5f2b6a3d3320c6cc10b7eed502de392d11b3c4d57fa6e3ddc69d3f73305bb6441a0359bd526272784523ae5319cffd2993abba54d26c4c1b760c8660b65161a349e415207a6fbb20d02ce13054e6ffa7776bccfd26c3e4220e0e504f102f352260aaa9864411f7eeae8f6071c9ba54b83d11af43ab58dcb6a7d9053654b98b165fb84a27c78361d957c70a064f45bf4501ef744302e497839a34222e94b3018e587c70c130208976d9f80cf6741a95abfa6b810203010001a3818b30818830130603551d25040c300a06082b0601050507030130230603551d11041c301a8218666c6f776572732d746f2d7468652d776f726c642e636f6d300c0603551d130101ff04023000301f0603551d23041830168014e93c04e1802fc284132d26709ef2fd1acfaafec6301d0603551d0e04160414df25c220250d548e08341c26cadc5effc177841c"
365 precertDER = "30820504308202eca0030201020207055667377e8bcc300d06092a864886f70d01010b0500307f310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793123302106035504030c1a4d657267652044656c617920496e7465726d6564696174652031301e170d3137303831303134343331365a170d3138303432363134323430315a3063310b3009060355040613024742310f300d06035504070c064c6f6e646f6e31283026060355040a0c1f476f6f676c65204365727469666963617465205472616e73706172656e637931193017060355040513103135303233373631393632313337303830820122300d06092a864886f70d01010105000382010f003082010a0282010100dea100ff02f31ae6f76f9c26525afcdd0ef6eef780d72b4b1c0ff14fc7ac021852d6f34af20713d05fea2c2e1a4b488b3849c2511cf30fcd2e61d9e7392557498a4ff600c8fdc912f05c8a583a5f2b6a3d3320c6cc10b7eed502de392d11b3c4d57fa6e3ddc69d3f73305bb6441a0359bd526272784523ae5319cffd2993abba54d26c4c1b760c8660b65161a349e415207a6fbb20d02ce13054e6ffa7776bccfd26c3e4220e0e504f102f352260aaa9864411f7eeae8f6071c9ba54b83d11af43ab58dcb6a7d9053654b98b165fb84a27c78361d957c70a064f45bf4501ef744302e497839a34222e94b3018e587c70c130208976d9f80cf6741a95abfa6b810203010001a381a030819d30130603551d25040c300a06082b0601050507030130230603551d11041c301a8218666c6f776572732d746f2d7468652d776f726c642e636f6d300c0603551d130101ff04023000301f0603551d23041830168014e93c04e1802fc284132d26709ef2fd1acfaafec6301d0603551d0e04160414df25c220250d548e08341c26cadc5effc177841c3013060a2b06010401d6790204030101ff04020500300d06092a864886f70d01010b05000382020100ae9ca16ec19bb469d08628b1296f50e3e15b362e2b18c691b11eef3af9ce655bf74e0c21c84f6091132851ba78465c3ae97a1409ee7505395d4e7e0318189029a12bf1c3ba2b6f3231c7aac13dbbfaade8d56f0fbe91d32440ad0ab816184c72392154275ead8418cc62e4e2b08de1b14acb6b27c0f36fa586feb875666f46d232a32ef022440d52cdd8bd31a42de55bfa77de8742816f086830b07eedbde545af5a2b9dd17bd49ded508589a0673f6e0d55f210818422093fd10939f0c81521ca654958e6e01b76ef8c7380bdb331e67d44ccb18a83ed04d97d463c37c7cbc592768e2373e198a1d64be3bd22d1833994706797461d05a85e779cd6e2b4b2b14e81d1eca454f29780c47a7366041ace1a48319eff3f1f04bbd471d5125774ef050e47bf664a98101b7be3337bb786b760a92be46488c6a15f72972a4b7c932c736311f0ac1d40920580329657f00e26cfb6d3b1db1eb7a95952fbcbfcbaf9d17587f03aeb9c3b403d1dccad895316658d35fe385fc5a62b60db36e3f07c4798314936aeb3f40094aee9ec1350ea8f68d1aeb41b211ecd0c9e29c5fa2d6576bcb2ad5ec8cc936e1f5a127afa0de3ae490b914adaa733f18ed9348d497e10ba4aa3008f84deec6976292dc0d3c2aa523602188916dd468b47f3d571e71fe51cd293c805d1280a53ab9f519a616d889303be461354edfc29dc3cc85d8570264cf4"
366 precertCA = "308205c8308203b0a00302010202021001300d06092a864886f70d0101050500307d310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793121301f06035504030c184d657267652044656c6179204d6f6e69746f7220526f6f74301e170d3134303731373132323633305a170d3139303731363132323633305a307f310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793123302106035504030c1a4d657267652044656c617920496e7465726d656469617465203130820222300d06092a864886f70d01010105000382020f003082020a0282020100c1e874feff9aeef303bbfa63453881faaf8dc1c22c09641daf430381f33bc157bf6c4c8a8d57b1abc792859d20f2191509c597c437b14673dea5af4bea14396dd436dc620555d7953e0ede01f7ffb44f3ff7cde64ed245634e0df0aafce9c3ac5eb63d8de1d969cac8854195403a9f9d1d4c3dceedf1351edd945743bc54ab745b204fb5259fe3edf695c2cf90b886c48ff680b744fec2691b4345242b31c36f3118b727c5de5c25ec1aa30a4c2461c5119ef6bb90d816e6e44c5b9955bfa2ed3416bf6e4a53c92fafac0d1f0b8bf3d35be0d4f61ca05d28fc662dfa588fba3ee0380470c012ded9e51bbf1e7a25efa745784c49d05eaf8dcee0527361ec913126005e972cf4b863914f8361582ed24563ff9e03c52e8a9ca3264c56c186b4ec52b7e695ce42ae17ec7ae0257131e1dbf48f2dde242e6e91ea304988135a15482b05fc091355328b39e586e8dd3a4a3a14cb97eef68f9f69728c291f2195d2cce73d4ae90845b1bfc5fae040b94fc359a29511981b9966aeb56d3a7c5e48f8eca815e5be86b3d36e6a27e0e2c4dee6e30f12a7c936b8c98cad5928aca238dfc39cf9f2c5246cbbbb280cb6f99eb49bfd1d78089539072c164c7083371746dedbc4dec1cb9439073af3f2e60f8c505f067961a8c539454fc5341158eccc78532f3e39c3187c9439fc0ff88ee957131d478df063dd50b2ad3fe7a070e905e3868b0203010001a350304e301d0603551d0e04160414e93c04e1802fc284132d26709ef2fd1acfaafec6301f0603551d23041830168014f35f7b7549e37841396a20b67c6b4c5cc93d5841300c0603551d13040530030101ff300d06092a864886f70d010105050003820201000858cbd545f2e92e09906ac39f3d55c13607a651436386c6e90f128773a0eb3f4725d8af35fb7f880436b481f2cf47801825de54f13f8f5920bf3d916e753141de5e59d2debbfc3fc226721f15a16d3b7a4618ea0551639f1d2cb7b9faad1b7e070f23a6e8197c3d7549bba6553fd5db419ce399477f6a0481b90f51c9d307d82cb05cf967828a1ace65207cf86b6d16792245dcf24b4c179f91184736e7e2fcb863a4b5c89b0ac2f368390a10594b95c856e259c77564316898cf87a6817d18585fc976d681d9d510ef2ad37e8ad0e49f5bd499c9ec7fe8f43b17dffb9b7d0dfd8300c1c5389c9ea0be4370dcbf78bd3efc2308d250b866bbca031c0c49ff77a7a5420daa1f1b6a444d366653974c2d179c3009871ee6c89140fca9efdf23bd4b88c6ebaeb9286f58f3cfc21e4874f182d1ecd6058919b03b18db7b795be9cb25fc5166a945ef8e1133cd60312a3234f4649df6166407cbb5ecc838e9e118c05dee7c896a9987655ae7e349cd8166e68d34dea3b4ae892a9f2385053271e860b542be3650503974f3bb6f2688375ab28487da6751d0f2c3a35e78efe30b19d57808ebea2c4453990ad81eb96289c0f99c5080f82092bc6123a340c63a617f3bc4adc1298d88a278a693ef93688611d3b4eded0b6d023ed9f6c2ea8836483197525b1b1bce70a90c3403b094d5f412aa1141b9965ab8314c52f772deffc1008c"
367 precertRoot = "308205cd308203b5a0030201020209009ed3ccb1d12ca272300d06092a864886f70d0101050500307d310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793121301f06035504030c184d657267652044656c6179204d6f6e69746f7220526f6f74301e170d3134303731373132303534335a170d3431313230323132303534335a307d310b3009060355040613024742310f300d06035504080c064c6f6e646f6e31173015060355040a0c0e476f6f676c6520554b204c74642e3121301f060355040b0c184365727469666963617465205472616e73706172656e63793121301f06035504030c184d657267652044656c6179204d6f6e69746f7220526f6f7430820222300d06092a864886f70d01010105000382020f003082020a0282020100aa161cf2205ed81ac565483cda426a3db2e588fdb758b17b93ea8d68495d534a01ba4f6cd1c0fc0a128af79c066dc54c3f437e05ba275ee61dbf9cbdb2928183738139397b6189ae738fef2b9b609a6dd8e0b0d0e20b243db936c029cdc2220af2c0e1a5e4aa41a006af458957e2b1178d27156ef0cb717e16d54025d97f43e9916fb240fb85f7d579462fa0ac76c76256843750bf1ccdfeb76c8c47886477644d5ec3235628adf6a09c8488bfa5036de717908151a6b585f273dd9fb5332b9af76e8fbfa91eaf4311816dde27c5c44f2fd06cc2204d7147f77ba6b16a2a5fca470023614729538bee6b3cb07264713832aec161550eb501906802215223acc2564ad1f98bb5934924eb56d383fc7598be45c89d995281c0efb0d206d29a6d25a10a48fe235332379c5ca69e83599faa677dd20823f5c84a961255eca5d4871d54ca1df0774aa117b0f42cd6e9fda7e8a48a53923c5f94043353544e644b5a6562e5cef9fc2bd2fcfcce3323335cf7fe7c4d83c1b7f839c4790192d3ba9aa9f32093aa8ee7cbe708059d538dc663cca1b825331aa836754a0d13de63bf65b6e2044dcdf041f1a0c5a9c3c38fe74cf576d451c23eaa519db32ef9e039bd848a194c3b5e41a55642dc283ddbd73d1dd97ae6951de18ad89d005007fae7e88bc7a3cce8b7ccc49603a0db67c76d58a28d4b77aa7460801e34377d0c5e4606c2e25b0203010001a350304e301d0603551d0e04160414f35f7b7549e37841396a20b67c6b4c5cc93d5841301f0603551d23041830168014f35f7b7549e37841396a20b67c6b4c5cc93d5841300c0603551d13040530030101ff300d06092a864886f70d01010505000382020100771cfea34579a97520d8c2423d68ecd07891f8c7f1c38bf3cd30ea9d3637bfc5d373532ec7656558bef4950646750c6fe085c52d9ffc09e66ebfa2b067de7727cb381d2b25db58b9c2197fd5eb53e020f429b86a3b1f37a07a761a66a5b3ecd797c46695a37ff2d47c54126be6bd28a2a103357227c6b73f7f689b09b48927e6e9a52267a728a115d4bcbb477533dc28f3fc57da735a3ec54fbc36990b17febb7e46b324208c1fa7425a0cba48bdc0381ea8285215261c3c483f2fa6d1da0dba4949107189f32d728a7ff395d43430af3b8ce4be5075bcf67d66661941dc8be37340f8f9282b2d2aadd69065932ad49769f8bc7fc9e5f6e79ff392420ba78de3172778e2b67e4df18440dd561e5a7844c8efa06c0e5f5b8695fa069114a00518fb4c19f9d7855831b5eeebced14b8598daffa49f2dcf505bff6417d84b28e83599d4e0371ef64b2d82ffa068a31044f7322fee2f654ec357c9c121f3458a509728c37f5673412ad0d5e76aa6b4eb1582181a8be404d3dc35e71edd83ee388087d6147c4d86f1cacacface0104df1f4b100c2ceb1be4d1851c4f31e7c4409262185878f23cceb30790143f0d5bd80d2c0ed4260aaa312597d950aaf3c8bcfc812d9a56e8d160dd772a494743710a7e478a046d8a5d505ee6b8cc37fec09dfd4cb57c6c4d8e8ef2a22e1d9e50957852633138d722253e51ba77b0069d38812207a"
368 )
369
370 corruptedLeafDER := "aaaaaaaaaa" + leafDER[10:]
371 corruptedPrecertTBS := precertTBS[:6] + "aaaaaaaaaa" + precertTBS[16:]
372
373 var tests = []struct {
374 leaf LeafEntry
375 wantCert bool
376 wantPrecert bool
377 wantErr string
378 }{
379 {
380 leaf: LeafEntry{},
381 wantErr: "failed to unmarshal MerkleTreeLeaf",
382 },
383 {
384 leaf: LeafEntry{
385
386 LeafInput: dh("00" + "00" + "0000015dcc2b99c8" + "0000" + "0004f3" + leafDER + noExts),
387 ExtraData: dh("000ba3" + "0005cc" + leafCA + "0005d1" + rootCA),
388 },
389 wantCert: true,
390 },
391 {
392 leaf: LeafEntry{
393 LeafInput: dh("00" + "00" + "0000015dcc2b99c8" + "0000" + "0004f3" + corruptedLeafDER + noExts),
394 ExtraData: dh("000ba3" + "0005cc" + leafCA + "0005d1" + rootCA),
395 },
396 wantErr: "failed to parse certificate",
397 },
398 {
399 leaf: LeafEntry{
400 LeafInput: dh("00" + "00" + "0000015dcc2b99c8" + "0000" + "0004f3" + leafDER + noExts + "ff"),
401 ExtraData: dh("000ba3" + "0005cc" + leafCA + "0005d1" + rootCA),
402 },
403 wantErr: "MerkleTreeLeaf: trailing data",
404 },
405 {
406 leaf: LeafEntry{
407 LeafInput: dh("00" + "00" + "0000015dcc2b99c8" + "0000" + "0004f3" + leafDER + noExts),
408 ExtraData: dh("000ba3" + "0005cc" + leafCA + "0005d1" + rootCA + "00"),
409 },
410 wantErr: "CertificateChain: trailing data",
411 },
412 {
413 leaf: LeafEntry{
414 LeafInput: dh("00" + "00" + "0000015dcc2b99c8" + "0000" + "0004f3" + leafDER + noExts),
415 },
416 wantErr: "failed to unmarshal CertificateChain",
417 },
418 {
419 leaf: LeafEntry{
420 LeafInput: dh("00" + "00" + "0000015dcc2b99c8" + "8000" + "0004f3" + leafDER + noExts),
421 },
422 wantErr: "unknown entry type",
423 },
424 {
425 leaf: LeafEntry{
426
427 LeafInput: dh("00" + "00" + "0000015dcc997890" + "0001" + issuerKeyHash + precertTBS + noExts),
428 ExtraData: dh("000508" + precertDER +
429 ("000ba3" + "0005cc" + precertCA + "0005d1" + precertRoot)),
430 },
431 wantPrecert: true,
432 },
433 {
434 leaf: LeafEntry{
435 LeafInput: dh("00" + "00" + "0000015dcc997890" + "0001" + issuerKeyHash + corruptedPrecertTBS + noExts),
436 ExtraData: dh("000508" + precertDER +
437 ("000ba3" + "0005cc" + precertCA + "0005d1" + precertRoot)),
438 },
439 wantErr: "failed to parse precertificate",
440 },
441 {
442 leaf: LeafEntry{
443 LeafInput: dh("00" + "00" + "0000015dcc997890" + "0001" + issuerKeyHash + precertTBS + noExts),
444 ExtraData: dh("000508" + precertDER +
445 ("000ba3" + "0005cc" + precertCA + "0005d1" + precertRoot) + "ff"),
446 },
447 wantErr: "PrecertChainEntry: trailing data",
448 },
449 {
450 leaf: LeafEntry{
451 LeafInput: dh("00" + "00" + "0000015dcc997890" + "0001" + issuerKeyHash + precertTBS + noExts + "ff"),
452 ExtraData: dh("000508" + precertDER +
453 ("000ba3" + "0005cc" + precertCA + "0005d1" + precertRoot)),
454 },
455 wantErr: "MerkleTreeLeaf: trailing data",
456 },
457 {
458 leaf: LeafEntry{
459 LeafInput: dh("00" + "00" + "0000015dcc997890" + "0001" + issuerKeyHash + precertTBS + noExts),
460 },
461 wantErr: "failed to unmarshal PrecertChainEntry",
462 },
463 }
464 for i, test := range tests {
465 got, err := LogEntryFromLeaf(int64(i), &test.leaf)
466 if err != nil {
467 if test.wantErr == "" {
468 t.Errorf("LogEntryFromLeaf(%d) = _, %v; want _, nil", i, err)
469 } else if !strings.Contains(err.Error(), test.wantErr) {
470 t.Errorf("LogEntryFromLeaf(%d) = _, %v; want _, err containing %q", i, err, test.wantErr)
471 }
472 } else if test.wantErr != "" {
473 t.Errorf("LogEntryFromLeaf(%d) = _, nil; want _, err containing %q", i, test.wantErr)
474 }
475 if gotCert := got != nil && got.X509Cert != nil; gotCert != test.wantCert {
476 t.Errorf("LogEntryFromLeaf(%d).X509Cert = %v; want %v", i, gotCert, test.wantCert)
477 }
478 if gotPrecert := got != nil && got.Precert != nil; gotPrecert != test.wantPrecert {
479 t.Errorf("LogEntryFromLeaf(%d).Precert = %v; want %v", i, gotPrecert, test.wantPrecert)
480 }
481 }
482 }
483
View as plain text