Unify usage of 'issuer' and 'signer' as nouns (#5085)
We define a "signer" to be a private key, or something that satisfies the crypto.Signer interface. We define an "issuer" to be an object which has both a signer (so it can sign things) and a certificate (so that the things it signs can have appropriate issuer fields set). As a result, this change: - moves the new "signer" library to be called "issuance" instead - renames several "signers" to instead be "issuers", as defined above - renames several "issuers" to instead be "certs", to reduce confusion more There are some further cleanups which could be made, but most of them will be made irrelevant by the removal of the CFSSL code, so I'm leaving them be for now.
This commit is contained in:
parent
ad2ec784d1
commit
d8a786ea08
54
ca/ca.go
54
ca/ca.go
|
@ -39,9 +39,9 @@ import (
|
|||
berrors "github.com/letsencrypt/boulder/errors"
|
||||
"github.com/letsencrypt/boulder/features"
|
||||
"github.com/letsencrypt/boulder/goodkey"
|
||||
"github.com/letsencrypt/boulder/issuance"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
sapb "github.com/letsencrypt/boulder/sa/proto"
|
||||
bsigner "github.com/letsencrypt/boulder/signer"
|
||||
)
|
||||
|
||||
// Miscellaneous PKIX OIDs that we need to refer to
|
||||
|
@ -167,42 +167,42 @@ type internalIssuer struct {
|
|||
cert *x509.Certificate
|
||||
ocspSigner crypto.Signer
|
||||
|
||||
// Only one of cfsslSigner and boulderSigner will be non-nill
|
||||
// Only one of cfsslSigner and boulderIssuer will be non-nill
|
||||
cfsslSigner localSigner
|
||||
boulderSigner *bsigner.Signer
|
||||
boulderIssuer *issuance.Issuer
|
||||
}
|
||||
|
||||
func makeInternalIssuers(issuers []bsigner.Config, lifespanOCSP time.Duration) (issuerMaps, error) {
|
||||
func makeInternalIssuers(configs []issuance.IssuerConfig, lifespanOCSP time.Duration) (issuerMaps, error) {
|
||||
issuersByAlg := make(map[x509.PublicKeyAlgorithm]*internalIssuer, 2)
|
||||
issuersByName := make(map[string]*internalIssuer, len(issuers))
|
||||
issuersByID := make(map[int64]*internalIssuer, len(issuers))
|
||||
for _, issuer := range issuers {
|
||||
signer, err := bsigner.NewSigner(issuer)
|
||||
issuersByName := make(map[string]*internalIssuer, len(configs))
|
||||
issuersByID := make(map[int64]*internalIssuer, len(configs))
|
||||
for _, config := range configs {
|
||||
issuer, err := issuance.New(config)
|
||||
if err != nil {
|
||||
return issuerMaps{}, err
|
||||
}
|
||||
ii := &internalIssuer{
|
||||
cert: issuer.Issuer,
|
||||
ocspSigner: issuer.Signer,
|
||||
boulderSigner: signer,
|
||||
cert: config.Cert,
|
||||
ocspSigner: config.Signer,
|
||||
boulderIssuer: issuer,
|
||||
}
|
||||
if issuer.Profile.UseForRSALeaves {
|
||||
if config.Profile.UseForRSALeaves {
|
||||
if issuersByAlg[x509.RSA] != nil {
|
||||
return issuerMaps{}, errors.New("Multiple issuer certs for RSA are not allowed")
|
||||
}
|
||||
issuersByAlg[x509.RSA] = ii
|
||||
}
|
||||
if issuer.Profile.UseForECDSALeaves {
|
||||
if config.Profile.UseForECDSALeaves {
|
||||
if issuersByAlg[x509.ECDSA] != nil {
|
||||
return issuerMaps{}, errors.New("Multiple issuer certs for ECDSA are not allowed")
|
||||
}
|
||||
issuersByAlg[x509.ECDSA] = ii
|
||||
}
|
||||
if issuersByName[issuer.Issuer.Subject.CommonName] != nil {
|
||||
if issuersByName[config.Cert.Subject.CommonName] != nil {
|
||||
return issuerMaps{}, errors.New("Multiple issuer certs with the same CommonName are not supported")
|
||||
}
|
||||
issuersByName[issuer.Issuer.Subject.CommonName] = ii
|
||||
issuersByID[idForIssuer(issuer.Issuer)] = ii
|
||||
issuersByName[config.Cert.Subject.CommonName] = ii
|
||||
issuersByID[idForCert(config.Cert)] = ii
|
||||
}
|
||||
return issuerMaps{issuersByAlg, issuersByName, issuersByID}, nil
|
||||
}
|
||||
|
@ -245,15 +245,15 @@ func makeCFSSLInternalIssuers(issuers []Issuer, policy *cfsslConfig.Signing, lif
|
|||
issuersByAlg[x509.ECDSA] = ii
|
||||
}
|
||||
issuersByName[cn] = ii
|
||||
issuersByID[idForIssuer(iss.Cert)] = ii
|
||||
issuersByID[idForCert(iss.Cert)] = ii
|
||||
}
|
||||
return issuerMaps{issuersByAlg, issuersByName, issuersByID}, nil
|
||||
}
|
||||
|
||||
// idForIssuer generates a stable ID for an issuer certificate. This
|
||||
// idForCert generates a stable ID for an issuer certificate. This
|
||||
// is used for identifying which issuer issued a certificate in the
|
||||
// certificateStatus table.
|
||||
func idForIssuer(cert *x509.Certificate) int64 {
|
||||
func idForCert(cert *x509.Certificate) int64 {
|
||||
h := sha256.Sum256(cert.Raw)
|
||||
return big.NewInt(0).SetBytes(h[:4]).Int64()
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ func NewCertificateAuthorityImpl(
|
|||
clk clock.Clock,
|
||||
stats prometheus.Registerer,
|
||||
cfsslIssuers []Issuer,
|
||||
boulderIssuers []bsigner.Config,
|
||||
boulderIssuers []issuance.IssuerConfig,
|
||||
keyPolicy goodkey.KeyPolicy,
|
||||
logger blog.Logger,
|
||||
orphanQueue *goque.Queue,
|
||||
|
@ -600,7 +600,7 @@ func (ca *CertificateAuthorityImpl) IssuePrecertificate(ctx context.Context, iss
|
|||
RegID: regID,
|
||||
Ocsp: ocspResp.Response,
|
||||
Issued: nowNanos,
|
||||
IssuerID: idForIssuer(issuer.cert),
|
||||
IssuerID: idForCert(issuer.cert),
|
||||
}
|
||||
|
||||
_, err = ca.sa.AddPrecertificate(ctx, req)
|
||||
|
@ -617,7 +617,7 @@ func (ca *CertificateAuthorityImpl) IssuePrecertificate(ctx context.Context, iss
|
|||
RegID: regID,
|
||||
OCSPResp: ocspResp.Response,
|
||||
Precert: true,
|
||||
IssuerID: idForIssuer(issuer.cert),
|
||||
IssuerID: idForCert(issuer.cert),
|
||||
})
|
||||
}
|
||||
return nil, err
|
||||
|
@ -686,11 +686,11 @@ func (ca *CertificateAuthorityImpl) IssueCertificateForPrecertificate(ctx contex
|
|||
|
||||
var certDER []byte
|
||||
if features.Enabled(features.NonCFSSLSigner) {
|
||||
issuanceReq, err := bsigner.RequestFromPrecert(precert, scts)
|
||||
issuanceReq, err := issuance.RequestFromPrecert(precert, scts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certDER, err = issuer.boulderSigner.Issue(issuanceReq)
|
||||
certDER, err = issuer.boulderIssuer.Issue(issuanceReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -711,7 +711,7 @@ func (ca *CertificateAuthorityImpl) IssueCertificateForPrecertificate(ctx contex
|
|||
ca.log.AuditInfof("Signing success: serial=[%s] names=[%s] csr=[%s] certificate=[%s]",
|
||||
serialHex, strings.Join(precert.DNSNames, ", "), hex.EncodeToString(req.DER),
|
||||
hex.EncodeToString(certDER))
|
||||
err = ca.storeCertificate(ctx, req.RegistrationID, req.OrderID, precert.SerialNumber, certDER, idForIssuer(issuer.cert))
|
||||
err = ca.storeCertificate(ctx, req.RegistrationID, req.OrderID, precert.SerialNumber, certDER, idForCert(issuer.cert))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -795,13 +795,13 @@ func (ca *CertificateAuthorityImpl) issuePrecertificateInner(ctx context.Context
|
|||
if features.Enabled(features.NonCFSSLSigner) {
|
||||
ca.log.AuditInfof("Signing: serial=[%s] names=[%s] csr=[%s]",
|
||||
serialHex, strings.Join(csr.DNSNames, ", "), hex.EncodeToString(csr.Raw))
|
||||
certDER, err = issuer.boulderSigner.Issue(&bsigner.IssuanceRequest{
|
||||
certDER, err = issuer.boulderIssuer.Issue(&issuance.IssuanceRequest{
|
||||
PublicKey: csr.PublicKey,
|
||||
Serial: serialBigInt.Bytes(),
|
||||
CommonName: csr.Subject.CommonName,
|
||||
DNSNames: csr.DNSNames,
|
||||
IncludeCTPoison: true,
|
||||
IncludeMustStaple: bsigner.ContainsMustStaple(csr.Extensions),
|
||||
IncludeMustStaple: issuance.ContainsMustStaple(csr.Extensions),
|
||||
NotBefore: validity.NotBefore,
|
||||
NotAfter: validity.NotAfter,
|
||||
})
|
||||
|
|
|
@ -38,11 +38,11 @@ import (
|
|||
berrors "github.com/letsencrypt/boulder/errors"
|
||||
"github.com/letsencrypt/boulder/features"
|
||||
"github.com/letsencrypt/boulder/goodkey"
|
||||
"github.com/letsencrypt/boulder/issuance"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
"github.com/letsencrypt/boulder/policy"
|
||||
sapb "github.com/letsencrypt/boulder/sa/proto"
|
||||
bsigner "github.com/letsencrypt/boulder/signer"
|
||||
"github.com/letsencrypt/boulder/test"
|
||||
)
|
||||
|
||||
|
@ -135,7 +135,7 @@ type testCtx struct {
|
|||
caConfig ca_config.CAConfig
|
||||
pa core.PolicyAuthority
|
||||
issuers []Issuer
|
||||
signerConfigs []bsigner.Config
|
||||
issuerConfigs []issuance.IssuerConfig
|
||||
keyPolicy goodkey.KeyPolicy
|
||||
fc clock.FakeClock
|
||||
stats prometheus.Registerer
|
||||
|
@ -261,12 +261,12 @@ func setup(t *testing.T) *testCtx {
|
|||
|
||||
issuers := []Issuer{{caKey, caCert}}
|
||||
|
||||
signerConfigs := []bsigner.Config{
|
||||
issuerConfigs := []issuance.IssuerConfig{
|
||||
{
|
||||
Issuer: caCert,
|
||||
Cert: caCert,
|
||||
Signer: caKey,
|
||||
Clk: fc,
|
||||
Profile: bsigner.ProfileConfig{
|
||||
Profile: issuance.ProfileConfig{
|
||||
UseForECDSALeaves: true,
|
||||
UseForRSALeaves: true,
|
||||
AllowMustStaple: true,
|
||||
|
@ -276,7 +276,7 @@ func setup(t *testing.T) *testCtx {
|
|||
IssuerURL: "http://not-example.com/issuer-url",
|
||||
OCSPURL: "http://not-example.com/ocsp",
|
||||
CRLURL: "http://not-example.com/crl",
|
||||
Policies: []bsigner.PolicyInformation{
|
||||
Policies: []issuance.PolicyInformation{
|
||||
{OID: "2.23.140.1.2.1"},
|
||||
},
|
||||
MaxValidityPeriod: cmd.ConfigDuration{Duration: time.Hour * 8760},
|
||||
|
@ -297,7 +297,7 @@ func setup(t *testing.T) *testCtx {
|
|||
caConfig,
|
||||
pa,
|
||||
issuers,
|
||||
signerConfigs,
|
||||
issuerConfigs,
|
||||
keyPolicy,
|
||||
fc,
|
||||
metrics.NoopRegisterer,
|
||||
|
@ -401,13 +401,13 @@ func TestIssuePrecertificate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func issueCertificateSubTestSetup(t *testing.T, boulderSigner bool) (*CertificateAuthorityImpl, *mockSA) {
|
||||
func issueCertificateSubTestSetup(t *testing.T, boulderIssuer bool) (*CertificateAuthorityImpl, *mockSA) {
|
||||
testCtx := setup(t)
|
||||
sa := &mockSA{}
|
||||
var issuers []Issuer
|
||||
var signerConfigs []bsigner.Config
|
||||
if boulderSigner {
|
||||
signerConfigs = testCtx.signerConfigs
|
||||
var issuerConfigs []issuance.IssuerConfig
|
||||
if boulderIssuer {
|
||||
issuerConfigs = testCtx.issuerConfigs
|
||||
_ = features.Set(map[string]bool{"NonCFSSLSigner": true})
|
||||
} else {
|
||||
issuers = testCtx.issuers
|
||||
|
@ -419,7 +419,7 @@ func issueCertificateSubTestSetup(t *testing.T, boulderSigner bool) (*Certificat
|
|||
testCtx.fc,
|
||||
testCtx.stats,
|
||||
issuers,
|
||||
signerConfigs,
|
||||
issuerConfigs,
|
||||
testCtx.keyPolicy,
|
||||
testCtx.logger,
|
||||
nil)
|
||||
|
@ -847,7 +847,7 @@ func TestIssueCertificateForPrecertificate(t *testing.T) {
|
|||
testCtx.fc,
|
||||
testCtx.stats,
|
||||
testCtx.issuers,
|
||||
testCtx.signerConfigs,
|
||||
testCtx.issuerConfigs,
|
||||
testCtx.keyPolicy,
|
||||
testCtx.logger,
|
||||
nil)
|
||||
|
@ -1291,7 +1291,7 @@ func TestGenerateOCSPWithIssuerID(t *testing.T) {
|
|||
// GenerateOCSP with feature enabled + req contains good IssuerID
|
||||
rsaIssuer := ca.issuers.byAlg[x509.RSA]
|
||||
_, err = ca.GenerateOCSP(context.Background(), &capb.GenerateOCSPRequest{
|
||||
IssuerID: idForIssuer(rsaIssuer.cert),
|
||||
IssuerID: idForCert(rsaIssuer.cert),
|
||||
Serial: "DEADDEADDEADDEADDEADDEADDEADDEADDEAD",
|
||||
Status: string(core.OCSPStatusGood),
|
||||
})
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"github.com/letsencrypt/pkcs11key/v4"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/signer"
|
||||
"github.com/letsencrypt/boulder/issuance"
|
||||
)
|
||||
|
||||
// CAConfig structs have configuration information for the certificate
|
||||
|
@ -27,7 +27,7 @@ type CAConfig struct {
|
|||
Issuers []IssuerConfig
|
||||
// SignerProfile contains the signer issuance profile, if using the boulder
|
||||
// signer rather than the CFSSL signer.
|
||||
SignerProfile signer.ProfileConfig
|
||||
SignerProfile issuance.ProfileConfig
|
||||
// LifespanOCSP is how long OCSP responses are valid for; It should be longer
|
||||
// than the minTimeToExpiry field for the OCSP Updater.
|
||||
LifespanOCSP cmd.ConfigDuration
|
||||
|
|
|
@ -22,9 +22,9 @@ import (
|
|||
"github.com/letsencrypt/boulder/features"
|
||||
"github.com/letsencrypt/boulder/goodkey"
|
||||
bgrpc "github.com/letsencrypt/boulder/grpc"
|
||||
"github.com/letsencrypt/boulder/issuance"
|
||||
"github.com/letsencrypt/boulder/policy"
|
||||
sapb "github.com/letsencrypt/boulder/sa/proto"
|
||||
bsigner "github.com/letsencrypt/boulder/signer"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
|
@ -48,15 +48,15 @@ func loadCFSSLIssuers(configs []ca_config.IssuerConfig) ([]ca.Issuer, error) {
|
|||
return issuers, nil
|
||||
}
|
||||
|
||||
func loadBoulderIssuers(configs []ca_config.IssuerConfig, profile bsigner.ProfileConfig, ignoredLints []string) ([]bsigner.Config, error) {
|
||||
boulderIssuerConfigs := make([]bsigner.Config, 0, len(configs))
|
||||
func loadBoulderIssuers(configs []ca_config.IssuerConfig, profile issuance.ProfileConfig, ignoredLints []string) ([]issuance.IssuerConfig, error) {
|
||||
boulderIssuerConfigs := make([]issuance.IssuerConfig, 0, len(configs))
|
||||
for _, issuerConfig := range configs {
|
||||
signer, issuer, err := loadIssuer(issuerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
boulderIssuerConfigs = append(boulderIssuerConfigs, bsigner.Config{
|
||||
Issuer: issuer,
|
||||
boulderIssuerConfigs = append(boulderIssuerConfigs, issuance.IssuerConfig{
|
||||
Cert: issuer,
|
||||
Signer: signer,
|
||||
IgnoredLints: ignoredLints,
|
||||
Clk: cmd.Clock(),
|
||||
|
@ -172,7 +172,7 @@ func main() {
|
|||
cmd.FailOnError(err, "Couldn't load hostname policy file")
|
||||
|
||||
var cfsslIssuers []ca.Issuer
|
||||
var boulderIssuerConfigs []bsigner.Config
|
||||
var boulderIssuerConfigs []issuance.IssuerConfig
|
||||
if features.Enabled(features.NonCFSSLSigner) {
|
||||
boulderIssuerConfigs, err = loadBoulderIssuers(c.CA.Issuers, c.CA.SignerProfile, c.CA.IgnoredLints)
|
||||
cmd.FailOnError(err, "Couldn't load issuers")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package signer
|
||||
package issuance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -45,25 +45,6 @@ type IssuanceRequest struct {
|
|||
SCTList []ct.SignedCertificateTimestamp
|
||||
}
|
||||
|
||||
type signingProfile struct {
|
||||
useForRSALeaves bool
|
||||
useForECDSALeaves bool
|
||||
|
||||
allowMustStaple bool
|
||||
allowCTPoison bool
|
||||
allowSCTList bool
|
||||
allowCommonName bool
|
||||
|
||||
sigAlg x509.SignatureAlgorithm
|
||||
ocspURL string
|
||||
crlURL string
|
||||
issuerURL string
|
||||
policies *pkix.Extension
|
||||
|
||||
maxBackdate time.Duration
|
||||
maxValidity time.Duration
|
||||
}
|
||||
|
||||
// PolicyQualifier describes a policy qualifier
|
||||
type PolicyQualifier struct {
|
||||
Type string
|
||||
|
@ -94,6 +75,26 @@ type ProfileConfig struct {
|
|||
MaxValidityBackdate cmd.ConfigDuration
|
||||
}
|
||||
|
||||
// The internal structure created by reading in ProfileConfigs
|
||||
type issuanceProfile struct {
|
||||
useForRSALeaves bool
|
||||
useForECDSALeaves bool
|
||||
|
||||
allowMustStaple bool
|
||||
allowCTPoison bool
|
||||
allowSCTList bool
|
||||
allowCommonName bool
|
||||
|
||||
sigAlg x509.SignatureAlgorithm
|
||||
ocspURL string
|
||||
crlURL string
|
||||
issuerURL string
|
||||
policies *pkix.Extension
|
||||
|
||||
maxBackdate time.Duration
|
||||
maxValidity time.Duration
|
||||
}
|
||||
|
||||
func parseOID(oidStr string) (asn1.ObjectIdentifier, error) {
|
||||
var oid asn1.ObjectIdentifier
|
||||
for _, a := range strings.Split(oidStr, ".") {
|
||||
|
@ -113,8 +114,14 @@ var stringToQualifierType = map[string]asn1.ObjectIdentifier{
|
|||
"id-qt-cps": policyasn1.CPSQualifierOID,
|
||||
}
|
||||
|
||||
func newProfile(config ProfileConfig) (*signingProfile, error) {
|
||||
sp := &signingProfile{
|
||||
func newProfile(config ProfileConfig) (*issuanceProfile, error) {
|
||||
if config.IssuerURL == "" {
|
||||
return nil, errors.New("Issuer URL is required")
|
||||
}
|
||||
if config.OCSPURL == "" {
|
||||
return nil, errors.New("OCSP URL is required")
|
||||
}
|
||||
sp := &issuanceProfile{
|
||||
useForRSALeaves: config.UseForRSALeaves,
|
||||
useForECDSALeaves: config.UseForECDSALeaves,
|
||||
allowMustStaple: config.AllowMustStaple,
|
||||
|
@ -127,12 +134,6 @@ func newProfile(config ProfileConfig) (*signingProfile, error) {
|
|||
maxBackdate: config.MaxValidityBackdate.Duration,
|
||||
maxValidity: config.MaxValidityPeriod.Duration,
|
||||
}
|
||||
if config.IssuerURL == "" {
|
||||
return nil, errors.New("Issuer URL is required")
|
||||
}
|
||||
if config.OCSPURL == "" {
|
||||
return nil, errors.New("OCSP URL is required")
|
||||
}
|
||||
if len(config.Policies) > 0 {
|
||||
var policies []policyasn1.PolicyInformation
|
||||
for _, policyConfig := range config.Policies {
|
||||
|
@ -166,9 +167,9 @@ func newProfile(config ProfileConfig) (*signingProfile, error) {
|
|||
return sp, nil
|
||||
}
|
||||
|
||||
// requestValid verifies the passed IssuanceRequest against the signingProfile. If the
|
||||
// requestValid verifies the passed IssuanceRequest against the profile. If the
|
||||
// request doesn't match the signing profile an error is returned.
|
||||
func (p *signingProfile) requestValid(clk clock.Clock, req *IssuanceRequest) error {
|
||||
func (p *issuanceProfile) requestValid(clk clock.Clock, req *IssuanceRequest) error {
|
||||
switch req.PublicKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
if !p.useForRSALeaves {
|
||||
|
@ -229,7 +230,7 @@ var defaultEKU = []x509.ExtKeyUsage{
|
|||
x509.ExtKeyUsageClientAuth,
|
||||
}
|
||||
|
||||
func (p *signingProfile) generateTemplate(clk clock.Clock) *x509.Certificate {
|
||||
func (p *issuanceProfile) generateTemplate(clk clock.Clock) *x509.Certificate {
|
||||
template := &x509.Certificate{
|
||||
SignatureAlgorithm: p.sigAlg,
|
||||
ExtKeyUsage: defaultEKU,
|
||||
|
@ -249,32 +250,32 @@ func (p *signingProfile) generateTemplate(clk clock.Clock) *x509.Certificate {
|
|||
return template
|
||||
}
|
||||
|
||||
// Signer is a certificate signer
|
||||
type Signer struct {
|
||||
issuer *x509.Certificate
|
||||
// Issuer is capable of issuing new certificates
|
||||
type Issuer struct {
|
||||
cert *x509.Certificate
|
||||
signer crypto.Signer
|
||||
profile *signingProfile
|
||||
clk clock.Clock
|
||||
profile *issuanceProfile
|
||||
lintKey crypto.Signer
|
||||
lints zlint.Registry
|
||||
clk clock.Clock
|
||||
}
|
||||
|
||||
// Config contains the information necessary to construct a Signer
|
||||
type Config struct {
|
||||
Issuer *x509.Certificate
|
||||
// IssuerConfig contains the information necessary to construct an Issuer
|
||||
type IssuerConfig struct {
|
||||
Cert *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
Profile ProfileConfig
|
||||
IgnoredLints []string
|
||||
Clk clock.Clock
|
||||
Profile ProfileConfig
|
||||
}
|
||||
|
||||
// NewSigner constructs a Signer from the provided Config
|
||||
func NewSigner(config Config) (*Signer, error) {
|
||||
// New constructs an Issuer from the provided IssuerConfig
|
||||
func New(config IssuerConfig) (*Issuer, error) {
|
||||
profile, err := newProfile(config.Profile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch k := config.Issuer.PublicKey.(type) {
|
||||
switch k := config.Cert.PublicKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
profile.sigAlg = x509.SHA256WithRSA
|
||||
case *ecdsa.PublicKey:
|
||||
|
@ -306,15 +307,15 @@ func NewSigner(config Config) (*Signer, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &Signer{
|
||||
issuer: config.Issuer,
|
||||
i := &Issuer{
|
||||
cert: config.Cert,
|
||||
signer: config.Signer,
|
||||
clk: config.Clk,
|
||||
lints: lints,
|
||||
lintKey: lintKey,
|
||||
profile: profile,
|
||||
}
|
||||
return s, nil
|
||||
return i, nil
|
||||
}
|
||||
|
||||
var ctPoisonExt = pkix.Extension{
|
||||
|
@ -381,14 +382,14 @@ func generateSKID(pk crypto.PublicKey) ([]byte, error) {
|
|||
// key, it is signed using a throwaway key so that it can be linted using
|
||||
// zlint. If the linting fails, an error is returned and the certificate
|
||||
// is not signed using the issuer's key.
|
||||
func (s *Signer) Issue(req *IssuanceRequest) ([]byte, error) {
|
||||
func (i *Issuer) Issue(req *IssuanceRequest) ([]byte, error) {
|
||||
// check request is valid according to the issuance profile
|
||||
if err := s.profile.requestValid(s.clk, req); err != nil {
|
||||
if err := i.profile.requestValid(i.clk, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// generate template from the issuance profile
|
||||
template := s.profile.generateTemplate(s.clk)
|
||||
template := i.profile.generateTemplate(i.clk)
|
||||
|
||||
// populate template from the issuance request
|
||||
template.NotBefore, template.NotAfter = req.NotBefore, req.NotAfter
|
||||
|
@ -397,7 +398,7 @@ func (s *Signer) Issue(req *IssuanceRequest) ([]byte, error) {
|
|||
template.Subject.CommonName = req.CommonName
|
||||
}
|
||||
template.DNSNames = req.DNSNames
|
||||
template.AuthorityKeyId = s.issuer.SubjectKeyId
|
||||
template.AuthorityKeyId = i.cert.SubjectKeyId
|
||||
skid, err := generateSKID(req.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -426,16 +427,16 @@ func (s *Signer) Issue(req *IssuanceRequest) ([]byte, error) {
|
|||
|
||||
// check that the tbsCertificate is properly formed by signing it
|
||||
// with a throwaway key and then linting it using zlint
|
||||
lintCert, err := lint.MakeLintCert(template, s.issuer, req.PublicKey, s.lintKey)
|
||||
lintCert, err := lint.MakeLintCert(template, i.cert, req.PublicKey, i.lintKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = lint.LintCert(lintCert, s.lints)
|
||||
err = lint.LintCert(lintCert, i.lints)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tbsCertificate linting failed: %w", err)
|
||||
}
|
||||
|
||||
return x509.CreateCertificate(rand.Reader, template, s.issuer, req.PublicKey, s.signer)
|
||||
return x509.CreateCertificate(rand.Reader, template, i.cert, req.PublicKey, i.signer)
|
||||
}
|
||||
|
||||
func ContainsMustStaple(extensions []pkix.Extension) bool {
|
|
@ -1,4 +1,4 @@
|
|||
package signer
|
||||
package issuance
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
|
@ -54,7 +54,7 @@ func TestNewProfilePolicies(t *testing.T) {
|
|||
})
|
||||
profile, err := newProfile(config)
|
||||
test.AssertNotError(t, err, "newProfile failed")
|
||||
test.AssertDeepEquals(t, *profile, signingProfile{
|
||||
test.AssertDeepEquals(t, *profile, issuanceProfile{
|
||||
useForRSALeaves: true,
|
||||
useForECDSALeaves: true,
|
||||
allowMustStaple: true,
|
||||
|
@ -131,31 +131,31 @@ func TestRequestValid(t *testing.T) {
|
|||
fc.Add(time.Hour * 24)
|
||||
tests := []struct {
|
||||
name string
|
||||
profile *signingProfile
|
||||
profile *issuanceProfile
|
||||
request *IssuanceRequest
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "unsupported key type",
|
||||
profile: &signingProfile{},
|
||||
profile: &issuanceProfile{},
|
||||
request: &IssuanceRequest{PublicKey: &dsa.PublicKey{}},
|
||||
expectedError: "unsupported public key type",
|
||||
},
|
||||
{
|
||||
name: "cannot sign rsa",
|
||||
profile: &signingProfile{},
|
||||
profile: &issuanceProfile{},
|
||||
request: &IssuanceRequest{PublicKey: &rsa.PublicKey{}},
|
||||
expectedError: "cannot sign RSA public keys",
|
||||
},
|
||||
{
|
||||
name: "cannot sign ecdsa",
|
||||
profile: &signingProfile{},
|
||||
profile: &issuanceProfile{},
|
||||
request: &IssuanceRequest{PublicKey: &ecdsa.PublicKey{}},
|
||||
expectedError: "cannot sign ECDSA public keys",
|
||||
},
|
||||
{
|
||||
name: "must staple not allowed",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
|
@ -166,7 +166,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "ct poison not allowed",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
|
@ -177,7 +177,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "sct list not allowed",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
|
@ -188,7 +188,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "sct list and ct poison not allowed",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
allowCTPoison: true,
|
||||
allowSCTList: true,
|
||||
|
@ -202,7 +202,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "common name not allowed",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
|
@ -213,7 +213,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "negative validity",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
|
@ -225,7 +225,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "validity larger than max",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
maxValidity: time.Minute,
|
||||
},
|
||||
|
@ -238,7 +238,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "validity backdated more than max",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
maxValidity: time.Hour * 2,
|
||||
maxBackdate: time.Hour,
|
||||
|
@ -252,7 +252,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "validity is forward dated",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
maxValidity: time.Hour * 2,
|
||||
maxBackdate: time.Hour,
|
||||
|
@ -266,7 +266,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "serial too short",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
maxValidity: time.Hour * 2,
|
||||
},
|
||||
|
@ -279,7 +279,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "serial too long",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
maxValidity: time.Hour * 2,
|
||||
},
|
||||
|
@ -293,7 +293,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "good",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
useForECDSALeaves: true,
|
||||
maxValidity: time.Hour * 2,
|
||||
},
|
||||
|
@ -325,12 +325,12 @@ func TestRequestValid(t *testing.T) {
|
|||
func TestGenerateTemplate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
profile *signingProfile
|
||||
profile *issuanceProfile
|
||||
expectedTemplate *x509.Certificate
|
||||
}{
|
||||
{
|
||||
name: "crl url",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
crlURL: "crl-url",
|
||||
sigAlg: x509.SHA256WithRSA,
|
||||
},
|
||||
|
@ -345,7 +345,7 @@ func TestGenerateTemplate(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "include policies",
|
||||
profile: &signingProfile{
|
||||
profile: &issuanceProfile{
|
||||
sigAlg: x509.SHA256WithRSA,
|
||||
policies: &pkix.Extension{
|
||||
Id: asn1.ObjectIdentifier{1, 2, 3},
|
||||
|
@ -378,23 +378,23 @@ func TestGenerateTemplate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNewSignerUnsupportedKeyType(t *testing.T) {
|
||||
_, err := NewSigner(Config{
|
||||
_, err := New(IssuerConfig{
|
||||
Profile: defaultProfileConfig(),
|
||||
Issuer: &x509.Certificate{
|
||||
Cert: &x509.Certificate{
|
||||
PublicKey: &ed25519.PublicKey{},
|
||||
},
|
||||
Signer: &ed25519.PrivateKey{},
|
||||
})
|
||||
test.AssertError(t, err, "NewSigner didn't fail")
|
||||
test.AssertError(t, err, "issuance.New didn't fail")
|
||||
test.AssertEquals(t, err.Error(), "unsupported issuer key type")
|
||||
}
|
||||
|
||||
func TestNewSignerRSAKey(t *testing.T) {
|
||||
mod, ok := big.NewInt(0).SetString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)
|
||||
test.Assert(t, ok, "failed to set mod")
|
||||
signer, err := NewSigner(Config{
|
||||
signer, err := New(IssuerConfig{
|
||||
Profile: defaultProfileConfig(),
|
||||
Issuer: &x509.Certificate{
|
||||
Cert: &x509.Certificate{
|
||||
PublicKey: &rsa.PublicKey{
|
||||
N: mod,
|
||||
},
|
||||
|
@ -405,15 +405,15 @@ func TestNewSignerRSAKey(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
test.AssertNotError(t, err, "NewSigner failed")
|
||||
test.AssertNotError(t, err, "issuance.New failed")
|
||||
_, ok = signer.lintKey.(*rsa.PrivateKey)
|
||||
test.Assert(t, ok, "lint key is not RSA")
|
||||
}
|
||||
|
||||
func TestNewSignerECDSAKey(t *testing.T) {
|
||||
signer, err := NewSigner(Config{
|
||||
signer, err := New(IssuerConfig{
|
||||
Profile: defaultProfileConfig(),
|
||||
Issuer: &x509.Certificate{
|
||||
Cert: &x509.Certificate{
|
||||
PublicKey: &ecdsa.PublicKey{
|
||||
Curve: elliptic.P256(),
|
||||
},
|
||||
|
@ -424,7 +424,7 @@ func TestNewSignerECDSAKey(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
test.AssertNotError(t, err, "NewSigner failed")
|
||||
test.AssertNotError(t, err, "issuance.New failed")
|
||||
_, ok := signer.lintKey.(*ecdsa.PrivateKey)
|
||||
test.Assert(t, ok, "lint key is not ECDSA")
|
||||
}
|
||||
|
@ -478,14 +478,14 @@ func TestIssue(t *testing.T) {
|
|||
t.Run(tc.name, func(t *testing.T) {
|
||||
fc := clock.NewFake()
|
||||
fc.Set(time.Now())
|
||||
signer, err := NewSigner(Config{
|
||||
Issuer: issuerCert,
|
||||
signer, err := New(IssuerConfig{
|
||||
Cert: issuerCert,
|
||||
Signer: issuerSigner,
|
||||
Clk: fc,
|
||||
Profile: defaultProfileConfig(),
|
||||
IgnoredLints: []string{"w_ct_sct_policy_count_unsatisfied", "n_subject_common_name_included"},
|
||||
})
|
||||
test.AssertNotError(t, err, "NewSigner failed")
|
||||
test.AssertNotError(t, err, "issuance.New failed")
|
||||
pk, err := tc.generateFunc()
|
||||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
certBytes, err := signer.Issue(&IssuanceRequest{
|
||||
|
@ -514,14 +514,14 @@ func TestIssue(t *testing.T) {
|
|||
func TestIssueRSA(t *testing.T) {
|
||||
fc := clock.NewFake()
|
||||
fc.Set(time.Now())
|
||||
signer, err := NewSigner(Config{
|
||||
Issuer: issuerCert,
|
||||
signer, err := New(IssuerConfig{
|
||||
Cert: issuerCert,
|
||||
Signer: issuerSigner,
|
||||
Clk: fc,
|
||||
Profile: defaultProfileConfig(),
|
||||
IgnoredLints: []string{"w_ct_sct_policy_count_unsatisfied"},
|
||||
})
|
||||
test.AssertNotError(t, err, "NewSigner failed")
|
||||
test.AssertNotError(t, err, "issuance.New failed")
|
||||
pk, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
certBytes, err := signer.Issue(&IssuanceRequest{
|
||||
|
@ -545,14 +545,14 @@ func TestIssueRSA(t *testing.T) {
|
|||
func TestIssueCTPoison(t *testing.T) {
|
||||
fc := clock.NewFake()
|
||||
fc.Set(time.Now())
|
||||
signer, err := NewSigner(Config{
|
||||
Issuer: issuerCert,
|
||||
signer, err := New(IssuerConfig{
|
||||
Cert: issuerCert,
|
||||
Signer: issuerSigner,
|
||||
Clk: fc,
|
||||
Profile: defaultProfileConfig(),
|
||||
IgnoredLints: []string{"w_ct_sct_policy_count_unsatisfied"},
|
||||
})
|
||||
test.AssertNotError(t, err, "NewSigner failed")
|
||||
test.AssertNotError(t, err, "issuance.New failed")
|
||||
pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
certBytes, err := signer.Issue(&IssuanceRequest{
|
||||
|
@ -577,14 +577,14 @@ func TestIssueCTPoison(t *testing.T) {
|
|||
func TestIssueSCTList(t *testing.T) {
|
||||
fc := clock.NewFake()
|
||||
fc.Set(time.Now())
|
||||
signer, err := NewSigner(Config{
|
||||
Issuer: issuerCert,
|
||||
signer, err := New(IssuerConfig{
|
||||
Cert: issuerCert,
|
||||
Signer: issuerSigner,
|
||||
Clk: fc,
|
||||
Profile: defaultProfileConfig(),
|
||||
IgnoredLints: []string{"w_ct_sct_policy_count_unsatisfied"},
|
||||
})
|
||||
test.AssertNotError(t, err, "NewSigner failed")
|
||||
test.AssertNotError(t, err, "issuance.New failed")
|
||||
pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
certBytes, err := signer.Issue(&IssuanceRequest{
|
||||
|
@ -614,14 +614,14 @@ func TestIssueSCTList(t *testing.T) {
|
|||
func TestIssueMustStaple(t *testing.T) {
|
||||
fc := clock.NewFake()
|
||||
fc.Set(time.Now())
|
||||
signer, err := NewSigner(Config{
|
||||
Issuer: issuerCert,
|
||||
signer, err := New(IssuerConfig{
|
||||
Cert: issuerCert,
|
||||
Signer: issuerSigner,
|
||||
Clk: fc,
|
||||
Profile: defaultProfileConfig(),
|
||||
IgnoredLints: []string{"w_ct_sct_policy_count_unsatisfied"},
|
||||
})
|
||||
test.AssertNotError(t, err, "NewSigner failed")
|
||||
test.AssertNotError(t, err, "issuance.New failed")
|
||||
pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
certBytes, err := signer.Issue(&IssuanceRequest{
|
||||
|
@ -646,13 +646,13 @@ func TestIssueMustStaple(t *testing.T) {
|
|||
func TestIssueBadLint(t *testing.T) {
|
||||
fc := clock.NewFake()
|
||||
fc.Set(time.Now())
|
||||
signer, err := NewSigner(Config{
|
||||
Issuer: issuerCert,
|
||||
signer, err := New(IssuerConfig{
|
||||
Cert: issuerCert,
|
||||
Signer: issuerSigner,
|
||||
Clk: fc,
|
||||
Profile: defaultProfileConfig(),
|
||||
})
|
||||
test.AssertNotError(t, err, "NewSigner failed")
|
||||
test.AssertNotError(t, err, "issuance.New failed")
|
||||
pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
_, err = signer.Issue(&IssuanceRequest{
|
Loading…
Reference in New Issue