Add SCT embedding (#3521)

Adds SCT embedding to the certificate issuance flow. When a issuance is requested a precertificate (the requested certificate but poisoned with the critical CT extension) is issued and submitted to the required CT logs. Once the SCTs for the precertificate have been collected a new certificate is issued with the poison extension replace with a SCT list extension containing the retrieved SCTs.

Fixes #2244, fixes #3492 and fixes #3429.
This commit is contained in:
Roland Bracewell Shoemaker 2018-03-12 18:58:30 +00:00 committed by Jacob Hoffman-Andrews
parent 6ad718a42e
commit 9c9e944759
27 changed files with 468 additions and 276 deletions

View File

@ -22,6 +22,8 @@ import (
"github.com/cloudflare/cfssl/ocsp"
"github.com/cloudflare/cfssl/signer"
"github.com/cloudflare/cfssl/signer/local"
"github.com/google/certificate-transparency-go"
cttls "github.com/google/certificate-transparency-go/tls"
"github.com/jmhodges/clock"
"github.com/miekg/pkcs11"
"golang.org/x/net/context"
@ -29,9 +31,9 @@ import (
"github.com/letsencrypt/boulder/ca/config"
caPB "github.com/letsencrypt/boulder/ca/proto"
"github.com/letsencrypt/boulder/core"
corePB "github.com/letsencrypt/boulder/core/proto"
csrlib "github.com/letsencrypt/boulder/csr"
berrors "github.com/letsencrypt/boulder/errors"
"github.com/letsencrypt/boulder/features"
"github.com/letsencrypt/boulder/goodkey"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/metrics"
@ -99,6 +101,13 @@ type certificateStorage interface {
AddCertificate(context.Context, []byte, int64, []byte) (string, error)
}
type certificateType string
const (
precertType = certificateType("precertificate")
certType = certificateType("certificate")
)
// CertificateAuthorityImpl represents a CA that signs certificates, CRLs, and
// OCSP responses.
type CertificateAuthorityImpl struct {
@ -135,7 +144,7 @@ type Issuer struct {
// issuer, including the cfssl signer and OCSP signer objects.
type internalIssuer struct {
cert *x509.Certificate
eeSigner signer.Signer
eeSigner *local.Signer
ocspSigner ocsp.Signer
}
@ -432,7 +441,7 @@ func (ca *CertificateAuthorityImpl) IssueCertificate(ctx context.Context, issueR
return emptyCert, err
}
certDER, err := ca.issueCertificateOrPrecertificate(ctx, issueReq, serialBigInt, validity, "cert", nil)
certDER, err := ca.issueCertificateOrPrecertificate(ctx, issueReq, serialBigInt, validity, certType)
if err != nil {
return emptyCert, err
}
@ -445,29 +454,60 @@ func (ca *CertificateAuthorityImpl) IssuePrecertificate(ctx context.Context, iss
return nil, berrors.InternalServerError("Precertificate flow is disabled")
}
if issueReq.RegistrationID == nil {
return nil, berrors.InternalServerError("RegistrationID is nil")
}
serialBigInt, validity, err := ca.generateSerialNumberAndValidity()
if err != nil {
return nil, err
}
precertDER, err := ca.issueCertificateOrPrecertificate(ctx, issueReq, serialBigInt, validity, "cert", &ctPoisonExtension)
precertDER, err := ca.issueCertificateOrPrecertificate(ctx, issueReq, serialBigInt, validity, precertType)
if err != nil {
return nil, err
}
return &caPB.IssuePrecertificateResponse{
Precert: &corePB.Precertificate{Der: precertDER},
SctFetchingConfig: &corePB.SCTFetchingConfig{},
DER: precertDER,
}, nil
}
// IssueCertificateForPrecertificate takes a precertificate and a set of SCTs for that precertificate
// and uses the signer to create and sign a certificate from them. The poison extension is removed
// and a SCT list extension is inserted in its place. Except for this and the signature the certificate
// exactly matches the precertificate. After the certificate is signed a OCSP response is generated
// and the response and certificate are stored in the database.
func (ca *CertificateAuthorityImpl) IssueCertificateForPrecertificate(ctx context.Context, req *caPB.IssueCertificateForPrecertificateRequest) (core.Certificate, error) {
emptyCert := core.Certificate{}
return emptyCert, berrors.InternalServerError("IssueCertificateForPrecertificate is not implemented")
if !features.Enabled(features.EmbedSCTs) {
return emptyCert, berrors.InternalServerError("IssueCertificateForPrecertificate is not implemented")
}
precert, err := x509.ParseCertificate(req.DER)
if err != nil {
return emptyCert, err
}
var scts []ct.SignedCertificateTimestamp
for _, sctBytes := range req.SCTs {
var sct ct.SignedCertificateTimestamp
_, err = cttls.Unmarshal(sctBytes, &sct)
if err != nil {
return emptyCert, err
}
scts = append(scts, sct)
}
certPEM, err := ca.defaultIssuer.eeSigner.SignFromPrecert(precert, scts)
if err != nil {
return emptyCert, err
}
serialHex := core.SerialToString(precert.SerialNumber)
block, _ := pem.Decode(certPEM)
if block == nil || block.Type != "CERTIFICATE" {
err = berrors.InternalServerError("invalid certificate value returned")
ca.log.AuditErr(fmt.Sprintf("PEM decode error, aborting: serial=[%s] pem=[%s] err=[%v]",
serialHex, certPEM, err))
return emptyCert, err
}
certDER := block.Bytes
ca.log.AuditInfo(fmt.Sprintf("Signing success: serial=[%s] names=[%s] precertificate=[%s] certificate=[%s]",
serialHex, strings.Join(precert.DNSNames, ", "), hex.EncodeToString(req.DER),
hex.EncodeToString(certDER)))
return ca.generateOCSPAndStoreCertificate(ctx, *req.RegistrationID, *req.OrderID, precert.SerialNumber, certDER)
}
type validity struct {
@ -498,7 +538,7 @@ func (ca *CertificateAuthorityImpl) generateSerialNumberAndValidity() (*big.Int,
return serialBigInt, validity, nil
}
func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context.Context, issueReq *caPB.IssueCertificateRequest, serialBigInt *big.Int, validity validity, certType string, addedExtension *signer.Extension) ([]byte, error) {
func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context.Context, issueReq *caPB.IssueCertificateRequest, serialBigInt *big.Int, validity validity, certType certificateType) ([]byte, error) {
csr, err := x509.ParseCertificateRequest(issueReq.Csr)
if err != nil {
return nil, err
@ -521,10 +561,6 @@ func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context
return nil, err
}
if addedExtension != nil {
extensions = append(extensions, *addedExtension)
}
issuer := ca.defaultIssuer
if issuer.cert.NotAfter.Before(validity.NotAfter) {
@ -565,6 +601,10 @@ func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context
NotAfter: validity.NotAfter,
}
if certType == precertType {
req.ReturnPrecert = true
}
serialHex := core.SerialToString(serialBigInt)
if !ca.forceCNFromSAN {
@ -581,7 +621,7 @@ func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context
ca.log.AuditErr(fmt.Sprintf("Signing failed: serial=[%s] err=[%v]", serialHex, err))
return nil, err
}
ca.signatureCount.With(prometheus.Labels{"purpose": certType}).Inc()
ca.signatureCount.With(prometheus.Labels{"purpose": string(certType)}).Inc()
if len(certPEM) == 0 {
err = berrors.InternalServerError("no certificate returned by server")

View File

@ -14,7 +14,11 @@ import (
cfsslConfig "github.com/cloudflare/cfssl/config"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/signer"
"github.com/google/certificate-transparency-go"
cttls "github.com/google/certificate-transparency-go/tls"
"github.com/jmhodges/clock"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/crypto/ocsp"
"golang.org/x/net/context"
@ -23,12 +27,12 @@ import (
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/core"
berrors "github.com/letsencrypt/boulder/errors"
"github.com/letsencrypt/boulder/features"
"github.com/letsencrypt/boulder/goodkey"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/metrics"
"github.com/letsencrypt/boulder/policy"
"github.com/letsencrypt/boulder/test"
"github.com/prometheus/client_golang/prometheus"
)
var (
@ -361,15 +365,14 @@ func TestIssueCertificate(t *testing.T) {
}
test.AssertNotError(t, err, "Failed to issue precertificate")
certDER = response.Precert.Der
certDER = response.DER
precertDER = certDER
} else {
coreCert := core.Certificate{}
if mode.issueCertificateForPrecertificate {
coreCert, err = ca.IssueCertificateForPrecertificate(ctx,
&caPB.IssueCertificateForPrecertificateRequest{
IssueReq: issueReq,
PrecertDER: precertDER,
DER: precertDER,
})
if true { // TODO(briansmith): !mode.enablePrecertificateFlow
@ -816,9 +819,13 @@ func countMustStaple(t *testing.T, cert *x509.Certificate) (count int) {
func issueCertificateSubTestMustStapleWhenDisabled(t *testing.T, i *TestCertificateIssuance) {
// With ca.enableMustStaple = false, should issue successfully and not add
// Must Staple.
certType := "certificate"
if i.mode.issuePrecertificate {
certType = "precertificate"
}
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionTLSFeature, i.ca.csrExtensionCount), 1)
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionTLSFeatureInvalid, i.ca.csrExtensionCount), 0)
test.AssertEquals(t, signatureCountByPurpose("cert", i.ca.signatureCount), 1)
test.AssertEquals(t, signatureCountByPurpose(certType, i.ca.signatureCount), 1)
test.AssertEquals(t, countMustStaple(t, i.cert), 0)
}
@ -826,9 +833,13 @@ func issueCertificateSubTestMustStapleWhenEnabled(t *testing.T, i *TestCertifica
// With ca.enableMustStaple = true, a TLS feature extension should put a must-staple
// extension into the cert. Even if there are multiple TLS Feature extensions, only
// one extension should be included.
certType := "certificate"
if i.mode.issuePrecertificate {
certType = "precertificate"
}
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionTLSFeature, i.ca.csrExtensionCount), 1)
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionTLSFeatureInvalid, i.ca.csrExtensionCount), 0)
test.AssertEquals(t, signatureCountByPurpose("cert", i.ca.signatureCount), 1)
test.AssertEquals(t, signatureCountByPurpose(certType, i.ca.signatureCount), 1)
test.AssertEquals(t, countMustStaple(t, i.cert), 1)
}
@ -839,8 +850,12 @@ func issueCertificateSubTestTLSFeatureUnknown(t *testing.T, ca *CertificateAutho
func issueCertificateSubTestUnknownExtension(t *testing.T, i *TestCertificateIssuance) {
// Unsupported extensions in the CSR should be silently ignored.
certType := "certificate"
if i.mode.issuePrecertificate {
certType = "precertificate"
}
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionOther, i.ca.csrExtensionCount), 1)
test.AssertEquals(t, signatureCountByPurpose("cert", i.ca.signatureCount), 1)
test.AssertEquals(t, signatureCountByPurpose(certType, i.ca.signatureCount), 1)
// NOTE: The hard-coded value here will have to change over time as Boulder
// adds new (unrequested) extensions to certificates.
@ -856,8 +871,12 @@ func issueCertificateSubTestCTPoisonExtension(t *testing.T, i *TestCertificateIs
// unknown extension, whether it has a valid or invalid value. The check
// for whether or not the poison extension is present in the issued
// certificate/precertificate is done in the caller.
certType := "certificate"
if i.mode.issuePrecertificate {
certType = "precertificate"
}
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionOther, i.ca.csrExtensionCount), 1)
test.AssertEquals(t, signatureCountByPurpose("cert", i.ca.signatureCount), 1)
test.AssertEquals(t, signatureCountByPurpose(certType, i.ca.signatureCount), 1)
}
func findExtension(extensions []pkix.Extension, id asn1.ObjectIdentifier) *pkix.Extension {
@ -872,3 +891,71 @@ func findExtension(extensions []pkix.Extension, id asn1.ObjectIdentifier) *pkix.
func signatureCountByPurpose(signatureType string, signatureCount *prometheus.CounterVec) int {
return test.CountCounterVec("purpose", signatureType, signatureCount)
}
func TestIssueCertificateForPrecertificate(t *testing.T) {
testCtx := setup(t)
sa := &mockSA{}
ca, err := NewCertificateAuthorityImpl(
testCtx.caConfig,
sa,
testCtx.pa,
testCtx.fc,
testCtx.stats,
testCtx.issuers,
testCtx.keyPolicy,
testCtx.logger)
test.AssertNotError(t, err, "Failed to create CA")
ca.enablePrecertificateFlow = true
_ = features.Set(map[string]bool{"EmbedSCTs": true})
defer features.Reset()
orderID := int64(0)
issueReq := caPB.IssueCertificateRequest{Csr: CNandSANCSR, RegistrationID: &arbitraryRegID, OrderID: &orderID}
precert, err := ca.IssuePrecertificate(ctx, &issueReq)
test.AssertNotError(t, err, "Failed to issue precert")
parsedPrecert, err := x509.ParseCertificate(precert.DER)
test.AssertNotError(t, err, "Failed to parse precert")
// Check for poison extension
poisoned := false
for _, ext := range parsedPrecert.Extensions {
if ext.Id.Equal(signer.CTPoisonOID) && ext.Critical {
poisoned = true
}
}
test.Assert(t, poisoned, "returned precert not poisoned")
sct := ct.SignedCertificateTimestamp{
SCTVersion: 0,
Timestamp: 2020,
Signature: ct.DigitallySigned{
Signature: []byte{0},
},
}
sctBytes, err := cttls.Marshal(sct)
test.AssertNotError(t, err, "Failed to marshal SCT")
cert, err := ca.IssueCertificateForPrecertificate(ctx, &caPB.IssueCertificateForPrecertificateRequest{
DER: precert.DER,
SCTs: [][]byte{sctBytes},
RegistrationID: &arbitraryRegID,
OrderID: new(int64),
})
test.AssertNotError(t, err, "Failed to issue cert from precert")
parsedCert, err := x509.ParseCertificate(cert.DER)
test.AssertNotError(t, err, "Failed to parse cert")
// Check for SCT list extension
list := false
for _, ext := range parsedCert.Extensions {
if ext.Id.Equal(signer.SCTListOID) && !ext.Critical {
list = true
var rawValue []byte
_, err = asn1.Unmarshal(ext.Value, &rawValue)
test.AssertNotError(t, err, "Failed to unmarshal extension value")
sctList, err := helpers.DeserializeSCTList(rawValue)
test.AssertNotError(t, err, "Failed to deserialize SCT list")
test.Assert(t, len(*sctList) == 1, fmt.Sprintf("Wrong number of SCTs, wanted: 1, got: %d", len(*sctList)))
}
}
test.Assert(t, list, "returned cert doesn't contain SCT list")
}

View File

@ -72,9 +72,8 @@ func (m *IssueCertificateRequest) GetOrderID() int64 {
}
type IssuePrecertificateResponse struct {
Precert *core.Precertificate `protobuf:"bytes,1,opt,name=precert" json:"precert,omitempty"`
SctFetchingConfig *core.SCTFetchingConfig `protobuf:"bytes,2,opt,name=sctFetchingConfig" json:"sctFetchingConfig,omitempty"`
XXX_unrecognized []byte `json:"-"`
DER []byte `protobuf:"bytes,1,opt,name=DER,json=dER" json:"DER,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *IssuePrecertificateResponse) Reset() { *m = IssuePrecertificateResponse{} }
@ -82,25 +81,19 @@ func (m *IssuePrecertificateResponse) String() string { return proto1
func (*IssuePrecertificateResponse) ProtoMessage() {}
func (*IssuePrecertificateResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *IssuePrecertificateResponse) GetPrecert() *core.Precertificate {
func (m *IssuePrecertificateResponse) GetDER() []byte {
if m != nil {
return m.Precert
}
return nil
}
func (m *IssuePrecertificateResponse) GetSctFetchingConfig() *core.SCTFetchingConfig {
if m != nil {
return m.SctFetchingConfig
return m.DER
}
return nil
}
type IssueCertificateForPrecertificateRequest struct {
IssueReq *IssueCertificateRequest `protobuf:"bytes,1,opt,name=issueReq" json:"issueReq,omitempty"`
PrecertDER []byte `protobuf:"bytes,2,opt,name=precertDER" json:"precertDER,omitempty"`
SCTs [][]byte `protobuf:"bytes,3,rep,name=SCTs,json=sCTs" json:"SCTs,omitempty"`
XXX_unrecognized []byte `json:"-"`
DER []byte `protobuf:"bytes,1,opt,name=DER,json=dER" json:"DER,omitempty"`
SCTs [][]byte `protobuf:"bytes,2,rep,name=SCTs,json=sCTs" json:"SCTs,omitempty"`
RegistrationID *int64 `protobuf:"varint,3,opt,name=registrationID" json:"registrationID,omitempty"`
OrderID *int64 `protobuf:"varint,4,opt,name=orderID" json:"orderID,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *IssueCertificateForPrecertificateRequest) Reset() {
@ -112,16 +105,9 @@ func (*IssueCertificateForPrecertificateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{2}
}
func (m *IssueCertificateForPrecertificateRequest) GetIssueReq() *IssueCertificateRequest {
func (m *IssueCertificateForPrecertificateRequest) GetDER() []byte {
if m != nil {
return m.IssueReq
}
return nil
}
func (m *IssueCertificateForPrecertificateRequest) GetPrecertDER() []byte {
if m != nil {
return m.PrecertDER
return m.DER
}
return nil
}
@ -133,6 +119,20 @@ func (m *IssueCertificateForPrecertificateRequest) GetSCTs() [][]byte {
return nil
}
func (m *IssueCertificateForPrecertificateRequest) GetRegistrationID() int64 {
if m != nil && m.RegistrationID != nil {
return *m.RegistrationID
}
return 0
}
func (m *IssueCertificateForPrecertificateRequest) GetOrderID() int64 {
if m != nil && m.OrderID != nil {
return *m.OrderID
}
return 0
}
type GenerateOCSPRequest struct {
CertDER []byte `protobuf:"bytes,1,opt,name=certDER" json:"certDER,omitempty"`
Status *string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
@ -404,34 +404,30 @@ var _OCSPGenerator_serviceDesc = grpc.ServiceDesc{
func init() { proto1.RegisterFile("ca/proto/ca.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 458 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x53, 0xc1, 0x6e, 0xd3, 0x40,
0x10, 0x4d, 0xe2, 0x94, 0xb4, 0x53, 0x83, 0x92, 0x69, 0x21, 0x56, 0x8a, 0x20, 0xf8, 0x80, 0x22,
0x84, 0x5c, 0x29, 0x17, 0x0e, 0x9c, 0x8a, 0xd3, 0xa2, 0x48, 0x48, 0x54, 0x9b, 0x70, 0xe1, 0xb6,
0xda, 0x4e, 0x52, 0x0b, 0xe1, 0x4d, 0x67, 0x37, 0x48, 0x1c, 0xf8, 0x0b, 0x24, 0x0e, 0xfc, 0x2c,
0xf2, 0xda, 0x0e, 0xc6, 0xb8, 0xed, 0x6d, 0x67, 0xde, 0xec, 0xbe, 0xe7, 0xf7, 0xc6, 0x30, 0x50,
0xf2, 0x74, 0xc3, 0xda, 0xea, 0x53, 0x25, 0x23, 0x77, 0xc0, 0x8e, 0x92, 0xa3, 0xc7, 0x4a, 0x33,
0x95, 0x80, 0x66, 0xca, 0xa1, 0xf0, 0x2b, 0x0c, 0xe7, 0xc6, 0x6c, 0x29, 0x26, 0xb6, 0xc9, 0x2a,
0x51, 0xd2, 0x92, 0xa0, 0x9b, 0x2d, 0x19, 0x8b, 0x7d, 0xf0, 0x94, 0xe1, 0xa0, 0x3d, 0x6e, 0x4f,
0x7c, 0x91, 0x1d, 0xf1, 0x25, 0x3c, 0x62, 0x5a, 0x27, 0xc6, 0xb2, 0xb4, 0x89, 0x4e, 0xe7, 0xb3,
0xa0, 0x33, 0x6e, 0x4f, 0x3c, 0x51, 0xeb, 0x62, 0x00, 0x3d, 0xcd, 0x57, 0xc4, 0xf3, 0x59, 0xe0,
0xb9, 0x81, 0xb2, 0x0c, 0x7f, 0xb6, 0xe1, 0xc4, 0xf1, 0x5d, 0x32, 0xa9, 0x2a, 0xa5, 0xd9, 0xe8,
0xd4, 0x10, 0x46, 0xd0, 0xdb, 0xe4, 0x88, 0xe3, 0x3d, 0x9c, 0x1e, 0x47, 0x4e, 0x6c, 0x6d, 0xbc,
0x1c, 0xc2, 0x73, 0x18, 0x18, 0x65, 0x2f, 0xc8, 0xaa, 0xeb, 0x24, 0x5d, 0xc7, 0x3a, 0x5d, 0x25,
0x6b, 0x27, 0xea, 0x70, 0x3a, 0xcc, 0x6f, 0x2e, 0xe2, 0xe5, 0xbf, 0xb0, 0xf8, 0xff, 0x46, 0xf8,
0xab, 0x0d, 0x93, 0xba, 0x0d, 0x17, 0x9a, 0xeb, 0x22, 0x73, 0x5f, 0xde, 0xc0, 0x7e, 0x92, 0xcd,
0x0a, 0xba, 0x29, 0x44, 0x9e, 0x44, 0x4a, 0x46, 0xb7, 0xd8, 0x28, 0x76, 0xc3, 0xf8, 0x0c, 0xa0,
0xd0, 0x3d, 0x3b, 0x17, 0x4e, 0xa5, 0x2f, 0x2a, 0x1d, 0x44, 0xe8, 0x2e, 0xe2, 0xa5, 0x09, 0xbc,
0xb1, 0x37, 0xf1, 0x45, 0xd7, 0xc4, 0x4b, 0x13, 0xfe, 0x80, 0xa3, 0xf7, 0x94, 0x12, 0x4b, 0x4b,
0x1f, 0xe3, 0xc5, 0x65, 0xa9, 0x21, 0x80, 0x5e, 0xf9, 0x4e, 0x9e, 0x4f, 0x59, 0xe2, 0x13, 0x78,
0x60, 0xac, 0xb4, 0x5b, 0xe3, 0x08, 0x0e, 0x44, 0x51, 0x65, 0x7d, 0x26, 0x69, 0x74, 0xea, 0x22,
0xd9, 0x13, 0x45, 0x85, 0x4f, 0xe1, 0x80, 0xe9, 0x9b, 0xfe, 0x42, 0x57, 0x67, 0x36, 0xe8, 0xba,
0xb4, 0xfe, 0x36, 0xc2, 0x57, 0xe0, 0xe7, 0xb4, 0x45, 0x3e, 0x23, 0xd8, 0xe7, 0xe2, 0x5c, 0x10,
0xef, 0xea, 0xe9, 0xef, 0x0e, 0x1c, 0x57, 0xbe, 0xff, 0x6c, 0x6b, 0xaf, 0x35, 0x27, 0xf6, 0x3b,
0xce, 0xa0, 0x5f, 0x37, 0x07, 0xef, 0xb2, 0x6c, 0x34, 0xc8, 0xa3, 0xab, 0x20, 0x61, 0x0b, 0x3f,
0xc1, 0x51, 0xc3, 0xe6, 0xdc, 0xfd, 0xd0, 0xf3, 0x1d, 0xd8, 0xbc, 0x6f, 0x61, 0x0b, 0x57, 0xf0,
0xe2, 0xde, 0xe4, 0xf1, 0x75, 0x13, 0xc9, 0x6d, 0x0b, 0xd2, 0x28, 0x7f, 0xfa, 0x01, 0x1e, 0x66,
0x4e, 0x16, 0x61, 0x6a, 0xc6, 0xb7, 0xe0, 0x57, 0x93, 0xc5, 0x61, 0xc6, 0xd1, 0x90, 0xf5, 0xa8,
0x9f, 0x01, 0xd5, 0x14, 0xc2, 0xd6, 0xbb, 0xde, 0xe7, 0x3d, 0xf7, 0xff, 0xfe, 0x09, 0x00, 0x00,
0xff, 0xff, 0x8f, 0x23, 0xc4, 0x53, 0xee, 0x03, 0x00, 0x00,
// 400 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xcf, 0xaf, 0xd2, 0x40,
0x10, 0xc7, 0x69, 0xcb, 0x13, 0xdf, 0xa4, 0x1a, 0xde, 0x3e, 0xf5, 0x35, 0xc5, 0x44, 0xec, 0xc1,
0x34, 0xc6, 0x94, 0x84, 0xab, 0x27, 0x6c, 0xd1, 0x90, 0x98, 0x48, 0x16, 0xbc, 0x78, 0xdb, 0x2c,
0x83, 0x36, 0xc6, 0x2e, 0xce, 0x6e, 0x4d, 0x3c, 0xf8, 0x4f, 0x78, 0xf5, 0x9f, 0x35, 0x2d, 0x2d,
0x94, 0xa6, 0x3c, 0x6e, 0xf3, 0x83, 0xe5, 0xf3, 0x9d, 0xf9, 0x4e, 0xe1, 0x46, 0x8a, 0xc9, 0x8e,
0x94, 0x51, 0x13, 0x29, 0xa2, 0x32, 0x60, 0xb6, 0x14, 0xfe, 0x53, 0xa9, 0x08, 0xeb, 0x86, 0x22,
0xdc, 0xb7, 0x82, 0x1f, 0x70, 0xb7, 0xd0, 0x3a, 0xc7, 0x18, 0xc9, 0xa4, 0xdb, 0x54, 0x0a, 0x83,
0x1c, 0x7f, 0xe6, 0xa8, 0x0d, 0x1b, 0x82, 0x23, 0x35, 0x79, 0xd6, 0xd8, 0x0a, 0x5d, 0x5e, 0x84,
0xec, 0x15, 0x3c, 0x26, 0xfc, 0x9a, 0x6a, 0x43, 0xc2, 0xa4, 0x2a, 0x5b, 0x24, 0x9e, 0x3d, 0xb6,
0x42, 0x87, 0xb7, 0xaa, 0xcc, 0x83, 0x81, 0xa2, 0x0d, 0xd2, 0x22, 0xf1, 0x9c, 0xf2, 0x07, 0x75,
0x1a, 0x4c, 0x60, 0x54, 0xe2, 0x96, 0x84, 0xb2, 0x49, 0xd4, 0x3b, 0x95, 0x69, 0x2c, 0x90, 0xc9,
0x9c, 0xd7, 0xc8, 0xcd, 0x9c, 0x07, 0x7f, 0x2d, 0x08, 0xdb, 0x02, 0xdf, 0x2b, 0x6a, 0xbf, 0x3f,
0x28, 0x3e, 0x7d, 0xce, 0x18, 0xf4, 0x57, 0xf1, 0x5a, 0x7b, 0xf6, 0xd8, 0x09, 0x5d, 0xde, 0xd7,
0xf1, 0x5a, 0x77, 0x4c, 0xe1, 0x5c, 0x9a, 0xa2, 0x7f, 0x3a, 0xc5, 0x1f, 0xb8, 0xfd, 0x80, 0x19,
0x92, 0x30, 0xf8, 0x29, 0x5e, 0x2d, 0x6b, 0xbc, 0x07, 0x83, 0x42, 0xd4, 0x51, 0x42, 0x9d, 0xb2,
0x67, 0xf0, 0x40, 0x1b, 0x61, 0x72, 0x5d, 0x2e, 0xec, 0x9a, 0x57, 0x59, 0x51, 0x27, 0x14, 0x5a,
0x65, 0xa5, 0x84, 0x2b, 0x5e, 0x65, 0xec, 0x39, 0x5c, 0x13, 0xfe, 0x52, 0xdf, 0x71, 0x33, 0x33,
0x15, 0xfc, 0x58, 0x08, 0x5e, 0x83, 0xbb, 0xc7, 0x56, 0x5b, 0xf3, 0xe1, 0x21, 0x55, 0x71, 0x05,
0x3e, 0xe4, 0xd3, 0x7f, 0x36, 0x3c, 0x69, 0xac, 0x6e, 0x96, 0x9b, 0x6f, 0x8a, 0x52, 0xf3, 0x9b,
0x25, 0x30, 0x6c, 0xef, 0x95, 0x8d, 0x22, 0x29, 0xa2, 0x33, 0xe7, 0xe0, 0xdf, 0x44, 0xe5, 0xd9,
0x34, 0x3a, 0x41, 0x8f, 0x7d, 0x86, 0xdb, 0x0e, 0x3f, 0xef, 0xff, 0xa3, 0x17, 0x87, 0x66, 0xf7,
0x15, 0x04, 0x3d, 0xb6, 0x85, 0x97, 0x17, 0x4d, 0x67, 0x6f, 0xba, 0x20, 0xe7, 0x6e, 0xa3, 0x53,
0xfe, 0xf4, 0x23, 0x3c, 0x2a, 0x36, 0x59, 0x99, 0xa9, 0x88, 0xbd, 0x05, 0xb7, 0xe9, 0x2c, 0xbb,
0x2b, 0x18, 0x1d, 0x5e, 0xfb, 0xc3, 0xa2, 0xd1, 0x74, 0x21, 0xe8, 0xbd, 0x1b, 0x7c, 0xb9, 0x2a,
0x3f, 0xaa, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x09, 0x3d, 0x95, 0xee, 0x83, 0x03, 0x00, 0x00,
}

View File

@ -27,14 +27,14 @@ message IssueCertificateRequest {
}
message IssuePrecertificateResponse {
optional core.Precertificate precert = 1;
optional core.SCTFetchingConfig sctFetchingConfig = 2;
optional bytes DER = 1;
}
message IssueCertificateForPrecertificateRequest {
optional IssueCertificateRequest issueReq = 1;
optional bytes precertDER = 2;
repeated bytes SCTs = 3;
optional bytes DER = 1;
repeated bytes SCTs = 2;
optional int64 registrationID = 3;
optional int64 orderID = 4;
}
message GenerateOCSPRequest {

View File

@ -151,16 +151,6 @@ func newUpdater(
failureBackoffFactor: config.SignFailureBackoffFactor,
failureBackoffMax: config.SignFailureBackoffMax.Duration,
},
// The missing SCT loop doesn't need to know about failureBackoffFactor or
// failureBackoffMax as it doesn't make any calls to the CA
{
clk: clk,
stats: stats.NewScope("MissingSCTReceipts"),
batchSize: config.MissingSCTBatchSize,
tickDur: config.MissingSCTWindow.Duration,
tickFunc: updater.missingReceiptsTick,
name: "MissingSCTReceipts",
},
}
if config.RevokedCertificateBatchSize != 0 &&
config.RevokedCertificateWindow.Duration != 0 {
@ -175,6 +165,18 @@ func newUpdater(
failureBackoffMax: config.SignFailureBackoffMax.Duration,
})
}
if !features.Enabled(features.EmbedSCTs) {
// The missing SCT loop doesn't need to know about failureBackoffFactor or
// failureBackoffMax as it doesn't make any calls to the CA
updater.loops = append(updater.loops, &looper{
clk: clk,
stats: stats.NewScope("MissingSCTReceipts"),
batchSize: config.MissingSCTBatchSize,
tickDur: config.MissingSCTWindow.Duration,
tickFunc: updater.missingReceiptsTick,
name: "MissingSCTReceipts",
})
}
// TODO(#1050): Remove this gate and the nil ccu checks below
if config.AkamaiBaseURL != "" {

View File

@ -586,9 +586,8 @@ type Order struct {
Status AcmeStatus
}
// SCTDER is a convenience type that helps differentiate what the
// underlying byte slice contains
type SCTDER []byte
// SCTDER is a convenience type
type SCTDERs [][]byte
// CertDER is a convenience type that helps differentiate what the
// underlying byte slice contains

View File

@ -12,9 +12,6 @@ It has these top-level messages:
Challenge
ValidationRecord
ProblemDetails
Precertificate
SCTFetchingConfig
SCTFetchingLogSet
Certificate
Registration
Authorization
@ -212,57 +209,6 @@ func (m *ProblemDetails) GetHttpStatus() int32 {
return 0
}
type Precertificate struct {
Der []byte `protobuf:"bytes,1,opt,name=der" json:"der,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *Precertificate) Reset() { *m = Precertificate{} }
func (m *Precertificate) String() string { return proto1.CompactTextString(m) }
func (*Precertificate) ProtoMessage() {}
func (*Precertificate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *Precertificate) GetDer() []byte {
if m != nil {
return m.Der
}
return nil
}
type SCTFetchingConfig struct {
LogSets []*SCTFetchingLogSet `protobuf:"bytes,1,rep,name=logSets" json:"logSets,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *SCTFetchingConfig) Reset() { *m = SCTFetchingConfig{} }
func (m *SCTFetchingConfig) String() string { return proto1.CompactTextString(m) }
func (*SCTFetchingConfig) ProtoMessage() {}
func (*SCTFetchingConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *SCTFetchingConfig) GetLogSets() []*SCTFetchingLogSet {
if m != nil {
return m.LogSets
}
return nil
}
type SCTFetchingLogSet struct {
LogURLs []string `protobuf:"bytes,1,rep,name=logURLs" json:"logURLs,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *SCTFetchingLogSet) Reset() { *m = SCTFetchingLogSet{} }
func (m *SCTFetchingLogSet) String() string { return proto1.CompactTextString(m) }
func (*SCTFetchingLogSet) ProtoMessage() {}
func (*SCTFetchingLogSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *SCTFetchingLogSet) GetLogURLs() []string {
if m != nil {
return m.LogURLs
}
return nil
}
type Certificate struct {
RegistrationID *int64 `protobuf:"varint,1,opt,name=registrationID" json:"registrationID,omitempty"`
Serial *string `protobuf:"bytes,2,opt,name=serial" json:"serial,omitempty"`
@ -276,7 +222,7 @@ type Certificate struct {
func (m *Certificate) Reset() { *m = Certificate{} }
func (m *Certificate) String() string { return proto1.CompactTextString(m) }
func (*Certificate) ProtoMessage() {}
func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *Certificate) GetRegistrationID() int64 {
if m != nil && m.RegistrationID != nil {
@ -335,7 +281,7 @@ type Registration struct {
func (m *Registration) Reset() { *m = Registration{} }
func (m *Registration) String() string { return proto1.CompactTextString(m) }
func (*Registration) ProtoMessage() {}
func (*Registration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
func (*Registration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *Registration) GetId() int64 {
if m != nil && m.Id != nil {
@ -407,7 +353,7 @@ type Authorization struct {
func (m *Authorization) Reset() { *m = Authorization{} }
func (m *Authorization) String() string { return proto1.CompactTextString(m) }
func (*Authorization) ProtoMessage() {}
func (*Authorization) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
func (*Authorization) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *Authorization) GetId() string {
if m != nil && m.Id != nil {
@ -475,7 +421,7 @@ type Order struct {
func (m *Order) Reset() { *m = Order{} }
func (m *Order) String() string { return proto1.CompactTextString(m) }
func (*Order) ProtoMessage() {}
func (*Order) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
func (*Order) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *Order) GetId() int64 {
if m != nil && m.Id != nil {
@ -554,15 +500,12 @@ type Empty struct {
func (m *Empty) Reset() { *m = Empty{} }
func (m *Empty) String() string { return proto1.CompactTextString(m) }
func (*Empty) ProtoMessage() {}
func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
func init() {
proto1.RegisterType((*Challenge)(nil), "core.Challenge")
proto1.RegisterType((*ValidationRecord)(nil), "core.ValidationRecord")
proto1.RegisterType((*ProblemDetails)(nil), "core.ProblemDetails")
proto1.RegisterType((*Precertificate)(nil), "core.Precertificate")
proto1.RegisterType((*SCTFetchingConfig)(nil), "core.SCTFetchingConfig")
proto1.RegisterType((*SCTFetchingLogSet)(nil), "core.SCTFetchingLogSet")
proto1.RegisterType((*Certificate)(nil), "core.Certificate")
proto1.RegisterType((*Registration)(nil), "core.Registration")
proto1.RegisterType((*Authorization)(nil), "core.Authorization")
@ -573,55 +516,51 @@ func init() {
func init() { proto1.RegisterFile("core/proto/core.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 795 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x51, 0x8e, 0xdb, 0x36,
0x10, 0x85, 0x2c, 0x2b, 0x5e, 0x8d, 0x55, 0xc7, 0x4b, 0x6c, 0x53, 0xa1, 0x28, 0x02, 0x41, 0x1f,
0x81, 0x10, 0xb4, 0x59, 0x34, 0x37, 0x48, 0xbd, 0x0d, 0x10, 0x20, 0x40, 0x0d, 0x7a, 0xd3, 0x8f,
0xfe, 0x69, 0xa5, 0x89, 0xcc, 0xae, 0x2c, 0x1a, 0x24, 0x1d, 0xd4, 0xbd, 0x43, 0x0f, 0xd2, 0xc3,
0xf4, 0x1a, 0xfd, 0xec, 0x19, 0x0a, 0x0e, 0x65, 0x9b, 0xb2, 0x53, 0xf4, 0x6f, 0xde, 0xe3, 0x88,
0x9c, 0x99, 0x37, 0x33, 0x82, 0x2f, 0x2b, 0xa9, 0xf0, 0x76, 0xab, 0xa4, 0x91, 0xb7, 0xd6, 0x7c,
0x45, 0x26, 0x1b, 0x5b, 0x3b, 0xff, 0x63, 0x04, 0xf1, 0x62, 0x5d, 0xb6, 0x2d, 0x76, 0x0d, 0xb2,
0x19, 0x8c, 0x44, 0x9d, 0x06, 0x59, 0x50, 0x84, 0x7c, 0x24, 0x6a, 0xc6, 0x60, 0x6c, 0xf6, 0x5b,
0x4c, 0x47, 0x59, 0x50, 0xc4, 0x9c, 0x6c, 0xf6, 0x0c, 0x9e, 0x68, 0x53, 0x9a, 0x9d, 0x4e, 0x9f,
0x10, 0xdb, 0x23, 0x36, 0x87, 0x70, 0xa7, 0x44, 0x1a, 0x13, 0x69, 0x4d, 0x76, 0x03, 0x91, 0x91,
0x8f, 0xd8, 0xa5, 0x21, 0x71, 0x0e, 0xb0, 0x97, 0x30, 0x7f, 0xc4, 0xfd, 0x9b, 0x9d, 0x59, 0x4b,
0x25, 0x7e, 0x2f, 0x8d, 0x90, 0x5d, 0x1a, 0x91, 0xc3, 0x05, 0xcf, 0xee, 0xe0, 0xfa, 0x53, 0xd9,
0x8a, 0x9a, 0x90, 0xc2, 0x4a, 0xaa, 0x5a, 0xa7, 0x90, 0x85, 0xc5, 0xf4, 0xf5, 0xb3, 0x57, 0x94,
0xcb, 0xcf, 0xc7, 0x63, 0x4e, 0xc7, 0xfc, 0xf2, 0x03, 0xf6, 0x12, 0x22, 0x54, 0x4a, 0xaa, 0x74,
0x92, 0x05, 0xc5, 0xf4, 0xf5, 0x8d, 0xfb, 0x72, 0xa9, 0xe4, 0x43, 0x8b, 0x9b, 0x3b, 0x34, 0xa5,
0x68, 0x35, 0x77, 0x2e, 0xf9, 0x3f, 0x01, 0xcc, 0xcf, 0xef, 0x64, 0x5f, 0xc3, 0xd5, 0x5a, 0x6a,
0xd3, 0x95, 0x1b, 0xa4, 0xe2, 0xc4, 0xfc, 0x88, 0x6d, 0x89, 0xb6, 0x52, 0x99, 0x43, 0x89, 0xac,
0xcd, 0xbe, 0x85, 0xeb, 0xb2, 0xae, 0x15, 0x6a, 0x8d, 0x9a, 0xa3, 0x96, 0xed, 0x27, 0xac, 0xd3,
0x30, 0x0b, 0x8b, 0x84, 0x5f, 0x1e, 0xb0, 0x0c, 0xa6, 0x3d, 0xf9, 0x41, 0x63, 0x9d, 0x8e, 0xb3,
0xa0, 0x48, 0xb8, 0x4f, 0x91, 0x87, 0xab, 0x8b, 0x11, 0xa8, 0xd3, 0x28, 0x0b, 0x8b, 0x98, 0xfb,
0x94, 0x2b, 0x7e, 0xdb, 0x2b, 0x62, 0x4d, 0xf6, 0x02, 0x66, 0xc7, 0xa7, 0xee, 0x95, 0xc0, 0x3a,
0x9d, 0x50, 0x00, 0x67, 0x6c, 0xfe, 0x2b, 0xcc, 0x86, 0x95, 0xb0, 0xaf, 0x6d, 0x1d, 0x73, 0x6f,
0xb5, 0x77, 0x09, 0xfb, 0x94, 0x6d, 0x81, 0x9a, 0x9c, 0xfb, 0xac, 0x7b, 0xc4, 0x9e, 0x03, 0xac,
0x8d, 0xd9, 0xae, 0x5c, 0x7b, 0x58, 0xd5, 0x23, 0xee, 0x31, 0x79, 0x6e, 0xdf, 0xc2, 0x0a, 0x95,
0x11, 0x1f, 0x45, 0x55, 0x1a, 0xb4, 0x71, 0xd7, 0xa8, 0xe8, 0x8d, 0x84, 0x5b, 0x33, 0x7f, 0x0b,
0xd7, 0xab, 0xc5, 0xfd, 0x5b, 0x34, 0xd5, 0x5a, 0x74, 0xcd, 0x42, 0x76, 0x1f, 0x45, 0xc3, 0xbe,
0x87, 0x49, 0x2b, 0x9b, 0x15, 0x1a, 0x9d, 0x06, 0xa4, 0xfe, 0x57, 0x4e, 0x43, 0xcf, 0xf3, 0x3d,
0x9d, 0xf3, 0x83, 0x5f, 0xfe, 0xdd, 0xe0, 0x1e, 0x77, 0xca, 0x52, 0xba, 0xe7, 0x03, 0x7f, 0xef,
0xee, 0x89, 0xf9, 0x01, 0xe6, 0x7f, 0x06, 0x30, 0x5d, 0x78, 0x81, 0xbd, 0x80, 0x99, 0xc2, 0x46,
0x68, 0xa3, 0xa8, 0x11, 0xde, 0xdd, 0xf5, 0x53, 0x71, 0xc6, 0xd2, 0x34, 0xa0, 0x12, 0xe5, 0xb1,
0x14, 0x0e, 0x51, 0x89, 0x44, 0x83, 0xda, 0xf4, 0xcd, 0xdf, 0xa3, 0x43, 0xc2, 0xe3, 0x63, 0xc2,
0xd6, 0x53, 0x68, 0xbd, 0xc3, 0x9a, 0xa6, 0x20, 0xe4, 0x3d, 0xb2, 0xb1, 0xe2, 0x6f, 0x5b, 0xa1,
0xd0, 0x0d, 0x5a, 0xc8, 0x0f, 0x30, 0xff, 0x3b, 0x80, 0x84, 0x7b, 0x61, 0x5c, 0x8c, 0xed, 0x1c,
0xc2, 0x47, 0xdc, 0x53, 0x44, 0x09, 0xb7, 0xa6, 0xbd, 0xac, 0x92, 0x9d, 0x29, 0x2b, 0x43, 0x7d,
0x18, 0xf3, 0x03, 0x64, 0x05, 0x3c, 0xed, 0x4d, 0xbd, 0x54, 0xa8, 0xb1, 0x33, 0x14, 0xdc, 0x15,
0x3f, 0xa7, 0xd9, 0x37, 0x10, 0x97, 0x8d, 0x42, 0xdc, 0x58, 0x1f, 0x37, 0xb1, 0x27, 0xc2, 0x9e,
0x8a, 0x4e, 0x18, 0x51, 0xb6, 0xef, 0x96, 0x14, 0x70, 0xc2, 0x4f, 0x84, 0x3d, 0xad, 0x14, 0x96,
0x06, 0xeb, 0x37, 0x86, 0xc6, 0x30, 0xe4, 0x27, 0xc2, 0x5b, 0x29, 0x57, 0xfe, 0x4a, 0xb1, 0xc3,
0xf8, 0xc5, 0x70, 0x21, 0x9c, 0x32, 0x8d, 0x29, 0xd3, 0xe7, 0x00, 0xa2, 0xc6, 0xce, 0xca, 0x86,
0xaa, 0x97, 0xc0, 0x63, 0x3e, 0x23, 0x63, 0xf8, 0x9f, 0x32, 0xba, 0x08, 0xc6, 0x83, 0xa5, 0xe6,
0x89, 0x10, 0x0d, 0x44, 0x60, 0xb7, 0x00, 0xd5, 0x61, 0x6f, 0x5a, 0x85, 0x6c, 0x57, 0x3e, 0x75,
0x5d, 0x79, 0xdc, 0xa7, 0xdc, 0x73, 0x61, 0x39, 0x24, 0x95, 0xdc, 0x3c, 0x88, 0x8e, 0xde, 0xd4,
0x54, 0x85, 0x84, 0x0f, 0xb8, 0xfc, 0xaf, 0x11, 0x44, 0x3f, 0x29, 0xdb, 0x15, 0xe7, 0x92, 0x5e,
0x26, 0x32, 0xfa, 0x6c, 0x22, 0x5e, 0xc0, 0xe1, 0x30, 0xe0, 0xe3, 0x16, 0x1c, 0xff, 0xef, 0x16,
0xb4, 0x0b, 0xcc, 0x9b, 0xd2, 0x95, 0x6b, 0x70, 0x27, 0xf9, 0xe5, 0x01, 0xad, 0x1a, 0x5f, 0x25,
0x57, 0x8e, 0x98, 0x9f, 0xb1, 0x5e, 0x91, 0x27, 0x83, 0x22, 0xdf, 0x40, 0x64, 0x57, 0xa9, 0x55,
0xdf, 0x7e, 0xe6, 0x80, 0x6d, 0xcc, 0x07, 0x6c, 0xca, 0x6e, 0xa9, 0x64, 0x85, 0x5a, 0x8b, 0xae,
0xa1, 0x7f, 0xcb, 0x15, 0x3f, 0xa7, 0xa9, 0xb9, 0x5d, 0x2f, 0xa5, 0xe0, 0x72, 0xee, 0x61, 0x3e,
0x81, 0xe8, 0xc7, 0xcd, 0xd6, 0xec, 0x7f, 0x98, 0xfc, 0x12, 0xd1, 0x5f, 0xef, 0xdf, 0x00, 0x00,
0x00, 0xff, 0xff, 0x1d, 0x63, 0xb4, 0xfe, 0x0d, 0x07, 0x00, 0x00,
// 723 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x41, 0x6e, 0xdb, 0x3a,
0x10, 0x85, 0x2c, 0x2b, 0xb6, 0xc6, 0xfe, 0x89, 0x43, 0xe4, 0x07, 0xc2, 0xc7, 0x47, 0x20, 0x68,
0x51, 0x08, 0x41, 0x91, 0x00, 0xb9, 0x41, 0x9a, 0x74, 0x91, 0x55, 0x0d, 0x26, 0xed, 0xa2, 0x3b,
0x45, 0x9a, 0xda, 0x6c, 0x64, 0xc9, 0x20, 0xe9, 0xa0, 0xee, 0x1d, 0x7a, 0x90, 0x1e, 0xa6, 0xd7,
0xe8, 0xb2, 0x67, 0x28, 0x66, 0x28, 0xdb, 0xb2, 0x9d, 0xa2, 0xbb, 0x99, 0x47, 0xca, 0x9c, 0x79,
0xef, 0xcd, 0x18, 0xfe, 0xcd, 0x6b, 0x8d, 0x97, 0x73, 0x5d, 0xdb, 0xfa, 0x92, 0xc2, 0x0b, 0x0e,
0x45, 0x97, 0xe2, 0xe4, 0x5b, 0x07, 0xc2, 0x9b, 0x69, 0x56, 0x96, 0x58, 0x4d, 0x50, 0x1c, 0x42,
0x47, 0x15, 0x91, 0x17, 0x7b, 0xa9, 0x2f, 0x3b, 0xaa, 0x10, 0x02, 0xba, 0x76, 0x39, 0xc7, 0xa8,
0x13, 0x7b, 0x69, 0x28, 0x39, 0x16, 0xa7, 0x70, 0x60, 0x6c, 0x66, 0x17, 0x26, 0x3a, 0x60, 0xb4,
0xc9, 0xc4, 0x08, 0xfc, 0x85, 0x56, 0x51, 0xc8, 0x20, 0x85, 0xe2, 0x04, 0x02, 0x5b, 0x3f, 0x61,
0x15, 0xf9, 0x8c, 0xb9, 0x44, 0x9c, 0xc3, 0xe8, 0x09, 0x97, 0xd7, 0x0b, 0x3b, 0xad, 0xb5, 0xfa,
0x9a, 0x59, 0x55, 0x57, 0x51, 0xc0, 0x17, 0xf6, 0x70, 0x71, 0x0b, 0xc7, 0xcf, 0x59, 0xa9, 0x0a,
0xce, 0x34, 0xe6, 0xb5, 0x2e, 0x4c, 0x04, 0xb1, 0x9f, 0x0e, 0xae, 0x4e, 0x2f, 0xb8, 0x97, 0x0f,
0xeb, 0x63, 0xc9, 0xc7, 0x72, 0xff, 0x03, 0x71, 0x0e, 0x01, 0x6a, 0x5d, 0xeb, 0xa8, 0x17, 0x7b,
0xe9, 0xe0, 0xea, 0xc4, 0x7d, 0x39, 0xd6, 0xf5, 0x63, 0x89, 0xb3, 0x5b, 0xb4, 0x99, 0x2a, 0x8d,
0x74, 0x57, 0x92, 0x5f, 0x1e, 0x8c, 0x76, 0x7f, 0x53, 0xfc, 0x07, 0xfd, 0x69, 0x6d, 0x6c, 0x95,
0xcd, 0x90, 0xc9, 0x09, 0xe5, 0x3a, 0x27, 0x8a, 0xe6, 0xb5, 0xb6, 0x2b, 0x8a, 0x28, 0x16, 0xaf,
0xe1, 0x38, 0x2b, 0x0a, 0x8d, 0xc6, 0xa0, 0x91, 0x68, 0xea, 0xf2, 0x19, 0x8b, 0xc8, 0x8f, 0xfd,
0x74, 0x28, 0xf7, 0x0f, 0x44, 0x0c, 0x83, 0x06, 0x7c, 0x6f, 0xb0, 0x88, 0xba, 0xb1, 0x97, 0x0e,
0x65, 0x1b, 0xe2, 0x1b, 0x8e, 0x17, 0xab, 0xd0, 0x44, 0x41, 0xec, 0xa7, 0xa1, 0x6c, 0x43, 0x8e,
0xfc, 0xb2, 0x51, 0x84, 0x42, 0xf1, 0x0a, 0x0e, 0xd7, 0x4f, 0x3d, 0x68, 0x85, 0x45, 0xd4, 0xe3,
0x02, 0x76, 0xd0, 0xe4, 0x33, 0x1c, 0x6e, 0x33, 0x41, 0xaf, 0xcd, 0x1d, 0xf2, 0x40, 0xda, 0xbb,
0x86, 0xdb, 0x10, 0x59, 0xa0, 0xe0, 0xcb, 0x4d, 0xd7, 0x4d, 0x26, 0xce, 0x00, 0xa6, 0xd6, 0xce,
0xef, 0x9d, 0x3d, 0x48, 0xf5, 0x40, 0xb6, 0x90, 0xe4, 0xbb, 0x07, 0x83, 0x1b, 0xd4, 0x56, 0x7d,
0x52, 0x79, 0x66, 0x91, 0x6a, 0xd4, 0x38, 0x51, 0xc6, 0x6a, 0x66, 0xfb, 0xee, 0xb6, 0xb1, 0xde,
0x0e, 0xca, 0x96, 0x43, 0xad, 0xb2, 0xf5, 0x7b, 0x2e, 0xe3, 0x3a, 0xd4, 0x04, 0x8d, 0x6d, 0x1c,
0xd6, 0x64, 0xc4, 0x46, 0x81, 0xba, 0x61, 0x92, 0x42, 0xba, 0xa9, 0x8c, 0x59, 0x60, 0xc1, 0x56,
0xf3, 0x65, 0x93, 0x89, 0x08, 0x7a, 0xf8, 0x65, 0xae, 0x34, 0x3a, 0x37, 0xfb, 0x72, 0x95, 0x26,
0x3f, 0x3d, 0x18, 0xca, 0x56, 0x19, 0x7b, 0xb3, 0x31, 0x02, 0xff, 0x09, 0x97, 0x5c, 0xd1, 0x50,
0x52, 0x48, 0x3f, 0x96, 0xd7, 0x95, 0xcd, 0x72, 0xcb, 0x62, 0x87, 0x72, 0x95, 0x8a, 0x14, 0x8e,
0x9a, 0xd0, 0x8c, 0x35, 0x1a, 0xac, 0x2c, 0x17, 0xd7, 0x97, 0xbb, 0xb0, 0xf8, 0x1f, 0xc2, 0x6c,
0xa2, 0x11, 0x67, 0x74, 0xc7, 0x8d, 0xc5, 0x06, 0xa0, 0x53, 0x55, 0x29, 0xab, 0xb2, 0xf2, 0x6e,
0xcc, 0x05, 0x0f, 0xe5, 0x06, 0xa0, 0xd3, 0x5c, 0x63, 0x66, 0xb1, 0xb8, 0xb6, 0xec, 0x75, 0x5f,
0x6e, 0x80, 0xd6, 0xdc, 0xf6, 0xdb, 0x73, 0x4b, 0x8e, 0xff, 0x67, 0x7b, 0xea, 0x36, 0x9d, 0x86,
0xdc, 0xe9, 0x19, 0x80, 0x2a, 0xb0, 0x22, 0xd9, 0x50, 0x37, 0x12, 0xb4, 0x90, 0x17, 0x64, 0xf4,
0xff, 0x28, 0xa3, 0xab, 0xa0, 0xbb, 0xb5, 0x39, 0x5a, 0x22, 0x04, 0x5b, 0x22, 0x88, 0x4b, 0x80,
0x7c, 0xb5, 0x9c, 0x48, 0x21, 0x1a, 0xfc, 0x23, 0x37, 0xbe, 0xeb, 0xa5, 0x25, 0x5b, 0x57, 0x44,
0x02, 0xc3, 0xbc, 0x9e, 0x3d, 0xaa, 0x8a, 0xdf, 0x34, 0xcc, 0xc2, 0x50, 0x6e, 0x61, 0xc9, 0x8f,
0x0e, 0x04, 0xef, 0x34, 0xb9, 0x62, 0x57, 0xd2, 0xfd, 0x46, 0x3a, 0x2f, 0x36, 0xd2, 0x2a, 0xd8,
0xdf, 0x2e, 0x78, 0xbd, 0x6a, 0xba, 0x7f, 0x5d, 0x35, 0xb4, 0x25, 0xf2, 0xcd, 0x30, 0xdc, 0x3b,
0x83, 0x3b, 0xc9, 0xf7, 0x0f, 0x78, 0x9e, 0xdb, 0x2a, 0x39, 0x3a, 0x42, 0xb9, 0x83, 0xb6, 0x48,
0xee, 0x6d, 0x91, 0x7c, 0x02, 0x01, 0xed, 0x2b, 0x52, 0x9f, 0x3e, 0x73, 0x09, 0x19, 0xf3, 0x11,
0x27, 0x59, 0x35, 0xd6, 0x75, 0x8e, 0xc6, 0xa8, 0x6a, 0xc2, 0x0b, 0xbc, 0x2f, 0x77, 0x61, 0x36,
0xb7, 0xf3, 0x52, 0x04, 0xae, 0xe7, 0x26, 0x4d, 0x7a, 0x10, 0xbc, 0x9d, 0xcd, 0xed, 0xf2, 0x4d,
0xef, 0x63, 0xc0, 0x7f, 0x2d, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf6, 0x75, 0x46, 0x28, 0x72,
0x06, 0x00, 0x00,
}

View File

@ -34,18 +34,6 @@ message ProblemDetails {
optional int32 httpStatus = 3;
}
message Precertificate {
optional bytes der = 1;
}
message SCTFetchingConfig {
repeated SCTFetchingLogSet logSets = 1;
}
message SCTFetchingLogSet {
repeated string logURLs = 1;
}
message Certificate {
optional int64 registrationID = 1;
optional string serial = 2;

View File

@ -33,7 +33,7 @@ func New(pub core.Publisher, groups []cmd.CTGroup, informational []cmd.LogDescri
}
type result struct {
sct core.SCTDER
sct []byte
err error
}
@ -41,7 +41,7 @@ type result struct {
// once it has the first SCT it cancels all of the other submissions and returns.
// It allows up to len(group)-1 of the submissions to fail as we only care about
// getting a single SCT.
func (ctp *CTPolicy) race(ctx context.Context, cert core.CertDER, group cmd.CTGroup) (core.SCTDER, error) {
func (ctp *CTPolicy) race(ctx context.Context, cert core.CertDER, group cmd.CTGroup) ([]byte, error) {
results := make(chan result, len(group.Logs))
var subCtx context.Context
var cancel func()
@ -51,12 +51,14 @@ func (ctp *CTPolicy) race(ctx context.Context, cert core.CertDER, group cmd.CTGr
subCtx, cancel = ctx, func() {}
}
defer cancel()
isPrecert := features.Enabled(features.EmbedSCTs)
for _, l := range group.Logs {
go func(l cmd.LogDescription) {
sct, err := ctp.pub.SubmitToSingleCTWithResult(subCtx, &pubpb.Request{
LogURL: &l.URI,
LogPublicKey: &l.Key,
Der: cert,
Precert: &isPrecert,
})
if err != nil {
// Only log the error if it is not a result of canceling subCtx
@ -90,7 +92,7 @@ func (ctp *CTPolicy) race(ctx context.Context, cert core.CertDER, group cmd.CTGr
// GetSCTs attempts to retrieve a SCT from each configured grouping of logs and returns
// the set of SCTs to the caller.
func (ctp *CTPolicy) GetSCTs(ctx context.Context, cert core.CertDER) ([]core.SCTDER, error) {
func (ctp *CTPolicy) GetSCTs(ctx context.Context, cert core.CertDER) (core.SCTDERs, error) {
results := make(chan result, len(ctp.groups))
var subCtx context.Context
var cancel func()
@ -120,7 +122,7 @@ func (ctp *CTPolicy) GetSCTs(ctx context.Context, cert core.CertDER) ([]core.SCT
}(log)
}
var ret []core.SCTDER
var ret core.SCTDERs
for i := 0; i < len(ctp.groups); i++ {
res := <-results
// If any one group fails to get a SCT then we fail out immediately

View File

@ -43,7 +43,7 @@ func TestGetSCTs(t *testing.T) {
mock core.Publisher
groups []cmd.CTGroup
ctx context.Context
result []core.SCTDER
result core.SCTDERs
errRegexp *regexp.Regexp
}{
{
@ -66,7 +66,7 @@ func TestGetSCTs(t *testing.T) {
},
},
ctx: context.Background(),
result: []core.SCTDER{[]byte{0}, []byte{0}},
result: core.SCTDERs{[]byte{0}, []byte{0}},
},
{
name: "basic failure case",

View File

@ -4,9 +4,9 @@ package features
import "strconv"
const _FeatureFlag_name = "unusedUseAIAIssuerURLReusePendingAuthzCountCertificatesExactIPv6FirstAllowRenewalFirstRLWildcardDomainsForceConsistentStatusEnforceChallengeDisableTLSSNIRevalidationCancelCTSubmissionsVAChecksGSBEnforceV2ContentType"
const _FeatureFlag_name = "unusedUseAIAIssuerURLReusePendingAuthzCountCertificatesExactIPv6FirstAllowRenewalFirstRLWildcardDomainsForceConsistentStatusEnforceChallengeDisableTLSSNIRevalidationEmbedSCTsCancelCTSubmissionsVAChecksGSBEnforceV2ContentType"
var _FeatureFlag_index = [...]uint8{0, 6, 21, 38, 60, 69, 88, 103, 124, 147, 165, 184, 195, 215}
var _FeatureFlag_index = [...]uint8{0, 6, 21, 38, 60, 69, 88, 103, 124, 147, 165, 174, 193, 204, 224}
func (i FeatureFlag) String() string {
if i < 0 || i >= FeatureFlag(len(_FeatureFlag_index)-1) {

View File

@ -26,6 +26,7 @@ const (
EnforceChallengeDisable
// Allow TLS-SNI in new-authz that are revalidating for previous issuance
TLSSNIRevalidation
EmbedSCTs
CancelCTSubmissions
VAChecksGSB
// Return errors to ACMEv2 clients that do not send the correct JWS
@ -44,6 +45,7 @@ var features = map[FeatureFlag]bool{
WildcardDomains: false,
EnforceChallengeDisable: false, // deprecated
TLSSNIRevalidation: false,
EmbedSCTs: false,
CancelCTSubmissions: true,
VAChecksGSB: false,
EnforceV2ContentType: false,

View File

@ -41,14 +41,21 @@ func (cac CertificateAuthorityClientWrapper) IssueCertificate(ctx context.Contex
if err != nil {
return core.Certificate{}, err
}
return pbToCert(res), nil
return pbToCert(res)
}
func (cac CertificateAuthorityClientWrapper) IssuePrecertificate(ctx context.Context, issueReq *caPB.IssueCertificateRequest) (*caPB.IssuePrecertificateResponse, error) {
if cac.inner == nil {
return nil, errors.New("this CA client does not support issuing precertificates")
}
return cac.inner.IssuePrecertificate(ctx, issueReq)
resp, err := cac.inner.IssuePrecertificate(ctx, issueReq)
if err != nil {
return nil, err
}
if resp.DER == nil {
return nil, errIncompleteResponse
}
return resp, nil
}
func (cac CertificateAuthorityClientWrapper) IssueCertificateForPrecertificate(ctx context.Context, req *caPB.IssueCertificateForPrecertificateRequest) (core.Certificate, error) {
@ -59,7 +66,7 @@ func (cac CertificateAuthorityClientWrapper) IssueCertificateForPrecertificate(c
if err != nil {
return core.Certificate{}, err
}
return pbToCert(res), nil
return pbToCert(res)
}
func (cac CertificateAuthorityClientWrapper) GenerateOCSP(ctx context.Context, ocspReq core.OCSPSigningRequest) ([]byte, error) {
@ -98,10 +105,23 @@ func (cas *CertificateAuthorityServerWrapper) IssueCertificate(ctx context.Conte
}
func (cas *CertificateAuthorityServerWrapper) IssuePrecertificate(ctx context.Context, request *caPB.IssueCertificateRequest) (*caPB.IssuePrecertificateResponse, error) {
return cas.inner.IssuePrecertificate(ctx, request)
if request == nil || request.Csr == nil || request.OrderID == nil || request.RegistrationID == nil {
return nil, errIncompleteRequest
}
resp, err := cas.inner.IssuePrecertificate(ctx, request)
if err != nil {
return nil, err
}
if resp.DER == nil {
return nil, errIncompleteRequest
}
return resp, nil
}
func (cas *CertificateAuthorityServerWrapper) IssueCertificateForPrecertificate(ctx context.Context, req *caPB.IssueCertificateForPrecertificateRequest) (*corepb.Certificate, error) {
if req == nil || req.DER == nil || req.OrderID == nil || req.RegistrationID == nil || req.SCTs == nil {
return nil, errIncompleteRequest
}
cert, err := cas.inner.IssueCertificateForPrecertificate(ctx, req)
if err != nil {
return nil, err

View File

@ -428,10 +428,6 @@ func authorizationValid(authz *corepb.Authorization) bool {
return !(authz.Id == nil || authz.Identifier == nil || authz.RegistrationID == nil || authz.Status == nil || authz.Expires == nil)
}
func certificateValid(cert *corepb.Certificate) bool {
return !(cert.RegistrationID == nil || cert.Serial == nil || cert.Digest == nil || cert.Der == nil || cert.Issued == nil || cert.Expires == nil)
}
func sctToPB(sct core.SignedCertificateTimestamp) *sapb.SignedCertificateTimestamp {
id := int64(sct.ID)
version := int64(sct.SCTVersion)
@ -475,7 +471,10 @@ func certToPB(cert core.Certificate) *corepb.Certificate {
}
}
func pbToCert(pb *corepb.Certificate) core.Certificate {
func pbToCert(pb *corepb.Certificate) (core.Certificate, error) {
if pb == nil || pb.RegistrationID == nil || pb.Serial == nil || pb.Digest == nil || pb.Der == nil || pb.Issued == nil || pb.Expires == nil {
return core.Certificate{}, errIncompleteResponse
}
return core.Certificate{
RegistrationID: *pb.RegistrationID,
Serial: *pb.Serial,
@ -483,5 +482,5 @@ func pbToCert(pb *corepb.Certificate) core.Certificate {
DER: pb.Der,
Issued: time.Unix(0, *pb.Issued),
Expires: time.Unix(0, *pb.Expires),
}
}, nil
}

View File

@ -330,7 +330,7 @@ func TestCert(t *testing.T) {
}
certPB := certToPB(cert)
outCert := pbToCert(certPB)
outCert, _ := pbToCert(certPB)
test.AssertDeepEquals(t, cert, outCert)
}

View File

@ -69,11 +69,7 @@ func (rac RegistrationAuthorityClientWrapper) NewCertificate(ctx context.Context
return core.Certificate{}, err
}
if response == nil || !certificateValid(response) {
return core.Certificate{}, errIncompleteResponse
}
return pbToCert(response), nil
return pbToCert(response)
}
func (rac RegistrationAuthorityClientWrapper) UpdateRegistration(ctx context.Context, base, updates core.Registration) (core.Registration, error) {

View File

@ -108,11 +108,7 @@ func (sac StorageAuthorityClientWrapper) GetCertificate(ctx context.Context, ser
return core.Certificate{}, err
}
if response == nil || !certificateValid(response) {
return core.Certificate{}, errIncompleteResponse
}
return pbToCert(response), nil
return pbToCert(response)
}
func (sac StorageAuthorityClientWrapper) GetCertificateStatus(ctx context.Context, serial string) (core.CertificateStatus, error) {

View File

@ -17,6 +17,7 @@ import (
corepb "github.com/letsencrypt/boulder/core/proto"
berrors "github.com/letsencrypt/boulder/errors"
"github.com/letsencrypt/boulder/probs"
pubpb "github.com/letsencrypt/boulder/publisher/proto"
"github.com/letsencrypt/boulder/revocation"
sapb "github.com/letsencrypt/boulder/sa/proto"
)
@ -567,6 +568,11 @@ func (*Publisher) SubmitToSingleCT(_ context.Context, _, _ string, _ []byte) err
return nil
}
// SubmitToSingleCTWithResult is a mock
func (*Publisher) SubmitToSingleCTWithResult(_ context.Context, _ *pubpb.Request) (*pubpb.Result, error) {
return nil, nil
}
// Mailer is a mock
type Mailer struct {
Messages []MailerMessage

View File

@ -1056,18 +1056,37 @@ func (ra *RegistrationAuthorityImpl) issueCertificateInner(
RegistrationID: &acctIDInt,
OrderID: &orderIDInt,
}
cert, err := ra.CA.IssueCertificate(ctx, issueReq)
if err != nil {
return emptyCert, err
}
if ra.ctpolicy != nil {
ra.getSCTs(ctx, cert.DER)
} else if ra.publisher != nil {
go func() {
// This context is limited by the gRPC timeout.
_ = ra.publisher.SubmitToCT(context.Background(), cert.DER)
}()
var cert core.Certificate
if features.Enabled(features.EmbedSCTs) {
precert, err := ra.CA.IssuePrecertificate(ctx, issueReq)
if err != nil {
logEvent.Error = err.Error()
return emptyCert, err
}
scts, err := ra.getSCTs(ctx, precert.DER)
if err != nil {
logEvent.Error = err.Error()
return emptyCert, err
}
cert, err = ra.CA.IssueCertificateForPrecertificate(ctx, &caPB.IssueCertificateForPrecertificateRequest{
DER: precert.DER,
SCTs: scts,
RegistrationID: &acctIDInt,
OrderID: &orderIDInt,
})
if err != nil {
logEvent.Error = err.Error()
return emptyCert, err
}
} else {
cert, err = ra.CA.IssueCertificate(ctx, issueReq)
if err != nil {
logEvent.Error = err.Error()
return emptyCert, err
}
_, _ = ra.getSCTs(ctx, cert.DER)
}
parsedCertificate, err := x509.ParseCertificate([]byte(cert.DER))
@ -1094,23 +1113,24 @@ func (ra *RegistrationAuthorityImpl) issueCertificateInner(
return cert, nil
}
func (ra *RegistrationAuthorityImpl) getSCTs(ctx context.Context, cert []byte) {
func (ra *RegistrationAuthorityImpl) getSCTs(ctx context.Context, cert []byte) (core.SCTDERs, error) {
started := ra.clk.Now()
_, err := ra.ctpolicy.GetSCTs(ctx, cert)
scts, err := ra.ctpolicy.GetSCTs(ctx, cert)
took := ra.clk.Since(started)
// The final cert has already been issued so actually return it to the
// user even if this fails since we aren't actually doing anything with
// the SCTs yet.
state := "failure"
if err != nil {
state := "failure"
if err == context.DeadlineExceeded {
state = "deadlineExceeded"
}
ra.log.Warning(fmt.Sprintf("ctpolicy.GetSCTs failed: %s", err))
} else if err == nil {
state = "success"
ra.ctpolicyResults.With(prometheus.Labels{"result": state}).Observe(took.Seconds())
return nil, err
}
ra.ctpolicyResults.With(prometheus.Labels{"result": state}).Observe(took.Seconds())
ra.ctpolicyResults.With(prometheus.Labels{"result": "success"}).Observe(took.Seconds())
return scts, nil
}
// domainsForRateLimiting transforms a list of FQDNs into a list of eTLD+1's

View File

@ -275,10 +275,12 @@ func initAuthorities(t *testing.T) (*DummyValidationAuthority, *sa.SQLStorageAut
Status: core.StatusValid,
})
ctp := ctpolicy.New(&mocks.Publisher{}, nil, nil, log)
ra := NewRegistrationAuthorityImpl(fc,
log,
stats,
1, testKeyPolicy, 0, true, false, 300*24*time.Hour, 7*24*time.Hour, nil, noopCAA{}, 0, nil)
1, testKeyPolicy, 0, true, false, 300*24*time.Hour, 7*24*time.Hour, nil, noopCAA{}, 0, ctp)
ra.SA = ssa
ra.VA = va
ra.CA = ca

View File

@ -42,6 +42,7 @@
"doNotForceCN": true,
"enableMustStaple": true,
"hostnamePolicyFile": "test/hostname-policy.json",
"enablePrecertificateFlow": true,
"cfssl": {
"signing": {
"profiles": {
@ -131,7 +132,8 @@
},
"maxConcurrentRPCServerRequests": 100000,
"features": {
"WildcardDomains": true
"WildcardDomains": true,
"EmbedSCTs": true
}
},

View File

@ -33,6 +33,9 @@
"ocspGeneratorService": {
"serverAddresses": ["ca.boulder:9096"],
"timeout": "15s"
},
"features": {
"EmbedSCTs": true
}
},

View File

@ -45,8 +45,9 @@
"WildcardDomains": true,
"TLSSNIRevalidation": true,
"ReusePendingAuthz": true,
"VAChecksGSB": true,
"CancelCTSubmissions": false
"CancelCTSubmissions": false,
"EmbedSCTs": true,
"VAChecksGSB": true
},
"CTLogGroups2": [
{

View File

@ -43,7 +43,35 @@
"features": {
"CountCertificatesExact": true,
"ReusePendingAuthz": false
}
},
"CTLogGroups2": [
{
"name": "a",
"logs": [
{
"uri": "http://boulder:4500",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYggOxPnPkzKBIhTacSYoIfnSL2jPugcbUKx83vFMvk5gKAz/AGe87w20riuPwEGn229hKVbEKHFB61NIqNHC3Q=="
},
{
"uri": "http://boulder:4501",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKtnFevaXV/kB8dmhCNZHmxKVLcHX1plaAsY9LrKilhYxdmQZiu36LvAvosTsqMVqRK9a96nC8VaxAdaHUbM8EA=="
}
]
},
{
"name": "b",
"logs": [
{
"uri": "http://boulder:4510",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyw1HymhJkuxSIgt3gqW3sVXqMqB3EFsXcMfPFo0vYwjNiRmCJDXKsR0Flp7MAK+wc3X/7Hpc8liUbMhPet7tEA=="
},
{
"uri": "http://boulder:4511",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFRu37ZRLg8lT4rVQwMwh4oAOpXb4Sx+9hgQ+JFCjmAv3oDV+sDOMsC7hULkGTn+LB5L1SRo/XIY4Kw5V+nFXgg=="
}
]
}
]
},
"pa": {

View File

@ -19,6 +19,9 @@ import os
import OpenSSL
import josepy as jose
from cryptography import x509
from cryptography.hazmat.backends import default_backend
import startservers
import chisel2
@ -45,6 +48,7 @@ def main():
test_overlapping_wildcard()
test_wildcard_exactblacklist()
test_wildcard_authz_reuse()
test_sct_embedding()
test_order_reuse_failed_authz()
test_revoke_by_issuer()
test_revoke_by_authz()
@ -280,6 +284,32 @@ def test_loadgeneration():
shell=True,
stderr=subprocess.STDOUT)
def test_sct_embedding():
order = auth_and_issue([random_domain()])
cert = x509.load_pem_x509_certificate(str(order.fullchain_pem), default_backend())
# make sure there is no poison extension
try:
cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3"))
raise Exception("certificate contains CT poison extension")
except x509.ExtensionNotFound:
# do nothing
pass
# make sure there is a SCT list extension
try:
sctList = cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2"))
except x509.ExtensionNotFound:
raise Exception("certificate doesn't contain SCT list extension")
if len(sctList.value) != 2:
raise Exception("SCT list contains wrong number of SCTs")
for sct in sctList.value:
if sct.version != x509.certificate_transparency.Version.v1:
raise Exception("SCT contains wrong version")
if sct.entry_type != x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE:
raise Exception("SCT contains wrong entry type")
if __name__ == "__main__":
try:
main()

View File

@ -12,6 +12,7 @@ import requests
import shutil
import subprocess
import signal
import struct
import sys
import tempfile
import time
@ -25,6 +26,9 @@ from chisel import auth_and_issue
import requests
import OpenSSL
from cryptography import x509
from cryptography.hazmat.backends import default_backend
class ProcInfo:
"""
Args:
@ -460,6 +464,32 @@ def test_stats():
expect_stat(8002, '\ngrpc_client_handling_seconds_count{grpc_method="UpdatePendingAuthorization",grpc_service="sa.StorageAuthority",grpc_type="unary"} ')
expect_stat(8001, "\ngo_goroutines ")
def test_sct_embedding():
certr, authzs = auth_and_issue([random_domain()])
certBytes = urllib2.urlopen(certr.uri).read()
cert = x509.load_der_x509_certificate(certBytes, default_backend())
# make sure there is no poison extension
try:
cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3"))
raise Exception("certificate contains CT poison extension")
except x509.ExtensionNotFound:
# do nothing
pass
# make sure there is a SCT list extension
try:
sctList = cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2"))
except x509.ExtensionNotFound:
raise Exception("certificate doesn't contain SCT list extension")
if len(sctList.value) != 2:
raise Exception("SCT list contains wrong number of SCTs")
for sct in sctList.value:
if sct.version != x509.certificate_transparency.Version.v1:
raise Exception("SCT contains wrong version")
if sct.entry_type != x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE:
raise Exception("SCT contains wrong entry type")
exit_status = 1
tempdir = tempfile.mkdtemp()
@ -530,6 +560,8 @@ def run_chisel():
test_expired_authzs_404()
test_account_update()
test_stats()
if os.environ.get('BOULDER_CONFIG_DIR', '').startswith("test/config-next"):
test_sct_embedding()
def run_loadtest():
# Run the load generator

View File

@ -24,6 +24,7 @@ import (
"github.com/jmhodges/clock"
"github.com/letsencrypt/boulder/core"
corepb "github.com/letsencrypt/boulder/core/proto"
"github.com/letsencrypt/boulder/ctpolicy"
berrors "github.com/letsencrypt/boulder/errors"
"github.com/letsencrypt/boulder/features"
"github.com/letsencrypt/boulder/goodkey"
@ -880,6 +881,7 @@ func TestIssueCertificate(t *testing.T) {
// authorized, etc.
stats := metrics.NewNoopScope()
ctp := ctpolicy.New(&mocks.Publisher{}, nil, nil, wfe.log)
ra := ra.NewRegistrationAuthorityImpl(
fc,
wfe.log,
@ -894,7 +896,7 @@ func TestIssueCertificate(t *testing.T) {
nil,
noopCAA{},
0,
nil,
ctp,
)
ra.SA = mocks.NewStorageAuthority(fc)
ra.CA = &mocks.MockCA{