Add AES128-GCM96 support to transit (#7555)
This commit is contained in:
parent
f714060c47
commit
4252f5c9e4
|
@ -968,8 +968,10 @@ func testDerivedKeyUpgrade(t *testing.T, keyType keysutil.KeyType) {
|
|||
|
||||
func TestConvergentEncryption(t *testing.T) {
|
||||
testConvergentEncryptionCommon(t, 0, keysutil.KeyType_AES256_GCM96)
|
||||
testConvergentEncryptionCommon(t, 2, keysutil.KeyType_AES128_GCM96)
|
||||
testConvergentEncryptionCommon(t, 2, keysutil.KeyType_AES256_GCM96)
|
||||
testConvergentEncryptionCommon(t, 2, keysutil.KeyType_ChaCha20_Poly1305)
|
||||
testConvergentEncryptionCommon(t, 3, keysutil.KeyType_AES128_GCM96)
|
||||
testConvergentEncryptionCommon(t, 3, keysutil.KeyType_AES256_GCM96)
|
||||
testConvergentEncryptionCommon(t, 3, keysutil.KeyType_ChaCha20_Poly1305)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
func TestTransit_BackupRestore(t *testing.T) {
|
||||
// Test encryption/decryption after a restore for supported keys
|
||||
testBackupRestore(t, "aes128-gcm96", "encrypt-decrypt")
|
||||
testBackupRestore(t, "aes256-gcm96", "encrypt-decrypt")
|
||||
testBackupRestore(t, "chacha20-poly1305", "encrypt-decrypt")
|
||||
testBackupRestore(t, "rsa-2048", "encrypt-decrypt")
|
||||
|
@ -23,6 +24,7 @@ func TestTransit_BackupRestore(t *testing.T) {
|
|||
testBackupRestore(t, "rsa-4096", "sign-verify")
|
||||
|
||||
// Test HMAC/verification after a restore for all key types
|
||||
testBackupRestore(t, "aes128-gcm96", "hmac-verify")
|
||||
testBackupRestore(t, "aes256-gcm96", "hmac-verify")
|
||||
testBackupRestore(t, "chacha20-poly1305", "hmac-verify")
|
||||
testBackupRestore(t, "ecdsa-p256", "hmac-verify")
|
||||
|
|
|
@ -32,13 +32,17 @@ func TestTransit_ConfigSettings(t *testing.T) {
|
|||
req := &logical.Request{
|
||||
Storage: storage,
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "keys/aes",
|
||||
Path: "keys/aes256",
|
||||
Data: map[string]interface{}{
|
||||
"derived": true,
|
||||
},
|
||||
}
|
||||
doReq(req)
|
||||
|
||||
req.Path = "keys/aes128"
|
||||
req.Data["type"] = "aes128-gcm96"
|
||||
doReq(req)
|
||||
|
||||
req.Path = "keys/ed"
|
||||
req.Data["type"] = "ed25519"
|
||||
doReq(req)
|
||||
|
@ -59,7 +63,13 @@ func TestTransit_ConfigSettings(t *testing.T) {
|
|||
|
||||
delete(req.Data, "type")
|
||||
|
||||
req.Path = "keys/aes/rotate"
|
||||
req.Path = "keys/aes128/rotate"
|
||||
doReq(req)
|
||||
doReq(req)
|
||||
doReq(req)
|
||||
doReq(req)
|
||||
|
||||
req.Path = "keys/aes256/rotate"
|
||||
doReq(req)
|
||||
doReq(req)
|
||||
doReq(req)
|
||||
|
@ -89,7 +99,7 @@ func TestTransit_ConfigSettings(t *testing.T) {
|
|||
doReq(req)
|
||||
doReq(req)
|
||||
|
||||
req.Path = "keys/aes/config"
|
||||
req.Path = "keys/aes256/config"
|
||||
// Too high
|
||||
req.Data["min_decryption_version"] = 7
|
||||
doErrReq(req)
|
||||
|
@ -114,6 +124,8 @@ func TestTransit_ConfigSettings(t *testing.T) {
|
|||
req.Data["min_decryption_version"] = 2
|
||||
req.Data["min_encryption_version"] = 3
|
||||
doReq(req)
|
||||
req.Path = "keys/aes128/config"
|
||||
doReq(req)
|
||||
req.Path = "keys/ed/config"
|
||||
doReq(req)
|
||||
req.Path = "keys/p256/config"
|
||||
|
@ -131,7 +143,7 @@ func TestTransit_ConfigSettings(t *testing.T) {
|
|||
}
|
||||
|
||||
maxKeyVersion := 5
|
||||
key := "aes"
|
||||
key := "aes256"
|
||||
|
||||
testHMAC := func(ver int, valid bool) {
|
||||
req.Path = "hmac/" + key
|
||||
|
@ -193,6 +205,16 @@ func TestTransit_ConfigSettings(t *testing.T) {
|
|||
testHMAC(3, true)
|
||||
testHMAC(2, false)
|
||||
|
||||
key = "aes128"
|
||||
testEncryptDecrypt(5, true)
|
||||
testEncryptDecrypt(4, true)
|
||||
testEncryptDecrypt(3, true)
|
||||
testEncryptDecrypt(2, false)
|
||||
testHMAC(5, true)
|
||||
testHMAC(4, true)
|
||||
testHMAC(3, true)
|
||||
testHMAC(2, false)
|
||||
|
||||
delete(req.Data, "plaintext")
|
||||
req.Data["input"] = "abcd"
|
||||
key = "ed"
|
||||
|
|
|
@ -88,8 +88,7 @@ encryption key) this nonce value is **never reused**.
|
|||
Description: `
|
||||
This parameter is required when encryption key is expected to be created.
|
||||
When performing an upsert operation, the type of key to create. Currently,
|
||||
"aes256-gcm96" (symmetric) is the only type supported. Defaults to
|
||||
"aes256-gcm96".`,
|
||||
"aes128-gcm96" (symmetric) and "aes256-gcm96" (symmetric) are the only types supported. Defaults to "aes256-gcm96".`,
|
||||
},
|
||||
|
||||
"convergent_encryption": &framework.FieldSchema{
|
||||
|
@ -228,6 +227,8 @@ func (b *backend) pathEncryptWrite(ctx context.Context, req *logical.Request, d
|
|||
|
||||
keyType := d.Get("type").(string)
|
||||
switch keyType {
|
||||
case "aes128-gcm96":
|
||||
polReq.KeyType = keysutil.KeyType_AES128_GCM96
|
||||
case "aes256-gcm96":
|
||||
polReq.KeyType = keysutil.KeyType_AES256_GCM96
|
||||
case "chacha20-poly1305":
|
||||
|
|
|
@ -155,7 +155,7 @@ func getExportKey(policy *keysutil.Policy, key *keysutil.KeyEntry, exportType st
|
|||
|
||||
case exportTypeEncryptionKey:
|
||||
switch policy.Type {
|
||||
case keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305:
|
||||
case keysutil.KeyType_AES128_GCM96, keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305:
|
||||
return strings.TrimSpace(base64.StdEncoding.EncodeToString(key.Key)), nil
|
||||
|
||||
case keysutil.KeyType_RSA2048, keysutil.KeyType_RSA4096:
|
||||
|
|
|
@ -11,12 +11,14 @@ import (
|
|||
)
|
||||
|
||||
func TestTransit_Export_KeyVersion_ExportsCorrectVersion(t *testing.T) {
|
||||
verifyExportsCorrectVersion(t, "encryption-key", "aes128-gcm96")
|
||||
verifyExportsCorrectVersion(t, "encryption-key", "aes256-gcm96")
|
||||
verifyExportsCorrectVersion(t, "encryption-key", "chacha20-poly1305")
|
||||
verifyExportsCorrectVersion(t, "signing-key", "ecdsa-p256")
|
||||
verifyExportsCorrectVersion(t, "signing-key", "ecdsa-p384")
|
||||
verifyExportsCorrectVersion(t, "signing-key", "ecdsa-p521")
|
||||
verifyExportsCorrectVersion(t, "signing-key", "ed25519")
|
||||
verifyExportsCorrectVersion(t, "hmac-key", "aes128-gcm96")
|
||||
verifyExportsCorrectVersion(t, "hmac-key", "aes256-gcm96")
|
||||
verifyExportsCorrectVersion(t, "hmac-key", "chacha20-poly1305")
|
||||
verifyExportsCorrectVersion(t, "hmac-key", "ecdsa-p256")
|
||||
|
|
|
@ -45,7 +45,7 @@ func (b *backend) pathKeys() *framework.Path {
|
|||
Type: framework.TypeString,
|
||||
Default: "aes256-gcm96",
|
||||
Description: `
|
||||
The type of key to create. Currently, "aes256-gcm96" (symmetric), "ecdsa-p256"
|
||||
The type of key to create. Currently, "aes128-gcm96" (symmetric), "aes256-gcm96" (symmetric), "ecdsa-p256"
|
||||
(asymmetric), "ecdsa-p384" (asymmetric), "ecdsa-p521" (asymmetric), "ed25519" (asymmetric), "rsa-2048" (asymmetric), "rsa-4096"
|
||||
(asymmetric) are supported. Defaults to "aes256-gcm96".
|
||||
`,
|
||||
|
@ -139,6 +139,8 @@ func (b *backend) pathPolicyWrite(ctx context.Context, req *logical.Request, d *
|
|||
AllowPlaintextBackup: allowPlaintextBackup,
|
||||
}
|
||||
switch keyType {
|
||||
case "aes128-gcm96":
|
||||
polReq.KeyType = keysutil.KeyType_AES128_GCM96
|
||||
case "aes256-gcm96":
|
||||
polReq.KeyType = keysutil.KeyType_AES256_GCM96
|
||||
case "chacha20-poly1305":
|
||||
|
@ -260,7 +262,7 @@ func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *f
|
|||
}
|
||||
|
||||
switch p.Type {
|
||||
case keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305:
|
||||
case keysutil.KeyType_AES128_GCM96, keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305:
|
||||
retKeys := map[string]int64{}
|
||||
for k, v := range p.Keys {
|
||||
retKeys[k] = v.DeprecatedCreationTime
|
||||
|
|
|
@ -327,7 +327,7 @@ func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest) (retP *
|
|||
// because we don't know if the parameters match.
|
||||
|
||||
switch req.KeyType {
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
if req.Convergent && !req.Derived {
|
||||
cleanup()
|
||||
return nil, false, fmt.Errorf("convergent encryption requires derivation to be enabled")
|
||||
|
|
|
@ -57,6 +57,7 @@ const (
|
|||
KeyType_ChaCha20_Poly1305
|
||||
KeyType_ECDSA_P384
|
||||
KeyType_ECDSA_P521
|
||||
KeyType_AES128_GCM96
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -91,7 +92,7 @@ type KeyType int
|
|||
|
||||
func (kt KeyType) EncryptionSupported() bool {
|
||||
switch kt {
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA4096:
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA4096:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -99,7 +100,7 @@ func (kt KeyType) EncryptionSupported() bool {
|
|||
|
||||
func (kt KeyType) DecryptionSupported() bool {
|
||||
switch kt {
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA4096:
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA4096:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -123,7 +124,7 @@ func (kt KeyType) HashSignatureInput() bool {
|
|||
|
||||
func (kt KeyType) DerivationSupported() bool {
|
||||
switch kt {
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_ED25519:
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_ED25519:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -131,6 +132,8 @@ func (kt KeyType) DerivationSupported() bool {
|
|||
|
||||
func (kt KeyType) String() string {
|
||||
switch kt {
|
||||
case KeyType_AES128_GCM96:
|
||||
return "aes128-gcm96"
|
||||
case KeyType_AES256_GCM96:
|
||||
return "aes256-gcm96"
|
||||
case KeyType_ChaCha20_Poly1305:
|
||||
|
@ -729,7 +732,7 @@ func (p *Policy) DeriveKey(context []byte, ver, numBytes int) ([]byte, error) {
|
|||
}
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
n, err := derBytes.ReadFrom(limReader)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("error reading returned derived bytes: %v", err)}
|
||||
|
@ -800,40 +803,45 @@ func (p *Policy) Encrypt(ver int, context, nonce []byte, value string) (string,
|
|||
var ciphertext []byte
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
hmacKey := context
|
||||
|
||||
var aead cipher.AEAD
|
||||
var encKey []byte
|
||||
var deriveHMAC bool
|
||||
|
||||
numBytes := 32
|
||||
encBytes := 32
|
||||
hmacBytes := 0
|
||||
if p.convergentVersion(ver) > 2 {
|
||||
deriveHMAC = true
|
||||
numBytes = 64
|
||||
hmacBytes = 32
|
||||
}
|
||||
key, err := p.DeriveKey(context, ver, numBytes)
|
||||
if p.Type == KeyType_AES128_GCM96 {
|
||||
encBytes = 16
|
||||
}
|
||||
|
||||
key, err := p.DeriveKey(context, ver, encBytes+hmacBytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(key) < numBytes {
|
||||
if len(key) < encBytes+hmacBytes {
|
||||
return "", errutil.InternalError{Err: "could not derive key, length too small"}
|
||||
}
|
||||
|
||||
encKey = key[:32]
|
||||
if len(encKey) != 32 {
|
||||
encKey = key[:encBytes]
|
||||
if len(encKey) != encBytes {
|
||||
return "", errutil.InternalError{Err: "could not derive enc key, length not correct"}
|
||||
}
|
||||
if deriveHMAC {
|
||||
hmacKey = key[32:]
|
||||
if len(hmacKey) != 32 {
|
||||
hmacKey = key[encBytes:]
|
||||
if len(hmacKey) != hmacBytes {
|
||||
return "", errutil.InternalError{Err: "could not derive hmac key, length not correct"}
|
||||
}
|
||||
}
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96:
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96:
|
||||
// Setup the cipher
|
||||
aesCipher, err := aes.NewCipher(encKey)
|
||||
if err != nil {
|
||||
|
@ -964,20 +972,25 @@ func (p *Policy) Decrypt(context, nonce []byte, value string) (string, error) {
|
|||
var plain []byte
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
var aead cipher.AEAD
|
||||
|
||||
encKey, err := p.DeriveKey(context, ver, 32)
|
||||
numBytes := 32
|
||||
if p.Type == KeyType_AES128_GCM96 {
|
||||
numBytes = 16
|
||||
}
|
||||
|
||||
encKey, err := p.DeriveKey(context, ver, numBytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(encKey) != 32 {
|
||||
if len(encKey) != numBytes {
|
||||
return "", errutil.InternalError{Err: "could not derive enc key, length not correct"}
|
||||
}
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96:
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96:
|
||||
// Setup the cipher
|
||||
aesCipher, err := aes.NewCipher(encKey)
|
||||
if err != nil {
|
||||
|
@ -1399,9 +1412,13 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
|
|||
entry.HMACKey = hmacKey
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
// Generate a 256bit key
|
||||
newKey, err := uuid.GenerateRandomBytes(32)
|
||||
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
// Default to 256 bit key
|
||||
numBytes := 32
|
||||
if p.Type == KeyType_AES128_GCM96 {
|
||||
numBytes = 16
|
||||
}
|
||||
newKey, err := uuid.GenerateRandomBytes(numBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue