Skip to content

Commit

Permalink
Merge pull request #1298 from hlandauf/ecdsa-good-key
Browse files Browse the repository at this point in the history
Add good key testing for ECDSA.
  • Loading branch information
jmhodges committed Jan 7, 2016
2 parents 1f6e566 + f218e31 commit 1cacde2
Show file tree
Hide file tree
Showing 13 changed files with 366 additions and 78 deletions.
5 changes: 4 additions & 1 deletion ca/certificate-authority.go
Expand Up @@ -65,6 +65,7 @@ type CertificateAuthorityImpl struct {
SA core.StorageAuthority
PA core.PolicyAuthority
Publisher core.Publisher
keyPolicy core.KeyPolicy
clk clock.Clock // TODO(jmhodges): should be private, like log
log *blog.AuditLogger
stats statsd.Statter
Expand All @@ -90,6 +91,7 @@ func NewCertificateAuthorityImpl(
stats statsd.Statter,
issuer *x509.Certificate,
privateKey crypto.Signer,
keyPolicy core.KeyPolicy,
) (*CertificateAuthorityImpl, error) {
var ca *CertificateAuthorityImpl
var err error
Expand Down Expand Up @@ -142,6 +144,7 @@ func NewCertificateAuthorityImpl(
stats: stats,
notAfter: issuer.NotAfter,
hsmFaultTimeout: config.HSMFaultTimeout.Duration,
keyPolicy: keyPolicy,
}

if config.Expiry == "" {
Expand Down Expand Up @@ -236,7 +239,7 @@ func (ca *CertificateAuthorityImpl) IssueCertificate(csr x509.CertificateRequest
ca.log.AuditErr(err)
return emptyCert, err
}
if err = core.GoodKey(key); err != nil {
if err = ca.keyPolicy.GoodKey(key); err != nil {
err = core.MalformedRequestError(fmt.Sprintf("Invalid public key in CSR: %s", err.Error()))
// AUDIT[ Certificate Requests ] 11917fa4-10ef-4e0d-9105-bacbe7836a3c
ca.log.AuditErr(err)
Expand Down
42 changes: 25 additions & 17 deletions ca/certificate-authority_test.go
Expand Up @@ -109,13 +109,14 @@ func mustRead(path string) []byte {
}

type testCtx struct {
sa core.StorageAuthority
caConfig cmd.CAConfig
reg core.Registration
pa core.PolicyAuthority
fc clock.FakeClock
stats *mocks.Statter
cleanUp func()
sa core.StorageAuthority
caConfig cmd.CAConfig
reg core.Registration
pa core.PolicyAuthority
keyPolicy core.KeyPolicy
fc clock.FakeClock
stats *mocks.Statter
cleanUp func()
}

var caKey crypto.Signer
Expand Down Expand Up @@ -207,11 +208,18 @@ func setup(t *testing.T) *testCtx {

stats := mocks.NewStatter()

keyPolicy := core.KeyPolicy{
AllowRSA: true,
AllowECDSANISTP256: true,
AllowECDSANISTP384: true,
}

return &testCtx{
ssa,
caConfig,
reg,
pa,
keyPolicy,
fc,
&stats,
cleanUp,
Expand All @@ -223,14 +231,14 @@ func TestFailNoSerial(t *testing.T) {
defer ctx.cleanUp()

ctx.caConfig.SerialPrefix = 0
_, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
_, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
test.AssertError(t, err, "CA should have failed with no SerialPrefix")
}

func TestIssueCertificate(t *testing.T) {
ctx := setup(t)
defer ctx.cleanUp()
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
test.AssertNotError(t, err, "Failed to create CA")
ca.Publisher = &mocks.Publisher{}
ca.PA = ctx.pa
Expand Down Expand Up @@ -307,7 +315,7 @@ func TestIssueCertificate(t *testing.T) {
func TestRejectNoName(t *testing.T) {
ctx := setup(t)
defer ctx.cleanUp()
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
test.AssertNotError(t, err, "Failed to create CA")
ca.Publisher = &mocks.Publisher{}
ca.PA = ctx.pa
Expand All @@ -324,7 +332,7 @@ func TestRejectNoName(t *testing.T) {
func TestRejectTooManyNames(t *testing.T) {
ctx := setup(t)
defer ctx.cleanUp()
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
test.AssertNotError(t, err, "Failed to create CA")
ca.Publisher = &mocks.Publisher{}
ca.PA = ctx.pa
Expand All @@ -341,7 +349,7 @@ func TestRejectTooManyNames(t *testing.T) {
func TestDeduplication(t *testing.T) {
ctx := setup(t)
defer ctx.cleanUp()
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
test.AssertNotError(t, err, "Failed to create CA")
ca.Publisher = &mocks.Publisher{}
ca.PA = ctx.pa
Expand All @@ -365,7 +373,7 @@ func TestDeduplication(t *testing.T) {
func TestRejectValidityTooLong(t *testing.T) {
ctx := setup(t)
defer ctx.cleanUp()
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
test.AssertNotError(t, err, "Failed to create CA")
ca.Publisher = &mocks.Publisher{}
ca.PA = ctx.pa
Expand All @@ -383,7 +391,7 @@ func TestRejectValidityTooLong(t *testing.T) {
func TestShortKey(t *testing.T) {
ctx := setup(t)
defer ctx.cleanUp()
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
ca.Publisher = &mocks.Publisher{}
ca.PA = ctx.pa
ca.SA = ctx.sa
Expand All @@ -399,7 +407,7 @@ func TestShortKey(t *testing.T) {
func TestRejectBadAlgorithm(t *testing.T) {
ctx := setup(t)
defer ctx.cleanUp()
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
ca.Publisher = &mocks.Publisher{}
ca.PA = ctx.pa
ca.SA = ctx.sa
Expand All @@ -416,7 +424,7 @@ func TestCapitalizedLetters(t *testing.T) {
ctx := setup(t)
defer ctx.cleanUp()
ctx.caConfig.MaxNames = 3
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
ca.Publisher = &mocks.Publisher{}
ca.PA = ctx.pa
ca.SA = ctx.sa
Expand All @@ -437,7 +445,7 @@ func TestHSMFaultTimeout(t *testing.T) {
ctx := setup(t)
defer ctx.cleanUp()

ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey)
ca, err := NewCertificateAuthorityImpl(ctx.caConfig, ctx.fc, ctx.stats, caCert, caKey, ctx.keyPolicy)
ca.Publisher = &mocks.Publisher{}
ca.PA = ctx.pa
ca.SA = ctx.sa
Expand Down
3 changes: 2 additions & 1 deletion cmd/boulder-ca/main.go
Expand Up @@ -91,7 +91,8 @@ func main() {
clock.Default(),
stats,
issuer,
priv)
priv,
c.KeyPolicy())
cmd.FailOnError(err, "Failed to create CA impl")
cai.PA = pa

Expand Down
2 changes: 1 addition & 1 deletion cmd/boulder-ra/main.go
Expand Up @@ -59,7 +59,7 @@ func main() {
}

rai := ra.NewRegistrationAuthorityImpl(clock.Default(), auditlogger, stats,
dc, rateLimitPolicies, c.RA.MaxContactsPerRegistration)
dc, rateLimitPolicies, c.RA.MaxContactsPerRegistration, c.KeyPolicy())
rai.PA = pa
raDNSTimeout, err := time.ParseDuration(c.Common.DNSTimeout)
cmd.FailOnError(err, "Couldn't parse RA DNS timeout")
Expand Down
4 changes: 3 additions & 1 deletion cmd/boulder-wfe/main.go
Expand Up @@ -53,7 +53,7 @@ func main() {
app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) {
go cmd.DebugServer(c.WFE.DebugAddr)

wfe, err := wfe.NewWebFrontEndImpl(stats, clock.Default())
wfe, err := wfe.NewWebFrontEndImpl(stats, clock.Default(), c.KeyPolicy())
cmd.FailOnError(err, "Unable to create WFE")
rac, sac := setupWFE(c, auditlogger, stats)
wfe.RA = rac
Expand All @@ -79,6 +79,8 @@ func main() {
wfe.IssuerCert, err = cmd.LoadCert(c.Common.IssuerCert)
cmd.FailOnError(err, fmt.Sprintf("Couldn't read issuer cert [%s]", c.Common.IssuerCert))

auditlogger.Info(fmt.Sprintf("WFE using key policy: %#v", c.KeyPolicy()))

go cmd.ProfileCmd("WFE", stats)

// Set up paths
Expand Down
17 changes: 17 additions & 0 deletions cmd/config.go
Expand Up @@ -187,9 +187,26 @@ type Config struct {
ReportDirectoryPath string
}

AllowedSigningAlgos struct {
RSA bool
ECDSANISTP256 bool
ECDSANISTP384 bool
ECDSANISTP521 bool
}

SubscriberAgreementURL string
}

// KeyPolicy returns a KeyPolicy reflecting the Boulder configuration.
func (config *Config) KeyPolicy() core.KeyPolicy {
return core.KeyPolicy{
AllowRSA: config.AllowedSigningAlgos.RSA,
AllowECDSANISTP256: config.AllowedSigningAlgos.ECDSANISTP256,
AllowECDSANISTP384: config.AllowedSigningAlgos.ECDSANISTP384,
AllowECDSANISTP521: config.AllowedSigningAlgos.ECDSANISTP521,
}
}

// ServiceConfig contains config items that are common to all our services, to
// be embedded in other config structs.
type ServiceConfig struct {
Expand Down

0 comments on commit 1cacde2

Please sign in to comment.