vault: sanity check key length

This commit is contained in:
Armon Dadgar 2015-03-12 11:20:27 -07:00
parent 1baf86b061
commit aa0ca02b8c
6 changed files with 57 additions and 2 deletions

View File

@ -5,6 +5,13 @@ import (
"fmt"
)
const (
// ShareOverhead is the byte size overhead of each share
// when using Split on a secret. This is caused by appending
// a one byte tag to the share.
ShareOverhead = 1
)
// polynomial represents a polynomial of arbitrary degree
type polynomial struct {
coefficients []uint8

View File

@ -39,6 +39,9 @@ type SecurityBarrier interface {
// GenerateKey is used to generate a new key
GenerateKey() ([]byte, error)
// KeyLength is used to sanity check a key
KeyLength() (int, int)
// Sealed checks if the barrier has been unlocked yet. The Barrier
// is not expected to be able to perform any CRUD until it is unsealed.
Sealed() (bool, error)

View File

@ -121,6 +121,11 @@ func (b *AESGCMBarrier) GenerateKey() ([]byte, error) {
return buf, err
}
// KeyLength is used to sanity check a key
func (b *AESGCMBarrier) KeyLength() (int, int) {
return aes.BlockSize, aes.BlockSize
}
// Sealed checks if the barrier has been unlocked yet. The Barrier
// is not expected to be able to perform any CRUD until it is unsealed.
func (b *AESGCMBarrier) Sealed() (bool, error) {

View File

@ -50,6 +50,15 @@ func testBarrier(t *testing.T, b SecurityBarrier) {
t.Fatalf("err: %v", err)
}
// Validate minimum key length
min, max := b.KeyLength()
if min < 16 {
t.Fatalf("minimum key size too small: %d", min)
}
if max < min {
t.Fatalf("maximum key size smaller than min")
}
// Unseal should not work
if err := b.Unseal(key); err != ErrBarrierNotInit {
t.Fatalf("err: %v", err)

View File

@ -54,6 +54,12 @@ func (s *SealConfig) Validate() error {
if s.SecretThreshold < 1 {
return fmt.Errorf("secret threshold must be at least one")
}
if s.SecretShares > 255 {
return fmt.Errorf("secret shares must be less than 256")
}
if s.SecretThreshold > 255 {
return fmt.Errorf("secret threshold must be less than 256")
}
if s.SecretThreshold > s.SecretShares {
return fmt.Errorf("secret threshold cannot be larger than secret shares")
}
@ -66,6 +72,16 @@ type InitResult struct {
SecretShares [][]byte
}
// ErrInvalidKey is returned if there is an error with a
// provided unseal key.
type ErrInvalidKey struct {
Reason string
}
func (e *ErrInvalidKey) Error() string {
return fmt.Sprintf("invalid key: %v", e.Reason)
}
// Core is used as the central manager of Vault activity. It is the primary point of
// interface for API handlers and is responsible for managing the logical and physical
// backends, router, security barrier, and audit trails.
@ -285,6 +301,16 @@ func (c *Core) SecretProgress() int {
// Unseal is used to provide one of the key parts to
// unseal the Vault.
func (c *Core) Unseal(key []byte) (bool, error) {
// Verify the key length
min, max := c.barrier.KeyLength()
max += shamir.ShareOverhead
if len(key) < min {
return false, &ErrInvalidKey{fmt.Sprintf("key is shorter than minimum %d bytes", min)}
}
if len(key) > max {
return false, &ErrInvalidKey{fmt.Sprintf("key is longer than maximum %d bytes", max)}
}
// Get the seal configuration
config, err := c.SealConfig()
if err != nil {

View File

@ -7,6 +7,11 @@ import (
"github.com/hashicorp/vault/physical"
)
var (
// invalidKey is used to test Unseal
invalidKey = []byte("abcdefghijklmnopqrstuvwxyz")[:17]
)
func testCore(t *testing.T) *Core {
inm := physical.NewInmem()
conf := &CoreConfig{Physical: inm}
@ -159,7 +164,7 @@ func TestCore_Init_MultiShare(t *testing.T) {
func TestCore_Unseal_MultiShare(t *testing.T) {
c := testCore(t)
_, err := c.Unseal([]byte("testing"))
_, err := c.Unseal(invalidKey)
if err != ErrNotInit {
t.Fatalf("err: %v", err)
}
@ -244,7 +249,7 @@ func TestCore_Unseal_MultiShare(t *testing.T) {
func TestCore_Unseal_Single(t *testing.T) {
c := testCore(t)
_, err := c.Unseal([]byte("testing"))
_, err := c.Unseal(invalidKey)
if err != ErrNotInit {
t.Fatalf("err: %v", err)
}