1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ct
16
17 import (
18 "crypto"
19 "crypto/sha256"
20 "fmt"
21 "time"
22
23 "github.com/google/certificate-transparency-go/tls"
24 "github.com/google/certificate-transparency-go/x509"
25 )
26
27
28
29 func SerializeSCTSignatureInput(sct SignedCertificateTimestamp, entry LogEntry) ([]byte, error) {
30 switch sct.SCTVersion {
31 case V1:
32 input := CertificateTimestamp{
33 SCTVersion: sct.SCTVersion,
34 SignatureType: CertificateTimestampSignatureType,
35 Timestamp: sct.Timestamp,
36 EntryType: entry.Leaf.TimestampedEntry.EntryType,
37 Extensions: sct.Extensions,
38 }
39 switch entry.Leaf.TimestampedEntry.EntryType {
40 case X509LogEntryType:
41 input.X509Entry = entry.Leaf.TimestampedEntry.X509Entry
42 case PrecertLogEntryType:
43 input.PrecertEntry = &PreCert{
44 IssuerKeyHash: entry.Leaf.TimestampedEntry.PrecertEntry.IssuerKeyHash,
45 TBSCertificate: entry.Leaf.TimestampedEntry.PrecertEntry.TBSCertificate,
46 }
47 default:
48 return nil, fmt.Errorf("unsupported entry type %s", entry.Leaf.TimestampedEntry.EntryType)
49 }
50 return tls.Marshal(input)
51 default:
52 return nil, fmt.Errorf("unknown SCT version %d", sct.SCTVersion)
53 }
54 }
55
56
57
58 func SerializeSTHSignatureInput(sth SignedTreeHead) ([]byte, error) {
59 switch sth.Version {
60 case V1:
61 if len(sth.SHA256RootHash) != crypto.SHA256.Size() {
62 return nil, fmt.Errorf("invalid TreeHash length, got %d expected %d", len(sth.SHA256RootHash), crypto.SHA256.Size())
63 }
64
65 input := TreeHeadSignature{
66 Version: sth.Version,
67 SignatureType: TreeHashSignatureType,
68 Timestamp: sth.Timestamp,
69 TreeSize: sth.TreeSize,
70 SHA256RootHash: sth.SHA256RootHash,
71 }
72 return tls.Marshal(input)
73 default:
74 return nil, fmt.Errorf("unsupported STH version %d", sth.Version)
75 }
76 }
77
78
79 func CreateX509MerkleTreeLeaf(cert ASN1Cert, timestamp uint64) *MerkleTreeLeaf {
80 return &MerkleTreeLeaf{
81 Version: V1,
82 LeafType: TimestampedEntryLeafType,
83 TimestampedEntry: &TimestampedEntry{
84 Timestamp: timestamp,
85 EntryType: X509LogEntryType,
86 X509Entry: &cert,
87 },
88 }
89 }
90
91
92 func MerkleTreeLeafFromRawChain(rawChain []ASN1Cert, etype LogEntryType, timestamp uint64) (*MerkleTreeLeaf, error) {
93
94 count := 3
95 if count > len(rawChain) {
96 count = len(rawChain)
97 }
98 chain := make([]*x509.Certificate, count)
99 for i := range chain {
100 cert, err := x509.ParseCertificate(rawChain[i].Data)
101 if x509.IsFatal(err) {
102 return nil, fmt.Errorf("failed to parse chain[%d] cert: %v", i, err)
103 }
104 chain[i] = cert
105 }
106 return MerkleTreeLeafFromChain(chain, etype, timestamp)
107 }
108
109
110 func MerkleTreeLeafFromChain(chain []*x509.Certificate, etype LogEntryType, timestamp uint64) (*MerkleTreeLeaf, error) {
111 leaf := MerkleTreeLeaf{
112 Version: V1,
113 LeafType: TimestampedEntryLeafType,
114 TimestampedEntry: &TimestampedEntry{
115 EntryType: etype,
116 Timestamp: timestamp,
117 },
118 }
119 if etype == X509LogEntryType {
120 leaf.TimestampedEntry.X509Entry = &ASN1Cert{Data: chain[0].Raw}
121 return &leaf, nil
122 }
123 if etype != PrecertLogEntryType {
124 return nil, fmt.Errorf("unknown LogEntryType %d", etype)
125 }
126
127
128
129 if len(chain) < 2 {
130 return nil, fmt.Errorf("no issuer cert available for precert leaf building")
131 }
132 issuer := chain[1]
133 cert := chain[0]
134
135 var preIssuer *x509.Certificate
136 if IsPreIssuer(issuer) {
137
138 preIssuer = issuer
139
140
141
142 if len(chain) < 3 {
143 return nil, fmt.Errorf("no issuer cert available for pre-issuer")
144 }
145 issuer = chain[2]
146 }
147
148
149
150 defangedTBS, err := x509.BuildPrecertTBS(cert.RawTBSCertificate, preIssuer)
151 if err != nil {
152 return nil, fmt.Errorf("failed to remove poison extension: %v", err)
153 }
154
155 leaf.TimestampedEntry.EntryType = PrecertLogEntryType
156 leaf.TimestampedEntry.PrecertEntry = &PreCert{
157 IssuerKeyHash: sha256.Sum256(issuer.RawSubjectPublicKeyInfo),
158 TBSCertificate: defangedTBS,
159 }
160 return &leaf, nil
161 }
162
163
164
165
166
167 func MerkleTreeLeafForEmbeddedSCT(chain []*x509.Certificate, timestamp uint64) (*MerkleTreeLeaf, error) {
168
169
170
171 if len(chain) < 2 {
172 return nil, fmt.Errorf("no issuer cert available for precert leaf building")
173 }
174 issuer := chain[1]
175 cert := chain[0]
176
177
178
179 tbs, err := x509.RemoveSCTList(cert.RawTBSCertificate)
180 if err != nil {
181 return nil, fmt.Errorf("failed to remove SCT List extension: %v", err)
182 }
183
184 return &MerkleTreeLeaf{
185 Version: V1,
186 LeafType: TimestampedEntryLeafType,
187 TimestampedEntry: &TimestampedEntry{
188 EntryType: PrecertLogEntryType,
189 Timestamp: timestamp,
190 PrecertEntry: &PreCert{
191 IssuerKeyHash: sha256.Sum256(issuer.RawSubjectPublicKeyInfo),
192 TBSCertificate: tbs,
193 },
194 },
195 }, nil
196 }
197
198
199 func LeafHashForLeaf(leaf *MerkleTreeLeaf) ([sha256.Size]byte, error) {
200 leafData, err := tls.Marshal(*leaf)
201 if err != nil {
202 return [sha256.Size]byte{}, fmt.Errorf("failed to tls-encode MerkleTreeLeaf: %s", err)
203 }
204
205 data := append([]byte{TreeLeafPrefix}, leafData...)
206 leafHash := sha256.Sum256(data)
207 return leafHash, nil
208 }
209
210
211
212 func IsPreIssuer(issuer *x509.Certificate) bool {
213 for _, eku := range issuer.ExtKeyUsage {
214 if eku == x509.ExtKeyUsageCertificateTransparency {
215 return true
216 }
217 }
218 return false
219 }
220
221
222
223 func RawLogEntryFromLeaf(index int64, entry *LeafEntry) (*RawLogEntry, error) {
224 ret := RawLogEntry{Index: index}
225 if rest, err := tls.Unmarshal(entry.LeafInput, &ret.Leaf); err != nil {
226 return nil, fmt.Errorf("failed to unmarshal MerkleTreeLeaf: %v", err)
227 } else if len(rest) > 0 {
228 return nil, fmt.Errorf("MerkleTreeLeaf: trailing data %d bytes", len(rest))
229 }
230
231 switch eType := ret.Leaf.TimestampedEntry.EntryType; eType {
232 case X509LogEntryType:
233 var certChain CertificateChain
234 if rest, err := tls.Unmarshal(entry.ExtraData, &certChain); err != nil {
235 return nil, fmt.Errorf("failed to unmarshal CertificateChain: %v", err)
236 } else if len(rest) > 0 {
237 return nil, fmt.Errorf("CertificateChain: trailing data %d bytes", len(rest))
238 }
239 ret.Cert = *ret.Leaf.TimestampedEntry.X509Entry
240 ret.Chain = certChain.Entries
241
242 case PrecertLogEntryType:
243 var precertChain PrecertChainEntry
244 if rest, err := tls.Unmarshal(entry.ExtraData, &precertChain); err != nil {
245 return nil, fmt.Errorf("failed to unmarshal PrecertChainEntry: %v", err)
246 } else if len(rest) > 0 {
247 return nil, fmt.Errorf("PrecertChainEntry: trailing data %d bytes", len(rest))
248 }
249 ret.Cert = precertChain.PreCertificate
250 ret.Chain = precertChain.CertificateChain
251
252 default:
253
254
255 return nil, fmt.Errorf("unknown entry type: %v", eType)
256 }
257
258 return &ret, nil
259 }
260
261
262
263
264
265
266 func (rle *RawLogEntry) ToLogEntry() (*LogEntry, error) {
267 var err error
268 entry := LogEntry{Index: rle.Index, Leaf: rle.Leaf, Chain: rle.Chain}
269
270 switch eType := rle.Leaf.TimestampedEntry.EntryType; eType {
271 case X509LogEntryType:
272 entry.X509Cert, err = rle.Leaf.X509Certificate()
273 if x509.IsFatal(err) {
274 return nil, fmt.Errorf("failed to parse certificate: %v", err)
275 }
276
277 case PrecertLogEntryType:
278 var tbsCert *x509.Certificate
279 tbsCert, err = rle.Leaf.Precertificate()
280 if x509.IsFatal(err) {
281 return nil, fmt.Errorf("failed to parse precertificate: %v", err)
282 }
283 entry.Precert = &Precertificate{
284 Submitted: rle.Cert,
285 IssuerKeyHash: rle.Leaf.TimestampedEntry.PrecertEntry.IssuerKeyHash,
286 TBSCertificate: tbsCert,
287 }
288
289 default:
290 return nil, fmt.Errorf("unknown entry type: %v", eType)
291 }
292
293
294 return &entry, err
295 }
296
297
298
299
300
301
302
303 func LogEntryFromLeaf(index int64, leaf *LeafEntry) (*LogEntry, error) {
304 rle, err := RawLogEntryFromLeaf(index, leaf)
305 if err != nil {
306 return nil, err
307 }
308 return rle.ToLogEntry()
309 }
310
311
312
313 func TimestampToTime(ts uint64) time.Time {
314 secs := int64(ts / 1000)
315 msecs := int64(ts % 1000)
316 return time.Unix(secs, msecs*1000000)
317 }
318
View as plain text