Source file
src/crypto/x509/cert_pool.go
1
2
3
4
5 package x509
6
7 import (
8 "encoding/pem"
9 "errors"
10 "runtime"
11 )
12
13
14 type CertPool struct {
15 bySubjectKeyId map[string][]int
16 byName map[string][]int
17 certs []*Certificate
18 }
19
20
21 func NewCertPool() *CertPool {
22 return &CertPool{
23 bySubjectKeyId: make(map[string][]int),
24 byName: make(map[string][]int),
25 }
26 }
27
28 func (s *CertPool) copy() *CertPool {
29 p := &CertPool{
30 bySubjectKeyId: make(map[string][]int, len(s.bySubjectKeyId)),
31 byName: make(map[string][]int, len(s.byName)),
32 certs: make([]*Certificate, len(s.certs)),
33 }
34 for k, v := range s.bySubjectKeyId {
35 indexes := make([]int, len(v))
36 copy(indexes, v)
37 p.bySubjectKeyId[k] = indexes
38 }
39 for k, v := range s.byName {
40 indexes := make([]int, len(v))
41 copy(indexes, v)
42 p.byName[k] = indexes
43 }
44 copy(p.certs, s.certs)
45 return p
46 }
47
48
49
50
51
52
53
54
55
56
57
58
59 func SystemCertPool() (*CertPool, error) {
60 if runtime.GOOS == "windows" {
61
62 return nil, errors.New("crypto/x509: system root pool is not available on Windows")
63 }
64
65 if sysRoots := systemRootsPool(); sysRoots != nil {
66 return sysRoots.copy(), nil
67 }
68
69 return loadSystemRoots()
70 }
71
72
73
74 func (s *CertPool) findPotentialParents(cert *Certificate) []int {
75 if s == nil {
76 return nil
77 }
78
79 var candidates []int
80 if len(cert.AuthorityKeyId) > 0 {
81 candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
82 }
83 if len(candidates) == 0 {
84 candidates = s.byName[string(cert.RawIssuer)]
85 }
86 return candidates
87 }
88
89 func (s *CertPool) contains(cert *Certificate) bool {
90 if s == nil {
91 return false
92 }
93
94 candidates := s.byName[string(cert.RawSubject)]
95 for _, c := range candidates {
96 if s.certs[c].Equal(cert) {
97 return true
98 }
99 }
100
101 return false
102 }
103
104
105 func (s *CertPool) AddCert(cert *Certificate) {
106 if cert == nil {
107 panic("adding nil Certificate to CertPool")
108 }
109
110
111 if s.contains(cert) {
112 return
113 }
114
115 n := len(s.certs)
116 s.certs = append(s.certs, cert)
117
118 if len(cert.SubjectKeyId) > 0 {
119 keyId := string(cert.SubjectKeyId)
120 s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
121 }
122 name := string(cert.RawSubject)
123 s.byName[name] = append(s.byName[name], n)
124 }
125
126
127
128
129
130
131
132 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
133 for len(pemCerts) > 0 {
134 var block *pem.Block
135 block, pemCerts = pem.Decode(pemCerts)
136 if block == nil {
137 break
138 }
139 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
140 continue
141 }
142
143 cert, err := ParseCertificate(block.Bytes)
144 if err != nil {
145 continue
146 }
147
148 s.AddCert(cert)
149 ok = true
150 }
151
152 return
153 }
154
155
156
157 func (s *CertPool) Subjects() [][]byte {
158 res := make([][]byte, len(s.certs))
159 for i, c := range s.certs {
160 res[i] = c.RawSubject
161 }
162 return res
163 }
164
View as plain text