From d4bf262cdee3aa08e21bebd3b06c84eb0abfe214 Mon Sep 17 00:00:00 2001 From: hc-github-team-secure-vault-core <82990506+hc-github-team-secure-vault-core@users.noreply.github.com> Date: Fri, 17 Jun 2022 16:00:03 -0400 Subject: [PATCH] backport of commit b0cbc03f00ec19b5bebb2eb5078d8512e2281b1d (#16050) Co-authored-by: Rachel Culpepper <84159930+rculpepper@users.noreply.github.com> --- website/content/api-docs/secret/transit.mdx | 161 +++++++++++++++++++- website/content/docs/secrets/transit.mdx | 52 +++++++ 2 files changed, 211 insertions(+), 2 deletions(-) diff --git a/website/content/api-docs/secret/transit.mdx b/website/content/api-docs/secret/transit.mdx index 817674dedf016..c798436af30d8 100644 --- a/website/content/api-docs/secret/transit.mdx +++ b/website/content/api-docs/secret/transit.mdx @@ -91,6 +91,158 @@ $ curl \ http://127.0.0.1:8200/v1/transit/keys/my-key ``` +## Import Key + +This endpoint imports existing key material into a new transit-managed encryption key. +To import key material into an existing key, see the `import_version/` endpoint. + +### Parameters + +- `name` `(string: )` – Specifies the name of the encryption key to + create. This is specified as part of the URL. + +- `ciphertext` `(string: )` - A base64-encoded string that contains +two values: an ephemeral AES key wrapped using the wrapping key +returned by Vault and the encryption of the import key material under the +provided AES key. The wrapped AES key should be the first 512 bytes of the +ciphertext, and the encrypted key material should be the remaining bytes. + +- `hash_function` `(string: "SHA256")` - The hash function used for the +RSA-OAEP step of creating the ciphertext. Supported hash functions are: +`SHA1`, `SHA224`, `SHA256`, `SHA384`, and `SHA512`. If not specified, +the hash function defaults to SHA256. + +- `type` `(string: )` – Specifies the type of key to create. The + currently-supported types are: + + - `aes128-gcm96` – AES-128 wrapped with GCM using a 96-bit nonce size AEAD + (symmetric, supports derivation and convergent encryption) + - `aes256-gcm96` – AES-256 wrapped with GCM using a 96-bit nonce size AEAD + (symmetric, supports derivation and convergent encryption, default) + - `chacha20-poly1305` – ChaCha20-Poly1305 AEAD (symmetric, supports + derivation and convergent encryption) + - `ed25519` – ED25519 (asymmetric, supports derivation). When using + derivation, a sign operation with the same context will derive the same + key and signature; this is a signing analogue to `convergent_encryption`. + - `ecdsa-p256` – ECDSA using the P-256 elliptic curve (asymmetric) + - `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) + +- `allow_rotation` `(bool: false)` - If set, the imported key can be rotated +within Vault by using the `rotate` endpoint. + +~> **NOTE**: Once an imported key is rotated within Vault, it will no longer +support importing key material with the `import_version` endpoint. + +- `derived` `(bool: false)` – Specifies if key derivation is to be used. If + enabled, all encrypt/decrypt requests to this named key must provide a context + which is used for key derivation. + +- `context` `(string: "")` - A base64-encoded string providing a context for +key derivation. Required if `derived` is set to `true`. + +- `exportable` `(bool: false)` - Enables keys to be exportable. This + allows for all the valid keys in the key ring to be exported. Once set, this + cannot be disabled. + +- `allow_plaintext_backup` `(bool: false)` - If set, enables taking backup of + named key in the plaintext format. Once set, this cannot be disabled. + +- `auto_rotate_period` `(duration: "0", optional)` – The period at which + this key should be rotated automatically. Setting this to "0" (the default) + will disable automatic key rotation. This value cannot be shorter than one + hour. + +### Sample Payload + +```json +{ + "type": "ed25519", + "ciphertext": "..." +} +``` + +### Sample Request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST \ + --data @payload.json \ + http://127.0.0.1:8200/v1/transit/keys/my-key/import +``` + +## Import Key Version + +This endpoint imports new key material into an existing imported key. + +~> **Note**: Keys whose material was generated by Vault do not support +importing key material. Only keys that were previously imported into +Vault can import new key material from an external source. + +### Parameters + +- `name` `(string: )` – Specifies the name of the encryption key to + create. This is specified as part of the URL. + +- `ciphertext` `(string: )` - A base64-encoded string that contains +two values: an ephemeral AES key wrapped using the wrapping key +returned by Vault and the encryption of the import key material under the +provided AES key. The wrapped AES key should be the first 512 bytes of the +ciphertext, and the encrypted key material should be the remaining bytes. +See the BYOK section of the [Transit secrets engine documentation](/docs/secret/transit) +for more information on constructing the ciphertext. + +- `hash_function` `(string: "SHA256")` - The hash function used for the +RSA-OAEP step of creating the ciphertext. Supported hash functions are: +`SHA1`, `SHA224`, `SHA256`, `SHA384`, and `SHA512`. If not specified, +the hash function defaults to SHA256. + +### Sample Payload + +```json +{ + "ciphertext": "..." +} +``` + +### Sample Request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST \ + --data @payload.json \ + http://127.0.0.1:8200/v1/transit/keys/my-key/import_version +``` + +## Get Wrapping Key + +This endpoint is used to retrieve the wrapping key to use for importing keys. +The returned key will be a 4096-bit RSA public key. + +### Sample Request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request GET \ + http://127.0.0.1:8200/v1/transit/wrapping_key +``` + +### Sample Response + +```json +{ + "data": { + "public_key": "..." + }, +} +``` + ## Read Key This endpoint returns information about a named encryption key. The `keys` @@ -135,7 +287,8 @@ $ curl \ "supports_encryption": true, "supports_decryption": true, "supports_derivation": true, - "supports_signing": false + "supports_signing": false, + "imported": false } } ``` @@ -266,6 +419,10 @@ ciphertext to be encrypted with the latest version of the key, use the `rewrap` endpoint. This is only supported with keys that support encryption and decryption operations. +~> **Note**: For imported keys, rotation is only supported if the +`allow_rotation` field was set to `true` on import. Once an imported key is +rotated within Vault, it will not support further import operations. + | Method | Path | | :----- | :--------------------------- | | `POST` | `/transit/keys/:name/rotate` | @@ -398,7 +555,7 @@ will be returned. all nonces are unique for a given context. Failing to do so will severely impact the ciphertext's security. -**NOTE:** All plaintext data **must be base64-encoded**. The reason for this +~>**NOTE:** All plaintext data **must be base64-encoded**. The reason for this requirement is that Vault does not require that the plaintext is "text". It could be a binary file such as a PDF or image. The easiest safe transport mechanism for this data as part of a JSON payload is to base64-encode it. diff --git a/website/content/docs/secrets/transit.mdx b/website/content/docs/secrets/transit.mdx index 04e788441533c..ec19e6b9f5685 100644 --- a/website/content/docs/secrets/transit.mdx +++ b/website/content/docs/secrets/transit.mdx @@ -235,6 +235,58 @@ the proper permission, it can use this secrets engine. data, since the process would not be able to get access to the plaintext data. +## Bring Your Own Key (BYOK) + +~> **Note:** Key import functionality supports cases in which there is a need to bring +in an existing key from an HSM or other outside system. It is more secure to +have Transit generate and manage a key within Vault. + +First, the wrapping key needs to be read from transit: + +```text +$ vault read transit/wrapping_key +``` + +The wrapping key will be a 4096-bit RSA public key. + +Then the wrapping key is used to create the ciphertext input for the `import` endpoint, +as described below. In the below, the target key refers to the key being imported. + +### HSM + +If the key is being imported from an HSM that supports PKCS#11, there are +two possible scenarios: + +- If the HSM supports the CKM_AES_KEY_WRAP_KWP mechanism, that can be used to wrap the +target key using the wrapping key. + +- Otherwise, two mechanisms can be combined to wrap the target key. First, an AES key should +be generated and then used to wrap the target key using the CKM_AES_KEY_WRAP_PAD mechanism. +Then the AES key should be wrapped under the wrapping key using the CKM_RSA_PKCS_OAEP mechanism +using MGF1 and either SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512. + +The ciphertext is constructed by appending the wrapped target key to the wrapped AES key. + +The ciphertext bytes should be base64-encoded. + +### Manual Process + +If the target key is not stored in an HSM or KMS, the following steps can be used to construct +the ciphertext for the input of the `import` endpoint: + +- Generate an ephemeral AES key. + +- Wrap the target key using the ephemeral AES key with AES-KWP. + +- Wrap the AES key under the Vault wrapping key using RSAES-OAEP with MGF1 and +either SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512. + +- Delete the ephemeral AES key. + +- Append the wrapped target key to the wrapped AES key. + +- Base64 encode the result. + ## Tutorial Refer to the [Encryption as a Service: Transit Secrets