// ParseCertificatesDER parses a DER encoding of a certificate object and possibly private key, // either PKCS #7, PKCS #12, or raw x509. func ParseCertificatesDER(certsDER []byte, password string) (certs []*x509.Certificate, key crypto.Signer, err error) { certsDER = bytes.TrimSpace(certsDER) pkcs7data, err := pkcs7.ParsePKCS7(certsDER) if err != nil { var pkcs12data interface{} certs = make([]*x509.Certificate, 1) pkcs12data, certs[0], err = pkcs12.Decode(certsDER, password) if err != nil { certs, err = x509.ParseCertificates(certsDER) if err != nil { return nil, nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed) } } else { key = pkcs12data.(crypto.Signer) } } else { if pkcs7data.ContentInfo != "SignedData" { return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.DecodeFailed, errors.New("can only extract certificates from signed data content info")) } certs = pkcs7data.Content.SignedData.Certificates } if certs == nil { return nil, key, cferr.New(cferr.CertificateError, cferr.DecodeFailed) } return certs, key, nil }
// NewBundlerFromPEM creates a new Bundler from PEM-encoded root certificates and // intermediate certificates. func NewBundlerFromPEM(caBundlePEM, intBundlePEM []byte) (*Bundler, error) { b := &Bundler{ RootPool: x509.NewCertPool(), IntermediatePool: x509.NewCertPool(), KnownIssuers: map[string]bool{}, } log.Debug("parsing root certificates from PEM") roots, err := helpers.ParseCertificatesPEM(caBundlePEM) if err != nil { log.Errorf("failed to parse root bundle: %v", err) return nil, errors.New(errors.RootError, errors.ParseFailed) } log.Debug("parse intermediate certificates from PEM") var intermediates []*x509.Certificate if intermediates, err = helpers.ParseCertificatesPEM(intBundlePEM); err != nil { log.Errorf("failed to parse intermediate bundle: %v", err) return nil, errors.New(errors.IntermediatesError, errors.ParseFailed) } log.Debug("building certificate pools") for _, c := range roots { b.RootPool.AddCert(c) b.KnownIssuers[string(c.Signature)] = true } for _, c := range intermediates { b.IntermediatePool.AddCert(c) b.KnownIssuers[string(c.Signature)] = true } log.Debug("bundler set up") return b, nil }
// Dial initiates a TLS connection to an outbound server. It returns a // TLS connection to the server. func Dial(address string, tr *Transport) (*tls.Conn, error) { host, _, err := net.SplitHostPort(address) if err != nil { // Assume address is a hostname, and that it should // use the HTTPS port number. host = address address = net.JoinHostPort(address, "443") } cfg, err := tr.TLSClientAuthClientConfig(host) if err != nil { return nil, err } conn, err := tls.Dial("tcp", address, cfg) if err != nil { return nil, err } state := conn.ConnectionState() if len(state.VerifiedChains) == 0 { return nil, errors.New(errors.CertificateError, errors.VerifyFailed) } for _, chain := range state.VerifiedChains { for _, cert := range chain { revoked, ok := revoke.VerifyCertificate(cert) if (!tr.RevokeSoftFail && !ok) || revoked { return nil, errors.New(errors.CertificateError, errors.VerifyFailed) } } } return conn, nil }
// NewBundler creates a new Bundler from the files passed in; these // files should contain a list of valid root certificates and a list // of valid intermediate certificates, respectively. func NewBundler(caBundleFile, intBundleFile string) (*Bundler, error) { log.Debug("Loading CA bundle: ", caBundleFile) caBundlePEM, err := ioutil.ReadFile(caBundleFile) if err != nil { log.Errorf("root bundle failed to load: %v", err) return nil, errors.New(errors.RootError, errors.None, err) } log.Debug("Loading Intermediate bundle: ", intBundleFile) intBundlePEM, err := ioutil.ReadFile(intBundleFile) if err != nil { log.Errorf("intermediate bundle failed to load: %v", err) return nil, errors.New(errors.IntermediatesError, errors.None, err) } if _, err := os.Stat(IntermediateStash); err != nil && os.IsNotExist(err) { log.Infof("intermediate stash directory %s doesn't exist, creating", IntermediateStash) err = os.MkdirAll(IntermediateStash, 0755) if err != nil { log.Errorf("failed to create intermediate stash directory %s: %v", err) return nil, err } log.Infof("intermediate stash directory %s created", IntermediateStash) } return NewBundlerFromPEM(caBundlePEM, intBundlePEM) }
// NewAuthHandlerFromSigner creates a new AuthHandler from the signer // that is passed in. func NewAuthHandlerFromSigner(signer signer.Signer) (http.Handler, error) { policy := signer.Policy() if policy == nil { return nil, errors.New(errors.PolicyError, errors.InvalidPolicy) } if policy.Default == nil && policy.Profiles == nil { return nil, errors.New(errors.PolicyError, errors.InvalidPolicy) } // AuthSign will not respond for profiles that have no auth provider. // So if there are no profiles with auth providers in this policy, // we return an error. haveAuth := (policy.Default.Provider != nil) for _, profile := range policy.Profiles { if haveAuth { break } haveAuth = (profile.Provider != nil) } if !haveAuth { return nil, errors.New(errors.PolicyError, errors.InvalidPolicy) } return &api.HTTPHandler{ Handler: &AuthHandler{ signer: signer, }, Methods: []string{"POST"}, }, nil }
// ParseCertificatesDER parses a DER encoding of a certificate object and possibly private key, // either PKCS #7, PKCS #12, or raw x509. func ParseCertificatesDER(certsDER []byte, password string) ([]*x509.Certificate, crypto.Signer, error) { var certs []*x509.Certificate var key crypto.Signer certsDER = bytes.TrimSpace(certsDER) pkcs7data, err := pkcs7.ParsePKCS7(certsDER) if err != nil { pkcs12data, err := pkcs12.ParsePKCS12(certsDER, []byte(password)) if err != nil { certs, err = x509.ParseCertificates(certsDER) if err != nil { return nil, nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed) } } else { key = pkcs12data.PrivateKey certs = pkcs12data.Certificates } } else { if pkcs7data.ContentInfo != "SignedData" { return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.DecodeFailed, errors.New("can only extract certificates from signed data content info")) } certs = pkcs7data.Content.SignedData.Certificates } if certs == nil { return nil, key, cferr.New(cferr.CertificateError, cferr.DecodeFailed) } return certs, key, nil }
// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, or elliptic curve // DER-encoded private key. The key must not be in PEM format. func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) { generalKey, err := x509.ParsePKCS8PrivateKey(keyDER) if err != nil { generalKey, err = x509.ParsePKCS1PrivateKey(keyDER) if err != nil { generalKey, err = x509.ParseECPrivateKey(keyDER) if err != nil { // We don't include the actual error into // the final error. The reason might be // we don't want to leak any info about // the private key. return nil, cferr.New(cferr.PrivateKeyError, cferr.ParseFailed) } } } switch generalKey.(type) { case *rsa.PrivateKey: return generalKey.(*rsa.PrivateKey), nil case *ecdsa.PrivateKey: return generalKey.(*ecdsa.PrivateKey), nil } // should never reach here return nil, cferr.New(cferr.PrivateKeyError, cferr.ParseFailed) }
// Sign signs a new certificate based on the PEM-encoded client // certificate or certificate request with the signing profile, specified by profileName. // The certificate will be valid for the host named in the hostName parameter. func (s *Signer) Sign(hostName string, in []byte, profileName string) (cert []byte, err error) { profile := s.Policy.Profiles[profileName] block, _ := pem.Decode(in) if block == nil { return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed, err) } var template *x509.Certificate switch block.Type { case "CERTIFICATE": template, err = helpers.ParseSelfSignedCertificatePEM(in) case "CERTIFICATE REQUEST": template, err = s.parseCertificateRequest(block.Bytes) default: return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed, errors.New("Not a certificate or csr.")) } if err != nil { return } if ip := net.ParseIP(hostName); ip != nil { template.IPAddresses = []net.IP{ip} } else { template.DNSNames = []string{hostName} } return s.sign(template, profile) }
// NewSignHandlerFromSigner generates a new SignHandler directly from // an existing signer. func NewSignHandlerFromSigner(s signer.Signer) (h http.Handler, err error) { policy := s.Policy() if policy == nil { err = errors.New(errors.PolicyError, errors.InvalidPolicy) return } // Sign will only respond for profiles that have no auth provider. // So if all of the profiles require authentication, we return an error. haveUnauth := (policy.Default.Provider == nil) for _, profile := range policy.Profiles { if !haveUnauth { break } haveUnauth = (profile.Provider == nil) } if !haveUnauth { err = errors.New(errors.PolicyError, errors.InvalidPolicy) return } return &api.HTTPHandler{ Handler: &SignHandler{ signer: s, }, Methods: []string{"POST"}, }, nil }
// ParsePrivateKeyPEM parses and returns a PEM-encoded private // key. The private key may be either an unencrypted PKCS#8, PKCS#1, // or elliptic private key. func ParsePrivateKeyPEM(keyPEM []byte) (key interface{}, err error) { keyDER, _ := pem.Decode(keyPEM) if keyDER == nil { return nil, cferr.New(cferr.PrivateKeyError, cferr.DecodeFailed, nil) } if procType, ok := keyDER.Headers["Proc-Type"]; ok { if strings.Contains(procType, "ENCRYPTED") { return nil, cferr.New(cferr.PrivateKeyError, cferr.Encrypted, nil) } } key, err = x509.ParsePKCS8PrivateKey(keyDER.Bytes) if err != nil { key, err = x509.ParsePKCS1PrivateKey(keyDER.Bytes) if err != nil { key, err = x509.ParseECPrivateKey(keyDER.Bytes) if err != nil { // We don't include the actual error into the final error. // The reason might be we don't want to leak any info about // the private key. return nil, cferr.New(cferr.PrivateKeyError, cferr.ParseFailed, nil) } } } return }
// BundleFromRemote fetches the certificate chain served by the server at // serverName (or ip, if the ip argument is not the empty string). It // is expected that the method will be able to make a connection at // port 443. The chain used by the server in this connection is // used to rebuild the bundle. func (b *Bundler) BundleFromRemote(serverName, ip string) (*Bundle, error) { config := &tls.Config{ RootCAs: b.RootPool, ServerName: serverName, } // Dial by IP if present var dialName string if ip != "" { dialName = ip + ":443" } else { dialName = serverName + ":443" } log.Debugf("bundling from remote %s", dialName) conn, err := tls.Dial("tcp", dialName, config) var dialError string // If there's an error in tls.Dial, try again with // InsecureSkipVerify to fetch the remote bundle to (re-)bundle with. // If the bundle is indeed not usable (expired, mismatched hostnames, etc.), // report the error. // Otherwise, create a working bundle and insert the tls error in the bundle.Status. if err != nil { log.Debugf("dial failed: %v", err) // record the error msg dialError = fmt.Sprintf("Failed rigid TLS handshake with %s: %v", dialName, err) // dial again with InsecureSkipVerify log.Debugf("try again with InsecureSkipVerify.") config.InsecureSkipVerify = true conn, err = tls.Dial("tcp", dialName, config) if err != nil { log.Debugf("dial with InsecureSkipVerify failed: %v", err) return nil, errors.New(errors.DialError, errors.Unknown, err) } } connState := conn.ConnectionState() certs := connState.PeerCertificates err = conn.VerifyHostname(serverName) if err != nil { log.Debugf("failed to verify hostname: %v", err) return nil, errors.New(errors.CertificateError, errors.VerifyFailed, err) } // verify peer intermediates and store them if there is any missing from the bundle. // Don't care if there is error, will throw it any way in Bundle() call. b.fetchIntermediates(certs) // Bundle with remote certs. Inject the initial dial error, if any, to the status reporting. bundle, err := b.Bundle(certs, nil, Ubiquitous) if err != nil { return nil, err } else if dialError != "" { bundle.Status.Messages = append(bundle.Status.Messages, dialError) } return bundle, err }
// NewSigner generates a new certificate signer from a Root structure. // This is one of two standard signers: local or remote. If the root // structure specifies a force remote, then a remote signer is created, // otherwise either a remote or local signer is generated based on the // policy. For a local signer, the CertFile and KeyFile need to be // defined in Root. func NewSigner(root Root, policy *config.Signing) (signer.Signer, error) { if policy == nil { policy = &config.Signing{ Profiles: map[string]*config.SigningProfile{}, Default: config.DefaultConfig(), } } if !policy.Valid() { return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy) } var s signer.Signer var err error if root.ForceRemote { s, err = remote.NewSigner(policy) } else { if policy.NeedsLocalSigner() && policy.NeedsRemoteSigner() { // Currently we don't support a hybrid signer return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy) } if policy.NeedsLocalSigner() { // shouldProvide indicates whether the // function *should* have produced a key. If // it's true, we should use the signer and // error returned. Otherwise, keep looking for // signers. var shouldProvide bool // localSignerList is defined in the // universal_signers*.go files. These activate // and deactivate signers based on build // flags; for example, // universal_signers_pkcs11.go contains a list // of valid signers when PKCS #11 is turned // on. for _, possibleSigner := range localSignerList { s, shouldProvide, err = possibleSigner(&root, policy) if shouldProvide { break } } if s == nil { err = cferr.New(cferr.PrivateKeyError, cferr.Unknown) } } if policy.NeedsRemoteSigner() { s, err = remote.NewSigner(policy) } } return s, err }
// NewSigner creates a new remote Signer directly from a // signing policy. func NewSigner(policy *config.Signing) (*Signer, error) { if policy != nil { if !policy.Valid() { return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy) } return &Signer{policy: policy}, nil } return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy) }
// ParseCertificatePEM parses and returns a PEM-encoded certificate. func ParseCertificatePEM(certPEM []byte) (*x509.Certificate, error) { certPEM = bytes.TrimSpace(certPEM) cert, rest, err := ParseOneCertificateFromPEM(certPEM) if err != nil { return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed, err) } else if cert == nil { return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed, nil) } else if len(rest) > 0 { return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed, errors.New("The PEM file should contain only one certificate.")) } return cert, nil }
// GetKeyDERFromPEM parses a PEM-encoded private key and returns DER-format key bytes. func GetKeyDERFromPEM(in []byte) ([]byte, error) { keyDER, _ := pem.Decode(in) if keyDER != nil { if procType, ok := keyDER.Headers["Proc-Type"]; ok { if strings.Contains(procType, "ENCRYPTED") { return nil, cferr.New(cferr.PrivateKeyError, cferr.Encrypted) } } return keyDER.Bytes, nil } return nil, cferr.New(cferr.PrivateKeyError, cferr.DecodeFailed) }
func newLocalSigner(root Root, policy *config.Signing) (s signer.Signer, err error) { // shouldProvide indicates whether the // function *should* have produced a key. If // it's true, we should use the signer and // error returned. Otherwise, keep looking for // signers. var shouldProvide bool // localSignerList is defined in the // universal_signers*.go files. These activate // and deactivate signers based on build // flags; for example, // universal_signers_pkcs11.go contains a list // of valid signers when PKCS #11 is turned // on. for _, possibleSigner := range localSignerList { s, shouldProvide, err = possibleSigner(&root, policy) if shouldProvide { break } } if s == nil { err = cferr.New(cferr.PrivateKeyError, cferr.Unknown) } return s, err }
// NewSigner generates a new certificate signer from a Root structure. // This is one of two standard signers: local or remote. If the root // structure specifies a force remote, then a remote signer is created, // otherwise either a remote or local signer is generated based on the // policy. For a local signer, the CertFile and KeyFile need to be // defined in Root. func NewSigner(root Root, policy *config.Signing) (signer.Signer, error) { if policy == nil { policy = &config.Signing{ Profiles: map[string]*config.SigningProfile{}, Default: config.DefaultConfig(), } } if !policy.Valid() { return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy) } var s signer.Signer var err error if root.ForceRemote { s, err = remote.NewSigner(policy) } else { if policy.NeedsLocalSigner() && policy.NeedsRemoteSigner() { s, err = newUniversalSigner(root, policy) } else { if policy.NeedsLocalSigner() { s, err = newLocalSigner(root, policy) } if policy.NeedsRemoteSigner() { s, err = remote.NewSigner(policy) } } } return s, err }
// post connects to the remote server and returns a Response struct func (srv *server) post(url string, jsonData []byte) (*api.Response, error) { buf := bytes.NewBuffer(jsonData) resp, err := http.Post(url, "application/json", buf) if err != nil { return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, err) } body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, errors.Wrap(errors.APIClientError, errors.IOError, err) } resp.Body.Close() if resp.StatusCode != http.StatusOK { return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, stderr.New(string(body))) } var response api.Response err = json.Unmarshal(body, &response) if err != nil { log.Debug("Unable to parse response body:", string(body)) return nil, errors.Wrap(errors.APIClientError, errors.JSONError, err) } if !response.Success || response.Result == nil { if len(response.Errors) > 0 { return nil, errors.Wrap(errors.APIClientError, errors.ServerRequestFailed, stderr.New(response.Errors[0].Message)) } return nil, errors.New(errors.APIClientError, errors.ServerRequestFailed) } return &response, nil }
// Generate creates a new CSR from a CertificateRequest structure and // an existing key. The KeyRequest field is ignored. func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err error) { sigAlgo := helpers.SignerAlgo(priv, crypto.SHA256) if sigAlgo == x509.UnknownSignatureAlgorithm { return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable) } var tpl = x509.CertificateRequest{ Subject: req.Name(), SignatureAlgorithm: sigAlgo, } for i := range req.Hosts { if ip := net.ParseIP(req.Hosts[i]); ip != nil { tpl.IPAddresses = append(tpl.IPAddresses, ip) } else { tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i]) } } csr, err = x509.CreateCertificateRequest(rand.Reader, &tpl, priv) if err != nil { log.Errorf("failed to generate a CSR: %v", err) err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err) return } block := pem.Block{ Type: "CERTIFICATE REQUEST", Bytes: csr, } log.Info("encoded CSR") csr = pem.EncodeToMemory(&block) return }
// pkcs11Signer looks for token, module, slot, and PIN configuration // options in the root. func pkcs11Signer(root *Root, policy *config.Signing) (signer.Signer, bool, error) { module := root.Config["pkcs11-module"] tokenLabel := root.Config["pkcs11-token-label"] privateKeyLabel := root.Config["pkcs11-private-key-label"] userPIN := root.Config["pkcs11-user-pin"] certFile := root.Config["cert-file"] if module == "" && tokenLabel == "" && privateKeyLabel == "" && userPIN == "" { return nil, false, nil } if !pkcs11.Enabled { return nil, true, cferr.New(cferr.PrivateKeyError, cferr.Unavailable) } conf := pkcs11.Config{ Module: module, Token: tokenLabel, Label: privateKeyLabel, PIN: userPIN, } s, err := pkcs11.New(certFile, policy, &conf) return s, true, err }
// ParseCertificatePEM parses and returns a PEM-encoded certificate, // can handle PEM encoded PKCS #7 structures. func ParseCertificatePEM(certPEM []byte) (*x509.Certificate, error) { certPEM = bytes.TrimSpace(certPEM) cert, rest, err := ParseOneCertificateFromPEM(certPEM) if err != nil { // Log the actual parsing error but throw a default parse error message. log.Debugf("Certificate parsing error: %v", err) return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed) } else if cert == nil { return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed) } else if len(rest) > 0 { return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("the PEM file should contain only one object")) } else if len(cert) > 1 { return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("the PKCS7 object in the PEM file should contain only one certificate")) } return cert[0], nil }
// Sign is used with an OCSP signer to request the issuance of // an OCSP response. func (s StandardSigner) Sign(req SignRequest) ([]byte, error) { if req.Certificate == nil { return nil, cferr.New(cferr.OCSPError, cferr.ReadFailed) } // Verify that req.Certificate is issued under s.issuer if bytes.Compare(req.Certificate.RawIssuer, s.issuer.RawSubject) != 0 { return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch) } if req.Certificate.CheckSignatureFrom(s.issuer) != nil { return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch) } // Round thisUpdate times down to the nearest hour thisUpdate := time.Now().Truncate(time.Hour) nextUpdate := thisUpdate.Add(s.interval) status, ok := StatusCode[req.Status] if !ok { return nil, cferr.New(cferr.OCSPError, cferr.InvalidStatus) } // If the OCSP responder is the same as the issuer, there is no need to // include any certificate in the OCSP response, which decreases the byte size // of OCSP responses dramatically. certificate := s.responder if s.issuer == s.responder || bytes.Equal(s.issuer.Raw, s.responder.Raw) { certificate = nil } template := ocsp.Response{ Status: status, SerialNumber: req.Certificate.SerialNumber, ThisUpdate: thisUpdate, NextUpdate: nextUpdate, Certificate: certificate, ExtraExtensions: req.Extensions, IssuerHash: req.IssuerHash, } if status == ocsp.Revoked { template.RevokedAt = req.RevokedAt template.RevocationReason = req.Reason } return ocsp.CreateResponse(s.issuer, s.responder, template, s.key) }
// Sign signs a new certificate based on the PEM-encoded client // certificate or certificate request with the signing profile, // specified by profileName. func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) { profile, err := signer.Profile(s, req.Profile) if err != nil { return } serialSeq := "" if profile.UseSerialSeq { serialSeq = req.SerialSeq } block, _ := pem.Decode([]byte(req.Request)) if block == nil { return nil, cferr.New(cferr.CSRError, cferr.DecodeFailed) } if block.Type != "CERTIFICATE REQUEST" { return nil, cferr.Wrap(cferr.CSRError, cferr.BadRequest, errors.New("not a certificate or csr")) } csrTemplate, err := signer.ParseCertificateRequest(s, block.Bytes) if err != nil { return nil, err } // Copy out only the fields from the CSR authorized by policy. safeTemplate := x509.Certificate{} // If the profile contains no explicit whitelist, assume that all fields // should be copied from the CSR. if profile.CSRWhitelist == nil { safeTemplate = *csrTemplate } else { if profile.CSRWhitelist.Subject { safeTemplate.Subject = csrTemplate.Subject } if profile.CSRWhitelist.PublicKeyAlgorithm { safeTemplate.PublicKeyAlgorithm = csrTemplate.PublicKeyAlgorithm } if profile.CSRWhitelist.PublicKey { safeTemplate.PublicKey = csrTemplate.PublicKey } if profile.CSRWhitelist.SignatureAlgorithm { safeTemplate.SignatureAlgorithm = csrTemplate.SignatureAlgorithm } if profile.CSRWhitelist.DNSNames { safeTemplate.DNSNames = csrTemplate.DNSNames } if profile.CSRWhitelist.IPAddresses { safeTemplate.IPAddresses = csrTemplate.IPAddresses } } OverrideHosts(&safeTemplate, req.Hosts) safeTemplate.Subject = PopulateSubjectFromCSR(req.Subject, safeTemplate.Subject) return s.sign(&safeTemplate, profile, serialSeq) }
// ParseSelfSignedCertificatePEM parses a PEM-encoded certificate and check if it is self-signed. func ParseSelfSignedCertificatePEM(certPEM []byte) (*x509.Certificate, error) { cert, err := ParseCertificatePEM(certPEM) if err != nil { return nil, err } if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil { return nil, cferr.New(cferr.CertificateError, cferr.VerifyFailed, err) } return cert, nil }
// NewBundlerFromPEM creates a new Bundler from PEM-encoded root certificates and // intermediate certificates. // If caBundlePEM is nil, the resulting Bundler can only do "Force" bundle. func NewBundlerFromPEM(caBundlePEM, intBundlePEM []byte) (*Bundler, error) { log.Debug("parsing root certificates from PEM") roots, err := helpers.ParseCertificatesPEM(caBundlePEM) if err != nil { log.Errorf("failed to parse root bundle: %v", err) return nil, errors.New(errors.RootError, errors.ParseFailed) } log.Debug("parse intermediate certificates from PEM") intermediates, err := helpers.ParseCertificatesPEM(intBundlePEM) if err != nil { log.Errorf("failed to parse intermediate bundle: %v", err) return nil, errors.New(errors.IntermediatesError, errors.ParseFailed) } b := &Bundler{ KnownIssuers: map[string]bool{}, IntermediatePool: x509.NewCertPool(), } log.Debug("building certificate pools") // RootPool will be nil if caBundlePEM is nil, also // that translates to caBundleFile is "". // Systems root store will be used. if caBundlePEM != nil { b.RootPool = x509.NewCertPool() } for _, c := range roots { b.RootPool.AddCert(c) b.KnownIssuers[string(c.Signature)] = true } for _, c := range intermediates { b.IntermediatePool.AddCert(c) b.KnownIssuers[string(c.Signature)] = true } log.Debug("bundler set up") return b, nil }
// ParseCertificatesPEM parses a sequence of PEM-encoded certificate and returns them. func ParseCertificatesPEM(certsPEM []byte) ([]*x509.Certificate, error) { var certs []*x509.Certificate var err error certsPEM = bytes.TrimSpace(certsPEM) for len(certsPEM) > 0 { var cert *x509.Certificate cert, certsPEM, err = ParseOneCertificateFromPEM(certsPEM) if err != nil { return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed, err) } else if cert == nil { break } certs = append(certs, cert) } if len(certsPEM) > 0 { return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed, nil) } return certs, nil }
func NewRemoteCertGenerator(validator Validator, remote string) (http.Handler, error) { log.Info("setting up a new remote certificate generator") cg := new(RemoteCertGeneratorHandler) if cg.remote = client.NewServer(remote); cg.remote == nil { log.Errorf("invalid address for remote server") return nil, errors.New(errors.DialError, errors.Unknown, nil) } cg.generator = &csr.Generator{validator} return HttpHandler{cg, "POST"}, nil }
// NewPKCS11Signer returns a new PKCS #11 signer. func NewPKCS11Signer(cfg ocspConfig.Config) (ocsp.Signer, error) { log.Debugf("Loading PKCS #11 module %s", cfg.PKCS11.Module) certData, err := ioutil.ReadFile(cfg.CACertFile) if err != nil { return nil, errors.New(errors.CertificateError, errors.ReadFailed) } cert, err := helpers.ParseCertificatePEM(certData) if err != nil { return nil, err } PKCS11 := cfg.PKCS11 priv, err := pkcs11key.New(PKCS11.Module, PKCS11.Token, PKCS11.PIN, PKCS11.Label) if err != nil { return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed) } return ocsp.NewSigner(cert, cert, priv, cfg.Interval) }
func (s *Signer) parseCertificateRequest(csrBytes []byte) (template *x509.Certificate, err error) { csr, err := x509.ParseCertificateRequest(csrBytes) if err != nil { err = cferr.New(cferr.CertificateError, cferr.ParseFailed, err) return } err = checkSignature(csr, csr.SignatureAlgorithm, csr.RawTBSCertificateRequest, csr.Signature) if err != nil { err = cferr.New(cferr.CertificateError, cferr.KeyMismatch, err) return } template = &x509.Certificate{ Subject: csr.Subject, PublicKeyAlgorithm: csr.PublicKeyAlgorithm, PublicKey: csr.PublicKey, SignatureAlgorithm: s.SigAlgo, } return }
// getMatchingProfile returns the SigningProfile that matches the profile passed. // if an empty profile string is passed it returns the default profile. func (s *Signer) getMatchingProfile(profile string) (*config.SigningProfile, error) { if profile == "" { return s.policy.Default, nil } for p, signingProfile := range s.policy.Profiles { if p == profile { return signingProfile, nil } } return nil, cferr.New(cferr.PolicyError, cferr.UnknownProfile) }