Source file
src/crypto/x509/cert_pool.go
1
2
3
4
5 package x509
6
7 import (
8 "bytes"
9 "crypto/sha256"
10 "encoding/pem"
11 "sync"
12 )
13
14 type sum224 [sha256.Size224]byte
15
16
17 type CertPool struct {
18 byName map[string][]int
19
20
21
22 lazyCerts []lazyCert
23
24
25
26
27
28
29 haveSum map[sum224]bool
30
31
32
33
34
35 systemPool bool
36 }
37
38
39
40 type lazyCert struct {
41
42
43
44
45 rawSubject []byte
46
47
48
49
50
51
52
53
54
55 getCert func() (*Certificate, error)
56 }
57
58
59 func NewCertPool() *CertPool {
60 return &CertPool{
61 byName: make(map[string][]int),
62 haveSum: make(map[sum224]bool),
63 }
64 }
65
66
67
68 func (s *CertPool) len() int {
69 if s == nil {
70 return 0
71 }
72 return len(s.lazyCerts)
73 }
74
75
76 func (s *CertPool) cert(n int) (*Certificate, error) {
77 return s.lazyCerts[n].getCert()
78 }
79
80
81 func (s *CertPool) Clone() *CertPool {
82 p := &CertPool{
83 byName: make(map[string][]int, len(s.byName)),
84 lazyCerts: make([]lazyCert, len(s.lazyCerts)),
85 haveSum: make(map[sum224]bool, len(s.haveSum)),
86 systemPool: s.systemPool,
87 }
88 for k, v := range s.byName {
89 indexes := make([]int, len(v))
90 copy(indexes, v)
91 p.byName[k] = indexes
92 }
93 for k := range s.haveSum {
94 p.haveSum[k] = true
95 }
96 copy(p.lazyCerts, s.lazyCerts)
97 return p
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111 func SystemCertPool() (*CertPool, error) {
112 if sysRoots := systemRootsPool(); sysRoots != nil {
113 return sysRoots.Clone(), nil
114 }
115
116 return loadSystemRoots()
117 }
118
119
120
121 func (s *CertPool) findPotentialParents(cert *Certificate) []*Certificate {
122 if s == nil {
123 return nil
124 }
125
126
127
128
129
130
131
132 var matchingKeyID, oneKeyID, mismatchKeyID []*Certificate
133 for _, c := range s.byName[string(cert.RawIssuer)] {
134 candidate, err := s.cert(c)
135 if err != nil {
136 continue
137 }
138 kidMatch := bytes.Equal(candidate.SubjectKeyId, cert.AuthorityKeyId)
139 switch {
140 case kidMatch:
141 matchingKeyID = append(matchingKeyID, candidate)
142 case (len(candidate.SubjectKeyId) == 0 && len(cert.AuthorityKeyId) > 0) ||
143 (len(candidate.SubjectKeyId) > 0 && len(cert.AuthorityKeyId) == 0):
144 oneKeyID = append(oneKeyID, candidate)
145 default:
146 mismatchKeyID = append(mismatchKeyID, candidate)
147 }
148 }
149
150 found := len(matchingKeyID) + len(oneKeyID) + len(mismatchKeyID)
151 if found == 0 {
152 return nil
153 }
154 candidates := make([]*Certificate, 0, found)
155 candidates = append(candidates, matchingKeyID...)
156 candidates = append(candidates, oneKeyID...)
157 candidates = append(candidates, mismatchKeyID...)
158 return candidates
159 }
160
161 func (s *CertPool) contains(cert *Certificate) bool {
162 if s == nil {
163 return false
164 }
165 return s.haveSum[sha256.Sum224(cert.Raw)]
166 }
167
168
169 func (s *CertPool) AddCert(cert *Certificate) {
170 if cert == nil {
171 panic("adding nil Certificate to CertPool")
172 }
173 s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) {
174 return cert, nil
175 })
176 }
177
178
179
180
181
182
183 func (s *CertPool) addCertFunc(rawSum224 sum224, rawSubject string, getCert func() (*Certificate, error)) {
184 if getCert == nil {
185 panic("getCert can't be nil")
186 }
187
188
189 if s.haveSum[rawSum224] {
190 return
191 }
192
193 s.haveSum[rawSum224] = true
194 s.lazyCerts = append(s.lazyCerts, lazyCert{
195 rawSubject: []byte(rawSubject),
196 getCert: getCert,
197 })
198 s.byName[rawSubject] = append(s.byName[rawSubject], len(s.lazyCerts)-1)
199 }
200
201
202
203
204
205
206
207 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
208 for len(pemCerts) > 0 {
209 var block *pem.Block
210 block, pemCerts = pem.Decode(pemCerts)
211 if block == nil {
212 break
213 }
214 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
215 continue
216 }
217
218 certBytes := block.Bytes
219 cert, err := ParseCertificate(certBytes)
220 if err != nil {
221 continue
222 }
223 var lazyCert struct {
224 sync.Once
225 v *Certificate
226 }
227 s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) {
228 lazyCert.Do(func() {
229
230 lazyCert.v, _ = ParseCertificate(certBytes)
231 certBytes = nil
232 })
233 return lazyCert.v, nil
234 })
235 ok = true
236 }
237
238 return ok
239 }
240
241
242
243
244
245
246 func (s *CertPool) Subjects() [][]byte {
247 res := make([][]byte, s.len())
248 for i, lc := range s.lazyCerts {
249 res[i] = lc.rawSubject
250 }
251 return res
252 }
253
254
255 func (s *CertPool) Equal(other *CertPool) bool {
256 if s == nil || other == nil {
257 return s == other
258 }
259 if s.systemPool != other.systemPool || len(s.haveSum) != len(other.haveSum) {
260 return false
261 }
262 for h := range s.haveSum {
263 if !other.haveSum[h] {
264 return false
265 }
266 }
267 return true
268 }
269
View as plain text