vault-24958: add cmac key types for import and export (#26610)

* add cmac key types to export

* set rsa public key and add cmac key types for wrapping

* add cmac types to import and export

* add cmac export key type

* fix import key type

* add cmac to policy import

* add enterprise checks

* fix imports
This commit is contained in:
Rachel Culpepper
2024-04-24 08:13:19 -05:00
committed by GitHub
parent b423254665
commit d2aad917bb
4 changed files with 34 additions and 7 deletions

View File

@@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"github.com/hashicorp/vault/helper/constants"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/keysutil"
"github.com/hashicorp/vault/sdk/logical"
@@ -97,6 +98,10 @@ func (b *backend) pathPolicyBYOKExportRead(ctx context.Context, req *logical.Req
return logical.ErrorResponse("key is not exportable"), nil
}
if srcP.Type.CMACSupported() && !constants.IsEnterprise {
return logical.ErrorResponse(ErrCmacEntOnly.Error()), logical.ErrInvalidRequest
}
retKeys := map[string]string{}
switch version {
case "":
@@ -154,7 +159,7 @@ func getBYOKExportKey(dstP *keysutil.Policy, srcP *keysutil.Policy, key *keysuti
var targetKey interface{}
switch srcP.Type {
case keysutil.KeyType_AES128_GCM96, keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305, keysutil.KeyType_HMAC:
case keysutil.KeyType_AES128_GCM96, keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305, keysutil.KeyType_HMAC, keysutil.KeyType_AES128_CMAC, keysutil.KeyType_AES256_CMAC:
targetKey = key.Key
case keysutil.KeyType_RSA2048, keysutil.KeyType_RSA3072, keysutil.KeyType_RSA4096:
targetKey = key.RSAKey

View File

@@ -16,6 +16,7 @@ import (
"strconv"
"strings"
"github.com/hashicorp/vault/helper/constants"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/keysutil"
"github.com/hashicorp/vault/sdk/logical"
@@ -27,6 +28,7 @@ const (
exportTypeHMACKey = "hmac-key"
exportTypePublicKey = "public-key"
exportTypeCertificateChain = "certificate-chain"
exportTypeCMACKey = "cmac-key"
)
func (b *backend) pathExportKeys() *framework.Path {
@@ -42,7 +44,7 @@ func (b *backend) pathExportKeys() *framework.Path {
Fields: map[string]*framework.FieldSchema{
"type": {
Type: framework.TypeString,
Description: "Type of key to export (encryption-key, signing-key, hmac-key, public-key)",
Description: "Type of key to export (encryption-key, signing-key, hmac-key, public-key, cmac-key)",
},
"name": {
Type: framework.TypeString,
@@ -74,6 +76,10 @@ func (b *backend) pathPolicyExportRead(ctx context.Context, req *logical.Request
case exportTypeHMACKey:
case exportTypePublicKey:
case exportTypeCertificateChain:
case exportTypeCMACKey:
if !constants.IsEnterprise {
return logical.ErrorResponse(ErrCmacEntOnly.Error()), logical.ErrInvalidRequest
}
default:
return logical.ErrorResponse(fmt.Sprintf("invalid export type: %s", exportType)), logical.ErrInvalidRequest
}
@@ -265,6 +271,11 @@ func getExportKey(policy *keysutil.Policy, key *keysutil.KeyEntry, exportType st
certChain := strings.Join(pemCerts, "\n")
return certChain, nil
case exportTypeCMACKey:
switch policy.Type {
case keysutil.KeyType_AES128_CMAC, keysutil.KeyType_AES256_CMAC:
return strings.TrimSpace(base64.StdEncoding.EncodeToString(key.Key)), nil
}
}
return "", fmt.Errorf("unknown key type %v for export type %v", policy.Type, exportType)

View File

@@ -18,6 +18,7 @@ import (
"time"
"github.com/google/tink/go/kwp/subtle"
"github.com/hashicorp/vault/helper/constants"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/keysutil"
"github.com/hashicorp/vault/sdk/logical"
@@ -45,7 +46,7 @@ func (b *backend) pathImport() *framework.Path {
Default: "aes256-gcm96",
Description: `The type of key being imported. Currently, "aes128-gcm96" (symmetric), "aes256-gcm96" (symmetric), "ecdsa-p256"
(asymmetric), "ecdsa-p384" (asymmetric), "ecdsa-p521" (asymmetric), "ed25519" (asymmetric), "rsa-2048" (asymmetric), "rsa-3072"
(asymmetric), "rsa-4096" (asymmetric) are supported. Defaults to "aes256-gcm96".
(asymmetric), "rsa-4096" (asymmetric), "hmac", "aes128-cmac", "aes256-cmac" are supported. Defaults to "aes256-gcm96".
`,
},
"hash_function": {
@@ -214,10 +215,18 @@ func (b *backend) pathImportWrite(ctx context.Context, req *logical.Request, d *
polReq.KeyType = keysutil.KeyType_RSA4096
case "hmac":
polReq.KeyType = keysutil.KeyType_HMAC
case "aes128-cmac":
polReq.KeyType = keysutil.KeyType_AES128_CMAC
case "aes256-cmac":
polReq.KeyType = keysutil.KeyType_AES256_CMAC
default:
return logical.ErrorResponse(fmt.Sprintf("unknown key type: %v", keyType)), logical.ErrInvalidRequest
}
if polReq.KeyType.CMACSupported() && !constants.IsEnterprise {
return logical.ErrorResponse(ErrCmacEntOnly.Error()), logical.ErrInvalidRequest
}
p, _, err := b.GetPolicy(ctx, polReq, b.GetRandomReader())
if err != nil {
return nil, err

View File

@@ -1527,13 +1527,13 @@ func (p *Policy) ImportPublicOrPrivate(ctx context.Context, storage logical.Stor
return fmt.Errorf("unable to import only public key for derived Ed25519 key: imported key should not be an Ed25519 key pair but is instead an HKDF key")
}
if (p.Type == KeyType_AES128_GCM96 && len(key) != 16) ||
((p.Type == KeyType_AES256_GCM96 || p.Type == KeyType_ChaCha20_Poly1305) && len(key) != 32) ||
if ((p.Type == KeyType_AES128_GCM96 || p.Type == KeyType_AES128_CMAC) && len(key) != 16) ||
((p.Type == KeyType_AES256_GCM96 || p.Type == KeyType_ChaCha20_Poly1305 || p.Type == KeyType_AES256_CMAC) && len(key) != 32) ||
(p.Type == KeyType_HMAC && (len(key) < HmacMinKeySize || len(key) > HmacMaxKeySize)) {
return fmt.Errorf("invalid key size %d bytes for key type %s", len(key), p.Type)
}
if p.Type == KeyType_AES128_GCM96 || p.Type == KeyType_AES256_GCM96 || p.Type == KeyType_ChaCha20_Poly1305 || p.Type == KeyType_HMAC {
if p.Type == KeyType_AES128_GCM96 || p.Type == KeyType_AES256_GCM96 || p.Type == KeyType_ChaCha20_Poly1305 || p.Type == KeyType_HMAC || p.Type == KeyType_AES128_CMAC || p.Type == KeyType_AES256_CMAC {
entry.Key = key
if p.Type == KeyType_HMAC {
p.KeySize = len(key)
@@ -1736,6 +1736,8 @@ func (p *Policy) RotateInMemory(randReader io.Reader) (retErr error) {
if err != nil {
return err
}
entry.RSAPublicKey = entry.RSAKey.Public().(*rsa.PublicKey)
}
if p.ConvergentEncryption {
@@ -2394,7 +2396,7 @@ func (ke *KeyEntry) WrapKey(targetKey interface{}, targetKeyType KeyType, hash h
var preppedTargetKey []byte
switch targetKeyType {
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_HMAC:
case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_HMAC, KeyType_AES128_CMAC, KeyType_AES256_CMAC:
var ok bool
preppedTargetKey, ok = targetKey.([]byte)
if !ok {