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

RSA3072 implementation in transit secrets engine #8151

Merged
merged 4 commits into from
Feb 15, 2020
Merged
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
1 change: 1 addition & 0 deletions builtin/logical/transit/backend_test.go
Original file line number Diff line number Diff line change
@@ -109,6 +109,7 @@ func createBackendWithForceNoCacheWithSysViewWithStorage(t *testing.T, s logical

func TestTransit_RSA(t *testing.T) {
testTransit_RSA(t, "rsa-2048")
testTransit_RSA(t, "rsa-3072")
testTransit_RSA(t, "rsa-4096")
}

3 changes: 3 additions & 0 deletions builtin/logical/transit/path_backup_test.go
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ func TestTransit_BackupRestore(t *testing.T) {
testBackupRestore(t, "aes256-gcm96", "encrypt-decrypt")
testBackupRestore(t, "chacha20-poly1305", "encrypt-decrypt")
testBackupRestore(t, "rsa-2048", "encrypt-decrypt")
testBackupRestore(t, "rsa-3072", "encrypt-decrypt")
testBackupRestore(t, "rsa-4096", "encrypt-decrypt")

// Test signing/verification after a restore for supported keys
@@ -21,6 +22,7 @@ func TestTransit_BackupRestore(t *testing.T) {
testBackupRestore(t, "ecdsa-p521", "sign-verify")
testBackupRestore(t, "ed25519", "sign-verify")
testBackupRestore(t, "rsa-2048", "sign-verify")
testBackupRestore(t, "rsa-3072", "sign-verify")
testBackupRestore(t, "rsa-4096", "sign-verify")

// Test HMAC/verification after a restore for all key types
@@ -32,6 +34,7 @@ func TestTransit_BackupRestore(t *testing.T) {
testBackupRestore(t, "ecdsa-p521", "hmac-verify")
testBackupRestore(t, "ed25519", "hmac-verify")
testBackupRestore(t, "rsa-2048", "hmac-verify")
testBackupRestore(t, "rsa-3072", "hmac-verify")
testBackupRestore(t, "rsa-4096", "hmac-verify")
}

4 changes: 2 additions & 2 deletions builtin/logical/transit/path_export.go
Original file line number Diff line number Diff line change
@@ -158,7 +158,7 @@ func getExportKey(policy *keysutil.Policy, key *keysutil.KeyEntry, exportType st
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:
case keysutil.KeyType_RSA2048, keysutil.KeyType_RSA3072, keysutil.KeyType_RSA4096:
return encodeRSAPrivateKey(key.RSAKey), nil
}

@@ -183,7 +183,7 @@ func getExportKey(policy *keysutil.Policy, key *keysutil.KeyEntry, exportType st
case keysutil.KeyType_ED25519:
return strings.TrimSpace(base64.StdEncoding.EncodeToString(key.Key)), nil

case keysutil.KeyType_RSA2048, keysutil.KeyType_RSA4096:
case keysutil.KeyType_RSA2048, keysutil.KeyType_RSA3072, keysutil.KeyType_RSA4096:
return encodeRSAPrivateKey(key.RSAKey), nil
}
}
14 changes: 10 additions & 4 deletions builtin/logical/transit/path_keys.go
Original file line number Diff line number Diff line change
@@ -46,8 +46,8 @@ func (b *backend) pathKeys() *framework.Path {
Default: "aes256-gcm96",
Description: `
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".
(asymmetric), "ecdsa-p384" (asymmetric), "ecdsa-p521" (asymmetric), "ed25519" (asymmetric), "rsa-2048" (asymmetric), "rsa-3072"
(asymmetric), "rsa-4096" (asymmetric) are supported. Defaults to "aes256-gcm96".
`,
},

@@ -155,6 +155,8 @@ func (b *backend) pathPolicyWrite(ctx context.Context, req *logical.Request, d *
polReq.KeyType = keysutil.KeyType_ED25519
case "rsa-2048":
polReq.KeyType = keysutil.KeyType_RSA2048
case "rsa-3072":
polReq.KeyType = keysutil.KeyType_RSA3072
case "rsa-4096":
polReq.KeyType = keysutil.KeyType_RSA4096
default:
@@ -269,7 +271,7 @@ func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *f
}
resp.Data["keys"] = retKeys

case keysutil.KeyType_ECDSA_P256, keysutil.KeyType_ECDSA_P384, keysutil.KeyType_ECDSA_P521, 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_RSA3072, keysutil.KeyType_RSA4096:
retKeys := map[string]map[string]interface{}{}
for k, v := range p.Keys {
key := asymKey{
@@ -305,8 +307,12 @@ func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *f
}
}
key.Name = "ed25519"
case keysutil.KeyType_RSA2048, keysutil.KeyType_RSA4096:
case keysutil.KeyType_RSA2048, keysutil.KeyType_RSA3072, keysutil.KeyType_RSA4096:
key.Name = "rsa-2048"
if p.Type == keysutil.KeyType_RSA3072 {
key.Name = "rsa-3072"
}

if p.Type == keysutil.KeyType_RSA4096 {
key.Name = "rsa-4096"
}
4 changes: 2 additions & 2 deletions builtin/logical/transit/path_sign_verify.go
Original file line number Diff line number Diff line change
@@ -111,7 +111,7 @@ to the min_encryption_version configured on the key.`,

"prehashed": {
Type: framework.TypeBool,
Description: `Set to 'true' when the input is already hashed. If the key type is 'rsa-2048' or 'rsa-4096', then the algorithm used to hash the input should be indicated by the 'algorithm' parameter.`,
Description: `Set to 'true' when the input is already hashed. If the key type is 'rsa-2048', 'rsa-3072' or 'rsa-4096', then the algorithm used to hash the input should be indicated by the 'algorithm' parameter.`,
},

"signature_algorithm": {
@@ -193,7 +193,7 @@ Defaults to "sha2-256". Not valid for all key types.`,

"prehashed": {
Type: framework.TypeBool,
Description: `Set to 'true' when the input is already hashed. If the key type is 'rsa-2048' or 'rsa-4096', then the algorithm used to hash the input should be indicated by the 'algorithm' parameter.`,
Description: `Set to 'true' when the input is already hashed. If the key type is 'rsa-2048', 'rsa-3072' or 'rsa-4096', then the algorithm used to hash the input should be indicated by the 'algorithm' parameter.`,
},

"signature_algorithm": {
2 changes: 1 addition & 1 deletion sdk/helper/keysutil/lock_manager.go
Original file line number Diff line number Diff line change
@@ -346,7 +346,7 @@ func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest, rand io
return nil, false, fmt.Errorf("convergent encryption not supported for keys of type %v", req.KeyType)
}

case KeyType_RSA2048, KeyType_RSA4096:
case KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
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)
24 changes: 15 additions & 9 deletions sdk/helper/keysutil/policy.go
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ const (
KeyType_ECDSA_P384
KeyType_ECDSA_P521
KeyType_AES128_GCM96
KeyType_RSA3072
)

const (
@@ -92,31 +93,31 @@ type KeyType int

func (kt KeyType) EncryptionSupported() bool {
switch kt {
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA4096:
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
return true
}
return false
}

func (kt KeyType) DecryptionSupported() bool {
switch kt {
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA4096:
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
return true
}
return false
}

func (kt KeyType) SigningSupported() bool {
switch kt {
case KeyType_ECDSA_P256, KeyType_ECDSA_P384, KeyType_ECDSA_P521, KeyType_ED25519, KeyType_RSA2048, KeyType_RSA4096:
case KeyType_ECDSA_P256, KeyType_ECDSA_P384, KeyType_ECDSA_P521, KeyType_ED25519, KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
return true
}
return false
}

func (kt KeyType) HashSignatureInput() bool {
switch kt {
case KeyType_ECDSA_P256, KeyType_ECDSA_P384, KeyType_ECDSA_P521, KeyType_RSA2048, KeyType_RSA4096:
case KeyType_ECDSA_P256, KeyType_ECDSA_P384, KeyType_ECDSA_P521, KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
return true
}
return false
@@ -148,6 +149,8 @@ func (kt KeyType) String() string {
return "ed25519"
case KeyType_RSA2048:
return "rsa-2048"
case KeyType_RSA3072:
return "rsa-3072"
case KeyType_RSA4096:
return "rsa-4096"
}
@@ -899,7 +902,7 @@ func (p *Policy) Encrypt(ver int, context, nonce []byte, value string) (string,
ciphertext = append(nonce, ciphertext...)
}

case KeyType_RSA2048, KeyType_RSA4096:
case KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
key := p.Keys[strconv.Itoa(ver)].RSAKey
ciphertext, err = rsa.EncryptOAEP(sha256.New(), rand.Reader, &key.PublicKey, plaintext, nil)
if err != nil {
@@ -1033,7 +1036,7 @@ func (p *Policy) Decrypt(context, nonce []byte, value string) (string, error) {
return "", errutil.UserError{Err: "invalid ciphertext: unable to decrypt"}
}

case KeyType_RSA2048, KeyType_RSA4096:
case KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
key := p.Keys[strconv.Itoa(ver)].RSAKey
plain, err = rsa.DecryptOAEP(sha256.New(), rand.Reader, key, decoded, nil)
if err != nil {
@@ -1169,7 +1172,7 @@ func (p *Policy) Sign(ver int, context, input []byte, hashAlgorithm HashType, si
return nil, err
}

case KeyType_RSA2048, KeyType_RSA4096:
case KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
key := p.Keys[strconv.Itoa(ver)].RSAKey

var algo crypto.Hash
@@ -1332,7 +1335,7 @@ func (p *Policy) VerifySignature(context, input []byte, hashAlgorithm HashType,

return ed25519.Verify(key.Public().(ed25519.PublicKey), input, sigBytes), nil

case KeyType_RSA2048, KeyType_RSA4096:
case KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
key := p.Keys[strconv.Itoa(ver)].RSAKey

var algo crypto.Hash
@@ -1464,8 +1467,11 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage, randReader
entry.Key = pri
entry.FormattedPublicKey = base64.StdEncoding.EncodeToString(pub)

case KeyType_RSA2048, KeyType_RSA4096:
case KeyType_RSA2048, KeyType_RSA3072, KeyType_RSA4096:
bitSize := 2048
if p.Type == KeyType_RSA3072 {
bitSize = 3072
}
if p.Type == KeyType_RSA4096 {
bitSize = 4096
}
4 changes: 2 additions & 2 deletions ui/app/components/transit-key-actions.js
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ export default Component.extend(TRANSIT_PARAMS, {

keyIsRSA: computed('key.type', function() {
let type = get(this, 'key.type');
return type === 'rsa-2048' || type === 'rsa-4096';
return type === 'rsa-2048' || type === 'rsa-3072' || type === 'rsa-4096';
}),

getModelInfo() {
@@ -150,7 +150,7 @@ export default Component.extend(TRANSIT_PARAMS, {

compactData(data) {
let type = get(this, 'key.type');
let isRSA = type === 'rsa-2048' || type === 'rsa-4096';
let isRSA = type === 'rsa-2048' || type === 'rsa-3072' || type === 'rsa-4096';
return Object.keys(data).reduce((result, key) => {
if (key === 'signature_algorithm' && !isRSA) {
return result;
2 changes: 1 addition & 1 deletion ui/app/templates/components/transit-key-action/sign.hbs
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@
</div>
</div>
</div>
{{#if (or (eq key.type 'rsa-2048') (eq key.type 'rsa-4096'))}}
{{#if (or (eq key.type 'rsa-2048') (eq key.type 'rsa-3072') (eq key.type 'rsa-4096'))}}
<div class="field">
<label for="signature_algorithm" class="is-label">Signature Algorithm</label>
<div class="control is-expanded">
3 changes: 3 additions & 0 deletions ui/app/templates/partials/transit-form-create.hbs
Original file line number Diff line number Diff line change
@@ -31,6 +31,9 @@
<option selected={{eq key.type "rsa-2048"}} value="rsa-2048">
rsa-2048
</option>
<option selected={{eq key.type "rsa-3072"}} value="rsa-3072">
rsa-3072
</option>
<option selected={{eq key.type "rsa-4096"}} value="rsa-4096">
rsa-4096
</option>
6 changes: 6 additions & 0 deletions ui/tests/acceptance/transit-test.js
Original file line number Diff line number Diff line change
@@ -49,6 +49,12 @@ const keyTypes = [
supportsSigning: true,
supportsEncryption: true,
},
{
name: ts => `rsa-3072-${ts}`,
type: `rsa-3072`,
supportsSigning: true,
supportsEncryption: true,
},
{
name: ts => `rsa-4096-${ts}`,
type: `rsa-4096`,

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 15 additions & 9 deletions vendor/github.com/hashicorp/vault/sdk/helper/keysutil/policy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions website/pages/api-docs/secret/transit/index.mdx
Original file line number Diff line number Diff line change
@@ -62,6 +62,7 @@ values set here cannot be changed after key creation.
- `ecdsa-p384` – ECDSA using the P-384 elliptic curve (asymmetric)
- `ecdsa-p521` – ECDSA using the P-521 elliptic curve (asymmetric)
- `rsa-2048` - RSA with bit size of 2048 (asymmetric)
- `rsa-3072` - RSA with bit size of 3072 (asymmetric)
- `rsa-4096` - RSA with bit size of 4096 (asymmetric)

### Sample Payload
@@ -910,7 +911,7 @@ supports signing.
keys.

- `prehashed` `(bool: false)` - Set to `true` when the input is already hashed.
If the key type is `rsa-2048` or `rsa-4096`, then the algorithm used to hash
If the key type is `rsa-2048`, `rsa-3072` or `rsa-4096`, then the algorithm used to hash
the input should be indicated by the `hash_algorithm` parameter. Just as the
value to sign should be the base64-encoded representation of the exact binary
data you want signed, when set, `input` is expected to be base64-encoded
@@ -1065,7 +1066,7 @@ data.
keys.

- `prehashed` `(bool: false)` - Set to `true` when the input is already
hashed. If the key type is `rsa-2048` or `rsa-4096`, then the algorithm used
hashed. If the key type is `rsa-2048`, `rsa-3072` or `rsa-4096`, then the algorithm used
to hash the input should be indicated by the `hash_algorithm` parameter.

- `signature_algorithm` `(string: "pss")` – When using a RSA key, specifies the RSA
2 changes: 2 additions & 0 deletions website/pages/docs/secrets/transit/index.mdx
Original file line number Diff line number Diff line change
@@ -71,6 +71,8 @@ types also generate separate HMAC keys):
verification
- `rsa-2048`: 2048-bit RSA key; supports encryption, decryption, signing, and
signature verification
- `rsa-3072`: 3072-bit RSA key; supports encryption, decryption, signing, and
signature verification
- `rsa-4096`: 4096-bit RSA key; supports encryption, decryption, signing, and
signature verification