Add AES128-GCM96 support to transit (#7555)

This commit is contained in:
Jeff Mitchell 2019-10-03 16:11:43 -04:00 committed by GitHub
parent f714060c47
commit 4252f5c9e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 79 additions and 31 deletions

View File

@ -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)
}

View File

@ -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")

View File

@ -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"

View File

@ -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":

View File

@ -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:

View File

@ -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")

View File

@ -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

View File

@ -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")

View File

@ -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
}