mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-11 17:17:01 +02:00
vault-24597: add key types and key creation for CMAC (#25967)
* add key types for cmac for transit key creation * add test for key creation * fix test logic and add cases * fix logic for hmac * add go doc * fix key size and add check for HMAC key
This commit is contained in:
parent
244b4998a0
commit
9ebcbf6a0c
@ -222,6 +222,10 @@ func (b *backend) pathPolicyWrite(ctx context.Context, req *logical.Request, d *
|
|||||||
polReq.KeyType = keysutil.KeyType_HMAC
|
polReq.KeyType = keysutil.KeyType_HMAC
|
||||||
case "managed_key":
|
case "managed_key":
|
||||||
polReq.KeyType = keysutil.KeyType_MANAGED_KEY
|
polReq.KeyType = keysutil.KeyType_MANAGED_KEY
|
||||||
|
case "aes128-cmac":
|
||||||
|
polReq.KeyType = keysutil.KeyType_AES128_CMAC
|
||||||
|
case "aes256-cmac":
|
||||||
|
polReq.KeyType = keysutil.KeyType_AES256_CMAC
|
||||||
default:
|
default:
|
||||||
return logical.ErrorResponse(fmt.Sprintf("unknown key type %v", keyType)), logical.ErrInvalidRequest
|
return logical.ErrorResponse(fmt.Sprintf("unknown key type %v", keyType)), logical.ErrInvalidRequest
|
||||||
}
|
}
|
||||||
|
@ -195,3 +195,113 @@ func TestTransit_CreateKeyWithAutorotation(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestTransit_CreateKey validates transit key creation functionality
|
||||||
|
func TestTransit_CreateKey(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
creationParams map[string]interface{}
|
||||||
|
shouldError bool
|
||||||
|
}{
|
||||||
|
"AES-128": {
|
||||||
|
creationParams: map[string]interface{}{"type": "aes128-gcm96"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"AES-256": {
|
||||||
|
creationParams: map[string]interface{}{"type": "aes256-gcm96"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"CHACHA20": {
|
||||||
|
creationParams: map[string]interface{}{"type": "chacha20-poly1305"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"ECDSA-P256": {
|
||||||
|
creationParams: map[string]interface{}{"type": "ecdsa-p256"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"ECDSA-P384": {
|
||||||
|
creationParams: map[string]interface{}{"type": "ecdsa-p384"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"ECDSA-P521": {
|
||||||
|
creationParams: map[string]interface{}{"type": "ecdsa-p521"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"RSA_2048": {
|
||||||
|
creationParams: map[string]interface{}{"type": "rsa-2048"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"RSA_3072": {
|
||||||
|
creationParams: map[string]interface{}{"type": "rsa-3072"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"RSA_4096": {
|
||||||
|
creationParams: map[string]interface{}{"type": "rsa-4096"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"HMAC": {
|
||||||
|
creationParams: map[string]interface{}{"type": "hmac", "key_size": 128},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"AES-128 CMAC": {
|
||||||
|
creationParams: map[string]interface{}{"type": "aes128-cmac"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"AES-256 CMAC": {
|
||||||
|
creationParams: map[string]interface{}{"type": "aes256-cmac"},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
"bad key type": {
|
||||||
|
creationParams: map[string]interface{}{"type": "fake-key-type"},
|
||||||
|
shouldError: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
coreConfig := &vault.CoreConfig{
|
||||||
|
LogicalBackends: map[string]logical.Factory{
|
||||||
|
"transit": transit.Factory,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
|
||||||
|
HandlerFunc: vaulthttp.Handler,
|
||||||
|
})
|
||||||
|
cluster.Start()
|
||||||
|
defer cluster.Cleanup()
|
||||||
|
cores := cluster.Cores
|
||||||
|
vault.TestWaitActive(t, cores[0].Core)
|
||||||
|
client := cores[0].Client
|
||||||
|
err := client.Sys().Mount("transit", &api.MountInput{
|
||||||
|
Type: "transit",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tt := range testCases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
keyName, err := uuid.GenerateUUID()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error generating key name: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Logical().Write(fmt.Sprintf("transit/keys/%s", keyName), tt.creationParams)
|
||||||
|
if err != nil && !tt.shouldError {
|
||||||
|
t.Fatalf("unexpected error creating key: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && tt.shouldError {
|
||||||
|
t.Fatal("expected error but got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
keyType, ok := resp.Data["type"]
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("missing key type in response")
|
||||||
|
}
|
||||||
|
|
||||||
|
if keyType != tt.creationParams["type"] {
|
||||||
|
t.Fatalf("incorrect key type: expected %s, got %s", tt.creationParams["type"], keyType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -397,6 +397,12 @@ func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest, rand io
|
|||||||
return nil, false, fmt.Errorf("key derivation and convergent encryption not supported for keys of type %v", req.KeyType)
|
return nil, false, fmt.Errorf("key derivation and convergent encryption not supported for keys of type %v", req.KeyType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case KeyType_AES128_CMAC, KeyType_AES256_CMAC:
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cleanup()
|
cleanup()
|
||||||
return nil, false, fmt.Errorf("unsupported key type %v", req.KeyType)
|
return nil, false, fmt.Errorf("unsupported key type %v", req.KeyType)
|
||||||
|
@ -68,6 +68,8 @@ const (
|
|||||||
KeyType_RSA3072
|
KeyType_RSA3072
|
||||||
KeyType_MANAGED_KEY
|
KeyType_MANAGED_KEY
|
||||||
KeyType_HMAC
|
KeyType_HMAC
|
||||||
|
KeyType_AES128_CMAC
|
||||||
|
KeyType_AES256_CMAC
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -202,6 +204,10 @@ func (kt KeyType) String() string {
|
|||||||
return "hmac"
|
return "hmac"
|
||||||
case KeyType_MANAGED_KEY:
|
case KeyType_MANAGED_KEY:
|
||||||
return "managed_key"
|
return "managed_key"
|
||||||
|
case KeyType_AES128_CMAC:
|
||||||
|
return "aes128-cmac"
|
||||||
|
case KeyType_AES256_CMAC:
|
||||||
|
return "aes256-cmac"
|
||||||
}
|
}
|
||||||
|
|
||||||
return "[unknown]"
|
return "[unknown]"
|
||||||
@ -1611,17 +1617,20 @@ func (p *Policy) RotateInMemory(randReader io.Reader) (retErr error) {
|
|||||||
DeprecatedCreationTime: now.Unix(),
|
DeprecatedCreationTime: now.Unix(),
|
||||||
}
|
}
|
||||||
|
|
||||||
hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader)
|
if p.Type != KeyType_AES128_CMAC && p.Type != KeyType_AES256_CMAC && p.Type != KeyType_HMAC {
|
||||||
if err != nil {
|
hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
entry.HMACKey = hmacKey
|
||||||
}
|
}
|
||||||
entry.HMACKey = hmacKey
|
|
||||||
|
|
||||||
|
var err error
|
||||||
switch p.Type {
|
switch p.Type {
|
||||||
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:
|
||||||
// Default to 256 bit key
|
// Default to 256 bit key
|
||||||
numBytes := 32
|
numBytes := 32
|
||||||
if p.Type == KeyType_AES128_GCM96 {
|
if p.Type == KeyType_AES128_GCM96 || p.Type == KeyType_AES128_CMAC {
|
||||||
numBytes = 16
|
numBytes = 16
|
||||||
} else if p.Type == KeyType_HMAC {
|
} else if p.Type == KeyType_HMAC {
|
||||||
numBytes = p.KeySize
|
numBytes = p.KeySize
|
||||||
|
Loading…
Reference in New Issue
Block a user