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 func (s *CertPool) copy() *CertPool {
81 p := &CertPool{
82 byName: make(map[string][]int, len(s.byName)),
83 lazyCerts: make([]lazyCert, len(s.lazyCerts)),
84 haveSum: make(map[sum224]bool, len(s.haveSum)),
85 systemPool: s.systemPool,
86 }
87 for k, v := range s.byName {
88 indexes := make([]int, len(v))
89 copy(indexes, v)
90 p.byName[k] = indexes
91 }
92 for k := range s.haveSum {
93 p.haveSum[k] = true
94 }
95 copy(p.lazyCerts, s.lazyCerts)
96 return p
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110 func SystemCertPool() (*CertPool, error) {
111 if sysRoots := systemRootsPool(); sysRoots != nil {
112 return sysRoots.copy(), nil
113 }
114
115 return loadSystemRoots()
116 }
117
118
119
120 func (s *CertPool) findPotentialParents(cert *Certificate) []*Certificate {
121 if s == nil {
122 return nil
123 }
124
125
126
127
128
129
130
131 var matchingKeyID, oneKeyID, mismatchKeyID []*Certificate
132 for _, c := range s.byName[string(cert.RawIssuer)] {
133 candidate, err := s.cert(c)
134 if err != nil {
135 continue
136 }
137 kidMatch := bytes.Equal(candidate.SubjectKeyId, cert.AuthorityKeyId)
138 switch {
139 case kidMatch:
140 matchingKeyID = append(matchingKeyID, candidate)
141 case (len(candidate.SubjectKeyId) == 0 && len(cert.AuthorityKeyId) > 0) ||
142 (len(candidate.SubjectKeyId) > 0 && len(cert.AuthorityKeyId) == 0):
143 oneKeyID = append(oneKeyID, candidate)
144 default:
145 mismatchKeyID = append(mismatchKeyID, candidate)
146 }
147 }
148
149 found := len(matchingKeyID) + len(oneKeyID) + len(mismatchKeyID)
150 if found == 0 {
151 return nil
152 }
153 candidates := make([]*Certificate, 0, found)
154 candidates = append(candidates, matchingKeyID...)
155 candidates = append(candidates, oneKeyID...)
156 candidates = append(candidates, mismatchKeyID...)
157 return candidates
158 }
159
160 func (s *CertPool) contains(cert *Certificate) bool {
161 if s == nil {
162 return false
163 }
164 return s.haveSum[sha256.Sum224(cert.Raw)]
165 }
166
167
168 func (s *CertPool) AddCert(cert *Certificate) {
169 if cert == nil {
170 panic("adding nil Certificate to CertPool")
171 }
172 s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) {
173 return cert, nil
174 })
175 }
176
177
178
179
180
181
182 func (s *CertPool) addCertFunc(rawSum224 sum224, rawSubject string, getCert func() (*Certificate, error)) {
183 if getCert == nil {
184 panic("getCert can't be nil")
185 }
186
187
188 if s.haveSum[rawSum224] {
189 return
190 }
191
192 s.haveSum[rawSum224] = true
193 s.lazyCerts = append(s.lazyCerts, lazyCert{
194 rawSubject: []byte(rawSubject),
195 getCert: getCert,
196 })
197 s.byName[rawSubject] = append(s.byName[rawSubject], len(s.lazyCerts)-1)
198 }
199
200
201
202
203
204
205
206 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
207 for len(pemCerts) > 0 {
208 var block *pem.Block
209 block, pemCerts = pem.Decode(pemCerts)
210 if block == nil {
211 break
212 }
213 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
214 continue
215 }
216
217 certBytes := block.Bytes
218 cert, err := ParseCertificate(certBytes)
219 if err != nil {
220 continue
221 }
222 var lazyCert struct {
223 sync.Once
224 v *Certificate
225 }
226 s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) {
227 lazyCert.Do(func() {
228
229 lazyCert.v, _ = ParseCertificate(certBytes)
230 certBytes = nil
231 })
232 return lazyCert.v, nil
233 })
234 ok = true
235 }
236
237 return ok
238 }
239
240
241
242
243
244
245 func (s *CertPool) Subjects() [][]byte {
246 res := make([][]byte, s.len())
247 for i, lc := range s.lazyCerts {
248 res[i] = lc.rawSubject
249 }
250 return res
251 }
252
View as plain text