blob: 10273e52f5a7a1f9faeb38db9f4712662134e7d6 [file] [log] [blame]
#include "OtaTlvEncryptionKey.h"
#include <lib/support/CodeUtils.h>
#include <platform/silabs/SilabsConfig.h>
#include <sl_psa_crypto.h>
#include <stdio.h>
#include <string.h>
namespace chip {
namespace DeviceLayer {
namespace Silabs {
namespace OtaTlvEncryptionKey {
using SilabsConfig = chip::DeviceLayer::Internal::SilabsConfig;
int destroyAESKey(uint32_t kid)
{
psa_key_handle_t key_handle;
int err = psa_open_key(kid, &key_handle);
if (err)
{
psa_close_key(kid);
}
else
{
err = psa_destroy_key(kid);
}
return err;
}
CHIP_ERROR OtaTlvEncryptionKey::Import(const uint8_t * key, size_t key_len)
{
destroyAESKey(mId);
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
psa_key_id_t key_id;
psa_set_key_id(&attributes, mId);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
status = psa_import_key(&attributes, key, key_len, &key_id);
if (status != PSA_SUCCESS)
{
printf("Failed to import a key error:%ld\n", status);
return CHIP_ERROR_INTERNAL;
}
return CHIP_NO_ERROR;
}
CHIP_ERROR OtaTlvEncryptionKey::Decrypt(MutableByteSpan & block, uint32_t & mIVOffset)
{
constexpr uint8_t au8Iv[] = { 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x00, 0x00, 0x00 };
uint8_t iv[16];
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_status_t status;
uint8_t output[PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES)];
size_t output_len;
size_t total_output;
uint32_t u32IVCount;
uint32_t Offset = 0;
memcpy(iv, au8Iv, sizeof(au8Iv));
u32IVCount = (((uint32_t) iv[12]) << 24) | (((uint32_t) iv[13]) << 16) | (((uint32_t) iv[14]) << 8) | (iv[15]);
u32IVCount += (mIVOffset >> 4);
iv[12] = (uint8_t) ((u32IVCount >> 24) & 0xff);
iv[13] = (uint8_t) ((u32IVCount >> 16) & 0xff);
iv[14] = (uint8_t) ((u32IVCount >> 8) & 0xff);
iv[15] = (uint8_t) (u32IVCount & 0xff);
while (Offset + 16 <= block.size())
{
status = psa_cipher_decrypt_setup(&operation, static_cast<psa_key_id_t>(mId), PSA_ALG_CTR);
if (status != PSA_SUCCESS)
{
printf("Failed to begin cipher operation error:%ld\n", status);
return CHIP_ERROR_INTERNAL;
}
status = psa_cipher_set_iv(&operation, iv, sizeof(iv));
if (status != PSA_SUCCESS)
{
printf("Failed to set IV error:%ld\n", status);
return CHIP_ERROR_INTERNAL;
}
status = psa_cipher_update(&operation, static_cast<uint8_t *>(&block[Offset]), 16, output, sizeof(output), &output_len);
if (status != PSA_SUCCESS)
{
printf("Failed to update cipher operation error:%ld\n", status);
return CHIP_ERROR_INTERNAL;
}
/* increment the IV for the next block */
u32IVCount++;
iv[12] = (uint8_t) ((u32IVCount >> 24) & 0xff);
iv[13] = (uint8_t) ((u32IVCount >> 16) & 0xff);
iv[14] = (uint8_t) ((u32IVCount >> 8) & 0xff);
iv[15] = (uint8_t) (u32IVCount & 0xff);
memcpy((void *) &block[Offset], &output, output_len);
Offset += 16; /* increment the buffer offset */
mIVOffset += 16;
status = psa_cipher_finish(&operation, output + total_output, sizeof(output) - total_output, &total_output);
if (status != PSA_SUCCESS)
{
printf("Failed to finish cipher operation\n");
return CHIP_ERROR_INTERNAL;
}
}
printf("Decrypted ciphertext\n");
psa_cipher_abort(&operation);
return CHIP_NO_ERROR;
}
} // namespace OtaTlvEncryptionKey
} // namespace Silabs
} // namespace DeviceLayer
} // namespace chip