in src/derivation/ecdh.c [126:280]
CK_RV aes_gcm_sample(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR aes_key) {
CK_RV rv;
CK_BYTE_PTR plaintext = "plaintext payload to encrypt";
CK_ULONG plaintext_length = (CK_ULONG) strlen(plaintext);
CK_ULONG ciphertext_length = 0;
CK_BYTE_PTR aad = "plaintext aad";
CK_ULONG aad_length = (CK_ULONG) strlen(aad);
CK_BYTE_PTR decrypted_ciphertext = NULL;
CK_BYTE_PTR ciphertext = NULL;
printf("Plaintext: %s\n", plaintext);
printf("Plaintext length: %lu\n", plaintext_length);
printf("AAD: %s\n", aad);
printf("AAD length: %lu\n", aad_length);
// Prepare the mechanism
CK_MECHANISM mech;
CK_GCM_PARAMS params;
// Allocate memory to hold the HSM generated IV.
CK_BYTE_PTR iv = malloc(AES_GCM_IV_SIZE);
rv = 1;
if (NULL == iv) {
fprintf(stderr, "Failed to allocate IV memory\n");
goto done;
}
memset(iv, 0, AES_GCM_IV_SIZE);
// Setup the mechanism with the IV location and AAD information.
params.pIv = iv;
params.ulIvLen = AES_GCM_IV_SIZE;
params.ulIvBits = 0;
params.pAAD = aad;
params.ulAADLen = aad_length;
params.ulTagBits = AES_GCM_TAG_SIZE * 8;
mech.mechanism = CKM_AES_GCM;
mech.ulParameterLen = sizeof(params);
mech.pParameter = ¶ms;
//**********************************************************************************************
// Encrypt
//**********************************************************************************************
rv = funcs->C_EncryptInit(session, &mech, *aes_key);
if (CKR_OK != rv) {
fprintf(stderr, "Encryption Init failed: %lu\n", rv);
goto done;
}
// Determine how much memory is required to store the ciphertext.
rv = funcs->C_Encrypt(session, plaintext, plaintext_length, NULL, &ciphertext_length);
// The ciphertext will be prepended with the HSM generated IV
// so the length must include the IV
ciphertext_length += AES_GCM_IV_SIZE;
if (CKR_OK != rv) {
fprintf(stderr, "Failed to find GCM ciphertext length\n");
goto done;
}
// Allocate memory to store the ciphertext.
ciphertext = malloc(ciphertext_length);
if (NULL == ciphertext) {
rv = 1;
fprintf(stderr, "Failed to allocate ciphertext memory\n");
goto done;
}
memset(ciphertext, 0, ciphertext_length);
// Encrypt the data.
rv = funcs->C_Encrypt(session, plaintext, plaintext_length, ciphertext + AES_GCM_IV_SIZE, &ciphertext_length);
// Prepend HSM generated IV to ciphertext buffer
memcpy(ciphertext, iv, AES_GCM_IV_SIZE);
ciphertext_length += AES_GCM_IV_SIZE;
if (CKR_OK != rv) {
fprintf(stderr, "Encryption failed: %lu\n", rv);
goto done;
}
// Ciphertext buffer = IV || ciphertext || TAG
// Print the HSM generated IV
printf("IV: ");
print_bytes_as_hex(ciphertext, AES_GCM_IV_SIZE);
printf("IV length: %d\n", AES_GCM_IV_SIZE);
// Print just the ciphertext in hex format
printf("Ciphertext: ");
print_bytes_as_hex(ciphertext + AES_GCM_IV_SIZE, ciphertext_length - AES_GCM_IV_SIZE - AES_GCM_TAG_SIZE);
printf("Ciphertext length: %lu\n", ciphertext_length - AES_GCM_IV_SIZE - AES_GCM_TAG_SIZE);
// Print TAG in hex format
printf("Tag: ");
print_bytes_as_hex(ciphertext + AES_GCM_IV_SIZE + plaintext_length, ciphertext_length - AES_GCM_IV_SIZE - plaintext_length);
printf("Tag length: %lu\n", ciphertext_length - AES_GCM_IV_SIZE - plaintext_length);
//**********************************************************************************************
// Decrypt
//**********************************************************************************************
// Use the IV that was prepended -- The first AES_GCM_IV_SIZE bytes of the ciphertext.
params.pIv = ciphertext;
mech.ulParameterLen = sizeof(params);
mech.pParameter = ¶ms;
rv = funcs->C_DecryptInit(session, &mech, *aes_key);
if (CKR_OK != rv) {
fprintf(stderr, "Decryption Init failed: %lu\n", rv);
goto done;
}
// Determine the length of decrypted ciphertext.
CK_ULONG decrypted_ciphertext_length = 0;
rv = funcs->C_Decrypt(session, ciphertext + AES_GCM_IV_SIZE, ciphertext_length - AES_GCM_IV_SIZE,
NULL, &decrypted_ciphertext_length);
if (CKR_OK != rv) {
fprintf(stderr, "Decryption failed: %lu\n", rv);
goto done;
}
// Allocate memory for the decrypted cipher text.
decrypted_ciphertext = malloc(decrypted_ciphertext_length);
if (NULL == decrypted_ciphertext) {
rv = 1;
fprintf(stderr, "Could not allocate memory for decrypted ciphertext\n");
goto done;
}
// Decrypt the ciphertext.
rv = funcs->C_Decrypt(session, ciphertext + AES_GCM_IV_SIZE, ciphertext_length - AES_GCM_IV_SIZE,
decrypted_ciphertext, &decrypted_ciphertext_length);
if (CKR_OK != rv) {
fprintf(stderr, "Decryption failed: %lu\n", rv);
goto done;
}
printf("Decrypted ciphertext: %.*s\n", (int)decrypted_ciphertext_length, decrypted_ciphertext);
printf("Decrypted ciphertext length: %lu\n", decrypted_ciphertext_length);
done:
if (NULL != iv) {
free(iv);
}
if (NULL != ciphertext) {
free(ciphertext);
}
if (NULL != decrypted_ciphertext) {
free(decrypted_ciphertext);
}
return rv;
}