...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package x509ext
17
18 import (
19 "errors"
20 "fmt"
21
22 "github.com/google/certificate-transparency-go/asn1"
23 "github.com/google/certificate-transparency-go/tls"
24 "github.com/google/certificate-transparency-go/x509"
25
26 ct "github.com/google/certificate-transparency-go"
27 )
28
29
30
31
32 var OIDExtensionCTSTH = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 5}
33
34
35
36
37
38 var OIDExtKeyUsageCTMinimalGossip = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 6}
39
40
41
42 type LogSTHInfo struct {
43 LogURL []byte `tls:"maxlen:255"`
44 Version tls.Enum `tls:"maxval:255"`
45 TreeSize uint64
46 Timestamp uint64
47 SHA256RootHash ct.SHA256Hash
48 TreeHeadSignature ct.DigitallySigned
49 }
50
51
52 func LogSTHInfoFromCert(cert *x509.Certificate) (*LogSTHInfo, error) {
53 for _, ext := range cert.Extensions {
54 if ext.Id.Equal(OIDExtensionCTSTH) {
55 var sthInfo LogSTHInfo
56 rest, err := tls.Unmarshal(ext.Value, &sthInfo)
57 if err != nil {
58 return nil, fmt.Errorf("failed to unmarshal STH: %v", err)
59 } else if len(rest) > 0 {
60 return nil, fmt.Errorf("trailing data (%d bytes) after STH", len(rest))
61 }
62 return &sthInfo, nil
63 }
64 }
65 return nil, errors.New("no STH extension found")
66 }
67
68
69 func HasSTHInfo(cert *x509.Certificate) bool {
70 for _, ext := range cert.Extensions {
71 if ext.Id.Equal(OIDExtensionCTSTH) {
72 return true
73 }
74 }
75 return false
76 }
77
78
79
80 func STHFromCert(cert *x509.Certificate) (*ct.SignedTreeHead, error) {
81 sthInfo, err := LogSTHInfoFromCert(cert)
82 if err != nil {
83 return nil, err
84 }
85 return &ct.SignedTreeHead{
86 Version: ct.Version(sthInfo.Version),
87 TreeSize: sthInfo.TreeSize,
88 Timestamp: sthInfo.Timestamp,
89 SHA256RootHash: sthInfo.SHA256RootHash,
90 TreeHeadSignature: sthInfo.TreeHeadSignature,
91 }, nil
92 }
93
View as plain text