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.
13 // CertPool is a set of certificates.
14 type CertPool
struct {
15 bySubjectKeyId
map[string][]int
16 byName
map[string][]int
20 // NewCertPool returns a new, empty CertPool.
21 func NewCertPool() *CertPool
{
23 bySubjectKeyId
: make(map[string][]int),
24 byName
: make(map[string][]int),
28 // SystemCertPool returns a copy of the system cert pool.
30 // Any mutations to the returned pool are not written to disk and do
31 // not affect any other pool.
32 func SystemCertPool() (*CertPool
, error
) {
33 if runtime
.GOOS
== "windows" {
34 // Issue 16736, 18609:
35 return nil, errors
.New("crypto/x509: system root pool is not available on Windows")
38 return loadSystemRoots()
41 // findVerifiedParents attempts to find certificates in s which have signed the
42 // given certificate. If any candidates were rejected then errCert will be set
43 // to one of them, arbitrarily, and err will contain the reason that it was
45 func (s
*CertPool
) findVerifiedParents(cert
*Certificate
) (parents
[]int, errCert
*Certificate
, err error
) {
51 if len(cert
.AuthorityKeyId
) > 0 {
52 candidates
= s
.bySubjectKeyId
[string(cert
.AuthorityKeyId
)]
54 if len(candidates
) == 0 {
55 candidates
= s
.byName
[string(cert
.RawIssuer
)]
58 for _
, c
:= range candidates
{
59 if err
= cert
.CheckSignatureFrom(s
.certs
[c
]); err
== nil {
60 parents
= append(parents
, c
)
69 func (s
*CertPool
) contains(cert
*Certificate
) bool {
74 candidates
:= s
.byName
[string(cert
.RawSubject
)]
75 for _
, c
:= range candidates
{
76 if s
.certs
[c
].Equal(cert
) {
84 // AddCert adds a certificate to a pool.
85 func (s
*CertPool
) AddCert(cert
*Certificate
) {
87 panic("adding nil Certificate to CertPool")
90 // Check that the certificate isn't being added twice.
96 s
.certs
= append(s
.certs
, cert
)
98 if len(cert
.SubjectKeyId
) > 0 {
99 keyId
:= string(cert
.SubjectKeyId
)
100 s
.bySubjectKeyId
[keyId
] = append(s
.bySubjectKeyId
[keyId
], n
)
102 name
:= string(cert
.RawSubject
)
103 s
.byName
[name
] = append(s
.byName
[name
], n
)
106 // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
107 // It appends any certificates found to s and reports whether any certificates
108 // were successfully parsed.
110 // On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
111 // of root CAs in a format suitable for this function.
112 func (s
*CertPool
) AppendCertsFromPEM(pemCerts
[]byte) (ok
bool) {
113 for len(pemCerts
) > 0 {
115 block
, pemCerts
= pem
.Decode(pemCerts
)
119 if block
.Type
!= "CERTIFICATE" ||
len(block
.Headers
) != 0 {
123 cert
, err
:= ParseCertificate(block
.Bytes
)
135 // Subjects returns a list of the DER-encoded subjects of
136 // all of the certificates in the pool.
137 func (s
*CertPool
) Subjects() [][]byte {
138 res
:= make([][]byte, len(s
.certs
))
139 for i
, c
:= range s
.certs
{
140 res
[i
] = c
.RawSubject