1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2025-02-15 00:18:03 +00:00
physwizz 99537be4e2 first
2024-03-11 06:53:12 +11:00

143 lines
3.5 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2011 MediaTek Inc.
*/
#include <linux/types.h>
#include "sec_hal.h"
#include "hacc_mach.h"
#define MOD "MASP"
#define SEC_DEBUG (0)
#define SMSG pr_info
#define DMSG pr_debug
static const unsigned int g_CFG_RANDOM_PATTERN[3][4] = {
{0x2D44BB70, 0xA744D227, 0xD0A9864B, 0x83FFC244},
{0x7EC8266B, 0x43E80FB2, 0x01A6348A, 0x2067F9A0},
{0x54536405, 0xD546A6B1, 0x1CC3EC3A, 0xDE377A83}
};
/******************************************************************************
* HACC HW internal function
******************************************************************************/
void HACC_V3_Init(bool encode, const unsigned int g_AC_CFG[])
{
unsigned int i, j;
const unsigned int *p1;
unsigned int acon_setting;
/* Power On HACC */
masp_hal_secure_algo_init();
/* Configuration */
/* set little endian */
acon_setting = HACC_AES_CHG_BO_OFF;
/* set mode */
acon_setting |= HACC_AES_CBC;
/* type */
acon_setting |= HACC_AES_128;
/* operation */
if (encode)
acon_setting |= HACC_AES_ENC;
else
acon_setting |= HACC_AES_DEC;
/* clear key */
for (i = 0; i < 8; i++)
writel(0, (void *)(HACC_AKEY0 + 4 * i));
/* Generate META Key */
writel(HACC_AES_CHG_BO_OFF | HACC_AES_128 | HACC_AES_CBC | HACC_AES_DEC,
(void *)HACC_ACON);
/* init ACONK
* B2C: bind HUID/HUK to HACC
*/
writel(HACC_AES_BK2C, (void *)HACC_ACONK);
/* enable R2K, so that output data is feedback to key
* by HACC internal algorithm
*/
writel(readl((const void *)HACC_ACONK) | HACC_AES_R2K,
(void *)HACC_ACONK);
/* clear HACC_ASRC/HACC_ACFG/HACC_AOUT */
writel(HACC_AES_CLR, (void *)HACC_ACON2);
/* set cfg */
p1 = &g_AC_CFG[0];
for (i = 0; i < 4; i++)
writel(*(p1 + i), (void *)(HACC_ACFG0 + 4 * i));
/* encrypt fix pattern 3 rounds to generate a pattern from HUID/HUK */
for (i = 0; i < 3; i++) {
/* set fixed pattern into source */
p1 = g_CFG_RANDOM_PATTERN[i];
for (j = 0; j < 4; j++)
writel(*(p1 + j), (void *)(HACC_ASRC0 + 4 * j));
/* start decryption */
writel(HACC_AES_START, (void *)HACC_ACON2);
/* polling ready */
while (0 == (readl((const void *)HACC_ACON2) & HACC_AES_RDY))
;
}
/* clear HACC_ASRC/HACC_ACFG/HACC_AOUT */
writel(HACC_AES_CLR, (void *)HACC_ACON2);
/* set cfg */
p1 = &g_AC_CFG[0];
for (i = 0; i < 4; i++)
writel(*(p1 + i), (void *)(HACC_ACFG0 + 4 * i));
/* set config without R2K */
writel(acon_setting, (void *)HACC_ACON);
writel(0, (void *)HACC_ACONK);
}
void HACC_V3_Run(unsigned int *p_src, unsigned int src_len, unsigned int *p_dst)
{
unsigned int i, j;
/* config src/dst addr and len */
unsigned int len = src_len;
/* fo operation */
for (i = 0; i < len; i += 16, p_src += 4, p_dst += 4) {
/* set fixed pattern into source */
for (j = 0; j < 4; j++)
writel(*(p_src + j), (void *)(HACC_ASRC0 + 4 * j));
/* start encryption */
writel(HACC_AES_START, (void *)HACC_ACON2);
/* polling ready */
while (0 == (readl((const void *)HACC_ACON2) & HACC_AES_RDY))
;
/* read out data */
for (j = 0; j < 4; j++) {
writel(readl((const void *)(HACC_AOUT0 + 4 * j)),
(void *)(p_dst + j));
}
}
}
void HACC_V3_Terminate(void)
{
unsigned int i;
/* clear HACC_ASRC/HACC_ACFG/HACC_AOUT */
writel(HACC_AES_CLR, (void *)HACC_ACON2);
/* clear key */
for (i = 0; i < 8; i++)
writel(0, (void *)(HACC_AKEY0 + 4 * i));
masp_hal_secure_algo_deinit();
}