OSDN Git Service

feat: add processIssuing (#152)
[bytom/vapor.git] / vendor / github.com / bytom / crypto / sm2 / cert_pool.go
diff --git a/vendor/github.com/bytom/crypto/sm2/cert_pool.go b/vendor/github.com/bytom/crypto/sm2/cert_pool.go
new file mode 100644 (file)
index 0000000..0a29b46
--- /dev/null
@@ -0,0 +1,214 @@
+package sm2
+
+import (
+       "encoding/pem"
+       "errors"
+       "io/ioutil"
+       "os"
+       "runtime"
+       "sync"
+)
+
+// Possible certificate files; stop after finding one.
+var certFiles = []string{
+       "/etc/ssl/certs/ca-certificates.crt",                // Debian/Ubuntu/Gentoo etc.
+       "/etc/pki/tls/certs/ca-bundle.crt",                  // Fedora/RHEL 6
+       "/etc/ssl/ca-bundle.pem",                            // OpenSUSE
+       "/etc/pki/tls/cacert.pem",                           // OpenELEC
+       "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
+}
+
+// CertPool is a set of certificates.
+type CertPool struct {
+       bySubjectKeyId map[string][]int
+       byName         map[string][]int
+       certs          []*Certificate
+}
+
+// NewCertPool returns a new, empty CertPool.
+func NewCertPool() *CertPool {
+       return &CertPool{
+               bySubjectKeyId: make(map[string][]int),
+               byName:         make(map[string][]int),
+       }
+}
+
+// Possible directories with certificate files; stop after successfully
+// reading at least one file from a directory.
+var certDirectories = []string{
+       "/etc/ssl/certs",               // SLES10/SLES11, https://golang.org/issue/12139
+       "/system/etc/security/cacerts", // Android
+}
+
+var (
+       once           sync.Once
+       systemRoots    *CertPool
+       systemRootsErr error
+)
+
+func systemRootsPool() *CertPool {
+       once.Do(initSystemRoots)
+       return systemRoots
+}
+
+func initSystemRoots() {
+       systemRoots, systemRootsErr = loadSystemRoots()
+}
+
+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
+       return nil, nil
+}
+
+func loadSystemRoots() (*CertPool, error) {
+       roots := NewCertPool()
+       var firstErr error
+       for _, file := range certFiles {
+               data, err := ioutil.ReadFile(file)
+               if err == nil {
+                       roots.AppendCertsFromPEM(data)
+                       return roots, nil
+               }
+               if firstErr == nil && !os.IsNotExist(err) {
+                       firstErr = err
+               }
+       }
+
+       for _, directory := range certDirectories {
+               fis, err := ioutil.ReadDir(directory)
+               if err != nil {
+                       if firstErr == nil && !os.IsNotExist(err) {
+                               firstErr = err
+                       }
+                       continue
+               }
+               rootsAdded := false
+               for _, fi := range fis {
+                       data, err := ioutil.ReadFile(directory + "/" + fi.Name())
+                       if err == nil && roots.AppendCertsFromPEM(data) {
+                               rootsAdded = true
+                       }
+               }
+               if rootsAdded {
+                       return roots, nil
+               }
+       }
+
+       return nil, firstErr
+}
+
+// SystemCertPool returns a copy of the system cert pool.
+//
+// Any mutations to the returned pool are not written to disk and do
+// not affect any other pool.
+func SystemCertPool() (*CertPool, error) {
+       if runtime.GOOS == "windows" {
+               // Issue 16736, 18609:
+               return nil, errors.New("crypto/x509: system root pool is not available on Windows")
+       }
+
+       return loadSystemRoots()
+}
+
+// findVerifiedParents attempts to find certificates in s which have signed the
+// given certificate. If any candidates were rejected then errCert will be set
+// to one of them, arbitrarily, and err will contain the reason that it was
+// rejected.
+func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
+       if s == nil {
+               return
+       }
+       var candidates []int
+
+       if len(cert.AuthorityKeyId) > 0 {
+               candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
+       }
+       if len(candidates) == 0 {
+               candidates = s.byName[string(cert.RawIssuer)]
+       }
+
+       for _, c := range candidates {
+               if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
+                       parents = append(parents, c)
+               } else {
+                       errCert = s.certs[c]
+               }
+       }
+
+       return
+}
+
+func (s *CertPool) contains(cert *Certificate) bool {
+       if s == nil {
+               return false
+       }
+
+       candidates := s.byName[string(cert.RawSubject)]
+       for _, c := range candidates {
+               if s.certs[c].Equal(cert) {
+                       return true
+               }
+       }
+
+       return false
+}
+
+// AddCert adds a certificate to a pool.
+func (s *CertPool) AddCert(cert *Certificate) {
+       if cert == nil {
+               panic("adding nil Certificate to CertPool")
+       }
+
+       // Check that the certificate isn't being added twice.
+       if s.contains(cert) {
+               return
+       }
+
+       n := len(s.certs)
+       s.certs = append(s.certs, cert)
+
+       if len(cert.SubjectKeyId) > 0 {
+               keyId := string(cert.SubjectKeyId)
+               s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
+       }
+       name := string(cert.RawSubject)
+       s.byName[name] = append(s.byName[name], n)
+}
+
+// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
+// It appends any certificates found to s and reports whether any certificates
+// were successfully parsed.
+//
+// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
+// of root CAs in a format suitable for this function.
+func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
+       for len(pemCerts) > 0 {
+               var block *pem.Block
+               block, pemCerts = pem.Decode(pemCerts)
+               if block == nil {
+                       break
+               }
+               if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
+                       continue
+               }
+
+               cert, err := ParseCertificate(block.Bytes)
+               if err != nil {
+                       continue
+               }
+
+               s.AddCert(cert)
+               ok = true
+       }
+
+       return
+}
+
+// Subjects returns a list of the DER-encoded subjects of
+// all of the certificates in the pool.
+func (s *CertPool) Subjects() [][]byte {
+       res := make([][]byte, len(s.certs))
+       for i, c := range s.certs {
+               res[i] = c.RawSubject
+       }
+       return res
+}