Vault
PKCS#11 support in Vault
Enterprise
Appropriate Vault Enterprise license required
PKCS11 provider is part of the KMIP Secret Engine, which requires Vault Enterprise with the Advanced Data Protection (ADP) module. The PKCS11 provider supports a subset of key generation, encryption, decryption and key storage operations. You must have an Enterprise ADP-KM license to use the PKCS11 provider.
PKCS#11 is an open standard C API that provides a means to access cryptographic capabilities on a device. For example, it is often used to access a Hardware Security Module (HSM) (like a Yubikey) from a local program (such as GPG).
Vault provides a PKCS#11 library (or provider) so that Vault can be used as an SSM (Software Security Module). This allows a user to treat Vault like any other PKCS#11 device to manage keys, objects, and perform encryption and decryption in Vault using PKCS#11 calls. The PKCS#11 library connects to Vault's KMIP Secrets Engine to provide cryptographic operations and object storage.
Platform support
This library works with Vault Enterprise 1.11+ with the advanced data protection module in the license with the KMIP Secrets Engine.
Operating System | Architecture | Distribution | glibc |
---|---|---|---|
Linux | x86-64 | RHEL 7 compatible | 2.17 |
Linux | x86-64 | RHEL 8 compatible | 2.28 |
Linux | x86-64 | RHEL 9 compatible | 2.34 |
macOS | x86-64 | — | — |
macOS | arm64 | — | — |
Note: vault-pkcs11-provider
runs on any glibc-based Linux distribution. The versions above are given in RHEL-compatible GLIBC versions; for your
distro's glibc version, choose the vault-pkcs11-provider
built against the same or older version as what your distro provides.
The provider comes in the form of a shared C library, libvault-pkcs11.so
(for Linux) or libvault-pkcs11.dylib
(for macOS).
It can be downloaded from releases.hashicorp.com.
Quick start
To use the provider, you will need access to a Vault Enterprise instance with the KMIP Secrets Engine.
For example, you can start one locally (if you have a license in the
VAULT_LICENSE
environment variable) with:docker pull hashicorp/vault-enterprise && docker run --name vault \ -p 5696:5696 \ -p 8200:8200 \ --cap-add=IPC_LOCK \ -e VAULT_LICENSE=$(printenv VAULT_LICENSE) \ -e VAULT_ADDR=http://127.0.0.1:8200 \ -e VAULT_TOKEN=root \ hashicorp/vault-enterprise \ server -dev -dev-root-token-id root -dev-listen-address 0.0.0.0:8200
Configure the KMIP Secrets Engine and a KMIP scope. The scope is used to hold keys and objects.
Note: These commands will output the credentials in plaintext.
vault secrets enable kmip vault write kmip/config listen_addrs=0.0.0.0:5696 vault write -f kmip/scope/my-service vault write kmip/scope/my-service/role/admin operation_all=true vault write -f -format=json kmip/scope/my-service/role/admin/credential/generate | tee kmip.json
Important: When configuring KMIP in production, you will probably need to set the
server_hostnames
andserver_ips
configuration parameters, otherwise the TLS connection to the KMIP Secrets Engine will fail due to certification validation errors.This last line will generate a JSON file with the certificate, key, and CA certificate chain to connect to the KMIP server. You'll need to save these to files so that the PKCS#11 provider can use them.
jq --raw-output --exit-status '.data.ca_chain[]' kmip.json > ca.pem jq --raw-output --exit-status '.data.certificate' kmip.json > cert.pem
The certificate file from the KMIP Secrets Engine also contains the key.
Create a configuration file called
vault-pkcs11.hcl
:slot { server = "127.0.0.1:5696" tls_cert_path = "cert.pem" ca_path = "ca.pem" scope = "my-service" }
See below for all available parameters.
Copy the certificates from the KMIP credentials into the files specified in the configuration file (e.g.,
cert.pem
, andca.pem
).You should now be able to use the
libvault-pkcs11.so
(or.dylib
) library to access the KMIP Secrets Engine in Vault using any PKCS#11-compatible tool, like OpenSC'spkcs11-tool
, e.g.:$ VAULT_LOG_FILE=/dev/null pkcs11-tool --module ./libvault-pkcs11.so -L Available slots: Slot 0 (0x0): Vault slot 0 token label : Token 0 token manufacturer : HashiCorp token model : Vault Enterprise token flags : token initialized, PIN initialized, other flags=0x60 hardware version : 1.12 firmware version : 1.12 serial num : 1234 pin min/max : 0/255 $ VAULT_LOG_FILE=/dev/null pkcs11-tool --module ./libvault-pkcs11.so --keygen -a abc123 --key-type AES:32 \ --extractable --allow-sw 2>/dev/null Key generated: Secret Key Object; AES length 32 VALUE: label: abc123 Usage: encrypt, decrypt, wrap, unwrap Access: none
The
VAULT_LOG_FILE=/dev/null
setting is to prevent the Vault PKCS#11 driver logs from appearing in stdout (the default if no file is specified). In production, it's good to setVAULT_LOG_FILE
to point to somewhere more permanent, like/var/log/vault.log
.
Configuration
The PKCS#11 Provider can be configured through an HCL file and through envionment variables.
The HCL file contains directives to map PKCS#11 device
slots (logical devices)
to Vault instances and KMIP scopes and configures how the library will authenticate to KMIP (with a client TLS certificate).
The PKCS#11 library will look for this file in vault-pkcs11.hcl
and /etc/vault-pkcs11.hcl
by default, or you can override this by setting the VAULT_KMIP_CONFIG
environment variable.
For example,
slot {
server = "127.0.0.1:5696"
tls_cert_path = "cert.pem"
ca_path = "ca.pem"
scope = "my-service"
}
The slot
block configures the first PKCS#11 slot to point to Vault.
Most programs will use only one slot.
server
(required): the Vault server's IP or DNS name and port number (5696 is the default).tls_cert_path
(required): the location of the client TLS certificate used to authenticate to the KMIP engine.tls_key_path
(optional, defaults to the value oftls_cert_path
): the location of the encrypted or unencrypted TLS key used to authenticate to the KMIP engine.ca_path
(required): the location of the CA bundle that will be used to verify the server's certificate.scope
(required): the KMIP scope to authenticate against and where the TDE master keys and associated metadata will be stored.cache
(optional, defaulttrue
): if the provider uses a cache to improve the performance ofC_GetAttributeValue
(KMIP:GetAttributes
) calls.emulate_hardware
(optional, defaultfalse
): specifies if the provider should report that it is connected to a hardware device.
The default location the PKCS#11 library will look for the configuration file is the current directory (vault-pkcs11.hcl
) and /etc/vault-pkcs11.hcl
, but you can override this by setting the VAULT_KMIP_CONFIG
environment variable to any file.
Environment variables can be also used to configure these parameters and more.
VAULT_KMIP_CONFIG
: location of the HCL configuration file. By default, the provider will check./vault-pkcs11.hcl
and/etc/vault-pkcs11.hcl
.VAULT_KMIP_CERT_FILE
: location of the TLS certificate used for authentication to the KMIP engine.VAULT_KMIP_KEY_FILE
: location of the TLS key used for authentication to the KMIP engine.VAULT_KMIP_KEY_PASSWORD
: password for the TLS key file, if it is encrypted to the KMIP engine.VAULT_KMIP_CA_FILE
: location of the TLS CA bundle used to authenticate the connection to the KMIP engine.VAULT_KMIP_SERVER
: address and port of the KMIP engine to use for encryption and storage.VAULT_KMIP_SCOPE
: KMIP scope to use for encryption and storageVAULT_KMIP_CACHE
: whether or not to cacheC_GetAttributeValue
(KMIP:GetAttributes
) calls.VAULT_LOG_LEVEL
: the log level that the provider will use. Defaults toWARN
. Valid values includeTRACE
,DEBUG
,INFO
,WARN
,ERROR
, andOFF
.VAULT_LOG_FILE
: the location of the file the provider will use for logging. Defaults to standard out.VAULT_EMULATE_HARDWARE
: whether or not the provider will report that it is backed by a hardware device.
Encrypted TLS key support
The TLS key returned by the KMIP engine is unencrypted by default. However, the PKCS#11 provider does support (limited) encryption options for the key using RFC 1423. We would only recommend using AES-256-CBC out of the available algorithms.
The keys from KMIP should be ECDSA keys, and can be encrypted with a password with OpenSSL, e.g.,:
openssl ec -in cert.key -out encrypted.key -aes-256-cbc
The PKCS#11 provider will need access to the password to decrypt the TLS key. The password can be supplied to the provider in two ways:
- The
VAULT_KMIP_KEY_PASSWORD
environment variable, or - the "PIN" parameter to the
C_Login
PKCS#11 function will be used to try to decrypt an encrypted TLS key.
Note that only a single password can be supplied via the VAULT_KMIP_KEY_PASSWORD
, so if multiple slots in the HCL file use encrypted TLS keys, they will need to be encrypted with the same password, or use the C_Login
method to specify the password.
Error handling
If an error occurs, the first place to check will be the VAULT_LOG_FILE
for any relevant error messages.
If the PKCS#11 provider returns an error code of 0x30
(CKR_DEVICE_ERROR
), then an additional device error code may
be available from the C_SessionInfo
call.
Here are the known device error codes the provider will return:
Code | Meaning |
---|---|
400 | Invalid input was provided in the configuration or PKCS#11 call. |
401 | Invalid credentials were provided. |
404 | The object, attribute, or key was not found. |
600 | An unknown I/O error occurred. |
601 | A KMIP engine error occured. |
Capabilities
The Vault PKCS#11 provider implements the following PKCS#11 provider profiles:
The following key genration mechanisms are currently supported:
Name | Mechanism Number | Provider Version | Vault Version |
---|---|---|---|
RSA-PKCS | 0x0000 | 0.2.0 | 1.13 |
AES key generation | 0x1080 | 0.1.0 | 1.12 |
The following encryption mechanisms are currently supported:
Name | Mechanism Number | Provider Version | Vault Version |
---|---|---|---|
RSA-PKCS | 0x0001 | 0.2.0 | 1.13 |
RSA-PKCS-OAEP | 0x0009 | 0.2.0 | 1.13 |
AES-ECB | 0x1081 | 0.2.0 | 1.13 |
AES-CBC | 0x1082 | 0.1.0 | 1.12 |
AES-CBC Pad | 0x1085 | 0.1.0 | 1.12 |
AES-CTR | 0x1086 | 0.1.0 | 1.12 |
AES-GCM | 0x1087 | 0.1.0 | 1.12 |
AES-OFB | 0x2104 | 0.2.0 | 1.13 |
AES-CFB128 | 0x2107 | 0.2.0 | 1.13 |
The following signing mechanisms are currently supported:
Name | Mechanism Number | Provider Version | Vault Version |
---|---|---|---|
RSA-PKCS | 0x0001 | 0.2.0 | 1.13 |
SHA256-RSA-PKCS | 0x0040 | 0.2.0 | 1.13 |
SHA384-RSA-PKCS | 0x0041 | 0.2.0 | 1.13 |
SHA512-RSA-PKCS | 0x0042 | 0.2.0 | 1.13 |
SHA224-RSA-PKCS | 0x0046 | 0.2.0 | 1.13 |
SHA512-224-HMAC | 0x0049 | 0.2.0 | 1.13 |
SHA512-256-HMAC | 0x004D | 0.2.0 | 1.13 |
SHA256-HMAC | 0x0251 | 0.2.0 | 1.13 |
SHA224-HMAC | 0x0256 | 0.2.0 | 1.13 |
SHA384-HMAC | 0x0261 | 0.2.0 | 1.13 |
SHA512-HMAC | 0x0271 | 0.2.0 | 1.13 |
Here is the list of supported and unsupported PKCS#11 functions:
- Encryption and decryption
-
C_EncryptInit
-
C_Encrypt
-
C_EncryptUpdate
-
C_EncryptFinal
-
C_DecryptInit
-
C_Decrypt
-
C_DecryptUpdate
-
C_DecryptFinal
-
- Key management
-
C_GenerateKey
-
C_GenerateKeyPair
-
C_WrapKey
-
C_UnwrapKey
-
C_DeriveKey
-
- Objects
-
C_CreateObject
-
C_DestroyObject
-
C_GetAttributeValue
-
C_FindObjectsInit
-
C_FindObjects
-
C_FindObjectsFinal
-
C_SetAttributeValue
-
C_CopyObject
-
C_GetObjectSize
-
- Management
-
C_Initialize
-
C_Finalize
-
C_Login
(PIN is used as a passphrase for the TLS encryption key, if provided) -
C_Logout
-
C_GetInfo
-
C_GetSlotList
-
C_GetSlotInfo
-
C_GetTokenInfo
-
C_GetMechanismList
-
C_GetMechanismInfo
-
C_OpenSession
-
C_CloseSession
-
C_CloseAllSessions
-
C_GetSessionInfo
-
C_InitToken
-
C_InitPIN
-
C_SetPIN
-
C_GetOperationState
-
C_SetOperationState
-
C_GetFunctionStatus
-
C_CancelFunction
-
C_WaitForSlotEvent
-
- Signing
-
C_SignInit
-
C_Sign
-
C_SignUpdate
-
C_SignFinal
-
C_SignRecoverInit
-
C_SignRecover
-
C_VerifyInit
-
C_Verify
-
C_VerifyUpdate
-
C_VerifyFinal
-
C_VerifyRecoverInit
-
C_VerifyRecover
-
- Digests
-
C_DigestInit
-
C_Digest
-
C_DigestUpdate
-
C_DigestKey
-
C_DigestFinal
-
C_DigestEncryptUpdate
-
C_DecryptDigestUpdate
-
C_SignEncryptUpdate
-
C_DecryptVerifyUpdate
-
- Random Number Generation (see note below)
-
C_SeedRandom
-
C_GenerateRandom
-
Limitations and notes
Due to the nature of Vault, the KMIP Secrets Engine, and PKCS#11, there are some other limitations to be aware of:
- The key and object IDs returned by
C_FindObjects
, etc., are randomized for each session, and cannot be shared between sessions; they have no meaning after a session is closed. This is because KMIP objects, which are used to store the PKCS#11 objects, have long random strings as IDs, but the PKCS#11 object ID is limited to a 32-bit integer. Also, the PKCS#11 provider does not have any local storage. - The PKCS#11 provider's performance is heavily dependent on the latency to the Vault server and its performance. This is because nearly all PKCS#11 API calls are translated 1-1 to KMIP calls, aside from some object attribute calls (which can be locally cached). Multiple sessions can be safely used simultaneously though, and a single Vault server node has been tested as supporting thousands of ongoing sessions.
- The object attribute cache is valid only for a single object per session, and will be cleared when another object's attributes are queried.
- The random number generator function,
C_GenerateRandom
, is currently implemented in software in the library by calling out to Go'scrypto/rand
package, and does not call Vault.
Changelog
v0.2.1
- Go update to 1.22.7 and Go dependency updates
- Add license files to artifacts
v0.2.0
- Introduced support for RSA and HMAC operations
v0.1.3
- Go update to 1.19.4 and Go dependency updates
- Added missing checksum for EL9 builds
v0.1.2
- Added arm64 support on macOS
- Go update to 1.19.2 and Go dependency updates
v0.1.1
- KMIP: Set activation date attribute required by Vault 1.12
- KMIP: Revoke a key prior to destroy
v0.1.0
- Initial release