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;