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 P384 and P521 support to Transit #7551

Merged
merged 1 commit 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions builtin/logical/transit/path_backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func TestTransit_BackupRestore(t *testing.T) {

// Test signing/verification after a restore for supported keys
testBackupRestore(t, "ecdsa-p256", "sign-verify")
testBackupRestore(t, "ecdsa-p384", "sign-verify")
testBackupRestore(t, "ecdsa-p521", "sign-verify")
testBackupRestore(t, "ed25519", "sign-verify")
testBackupRestore(t, "rsa-2048", "sign-verify")
testBackupRestore(t, "rsa-4096", "sign-verify")
Expand All @@ -24,6 +26,8 @@ func TestTransit_BackupRestore(t *testing.T) {
testBackupRestore(t, "aes256-gcm96", "hmac-verify")
testBackupRestore(t, "chacha20-poly1305", "hmac-verify")
testBackupRestore(t, "ecdsa-p256", "hmac-verify")
testBackupRestore(t, "ecdsa-p384", "hmac-verify")
testBackupRestore(t, "ecdsa-p521", "hmac-verify")
testBackupRestore(t, "ed25519", "hmac-verify")
testBackupRestore(t, "rsa-2048", "hmac-verify")
testBackupRestore(t, "rsa-4096", "hmac-verify")
Expand Down
45 changes: 45 additions & 0 deletions builtin/logical/transit/path_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ func TestTransit_ConfigSettings(t *testing.T) {
req.Data["type"] = "ecdsa-p256"
doReq(req)

req.Path = "keys/p384"
req.Data["type"] = "ecdsa-p384"
doReq(req)

req.Path = "keys/p521"
req.Data["type"] = "ecdsa-p521"
doReq(req)

delete(req.Data, "type")

req.Path = "keys/aes/rotate"
Expand All @@ -69,6 +77,18 @@ func TestTransit_ConfigSettings(t *testing.T) {
doReq(req)
doReq(req)

req.Path = "keys/p384/rotate"
doReq(req)
doReq(req)
doReq(req)
doReq(req)

req.Path = "keys/p521/rotate"
doReq(req)
doReq(req)
doReq(req)
doReq(req)

req.Path = "keys/aes/config"
// Too high
req.Data["min_decryption_version"] = 7
Expand Down Expand Up @@ -98,6 +118,11 @@ func TestTransit_ConfigSettings(t *testing.T) {
doReq(req)
req.Path = "keys/p256/config"
doReq(req)
req.Path = "keys/p384/config"
doReq(req)

req.Path = "keys/p521/config"
doReq(req)

req.Data = map[string]interface{}{
"plaintext": "abcd",
Expand Down Expand Up @@ -215,4 +240,24 @@ func TestTransit_ConfigSettings(t *testing.T) {
testHMAC(4, true)
testHMAC(3, true)
testHMAC(2, false)

key = "p384"
testSignVerify(5, true)
testSignVerify(4, true)
testSignVerify(3, true)
testSignVerify(2, false)
testHMAC(5, true)
testHMAC(4, true)
testHMAC(3, true)
testHMAC(2, false)

key = "p521"
testSignVerify(5, true)
testSignVerify(4, true)
testSignVerify(3, true)
testSignVerify(2, false)
testHMAC(5, true)
testHMAC(4, true)
testHMAC(3, true)
testHMAC(2, false)
}
2 changes: 1 addition & 1 deletion builtin/logical/transit/path_encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ func (b *backend) pathEncryptWrite(ctx context.Context, req *logical.Request, d
polReq.KeyType = keysutil.KeyType_AES256_GCM96
case "chacha20-poly1305":
polReq.KeyType = keysutil.KeyType_ChaCha20_Poly1305
case "ecdsa-p256":
case "ecdsa-p256", "ecdsa-p384", "ecdsa-p521":
return logical.ErrorResponse(fmt.Sprintf("key type %v not supported for this operation", keyType)), logical.ErrInvalidRequest
default:
return logical.ErrorResponse(fmt.Sprintf("unknown key type %v", keyType)), logical.ErrInvalidRequest
Expand Down
13 changes: 11 additions & 2 deletions builtin/logical/transit/path_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,17 @@ func getExportKey(policy *keysutil.Policy, key *keysutil.KeyEntry, exportType st

case exportTypeSigningKey:
switch policy.Type {
case keysutil.KeyType_ECDSA_P256:
ecKey, err := keyEntryToECPrivateKey(key, elliptic.P256())
case keysutil.KeyType_ECDSA_P256, keysutil.KeyType_ECDSA_P384, keysutil.KeyType_ECDSA_P521:
var curve elliptic.Curve
switch policy.Type {
case keysutil.KeyType_ECDSA_P384:
curve = elliptic.P384()
case keysutil.KeyType_ECDSA_P521:
curve = elliptic.P521()
default:
curve = elliptic.P256()
}
ecKey, err := keyEntryToECPrivateKey(key, curve)
if err != nil {
return "", err
}
Expand Down
6 changes: 6 additions & 0 deletions builtin/logical/transit/path_export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ func TestTransit_Export_KeyVersion_ExportsCorrectVersion(t *testing.T) {
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", "aes256-gcm96")
verifyExportsCorrectVersion(t, "hmac-key", "chacha20-poly1305")
verifyExportsCorrectVersion(t, "hmac-key", "ecdsa-p256")
verifyExportsCorrectVersion(t, "hmac-key", "ecdsa-p384")
verifyExportsCorrectVersion(t, "hmac-key", "ecdsa-p521")
verifyExportsCorrectVersion(t, "hmac-key", "ed25519")
}

Expand Down Expand Up @@ -271,6 +275,8 @@ func TestTransit_Export_SigningDoesNotSupportSigning_ReturnsError(t *testing.T)

func TestTransit_Export_EncryptionDoesNotSupportEncryption_ReturnsError(t *testing.T) {
testTransit_Export_EncryptionDoesNotSupportEncryption_ReturnsError(t, "ecdsa-p256")
testTransit_Export_EncryptionDoesNotSupportEncryption_ReturnsError(t, "ecdsa-p384")
testTransit_Export_EncryptionDoesNotSupportEncryption_ReturnsError(t, "ecdsa-p521")
testTransit_Export_EncryptionDoesNotSupportEncryption_ReturnsError(t, "ed25519")
}

Expand Down
12 changes: 10 additions & 2 deletions builtin/logical/transit/path_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (b *backend) pathKeys() *framework.Path {
Default: "aes256-gcm96",
Description: `
The type of key to create. Currently, "aes256-gcm96" (symmetric), "ecdsa-p256"
(asymmetric), 'ed25519' (asymmetric), 'rsa-2048' (asymmetric), 'rsa-4096'
(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 @@ -145,6 +145,10 @@ func (b *backend) pathPolicyWrite(ctx context.Context, req *logical.Request, d *
polReq.KeyType = keysutil.KeyType_ChaCha20_Poly1305
case "ecdsa-p256":
polReq.KeyType = keysutil.KeyType_ECDSA_P256
case "ecdsa-p384":
polReq.KeyType = keysutil.KeyType_ECDSA_P384
case "ecdsa-p521":
polReq.KeyType = keysutil.KeyType_ECDSA_P521
case "ed25519":
polReq.KeyType = keysutil.KeyType_ED25519
case "rsa-2048":
Expand Down Expand Up @@ -263,7 +267,7 @@ func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *f
}
resp.Data["keys"] = retKeys

case keysutil.KeyType_ECDSA_P256, keysutil.KeyType_ED25519, keysutil.KeyType_RSA2048, keysutil.KeyType_RSA4096:
case keysutil.KeyType_ECDSA_P256, keysutil.KeyType_ECDSA_P384, keysutil.KeyType_ECDSA_P521, keysutil.KeyType_ED25519, keysutil.KeyType_RSA2048, keysutil.KeyType_RSA4096:
retKeys := map[string]map[string]interface{}{}
for k, v := range p.Keys {
key := asymKey{
Expand All @@ -277,6 +281,10 @@ func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *f
switch p.Type {
case keysutil.KeyType_ECDSA_P256:
key.Name = elliptic.P256().Params().Name
case keysutil.KeyType_ECDSA_P384:
key.Name = elliptic.P384().Params().Name
case keysutil.KeyType_ECDSA_P521:
key.Name = elliptic.P521().Params().Name
case keysutil.KeyType_ED25519:
if p.Derived {
if len(context) == 0 {
Expand Down
12 changes: 12 additions & 0 deletions builtin/logical/transit/path_keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ func TestTransit_Issue_2958(t *testing.T) {
t.Fatal(err)
}

_, err = client.Logical().Write("transit/keys/foobar", map[string]interface{}{
"type": "ecdsa-p384",
})
if err != nil {
t.Fatal(err)
}

_, err = client.Logical().Write("transit/keys/bar", map[string]interface{}{
"type": "ed25519",
})
Expand All @@ -70,6 +77,11 @@ func TestTransit_Issue_2958(t *testing.T) {
t.Fatal(err)
}

_, err = client.Logical().Read("transit/keys/foobar")
if err != nil {
t.Fatal(err)
}

_, err = client.Logical().Read("transit/keys/bar")
if err != nil {
t.Fatal(err)
Expand Down
88 changes: 75 additions & 13 deletions builtin/logical/transit/path_sign_verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package transit
import (
"context"
"encoding/base64"
"fmt"
"strconv"
"strings"
"testing"
Expand All @@ -24,7 +25,19 @@ type signOutcome struct {
keyValid bool
}

func TestTransit_SignVerify_P256(t *testing.T) {
func TestTransit_SignVerify_ECDSA(t *testing.T) {
t.Run("256", func(t *testing.T) {
testTransit_SignVerify_ECDSA(t, 256)
})
t.Run("384", func(t *testing.T) {
testTransit_SignVerify_ECDSA(t, 384)
})
t.Run("521", func(t *testing.T) {
testTransit_SignVerify_ECDSA(t, 521)
})
}

func testTransit_SignVerify_ECDSA(t *testing.T, bits int) {
b, storage := createBackendWithSysView(t)

// First create a key
Expand All @@ -33,7 +46,7 @@ func TestTransit_SignVerify_P256(t *testing.T) {
Operation: logical.UpdateOperation,
Path: "keys/foo",
Data: map[string]interface{}{
"type": "ecdsa-p256",
"type": fmt.Sprintf("ecdsa-p%d", bits),
},
}
_, err := b.HandleRequest(context.Background(), req)
Expand All @@ -52,35 +65,77 @@ func TestTransit_SignVerify_P256(t *testing.T) {

// Useful code to output a key for openssl verification
/*
{
key := p.Keys[p.LatestVersion]
if bits == 384 {
var curve elliptic.Curve
switch bits {
case 521:
curve = elliptic.P521()
case 384:
curve = elliptic.P384()
default:
curve = elliptic.P256()
}
key := p.Keys[strconv.Itoa(p.LatestVersion)]
keyBytes, _ := x509.MarshalECPrivateKey(&ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: elliptic.P256(),
X: key.X,
Y: key.Y,
Curve: curve,
X: key.EC_X,
Y: key.EC_Y,
},
D: key.D,
D: key.EC_D,
})
pemBlock := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: keyBytes,
}
pemBytes := pem.EncodeToMemory(pemBlock)
t.Fatalf("X: %s, Y: %s, D: %s, marshaled: %s", key.X.Text(16), key.Y.Text(16), key.D.Text(16), string(pemBytes))
t.Fatalf("X: %s, Y: %s, D: %s, marshaled: %s", key.EC_X.Text(16), key.EC_Y.Text(16), key.EC_D.Text(16), string(pemBytes))
}
*/

var xString, yString, dString string
switch bits {
case 384:
xString = "703457a84e48bfcb037cfb509f1870d2aa5b74c109c2f24624ab21444492575229f8711453e5c656dab596b4e26db30e"
yString = "411c5b7092a893dc8b7af39de3d21d1c26f45b27616baeac4c479ef3c9f21c194b5ac501dee47ba2b2cb243a54256524"
dString = "3de3e4fd2ecbc490e956f41f5003a1e57a84763cec7b722fa3427cf461a1148ea4d5206023bcce0422289f6633730759"
/*
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDA94+T9LsvEkOlW9B9QA6HleoR2POx7ci+jQnz0YaEUjqTVIGAjvM4E
IiifZjNzB1mgBwYFK4EEACKhZANiAARwNFeoTki/ywN8+1CfGHDSqlt0wQnC8kYk
qyFERJJXUin4cRRT5cZW2rWWtOJtsw5BHFtwkqiT3It6853j0h0cJvRbJ2FrrqxM
R57zyfIcGUtaxQHe5HuissskOlQlZSQ=
-----END EC PRIVATE KEY-----
*/
case 521:
xString = "1913f75fc044fe5d1f871c2629a377462fd819b174a41d3ec7d04ebd5ae35475ff8de544f4e19a9aa6b16a8f67af479be6884e00ca3147dc24d5924d66ac395e04b"
yString = "4919406b90d8323fdb5c9c4f48259c56ebcea37b40ad1a82bbbfad62a9b9c2dce515772274b84725471c7d0b7c62e10c23296b1a9d2b2586ada67735ff5d9fffc4"
dString = "1867d0fcd9bac4c5821b70a6b13117499438f8c274579c0aba254fbd85fa98892c3608576197d5534366a9aab0f904155bec46d800d23a57f7f053d91526568b09"
/*
-----BEGIN EC PRIVATE KEY-----
MIHcAgEBBEIAGGfQ/Nm6xMWCG3CmsTEXSZQ4+MJ0V5wKuiVPvYX6mIksNghXYZfV
U0Nmqaqw+QQVW+xG2ADSOlf38FPZFSZWiwmgBwYFK4EEACOhgYkDgYYABAGRP3X8
BE/l0fhxwmKaN3Ri/YGbF0pB0+x9BOvVrjVHX/jeVE9OGamqaxao9nr0eb5ohOAM
oxR9wk1ZJNZqw5XgSwBJGUBrkNgyP9tcnE9IJZxW686je0CtGoK7v61iqbnC3OUV
dyJ0uEclRxx9C3xi4QwjKWsanSslhq2mdzX/XZ//xA==
-----END EC PRIVATE KEY-----
*/
default:
xString = "7336010a6da5935113d26d9ea4bb61b3b8d102c9a8083ed432f9b58fd7e80686"
yString = "4040aa31864691a8a9e7e3ec9250e85425b797ad7be34ba8df62bfbad45ebb0e"
dString = "99e5569be8683a2691dfc560ca9dfa71e887867a3af60635a08a3e3655aba3ef"
}

keyEntry := p.Keys[strconv.Itoa(p.LatestVersion)]
_, ok := keyEntry.EC_X.SetString("7336010a6da5935113d26d9ea4bb61b3b8d102c9a8083ed432f9b58fd7e80686", 16)
_, ok := keyEntry.EC_X.SetString(xString, 16)
if !ok {
t.Fatal("could not set X")
}
_, ok = keyEntry.EC_Y.SetString("4040aa31864691a8a9e7e3ec9250e85425b797ad7be34ba8df62bfbad45ebb0e", 16)
_, ok = keyEntry.EC_Y.SetString(yString, 16)
if !ok {
t.Fatal("could not set Y")
}
_, ok = keyEntry.EC_D.SetString("99e5569be8683a2691dfc560ca9dfa71e887867a3af60635a08a3e3655aba3ef", 16)
_, ok = keyEntry.EC_D.SetString(dString, 16)
if !ok {
t.Fatal("could not set D")
}
Expand Down Expand Up @@ -157,7 +212,14 @@ func TestTransit_SignVerify_P256(t *testing.T) {
verifyRequest(req, true, "", sig[0:len(sig)-2])

// Test a signature generated with the same key by openssl
sig = `vault:v1:MEUCIAgnEl9V8P305EBAlz68Nq4jZng5fE8k6MactcnlUw9dAiEAvJVePg3dazW6MaW7lRAVtEz82QJDVmR98tXCl8Pc7DA=`
switch bits {
case 384:
sig = `vault:v1:MGUCMHHZLRN/3ehWuWACfSCMLtFtNEAdx6Rkwon2Lx6FWCyXCXqH6A8Pz8er0Qkgvm2ElQIxAO922LmUeYzHmDSfC5is/TjFu3b4Fb+1XtoBXncc2u4t2vSuTAxEv7WMh2D2YDdxeA==`
case 521:
sig = `vault:v1:MIGIAkIBYhspOgSs/K/NUWtlBN+CfYe1IVFpUbQNSqdjT7s+QKcr6GKmdGLIQAXw0q6K0elBgzi1wgLjxwdscwMeW7tm/QQCQgDzdITGlUEd9Z7DOfLCnDP4X8pGsfO60Tvsh/BN44drZsHLtXYBXLczB/XZfIWAsPMuI5F7ExwVNbmQP0FBVri/QQ==`
default:
sig = `vault:v1:MEUCIAgnEl9V8P305EBAlz68Nq4jZng5fE8k6MactcnlUw9dAiEAvJVePg3dazW6MaW7lRAVtEz82QJDVmR98tXCl8Pc7DA=`
}
verifyRequest(req, false, "", sig)

// Test algorithm selection in the path
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 @@ -333,7 +333,7 @@ func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest) (retP *
return nil, false, fmt.Errorf("convergent encryption requires derivation to be enabled")
}

case KeyType_ECDSA_P256:
case KeyType_ECDSA_P256, KeyType_ECDSA_P384, KeyType_ECDSA_P521:
if req.Derived || req.Convergent {
cleanup()
return nil, false, fmt.Errorf("key derivation and convergent encryption not supported for keys of type %v", req.KeyType)
Expand Down
Loading