Programming with libzpc
This part describes important concepts that you need to know before applying the libzpc APIs in order to avoid errors.
You can use the protected key functions of libzpc for AES cryptography and elliptic curve cryptography (ECC) as follows:
- AES
-
- Encryption/Decryption
- Authenticated encryption with associated data (AEAD)
- Message authentication (MAC)
- AES Full-XTS
-
- Encryption/Decryption
- ECC
-
- ECDSA signature creation and verification
- HMAC
-
- Hash-based message authentication (HMAC)
How to create a protected key for libzpc programming
There are the following methods to generate or retrieve a protected key for quick cryptography depending on the type of cryptography or the environment where you are working:
- When using libzpc for AES cryptography, you can either generate a secure key/protected key pair, where the protected key is derived from a persistent secure key and whose effective key can therefore be automatically re-wrapped with a new firmware wrapping key when the old one is no longer available, for example, because an LPAR has been rebooted in the meanwhile.
- Or you can directly generate a protected key in the CPACF, when you only need it within the lifetime of an LPAR, for example for encrypting swap disks.
Note: However, you cannot directly generate a protected key when performing ECC key APIs. For more information, read Performing ECC cryptographic operations.
#include <stdlib.h>
#include <stdio.h>
#include <zpc/aes_key.h>
#include <zpc/aes_gcm.h>
const int size = 256;
const int type = ZPC_AES_KEY_TYPE_CCA_DATA;
const char *apqns[] = {"01.0037", NULL};
int main(void)
{
/* Allocate objects. */
rc = zpc_aes_key_alloc(&aes_key);
if (rc) goto ret;
/* Setup key object. */
rc = zpc_aes_key_set_type(aes_key, type);
rc = zpc_aes_key_set_apqns(aes_key, apqns);
rc = zpc_aes_key_set_size(aes_key, size);
/* Generate key. */
rc = zpc_aes_key_generate(aes_key);
...
...
In any case, applications include the <zpc/...> header files corresponding to the required APIs and link with -lzp. With the exception of zpc_error_string(), all libzpc functions return either no value or an integer which is either zero (in case of success), or a non-zero error code (in case of failure).
How to obtain a protected key from a retrievable secret
If you work on a KVM SEL guest in a IBM® Secure Execution for Linux® (SEL) environment, you do not generate, but you retrieve a protected key from a secret. At the beginning, you proceed as usual with allocation and setting of type and size, as described in Performing AES cryptographic operations. Be sure to specify the adequate key type: ZPC_AES_KEY_TYPE_PVSECRET.
Then you import the desired secret by specifying this ID. You can find this ID in the output of the pvsecret list command, like for example:
# pvsecret list Total number of secrets: 14 0 Association: 0x7434d54750269e37519fe9a338db05dc5c70a592922d199f1c2765e818efad24 1 PLAIN-TEXT: 0xa116c9ed46d6207734a43317d30fd88f52ac8634c37d904bbf4e41d865f90475 2 AES-128-KEY: 0x8cf9659cdea52a5c9ece7446593becc58a3ac519a14d8d54297ab5a01562b7b9 3 AES-192-KEY: 0x5498c4450db472397b0637f536491d11dbaee860cf47a05c6af822f0787a1aaf 4 AES-256-KEY: 0x7237b089a3fcdbef82404477f1f28e20d66de8c80a7dea00cd10520293eefeff ...
With the help of the 32-byte secret ID to be specified, libzpc can import the underlying protected key which you now can use for your required cryptographic operations by exploiting the available libzpc APIs (encryption/decryption and sign/verify).
libzpc verifies that a secret with the given ID exists in the ultravisor of the KVM SEL guest.
Once, the protected key gets invalid, for example, after a reboot of the KVM SEL guest, libzpc automatically re-retrieves the secret from the ultravisor to obtain a new, valid protected key and continues working with this one. This is transparent for libzpc users.
Steps of the procedure:
The steps for such a processing may comprise instructions similar to ones shown in the subsequent list.
- Allocate a key object and define its properties.
const int type = ZPC_AES_KEY_TYPE_PVSECRET; const int size = 256 rc = zpc_aes_key_alloc(&aes_key); /* allocates new AES key object */ rc = zpc_aes_key_set_type(aes_key, type); /* sets key type to ZPC_AES_KEY_TYPE_PVSECRET */ rc = zpc_aes_key_set_size(aes_key, size); /* sets key size to 128, 192, or 256 bits */ - The application must retrieve a list of retrievable secrets available in the system. The previously mentioned pvsecret list sub-command, which is not part of libzpc, can be used for this purpose.
Note: Running the pvsecret list command requires to run as a
rootuser. However, running libzpc to use retrievable secrets does not requirerootuser access rights. - Use the zpc_aes_key_import() API to obtain the protected key from the retrievable secret identified by the specified ID. In the input_ID parameter, this API receives the 32-byte ID of the desired retrievable secret identified from the list of retrievable secrets. With this information, libzpc obtains the pertaining protected key and stores it in the AES key object (aes_key parameter).
rc = zpc_aes_key_import(aes_key, input_ID, size); - Now the application can use the AES key object for encryption or decryption.
rc = zpc_aes_gcm_alloc(&aes_key); rc = zpc_aes_gcm_encrypt(&aes_key, ...); rc = zpc_aes_gcm_decrypt(&aes_key, ...);In case of a WKVP mismatch, for example, after a live guest relocation, libzpc automatically once more retrieves the protected key from the ultravisor, provided that the respective ID is still available there.
- At the end, the space for the AES key object is freed again.
zpc_aes_key_free(&aes_key);
Here also, the applications include the <zpc/...> header files corresponding to the required APIs and link with -lzp.