Skip to content

Commit

Permalink
kms: add ImportKey API and ImportKeyRequest type
Browse files Browse the repository at this point in the history
This commits adds the `ImportKey` API call. Clients can
now import an existing key into the KMS. However, such
keys are marked by the KMS server to indentify keys that
have been outside of the KMS.

Signed-off-by: Andreas Auernhammer <[email protected]>
  • Loading branch information
aead committed Feb 7, 2024
1 parent a901894 commit cfd2e4f
Show file tree
Hide file tree
Showing 7 changed files with 340 additions and 223 deletions.
32 changes: 30 additions & 2 deletions kms/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,34 @@ func (c *Client) CreateKey(ctx context.Context, req *CreateKeyRequest) error {
return resp.Body.Close()
}

// ImportKey imports an existing key with the name req.Name into req.Enclave.
// By default, a new key is created if and only if no such key exists. If
// req.AddVersion is true, a new key version is added to an existing key.
// The later is often referred to as key rotation.
//
// Keys that imported are marked by the KMS server to distinguish them from
// keys that never left the KMS boundary.
//
// It returns ErrEnclaveNotFound if no such enclave exists and ErrKeyExists
// if such a key already exists wrapped in a HostError.
//
// The returned error is of type *HostError.
func (c *Client) ImportKey(ctx context.Context, req *ImportKeyRequest) error {
body, err := cmds.Encode(nil, cmds.KeyImport, req)
if err != nil {
return err
}

resp, err := c.Send(ctx, &Request{
Enclave: req.Enclave,
Body: body,
})
if err != nil {
return err
}
return resp.Body.Close()
}

// DescribeKeyVersion returns metadata about the key req.Name within
// the req.Enclave.
//
Expand Down Expand Up @@ -898,7 +926,7 @@ func (c *Client) Decrypt(ctx context.Context, req *DecryptRequest) (*DecryptResp
//
// The returned error is of type *HostError.
func (c *Client) GenerateKey(ctx context.Context, req *GenerateKeyRequest) (*GenerateKeyResponse, error) {
body, err := cmds.Encode(nil, cmds.KeyDataKey, req)
body, err := cmds.Encode(nil, cmds.KeyGenerate, req)
if err != nil {
return nil, err
}
Expand All @@ -913,7 +941,7 @@ func (c *Client) GenerateKey(ctx context.Context, req *GenerateKeyRequest) (*Gen
defer resp.Body.Close()

var data GenerateKeyResponse
if err := decodeResponse(resp, cmds.KeyDataKey, &data); err != nil {
if err := decodeResponse(resp, cmds.KeyGenerate, &data); err != nil {
return nil, err
}
return &data, nil
Expand Down
18 changes: 10 additions & 8 deletions kms/cmds/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ const (

KeyCreate Command = 201
KeyDelete Command = 202
KeyStatus Command = 203
KeyEncrypt Command = 204
KeyDecrypt Command = 205
KeyDataKey Command = 206
KeyList Command = 207
KeyListVersions Command = 208
KeyImport Command = 203
KeyStatus Command = 204
KeyEncrypt Command = 205
KeyDecrypt Command = 206
KeyGenerate Command = 207
KeyList Command = 208
KeyListVersions Command = 209

PolicyCreate Command = 301
PolicyDelete Command = 302
Expand Down Expand Up @@ -108,6 +109,7 @@ var isWrite = map[Command]struct{}{ // Commands that change state on a KMS serve

KeyCreate: {},
KeyDelete: {},
KeyImport: {},

PolicyCreate: {},
PolicyDelete: {},
Expand All @@ -133,7 +135,7 @@ var cmdTexts = map[Command]string{
KeyStatus: "KEY:STATUS",
KeyEncrypt: "KEY:ENCRYPT",
KeyDecrypt: "KEY:DECRYPT",
KeyDataKey: "KEY:DATAKEY",
KeyGenerate: "KEY:GENERATE",
KeyList: "KEY:LIST",
KeyListVersions: "KEY:LISTVERSIONS",

Expand Down Expand Up @@ -166,7 +168,7 @@ var textCmds = map[string]Command{
"KEY:STATUS": KeyStatus,
"KEY:ENCRYPT": KeyEncrypt,
"KEY:DECRYPT": KeyDecrypt,
"KEY:DATAKEY": KeyDataKey,
"KEY:GENERATE": KeyGenerate,
"KEY:LIST": KeyList,
"KEY:LISTVERSIONS": KeyListVersions,

Expand Down
23 changes: 12 additions & 11 deletions kms/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ import (
"strconv"
)

// ParseSecretKeyType returns a SecretKeyType from its string representation.
func ParseSecretKeyType(s string) (SecretKeyType, error) {
switch s {
case "AES256":
return AES256, nil
case "ChaCha20":
return ChaCha20, nil
default:
return 0, fmt.Errorf("kms: key type '%s' is not supported", s)
}
}

// SecretKeyType defines the type of a secret key. Secret keys with
// different types are not compatible since they may differ in the
// encryption algorithm, key length, cipher mode, etc.
Expand All @@ -34,14 +46,3 @@ func (s SecretKeyType) String() string {
return "!INVALID:" + strconv.Itoa(int(s))
}
}

func secretKeyTypeFromString(s string) (SecretKeyType, error) {
switch s {
case "AES256":
return AES256, nil
case "ChaCha20":
return ChaCha20, nil
default:
return 0, fmt.Errorf("kms: key type '%s' is not supported", s)
}
}
Loading

0 comments on commit cfd2e4f

Please sign in to comment.