in src/encrypt/aes_cbc.c [39:193]
CK_RV aes_cbc_multipart_sample(CK_SESSION_HANDLE session) {
CK_RV rv;
CK_BYTE_PTR decrypted_ciphertext = NULL;
// Generate a 256 bit AES key.
CK_OBJECT_HANDLE aes_key;
rv = generate_aes_key(session, 32, &aes_key);
if (CKR_OK != rv) {
printf("AES key generation failed: %lu\n", rv);
return rv;
}
// Prepare the mechanism
// The IV is hardcoded to all 0x01 bytes for this example.
CK_BYTE iv[16] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
CK_MECHANISM mech = {CKM_AES_CBC_PAD, iv, 16};
//**********************************************************************************************
// Encrypt
//**********************************************************************************************
rv = funcs->C_EncryptInit(session, &mech, aes_key);
if (CKR_OK != rv) {
printf("Encryption Init failed: %lu\n", rv);
return rv;
}
// We will stream several chunks of non block aligned random data to encrypt
size_t max_chunks = 4;
size_t chunk_idx = 0;
// The encrypted chunks will be stored in the ciphertext buffer
CK_BYTE_PTR ciphertext = NULL;
CK_ULONG ciphertext_size = 0;
CK_ULONG encrypted_chunk_size = 0;
// We store the randomly generated plaintext as well, for visual comparison
// 512 will hold enough for this sample.
CK_BYTE plaintext[512] = { };
CK_ULONG plaintext_size = CHUNK_SIZE * max_chunks;
while(chunk_idx < max_chunks) {
CK_BYTE chunk[CHUNK_SIZE] = { };
get_random_data(chunk, CHUNK_SIZE);
memcpy(&plaintext[chunk_idx * CHUNK_SIZE], chunk, CHUNK_SIZE);
chunk_idx += 1;
// Determine how much memory will be required to hold this chunk of ciphertext.
rv = funcs->C_EncryptUpdate(session, chunk, CHUNK_SIZE, NULL, &encrypted_chunk_size);
if (CKR_OK != rv) {
printf("Encryption failed: %lu\n", rv);
goto done;
}
// Increase the ciphertext buffer to hold the new chunk.
CK_BYTE_PTR new_ciphertext = realloc(ciphertext, ciphertext_size + encrypted_chunk_size);
if (NULL == new_ciphertext) {
printf("Could not allocate memory for ciphertext\n");
goto done;
}
ciphertext = new_ciphertext;
// Encrypt the data.
rv = funcs->C_EncryptUpdate(session, chunk, CHUNK_SIZE, &ciphertext[ciphertext_size], &encrypted_chunk_size);
if (CKR_OK != rv) {
printf("Encryption failed: %lu\n", rv);
goto done;
}
ciphertext_size += encrypted_chunk_size;
}
// Calculate the size needed for the final buffer. This could include a block of padding.
rv = funcs->C_EncryptFinal(session, NULL, &encrypted_chunk_size);
if (CKR_OK != rv) {
printf("Encryption failed: %lu\n", rv);
goto done;
}
CK_BYTE_PTR new_ciphertext = realloc(ciphertext, ciphertext_size + encrypted_chunk_size);
if (NULL == new_ciphertext) {
printf("Could not allocate memory for ciphertext\n");
goto done;
}
ciphertext = new_ciphertext;
// Finalize the encryption, including any final padding
rv = funcs->C_EncryptFinal(session, &ciphertext[ciphertext_size], &encrypted_chunk_size);
if (CKR_OK != rv) {
printf("Encryption failed: %lu\n", rv);
goto done;
}
ciphertext_size += encrypted_chunk_size;
printf("Plaintext: ");
print_bytes_as_hex(plaintext, plaintext_size);
printf("Plaintext length: %lu\n", plaintext_size);
// Print just the ciphertext in hex format
printf("Ciphertext: ");
print_bytes_as_hex(ciphertext, ciphertext_size);
printf("Ciphertext length: %lu\n", ciphertext_size);
//**********************************************************************************************
// Decrypt
//**********************************************************************************************
rv = funcs->C_DecryptInit(session, &mech, aes_key);
if (CKR_OK != rv) {
printf("Decryption Init failed: %lu\n", rv);
goto done;
}
// Determine how much memory is required to hold the decrypted text.
CK_ULONG decrypted_ciphertext_length = 0;
rv = funcs->C_Decrypt(session, ciphertext, ciphertext_size, NULL, &decrypted_ciphertext_length);
if (CKR_OK != rv) {
printf("Decryption failed: %lu\n", rv);
goto done;
}
// Allocate memory for the decrypted ciphertext.
printf("Allocating %lu for decryption\n", decrypted_ciphertext_length);
decrypted_ciphertext = malloc(decrypted_ciphertext_length + 1); //We want to null terminate the raw chars later
if (NULL == decrypted_ciphertext) {
rv = 1;
printf("Could not allocate memory for decrypted ciphertext\n");
goto done;
}
// Decrypt the ciphertext.
rv = funcs->C_Decrypt(session, ciphertext, ciphertext_size, decrypted_ciphertext, &decrypted_ciphertext_length);
if (CKR_OK != rv) {
printf("Decryption failed: %lu\n", rv);
goto done;
}
decrypted_ciphertext[decrypted_ciphertext_length] = 0; // Turn the chars into a C-String via null termination
printf("Decrypted ciphertext: ");
print_bytes_as_hex(decrypted_ciphertext, decrypted_ciphertext_length);
printf("Decrypted ciphertext length: %lu\n", decrypted_ciphertext_length);
done:
if (NULL != decrypted_ciphertext) {
free(decrypted_ciphertext);
}
if (NULL != ciphertext) {
free(ciphertext);
}
return rv;
}