diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 8ca2bb1ee..9f7e1c242 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -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", diff --git a/vendor/github.com/cloudflare/cfssl/errors/error.go b/vendor/github.com/cloudflare/cfssl/errors/error.go index 607223765..50ef8ac17 100644 --- a/vendor/github.com/cloudflare/cfssl/errors/error.go +++ b/vendor/github.com/cloudflare/cfssl/errors/error.go @@ -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)) } diff --git a/vendor/github.com/cloudflare/cfssl/ocsp/responder.go b/vendor/github.com/cloudflare/cfssl/ocsp/responder.go index acccfb69d..467c877b6 100644 --- a/vendor/github.com/cloudflare/cfssl/ocsp/responder.go +++ b/vendor/github.com/cloudflare/cfssl/ocsp/responder.go @@ -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(), } } diff --git a/vendor/github.com/cloudflare/cfssl/signer/local/local.go b/vendor/github.com/cloudflare/cfssl/signer/local/local.go index 686deac9d..de07fb1c5 100644 --- a/vendor/github.com/cloudflare/cfssl/signer/local/local.go +++ b/vendor/github.com/cloudflare/cfssl/signer/local/local.go @@ -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) diff --git a/vendor/github.com/cloudflare/cfssl/signer/signer.go b/vendor/github.com/cloudflare/cfssl/signer/signer.go index 20101f682..97d123673 100644 --- a/vendor/github.com/cloudflare/cfssl/signer/signer.go +++ b/vendor/github.com/cloudflare/cfssl/signer/signer.go @@ -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.