blob: c8fc6814600d6cd5b2ebdedebd9c089d000029b1 [file] [log] [blame]
/*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
* *
This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* *
This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* *
You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* *
Description:
*/
/*
* Amlogic AES hardware acceleration
*
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*/
#include <common.h>
#include <asm/hw_aes.h>
#include <asm/arch/secure_apb.h>
static void *aes_block(void *dst, void *src, uint32_t len,uint16_t AEStype,uint8_t CryptMode)
{
//limitation: len < ((128K -1)/2) KB
//block here if len > ((128K - 1) KB ??
struct {
unsigned long lSource;
unsigned long lTarget;
int nLength;
int nBlkFlag;
} arrSteps[2];
int index;
memset(arrSteps, 0, sizeof(arrSteps));
arrSteps[0].lSource = (unsigned long)src;
arrSteps[0].lTarget = (unsigned long)dst;
if (len > 512)
{
arrSteps[0].nLength = len >> 9;
arrSteps[0].nBlkFlag = 1;
arrSteps[1].lSource = arrSteps[0].lSource + (arrSteps[0].nLength << 9);
arrSteps[1].lTarget = arrSteps[0].lTarget + (arrSteps[0].nLength << 9);
arrSteps[1].nLength = len & 0x1FF;
}
else
{
arrSteps[0].nLength = len;
}
dma_dsc_t dsc;
for (index=0; index < sizeof(arrSteps) / sizeof(arrSteps[0]); ++index)
{
dsc.src_addr = arrSteps[index].lSource;
dsc.tgt_addr = arrSteps[index].lTarget;
dsc.dsc_cfg.d32 = 0;
dsc.dsc_cfg.b.length = arrSteps[index].nLength;
dsc.dsc_cfg.b.mode = (AEStype>>6)+6; // 8:aes128 9:aes192 10:aes256
dsc.dsc_cfg.b.op_mode = 1; // cbc
dsc.dsc_cfg.b.enc_sha_only=CryptMode; //1:encrypt 0:decrypt
dsc.dsc_cfg.b.eoc = 1;
dsc.dsc_cfg.b.owner = 1;
dsc.dsc_cfg.b.block = arrSteps[index].nBlkFlag;
*P_DMA_STS0 = 0xf;
*P_DMA_T0 = (uint64_t)&dsc | 2;
while (*P_DMA_STS0 == 0);
}
return dst;
}
int aes_cbc_crypt(uint8_t *key, uint8_t *iv,
uint8_t *ct, uint8_t *pt, uint32_t size, uint16_t AEStype,uint8_t CryptMode)
{
dma_dsc_t dsc[3];
unsigned char dcache_flag=0;
enum aes_ret_t nReturn = AES_RET_SUCCESS;
if (NULL == key || NULL == iv || NULL == ct || NULL == pt)
{
nReturn = AES_RET_ADDR;
goto exit;
}
if (0 == size || (64<<20) <= size || 0 != size%16)
{
nReturn = AES_RET_SIZE;
goto exit;
}
if (128 != AEStype && 192 != AEStype && 256 != AEStype)
{
nReturn = AES_RET_TYPE;
goto exit;
}
if (0 != CryptMode && 1 != CryptMode)
{
nReturn = AES_RET_MODE;
goto exit;
}
if (dcache_status())
{
dcache_disable();
dcache_flag=1;
}
else
{
dcache_flag=0;
}
dsc[0].src_addr = (uint64_t)key;
dsc[0].tgt_addr = 0;
dsc[0].dsc_cfg.d32 = 0;
dsc[0].dsc_cfg.b.length = 16;
dsc[0].dsc_cfg.b.mode = 1; // key
dsc[0].dsc_cfg.b.owner = 1;
dsc[1].src_addr = (uint64_t)(key+16);
dsc[1].tgt_addr = 16;
dsc[1].dsc_cfg.d32 = 0;
dsc[1].dsc_cfg.b.length = (AEStype>>3)-16;
dsc[1].dsc_cfg.b.mode = 1; // key
dsc[1].dsc_cfg.b.owner = 1;
dsc[2].src_addr = (uint64_t)iv;
dsc[2].tgt_addr = 32;
dsc[2].dsc_cfg.d32 = 0;
dsc[2].dsc_cfg.b.length = 16;
dsc[2].dsc_cfg.b.eoc = 1;
dsc[2].dsc_cfg.b.mode = 1; // key
dsc[2].dsc_cfg.b.owner = 1;
*P_DMA_STS0 = 0xf;
*P_DMA_T0= (uint64_t)dsc | 2;
while (*P_DMA_STS0 == 0);
aes_block(pt, ct, size,AEStype,CryptMode);
if (dcache_flag == 1)
{
dcache_enable();
}
exit:
return nReturn;
}