| /* |
| * 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; |
| |
| } |
| |
| |