Update github.com/cloudflare/cfssl (#3528)

```
 roland@catbus  ~/code/go/src/github.com/cloudflare/cfssl   master  ./test.sh
BUILDING.md		Gopkg.toml		certdb			crl			helpers			revoke			test.sh
CHANGELOG		LICENSE			certinfo		crypto			info			scan			testdata
Dockerfile		README.md		cli			csr			initca			script			transport
Dockerfile.build	api			cmd			doc			log			selfsign		ubiquity
Dockerfile.minimal	auth			config			errors			multiroot		signer			vendor
Gopkg.lock		bundler			coverprofile.txt	gopath			ocsp			test.prof		whitelist
ok  	github.com/cloudflare/cfssl/api	1.043s	coverage: 81.1% of statements
ok  	github.com/cloudflare/cfssl/api/bundle	1.570s	coverage: 87.2% of statements
ok  	github.com/cloudflare/cfssl/api/certadd	12.607s	coverage: 86.8% of statements
ok  	github.com/cloudflare/cfssl/api/client	1.070s	coverage: 52.2% of statements
ok  	github.com/cloudflare/cfssl/api/crl	1.107s	coverage: 75.0% of statements
ok  	github.com/cloudflare/cfssl/api/gencrl	1.057s	coverage: 72.5% of statements
ok  	github.com/cloudflare/cfssl/api/generator	1.262s	coverage: 33.3% of statements
ok  	github.com/cloudflare/cfssl/api/info	1.102s	coverage: 84.1% of statements
ok  	github.com/cloudflare/cfssl/api/initca	1.073s	coverage: 90.5% of statements
ok  	github.com/cloudflare/cfssl/api/ocsp	1.116s	coverage: 93.8% of statements
ok  	github.com/cloudflare/cfssl/api/revoke	2.923s	coverage: 75.0% of statements
ok  	github.com/cloudflare/cfssl/api/scan	17.178s	coverage: 62.1% of statements
ok  	github.com/cloudflare/cfssl/api/sign	2.221s	coverage: 83.3% of statements
ok  	github.com/cloudflare/cfssl/api/signhandler	1.145s	coverage: 26.3% of statements
ok  	github.com/cloudflare/cfssl/auth	1.022s	coverage: 68.2% of statements
ok  	github.com/cloudflare/cfssl/bundler	14.899s	coverage: 84.5% of statements
ok  	github.com/cloudflare/cfssl/certdb/dbconf	1.040s	coverage: 84.2% of statements
ok  	github.com/cloudflare/cfssl/certdb/ocspstapling	1.283s	coverage: 69.2% of statements
ok  	github.com/cloudflare/cfssl/certdb/sql	1.092s	coverage: 70.5% of statements
ok  	github.com/cloudflare/cfssl/cli	1.036s	coverage: 61.9% of statements
ok  	github.com/cloudflare/cfssl/cli/bundle	1.034s	coverage: 0.0% of statements [no tests to run]
ok  	github.com/cloudflare/cfssl/cli/crl	1.106s	coverage: 57.8% of statements
ok  	github.com/cloudflare/cfssl/cli/gencert	6.106s	coverage: 83.6% of statements
ok  	github.com/cloudflare/cfssl/cli/gencrl	1.081s	coverage: 73.3% of statements
ok  	github.com/cloudflare/cfssl/cli/gencsr	1.075s	coverage: 70.3% of statements
ok  	github.com/cloudflare/cfssl/cli/genkey	2.903s	coverage: 70.0% of statements
ok  	github.com/cloudflare/cfssl/cli/ocsprefresh	1.074s	coverage: 64.3% of statements
ok  	github.com/cloudflare/cfssl/cli/revoke	1.054s	coverage: 88.2% of statements
ok  	github.com/cloudflare/cfssl/cli/scan	1.032s	coverage: 36.0% of statements
ok  	github.com/cloudflare/cfssl/cli/selfsign	2.429s	coverage: 73.2% of statements
ok  	github.com/cloudflare/cfssl/cli/serve	1.172s	coverage: 39.0% of statements
ok  	github.com/cloudflare/cfssl/cli/sign	1.058s	coverage: 54.8% of statements
ok  	github.com/cloudflare/cfssl/cli/version	1.028s	coverage: 100.0% of statements
ok  	github.com/cloudflare/cfssl/cmd/cfssl	1.196s	coverage: 0.0% of statements [no tests to run]
ok  	github.com/cloudflare/cfssl/cmd/cfssljson	1.031s	coverage: 3.4% of statements
ok  	github.com/cloudflare/cfssl/cmd/mkbundle	1.032s	coverage: 0.0% of statements [no tests to run]
ok  	github.com/cloudflare/cfssl/config	1.054s	coverage: 67.7% of statements
ok  	github.com/cloudflare/cfssl/crl	1.072s	coverage: 68.3% of statements
ok  	github.com/cloudflare/cfssl/csr	20.657s	coverage: 89.6% of statements
ok  	github.com/cloudflare/cfssl/errors	1.029s	coverage: 79.6% of statements
ok  	github.com/cloudflare/cfssl/helpers	1.225s	coverage: 82.8% of statements
ok  	github.com/cloudflare/cfssl/helpers/testsuite	6.558s	coverage: 65.8% of statements
ok  	github.com/cloudflare/cfssl/initca	81.870s	coverage: 73.2% of statements
ok  	github.com/cloudflare/cfssl/log	1.019s	coverage: 59.3% of statements
ok  	github.com/cloudflare/cfssl/multiroot/config	1.190s	coverage: 77.4% of statements
ok  	github.com/cloudflare/cfssl/ocsp	1.226s	coverage: 77.4% of statements
ok  	github.com/cloudflare/cfssl/revoke	1.832s	coverage: 77.9% of statements
ok  	github.com/cloudflare/cfssl/scan	1.042s	coverage: 1.1% of statements
ok  	github.com/cloudflare/cfssl/selfsign	1.073s	coverage: 70.0% of statements
ok  	github.com/cloudflare/cfssl/signer	1.030s	coverage: 19.4% of statements
ok  	github.com/cloudflare/cfssl/signer/local	3.171s	coverage: 78.1% of statements
ok  	github.com/cloudflare/cfssl/signer/remote	2.197s	coverage: 70.0% of statements
ok  	github.com/cloudflare/cfssl/signer/universal	2.061s	coverage: 67.7% of statements
ok  	github.com/cloudflare/cfssl/transport	1.031s
ok  	github.com/cloudflare/cfssl/transport/ca/localca	1.062s	coverage: 94.9% of statements
ok  	github.com/cloudflare/cfssl/transport/core	1.054s	coverage: 90.9% of statements
ok  	github.com/cloudflare/cfssl/transport/kp	1.059s	coverage: 37.1% of statements
ok  	github.com/cloudflare/cfssl/transport/roots/system	1.384s	coverage: 77.1% of statements
ok  	github.com/cloudflare/cfssl/ubiquity	1.057s	coverage: 88.3% of statements
ok  	github.com/cloudflare/cfssl/whitelist	2.060s	coverage: 100.0% of statements
```
This commit is contained in:
Roland Bracewell Shoemaker 2018-03-06 20:44:57 +00:00 committed by Jacob Hoffman-Andrews
parent 49d55d9ab5
commit 66695c0727
5 changed files with 147 additions and 52 deletions

64
Godeps/Godeps.json generated
View File

@ -12,83 +12,83 @@
},
{
"ImportPath": "github.com/cloudflare/cfssl/auth",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certdb",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certdb/dbconf",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certdb/sql",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/config",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/csr",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/errors",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/helpers",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/helpers/derhelpers",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/info",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/log",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/ocsp",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/ocsp/config",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/signer",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/cloudflare/cfssl/signer/local",
"Comment": "1.2.0-208-ged5223a",
"Rev": "ed5223a490ece4d66899bbb292e3e46c0677cb86"
"Comment": "1.3.1-8-g74f2ddc",
"Rev": "74f2ddc212e277519d83f942a8efd3bb9e243f16"
},
{
"ImportPath": "github.com/go-sql-driver/mysql",

View File

@ -194,6 +194,13 @@ const (
// CTClientConstructionFailed occurs when the construction of a new
// github.com/google/certificate-transparency client fails.
CTClientConstructionFailed
// PrecertMissingPoison occurs when a precert is passed to SignFromPrecert
// and is missing the CT poison extension.
PrecertMissingPoison
// PrecertInvalidPoison occurs when a precert is passed to SignFromPrecert
// and has a invalid CT poison extension value or the extension is not
// critical.
PrecertInvalidPoison
)
// Certificate persistence related errors specified with CertStoreError
@ -369,6 +376,10 @@ func New(category Category, reason Reason) *Error {
msg = "Certificate transparency parsing failed due to unknown error"
case PrecertSubmissionFailed:
msg = "Certificate transparency precertificate submission failed"
case PrecertMissingPoison:
msg = "Precertificate is missing CT poison extension"
case PrecertInvalidPoison:
msg = "Precertificate contains an invalid CT poison extension"
default:
panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CTError.", reason))
}

View File

@ -13,17 +13,18 @@ import (
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"time"
"github.com/cloudflare/cfssl/certdb"
"github.com/cloudflare/cfssl/certdb/dbconf"
"github.com/cloudflare/cfssl/certdb/sql"
"github.com/cloudflare/cfssl/log"
"github.com/jmhodges/clock"
"golang.org/x/crypto/ocsp"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"time"
)
var (
@ -186,7 +187,7 @@ type Responder struct {
func NewResponder(source Source) *Responder {
return &Responder{
Source: source,
clk: clock.Default(),
clk: clock.New(),
}
}

View File

@ -29,7 +29,6 @@ import (
"github.com/google/certificate-transparency-go/client"
"github.com/google/certificate-transparency-go/jsonclient"
"golang.org/x/net/context"
"time"
)
// Signer contains a signer that uses the standard library to
@ -97,16 +96,7 @@ func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signe
return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy)
}
func (s *Signer) sign(template *x509.Certificate, profile *config.SigningProfile, notBefore time.Time, notAfter time.Time) (cert []byte, err error) {
var distPoints = template.CRLDistributionPoints
if distPoints != nil && len(distPoints) > 0 {
template.CRLDistributionPoints = distPoints
}
err = signer.FillTemplate(template, s.policy.Default, profile, notBefore, notAfter)
if err != nil {
return nil, err
}
func (s *Signer) sign(template *x509.Certificate) (cert []byte, err error) {
var initRoot bool
if s.ca == nil {
if !template.IsCA {
@ -336,18 +326,31 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
}
}
var distPoints = safeTemplate.CRLDistributionPoints
err = signer.FillTemplate(&safeTemplate, s.policy.Default, profile, req.NotBefore, req.NotAfter)
if err != nil {
return nil, err
}
if distPoints != nil && len(distPoints) > 0 {
safeTemplate.CRLDistributionPoints = distPoints
}
var certTBS = safeTemplate
if len(profile.CTLogServers) > 0 {
if len(profile.CTLogServers) > 0 || req.ReturnPrecert {
// Add a poison extension which prevents validation
var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}}
var poisonedPreCert = certTBS
poisonedPreCert.ExtraExtensions = append(safeTemplate.ExtraExtensions, poisonExtension)
cert, err = s.sign(&poisonedPreCert, profile, req.NotBefore, req.NotAfter)
cert, err = s.sign(&poisonedPreCert)
if err != nil {
return
}
if req.ReturnPrecert {
return cert, nil
}
derCert, _ := pem.Decode(cert)
prechain := []ct.ASN1Cert{{Data: derCert.Bytes}, {Data: s.ca.Raw}}
var sctList []ct.SignedCertificateTimestamp
@ -383,7 +386,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
certTBS.ExtraExtensions = append(certTBS.ExtraExtensions, SCTListExtension)
}
var signedCert []byte
signedCert, err = s.sign(&certTBS, profile, req.NotBefore, req.NotAfter)
signedCert, err = s.sign(&certTBS)
if err != nil {
return nil, err
}
@ -415,6 +418,80 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
return signedCert, nil
}
// SignFromPrecert creates and signs a certificate from an existing precertificate
// that was previously signed by Signer.ca and inserts the provided SCTs into the
// new certificate. The resulting certificate will be a exact copy of the precert
// except for the removal of the poison extension and the addition of the SCT list
// extension. SignFromPrecert does not verify that the contents of the certificate
// still match the signing profile of the signer, it only requires that the precert
// was previously signed by the Signers CA.
func (s *Signer) SignFromPrecert(precert *x509.Certificate, scts []ct.SignedCertificateTimestamp) ([]byte, error) {
// Verify certificate was signed by s.ca
if err := precert.CheckSignatureFrom(s.ca); err != nil {
return nil, err
}
// Verify certificate is a precert
isPrecert := false
poisonIndex := 0
for i, ext := range precert.Extensions {
if ext.Id.Equal(signer.CTPoisonOID) {
if !ext.Critical {
return nil, cferr.New(cferr.CTError, cferr.PrecertInvalidPoison)
}
// Check extension contains ASN.1 NULL
if bytes.Compare(ext.Value, []byte{0x05, 0x00}) != 0 {
return nil, cferr.New(cferr.CTError, cferr.PrecertInvalidPoison)
}
isPrecert = true
poisonIndex = i
break
}
}
if !isPrecert {
return nil, cferr.New(cferr.CTError, cferr.PrecertMissingPoison)
}
// Serialize SCTs into list format and create extension
serializedList, err := helpers.SerializeSCTList(scts)
if err != nil {
return nil, err
}
sctExt := pkix.Extension{Id: signer.SCTListOID, Critical: false, Value: serializedList}
// Create the new tbsCert from precert. Do explicit copies of any slices so that we don't
// use memory that may be altered by us or the caller at a later stage.
tbsCert := x509.Certificate{
SignatureAlgorithm: precert.SignatureAlgorithm,
PublicKeyAlgorithm: precert.PublicKeyAlgorithm,
PublicKey: precert.PublicKey,
Version: precert.Version,
SerialNumber: precert.SerialNumber,
Issuer: precert.Issuer,
Subject: precert.Subject,
NotBefore: precert.NotBefore,
NotAfter: precert.NotAfter,
KeyUsage: precert.KeyUsage,
BasicConstraintsValid: precert.BasicConstraintsValid,
IsCA: precert.IsCA,
MaxPathLen: precert.MaxPathLen,
MaxPathLenZero: precert.MaxPathLenZero,
PermittedDNSDomainsCritical: precert.PermittedDNSDomainsCritical,
}
if len(precert.Extensions) > 0 {
tbsCert.ExtraExtensions = make([]pkix.Extension, len(precert.Extensions))
copy(tbsCert.ExtraExtensions, precert.Extensions)
}
// Remove the poison extension from ExtraExtensions
tbsCert.ExtraExtensions = append(tbsCert.ExtraExtensions[:poisonIndex], tbsCert.ExtraExtensions[poisonIndex+1:]...)
// Insert the SCT list extension
tbsCert.ExtraExtensions = append(tbsCert.ExtraExtensions, sctExt)
// Sign the tbsCert
return s.sign(&tbsCert)
}
// Info return a populated info.Resp struct or an error.
func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
cert, err := s.Certificate(req.Label, req.Profile)

View File

@ -64,6 +64,12 @@ type SignRequest struct {
// for canonicalization) as the value of the notAfter field of the
// certificate.
NotAfter time.Time
// If ReturnPrecert is true a certificate with the CT poison extension
// will be returned from the Signer instead of attempting to retrieve
// SCTs and populate the tbsCert with them itself. This precert can then
// be passed to SignFromPrecert with the SCTs in order to create a
// valid certificate.
ReturnPrecert bool
}
// appendIf appends to a if s is not an empty string.