Cryptographic Plugin Development¶
This guide describes how to develop a custom cryptographic plugin for use by Barbican.
Barbican supports two storage modes for secrets: a cryptographic mode (detailed on this page), and a secret store mode. The cryptographic mode stores encrypted secrets in Barbican’s data store, utilizing a cryptographic process or appliance (such as a hardware security module (HSM)) to perform the encryption/decryption. Barbican includes a PKCS11-based interface to SafeNet HSMs.
Note that cryptographic plugins are not invoked directly from Barbican core, but rather via a secret store mode plugin adapter class, further described in The Cryptographic Plugin Adapter.
crypto
Module¶
The barbican.plugin.crypto
module contains the classes needed to implement
a custom plugin. These classes include the CryptoPluginBase
abstract base class which custom plugins should inherit from, as well as
several Data Transfer Object (DTO) classes used to transfer data between
Barbican and the plugin.
Data Transfer Objects¶
The DTO classes are used to wrap data that is passed from Barbican to the plugin as well as data that is returned from the plugin back to Barbican. They provide a level of isolation between the plugins and Barbican’s internal data models.
- class barbican.plugin.crypto.base.KEKMetaDTO(kek_datum)¶
Key Encryption Key Meta DTO
Key Encryption Keys (KEKs) in Barbican are intended to represent a distinct key that is used to perform encryption on secrets for a particular project.
KEKMetaDTO
objects are provided to cryptographic backends by Barbican to allow plugins to persist metadata related to the project’s KEK.For example, a plugin that interfaces with a Hardware Security Module (HSM) may want to use a different encryption key for each project. Such a plugin could use the
KEKMetaDTO
object to save the key ID used for that project. Barbican will persist the KEK metadata and ensure that it is provided to the plugin every time a request from that same project is processed.- plugin_name¶
String attribute used by Barbican to identify the plugin that is bound to the KEK metadata. Plugins should not change this attribute.
- kek_label¶
String attribute used to label the project’s KEK by the plugin. The value of this attribute should be meaningful to the plugin. Barbican does not use this value.
- algorithm¶
String attribute used to identify the encryption algorithm used by the plugin. e.g. “AES”, “3DES”, etc. This value should be meaningful to the plugin. Barbican does not use this value.
- mode¶
String attribute used to identify the algorithm mode used by the plugin. e.g. “CBC”, “GCM”, etc. This value should be meaningful to the plugin. Barbican does not use this value.
- bit_length¶
Integer attribute used to identify the bit length of the KEK by the plugin. This value should be meaningful to the plugin. Barbican does not use this value.
- plugin_meta¶
String attribute used to persist any additional metadata that does not fit in any other attribute. The value of this attribute is defined by the plugin. It could be used to store external system references, such as Key IDs in an HSM, URIs to an external service, or any other data that the plugin deems necessary to persist. Because this is just a plain text field, a plug in may even choose to persist data such as key value pairs in a JSON object.
- class barbican.plugin.crypto.base.EncryptDTO(unencrypted)¶
Secret Encryption DTO
Data Transfer Object used to pass all the necessary data for the plugin to perform encryption of a secret.
Currently, this DTO only contains the raw bytes to be encrypted by the plugin, but in the future this may contain more information.
- unencrypted¶
The secret data in Bytes to be encrypted by the plugin.
- class barbican.plugin.crypto.base.DecryptDTO(encrypted)¶
Secret Decryption DTO
Data Transfer Object used to pass all the necessary data for the plugin to perform decryption of a secret.
Currently, this DTO only contains the data produced by the plugin during encryption, but in the future this DTO will contain more information, such as a transport key for secret wrapping back to the client.
- encrypted¶
The data that was produced by the plugin during encryption. For some plugins this will be the actual bytes that need to be decrypted to produce the secret. In other implementations, this may just be a reference to some external system that can produce the unencrypted secret.
- class barbican.plugin.crypto.base.GenerateDTO(algorithm, bit_length, mode, passphrase=None)¶
Secret Generation DTO
Data Transfer Object used to pass all the necessary data for the plugin to generate a secret on behalf of the user.
- generation_type¶
String attribute used to identify the type of secret that should be generated. This will be either
"symmetric"
or"asymmetric"
.
- algorithm¶
String attribute used to specify what type of algorithm the secret will be used for. e.g.
"AES"
for a"symmetric"
type, or"RSA"
for"asymmetric"
.
- mode¶
String attribute used to specify what algorithm mode the secret will be used for. e.g.
"CBC"
for"AES"
algorithm.
- bit_length¶
Integer attribute used to specify the bit length of the secret. For example, this attribute could specify the key length for an encryption key to be used in AES-CBC.
- class barbican.plugin.crypto.base.ResponseDTO(cypher_text, kek_meta_extended=None)¶
Data transfer object for secret generation response.
Barbican guarantees that both the
cypher_text
andkek_metadata_extended
will be persisted and then given back to the plugin when requesting a decryption operation.kek_metadata_extended
takes the idea of Key Encryption Key (KEK) metadata further by giving plugins the option to store secret-level KEK metadata. One example of using secret-level KEK metadata would be plugins that want to use a unique KEK for every secret that is encrypted. Such a plugin could usekek_metadata_extended
to store the Key ID for the KEK used to encrypt this particular secret.- Parameters:
cypher_text – Byte data resulting from the encryption of the secret data.
kek_meta_extended – Optional String object to be persisted alongside the cyphertext.
Plugin Base Class¶
Barbican cryptographic plugins should implement the abstract base class
CryptoPluginBase
. Concrete implementations of this class should be exposed
to barbican using stevedore
mechanisms explained in the configuration
portion of this guide.
- class barbican.plugin.crypto.base.CryptoPluginBase¶
Base class for all Crypto plugins.
Barbican requests operations by invoking the methods on an instance of the implementing class. Barbican’s plugin manager handles the life-cycle of the Data Transfer Objects (DTOs) that are passed into these methods, and persist the data that is assigned to these DTOs by the plugin.
- abstract bind_kek_metadata(kek_meta_dto)¶
Key Encryption Key Metadata binding function
Bind a key encryption key (KEK) metadata to the sub-system handling encryption/decryption, updating information about the key encryption key (KEK) metadata in the supplied ‘kek_metadata’ data-transfer-object instance, and then returning this instance.
This method is invoked prior to the encrypt() method above. Implementors should fill out the supplied ‘kek_meta_dto’ instance (an instance of KEKMetadata above) as needed to completely describe the kek metadata and to complete the binding process. Barbican will persist the contents of this instance once this method returns.
- Parameters:
kek_meta_dto – Key encryption key metadata to bind, with the ‘kek_label’ attribute guaranteed to be unique, and the and ‘plugin_name’ attribute already configured.
- Returns:
kek_meta_dto: Returns the specified DTO, after modifications.
- abstract decrypt(decrypt_dto, kek_meta_dto, kek_meta_extended, project_id)¶
Decrypt encrypted_datum in the context of the provided project.
- Parameters:
decrypt_dto – data transfer object containing the cyphertext to be decrypted.
kek_meta_dto – Key encryption key metadata to use for decryption
kek_meta_extended – Optional per-secret KEK metadata to use for decryption.
project_id – Project ID associated with the encrypted datum.
- Returns:
str – unencrypted byte data
- abstract encrypt(encrypt_dto, kek_meta_dto, project_id)¶
Encryption handler function
This method will be called by Barbican when requesting an encryption operation on a secret on behalf of a project.
- Parameters:
encrypt_dto (
EncryptDTO
) –EncryptDTO
instance containing the raw secret byte data to be encrypted.kek_meta_dto (
KEKMetaDTO
) –KEKMetaDTO
instance containing information about the project’s Key Encryption Key (KEK) to be used for encryption. Plugins may assume that binding viabind_kek_metadata()
has already taken place before this instance is passed in.project_id – Project ID associated with the unencrypted data.
- Returns:
A response DTO containing the cyphertext and KEK information.
- Return type:
- abstract generate_asymmetric(generate_dto, kek_meta_dto, project_id)¶
Create a new asymmetric key.
- Parameters:
generate_dto – data transfer object for the record associated with this generation request. Some relevant parameters can be extracted from this object, including bit_length, algorithm and passphrase
kek_meta_dto – Key encryption key metadata to use for decryption
project_id – Project ID associated with the data.
- Returns:
A tuple containing objects for private_key, public_key and optionally one for passphrase. The objects will be of type ResponseDTO. Each object containing encrypted data and kek_meta_extended, the former the resultant cypher text, the latter being optional per-secret metadata needed to decrypt (over and above the per-project metadata managed outside of the plugins)
- abstract generate_symmetric(generate_dto, kek_meta_dto, project_id)¶
Generate a new key.
- Parameters:
generate_dto – data transfer object for the record associated with this generation request. Some relevant parameters can be extracted from this object, including bit_length, algorithm and mode
kek_meta_dto – Key encryption key metadata to use for decryption
project_id – Project ID associated with the data.
- Returns:
An object of type ResponseDTO containing encrypted data and kek_meta_extended, the former the resultant cypher text, the latter being optional per-secret metadata needed to decrypt (over and above the per-project metadata managed outside of the plugins)
- abstract get_plugin_name()¶
Gets user friendly plugin name.
This plugin name is expected to be read from config file. There will be a default defined for plugin name which can be customized in specific deployment if needed.
This name needs to be unique across a deployment.
- abstract supports(type_enum, algorithm=None, bit_length=None, mode=None)¶
Used to determine if the plugin supports the requested operation.
- Parameters:
type_enum – Enumeration from PluginSupportsType class
algorithm – String algorithm name if needed
Barbican Core Plugin Sequence¶
Barbican invokes a different sequence of methods on the CryptoPluginBase
plugin depending on the requested action. Note that these actions are invoked
via the secret store adapter class StoreCryptoAdapterPlugin
which is further
described in The Cryptographic Plugin Adapter.
For secret storage actions, Barbican core calls the following methods:
supports()
- Asks the plugin if it can support thebarbican.plugin.crypto.base.PluginSupportTypes.ENCRYPT_DECRYPT
operation type.bind_kek_metadata()
- Allows a plugin to bind an internal key encryption key (KEK) to a project-ID, typically as a ‘label’ or reference to the actual KEK stored within the cryptographic appliance. This KEK information is stored into Barbican’s data store on behalf of the plugin, and then provided back to the plugin for subsequent calls.encrypt()
- Asks the plugin to perform encryption of an unencrypted secret payload, utilizing the KEK bound to the project-ID above. Barbican core will then persist the encrypted data returned from this method for later retrieval. The name of the plugin used to perform this encryption is also persisted into Barbican core, to ensure we decrypt this secret only with this plugin.
For secret decryptions and retrievals, Barbican core will select the same
plugin as was used to store the secret, and then invoke its decrypt()
method, providing it both the previously-persisted encrypted secret data as well
as the project-ID KEK used to encrypt the secret.
For symmetric key generation, Barbican core calls the following methods:
supports()
- Asks the plugin if it can support thebarbican.plugin.crypto.base.PluginSupportTypes.SYMMETRIC_KEY_GENERATION
operation type.bind_kek_metadata()
- Same comments as for secret storage above.generate_symmetric()
- Asks the plugin to both generate a symmetric key, and then encrypted it with the project-ID KEK. Barbican core persists this newly generated and encrypted secret similar to secret storage above.
For asymmetric key generation, Barbican core calls the following methods:
supports()
- Asks the plugin if it can support thebarbican.plugin.crypto.base.PluginSupportTypes.ASYMMETRIC_KEY_GENERATION
operation type.bind_kek_metadata()
- Same comments as for secret storage above.generate_asymmetric()
- Asks the plugin to generate and encrypt asymmetric public and private key (and optional passphrase) information, which Barbican core will persist as a container of separate encrypted secrets.