Move goodkey and nonce out of core (#1869)
This commit is contained in:
parent
d6a301645f
commit
9a4b979397
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
|||
package core
|
||||
package goodkey
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
|
@ -1,4 +1,4 @@
|
|||
package core
|
||||
package nonce
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
|
@ -1,4 +1,4 @@
|
|||
package core
|
||||
package nonce
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -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{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue