file/log_file_encrypted/crypto_utils.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"
/*************************************************************************************************/
void calculate_mac(const uint8_t *key, const uint8_t *buffer, uint32_t buffer_length, uint8_t *mac)
{
crypt_context_t context;
uint8_t tmp_buffer[AES128_BLOCK_SIZE];
const gos_buffer_t inbuf =
{
.data = tmp_buffer,
.size = sizeof(tmp_buffer)
};
gos_buffer_t outbuf =
{
.data = mac,
.size = AES128_BLOCK_SIZE
};
// Initialize AES context with key
gos_aes_setkey_enc(&context.aes, key, AES128_BLOCK_BITS);
// Set the IV to 0
memset(context.iv.buf, 0, AES128_BLOCK_SIZE);
// Process the file block by block
const uint8_t *buffer_ptr = buffer;
for (int remaining = buffer_length; remaining > 0; )
{
// We 0-pad the end of the buffer if the file data isn't 16 byte aligned
memset(tmp_buffer, 0, AES128_BLOCK_SIZE);
// Processing a 16 byte block or the remainder of the file
memcpy(tmp_buffer, buffer_ptr, MIN(remaining, AES128_BLOCK_SIZE));
// Calculate the CBC of this block of the file data, the output goes in the supplied hmac buffer
gos_aes_encrypt_cbc(&context.aes, context.iv.buf, &inbuf, &outbuf);
remaining -= AES128_BLOCK_SIZE;
buffer_ptr += AES128_BLOCK_SIZE;
}
// The last calculated CBC of the file data is the HMAC,
// The supplied hmac buffer now contains the HMAC of the file
}
/*************************************************************************************************/
void encrypt_buffer(crypt_context_t *context, uint8_t *ptr, int32_t size)
{
while (size > 0)
{
if (size >= AES128_BLOCK_SIZE)
{
encrypt_block(context, ptr);
}
else
{
encrypt_unaligned_block(context, ptr, (uint8_t)size);
}
ptr += AES128_BLOCK_SIZE;
size -= AES128_BLOCK_SIZE;
}
}
/*************************************************************************************************/
void encrypt_block(crypt_context_t *context, uint8_t *ptr)
{
uint8_t ctr_key[AES128_BLOCK_SIZE];
uint32_t *ctr_key_ptr = (uint32_t*)ctr_key;
uint32_t *data_ptr = (uint32_t*)ptr;
// Set up next CTR key.
memcpy(ctr_key, context->iv.buf, AES128_BLOCK_SIZE);
gos_aes_encrypt_ecb(&context->aes, ctr_key, ctr_key);
context->iv.iv.counter = __REV(__REV(context->iv.iv.counter) + 1);
// Encrypt CTR block.
data_ptr[0] ^= ctr_key_ptr[0];
data_ptr[1] ^= ctr_key_ptr[1];
data_ptr[2] ^= ctr_key_ptr[2];
data_ptr[3] ^= ctr_key_ptr[3];
}
/*************************************************************************************************/
void encrypt_unaligned_block(crypt_context_t *context, uint8_t *ptr, uint8_t size)
{
uint8_t ctr_key[AES128_BLOCK_SIZE];
uint8_t *ctr_key_ptr = (uint8_t*)ctr_key;
// Set up next CTR key.
memcpy(ctr_key, context->iv.buf, AES128_BLOCK_SIZE);
gos_aes_encrypt_ecb(&context->aes, ctr_key, ctr_key);
context->iv.iv.counter = __REV(__REV(context->iv.iv.counter) + 1);
// Encrypt CTR block.
while (size-- > 0)
{
*ptr++ ^= *ctr_key_ptr++;
}
}