Sample programs using libzpc
View some sample applications using some of the most important libzpc APIs. They also illustrate the techniques how to apply these APIs.
Generating a CCA AES DATA key
This sample generates a secure key/protected key pair from a common effective key, where a new protected key is automatically re-derived from the secure key when required, for example, after a reboot of an LPAR, which causes a change of the protected key and thus of the wrapping key verification pattern (WKPV).
/*
* Example: Generate a 256-bit AES key on CCA card 1 on domain 37
* as a CCA data key. Use the key to encrypt a message in multiple
* chunks using AES-GCM.
* Build: cc -Wall -Wextra -pthread -o aes_gcm aes_gcm.c -lzpc -ldl
*/
#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)
{
unsigned char iv[12], aad[99], m[99], tag[12], c[99];
struct zpc_aes_key *aes_key = NULL;
struct zpc_aes_gcm *aes_gcm = NULL;
int rc = -1, rv = -1;
/* Allocate objects. */
rc = zpc_aes_key_alloc(&aes_key);
if (rc) goto ret;
rc = zpc_aes_gcm_alloc(&aes_gcm);
if (rc) goto ret;
/* Setup key object. */
rc = zpc_aes_key_set_type(aes_key, type);
if (rc) goto ret;
rc = zpc_aes_key_set_apqns(aes_key, apqns);
if (rc) goto ret;
rc = zpc_aes_key_set_size(aes_key, size);
if (rc) goto ret;
/* Generate key. */
rc = zpc_aes_key_generate(aes_key);
if (rc) goto ret;
/* Setup context object. */
rc = zpc_aes_gcm_set_key(aes_gcm, aes_key);
if (rc) goto ret;
rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 12);
if (rc) goto ret;
/* Encrypt first chunk. */
rc = zpc_aes_gcm_encrypt(aes_gcm, c, tag, 12, aad, 99, m, 32);
if (rc) goto ret;
/* Encrypt second chunk. */
rc = zpc_aes_gcm_encrypt(aes_gcm, c+32, tag, 12, NULL, 0, m + 32, 99 - 32);
if (rc) goto ret;
rv = 0;
ret:
/* Free objects. */
zpc_aes_gcm_free(&aes_gcm);
zpc_aes_key_free(&aes_key);
printf("%s\n", rv == 0 ? "SUCCESS" : "ERROR");
return rv;
}
Generating a random protected key
This sample generates a protected key only, without a secure key. This protected key becomes unusable, if the WKVP changes.
/*
* Example: Generate a 256-bit AES key as a random protected key.
* Use the key to encrypt a message using AES-GCM.
* Build: cc -Wall -Wextra -pthread -o aes_gcm2 aes_gcm2.c -lzpc -ldl
*/
#include <stdlib.h>
#include <stdio.h>
#include <zpc/aes_key.h>
#include <zpc/aes_gcm.h>
const int size = 256;
int main(void)
{
unsigned char iv[12], aad[99], m[99], tag[12], c[99];
struct zpc_aes_key *aes_key = NULL;
struct zpc_aes_gcm *aes_gcm = NULL;
int rc = -1, rv = -1;
/* Allocate objects. */
rc = zpc_aes_key_alloc(&aes_key);
if (rc) goto ret;
rc = zpc_aes_gcm_alloc(&aes_gcm);
if (rc) goto ret;
/* Setup key object. */
rc = zpc_aes_key_set_size(aes_key, size);
if (rc) goto ret;
/* Generate key. */
rc = zpc_aes_key_generate(aes_key);
if (rc) goto ret;
/* Setup context object. */
rc = zpc_aes_gcm_set_key(aes_gcm, aes_key);
if (rc) goto ret;
rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 12);
if (rc) goto ret;
/* Encrypt. */
rc = zpc_aes_gcm_encrypt(aes_gcm, c, tag, 12, aad, 99, m, 99);
if (rc) goto ret;
rv = 0;
ret:
/* Free objects. */
zpc_aes_gcm_free(&aes_gcm);
zpc_aes_key_free(&aes_key);
printf("%s\n", rv == 0 ? "SUCCESS" : "ERROR");
return rv;
}
Generating an ECC secure key and create and verify a signature
This sample generates an ECC secure key pair of type CCA and uses this key pair to generate and verify a signature for an input hashed data.
/*
* Example: Generate a p256 EC key on CCA card 1 on domain 37
* as a CCA key. Use the key to sign a given message hash and verify
* the created signature afterwards.
* Build: cc -Wall -Wextra -pthread -o ec_test ec_test.c -lzpc -ldl
*/
#include <stdlib.h>
#include <stdio.h>
#include <zpc/ecc_key.h>
#include <zpc/ecdsa_ctx.h>
const int type = ZPC_EC_KEY_TYPE_CCA;
const char *apqns[] = {"01.0037", NULL};
int main(void)
{
unsigned char hash[32], signature[64];
unsigned int hash_len = sizeof(hash);
unsigned int sig_len = sizeof(signature);
struct zpc_ec_key *ec_key = NULL;
struct zpc_ec_ctx *ctx = NULL;
int rc = -1, rv = -1;
/* Allocate objects. */
rc = zpc_ec_key_alloc(&ec_key);
if (rc)
goto ret;
rc = zpc_ecdsa_ctx_alloc(&ctx);
if (rc)
goto ret;
/* Setup key object. */
rc = zpc_ec_key_set_type(ec_key, type);
if (rc)
goto ret;
rc = zpc_ec_key_set_apqns(ec_key, apqns);
if (rc)
goto ret;
rc = zpc_ec_key_set_curve(ec_key, ZPC_EC_CURVE_P256);
if (rc)
goto ret;
/* Generate key. */
rc = zpc_ec_key_generate(ec_key);
if (rc)
goto ret;
/* Setup context object. */
rc = zpc_ecdsa_ctx_set_key(ctx, ec_key);
if (rc)
goto ret;
/* Obtain the length of the signature to be created */
rc = zpc_ecdsa_sign(ctx, hash, hash_len, NULL, &sig_len);
if (rc || sig_len > sizeof(signature))
goto ret;
/* Create the ECDSA signature */
rc = zpc_ecdsa_sign(ctx, hash, hash_len, signature, &sig_len);
if (rc)
goto ret;
/* Verify the ECDSA signature */
rc = zpc_ecdsa_verify(ctx, hash, hash_len, signature, sig_len);
if (rc)
goto ret;
rv = 0;
ret:
/* Free objects. */
zpc_ecdsa_ctx_free(&ctx);
zpc_ec_key_free(&ec_key);
printf("%s\n", rv == 0 ? "SUCCESS" : "ERROR");
return rv;