diff --git a/wolfcrypt/src/port/pic32/pic32mz-hash.c b/wolfcrypt/src/port/pic32/pic32mz-hash.c new file mode 100644 index 000000000..ff881bcb8 --- /dev/null +++ b/wolfcrypt/src/port/pic32/pic32mz-hash.c @@ -0,0 +1,248 @@ +/* pic32mz-hash.c + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL 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. + * + * wolfSSL 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_PIC32MZ_HASH + +#include +#include +#include +#include + +#include + +#if !defined(NO_MD5) && !defined(NO_SHA) && !defined(NO_SHA256) + +static void reset_engine(pic32mz_desc *desc_l, int algo) +{ + pic32mz_desc *desc ; + desc = KVA0_TO_KVA1(desc_l) ; + + CECON = 1 << 6; + while (CECON); + + /* Make sure everything is clear first before we make settings. */ + XMEMSET((void *)KVA0_TO_KVA1(&desc->sa), 0, sizeof(desc->sa)); + XMEMSET((void *)KVA0_TO_KVA1(&desc->bd[0]), 0, sizeof(desc->bd[0])); + XMEMSET((void *)KVA0_TO_KVA1(&desc->bd[1]), 0, sizeof(desc->bd[1])); + + /* Set up the security association */ + desc->sa.SA_CTRL.ALGO = algo ; + desc->sa.SA_CTRL.LNC = 1; + desc->sa.SA_CTRL.FB = 1; + desc->sa.SA_CTRL.ENCTYPE = 1; + desc->sa.SA_CTRL.LOADIV = 1; + + /* Set up the buffer descriptor */ + desc->err = 0 ; + desc->bd[0].BD_CTRL.LAST_BD = 1; + desc->bd[0].BD_CTRL.LIFM = 1; + desc->bd[0].SA_ADDR = KVA_TO_PA(&desc->sa); + desc->bd[1].BD_CTRL.LAST_BD = 1; + desc->bd[1].BD_CTRL.LIFM = 1; + desc->bd[1].SA_ADDR = KVA_TO_PA(&desc->sa); + desc_l->bdCount = 0 ; + CEBDPADDR = KVA_TO_PA(&(desc->bd[0])); + + CECON = 0x27; +} + +#define PIC32MZ_IF_RAM(addr) (KVA_TO_PA(addr) < 0x80000) + +static void update_engine(pic32mz_desc *desc_l, const char *input, word32 len, + word32 *hash) +{ + pic32mz_desc *desc ; + int i ; + int total ; + desc = KVA0_TO_KVA1(desc_l) ; + + i = desc_l->bdCount ; + if(i >= PIC32MZ_MAX_BD) { + desc_l->err = 1 ; + return ; + } + + if(PIC32MZ_IF_RAM(input)) + XMEMCPY(KVA0_TO_KVA1(input), input, len) ; /* Sync phys with cache */ + desc->bd[i].SRCADDR = KVA_TO_PA(input); + /* Finally, turn on the buffer descriptor */ + if (len % 4) + desc->bd[i].BD_CTRL.BUFLEN = (len + 4) - (len % 4); + else desc->bd[i].BD_CTRL.BUFLEN = len ; + + if(i == 0) { + desc->bd[i].MSGLEN = len ; + desc->bd[i].BD_CTRL.SA_FETCH_EN = 1; + } else { + desc->bd[i-1].NXTPTR = KVA_TO_PA(&(desc->bd[i])) ; + desc->bd[i].BD_CTRL.DESC_EN = 1; + desc->bd[i-1].BD_CTRL.LAST_BD = 0 ; + desc->bd[i-1].BD_CTRL.LIFM = 0 ; + total = desc->bd[i-1].MSGLEN + len ; + desc->bd[i].MSGLEN = total ; + desc->bd[i-1].MSGLEN = total ; + } + desc->bd[i].UPDPTR = KVA_TO_PA(hash); + desc_l->bdCount ++ ; + + #ifdef DEBUG_CYASSL + printf("Input[bd=%d, len=%d]:%x->\"%s\"\n", desc_l->bdCount, len, input, input) ; + print_mem(input, len+4) ; + #endif +} + +static void start_engine(pic32mz_desc *desc) { + bufferDescriptor *hash_bd[2] ; + hash_bd[0] = (bufferDescriptor *)KVA0_TO_KVA1(&(desc->bd[0])) ; + hash_bd[0]->BD_CTRL.DESC_EN = 1; +} + +void wait_engine(pic32mz_desc *desc, char *hash, int hash_sz) { + unsigned int i; + unsigned int *intptr; + pic32mz_desc *uc_desc = KVA0_TO_KVA1(desc); + enum {true = 1, false = 0} engineRunning = true; + + while (engineRunning) + { + engineRunning = false; + for (i = 0; i < PIC32MZ_MAX_BD; i++) + engineRunning = engineRunning || uc_desc->bd[i].BD_CTRL.DESC_EN; + } + XMEMCPY(hash, KVA0_TO_KVA1(hash), hash_sz) ; + + #ifdef DEBUG_CYASSL + print_mem(KVA0_TO_KVA1(hash), hash_sz) ; + print_mem( hash , hash_sz) ; + #endif + for (i = 0, intptr = (unsigned int *)hash; i < hash_sz/sizeof(unsigned int); + i++, intptr++) + { + *intptr = ntohl(*intptr); + } +} + +static int fillBuff(char *buff, int *bufflen, const char *data, int len, int blocksz) +{ + int room, copysz ; + + room = blocksz - *bufflen ; + copysz = (len <= room) ? len : room ; + XMEMCPY(buff, data, copysz) ; + *bufflen += copysz ; + return (*bufflen == blocksz) ? 1 : 0 ; +} + +#endif + +#ifndef NO_MD5 +void wc_InitMd5(Md5* md5) +{ + WOLFSSL_ENTER("InitMd5\n") ; + XMEMSET((void *)md5, 0xcc, sizeof(Md5)) ; + XMEMSET((void *)KVA0_TO_KVA1(md5), 0xcc, sizeof(Md5)) ; + reset_engine(&(md5->desc), PIC32_ALGO_MD5) ; + +} + +void wc_Md5Update(Md5* md5, const byte* data, word32 len) +{ + WOLFSSL_ENTER("Md5Update\n") ; + update_engine(&(md5->desc), data, len, md5->digest) ; +} + +void wc_Md5Final(Md5* md5, byte* hash) +{ + WOLFSSL_ENTER("Md5Final\n") ; + start_engine(&(md5->desc)) ; + wait_engine(&(md5->desc), (char *)md5->digest, MD5_HASH_SIZE) ; + XMEMCPY(hash, md5->digest, MD5_HASH_SIZE) ; + wc_InitMd5(md5); /* reset state */ +} +#endif + +#ifndef NO_SHA +int wc_InitSha(Sha* sha) +{ + WOLFSSL_ENTER("InitSha\n") ; + XMEMSET((void *)sha, 0xcc, sizeof(Sha)) ; + XMEMSET((void *)KVA0_TO_KVA1(sha), 0xcc, sizeof(Sha)) ; + reset_engine(&(sha->desc), PIC32_ALGO_SHA1) ; + return 0; +} + +int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +{ + WOLFSSL_ENTER("ShaUpdate\n") ; + update_engine(&(sha->desc), data, len, sha->digest) ; + return 0; +} + +int wc_ShaFinal(Sha* sha, byte* hash) +{ + WOLFSSL_ENTER("ShaFinal\n") ; + start_engine(&(sha->desc)) ; + wait_engine(&(sha->desc), (char *)sha->digest, SHA1_HASH_SIZE) ; + XMEMCPY(hash, sha->digest, SHA1_HASH_SIZE) ; + + wc_InitSha(sha); /* reset state */ + return 0; +} +#endif /* NO_SHA */ + +#ifndef NO_SHA256 +int wc_InitSha256(Sha256* sha256) +{ + WOLFSSL_ENTER("InitSha256\n") ; + XMEMSET((void *)sha256, 0xcc, sizeof(Sha256)) ; + XMEMSET((void *)KVA0_TO_KVA1(sha256), 0xcc, sizeof(Sha256)) ; + reset_engine(&(sha256->desc), PIC32_ALGO_SHA256) ; + return 0; +} + +int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) +{ + WOLFSSL_ENTER("Sha256Update\n") ; + update_engine(&(sha256->desc), data, len, sha256->digest) ; + + return 0; +} + +int wc_Sha256Final(Sha256* sha256, byte* hash) +{ + WOLFSSL_ENTER("Sha256Final\n") ; + start_engine(&(sha256->desc)) ; + wait_engine(&(sha256->desc), (char *)sha256->digest, SHA256_HASH_SIZE) ; + XMEMCPY(hash, sha256->digest, SHA256_HASH_SIZE) ; + wc_InitSha256(sha256); /* reset state */ + + return 0; +} +#endif /* NO_SHA256 */ + +#endif +