Vault
PKCS#11 provider
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.
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