Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AES128-GCM96 support to transit #7555

Merged
merged 2 commits into from
Oct 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions builtin/logical/transit/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
2 changes: 2 additions & 0 deletions builtin/logical/transit/path_backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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")
Expand Down
30 changes: 26 additions & 4 deletions builtin/logical/transit/path_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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"
Expand Down
5 changes: 3 additions & 2 deletions builtin/logical/transit/path_encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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":
Expand Down
2 changes: 1 addition & 1 deletion builtin/logical/transit/path_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions builtin/logical/transit/path_export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
6 changes: 4 additions & 2 deletions builtin/logical/transit/path_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -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".
`,
Expand Down Expand Up @@ -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":
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion sdk/helper/keysutil/lock_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
59 changes: 38 additions & 21 deletions sdk/helper/keysutil/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const (
KeyType_ChaCha20_Poly1305
KeyType_ECDSA_P384
KeyType_ECDSA_P521
KeyType_AES128_GCM96
)

const (
Expand Down Expand Up @@ -91,15 +92,15 @@ 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
}

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
Expand All @@ -123,14 +124,16 @@ 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
}

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:
Expand Down Expand Up @@ -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)}
Expand Down Expand Up @@ -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
}
if p.Type == KeyType_AES128_GCM96 {
encBytes = 16
}
key, err := p.DeriveKey(context, ver, numBytes)

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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
Expand Down