basic/file_encrypt/decrypt.c

See examples/basic/file_encrypt

/*
* ZentriOS SDK LICENSE AGREEMENT | Zentri.com, 2016.
*
* Use of source code and/or libraries contained in the ZentriOS SDK is
* subject to the Zentri Operating System SDK license agreement and
* applicable open source license agreements.
*
*/
#include "crypto.h"
/*************************************************************************************************/
zos_result_t decrypt_file_to_buffer(const uint8_t *key, const char *filename, uint8_t *buffer, uint32_t buffer_length)
{
uint32_t handle;
zos_result_t result;
uint8_t hmac[16], calculated_hmac[16];
zos_file_t file_info;
// open the encrypted file
if(ZOS_FAILED(result, zn_file_open(filename, &handle)))
{
ZOS_LOG("Failed to open encrypted file: %s", filename);
return result;
}
// retrieve the file's info
else if(ZOS_FAILED(result, zn_file_stat(filename, &file_info)))
{
ZOS_LOG("Failed to get file info: %d", result);
return result;
}
else if(file_info.size <= AES128_BIT_SIZE*2)
{
ZOS_LOG("Encrypted file not long enough, must be at least 33 bytes: %d", result);
}
else if(buffer_length < (file_info.size - AES128_BIT_SIZE*2))
{
ZOS_LOG("Supplied buffer not large enough to hold decrypted data", result);
}
// initialize the AES context with the supplied key
aes_setkey_enc(&context.aes, key, AES128_BIT_SIZE);
// read the IV
if(ZOS_FAILED(result, zn_file_read(handle, context.iv.buffer, sizeof(context.iv.buffer), NULL)))
{
ZOS_LOG("Failed to read IV: %d", result);
return result;
}
zn_dump_buffer(context.iv.buffer, AES128_BLOCK_SIZE, "IV", ZOS_DUMP_FLAGS(16, 1, LITTLE, ADD_SPACE, NO_ADDRESSES, NO_ASCII ));
// the next 16 bytes of the file is the HMAC
// read the encrypted HMAC into the buffer
if(ZOS_FAILED(result, zn_file_read(handle, hmac, sizeof(hmac), NULL)))
{
ZOS_LOG("Failed to read encrypted HMAC: %d", result);
return result;
}
// decrypt the HMAC
decrypt_block(&context, hmac);
zn_dump_buffer(hmac, AES128_BLOCK_SIZE, "HMAC", ZOS_DUMP_FLAGS(16, 1, LITTLE, ADD_SPACE, NO_ADDRESSES, NO_ASCII ));
// read the rest of the file into the buffer
if(ZOS_FAILED(result, zn_file_read(handle, buffer, file_info.size, NULL)))
{
ZOS_LOG("Failed to read encrypted file data into buffer: %d", result);
return result;
}
// Decrypt the buffer AES128_BLOCK_SIZE bytes at a time
uint8_t *buffer_ptr = buffer;
for(int remaining = file_info.size; remaining > 0;)
{
// NOTE: we don't want to overflow the decryption buffer as this will make the final HMAC calculation incorrect
if(remaining >= AES128_BLOCK_SIZE)
{
decrypt_block(&context, buffer_ptr);
}
else
{
decrypt_buffer(&context, buffer_ptr, remaining);
}
remaining -= AES128_BLOCK_SIZE;
buffer_ptr += AES128_BLOCK_SIZE;
}
// Calculate the HMAC of the *decrypted* data
calculate_hmac(key, buffer, buffer_length, calculated_hmac);
if(memcmp(hmac, calculated_hmac, AES128_BLOCK_SIZE) != 0)
{
ZOS_LOG("Failed to verify HMAC");
zn_dump_buffer(calculated_hmac, AES128_BLOCK_SIZE, "Calculated HMAC", ZOS_DUMP_FLAGS(16, 1, LITTLE, ADD_SPACE, NO_ADDRESSES, NO_ASCII ));
}
return ZOS_SUCCESS;
}