diff --git a/builtin/logical/transit/backend_test.go b/builtin/logical/transit/backend_test.go index db103782e..c749d592e 100644 --- a/builtin/logical/transit/backend_test.go +++ b/builtin/logical/transit/backend_test.go @@ -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) } diff --git a/builtin/logical/transit/path_backup_test.go b/builtin/logical/transit/path_backup_test.go index ce0fb9eea..8a6e34465 100644 --- a/builtin/logical/transit/path_backup_test.go +++ b/builtin/logical/transit/path_backup_test.go @@ -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") diff --git a/builtin/logical/transit/path_config_test.go b/builtin/logical/transit/path_config_test.go index 8b644c9ae..c0f0eba0e 100644 --- a/builtin/logical/transit/path_config_test.go +++ b/builtin/logical/transit/path_config_test.go @@ -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" diff --git a/builtin/logical/transit/path_encrypt.go b/builtin/logical/transit/path_encrypt.go index 914092853..9dca044cd 100644 --- a/builtin/logical/transit/path_encrypt.go +++ b/builtin/logical/transit/path_encrypt.go @@ -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": diff --git a/builtin/logical/transit/path_export.go b/builtin/logical/transit/path_export.go index a4c3e6163..9384827d4 100644 --- a/builtin/logical/transit/path_export.go +++ b/builtin/logical/transit/path_export.go @@ -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: diff --git a/builtin/logical/transit/path_export_test.go b/builtin/logical/transit/path_export_test.go index 40c8d0118..d811556a6 100644 --- a/builtin/logical/transit/path_export_test.go +++ b/builtin/logical/transit/path_export_test.go @@ -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") diff --git a/builtin/logical/transit/path_keys.go b/builtin/logical/transit/path_keys.go index 3859d50e4..b1b05fe96 100644 --- a/builtin/logical/transit/path_keys.go +++ b/builtin/logical/transit/path_keys.go @@ -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 diff --git a/sdk/helper/keysutil/lock_manager.go b/sdk/helper/keysutil/lock_manager.go index aee0338af..ce46c69f9 100644 --- a/sdk/helper/keysutil/lock_manager.go +++ b/sdk/helper/keysutil/lock_manager.go @@ -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") diff --git a/sdk/helper/keysutil/policy.go b/sdk/helper/keysutil/policy.go index ef6b2df6a..17c4d074d 100644 --- a/sdk/helper/keysutil/policy.go +++ b/sdk/helper/keysutil/policy.go @@ -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 }