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;

Generate an HMAC key and use it to sign and verify a message

This sample generates an HMAC key as a random protected key. This key is then used to sign and verify a message using HMAC with the SHA-256 hashing algorithm.



/*
* Example: Generate a 512-bit HMAC key as a random protected key.
* Use the key to sign and verify a message using HMAC(SHA-256).
* Build: cc -Wall -Wextra -pthread -o hmac_sha256 hmac_sha256.c -lzpc
*/
#include <stdio.h>
#include <zpc/hmac_key.h>
#include <zpc/hmac.h>

int main(void)
{
    const unsigned char *msg = (unsigned char *)"Protected-key HMAC example";
    struct zpc_hmac_key *hmac_key = NULL;
    struct zpc_hmac *hmac = NULL;
    unsigned char mac[32];
    int rc = -1, rv = -1;

    /* Allocate objects. */
    rc = zpc_hmac_key_alloc(&hmac_key);
    if (rc) goto ret;
    rc = zpc_hmac_alloc(&hmac);
    if (rc) goto ret;

    /* Setup key object. */
    rc = zpc_hmac_key_set_hash_function(hmac_key, ZPC_HMAC_HASHFUNC_SHA_256);
    if (rc) goto ret;

    /* Generate key. */
    rc = zpc_hmac_key_generate(hmac_key);
    if (rc) goto ret;

    /* Setup context object. */
    rc = zpc_hmac_set_key(hmac, hmac_key);
    if (rc) goto ret;

    /* Sign message. */
    rc = zpc_hmac_sign(hmac, mac, 32, msg, sizeof(msg));
    if (rc) goto ret;

    /* Verify message. */
    rc = zpc_hmac_verify(hmac, mac, 32, msg, sizeof(msg));
    if (rc) goto ret;

    rv = 0;
    ret:
    /* Free objects. */
    zpc_hmac_free(&hmac);
    zpc_hmac_key_free(&hmac_key);

    printf("%s\n", rv == 0 ? "SUCCESS" : "ERROR");
    return rv;