Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / google / certificate-transparency / go / x509 / cert_pool.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package x509
6
7 import (
8         "encoding/pem"
9 )
10
11 // CertPool is a set of certificates.
12 type CertPool struct {
13         bySubjectKeyId map[string][]int
14         byName         map[string][]int
15         certs          []*Certificate
16 }
17
18 // NewCertPool returns a new, empty CertPool.
19 func NewCertPool() *CertPool {
20         return &CertPool{
21                 make(map[string][]int),
22                 make(map[string][]int),
23                 nil,
24         }
25 }
26
27 // findVerifiedParents attempts to find certificates in s which have signed the
28 // given certificate. If any candidates were rejected then errCert will be set
29 // to one of them, arbitrarily, and err will contain the reason that it was
30 // rejected.
31 func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
32         if s == nil {
33                 return
34         }
35         var candidates []int
36
37         if len(cert.AuthorityKeyId) > 0 {
38                 candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
39         }
40         if len(candidates) == 0 {
41                 candidates = s.byName[string(cert.RawIssuer)]
42         }
43
44         for _, c := range candidates {
45                 if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
46                         parents = append(parents, c)
47                 } else {
48                         errCert = s.certs[c]
49                 }
50         }
51
52         return
53 }
54
55 // AddCert adds a certificate to a pool.
56 func (s *CertPool) AddCert(cert *Certificate) {
57         if cert == nil {
58                 panic("adding nil Certificate to CertPool")
59         }
60
61         // Check that the certificate isn't being added twice.
62         for _, c := range s.certs {
63                 if c.Equal(cert) {
64                         return
65                 }
66         }
67
68         n := len(s.certs)
69         s.certs = append(s.certs, cert)
70
71         if len(cert.SubjectKeyId) > 0 {
72                 keyId := string(cert.SubjectKeyId)
73                 s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
74         }
75         name := string(cert.RawSubject)
76         s.byName[name] = append(s.byName[name], n)
77 }
78
79 // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
80 // It appends any certificates found to s and returns true if any certificates
81 // were successfully parsed.
82 //
83 // On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
84 // of root CAs in a format suitable for this function.
85 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
86         for len(pemCerts) > 0 {
87                 var block *pem.Block
88                 block, pemCerts = pem.Decode(pemCerts)
89                 if block == nil {
90                         break
91                 }
92                 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
93                         continue
94                 }
95
96                 cert, err := ParseCertificate(block.Bytes)
97                 if err != nil {
98                         continue
99                 }
100
101                 s.AddCert(cert)
102                 ok = true
103         }
104
105         return
106 }
107
108 // Subjects returns a list of the DER-encoded subjects of
109 // all of the certificates in the pool.
110 func (s *CertPool) Subjects() (res [][]byte) {
111         res = make([][]byte, len(s.certs))
112         for i, c := range s.certs {
113                 res[i] = c.RawSubject
114         }
115         return
116 }