github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/crypto/x509/cert_pool.go (about) 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 "errors" 10 "runtime" 11 ) 12 13 // CertPool is a set of certificates. 14 type CertPool struct { 15 bySubjectKeyId map[string][]int 16 byName map[string][]int 17 certs []*Certificate 18 } 19 20 // NewCertPool returns a new, empty CertPool. 21 func NewCertPool() *CertPool { 22 return &CertPool{ 23 bySubjectKeyId: make(map[string][]int), 24 byName: make(map[string][]int), 25 } 26 } 27 28 // SystemCertPool returns a copy of the system cert pool. 29 // 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") 36 } 37 38 return loadSystemRoots() 39 } 40 41 // findPotentialParents returns the indexes of certificates in s which might 42 // have signed cert. The caller must not modify the returned slice. 43 func (s *CertPool) findPotentialParents(cert *Certificate) []int { 44 if s == nil { 45 return nil 46 } 47 if len(cert.AuthorityKeyId) > 0 { 48 return s.bySubjectKeyId[string(cert.AuthorityKeyId)] 49 } 50 return s.byName[string(cert.RawIssuer)] 51 } 52 53 func (s *CertPool) contains(cert *Certificate) bool { 54 if s == nil { 55 return false 56 } 57 58 candidates := s.byName[string(cert.RawSubject)] 59 for _, c := range candidates { 60 if s.certs[c].Equal(cert) { 61 return true 62 } 63 } 64 65 return false 66 } 67 68 // AddCert adds a certificate to a pool. 69 func (s *CertPool) AddCert(cert *Certificate) { 70 if cert == nil { 71 panic("adding nil Certificate to CertPool") 72 } 73 74 // Check that the certificate isn't being added twice. 75 if s.contains(cert) { 76 return 77 } 78 79 n := len(s.certs) 80 s.certs = append(s.certs, cert) 81 82 if len(cert.SubjectKeyId) > 0 { 83 keyId := string(cert.SubjectKeyId) 84 s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n) 85 } 86 name := string(cert.RawSubject) 87 s.byName[name] = append(s.byName[name], n) 88 } 89 90 // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. 91 // It appends any certificates found to s and reports whether any certificates 92 // were successfully parsed. 93 // 94 // On many Linux systems, /etc/ssl/cert.pem will contain the system wide set 95 // of root CAs in a format suitable for this function. 96 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { 97 for len(pemCerts) > 0 { 98 var block *pem.Block 99 block, pemCerts = pem.Decode(pemCerts) 100 if block == nil { 101 break 102 } 103 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { 104 continue 105 } 106 107 cert, err := ParseCertificate(block.Bytes) 108 if err != nil { 109 continue 110 } 111 112 s.AddCert(cert) 113 ok = true 114 } 115 116 return 117 } 118 119 // Subjects returns a list of the DER-encoded subjects of 120 // all of the certificates in the pool. 121 func (s *CertPool) Subjects() [][]byte { 122 res := make([][]byte, len(s.certs)) 123 for i, c := range s.certs { 124 res[i] = c.RawSubject 125 } 126 return res 127 }