vault: sanity check key length
This commit is contained in:
parent
1baf86b061
commit
aa0ca02b8c
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue