Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / google / certificate-transparency / go / types.go
1 package ct
2
3 import (
4         "bytes"
5         "crypto/sha256"
6         "encoding/base64"
7         "encoding/json"
8         "fmt"
9
10         "github.com/google/certificate-transparency/go/x509"
11 )
12
13 const (
14         issuerKeyHashLength = 32
15 )
16
17 ///////////////////////////////////////////////////////////////////////////////
18 // The following structures represent those outlined in the RFC6962 document:
19 ///////////////////////////////////////////////////////////////////////////////
20
21 // LogEntryType represents the LogEntryType enum from section 3.1 of the RFC:
22 //   enum { x509_entry(0), precert_entry(1), (65535) } LogEntryType;
23 type LogEntryType uint16
24
25 func (e LogEntryType) String() string {
26         switch e {
27         case X509LogEntryType:
28                 return "X509LogEntryType"
29         case PrecertLogEntryType:
30                 return "PrecertLogEntryType"
31         case XJSONLogEntryType:
32                 return "XJSONLogEntryType"
33         }
34         panic(fmt.Sprintf("No string defined for LogEntryType constant value %d", e))
35 }
36
37 // LogEntryType constants, see section 3.1 of RFC6962.
38 const (
39         X509LogEntryType    LogEntryType = 0
40         PrecertLogEntryType LogEntryType = 1
41         XJSONLogEntryType   LogEntryType = 0x8000 // Experimental.  Don't rely on this!
42 )
43
44 // MerkleLeafType represents the MerkleLeafType enum from section 3.4 of the
45 // RFC: enum { timestamped_entry(0), (255) } MerkleLeafType;
46 type MerkleLeafType uint8
47
48 func (m MerkleLeafType) String() string {
49         switch m {
50         case TimestampedEntryLeafType:
51                 return "TimestampedEntryLeafType"
52         default:
53                 return fmt.Sprintf("UnknownLeafType(%d)", m)
54         }
55 }
56
57 // MerkleLeafType constants, see section 3.4 of the RFC.
58 const (
59         TimestampedEntryLeafType MerkleLeafType = 0 // Entry type for an SCT
60 )
61
62 // Version represents the Version enum from section 3.2 of the RFC:
63 // enum { v1(0), (255) } Version;
64 type Version uint8
65
66 func (v Version) String() string {
67         switch v {
68         case V1:
69                 return "V1"
70         default:
71                 return fmt.Sprintf("UnknownVersion(%d)", v)
72         }
73 }
74
75 // CT Version constants, see section 3.2 of the RFC.
76 const (
77         V1 Version = 0
78 )
79
80 // SignatureType differentiates STH signatures from SCT signatures, see RFC
81 // section 3.2
82 type SignatureType uint8
83
84 func (st SignatureType) String() string {
85         switch st {
86         case CertificateTimestampSignatureType:
87                 return "CertificateTimestamp"
88         case TreeHashSignatureType:
89                 return "TreeHash"
90         default:
91                 return fmt.Sprintf("UnknownSignatureType(%d)", st)
92         }
93 }
94
95 // SignatureType constants, see RFC section 3.2
96 const (
97         CertificateTimestampSignatureType SignatureType = 0
98         TreeHashSignatureType             SignatureType = 1
99 )
100
101 // ASN1Cert type for holding the raw DER bytes of an ASN.1 Certificate
102 // (section 3.1)
103 type ASN1Cert []byte
104
105 // PreCert represents a Precertificate (section 3.2)
106 type PreCert struct {
107         IssuerKeyHash  [issuerKeyHashLength]byte
108         TBSCertificate []byte
109 }
110
111 // CTExtensions is a representation of the raw bytes of any CtExtension
112 // structure (see section 3.2)
113 type CTExtensions []byte
114
115 // MerkleTreeNode represents an internal node in the CT tree
116 type MerkleTreeNode []byte
117
118 // ConsistencyProof represents a CT consistency proof (see sections 2.1.2 and
119 // 4.4)
120 type ConsistencyProof []MerkleTreeNode
121
122 // AuditPath represents a CT inclusion proof (see sections 2.1.1 and 4.5)
123 type AuditPath []MerkleTreeNode
124
125 // LeafInput represents a serialized MerkleTreeLeaf structure
126 type LeafInput []byte
127
128 // HashAlgorithm from the DigitallySigned struct
129 type HashAlgorithm byte
130
131 // HashAlgorithm constants
132 const (
133         None   HashAlgorithm = 0
134         MD5    HashAlgorithm = 1
135         SHA1   HashAlgorithm = 2
136         SHA224 HashAlgorithm = 3
137         SHA256 HashAlgorithm = 4
138         SHA384 HashAlgorithm = 5
139         SHA512 HashAlgorithm = 6
140 )
141
142 func (h HashAlgorithm) String() string {
143         switch h {
144         case None:
145                 return "None"
146         case MD5:
147                 return "MD5"
148         case SHA1:
149                 return "SHA1"
150         case SHA224:
151                 return "SHA224"
152         case SHA256:
153                 return "SHA256"
154         case SHA384:
155                 return "SHA384"
156         case SHA512:
157                 return "SHA512"
158         default:
159                 return fmt.Sprintf("UNKNOWN(%d)", h)
160         }
161 }
162
163 // SignatureAlgorithm from the the DigitallySigned struct
164 type SignatureAlgorithm byte
165
166 // SignatureAlgorithm constants
167 const (
168         Anonymous SignatureAlgorithm = 0
169         RSA       SignatureAlgorithm = 1
170         DSA       SignatureAlgorithm = 2
171         ECDSA     SignatureAlgorithm = 3
172 )
173
174 func (s SignatureAlgorithm) String() string {
175         switch s {
176         case Anonymous:
177                 return "Anonymous"
178         case RSA:
179                 return "RSA"
180         case DSA:
181                 return "DSA"
182         case ECDSA:
183                 return "ECDSA"
184         default:
185                 return fmt.Sprintf("UNKNOWN(%d)", s)
186         }
187 }
188
189 // DigitallySigned represents an RFC5246 DigitallySigned structure
190 type DigitallySigned struct {
191         HashAlgorithm      HashAlgorithm
192         SignatureAlgorithm SignatureAlgorithm
193         Signature          []byte
194 }
195
196 // FromBase64String populates the DigitallySigned structure from the base64 data passed in.
197 // Returns an error if the base64 data is invalid.
198 func (d *DigitallySigned) FromBase64String(b64 string) error {
199         raw, err := base64.StdEncoding.DecodeString(b64)
200         if err != nil {
201                 return fmt.Errorf("failed to unbase64 DigitallySigned: %v", err)
202         }
203         ds, err := UnmarshalDigitallySigned(bytes.NewReader(raw))
204         if err != nil {
205                 return fmt.Errorf("failed to unmarshal DigitallySigned: %v", err)
206         }
207         *d = *ds
208         return nil
209 }
210
211 // Base64String returns the base64 representation of the DigitallySigned struct.
212 func (d DigitallySigned) Base64String() (string, error) {
213         b, err := MarshalDigitallySigned(d)
214         if err != nil {
215                 return "", err
216         }
217         return base64.StdEncoding.EncodeToString(b), nil
218 }
219
220 // MarshalJSON implements the json.Marshaller interface.
221 func (d DigitallySigned) MarshalJSON() ([]byte, error) {
222         b64, err := d.Base64String()
223         if err != nil {
224                 return []byte{}, err
225         }
226         return []byte(`"` + b64 + `"`), nil
227 }
228
229 // UnmarshalJSON implements the json.Unmarshaler interface.
230 func (d *DigitallySigned) UnmarshalJSON(b []byte) error {
231         var content string
232         if err := json.Unmarshal(b, &content); err != nil {
233                 return fmt.Errorf("failed to unmarshal DigitallySigned: %v", err)
234         }
235         return d.FromBase64String(content)
236 }
237
238 // LogEntry represents the contents of an entry in a CT log, see section 3.1.
239 type LogEntry struct {
240         Index    int64
241         Leaf     MerkleTreeLeaf
242         X509Cert *x509.Certificate
243         Precert  *Precertificate
244         JSONData []byte
245         Chain    []ASN1Cert
246 }
247
248 // SHA256Hash represents the output from the SHA256 hash function.
249 type SHA256Hash [sha256.Size]byte
250
251 // FromBase64String populates the SHA256 struct with the contents of the base64 data passed in.
252 func (s *SHA256Hash) FromBase64String(b64 string) error {
253         bs, err := base64.StdEncoding.DecodeString(b64)
254         if err != nil {
255                 return fmt.Errorf("failed to unbase64 LogID: %v", err)
256         }
257         if len(bs) != sha256.Size {
258                 return fmt.Errorf("invalid SHA256 length, expected 32 but got %d", len(bs))
259         }
260         copy(s[:], bs)
261         return nil
262 }
263
264 // Base64String returns the base64 representation of this SHA256Hash.
265 func (s SHA256Hash) Base64String() string {
266         return base64.StdEncoding.EncodeToString(s[:])
267 }
268
269 // MarshalJSON implements the json.Marshaller interface for SHA256Hash.
270 func (s SHA256Hash) MarshalJSON() ([]byte, error) {
271         return []byte(`"` + s.Base64String() + `"`), nil
272 }
273
274 // UnmarshalJSON implements the json.Unmarshaller interface.
275 func (s *SHA256Hash) UnmarshalJSON(b []byte) error {
276         var content string
277         if err := json.Unmarshal(b, &content); err != nil {
278                 return fmt.Errorf("failed to unmarshal SHA256Hash: %v", err)
279         }
280         return s.FromBase64String(content)
281 }
282
283 // SignedTreeHead represents the structure returned by the get-sth CT method
284 // after base64 decoding. See sections 3.5 and 4.3 in the RFC)
285 type SignedTreeHead struct {
286         Version           Version         `json:"sth_version"`         // The version of the protocol to which the STH conforms
287         TreeSize          uint64          `json:"tree_size"`           // The number of entries in the new tree
288         Timestamp         uint64          `json:"timestamp"`           // The time at which the STH was created
289         SHA256RootHash    SHA256Hash      `json:"sha256_root_hash"`    // The root hash of the log's Merkle tree
290         TreeHeadSignature DigitallySigned `json:"tree_head_signature"` // The Log's signature for this STH (see RFC section 3.5)
291         LogID             SHA256Hash      `json:"log_id"`              // The SHA256 hash of the log's public key
292 }
293
294 // SignedCertificateTimestamp represents the structure returned by the
295 // add-chain and add-pre-chain methods after base64 decoding. (see RFC sections
296 // 3.2 ,4.1 and 4.2)
297 type SignedCertificateTimestamp struct {
298         SCTVersion Version    // The version of the protocol to which the SCT conforms
299         LogID      SHA256Hash // the SHA-256 hash of the log's public key, calculated over
300         // the DER encoding of the key represented as SubjectPublicKeyInfo.
301         Timestamp  uint64          // Timestamp (in ms since unix epoc) at which the SCT was issued
302         Extensions CTExtensions    // For future extensions to the protocol
303         Signature  DigitallySigned // The Log's signature for this SCT
304 }
305
306 func (s SignedCertificateTimestamp) String() string {
307         return fmt.Sprintf("{Version:%d LogId:%s Timestamp:%d Extensions:'%s' Signature:%v}", s.SCTVersion,
308                 base64.StdEncoding.EncodeToString(s.LogID[:]),
309                 s.Timestamp,
310                 s.Extensions,
311                 s.Signature)
312 }
313
314 // TimestampedEntry is part of the MerkleTreeLeaf structure.
315 // See RFC section 3.4
316 type TimestampedEntry struct {
317         Timestamp    uint64
318         EntryType    LogEntryType
319         X509Entry    ASN1Cert
320         JSONData     []byte
321         PrecertEntry PreCert
322         Extensions   CTExtensions
323 }
324
325 // MerkleTreeLeaf represents the deserialized sructure of the hash input for the
326 // leaves of a log's Merkle tree. See RFC section 3.4
327 type MerkleTreeLeaf struct {
328         Version          Version          // the version of the protocol to which the MerkleTreeLeaf corresponds
329         LeafType         MerkleLeafType   // The type of the leaf input, currently only TimestampedEntry can exist
330         TimestampedEntry TimestampedEntry // The entry data itself
331 }
332
333 // Precertificate represents the parsed CT Precertificate structure.
334 type Precertificate struct {
335         // Raw DER bytes of the precert
336         Raw []byte
337         // SHA256 hash of the issuing key
338         IssuerKeyHash [issuerKeyHashLength]byte
339         // Parsed TBSCertificate structure (held in an x509.Certificate for ease of
340         // access.
341         TBSCertificate x509.Certificate
342 }
343
344 // X509Certificate returns the X.509 Certificate contained within the
345 // MerkleTreeLeaf.
346 // Returns a pointer to an x509.Certificate or a non-nil error.
347 func (m *MerkleTreeLeaf) X509Certificate() (*x509.Certificate, error) {
348         return x509.ParseCertificate(m.TimestampedEntry.X509Entry)
349 }
350
351 type sctError int
352
353 // Preallocate errors for performance
354 var (
355         ErrInvalidVersion  error = sctError(1)
356         ErrNotEnoughBuffer error = sctError(2)
357 )
358
359 func (e sctError) Error() string {
360         switch e {
361         case ErrInvalidVersion:
362                 return "invalid SCT version detected"
363         case ErrNotEnoughBuffer:
364                 return "provided buffer was too small"
365         default:
366                 return "unknown error"
367         }
368 }
369
370 // AddJSONRequest represents the JSON request body sent ot the add-json CT
371 // method.
372 type AddJSONRequest struct {
373         Data interface{} `json:"data"`
374 }