Bring your own key specification

This document describes specifications for importing HSM-protected keys from customers' on-premises HSMs into Key Vault.

Scenario

A Key Vault customer would like to securely transfer a key from their on-premises HSM outside Azure, into the HSM backing Azure Key Vault. The process of importing a key generated outside Key Vault is referred to as Bring Your Own Key (BYOK).

The following are the requirements:

  • The key to be transferred never exists outside an HSM in plain text form.
  • Outside an HSM, the key to be transferred is always protected by a key held in the Azure Key Vault HSM

Terminology

Key Name Key Type Origin Description
Key Exchange Key (KEK) RSA Azure Key Vault HSM An HSM backed RSA key pair generated in Azure Key Vault
Wrapping Key AES Vendor HSM An [ephemeral] AES key generated by HSM on-premises
Target Key RSA, EC, AES (Managed HSM only) Vendor HSM The key to be transferred to the Azure Key Vault HSM

Key Exchange Key: An HSM-backed key that customer generates in the key vault where the BYOK key will be imported. This KEK must have following properties:

  • It’s an RSA-HSM key (4096-bit or 3072-bit or 2048-bit)
  • It will have fixed key_ops (ONLY ‘import’), that will allow it to be used ONLY during BYOK
  • Must be in the same vault where the Target Key will be imported

User steps

To perform a key transfer, a user performs following steps:

  1. Generate KEK.
  2. Retrieve the public key of the KEK.
  3. Using HSM vendor provided BYOK tool - Import the KEK into the target HSM and exports the Target Key protected by the KEK.
  4. Import the protected Target Key to Azure Key Vault.

Customers use the BYOK tool and documentation provided by HSM vendor to complete Steps 3. It produces a Key Transfer Blob (a ".byok" file).

HSM constraints

Existing HSM may apply constraints on key that they manage, including:

  • The HSM may need to be configured to allow key wrap-based export
  • The target key may need to be marked CKA_EXTRACTABLE for the HSM to allow controlled export
  • In some cases, the KEK and wrapping key may need to be marked as CKA_TRUSTED, which allows it to be used to wrap keys in the HSM.

The configuration of source HSM is, generally, outside the scope of this specification. Microsoft expects the HSM vendor to produce documentation accompanying their BYOK tool to include any such configuration steps.

Note

Several of these steps can be performed using other interfaces such as Azure PowerShell and Azure Portal. They can also be performed programmatically using equivalent functions in Key Vault SDK.

Generate KEK

Use the az keyvault key create command to create KEK with key operations set to import. Note down the key identifier 'kid' returned from the below command.

az keyvault key create --kty RSA-HSM --size 4096 --name KEKforBYOK --ops import --vault-name ContosoKeyVaultHSM

Note

Services support different KEK lengths; Azure SQL, for instance, only supports key lengths of 2048 or 3072 bytes. Consult the documentation for your service for specifics.

Retrieve the public key of the KEK

Download the public key portion of the KEK and store it into a PEM file.

az keyvault key download --name KEKforBYOK --vault-name ContosoKeyVaultHSM --file KEKforBYOK.publickey.pem

Generate key transfer blob using HSM vendor provided BYOK tool

Customer will use HSM Vendor provided BYOK tool to create a key transfer blob (stored as a ".byok" file). KEK public key (as a .pem file) will be one of the inputs to this tool.

Key Transfer Blob

Long term, Microsoft would like to use PKCS#11 CKM_RSA_AES_KEY_WRAP mechanism to transfer the target key to Azure Key Vault since this mechanism produces a single blob and, more importantly, the intermediate AES key is handled by the two HSMs and is guaranteed to be ephemeral. This mechanism is not presently available in some HSMs but the combination of protecting the target key with CKM_AES_KEY_WRAP_PAD using an AES key and protecting the AES key with CKM_RSA_PKCS_OAEP produces an equivalent blob.

The target key plaintext depends on the key type:

  • For an RSA key, the private key ASN.1 DER encoding [RFC3447] wrapped in PKCS#8 [RFC5208]
  • For an EC key, the private key ASN.1 DER encoding [RFC5915] wrapped in PKCS#8 [RFC5208]
  • For an octet key, the raw bytes of the key

The bytes for the plaintext key are then transformed using the CKM_RSA_AES_KEY_WRAP mechanism:

  • An ephemeral AES key is generated and encrypted with the wrapping RSA key using RSA-OAEP with SHA1.
  • The encoded plaintext key is encrypted using the AES key using AES Key Wrap with Padding.
  • The encrypted AES key and the encrypted plaintext key are concatenated to produce the final ciphertext blob.

The format of the transfer blob uses JSON Web Encryption compact serialization (RFC7516) primarily as a vehicle for delivering the required metadata to the service for correct decryption.

If CKM_RSA_AES_KEY_WRAP_PAD is used, the JSON serialization of the transfer blob would be:

{
  "schema_version": "1.0.0",
  "header":
  {
    "kid": "<key identifier of the KEK>",
    "alg": "dir",
    "enc": "CKM_RSA_AES_KEY_WRAP"
  },
  "ciphertext":"BASE64URL(<ciphertext contents>)",
  "generator": "BYOK tool name and version; source HSM name and firmware version"
}

  • kid = key identifier of KEK. For Key Vault keys it looks like this: https://ContosoKeyVaultHSM.vault.azure.net/keys/mykek/eba63d27e4e34e028839b53fac905621
  • alg = algorithm.
  • dir = Direct mode, that is, the referenced kid is used to directly protect the ciphertext that is an accurate representation of CKM_RSA_AES_KEY_WRAP
  • generator = an informational field that denotes the name and version of BYOK tool and the source HSM manufacturer and model. This information is intended for use in troubleshooting and support.

The JSON blob is stored in a file with a ".byok" extension so that the Azure PowerShell/CLI clients treats it correctly when ‘Add-AzKeyVaultKey’ (PSH) or ‘az keyvault key import’ (CLI) commands are used.

Upload key transfer blob to import HSM-key

Customer will transfer the Key Transfer Blob (".byok" file) to an online workstation and then run a az keyvault key import command to import this blob as a new HSM-backed key into Key Vault.

To import an RSA key, use this command:

az keyvault key import --vault-name ContosoKeyVaultHSM --name ContosoFirstHSMkey --byok-file KeyTransferPackage-ContosoFirstHSMkey.byok --ops encrypt decrypt

To import an EC key, you must specify key type and the curve name.

az keyvault key import --vault-name ContosoKeyVaultHSM --name ContosoFirstHSMkey --byok-file --kty EC-HSM --curve-name "P-256" KeyTransferPackage-ContosoFirstHSMkey.byok --ops sign verify

When the above command is executed, it results in sending a REST API request as follows:

PUT https://contosokeyvaulthsm.vault.azure.net/keys/ContosoFirstHSMKey?api-version=7.0

Request body when importing an RSA key:

{
  "key": {
    "kty": "RSA-HSM",
    "key_ops": [
      "decrypt",
      "encrypt"
    ],
    "key_hsm": "<Base64 encoded BYOK_BLOB>"
  },
  "attributes": {
    "enabled": true
  }
}

Request body when importing an EC key:

{
  "key": {
    "kty": "EC-HSM",
    "crv": "P-256",
    "key_ops": [
      "sign",
      "verify"
    ],
    "key_hsm": "<Base64 encoded BYOK_BLOB>"
  },
  "attributes": {
    "enabled": true
  }
}

“key_hsm” value is the entire contents of the KeyTransferPackage-ContosoFirstHSMkey.byok encoded in the Base64 format.

References

Next steps