mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-17 15:38:14 +08:00
163 lines
4.2 KiB
C
163 lines
4.2 KiB
C
/*
|
|
* Copyright (C) 2008-2014, Marvell International Ltd.
|
|
* All Rights Reserved.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <secure_boot2.h>
|
|
#include <secure_boot.h>
|
|
#include <cyassl/ctaocrypt/rsa.h>
|
|
#include <cyassl/ctaocrypt/aes.h>
|
|
#include <cyassl/ctaocrypt/sha256.h>
|
|
#include <boot2.h>
|
|
#include <aes.h>
|
|
#include <secure_boot.h>
|
|
|
|
#define RSA_SIGN_LEN 256
|
|
|
|
static Sha256 sha;
|
|
static RsaKey key;
|
|
static aes_t dec;
|
|
static uint8_t sig[RSA_SIGN_LEN];
|
|
static uint8_t hash[SHA256_DIGEST_SIZE];
|
|
static uint8_t nonce[AES_BLOCK_SIZE];
|
|
|
|
static secure_boot_struct_t priv_data;
|
|
|
|
/* Initialize the AES CTR context */
|
|
static void aes_ctr_init(void *context, void *key, uint32_t key_len,
|
|
void *iv)
|
|
{
|
|
aes_drv_setkey(NULL, context, key, key_len, iv, AES_DECRYPTION,
|
|
HW_AES_MODE_CTR);
|
|
}
|
|
|
|
/* This function needs to be defined to match the signature of decrypt_func_t
|
|
* Use appropriate decryption function in it.
|
|
*/
|
|
static int aes_ctr_decrypt(void *context, void *inbuf,
|
|
void *outbuf, uint32_t len)
|
|
{
|
|
return aes_drv_decrypt(NULL, context, inbuf, outbuf, len);
|
|
}
|
|
|
|
/* RSA verification callback */
|
|
static int rsassl_verify(void *message, int len, void *pk, void *signature)
|
|
{
|
|
int ret;
|
|
uint8_t hashDecrypt[SHA256_DIGEST_SIZE];
|
|
|
|
ret = RsaSSL_Verify(signature, RSA_SIGN_LEN, hashDecrypt,
|
|
sizeof(hashDecrypt), pk);
|
|
if (ret < 0) {
|
|
dbg("Err...RSA verification failure: %d\n", ret);
|
|
return -1;
|
|
}
|
|
|
|
/* Compare if the hash of the decrypted firmware image matches
|
|
* with hash derived from Signature */
|
|
if (memcmp(message, hashDecrypt, sizeof(hashDecrypt)))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sha256 hash update callback */
|
|
static void sha256_update(void *context, void *buf, int len)
|
|
{
|
|
Sha256Update(context, buf, len);
|
|
}
|
|
|
|
/* Sha256 has finish callback */
|
|
static void sha256_finish(void *context, void *result)
|
|
{
|
|
Sha256Final(context, result);
|
|
}
|
|
|
|
extern unsigned long _rom_data_start, _rom_data_size;
|
|
static void secure_boot_init()
|
|
{
|
|
memset(&_rom_data_start, 0, (unsigned) &_rom_data_size);
|
|
ROM_prvHeapInit((unsigned char *)&_heap_start,
|
|
(unsigned char *)&_heap_end);
|
|
CyaSSL_SetAllocators((CyaSSL_Malloc_cb)
|
|
((uint32_t) ROM_pvPortMalloc | 0x1),
|
|
(CyaSSL_Free_cb)
|
|
((uint32_t) ROM_vPortFree | 0x1),
|
|
(CyaSSL_Realloc_cb)
|
|
((uint32_t) ROM_pvPortReAlloc | 0x1));
|
|
aes_drv_init();
|
|
}
|
|
|
|
/* This function will initialize the encryption and hashing
|
|
* context appropriately by fetching the required data.
|
|
*/
|
|
int secure_boot_firmware(secure_boot_init_t *sb, secure_boot_struct_t **priv)
|
|
{
|
|
int ret = 0;
|
|
word32 idx = 0;
|
|
|
|
/* Initialize ROM libs and AES hardware engine */
|
|
secure_boot_init();
|
|
|
|
if (sb->sign_algo == RSA_SIGN) {
|
|
priv_data.signature_verify = rsassl_verify;
|
|
priv_data.signature = sig;
|
|
priv_data.signature_len = sb->digital_sig->len;
|
|
priv_data.pk = &key;
|
|
InitRsaKey(&key, 0);
|
|
ret = RsaPublicKeyDecode(sb->public_key->value, &idx, &key,
|
|
sb->public_key->len);
|
|
if (ret != 0) {
|
|
dbg("RSA Public key decode error:%d", ret);
|
|
FreeRsaKey(&key);
|
|
return -1;
|
|
}
|
|
memcpy(priv_data.signature, sb->digital_sig->value,
|
|
priv_data.signature_len > RSA_SIGN_LEN ?
|
|
RSA_SIGN_LEN : priv_data.signature_len);
|
|
if (sb->hash_algo == SHA256_HASH) {
|
|
priv_data.hash_update = sha256_update;
|
|
priv_data.hash_finish = sha256_finish;
|
|
priv_data.hash_ctx = &sha;
|
|
priv_data.hash = hash;
|
|
priv_data.hash_len = SHA256_DIGEST_SIZE;
|
|
InitSha256(&sha);
|
|
}
|
|
priv_data.bytes_to_read = sb->fw_img_len;
|
|
}
|
|
|
|
/* AES-CTR algorithm init */
|
|
if (sb->encrypt_algo == AES_CTR_128_ENCRYPT) {
|
|
priv_data.decrypt_init = aes_ctr_init;
|
|
priv_data.decrypt = aes_ctr_decrypt;
|
|
priv_data.decrypt_ctx = &dec;
|
|
priv_data.iv = nonce;
|
|
priv_data.iv_len = sb->nonce->len;
|
|
priv_data.decrypt_key_len = sb->decrypt_key->len;
|
|
priv_data.decrypt_key = sb->decrypt_key->value;
|
|
memcpy(priv_data.iv, sb->nonce->value,
|
|
priv_data.iv_len > AES_BLOCK_SIZE ?
|
|
AES_BLOCK_SIZE : priv_data.iv_len);
|
|
|
|
/* Initialize decryption hardware engine */
|
|
priv_data.decrypt_init(priv_data.decrypt_ctx,
|
|
priv_data.decrypt_key,
|
|
priv_data.decrypt_key_len,
|
|
priv_data.iv);
|
|
}
|
|
|
|
if (priv)
|
|
*priv = &priv_data;
|
|
|
|
return ret;
|
|
}
|
|
|
|
void secure_boot_cleanup(secure_boot_struct_t *priv)
|
|
{
|
|
if (priv && priv->pk)
|
|
FreeRsaKey(priv->pk);
|
|
}
|