file/file_encrypt/encrypt.c

/*******************************************************************************
* # License
* Copyright 2019 Silicon Laboratories Inc. www.silabs.com
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#include "crypto.h"
/*************************************************************************************************
* Encrypt buffer with supplied AES-128 key and write to file
*/
gos_result_t encrypt_buffer_to_file(const uint8_t *key, uint8_t *buffer, uint32_t buffer_length, const char *encrypted_filename)
{
gos_handle_t handle;
gos_result_t result;
uint8_t mac[MAC_SIZE];
gos_aes128_iv_t init_iv;
crypt_context_t context;
int32_t remaining_bytes;
// Initialize the AES context with the supplied key
gos_aes_setkey_enc(&context.aes, key, AES128_BLOCK_BITS);
// Generate random initialization vector (IV)
gos_get_random_buffer(init_iv.buf, IV_SIZE);
memcpy(context.iv.buf, init_iv.buf, IV_SIZE);
gos_dump_buffer(init_iv.buf, IV_SIZE, "IV", GOS_DUMP_FLAGS(16, 1, LITTLE, ADD_SPACE, NO_ADDRESSES, NO_ASCII ));
// Calculate the file's MAC
calculate_mac(key, buffer, buffer_length, mac);
gos_dump_buffer(mac, MAC_SIZE, "MAC", GOS_DUMP_FLAGS(16, 1, LITTLE, ADD_SPACE, NO_ADDRESSES, NO_ASCII ));
// Create the output file
// Notes:
// * The encrypted file is 32 bytes longer to store the IV and MAC
// * The GOS_FILE_OWNER_USER owner types indicates that the file is encrypted with the 'user key'
// * The GOS_FILE_FLAG_PRE_ENCRYPTED flag indicates that the file is encrypted
// * The GOS_FILE_FLAG_PRE_ENCRYPTED flag indicates that the file is pre-encrypted (i.e. Gecko OS will NOT encrypt the file as it's written)
file.size = sizeof(init_iv) + sizeof(mac) + buffer_length;
strcpy(file.name, encrypted_filename);
// Delete the file if it already exists
gos_file_delete(encrypted_filename, GOS_FILE_LOCATION_ANY);
// Create the file
if (GOS_FAILED(result, gos_file_create(&file, &handle)))
{
GOS_LOG("Failed to create file: %d", result);
return result;
}
// Write the initial IV
if (GOS_FAILED(result, gos_file_write(handle, init_iv.buf, sizeof(init_iv))))
{
GOS_LOG("Failed to write IV: %d", result);
return result;
}
// Encrypt the MAC and write to the file
encrypt_block(&context, mac);
if (GOS_FAILED(result, gos_file_write(handle, mac, sizeof(mac))))
{
GOS_LOG("Failed to write MAC: %d", result);
return result;
}
// Encrypt the input file data AES128_BLOCK_SIZE bytes at a time and write to the output file
uint8_t *file_ptr = buffer;
remaining_bytes = buffer_length;
while (remaining_bytes > 0)
{
encrypt_block(&context, file_ptr);
if (GOS_FAILED(result, gos_file_write(handle, file_ptr, MIN(remaining_bytes, AES128_BLOCK_SIZE))))
{
GOS_LOG("Failed to write encrypted data: %d", result);
return result;
}
remaining_bytes -= AES128_BLOCK_SIZE;
file_ptr += AES128_BLOCK_SIZE;
}
gos_file_close(handle);
return GOS_SUCCESS;
}