Move goodkey and nonce out of core (#1869)

This commit is contained in:
Jacob Hoffman-Andrews 2016-06-02 11:29:58 -07:00
parent d6a301645f
commit 9a4b979397
13 changed files with 49 additions and 36 deletions

View File

@ -31,6 +31,7 @@ import (
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/core"
csrlib "github.com/letsencrypt/boulder/csr"
"github.com/letsencrypt/boulder/goodkey"
blog "github.com/letsencrypt/boulder/log"
)
@ -111,7 +112,7 @@ type CertificateAuthorityImpl struct {
SA certificateStorage
PA core.PolicyAuthority
Publisher core.Publisher
keyPolicy core.KeyPolicy
keyPolicy goodkey.KeyPolicy
clk clock.Clock
log blog.Logger
stats statsd.Statter
@ -181,7 +182,7 @@ func NewCertificateAuthorityImpl(
clk clock.Clock,
stats statsd.Statter,
issuers []Issuer,
keyPolicy core.KeyPolicy,
keyPolicy goodkey.KeyPolicy,
) (*CertificateAuthorityImpl, error) {
var ca *CertificateAuthorityImpl
var err error

View File

@ -19,6 +19,7 @@ import (
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/goodkey"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/mocks"
"github.com/letsencrypt/boulder/policy"
@ -130,7 +131,7 @@ type testCtx struct {
caConfig cmd.CAConfig
pa core.PolicyAuthority
issuers []Issuer
keyPolicy core.KeyPolicy
keyPolicy goodkey.KeyPolicy
fc clock.FakeClock
stats *mocks.Statter
}
@ -238,7 +239,7 @@ func setup(t *testing.T) *testCtx {
issuers := []Issuer{{caKey, caCert}}
keyPolicy := core.KeyPolicy{
keyPolicy := goodkey.KeyPolicy{
AllowRSA: true,
AllowECDSANISTP256: true,
AllowECDSANISTP384: true,

View File

@ -12,6 +12,7 @@ import (
"github.com/letsencrypt/pkcs11key"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/goodkey"
)
// Config stores configuration parameters that applications
@ -203,16 +204,16 @@ type AllowedSigningAlgos struct {
}
// KeyPolicy returns a KeyPolicy reflecting the Boulder configuration.
func (config *Config) KeyPolicy() core.KeyPolicy {
func (config *Config) KeyPolicy() goodkey.KeyPolicy {
if config.AllowedSigningAlgos != nil {
return core.KeyPolicy{
return goodkey.KeyPolicy{
AllowRSA: config.AllowedSigningAlgos.RSA,
AllowECDSANISTP256: config.AllowedSigningAlgos.ECDSANISTP256,
AllowECDSANISTP384: config.AllowedSigningAlgos.ECDSANISTP384,
AllowECDSANISTP521: config.AllowedSigningAlgos.ECDSANISTP521,
}
}
return core.KeyPolicy{
return goodkey.KeyPolicy{
AllowRSA: true,
}
}

View File

@ -8,6 +8,7 @@ import (
"strings"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/goodkey"
)
// maxCNLength is the maximum length allowed for the common name as specified in RFC 5280
@ -32,7 +33,7 @@ var badSignatureAlgorithms = map[x509.SignatureAlgorithm]bool{
// VerifyCSR checks the validity of a x509.CertificateRequest. Before doing checks it normalizes
// the CSR which lowers the case of DNS names and subject CN, and if forceCNFromSAN is true it
// will hoist a DNS name into the CN if it is empty.
func VerifyCSR(csr *x509.CertificateRequest, maxNames int, keyPolicy *core.KeyPolicy, pa core.PolicyAuthority, forceCNFromSAN bool, regID int64) error {
func VerifyCSR(csr *x509.CertificateRequest, maxNames int, keyPolicy *goodkey.KeyPolicy, pa core.PolicyAuthority, forceCNFromSAN bool, regID int64) error {
normalizeCSR(csr, forceCNFromSAN)
key, ok := csr.PublicKey.(crypto.PublicKey)
if !ok {

View File

@ -12,10 +12,11 @@ import (
"github.com/square/go-jose"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/goodkey"
"github.com/letsencrypt/boulder/test"
)
var testingPolicy = &core.KeyPolicy{
var testingPolicy = &goodkey.KeyPolicy{
AllowRSA: true,
AllowECDSANISTP256: true,
AllowECDSANISTP384: true,
@ -57,7 +58,7 @@ func TestVerifyCSR(t *testing.T) {
cases := []struct {
csr *x509.CertificateRequest
maxNames int
keyPolicy *core.KeyPolicy
keyPolicy *goodkey.KeyPolicy
pa core.PolicyAuthority
regID int64
expectedError error

View File

@ -1,4 +1,4 @@
package core
package goodkey
import (
"crypto"
@ -9,6 +9,8 @@ import (
"math/big"
"reflect"
"sync"
"github.com/letsencrypt/boulder/core"
)
// To generate, run: primes 2 752 | tr '\n' ,
@ -57,7 +59,7 @@ func (policy *KeyPolicy) GoodKey(key crypto.PublicKey) error {
case *ecdsa.PublicKey:
return policy.goodKeyECDSA(*t)
default:
return MalformedRequestError(fmt.Sprintf("Unknown key type %s", reflect.TypeOf(key)))
return core.MalformedRequestError(fmt.Sprintf("Unknown key type %s", reflect.TypeOf(key)))
}
}
@ -87,7 +89,7 @@ func (policy *KeyPolicy) goodKeyECDSA(key ecdsa.PublicKey) (err error) {
// This code assumes that the point at infinity is (0,0), which is the
// case for all supported curves.
if isPointAtInfinityNISTP(key.X, key.Y) {
return MalformedRequestError("Key x, y must not be the point at infinity")
return core.MalformedRequestError("Key x, y must not be the point at infinity")
}
// SP800-56A § 5.6.2.3.2 Step 2.
@ -104,11 +106,11 @@ func (policy *KeyPolicy) goodKeyECDSA(key ecdsa.PublicKey) (err error) {
// correct representation of an element in the underlying field by verifying
// that x and y are integers in [0, p-1].
if key.X.Sign() < 0 || key.Y.Sign() < 0 {
return MalformedRequestError("Key x, y must not be negative")
return core.MalformedRequestError("Key x, y must not be negative")
}
if key.X.Cmp(params.P) >= 0 || key.Y.Cmp(params.P) >= 0 {
return MalformedRequestError("Key x, y must not exceed P-1")
return core.MalformedRequestError("Key x, y must not exceed P-1")
}
// SP800-56A § 5.6.2.3.2 Step 3.
@ -126,7 +128,7 @@ func (policy *KeyPolicy) goodKeyECDSA(key ecdsa.PublicKey) (err error) {
// This proves that the public key is on the correct elliptic curve.
// But in practice, this test is provided by crypto/elliptic, so use that.
if !key.Curve.IsOnCurve(key.X, key.Y) {
return MalformedRequestError("Key point is not on the curve")
return core.MalformedRequestError("Key point is not on the curve")
}
// SP800-56A § 5.6.2.3.2 Step 4.
@ -142,7 +144,7 @@ func (policy *KeyPolicy) goodKeyECDSA(key ecdsa.PublicKey) (err error) {
// n*Q = O iff n*Q is the point at infinity (see step 1).
ox, oy := key.Curve.ScalarMult(key.X, key.Y, params.N.Bytes())
if !isPointAtInfinityNISTP(ox, oy) {
return MalformedRequestError("Public key does not have correct order")
return core.MalformedRequestError("Public key does not have correct order")
}
// End of SP800-56A § 5.6.2.3.2 Public Key Validation Routine.
@ -170,14 +172,14 @@ func (policy *KeyPolicy) goodCurve(c elliptic.Curve) (err error) {
case policy.AllowECDSANISTP521 && params == elliptic.P521().Params():
return nil
default:
return MalformedRequestError(fmt.Sprintf("ECDSA curve %v not allowed", params.Name))
return core.MalformedRequestError(fmt.Sprintf("ECDSA curve %v not allowed", params.Name))
}
}
// GoodKeyRSA determines if a RSA pubkey meets our requirements
func (policy *KeyPolicy) goodKeyRSA(key rsa.PublicKey) (err error) {
if !policy.AllowRSA {
return MalformedRequestError("RSA keys are not allowed")
return core.MalformedRequestError("RSA keys are not allowed")
}
// Baseline Requirements Appendix A
@ -186,15 +188,15 @@ func (policy *KeyPolicy) goodKeyRSA(key rsa.PublicKey) (err error) {
modulusBitLen := modulus.BitLen()
const maxKeySize = 4096
if modulusBitLen < 2048 {
return MalformedRequestError(fmt.Sprintf("Key too small: %d", modulusBitLen))
return core.MalformedRequestError(fmt.Sprintf("Key too small: %d", modulusBitLen))
}
if modulusBitLen > maxKeySize {
return MalformedRequestError(fmt.Sprintf("Key too large: %d > %d", modulusBitLen, maxKeySize))
return core.MalformedRequestError(fmt.Sprintf("Key too large: %d > %d", modulusBitLen, maxKeySize))
}
// Bit lengths that are not a multiple of 8 may cause problems on some
// client implementations.
if modulusBitLen%8 != 0 {
return MalformedRequestError(fmt.Sprintf("Key length wasn't a multiple of 8: %d", modulusBitLen))
return core.MalformedRequestError(fmt.Sprintf("Key length wasn't a multiple of 8: %d", modulusBitLen))
}
// The CA SHALL confirm that the value of the public exponent is an
// odd number equal to 3 or more. Additionally, the public exponent
@ -203,13 +205,13 @@ func (policy *KeyPolicy) goodKeyRSA(key rsa.PublicKey) (err error) {
// 2^32 - 1 or 2^64 - 1, because it stores E as an integer. So we
// don't need to check the upper bound.
if (key.E%2) == 0 || key.E < ((1<<16)+1) {
return MalformedRequestError(fmt.Sprintf("Key exponent should be odd and >2^16: %d", key.E))
return core.MalformedRequestError(fmt.Sprintf("Key exponent should be odd and >2^16: %d", key.E))
}
// The modulus SHOULD also have the following characteristics: an odd
// number, not the power of a prime, and have no factors smaller than 752.
// TODO: We don't yet check for "power of a prime."
if checkSmallPrimes(modulus) {
return MalformedRequestError("Key divisible by small prime")
return core.MalformedRequestError("Key divisible by small prime")
}
return nil

View File

@ -1,4 +1,4 @@
package core
package goodkey
import (
"crypto/ecdsa"

View File

@ -1,4 +1,4 @@
package core
package nonce
import (
"crypto/aes"

View File

@ -1,4 +1,4 @@
package core
package nonce
import (
"fmt"

View File

@ -14,6 +14,7 @@ import (
"github.com/cactus/go-statsd-client/statsd"
"github.com/jmhodges/clock"
"github.com/letsencrypt/boulder/goodkey"
"github.com/letsencrypt/boulder/metrics"
"github.com/letsencrypt/boulder/probs"
"github.com/letsencrypt/net/publicsuffix"
@ -51,7 +52,7 @@ type RegistrationAuthorityImpl struct {
clk clock.Clock
log blog.Logger
dc *DomainCheck
keyPolicy core.KeyPolicy
keyPolicy goodkey.KeyPolicy
// How long before a newly created authorization expires.
authorizationLifetime time.Duration
pendingAuthorizationLifetime time.Duration
@ -71,7 +72,7 @@ type RegistrationAuthorityImpl struct {
}
// NewRegistrationAuthorityImpl constructs a new RA object.
func NewRegistrationAuthorityImpl(clk clock.Clock, logger blog.Logger, stats statsd.Statter, dc *DomainCheck, policies ratelimit.RateLimitConfig, maxContactsPerReg int, keyPolicy core.KeyPolicy, newVARPC bool, maxNames int, forceCNFromSAN bool) *RegistrationAuthorityImpl {
func NewRegistrationAuthorityImpl(clk clock.Clock, logger blog.Logger, stats statsd.Statter, dc *DomainCheck, policies ratelimit.RateLimitConfig, maxContactsPerReg int, keyPolicy goodkey.KeyPolicy, newVARPC bool, maxNames int, forceCNFromSAN bool) *RegistrationAuthorityImpl {
// TODO(jmhodges): making RA take a "RA" stats.Scope, not Statter
scope := metrics.NewStatsdScope(stats, "RA")
ra := &RegistrationAuthorityImpl{

View File

@ -19,6 +19,7 @@ import (
"github.com/letsencrypt/boulder/bdns"
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/goodkey"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/mocks"
"github.com/letsencrypt/boulder/policy"
@ -146,7 +147,7 @@ func makeResponse(ch core.Challenge) (out core.Challenge, err error) {
return
}
var testKeyPolicy = core.KeyPolicy{
var testKeyPolicy = goodkey.KeyPolicy{
AllowRSA: true,
AllowECDSANISTP256: true,
AllowECDSANISTP384: true,

View File

@ -19,7 +19,9 @@ import (
"github.com/cactus/go-statsd-client/statsd"
"github.com/jmhodges/clock"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/goodkey"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/nonce"
"github.com/letsencrypt/boulder/probs"
jose "github.com/square/go-jose"
)
@ -61,10 +63,10 @@ type WebFrontEndImpl struct {
SubscriberAgreementURL string
// Register of anti-replay nonces
nonceService *core.NonceService
nonceService *nonce.NonceService
// Key policy.
keyPolicy core.KeyPolicy
keyPolicy goodkey.KeyPolicy
// Cache settings
CertCacheDuration time.Duration
@ -84,10 +86,10 @@ type WebFrontEndImpl struct {
}
// NewWebFrontEndImpl constructs a web service for Boulder
func NewWebFrontEndImpl(stats statsd.Statter, clk clock.Clock, keyPolicy core.KeyPolicy) (WebFrontEndImpl, error) {
func NewWebFrontEndImpl(stats statsd.Statter, clk clock.Clock, keyPolicy goodkey.KeyPolicy) (WebFrontEndImpl, error) {
logger := blog.Get()
nonceService, err := core.NewNonceService()
nonceService, err := nonce.NewNonceService()
if err != nil {
return WebFrontEndImpl{}, err
}

View File

@ -24,6 +24,8 @@ import (
"github.com/cactus/go-statsd-client/statsd"
"github.com/jmhodges/clock"
"github.com/letsencrypt/boulder/goodkey"
"github.com/letsencrypt/boulder/nonce"
"github.com/letsencrypt/boulder/probs"
"github.com/square/go-jose"
@ -188,7 +190,7 @@ func makeBody(s string) io.ReadCloser {
return ioutil.NopCloser(strings.NewReader(s))
}
func signRequest(t *testing.T, req string, nonceService *core.NonceService) string {
func signRequest(t *testing.T, req string, nonceService *nonce.NonceService) string {
accountKey, err := jose.LoadPrivateKey([]byte(test1KeyPrivatePEM))
test.AssertNotError(t, err, "Failed to load key")
@ -201,7 +203,7 @@ func signRequest(t *testing.T, req string, nonceService *core.NonceService) stri
return ret
}
var testKeyPolicy = core.KeyPolicy{
var testKeyPolicy = goodkey.KeyPolicy{
AllowRSA: true,
AllowECDSANISTP256: true,
AllowECDSANISTP384: true,