From 1a315fd89e97a413e30e9d4f4ed92508f317df99 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Thu, 21 May 2015 13:31:02 +0900 Subject: [PATCH 01/21] Initial TI crypt/hash --- wolfcrypt/src/port/ti/ti-aes.c | 548 ++++++++++++++++++++++++++++++++ wolfcrypt/src/port/ti/ti-ccm.c | 81 +++++ wolfcrypt/src/port/ti/ti-des3.c | 181 +++++++++++ wolfcrypt/src/port/ti/ti-hash.c | 231 ++++++++++++++ 4 files changed, 1041 insertions(+) create mode 100644 wolfcrypt/src/port/ti/ti-aes.c create mode 100644 wolfcrypt/src/port/ti/ti-ccm.c create mode 100644 wolfcrypt/src/port/ti/ti-des3.c create mode 100644 wolfcrypt/src/port/ti/ti-hash.c diff --git a/wolfcrypt/src/port/ti/ti-aes.c b/wolfcrypt/src/port/ti/ti-aes.c new file mode 100644 index 000000000..11a0680b6 --- /dev/null +++ b/wolfcrypt/src/port/ti/ti-aes.c @@ -0,0 +1,548 @@ +/* port/ti/ti-aes.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 + +#ifndef NO_AES + + +#if defined(WOLFSSL_TI_CRYPT) +#include +#include + +#include +#include +#include + +#include "inc/hw_aes.h" +#include "inc/hw_memmap.h" +#include "inc/hw_ints.h" +#include "driverlib/aes.h" +#include "driverlib/sysctl.h" +#include "driverlib/rom_map.h" +#include "driverlib/rom.h" + +static int AesSetIV(Aes* aes, const byte* iv) +{ + if (aes == NULL) + return BAD_FUNC_ARG; + + if (iv) + XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + else + XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); + + return 0; +} + +WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, + int dir) +{ + if(!wolfSSL_TI_CCMInit())return 1 ; + if ((aes == NULL) || (key == NULL) || (iv == NULL)) + return BAD_FUNC_ARG; + if(!((dir == AES_ENCRYPTION) || (dir == AES_DECRYPTION))) + return BAD_FUNC_ARG; + + switch(len) { + case 16: aes->keylen = AES_CFG_KEY_SIZE_128BIT ; break ; + case 24: aes->keylen = AES_CFG_KEY_SIZE_192BIT ; break ; + case 32: aes->keylen = AES_CFG_KEY_SIZE_256BIT ; break ; + default: return BAD_FUNC_ARG; + } + + XMEMCPY(aes->key, key, len) ; + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ + return AesSetIV(aes, iv); +} + +#define AES_CFG_MODE_CTR_NOCTR AES_CFG_MODE_CTR+100 +#define IS_ALIGN16(p) (((unsigned int)(p)&0xf) == 0) + +static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode) +{ + wolfSSL_TI_lockCCM() ; + ROM_AESReset(AES_BASE); + ROM_AESConfigSet(AES_BASE, (aes->keylen | dir | + (mode==AES_CFG_MODE_CTR_NOCTR ? AES_CFG_MODE_CTR : mode))); + AESIVSet(AES_BASE, aes->reg); + ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); + if((dir == AES_CFG_DIR_DECRYPT)&& (mode == AES_CFG_MODE_CBC)) + /* if input and output same will overwrite input iv */ + XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + ROM_AESDataProcess(AES_BASE, (uint32_t *)in, (uint32_t *)out, sz); + wolfSSL_TI_unlockCCM() ; + + /* store iv for next call */ + if(mode == AES_CFG_MODE_CBC){ + if(dir == AES_CFG_DIR_ENCRYPT) + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + else + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + + if(mode == AES_CFG_MODE_CTR) { + do { + int i ; + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++((byte *)aes->reg)[i]) + break ; + } + sz -= AES_BLOCK_SIZE ; + } while((int)sz > 0) ; + } + + return 0 ; +} + +static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode) +{ + const byte * in_p ; byte * out_p ; + word32 size ; + #define TI_BUFFSIZE 1024 + byte buff[TI_BUFFSIZE] ; + + if ((aes == NULL) || (in == NULL) || (out == NULL)) + return BAD_FUNC_ARG; + if(sz % AES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + while(sz > 0) { + size = sz ; in_p = in ; out_p = out ; + if(!IS_ALIGN16(in)){ + size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; + XMEMCPY(buff, in, size) ; + in_p = (const byte *)buff ; + } + if(!IS_ALIGN16(out)){ + size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; + out_p = buff ; + } + + AesAlign16(aes, out_p, in_p, size, dir, mode) ; + + if(!IS_ALIGN16(out)){ + XMEMCPY(out, buff, size) ; + } + sz -= size ; in += size ; out += size ; + } + + return 0 ; +} + +WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return AesProcess(aes, out, in, sz, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CBC) ; +} + +WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return AesProcess(aes, out, in, sz, AES_CFG_DIR_DECRYPT, AES_CFG_MODE_CBC) ; +} + +#ifdef WOLFSSL_AES_COUNTER +WOLFSSL_API void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + char out_block[AES_BLOCK_SIZE] ; + int odd ; + int even ; + char *tmp ; /* (char *)aes->tmp, for short */ + + tmp = (char *)aes->tmp ; + if(aes->left) { + if((aes->left + sz) >= AES_BLOCK_SIZE){ + odd = AES_BLOCK_SIZE - aes->left ; + } else { + odd = sz ; + } + XMEMCPY(tmp+aes->left, in, odd) ; + if((odd+aes->left) == AES_BLOCK_SIZE){ + AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, + AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CTR) ; + XMEMCPY(out, out_block+aes->left, odd) ; + aes->left = 0 ; + XMEMSET(tmp, 0x0, AES_BLOCK_SIZE) ; + } + in += odd ; + out+= odd ; + sz -= odd ; + } + odd = sz % AES_BLOCK_SIZE ; /* if there is tail flagment */ + if(sz / AES_BLOCK_SIZE) { + even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE ; + AesProcess(aes, out, in, even, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CTR); + out += even ; + in += even ; + } + if(odd) { + XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left) ; + XMEMCPY(tmp+aes->left, in, odd) ; + AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, + AES_CFG_DIR_ENCRYPT, + AES_CFG_MODE_CTR_NOCTR /* Counter mode without counting IV */ + ); + XMEMCPY(out, out_block+aes->left,odd) ; + aes->left += odd ; + } +} +#endif + +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) +WOLFSSL_API void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) +{ + AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CBC) ; +} +WOLFSSL_API void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) +{ + AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_DECRYPT, AES_CFG_MODE_CBC) ; +} +WOLFSSL_API int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) +{ + return(wc_AesSetKey(aes, key, len, iv, dir)) ; +} +#endif + + +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + +static int AesAuthSetKey(Aes* aes, const byte* key, word32 keySz) +{ + byte nonce[AES_BLOCK_SIZE]; + + if ((aes == NULL) || (key == NULL)) + return BAD_FUNC_ARG ; + if (!((keySz == 16) || (keySz == 24) || (keySz == 32))) + return BAD_FUNC_ARG ; + + XMEMSET(nonce, 0, sizeof(nonce)); + return wc_AesSetKey(aes, key, keySz, nonce, AES_ENCRYPTION); +} + + +static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz, word32 *M, word32 *L) +{ + if((aes == NULL)||(nonce == NULL)||(authTag== NULL)||(authIn == NULL)) + return BAD_FUNC_ARG; + if((inSz != 0) && ((out == NULL)||(in == NULL))) + return BAD_FUNC_ARG; + + switch(authTagSz){ + case 4: + *M = AES_CFG_CCM_M_4; break ; + case 6: + *M = AES_CFG_CCM_M_6; break ; + case 8: + *M = AES_CFG_CCM_M_8; break ; + case 10: + *M = AES_CFG_CCM_M_10; break ; + case 12: + *M = AES_CFG_CCM_M_12; break ; + case 14: + *M = AES_CFG_CCM_M_14; break ; + case 16: + *M = AES_CFG_CCM_M_16; break ; + default: + return 1 ; + } + + switch(nonceSz){ + case 7: + *L = AES_CFG_CCM_L_8; break ; + case 8: + *L = AES_CFG_CCM_L_7; break ; + case 9: + *L = AES_CFG_CCM_L_6; break ; + case 10: + *L = AES_CFG_CCM_L_5; break ; + case 11: + *L = AES_CFG_CCM_L_4; break ; + case 12: + *L = AES_CFG_CCM_L_3; break ; + case 13: + *L = AES_CFG_CCM_L_2; break ; + case 14: + *L = AES_CFG_CCM_L_1; break ; + default: + return 1; + } + return 0 ; +} + +static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, int mode) { + + if(mode == AES_CFG_MODE_CCM){ + XMEMSET(aes->reg, 0, 16) ; + switch(L){ + case AES_CFG_CCM_L_8: + aes->reg[0] = 0x7; break ; + case AES_CFG_CCM_L_7: + aes->reg[0] = 0x6; break ; + case AES_CFG_CCM_L_6: + aes->reg[0] = 0x5; break ; + case AES_CFG_CCM_L_5: + aes->reg[0] = 0x4; break ; + case AES_CFG_CCM_L_4: + aes->reg[0] = 0x3; break ; + case AES_CFG_CCM_L_3: + aes->reg[0] = 0x2; break ; + case AES_CFG_CCM_L_2: + aes->reg[0] = 0x1; break ; + case AES_CFG_CCM_L_1: + aes->reg[0] = 0x0; break ; + } + XMEMCPY(((byte *)aes->reg)+1, nonce, len) ; + } else { + byte *b = (byte *)aes->reg ; + XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, nonce, len); + b[AES_BLOCK_SIZE-4] = 0 ; + b[AES_BLOCK_SIZE-3] = 0 ; + b[AES_BLOCK_SIZE-2] = 0 ; + b[AES_BLOCK_SIZE-1] = 1 ; + } +} + +#define RoundUp16(n) ((n+15)&0xfffffff0) +#define FREE_ALL \ + if(in_save) XFREE(in_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\ + if(out_save) XFREE(out_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\ + if(authIn_save)XFREE(authIn_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\ + if(nonce_save) XFREE(nonce_save, NULL, DYNAMIC_TYPE_TMP_BUFFER); + +static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz, int mode) +{ + word32 M, L ; + byte *in_a, *in_save ; + byte *out_a, *out_save ; + byte *authIn_a, *authIn_save ; + byte *nonce_a, *nonce_save ; + word32 tmpTag[4] ; + int ret ; + + if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L) + == BAD_FUNC_ARG)return BAD_FUNC_ARG ; + + /* 16 byte padding */ + in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ; + if((inSz%16)==0){ + in_save = NULL ; in_a = (byte *)in ; + out_save = NULL ; out_a = out ; + } else { + if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E ; } + in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ; + + if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E ; } + out_a = out_save ; + } + + if((authInSz%16)==0){ + authIn_save = NULL ; authIn_a = (byte *)authIn ; + } else { + if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E ; } + authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ; + } + + if((nonceSz%16)==0){ + nonce_save = NULL ; nonce_a = (byte *)nonce ; + } else { + if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E; } + nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ; + } + + /* do aes-ccm */ + AesAuthSetIv(aes, nonce, nonceSz, L, mode) ; + ROM_AESReset(AES_BASE); + ROM_AESConfigSet(AES_BASE, (aes->keylen | AES_CFG_DIR_ENCRYPT | + AES_CFG_CTR_WIDTH_128 | + mode | ((mode== AES_CFG_MODE_CCM) ? (L | M) : 0 ))) ; + ROM_AESIVSet(AES_BASE, aes->reg); + ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); + ret = ROM_AESDataProcessAuth(AES_BASE, (unsigned int*)in_a, (unsigned int *)out_a, inSz, + (unsigned int*)authIn_a, authInSz, (unsigned int *)tmpTag); + if(ret == false){ + XMEMSET(out, 0, inSz) ; + XMEMSET(authTag, 0, authTagSz) ; + } else { + XMEMCPY(out, out_a, inSz) ; + XMEMCPY(authTag, tmpTag, authTagSz) ; + } + + FREE_ALL; + return 0 ; +} + +static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz, int mode) +{ + word32 M, L ; + byte *in_a, *in_save ; + byte *out_a, *out_save ; + byte *authIn_a, *authIn_save ; + byte *nonce_a, *nonce_save ; + word32 tmpTag[4] ; + bool ret ; + + if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L) + == BAD_FUNC_ARG)return BAD_FUNC_ARG ; + + /* 16 byte padding */ + in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ; + if((inSz%16)==0){ + in_save = NULL ; in_a = (byte *)in ; + out_save = NULL ; out_a = out ; + } else { + if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E;} + in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ; + + if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E;} + out_a = out_save ; + } + + if((authInSz%16)==0){ + authIn_save = NULL ; authIn_a = (byte *)authIn ; + } else { + if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E; } + authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ; + } + + if((nonceSz%16)==0){ + nonce_save = NULL ; nonce_a = (byte *)nonce ; + } else { + if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E; } + nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ; + } + + /* do aes-ccm */ + AesAuthSetIv(aes, nonce, nonceSz, L, mode) ; + ROM_AESReset(AES_BASE); + ROM_AESConfigSet(AES_BASE, (aes->keylen | AES_CFG_DIR_DECRYPT | + AES_CFG_CTR_WIDTH_128 | + mode | ((mode== AES_CFG_MODE_CCM) ? (L | M) : 0 ))) ; + ROM_AESIVSet(AES_BASE, aes->reg); + ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); + ret = ROM_AESDataProcessAuth(AES_BASE, (unsigned int*)in_a, (unsigned int *)out_a, inSz, + (unsigned int*)authIn_a, authInSz, (unsigned int *)tmpTag); + if((ret == false) || (XMEMCMP(authTag, tmpTag, authTagSz) != 0)){ + XMEMSET(out, 0, inSz) ; + ret = false ; + } else { + XMEMCPY(out, out_a, inSz) ; + } + + FREE_ALL ; + return ret==true ? 0 : 1 ; +} +#endif + + +#ifdef HAVE_AESGCM +WOLFSSL_API int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) +{ + return AesAuthSetKey(aes, key, len) ; +} + +WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + return AesAuthEncrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; +} +WOLFSSL_API int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + return AesAuthDecrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; +} + +WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) +{ + return AesAuthSetKey(&gmac->aes, key, len) ; +} + +WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz) +{ + return AesAuthEncrypt(&gmac->aes, NULL, NULL, 0, iv, ivSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; +} + +#endif /* HAVE_AESGCM */ + +#ifdef HAVE_AESCCM +WOLFSSL_API void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +{ + AesAuthSetKey(aes, key, keySz) ; +} + +WOLFSSL_API void wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + AesAuthEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_CCM) ; +} + +WOLFSSL_API int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + return AesAuthDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_CCM) ; +} +#endif /* HAVE_AESCCM */ + +#endif /* WOLFSSL_TI_CRYPT */ + +#endif /* NO_AES */ + + + diff --git a/wolfcrypt/src/port/ti/ti-ccm.c b/wolfcrypt/src/port/ti/ti-ccm.c new file mode 100644 index 000000000..801cc9bb5 --- /dev/null +++ b/wolfcrypt/src/port/ti/ti-ccm.c @@ -0,0 +1,81 @@ +/* port/ti/ti_ccm.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 + +#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) + + +#include +#include + +#include "driverlib/sysctl.h" +#include "driverlib/rom_map.h" +#include "driverlib/rom.h" + +#ifndef SINGLE_THREADED + static wolfSSL_Mutex TI_CCM_Mutex ; +#endif + +#define TIMEOUT 500000 +#define WAIT(stat) { volatile int i ; for(i=0; i +#endif + +#include + +#ifndef NO_DES + +#if defined(WOLFSSL_TI_CRYPT) +#include +#include + +#include +#include +#include + +#include "inc/hw_des.h" +#include "inc/hw_memmap.h" +#include "inc/hw_ints.h" +#include "driverlib/des.h" +#include "driverlib/sysctl.h" +#include "driverlib/rom_map.h" +#include "driverlib/rom.h" + +static int DesSetIV(Des* des, const byte* iv, int tri) +{ + if (des == NULL) + return BAD_FUNC_ARG; + + if (iv) + XMEMCPY(des->reg, iv, tri == DES_CFG_TRIPLE ? DES3_IVLEN : DES_IVLEN); + else + XMEMSET(des->reg, 0, tri == DES_CFG_TRIPLE ? DES3_IVLEN : DES_IVLEN); + + return 0; +} + +static int DesSetKey(Des* des, const byte* key, const byte* iv,int dir, int tri) +{ + if(!wolfSSL_TI_CCMInit())return 1 ; + if ((des == NULL) || (key == NULL) || (iv == NULL)) + return BAD_FUNC_ARG; + if(!((dir == DES_ENCRYPTION) || (dir == DES_DECRYPTION))) + return BAD_FUNC_ARG; + + XMEMCPY(des->key, key, tri == DES_CFG_SINGLE ? DES_KEYLEN : DES3_KEYLEN) ; + return DesSetIV(des, iv, tri); +} + +static int DesCbcAlign16(Des* des, byte* out, const byte* in, word32 sz, word32 dir, word32 tri) +{ + + wolfSSL_TI_lockCCM() ; + ROM_DESReset(DES_BASE); + ROM_DESConfigSet(DES_BASE, (dir | DES_CFG_MODE_CBC | tri)); + DESIVSet(DES_BASE, des->reg); + ROM_DESKeySet(DES_BASE, des->key); + if(dir == DES_CFG_DIR_DECRYPT) + /* if input and output same will overwrite input iv */ + XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + ROM_DESDataProcess(DES_BASE, (uint32_t *)in, (uint32_t *)out, sz); + wolfSSL_TI_unlockCCM() ; + + /* store iv for next call */ + if(dir == DES_CFG_DIR_ENCRYPT) + XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + else + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + return 0 ; +} + +#define IS_ALIGN16(p) (((unsigned int)(p)&0xf) == 0) + +static int DesCbc(Des* des, byte* out, const byte* in, word32 sz, word32 dir, word32 tri) +{ + const byte * in_p ; byte * out_p ; + word32 size ; + #define TI_BUFFSIZE 1024 + byte buff[TI_BUFFSIZE] ; + if ((des == NULL) || (in == NULL) || (out == NULL)) + return BAD_FUNC_ARG; + if(sz % DES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + while(sz > 0) { + size = sz ; in_p = in ; out_p = out ; + if(!IS_ALIGN16(in)){ + size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; + XMEMCPY(buff, in, size) ; + in_p = (const byte *)buff ; + } + if(!IS_ALIGN16(out)){ + size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; + out_p = (byte *)buff ; + } + + DesCbcAlign16(des, out_p, in_p, size, dir, tri) ; + + if(!IS_ALIGN16(out)){ + XMEMCPY(out, buff, size) ; + } + sz -= size ; in += size ; out += size ; + } + return 0 ; +} + +WOLFSSL_API int wc_Des_SetKey(Des* des, const byte* key, const byte* iv,int dir) +{ + return DesSetKey(des, key, iv, dir, DES_CFG_SINGLE) ; +} + +WOLFSSL_API void wc_Des_SetIV(Des* des, const byte* iv) +{ + DesSetIV(des, iv, DES_CFG_SINGLE) ; +} + +WOLFSSL_API int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv,int dir) +{ + return DesSetKey((Des *)des, key, iv, dir, DES_CFG_TRIPLE) ; +} + +WOLFSSL_API int wc_Des3_SetIV(Des3* des, const byte* iv) +{ + return DesSetIV((Des *)des, iv, DES_CFG_TRIPLE) ; +} + + +WOLFSSL_API int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) +{ + return DesCbc(des, out, in, sz, DES_CFG_DIR_ENCRYPT, DES_CFG_SINGLE) ; +} + +WOLFSSL_API int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) +{ + return DesCbc(des, out, in, sz, DES_CFG_DIR_DECRYPT, DES_CFG_SINGLE) ; +} + +WOLFSSL_API int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ return 0 ;} + +WOLFSSL_API int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) +{ + return DesCbc((Des *)des, out, in, sz, DES_CFG_DIR_ENCRYPT, DES_CFG_TRIPLE) ; +} + +WOLFSSL_API int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) +{ + return DesCbc((Des *)des, out, in, sz, DES_CFG_DIR_DECRYPT, DES_CFG_TRIPLE) ; +} + +WOLFSSL_API int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ return 0 ; } + + +#endif /* WOLFSSL_TI_CRYPT */ + +#endif /* NO_DES */ diff --git a/wolfcrypt/src/port/ti/ti-hash.c b/wolfcrypt/src/port/ti/ti-hash.c new file mode 100644 index 000000000..223874b20 --- /dev/null +++ b/wolfcrypt/src/port/ti/ti-hash.c @@ -0,0 +1,231 @@ +/* port/ti/ti-hash.h + * + * 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 + */ + + +#ifndef WOLFSSL_TI_HASH_H +#define WOLFSSL_TI_HASH_H + +#include + +#if defined(WOLFSSL_TI_HASH) + +#ifdef __cplusplus + extern "C" { +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "inc/hw_memmap.h" +#include "inc/hw_shamd5.h" +#include "inc/hw_ints.h" +#include "driverlib/shamd5.h" +#include "driverlib/sysctl.h" +#include "driverlib/rom_map.h" +#include "driverlib/rom.h" + +static int hashInit(wolfssl_TI_Hash *hash) { + hash->used = 0 ; + hash->msg = 0 ; + hash->len = 0 ; + return 0 ; +} + +static int hashUpdate(wolfssl_TI_Hash *hash, const byte* data, word32 len) +{ + void *p ; + if((hash== NULL) || (data == NULL))return BAD_FUNC_ARG; + if(hash->len < hash->used+len) { + if(hash->msg == NULL) { + p = XMALLOC(hash->used+len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } else { + p = XREALLOC(hash->msg, hash->used+len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if(p == 0)return 1 ; + hash->msg = p ; + hash->len = hash->used+len ; + } + XMEMCPY(hash->msg+hash->used, data, len) ; + hash->used += len ; + return 0 ; +} + +static int hashFinal(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) +{ + uint32_t h[16] ; + wolfSSL_TI_lockCCM() ; + ROM_SHAMD5Reset(SHAMD5_BASE); + ROM_SHAMD5ConfigSet(SHAMD5_BASE, algo); + ROM_SHAMD5DataProcess(SHAMD5_BASE, + (uint32_t *)hash->msg, hash->used, h); + XMEMCPY(result, h, hsize) ; + wolfSSL_TI_unlockCCM() ; + XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); + hashInit(hash) ; + return 0 ; +} + +static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word32 hsize) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + wolfssl_TI_Hash* hash_desc; +#else + wolfssl_TI_Hash hash_desc[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + hash_desc = (wolfssl_TI_Hash*)XMALLOC(sizeof(wolfssl_TI_Hash), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hash_desc == NULL) + return MEMORY_E; +#endif + + if ((ret = hashInit(hash_desc)) != 0) { + WOLFSSL_MSG("Hash Init failed"); + } + else { + hashUpdate(hash_desc, data, len); + hashFinal(hash_desc, hash, algo, hsize); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#if !defined(NO_MD5) + +void wc_InitMd5(Md5* md5) +{ + if (md5 == NULL) + return ; + if(!wolfSSL_TI_CCMInit())return ; + hashInit((wolfssl_TI_Hash *)md5) ; +} + +void wc_Md5Update(Md5* md5, const byte* data, word32 len) +{ + hashUpdate((wolfssl_TI_Hash *)md5, data, len) ; +} + +void wc_Md5Final(Md5* md5, byte* hash) +{ + hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; +} + +WOLFSSL_API int wc_Md5Hash(const byte*data, word32 len, byte*hash) +{ + return hashHash(data, len, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; +} + +#endif /* NO_MD5 */ + +#if !defined(NO_SHA) + +WOLFSSL_API int wc_InitSha(Sha* sha) +{ + if (sha == NULL) + return 1 ; + if(!wolfSSL_TI_CCMInit())return 1 ; + return hashInit((wolfssl_TI_Hash *)sha) ; +} + +WOLFSSL_API int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +{ + return hashUpdate((wolfssl_TI_Hash *)sha, data, len) ; +} + +WOLFSSL_API int wc_ShaFinal(Sha* sha, byte* hash) +{ + return hashFinal((wolfssl_TI_Hash *)sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; +} +WOLFSSL_API int wc_ShaHash(const byte*data, word32 len, byte*hash) +{ + return hashHash(data, len, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; +} + +#endif /* NO_SHA */ + +#if defined(HAVE_SHA224) +WOLFSSL_API int wc_InitSha224(Sha224* sha224) +{ + if (sha224 == NULL) + return 1 ; + if(!wolfSSL_TI_CCMInit())return 1 ; + return hashInit((wolfssl_TI_Hash *)sha224) ; +} + +WOLFSSL_API int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) +{ + return hashUpdate((wolfssl_TI_Hash *)sha224, data, len) ; +} + +WOLFSSL_API int wc_Sha224Final(Sha224* sha224, byte* hash) +{ + return hashFinal((wolfssl_TI_Hash *)sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; +} + +WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) +{ + return hashHash(data, len, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; +} + +#endif /* HAVE_SHA224 */ + +#if !defined(NO_SHA256) +WOLFSSL_API int wc_InitSha256(Sha256* sha256) +{ + if (sha256 == NULL) + return 1 ; + if(!wolfSSL_TI_CCMInit())return 1 ; + return hashInit((wolfssl_TI_Hash *)sha256) ; +} + +WOLFSSL_API int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) +{ + return hashUpdate((wolfssl_TI_Hash *)sha256, data, len) ; +} + +WOLFSSL_API int wc_Sha256Final(Sha256* sha256, byte* hash) +{ + return hashFinal((wolfssl_TI_Hash *)sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; +} + +WOLFSSL_API int wc_Sha256Hash(const byte* data, word32 len, byte*hash) +{ + return hashHash(data, len, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; +} + +#endif /* NO_SHA256 */ + +#endif /* WOLFSSL_TI_HASH */ + +#endif /* WOLFSSL_TI_HASH_H */ From b5654092ecce93997d464cde0a62abc961e926fb Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Thu, 21 May 2015 13:42:02 +0900 Subject: [PATCH 02/21] Added Md5GetHash for BuildCertHashes --- src/include.am | 2 + src/internal.c | 6 +- wolfcrypt/src/md5.c | 818 +++---- wolfcrypt/src/port/ti/ti-hash.c | 99 +- wolfcrypt/src/sha.c | 925 ++++---- wolfcrypt/src/sha256.c | 3540 ++++++++++++++++--------------- wolfssl/wolfcrypt/md5.h | 181 +- wolfssl/wolfcrypt/sha.h | 168 +- wolfssl/wolfcrypt/sha256.h | 166 +- 9 files changed, 3045 insertions(+), 2860 deletions(-) mode change 100755 => 100644 wolfcrypt/src/sha256.c diff --git a/src/include.am b/src/include.am index a89d7d472..1dcf24a2b 100644 --- a/src/include.am +++ b/src/include.am @@ -191,6 +191,8 @@ if BUILD_PKCS7 src_libwolfssl_la_SOURCES += wolfcrypt/src/pkcs7.c endif +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/ti/ti-hash.c + # ssl files src_libwolfssl_la_SOURCES += \ src/internal.c \ diff --git a/src/internal.c b/src/internal.c index aa69f8310..48f226201 100644 --- a/src/internal.c +++ b/src/internal.c @@ -6925,14 +6925,14 @@ static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) if (ssl->options.tls) { #if ! defined( NO_OLD_TLS ) - wc_Md5Final(&ssl->hsHashes->hashMd5, hashes->md5); - wc_ShaFinal(&ssl->hsHashes->hashSha, hashes->sha); + wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5); + wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha); #endif if (IsAtLeastTLSv1_2(ssl)) { int ret; #ifndef NO_SHA256 - ret = wc_Sha256Final(&ssl->hsHashes->hashSha256,hashes->sha256); + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,hashes->sha256); if (ret != 0) return ret; #endif diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index d2583bd9b..a3e76eda8 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -1,392 +1,426 @@ -/* md5.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 - -#if !defined(NO_MD5) - -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitMd5 wc_InitMd5_sw -#define wc_Md5Update wc_Md5Update_sw -#define wc_Md5Final wc_Md5Final_sw -#endif - -#include -#include - -#ifdef NO_INLINE - #include -#else - #include -#endif - -#ifdef FREESCALE_MMCAU - #include "cau_api.h" - #define XTRANSFORM(S,B) cau_md5_hash_n((B), 1, (unsigned char*)(S)->digest) -#else - #define XTRANSFORM(S,B) Transform((S)) -#endif - - -#ifdef STM32F2_HASH - /* - * STM32F2 hardware MD5 support through the STM32F2 standard peripheral - * library. Documentation located in STM32F2xx Standard Peripheral Library - * document (See note in README). - */ - #include "stm32f2xx.h" - - void wc_InitMd5(Md5* md5) - { - /* STM32F2 struct notes: - * md5->buffer = first 4 bytes used to hold partial block if needed - * md5->buffLen = num bytes currently stored in md5->buffer - * md5->loLen = num bytes that have been written to STM32 FIFO - */ - XMEMSET(md5->buffer, 0, MD5_REG_SIZE); - - md5->buffLen = 0; - md5->loLen = 0; - - /* initialize HASH peripheral */ - HASH_DeInit(); - - /* configure algo used, algo mode, datatype */ - HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); - HASH->CR |= (HASH_AlgoSelection_MD5 | HASH_AlgoMode_HASH - | HASH_DataType_8b); - - /* reset HASH processor */ - HASH->CR |= HASH_CR_INIT; - } - - void wc_Md5Update(Md5* md5, const byte* data, word32 len) - { - word32 i = 0; - word32 fill = 0; - word32 diff = 0; - - /* if saved partial block is available */ - if (md5->buffLen > 0) { - fill = 4 - md5->buffLen; - - /* if enough data to fill, fill and push to FIFO */ - if (fill <= len) { - XMEMCPY((byte*)md5->buffer + md5->buffLen, data, fill); - HASH_DataIn(*(uint32_t*)md5->buffer); - - data += fill; - len -= fill; - md5->loLen += 4; - md5->buffLen = 0; - } else { - /* append partial to existing stored block */ - XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); - md5->buffLen += len; - return; - } - } - - /* write input block in the IN FIFO */ - for (i = 0; i < len; i += 4) - { - diff = len - i; - if (diff < 4) { - /* store incomplete last block, not yet in FIFO */ - XMEMSET(md5->buffer, 0, MD5_REG_SIZE); - XMEMCPY((byte*)md5->buffer, data, diff); - md5->buffLen = diff; - } else { - HASH_DataIn(*(uint32_t*)data); - data+=4; - } - } - - /* keep track of total data length thus far */ - md5->loLen += (len - md5->buffLen); - } - - void wc_Md5Final(Md5* md5, byte* hash) - { - __IO uint16_t nbvalidbitsdata = 0; - - /* finish reading any trailing bytes into FIFO */ - if (md5->buffLen > 0) { - HASH_DataIn(*(uint32_t*)md5->buffer); - md5->loLen += md5->buffLen; - } - - /* calculate number of valid bits in last word of input data */ - nbvalidbitsdata = 8 * (md5->loLen % MD5_REG_SIZE); - - /* configure number of valid bits in last word of the data */ - HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); - - /* start HASH processor */ - HASH_StartDigest(); - - /* wait until Busy flag == RESET */ - while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} - - /* read message digest */ - md5->digest[0] = HASH->HR[0]; - md5->digest[1] = HASH->HR[1]; - md5->digest[2] = HASH->HR[2]; - md5->digest[3] = HASH->HR[3]; - - ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); - - XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); - - wc_InitMd5(md5); /* reset state */ - } - -#else /* CTaoCrypt software implementation */ - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -void wc_InitMd5(Md5* md5) -{ - md5->digest[0] = 0x67452301L; - md5->digest[1] = 0xefcdab89L; - md5->digest[2] = 0x98badcfeL; - md5->digest[3] = 0x10325476L; - - md5->buffLen = 0; - md5->loLen = 0; - md5->hiLen = 0; -} - -#ifndef FREESCALE_MMCAU - -static void Transform(Md5* md5) -{ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -#define MD5STEP(f, w, x, y, z, data, s) \ - w = rotlFixed(w + f(x, y, z) + data, s) + x - - /* Copy context->state[] to working vars */ - word32 a = md5->digest[0]; - word32 b = md5->digest[1]; - word32 c = md5->digest[2]; - word32 d = md5->digest[3]; - - MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); - - /* Add the working vars back into digest state[] */ - md5->digest[0] += a; - md5->digest[1] += b; - md5->digest[2] += c; - md5->digest[3] += d; -} - -#endif /* FREESCALE_MMCAU */ - - -static INLINE void AddLength(Md5* md5, word32 len) -{ - word32 tmp = md5->loLen; - if ( (md5->loLen += len) < tmp) - md5->hiLen++; /* carry low to high */ -} - - -void wc_Md5Update(Md5* md5, const byte* data, word32 len) -{ - /* do block size increments */ - byte* local = (byte*)md5->buffer; - - while (len) { - word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); - XMEMCPY(&local[md5->buffLen], data, add); - - md5->buffLen += add; - data += add; - len -= add; - - if (md5->buffLen == MD5_BLOCK_SIZE) { - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif - XTRANSFORM(md5, local); - AddLength(md5, MD5_BLOCK_SIZE); - md5->buffLen = 0; - } - } -} - - -void wc_Md5Final(Md5* md5, byte* hash) -{ - byte* local = (byte*)md5->buffer; - - AddLength(md5, md5->buffLen); /* before adding pads */ - - local[md5->buffLen++] = 0x80; /* add 1 */ - - /* pad with zeros */ - if (md5->buffLen > MD5_PAD_SIZE) { - XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen); - md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen; - - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif - XTRANSFORM(md5, local); - md5->buffLen = 0; - } - XMEMSET(&local[md5->buffLen], 0, MD5_PAD_SIZE - md5->buffLen); - - /* put lengths in bits */ - md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) + - (md5->hiLen << 3); - md5->loLen = md5->loLen << 3; - - /* store lengths */ - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif - /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); - XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); - - XTRANSFORM(md5, local); - #ifdef BIG_ENDIAN_ORDER - ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); - #endif - XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); - - wc_InitMd5(md5); /* reset state */ -} - -#endif /* STM32F2_HASH */ - - -int wc_Md5Hash(const byte* data, word32 len, byte* hash) -{ -#ifdef WOLFSSL_SMALL_STACK - Md5* md5; -#else - Md5 md5[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (md5 == NULL) - return MEMORY_E; -#endif - - wc_InitMd5(md5); - wc_Md5Update(md5, data, len); - wc_Md5Final(md5, hash); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return 0; -} - -#endif /* NO_MD5 */ +/* md5.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 + +#if !defined(NO_MD5) && !defined(WOLFSSL_TI_HASH) + +#ifdef WOLFSSL_PIC32MZ_HASH +#define wc_InitMd5 wc_InitMd5_sw +#define wc_Md5Update wc_Md5Update_sw +#define wc_Md5Final wc_Md5Final_sw +#endif + +#include +#include + +#ifdef NO_INLINE + #include +#else + #include +#endif + +#ifdef FREESCALE_MMCAU + #include "cau_api.h" + #define XTRANSFORM(S,B) cau_md5_hash_n((B), 1, (unsigned char*)(S)->digest) +#else + #define XTRANSFORM(S,B) Transform((S)) +#endif + + +#ifdef STM32F2_HASH + /* + * STM32F2 hardware MD5 support through the STM32F2 standard peripheral + * library. Documentation located in STM32F2xx Standard Peripheral Library + * document (See note in README). + */ + #include "stm32f2xx.h" + + void wc_InitMd5(Md5* md5) + { + /* STM32F2 struct notes: + * md5->buffer = first 4 bytes used to hold partial block if needed + * md5->buffLen = num bytes currently stored in md5->buffer + * md5->loLen = num bytes that have been written to STM32 FIFO + */ + XMEMSET(md5->buffer, 0, MD5_REG_SIZE); + + md5->buffLen = 0; + md5->loLen = 0; + + /* initialize HASH peripheral */ + HASH_DeInit(); + + /* configure algo used, algo mode, datatype */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + HASH->CR |= (HASH_AlgoSelection_MD5 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + } + + void wc_Md5Update(Md5* md5, const byte* data, word32 len) + { + word32 i = 0; + word32 fill = 0; + word32 diff = 0; + + /* if saved partial block is available */ + if (md5->buffLen > 0) { + fill = 4 - md5->buffLen; + + /* if enough data to fill, fill and push to FIFO */ + if (fill <= len) { + XMEMCPY((byte*)md5->buffer + md5->buffLen, data, fill); + HASH_DataIn(*(uint32_t*)md5->buffer); + + data += fill; + len -= fill; + md5->loLen += 4; + md5->buffLen = 0; + } else { + /* append partial to existing stored block */ + XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); + md5->buffLen += len; + return; + } + } + + /* write input block in the IN FIFO */ + for (i = 0; i < len; i += 4) + { + diff = len - i; + if (diff < 4) { + /* store incomplete last block, not yet in FIFO */ + XMEMSET(md5->buffer, 0, MD5_REG_SIZE); + XMEMCPY((byte*)md5->buffer, data, diff); + md5->buffLen = diff; + } else { + HASH_DataIn(*(uint32_t*)data); + data+=4; + } + } + + /* keep track of total data length thus far */ + md5->loLen += (len - md5->buffLen); + } + + void wc_Md5Final(Md5* md5, byte* hash) + { + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (md5->buffLen > 0) { + HASH_DataIn(*(uint32_t*)md5->buffer); + md5->loLen += md5->buffLen; + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (md5->loLen % MD5_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + md5->digest[0] = HASH->HR[0]; + md5->digest[1] = HASH->HR[1]; + md5->digest[2] = HASH->HR[2]; + md5->digest[3] = HASH->HR[3]; + + ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); + + XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); + + wc_InitMd5(md5); /* reset state */ + } + +#elif defined(WOLFSSL_IT_HASH) + + /* defined in port/ti_md5.c */ + +#else /* CTaoCrypt software implementation */ + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + +#ifdef TI_HASH_TEST +void wc_InitMd5_ti(Md5* md5) ; +void wc_Md5Update_ti(Md5* md5, const byte* data, word32 len) ; +void wc_Md5Final_ti(Md5* md5, byte* hash) ; +#endif + +void wc_InitMd5(Md5* md5) +{ + md5->digest[0] = 0x67452301L; + md5->digest[1] = 0xefcdab89L; + md5->digest[2] = 0x98badcfeL; + md5->digest[3] = 0x10325476L; + + md5->buffLen = 0; + md5->loLen = 0; + md5->hiLen = 0; + +#ifdef TI_HASH_TEST + wc_InitMd5_ti(md5) ; +#endif +} + +#ifndef FREESCALE_MMCAU + +static void Transform(Md5* md5) +{ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, data, s) \ + w = rotlFixed(w + f(x, y, z) + data, s) + x + + /* Copy context->state[] to working vars */ + word32 a = md5->digest[0]; + word32 b = md5->digest[1]; + word32 c = md5->digest[2]; + word32 d = md5->digest[3]; + + MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); + + /* Add the working vars back into digest state[] */ + md5->digest[0] += a; + md5->digest[1] += b; + md5->digest[2] += c; + md5->digest[3] += d; +} + +#endif /* FREESCALE_MMCAU */ + + +static INLINE void AddLength(Md5* md5, word32 len) +{ + word32 tmp = md5->loLen; + if ( (md5->loLen += len) < tmp) + md5->hiLen++; /* carry low to high */ +} + + +void wc_Md5Update(Md5* md5, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local = (byte*)md5->buffer; + + while (len) { + word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); + XMEMCPY(&local[md5->buffLen], data, add); + + md5->buffLen += add; + data += add; + len -= add; + + if (md5->buffLen == MD5_BLOCK_SIZE) { + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif + XTRANSFORM(md5, local); + AddLength(md5, MD5_BLOCK_SIZE); + md5->buffLen = 0; + } + } +#ifdef TI_HASH_TEST + wc_Md5Update_ti(md5, data, len) ; +#endif + +} + + +void wc_Md5Final(Md5* md5, byte* hash) +{ + byte* local = (byte*)md5->buffer; + + AddLength(md5, md5->buffLen); /* before adding pads */ + + local[md5->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (md5->buffLen > MD5_PAD_SIZE) { + XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen); + md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen; + + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif + XTRANSFORM(md5, local); + md5->buffLen = 0; + } + XMEMSET(&local[md5->buffLen], 0, MD5_PAD_SIZE - md5->buffLen); + + /* put lengths in bits */ + md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) + + (md5->hiLen << 3); + md5->loLen = md5->loLen << 3; + + /* store lengths */ + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); + XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); + + XTRANSFORM(md5, local); + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); + #endif + XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); + + wc_InitMd5(md5); /* reset state */ + +#ifdef TI_HASH_TEST + wc_Md5Final_ti(md5, hash) ; +#endif +} + +#endif /* STM32F2_HASH */ + + +int wc_Md5Hash(const byte* data, word32 len, byte* hash) +{ +#ifdef WOLFSSL_SMALL_STACK + Md5* md5; +#else + Md5 md5[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; +#endif + + wc_InitMd5(md5); + wc_Md5Update(md5, data, len); + wc_Md5Final(md5, hash); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +#if defined(WOLFSSL_TI_HASH)||defined(TI_HASH_TEST) +#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif +void wc_Md5GetHash(Md5* md5, byte* hash) +{ +#if defined(WOLFSSL_TI_HASH) || defined(TI_HASH_TEST) + wc_Md5GetHash_ti(md5, hash) ; +#else + Md5 save = *md5 ; + wc_Md5Final(md5, hash) ; + *md5 = save ; +#endif +} +#endif /* NO_MD5 */ diff --git a/wolfcrypt/src/port/ti/ti-hash.c b/wolfcrypt/src/port/ti/ti-hash.c index 223874b20..7647dcdb4 100644 --- a/wolfcrypt/src/port/ti/ti-hash.c +++ b/wolfcrypt/src/port/ti/ti-hash.c @@ -1,4 +1,4 @@ -/* port/ti/ti-hash.h +/* port/ti/ti-hash.c * * Copyright (C) 2006-2015 wolfSSL Inc. * @@ -20,12 +20,9 @@ */ -#ifndef WOLFSSL_TI_HASH_H -#define WOLFSSL_TI_HASH_H - #include -#if defined(WOLFSSL_TI_HASH) +#if defined(WOLFSSL_TI_HASH)||defined(TI_HASH_TEST) #ifdef __cplusplus extern "C" { @@ -41,7 +38,8 @@ #include #include #include - + +#if !defined(TI_HASH_TEST) #include "inc/hw_memmap.h" #include "inc/hw_shamd5.h" #include "inc/hw_ints.h" @@ -49,6 +47,7 @@ #include "driverlib/sysctl.h" #include "driverlib/rom_map.h" #include "driverlib/rom.h" +#endif static int hashInit(wolfssl_TI_Hash *hash) { hash->used = 0 ; @@ -60,6 +59,7 @@ static int hashInit(wolfssl_TI_Hash *hash) { static int hashUpdate(wolfssl_TI_Hash *hash, const byte* data, word32 len) { void *p ; + if((hash== NULL) || (data == NULL))return BAD_FUNC_ARG; if(hash->len < hash->used+len) { if(hash->msg == NULL) { @@ -77,8 +77,10 @@ static int hashUpdate(wolfssl_TI_Hash *hash, const byte* data, word32 len) } static int hashFinal(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) -{ +{ + #if !defined(TI_HASH_TEST) uint32_t h[16] ; + wolfSSL_TI_lockCCM() ; ROM_SHAMD5Reset(SHAMD5_BASE); ROM_SHAMD5ConfigSet(SHAMD5_BASE, algo); @@ -86,11 +88,38 @@ static int hashFinal(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hs (uint32_t *)hash->msg, hash->used, h); XMEMCPY(result, h, hsize) ; wolfSSL_TI_unlockCCM() ; + #else + (void) result ; + (void) algo ; + (void) hsize ; + #endif XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); hashInit(hash) ; return 0 ; } +static int hashGetHash(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) +{ + #if !defined(TI_HASH_TEST) + uint32_t h[16] ; + + wolfSSL_TI_lockCCM() ; + ROM_SHAMD5Reset(SHAMD5_BASE); + ROM_SHAMD5ConfigSet(SHAMD5_BASE, algo); + ROM_SHAMD5DataProcess(SHAMD5_BASE, + (uint32_t *)hash->msg, hash->used, h); + XMEMCPY(result, h, hsize) ; + wolfSSL_TI_unlockCCM() ; + #else + (void) hash ; + (void) result ; + (void) algo ; + (void) hsize ; + #endif + return 0 ; +} + +#ifndef TI_HASH_TEST static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word32 hsize) { int ret = 0; @@ -120,34 +149,80 @@ static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word3 return ret; } +#endif #if !defined(NO_MD5) +#ifdef TI_HASH_TEST +#define SHAMD5_ALGO_MD5 1 +void wc_InitMd5_ti(Md5* md5) ; +void wc_Md5Update_ti(Md5* md5, const byte* data, word32 len); +void wc_Md5Final_ti(Md5* md5, byte* hash); +bool wolfSSL_TI_CCMInit(void) ; +bool wolfSSL_TI_CCMInit(void) { return true ; } +#endif + +#ifdef TI_HASH_TEST +void wc_InitMd5_ti(Md5* md5) +#else void wc_InitMd5(Md5* md5) +#endif { if (md5 == NULL) return ; if(!wolfSSL_TI_CCMInit())return ; + #ifdef TI_HASH_TEST + hashInit(&(md5->ti)) ; + #else hashInit((wolfssl_TI_Hash *)md5) ; + #endif } +#ifdef TI_HASH_TEST +void wc_Md5Update_ti(Md5* md5, const byte* data, word32 len) +#else void wc_Md5Update(Md5* md5, const byte* data, word32 len) +#endif { + #ifdef TI_HASH_TEST + hashUpdate(&(md5->ti), data, len) ; + #else hashUpdate((wolfssl_TI_Hash *)md5, data, len) ; + #endif } +#ifdef TI_HASH_TEST +void wc_Md5Final_ti(Md5* md5, byte* hash) +#else void wc_Md5Final(Md5* md5, byte* hash) +#endif { - hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + #ifdef TI_HASH_TEST + hashFinal(&(md5->ti), hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + #else + hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + #endif } + +void wc_Md5GetHash_ti(Md5* md5, byte* hash) +{ + hashGetHash(&(md5->ti), hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + #ifdef TI_HASH_TEST + wc_Md5Final(md5, hash) ; + #endif +} + +#ifndef TI_HASH_TEST WOLFSSL_API int wc_Md5Hash(const byte*data, word32 len, byte*hash) { return hashHash(data, len, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; } +#endif #endif /* NO_MD5 */ +#ifndef TI_HASH_TEST #if !defined(NO_SHA) WOLFSSL_API int wc_InitSha(Sha* sha) @@ -223,9 +298,7 @@ WOLFSSL_API int wc_Sha256Hash(const byte* data, word32 len, byte*hash) { return hashHash(data, len, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; } +#endif +#endif /* TI_HASH_TEST */ -#endif /* NO_SHA256 */ - -#endif /* WOLFSSL_TI_HASH */ - -#endif /* WOLFSSL_TI_HASH_H */ +#endif diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 0109b8363..2a91116a2 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -1,452 +1,473 @@ -/* sha.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 - -#if !defined(NO_SHA) - -#include -#include -#include - -#ifdef NO_INLINE - #include -#else - #include -#endif - -/* fips wrapper calls, user can call direct */ -#ifdef HAVE_FIPS - int wc_InitSha(Sha* sha) - { - return InitSha_fips(sha); - } - - - int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) - { - return ShaUpdate_fips(sha, data, len); - } - - - int wc_ShaFinal(Sha* sha, byte* out) - { - return ShaFinal_fips(sha,out); - } - - int wc_ShaHash(const byte* data, word32 sz, byte* out) - { - return ShaHash(data, sz, out); - } - -#else /* else build without fips */ - -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitSha wc_InitSha_sw -#define wc_ShaUpdate wc_ShaUpdate_sw -#define wc_ShaFinal wc_ShaFinal_sw -#endif - - -#ifdef FREESCALE_MMCAU - #include "cau_api.h" - #define XTRANSFORM(S,B) cau_sha1_hash_n((B), 1, ((S))->digest) -#else - #define XTRANSFORM(S,B) Transform((S)) -#endif - -#ifdef STM32F2_HASH -/* - * STM32F2 hardware SHA1 support through the STM32F2 standard peripheral - * library. Documentation located in STM32F2xx Standard Peripheral Library - * document (See note in README). - */ -#include "stm32f2xx.h" -#include "stm32f2xx_hash.h" - -int wc_InitSha(Sha* sha) -{ - /* STM32F2 struct notes: - * sha->buffer = first 4 bytes used to hold partial block if needed - * sha->buffLen = num bytes currently stored in sha->buffer - * sha->loLen = num bytes that have been written to STM32 FIFO - */ - XMEMSET(sha->buffer, 0, SHA_REG_SIZE); - sha->buffLen = 0; - sha->loLen = 0; - - /* initialize HASH peripheral */ - HASH_DeInit(); - - /* configure algo used, algo mode, datatype */ - HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); - HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH - | HASH_DataType_8b); - - /* reset HASH processor */ - HASH->CR |= HASH_CR_INIT; - - return 0; -} - -int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) -{ - word32 i = 0; - word32 fill = 0; - word32 diff = 0; - - /* if saved partial block is available */ - if (sha->buffLen) { - fill = 4 - sha->buffLen; - - /* if enough data to fill, fill and push to FIFO */ - if (fill <= len) { - XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill); - HASH_DataIn(*(uint32_t*)sha->buffer); - - data += fill; - len -= fill; - sha->loLen += 4; - sha->buffLen = 0; - } else { - /* append partial to existing stored block */ - XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); - sha->buffLen += len; - return; - } - } - - /* write input block in the IN FIFO */ - for(i = 0; i < len; i += 4) - { - diff = len - i; - if ( diff < 4) { - /* store incomplete last block, not yet in FIFO */ - XMEMSET(sha->buffer, 0, SHA_REG_SIZE); - XMEMCPY((byte*)sha->buffer, data, diff); - sha->buffLen = diff; - } else { - HASH_DataIn(*(uint32_t*)data); - data+=4; - } - } - - /* keep track of total data length thus far */ - sha->loLen += (len - sha->buffLen); - - return 0; -} - -int wc_ShaFinal(Sha* sha, byte* hash) -{ - __IO uint16_t nbvalidbitsdata = 0; - - /* finish reading any trailing bytes into FIFO */ - if (sha->buffLen) { - HASH_DataIn(*(uint32_t*)sha->buffer); - sha->loLen += sha->buffLen; - } - - /* calculate number of valid bits in last word of input data */ - nbvalidbitsdata = 8 * (sha->loLen % SHA_REG_SIZE); - - /* configure number of valid bits in last word of the data */ - HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); - - /* start HASH processor */ - HASH_StartDigest(); - - /* wait until Busy flag == RESET */ - while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} - - /* read message digest */ - sha->digest[0] = HASH->HR[0]; - sha->digest[1] = HASH->HR[1]; - sha->digest[2] = HASH->HR[2]; - sha->digest[3] = HASH->HR[3]; - sha->digest[4] = HASH->HR[4]; - - ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); - - XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); - - return wc_InitSha(sha); /* reset state */ -} - -#else /* wc_ software implementation */ - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -int wc_InitSha(Sha* sha) -{ -#ifdef FREESCALE_MMCAU - cau_sha1_initialize_output(sha->digest); -#else - sha->digest[0] = 0x67452301L; - sha->digest[1] = 0xEFCDAB89L; - sha->digest[2] = 0x98BADCFEL; - sha->digest[3] = 0x10325476L; - sha->digest[4] = 0xC3D2E1F0L; -#endif - - sha->buffLen = 0; - sha->loLen = 0; - sha->hiLen = 0; - - return 0; -} - -#ifndef FREESCALE_MMCAU - -#define blk0(i) (W[i] = sha->buffer[i]) -#define blk1(i) (W[(i)&15] = \ -rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1)) - -#define f1(x,y,z) ((z)^((x) &((y)^(z)))) -#define f2(x,y,z) ((x)^(y)^(z)) -#define f3(x,y,z) (((x)&(y))|((z)&((x)|(y)))) -#define f4(x,y,z) ((x)^(y)^(z)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); - -static void Transform(Sha* sha) -{ - word32 W[SHA_BLOCK_SIZE / sizeof(word32)]; - - /* Copy context->state[] to working vars */ - word32 a = sha->digest[0]; - word32 b = sha->digest[1]; - word32 c = sha->digest[2]; - word32 d = sha->digest[3]; - word32 e = sha->digest[4]; - -#ifdef USE_SLOW_SHA - word32 t, i; - - for (i = 0; i < 16; i++) { - R0(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 20; i++) { - R1(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 40; i++) { - R2(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 60; i++) { - R3(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 80; i++) { - R4(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } -#else - /* nearly 1 K bigger in code size but 25% faster */ - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); -#endif - - /* Add the working vars back into digest state[] */ - sha->digest[0] += a; - sha->digest[1] += b; - sha->digest[2] += c; - sha->digest[3] += d; - sha->digest[4] += e; -} - -#endif /* FREESCALE_MMCAU */ - - -static INLINE void AddLength(Sha* sha, word32 len) -{ - word32 tmp = sha->loLen; - if ( (sha->loLen += len) < tmp) - sha->hiLen++; /* carry low to high */ -} - - -int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) -{ - /* do block size increments */ - byte* local = (byte*)sha->buffer; - - while (len) { - word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); - XMEMCPY(&local[sha->buffLen], data, add); - - sha->buffLen += add; - data += add; - len -= add; - - if (sha->buffLen == SHA_BLOCK_SIZE) { -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); -#endif - XTRANSFORM(sha, local); - AddLength(sha, SHA_BLOCK_SIZE); - sha->buffLen = 0; - } - } - - return 0; -} - - -int wc_ShaFinal(Sha* sha, byte* hash) -{ - byte* local = (byte*)sha->buffer; - - AddLength(sha, sha->buffLen); /* before adding pads */ - - local[sha->buffLen++] = 0x80; /* add 1 */ - - /* pad with zeros */ - if (sha->buffLen > SHA_PAD_SIZE) { - XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen); - sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen; - -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); -#endif - XTRANSFORM(sha, local); - sha->buffLen = 0; - } - XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen); - - /* put lengths in bits */ - sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + - (sha->hiLen << 3); - sha->loLen = sha->loLen << 3; - - /* store lengths */ -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); -#endif - /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); - XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); - -#ifdef FREESCALE_MMCAU - /* Kinetis requires only these bytes reversed */ - ByteReverseWords(&sha->buffer[SHA_PAD_SIZE/sizeof(word32)], - &sha->buffer[SHA_PAD_SIZE/sizeof(word32)], - 2 * sizeof(word32)); -#endif - - XTRANSFORM(sha, local); -#ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); -#endif - XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); - - return wc_InitSha(sha); /* reset state */ -} - -#endif /* STM32F2_HASH */ - - -int wc_ShaHash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha* sha; -#else - Sha sha[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha(sha)) != 0) { - WOLFSSL_MSG("wc_InitSha failed"); - } - else { - wc_ShaUpdate(sha, data, len); - wc_ShaFinal(sha, hash); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; - -} -#endif /* HAVE_FIPS */ -#endif /* NO_SHA */ - +/* sha.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 + +#if !defined(NO_SHA) && !defined(WOLFSSL_TI_HASH) + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #include +#endif + +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + int wc_InitSha(Sha* sha) + { + return InitSha_fips(sha); + } + + + int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) + { + return ShaUpdate_fips(sha, data, len); + } + + + int wc_ShaFinal(Sha* sha, byte* out) + { + return ShaFinal_fips(sha,out); + } + + int wc_ShaHash(const byte* data, word32 sz, byte* out) + { + return ShaHash(data, sz, out); + } + +#else /* else build without fips */ + +#ifdef WOLFSSL_PIC32MZ_HASH +#define wc_InitSha wc_InitSha_sw +#define wc_ShaUpdate wc_ShaUpdate_sw +#define wc_ShaFinal wc_ShaFinal_sw +#endif + + +#ifdef FREESCALE_MMCAU + #include "cau_api.h" + #define XTRANSFORM(S,B) cau_sha1_hash_n((B), 1, ((S))->digest) +#else + #define XTRANSFORM(S,B) Transform((S)) +#endif + +#ifdef STM32F2_HASH +/* + * STM32F2 hardware SHA1 support through the STM32F2 standard peripheral + * library. Documentation located in STM32F2xx Standard Peripheral Library + * document (See note in README). + */ +#include "stm32f2xx.h" +#include "stm32f2xx_hash.h" + +int wc_InitSha(Sha* sha) +{ + /* STM32F2 struct notes: + * sha->buffer = first 4 bytes used to hold partial block if needed + * sha->buffLen = num bytes currently stored in sha->buffer + * sha->loLen = num bytes that have been written to STM32 FIFO + */ + XMEMSET(sha->buffer, 0, SHA_REG_SIZE); + sha->buffLen = 0; + sha->loLen = 0; + + /* initialize HASH peripheral */ + HASH_DeInit(); + + /* configure algo used, algo mode, datatype */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + + return 0; +} + +int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +{ + word32 i = 0; + word32 fill = 0; + word32 diff = 0; + + /* if saved partial block is available */ + if (sha->buffLen) { + fill = 4 - sha->buffLen; + + /* if enough data to fill, fill and push to FIFO */ + if (fill <= len) { + XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill); + HASH_DataIn(*(uint32_t*)sha->buffer); + + data += fill; + len -= fill; + sha->loLen += 4; + sha->buffLen = 0; + } else { + /* append partial to existing stored block */ + XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); + sha->buffLen += len; + return; + } + } + + /* write input block in the IN FIFO */ + for(i = 0; i < len; i += 4) + { + diff = len - i; + if ( diff < 4) { + /* store incomplete last block, not yet in FIFO */ + XMEMSET(sha->buffer, 0, SHA_REG_SIZE); + XMEMCPY((byte*)sha->buffer, data, diff); + sha->buffLen = diff; + } else { + HASH_DataIn(*(uint32_t*)data); + data+=4; + } + } + + /* keep track of total data length thus far */ + sha->loLen += (len - sha->buffLen); + + return 0; +} + +int wc_ShaFinal(Sha* sha, byte* hash) +{ + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (sha->buffLen) { + HASH_DataIn(*(uint32_t*)sha->buffer); + sha->loLen += sha->buffLen; + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (sha->loLen % SHA_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + sha->digest[0] = HASH->HR[0]; + sha->digest[1] = HASH->HR[1]; + sha->digest[2] = HASH->HR[2]; + sha->digest[3] = HASH->HR[3]; + sha->digest[4] = HASH->HR[4]; + + ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); + + XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); + + return wc_InitSha(sha); /* reset state */ +} + +#elif defined(WOLFSSL_TI_HASH) + + /* defined in port/ti/ti_sha.c */ + +#else /* wc_ software implementation */ + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +int wc_InitSha(Sha* sha) +{ +#ifdef FREESCALE_MMCAU + cau_sha1_initialize_output(sha->digest); +#else + sha->digest[0] = 0x67452301L; + sha->digest[1] = 0xEFCDAB89L; + sha->digest[2] = 0x98BADCFEL; + sha->digest[3] = 0x10325476L; + sha->digest[4] = 0xC3D2E1F0L; +#endif + + sha->buffLen = 0; + sha->loLen = 0; + sha->hiLen = 0; + + return 0; +} + +#ifndef FREESCALE_MMCAU + +#define blk0(i) (W[i] = sha->buffer[i]) +#define blk1(i) (W[(i)&15] = \ +rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1)) + +#define f1(x,y,z) ((z)^((x) &((y)^(z)))) +#define f2(x,y,z) ((x)^(y)^(z)) +#define f3(x,y,z) (((x)&(y))|((z)&((x)|(y)))) +#define f4(x,y,z) ((x)^(y)^(z)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); +#define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); +#define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); +#define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); +#define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); + +static void Transform(Sha* sha) +{ + word32 W[SHA_BLOCK_SIZE / sizeof(word32)]; + + /* Copy context->state[] to working vars */ + word32 a = sha->digest[0]; + word32 b = sha->digest[1]; + word32 c = sha->digest[2]; + word32 d = sha->digest[3]; + word32 e = sha->digest[4]; + +#ifdef USE_SLOW_SHA + word32 t, i; + + for (i = 0; i < 16; i++) { + R0(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 20; i++) { + R1(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; i++) { + R2(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; i++) { + R3(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; i++) { + R4(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } +#else + /* nearly 1 K bigger in code size but 25% faster */ + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); +#endif + + /* Add the working vars back into digest state[] */ + sha->digest[0] += a; + sha->digest[1] += b; + sha->digest[2] += c; + sha->digest[3] += d; + sha->digest[4] += e; +} + +#endif /* FREESCALE_MMCAU */ + + +static INLINE void AddLength(Sha* sha, word32 len) +{ + word32 tmp = sha->loLen; + if ( (sha->loLen += len) < tmp) + sha->hiLen++; /* carry low to high */ +} + + +int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local = (byte*)sha->buffer; + + while (len) { + word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, add); + + sha->buffLen += add; + data += add; + len -= add; + + if (sha->buffLen == SHA_BLOCK_SIZE) { +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); +#endif + XTRANSFORM(sha, local); + AddLength(sha, SHA_BLOCK_SIZE); + sha->buffLen = 0; + } + } + + return 0; +} + + +int wc_ShaFinal(Sha* sha, byte* hash) +{ + byte* local = (byte*)sha->buffer; + + AddLength(sha, sha->buffLen); /* before adding pads */ + + local[sha->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha->buffLen > SHA_PAD_SIZE) { + XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen); + sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen; + +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); +#endif + XTRANSFORM(sha, local); + sha->buffLen = 0; + } + XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen); + + /* put lengths in bits */ + sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + + (sha->hiLen << 3); + sha->loLen = sha->loLen << 3; + + /* store lengths */ +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); +#endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); + XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); + +#ifdef FREESCALE_MMCAU + /* Kinetis requires only these bytes reversed */ + ByteReverseWords(&sha->buffer[SHA_PAD_SIZE/sizeof(word32)], + &sha->buffer[SHA_PAD_SIZE/sizeof(word32)], + 2 * sizeof(word32)); +#endif + + XTRANSFORM(sha, local); +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); +#endif + XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); + + return wc_InitSha(sha); /* reset state */ +} + +#endif /* STM32F2_HASH */ + + +int wc_ShaHash(const byte* data, word32 len, byte* hash) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Sha* sha; +#else + Sha sha[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return MEMORY_E; +#endif + + if ((ret = wc_InitSha(sha)) != 0) { + WOLFSSL_MSG("wc_InitSha failed"); + } + else { + wc_ShaUpdate(sha, data, len); + wc_ShaFinal(sha, hash); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; + +} + +#ifdef WOLFSSL_TI_HASH +#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif +int wc_ShaGetHash(Sha* sha, byte* hash) +{ +#if defined(WOLFSS_TI_HASH) + wc_ShaGetHash_TI(sha, hash) ; +#else + int ret ; + Sha save = *sha ; + ret = wc_ShaFinal(sha, hash) ; + *sha = save ; + return ret ; +#endif +} + +#endif /* HAVE_FIPS */ +#endif /* NO_SHA */ + diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c old mode 100755 new mode 100644 index 2821166b4..ec4eb918b --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -1,1759 +1,1781 @@ -/* sha256.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 - */ - -/* code submitted by raphael.huck@efixo.com */ - -#ifdef HAVE_CONFIG_H - #include -#endif - -#include -#include - -#if !defined(NO_SHA256) -#ifdef HAVE_FIPS - -int wc_InitSha256(Sha256* sha) -{ - return InitSha256_fips(sha); -} - - -int wc_Sha256Update(Sha256* sha, const byte* data, word32 len) -{ - return Sha256Update_fips(sha, data, len); -} - - -int wc_Sha256Final(Sha256* sha, byte* out) -{ - return Sha256Final_fips(sha, out); -} - - -int wc_Sha256Hash(const byte* data, word32 len, byte* out) -{ - return Sha256Hash(data, len, out); -} - -#else /* else build without fips */ - -#if !defined (ALIGN32) - #if defined (__GNUC__) - #define ALIGN32 __attribute__ ( (aligned (32))) - #elif defined(_MSC_VER) - /* disable align warning, we want alignment ! */ - #pragma warning(disable: 4324) - #define ALIGN32 __declspec (align (32)) - #else - #define ALIGN32 - #endif -#endif - -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitSha256 wc_InitSha256_sw -#define wc_Sha256Update wc_Sha256Update_sw -#define wc_Sha256Final wc_Sha256Final_sw -#endif - -#ifdef HAVE_FIPS - /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ - #define FIPS_NO_WRAPPERS -#endif - -#if defined(USE_INTEL_SPEEDUP) -#define HAVE_INTEL_AVX1 -#define HAVE_INTEL_AVX2 - -#if defined(DEBUG_XMM) -#include "stdio.h" -#endif - -#endif - -#if defined(HAVE_INTEL_AVX2) -#define HAVE_INTEL_RORX -#endif - - -/***** -Intel AVX1/AVX2 Macro Control Structure - -#define HAVE_INTEL_AVX1 -#define HAVE_INTEL_AVX2 - -#define HAVE_INTEL_RORX - - -int InitSha256(Sha256* sha256) { - Save/Recover XMM, YMM - ... -} - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - Transform() ; Function prototype -#else - Transform() { } - int Sha256Final() { - Save/Recover XMM, YMM - ... - } -#endif - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - #if defined(HAVE_INTEL_RORX - #define RND with rorx instuction - #else - #define RND - #endif -#endif - -#if defined(HAVE_INTEL_AVX1) - - #define XMM Instructions/inline asm - - int Transform() { - Stitched Message Sched/Round - } - -#elif defined(HAVE_INTEL_AVX2) - - #define YMM Instructions/inline asm - - int Transform() { - More granural Stitched Message Sched/Round - } - -*/ - - -#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - -/* Each platform needs to query info type 1 from cpuid to see if aesni is - * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts - */ - -#ifndef _MSC_VER - #define cpuid(reg, leaf, sub)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (leaf), "c"(sub)); - - #define XASM_LINK(f) asm(f) -#else - - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - -#define EAX 0 -#define EBX 1 -#define ECX 2 -#define EDX 3 - -#define CPUID_AVX1 0x1 -#define CPUID_AVX2 0x2 -#define CPUID_RDRAND 0x4 -#define CPUID_RDSEED 0x8 -#define CPUID_BMI2 0x10 /* MULX, RORX */ - -#define IS_INTEL_AVX1 (cpuid_flags&CPUID_AVX1) -#define IS_INTEL_AVX2 (cpuid_flags&CPUID_AVX2) -#define IS_INTEL_BMI2 (cpuid_flags&CPUID_BMI2) -#define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) -#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) - -static word32 cpuid_check = 0 ; -static word32 cpuid_flags = 0 ; - -static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { - int got_intel_cpu=0; - unsigned int reg[5]; - - reg[4] = '\0' ; - cpuid(reg, 0, 0); - if(memcmp((char *)&(reg[EBX]), "Genu", 4) == 0 && - memcmp((char *)&(reg[EDX]), "ineI", 4) == 0 && - memcmp((char *)&(reg[ECX]), "ntel", 4) == 0) { - got_intel_cpu = 1; - } - if (got_intel_cpu) { - cpuid(reg, leaf, sub); - return((reg[num]>>bit)&0x1) ; - } - return 0 ; -} - -static int set_cpuid_flags(void) { - if(cpuid_check==0) { - if(cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1 ;} - if(cpuid_flag(7, 0, EBX, 5)){ cpuid_flags |= CPUID_AVX2 ; } - if(cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } - if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ; } - if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ; } - cpuid_check = 1 ; - return 0 ; - } - return 1 ; -} - - -/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha512 */ -static int Transform(Sha256* sha256); - -#if defined(HAVE_INTEL_AVX1) -static int Transform_AVX1(Sha256 *sha256) ; -#endif -#if defined(HAVE_INTEL_AVX2) -static int Transform_AVX2(Sha256 *sha256) ; -static int Transform_AVX1_RORX(Sha256 *sha256) ; -#endif - -static int (*Transform_p)(Sha256* sha256) /* = _Transform */; - -#define XTRANSFORM(sha256, B) (*Transform_p)(sha256) - -static void set_Transform(void) { - if(set_cpuid_flags())return ; - -#if defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ - Transform_p = Transform_AVX1_RORX; return ; - Transform_p = Transform_AVX2 ; - /* for avoiding warning,"not used" */ - } -#endif -#if defined(HAVE_INTEL_AVX1) - Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : Transform) ; return ; -#endif - Transform_p = Transform ; return ; -} - -#else - #if defined(FREESCALE_MMCAU) - #define XTRANSFORM(sha256, B) Transform(sha256, B) - #else - #define XTRANSFORM(sha256, B) Transform(sha256) - #endif -#endif - -/* Dummy for saving MM_REGs on behalf of Transform */ -#if defined(HAVE_INTEL_AVX2)&& !defined(HAVE_INTEL_AVX1) -#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ - "%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15") -#elif defined(HAVE_INTEL_AVX1) -#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ - "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10",\ - "xmm11","xmm12","xmm13","xmm14","xmm15") -#else -#define SAVE_XMM_YMM -#endif - -#ifdef WOLFSSL_PIC32MZ_HASH -#define InitSha256 InitSha256_sw -#define Sha256Update Sha256Update_sw -#define Sha256Final Sha256Final_sw -#endif - -#include -#include - -#ifdef NO_INLINE - #include -#else - #include -#endif - -#ifdef FREESCALE_MMCAU - #include "cau_api.h" -#endif - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -int wc_InitSha256(Sha256* sha256) -{ - #ifdef FREESCALE_MMCAU - cau_sha256_initialize_output(sha256->digest); - #else - sha256->digest[0] = 0x6A09E667L; - sha256->digest[1] = 0xBB67AE85L; - sha256->digest[2] = 0x3C6EF372L; - sha256->digest[3] = 0xA54FF53AL; - sha256->digest[4] = 0x510E527FL; - sha256->digest[5] = 0x9B05688CL; - sha256->digest[6] = 0x1F83D9ABL; - sha256->digest[7] = 0x5BE0CD19L; - #endif - - sha256->buffLen = 0; - sha256->loLen = 0; - sha256->hiLen = 0; - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; /* choose best Transform function under this runtime environment */ -#endif - - return 0; -} - - -#if !defined(FREESCALE_MMCAU) -static const ALIGN32 word32 K[64] = { - 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, - 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, - 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, - 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, - 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L, - 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L, - 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, - 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, - 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L, - 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L, - 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, - 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, - 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L -}; - -#endif - -#if defined(FREESCALE_MMCAU) - -static int Transform(Sha256* sha256, byte* buf) -{ - cau_sha256_hash_n(buf, 1, sha256->digest); - - return 0; -} - -#endif /* FREESCALE_MMCAU */ - -#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) -#define R(x, n) (((x)&0xFFFFFFFFU)>>(n)) - -#define S(x, n) rotrFixed(x, n) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - -#define RND(a,b,c,d,e,f,g,h,i) \ - t0 = (h) + Sigma1((e)) + Ch((e), (f), (g)) + K[(i)] + W[(i)]; \ - t1 = Sigma0((a)) + Maj((a), (b), (c)); \ - (d) += t0; \ - (h) = t0 + t1; - -#if !defined(FREESCALE_MMCAU) -static int Transform(Sha256* sha256) -{ - word32 S[8], t0, t1; - int i; - -#ifdef WOLFSSL_SMALL_STACK - word32* W; - - W = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (W == NULL) - return MEMORY_E; -#else - word32 W[64]; -#endif - - /* Copy context->state[] to working vars */ - for (i = 0; i < 8; i++) - S[i] = sha256->digest[i]; - - for (i = 0; i < 16; i++) - W[i] = sha256->buffer[i]; - - for (i = 16; i < 64; i++) - W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; - - for (i = 0; i < 64; i += 8) { - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); - } - - /* Add the working vars back into digest state[] */ - for (i = 0; i < 8; i++) { - sha256->digest[i] += S[i]; - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return 0; -} - -#endif /* #if !defined(FREESCALE_MMCAU) */ - -static INLINE void AddLength(Sha256* sha256, word32 len) -{ - word32 tmp = sha256->loLen; - if ( (sha256->loLen += len) < tmp) - sha256->hiLen++; /* carry low to high */ -} - -int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) -{ - - /* do block size increments */ - byte* local = (byte*)sha256->buffer; - - SAVE_XMM_YMM ; /* for Intel AVX */ - - while (len) { - word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); - XMEMCPY(&local[sha256->buffLen], data, add); - - sha256->buffLen += add; - data += add; - len -= add; - - if (sha256->buffLen == SHA256_BLOCK_SIZE) { - int ret; - - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords(sha256->buffer, sha256->buffer, - SHA256_BLOCK_SIZE); - #endif - ret = XTRANSFORM(sha256, local); - if (ret != 0) - return ret; - - AddLength(sha256, SHA256_BLOCK_SIZE); - sha256->buffLen = 0; - } - } - - return 0; -} - -int wc_Sha256Final(Sha256* sha256, byte* hash) -{ - byte* local = (byte*)sha256->buffer; - int ret; - - SAVE_XMM_YMM ; /* for Intel AVX */ - - AddLength(sha256, sha256->buffLen); /* before adding pads */ - - local[sha256->buffLen++] = 0x80; /* add 1 */ - - /* pad with zeros */ - if (sha256->buffLen > SHA256_PAD_SIZE) { - XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen); - sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; - - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); - #endif - - ret = XTRANSFORM(sha256, local); - if (ret != 0) - return ret; - - sha256->buffLen = 0; - } - XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen); - - /* put lengths in bits */ - sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) + - (sha256->hiLen << 3); - sha256->loLen = sha256->loLen << 3; - - /* store lengths */ - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); - #endif - /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); - XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, - sizeof(word32)); - - #if defined(FREESCALE_MMCAU) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - /* Kinetis requires only these bytes reversed */ - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX1 || IS_INTEL_AVX2) - #endif - ByteReverseWords(&sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], - &sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], - 2 * sizeof(word32)); - #endif - - ret = XTRANSFORM(sha256, local); - if (ret != 0) - return ret; - - #if defined(LITTLE_ENDIAN_ORDER) - ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE); - #endif - XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE); - - return wc_InitSha256(sha256); /* reset state */ -} - - - -int wc_Sha256Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha256* sha256; -#else - Sha256 sha256[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha256(sha256)) != 0) { - WOLFSSL_MSG("InitSha256 failed"); - } - else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { - WOLFSSL_MSG("Sha256Update failed"); - } - else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { - WOLFSSL_MSG("Sha256Final failed"); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - -#define _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ;\ - d = sha256->digest[0]; __asm__ volatile("movl %0, %"#S_0::"r"(d):SSE_REGs) ;\ - d = sha256->digest[1]; __asm__ volatile("movl %0, %"#S_1::"r"(d):SSE_REGs) ;\ - d = sha256->digest[2]; __asm__ volatile("movl %0, %"#S_2::"r"(d):SSE_REGs) ;\ - d = sha256->digest[3]; __asm__ volatile("movl %0, %"#S_3::"r"(d):SSE_REGs) ;\ - d = sha256->digest[4]; __asm__ volatile("movl %0, %"#S_4::"r"(d):SSE_REGs) ;\ - d = sha256->digest[5]; __asm__ volatile("movl %0, %"#S_5::"r"(d):SSE_REGs) ;\ - d = sha256->digest[6]; __asm__ volatile("movl %0, %"#S_6::"r"(d):SSE_REGs) ;\ - d = sha256->digest[7]; __asm__ volatile("movl %0, %"#S_7::"r"(d):SSE_REGs) ;\ -} - -#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ; \ - __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ; sha256->digest[0] += d;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ; sha256->digest[1] += d;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ; sha256->digest[2] += d;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ; sha256->digest[3] += d;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ; sha256->digest[4] += d;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ; sha256->digest[5] += d;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ; sha256->digest[6] += d;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ; sha256->digest[7] += d;\ -} - - -#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - -#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - - - - -#define S_0 %r15d -#define S_1 %r10d -#define S_2 %r11d -#define S_3 %r12d -#define S_4 %r13d -#define S_5 %r14d -#define S_6 %ebx -#define S_7 %r9d - -#define SSE_REGs "%edi", "%ecx", "%esi", "%edx", "%ebx","%r8","%r9","%r10","%r11","%r12","%r13","%r14","%r15" - -#if defined(HAVE_INTEL_RORX) -#define RND_STEP_RORX_1(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("rorx $6, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ - -#define RND_STEP_RORX_2(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("rorx $11, %"#e",%%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ -__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ -__asm__ volatile("rorx $25, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ - -#define RND_STEP_RORX_3(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ -__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ - -#define RND_STEP_RORX_4(a,b,c,d,e,f,g,h,i)\ -/*__asm__ volatile("movl %0, %%edx\n\t"::"m"(w_k):"%edx");*/\ -__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ -__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ -__asm__ volatile("rorx $2, %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ -__asm__ volatile("rorx $13, %"#a", %%edi\n\t":::"%edi",SSE_REGs);/* edi = a>>13 */\ - -#define RND_STEP_RORX_5(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("rorx $22, %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ -__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs);/* edi = (a>>2) ^ (a>>13) */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma0(a) */\ - -#define RND_STEP_RORX_6(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ -__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ -__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c*/\ -__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ - -#define RND_STEP_RORX_7(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ -__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ -__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ - -#define RND_STEP_RORX_8(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ -__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ -__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs); \ -__asm__ volatile("movl %r8d, "#h"\n\t"); - -#endif - -#define RND_STEP_1(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs);\ -__asm__ volatile("roll $26, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ -__asm__ volatile("movl %"#e", %%edi\n\t":::"%edi",SSE_REGs);\ - -#define RND_STEP_2(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("roll $21, %%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ -__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ -__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e */\ -__asm__ volatile("roll $7, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ - -#define RND_STEP_3(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ -__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ - -#define RND_STEP_4(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ -__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ -__asm__ volatile("movl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a */\ -__asm__ volatile("roll $30, %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ -__asm__ volatile("movl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a */\ -__asm__ volatile("roll $19, %%edi\n\t":::"%edi",SSE_REGs); /* edi = a>>13 */\ -__asm__ volatile("movl %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a */\ - -#define RND_STEP_5(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("roll $10, %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ -__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs); /* edi = (a>>2) ^ (a>>13) */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs);/* edx = Sigma0(a) */\ - -#define RND_STEP_6(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ -__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ -__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c */\ -__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ - -#define RND_STEP_7(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ -__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ -__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ - -#define RND_STEP_8(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ -__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ - /* r8b = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */\ -__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs);\ - /* r8b = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */\ -__asm__ volatile("movl %%r8d, %"#h"\n\t":::"%r8", SSE_REGs); \ - /* h = h + w_k + Sigma1(e) + Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ - -#define RND_X(a,b,c,d,e,f,g,h,i) \ - RND_STEP_1(a,b,c,d,e,f,g,h,i); \ - RND_STEP_2(a,b,c,d,e,f,g,h,i); \ - RND_STEP_3(a,b,c,d,e,f,g,h,i); \ - RND_STEP_4(a,b,c,d,e,f,g,h,i); \ - RND_STEP_5(a,b,c,d,e,f,g,h,i); \ - RND_STEP_6(a,b,c,d,e,f,g,h,i); \ - RND_STEP_7(a,b,c,d,e,f,g,h,i); \ - RND_STEP_8(a,b,c,d,e,f,g,h,i); - -#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - - -#define RND_1_3(a,b,c,d,e,f,g,h,i) {\ - RND_STEP_1(a,b,c,d,e,f,g,h,i); \ - RND_STEP_2(a,b,c,d,e,f,g,h,i); \ - RND_STEP_3(a,b,c,d,e,f,g,h,i); \ -} - -#define RND_4_6(a,b,c,d,e,f,g,h,i) {\ - RND_STEP_4(a,b,c,d,e,f,g,h,i); \ - RND_STEP_5(a,b,c,d,e,f,g,h,i); \ - RND_STEP_6(a,b,c,d,e,f,g,h,i); \ -} - -#define RND_7_8(a,b,c,d,e,f,g,h,i) {\ - RND_STEP_7(a,b,c,d,e,f,g,h,i); \ - RND_STEP_8(a,b,c,d,e,f,g,h,i); \ -} - -#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - - -#define RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - -#define RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - -#define RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - -#define FOR(cnt, init, max, inc, loop) \ - __asm__ volatile("movl $"#init", %0\n\t"#loop":"::"m"(cnt):) -#define END(cnt, init, max, inc, loop) \ - __asm__ volatile("addl $"#inc", %0\n\tcmpl $"#max", %0\n\tjle "#loop"\n\t":"=m"(cnt)::) ; - -#endif /* defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) */ - -#if defined(HAVE_INTEL_AVX1) /* inline Assember for Intel AVX1 instructions */ - -#define VPALIGNR(op1,op2,op3,op4) __asm__ volatile("vpalignr $"#op4", %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPADDD(op1,op2,op3) __asm__ volatile("vpaddd %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSRLD(op1,op2,op3) __asm__ volatile("vpsrld $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSRLQ(op1,op2,op3) __asm__ volatile("vpsrlq $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSLLD(op1,op2,op3) __asm__ volatile("vpslld $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPOR(op1,op2,op3) __asm__ volatile("vpor %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPXOR(op1,op2,op3) __asm__ volatile("vpxor %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSHUFD(op1,op2,op3) __asm__ volatile("vpshufd $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSHUFB(op1,op2,op3) __asm__ volatile("vpshufb %"#op3", %"#op2", %"#op1:::XMM_REGs) - -#define MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, SHUF_00BA, SHUF_DC00,\ - a,b,c,d,e,f,g,h,_i)\ - RND_STEP_1(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP0, X3, X2, 4) ;\ - RND_STEP_2(a,b,c,d,e,f,g,h,_i);\ - VPADDD (XTMP0, XTMP0, X0) ;\ - RND_STEP_3(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ - RND_STEP_4(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1, 7) ;\ - RND_STEP_5(a,b,c,d,e,f,g,h,_i);\ - VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ - RND_STEP_6(a,b,c,d,e,f,g,h,_i);\ - VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ - RND_STEP_7(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1,18) ;\ - RND_STEP_8(a,b,c,d,e,f,g,h,_i);\ -\ - RND_STEP_1(h,a,b,c,d,e,f,g,_i+1);\ - VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ - RND_STEP_2(h,a,b,c,d,e,f,g,_i+1);\ - VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ - RND_STEP_3(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP1) ;\ - RND_STEP_4(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ - RND_STEP_5(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ - RND_STEP_6(h,a,b,c,d,e,f,g,_i+1);\ - VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ - RND_STEP_7(h,a,b,c,d,e,f,g,_i+1);\ - VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ - RND_STEP_8(h,a,b,c,d,e,f,g,_i+1);\ -\ - RND_STEP_1(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ - RND_STEP_2(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ - RND_STEP_3(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ - RND_STEP_4(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_5(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ - RND_STEP_6(g,h,a,b,c,d,e,f,_i+2);\ - VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ - RND_STEP_7(g,h,a,b,c,d,e,f,_i+2);\ - VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ - RND_STEP_8(g,h,a,b,c,d,e,f,_i+2);\ -\ - RND_STEP_1(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ - RND_STEP_2(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ - RND_STEP_3(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ - RND_STEP_4(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ - RND_STEP_5(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_6(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ - RND_STEP_7(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ - RND_STEP_8(f,g,h,a,b,c,d,e,_i+3);\ - VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ - -#if defined(HAVE_INTEL_RORX) - -#define MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, \ - XFER, SHUF_00BA, SHUF_DC00,a,b,c,d,e,f,g,h,_i)\ - RND_STEP_RORX_1(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP0, X3, X2, 4) ;\ - RND_STEP_RORX_2(a,b,c,d,e,f,g,h,_i);\ - VPADDD (XTMP0, XTMP0, X0) ;\ - RND_STEP_RORX_3(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ - RND_STEP_RORX_4(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1, 7) ;\ - RND_STEP_RORX_5(a,b,c,d,e,f,g,h,_i);\ - VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ - RND_STEP_RORX_6(a,b,c,d,e,f,g,h,_i);\ - VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ - RND_STEP_RORX_7(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1,18) ;\ - RND_STEP_RORX_8(a,b,c,d,e,f,g,h,_i);\ -\ - RND_STEP_RORX_1(h,a,b,c,d,e,f,g,_i+1);\ - VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ - RND_STEP_RORX_2(h,a,b,c,d,e,f,g,_i+1);\ - VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ - RND_STEP_RORX_3(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP1) ;\ - RND_STEP_RORX_4(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ - RND_STEP_RORX_5(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ - RND_STEP_RORX_6(h,a,b,c,d,e,f,g,_i+1);\ - VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ - RND_STEP_RORX_7(h,a,b,c,d,e,f,g,_i+1);\ - VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ - RND_STEP_RORX_8(h,a,b,c,d,e,f,g,_i+1);\ -\ - RND_STEP_RORX_1(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ - RND_STEP_RORX_2(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ - RND_STEP_RORX_3(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ - RND_STEP_RORX_4(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_RORX_5(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ - RND_STEP_RORX_6(g,h,a,b,c,d,e,f,_i+2);\ - VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ - RND_STEP_RORX_7(g,h,a,b,c,d,e,f,_i+2);\ - VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ - RND_STEP_RORX_8(g,h,a,b,c,d,e,f,_i+2);\ -\ - RND_STEP_RORX_1(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ - RND_STEP_RORX_2(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ - RND_STEP_RORX_3(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ - RND_STEP_RORX_4(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ - RND_STEP_RORX_5(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_RORX_6(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ - RND_STEP_RORX_7(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ - RND_STEP_RORX_8(f,g,h,a,b,c,d,e,_i+3);\ - VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ - -#endif - - -#define W_K_from_buff\ - __asm__ volatile("vmovdqu %0, %%xmm4\n\t"\ - "vpshufb %%xmm13, %%xmm4, %%xmm4\n\t"\ - :: "m"(sha256->buffer[0]):"%xmm4") ;\ - __asm__ volatile("vmovdqu %0, %%xmm5\n\t"\ - "vpshufb %%xmm13, %%xmm5, %%xmm5\n\t"\ - ::"m"(sha256->buffer[4]):"%xmm5") ;\ - __asm__ volatile("vmovdqu %0, %%xmm6\n\t"\ - "vpshufb %%xmm13, %%xmm6, %%xmm6\n\t"\ - ::"m"(sha256->buffer[8]):"%xmm6") ;\ - __asm__ volatile("vmovdqu %0, %%xmm7\n\t"\ - "vpshufb %%xmm13, %%xmm7, %%xmm7\n\t"\ - ::"m"(sha256->buffer[12]):"%xmm7") ;\ - -#define _SET_W_K_XFER(reg, i)\ - __asm__ volatile("vpaddd %0, %"#reg", %%xmm9"::"m"(K[i]):XMM_REGs) ;\ - __asm__ volatile("vmovdqa %%xmm9, %0":"=m"(W_K[i])::XMM_REGs) ; - -#define SET_W_K_XFER(reg, i) _SET_W_K_XFER(reg, i) - -static const ALIGN32 word64 mSHUF_00BA[] = { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF } ; /* shuffle xBxA -> 00BA */ -static const ALIGN32 word64 mSHUF_DC00[] = { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 } ; /* shuffle xDxC -> DC00 */ -static const ALIGN32 word64 mBYTE_FLIP_MASK[] = { 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - - -#define _Init_Masks(mask1, mask2, mask3)\ -__asm__ volatile("vmovdqu %0, %"#mask1 ::"m"(mBYTE_FLIP_MASK[0])) ;\ -__asm__ volatile("vmovdqu %0, %"#mask2 ::"m"(mSHUF_00BA[0])) ;\ -__asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])) ; - -#define Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)\ - _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) - -#define X0 %xmm4 -#define X1 %xmm5 -#define X2 %xmm6 -#define X3 %xmm7 -#define X_ X0 - -#define XTMP0 %xmm0 -#define XTMP1 %xmm1 -#define XTMP2 %xmm2 -#define XTMP3 %xmm3 -#define XTMP4 %xmm8 -#define XTMP5 %xmm9 -#define XFER %xmm10 - -#define SHUF_00BA %xmm11 /* shuffle xBxA -> 00BA */ -#define SHUF_DC00 %xmm12 /* shuffle xDxC -> DC00 */ -#define BYTE_FLIP_MASK %xmm13 - -#define XMM_REGs /* Registers are saved in Sha256Update/Finel */ - /*"xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13" */ - -static int Transform_AVX1(Sha256* sha256) -{ - - word32 W_K[64] ; /* temp for W+K */ - - #if defined(DEBUG_XMM) - int i, j ; - word32 xmm[29][4*15] ; - #endif - - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ - - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - SET_W_K_XFER(X0, 0) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - SET_W_K_XFER(X1, 4) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; - SET_W_K_XFER(X2, 8) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - SET_W_K_XFER(X3, 12) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; - SET_W_K_XFER(X0, 16) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - SET_W_K_XFER(X1, 20) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; - SET_W_K_XFER(X2, 24) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - SET_W_K_XFER(X3, 28) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; - SET_W_K_XFER(X0, 32) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - SET_W_K_XFER(X1, 36) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; - SET_W_K_XFER(X2, 40) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - SET_W_K_XFER(X3, 44) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; - - SET_W_K_XFER(X0, 48) ; - SET_W_K_XFER(X1, 52) ; - SET_W_K_XFER(X2, 56) ; - SET_W_K_XFER(X3, 60) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - #if defined(DEBUG_XMM) - for(i=0; i<29; i++) { - for(j=0; j<4*14; j+=4) - printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, - xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; - printf("\n") ; - } - - for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; - #endif - - return 0; -} - -#if defined(HAVE_INTEL_RORX) -static int Transform_AVX1_RORX(Sha256* sha256) -{ - - word32 W_K[64] ; /* temp for W+K */ - - #if defined(DEBUG_XMM) - int i, j ; - word32 xmm[29][4*15] ; - #endif - - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ - - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - SET_W_K_XFER(X0, 0) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - SET_W_K_XFER(X1, 4) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; - SET_W_K_XFER(X2, 8) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - SET_W_K_XFER(X3, 12) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; - SET_W_K_XFER(X0, 16) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - SET_W_K_XFER(X1, 20) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; - SET_W_K_XFER(X2, 24) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - SET_W_K_XFER(X3, 28) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; - SET_W_K_XFER(X0, 32) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - SET_W_K_XFER(X1, 36) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; - SET_W_K_XFER(X2, 40) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - SET_W_K_XFER(X3, 44) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; - - SET_W_K_XFER(X0, 48) ; - SET_W_K_XFER(X1, 52) ; - SET_W_K_XFER(X2, 56) ; - SET_W_K_XFER(X3, 60) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - #if defined(DEBUG_XMM) - for(i=0; i<29; i++) { - for(j=0; j<4*14; j+=4) - printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, - xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; - printf("\n") ; - } - - for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; - #endif - - return 0; -} -#endif /* HAVE_INTEL_RORX */ - -#endif /* HAVE_INTEL_AVX1 */ - - -#if defined(HAVE_INTEL_AVX2) - -#define _MOVE_to_REG(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" ":: "m"(mem):YMM_REGs) ; -#define _MOVE_to_MEM(mem, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" : "=m"(mem)::YMM_REGs) ; -#define _BYTE_SWAP(ymm, map) __asm__ volatile("vpshufb %0, %%"#ymm", %%"#ymm"\n\t"\ - :: "m"(map):YMM_REGs) ; -#define _MOVE_128(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"#map", %%"\ - #ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; -#define _MOVE_BYTE(ymm0, ymm1, map) __asm__ volatile("vpshufb %0, %%"#ymm1", %%"\ - #ymm0"\n\t":: "m"(map):YMM_REGs) ; -#define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrld $"#bits", %%"\ - #src", %%"#dest"\n\tvpslld $32-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ - #temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; -#define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrld $"#bits", %%"\ - #src", %%"#dest" ":::YMM_REGs) ; -#define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _ADD(dest, src1, src2) __asm__ volatile("vpaddd %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddd %0, %%"#src1", %%"\ - #dest" "::"m"(mem):YMM_REGs) ; -#define _BLEND(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ - #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; - -#define _EXTRACT_XMM_0(xmm, mem) __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_1(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_2(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_3(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_4(ymm, xmm, mem)\ - __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ;\ - __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_5(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_6(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_7(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; - -#define _SWAP_YMM_HL(ymm) __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ; -#define SWAP_YMM_HL(ymm) _SWAP_YMM_HL(ymm) - -#define MOVE_to_REG(ymm, mem) _MOVE_to_REG(ymm, mem) -#define MOVE_to_MEM(mem, ymm) _MOVE_to_MEM(mem, ymm) -#define BYTE_SWAP(ymm, map) _BYTE_SWAP(ymm, map) -#define MOVE_128(ymm0, ymm1, ymm2, map) _MOVE_128(ymm0, ymm1, ymm2, map) -#define MOVE_BYTE(ymm0, ymm1, map) _MOVE_BYTE(ymm0, ymm1, map) -#define XOR(dest, src1, src2) _XOR(dest, src1, src2) -#define OR(dest, src1, src2) _OR(dest, src1, src2) -#define ADD(dest, src1, src2) _ADD(dest, src1, src2) -#define ADD_MEM(dest, src1, mem) _ADD_MEM(dest, src1, mem) -#define BLEND(map, dest, src1, src2) _BLEND(map, dest, src1, src2) - -#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); -#define AVX2_S(dest, src, bits) S_TMP(dest, src, bits, S_TEMP) -#define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) - -#define GAMMA0(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); \ - XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); XOR(dest, G_TEMP, dest) ; -#define GAMMA0_1(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); -#define GAMMA0_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); \ - XOR(dest, G_TEMP, dest) ; - -#define GAMMA1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); \ - XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); XOR(dest, G_TEMP, dest) ; -#define GAMMA1_1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); -#define GAMMA1_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); \ - XOR(dest, G_TEMP, dest) ; - -#define FEEDBACK1_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP1toW_I_2[0]) ; \ - BLEND(0x0c, W_I_2, YMM_TEMP0, W_I_2) ; -#define FEEDBACK2_to_W_I_2 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ; \ - MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAP2toW_I_2[0]) ; BLEND(0x30, W_I_2, YMM_TEMP0, W_I_2) ; -#define FEEDBACK3_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP3toW_I_2[0]) ; \ - BLEND(0xc0, W_I_2, YMM_TEMP0, W_I_2) ; - -#define FEEDBACK_to_W_I_7 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ;\ - MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAPtoW_I_7[0]) ; BLEND(0x80, W_I_7, YMM_TEMP0, W_I_7) ; - -#undef voitle - -#define W_I_16 ymm8 -#define W_I_15 ymm9 -#define W_I_7 ymm10 -#define W_I_2 ymm11 -#define W_I ymm12 -#define G_TEMP ymm13 -#define S_TEMP ymm14 -#define YMM_TEMP0 ymm15 -#define YMM_TEMP0x xmm15 -#define W_I_TEMP ymm7 -#define W_K_TEMP ymm15 -#define W_K_TEMPx xmm15 - -#define YMM_REGs /* Registers are saved in Sha256Update/Finel */ - /* "%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15"*/ - - -#define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - -#define MOVE_7_to_15(w_i_15, w_i_7)\ - __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - -#define MOVE_I_to_7(w_i_7, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ - -#define MOVE_I_to_2(w_i_2, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ - -#define ROTATE_W(w_i_16, w_i_15, w_i_7, w_i_2, w_i)\ - MOVE_15_to_16(w_i_16, w_i_15, w_i_7) ; \ - MOVE_7_to_15(w_i_15, w_i_7) ; \ - MOVE_I_to_7(w_i_7, w_i) ; \ - MOVE_I_to_2(w_i_2, w_i) ;\ - -#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ;\ - __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[0] += d;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[1] += d;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[2] += d;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[3] += d;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[4] += d;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[5] += d;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[6] += d;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[7] += d;\ -} - -#define _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d[8] ;\ - __asm__ volatile("movl %"#S_0", %0":"=r"(d[0])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d[1])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d[2])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d[3])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d[4])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d[5])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d[6])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d[7])::SSE_REGs) ;\ - printf("S[0..7]=%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);\ - __asm__ volatile("movl %0, %"#S_0::"r"(d[0]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_1::"r"(d[1]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_2::"r"(d[2]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_3::"r"(d[3]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_4::"r"(d[4]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_5::"r"(d[5]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_6::"r"(d[6]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_7::"r"(d[7]):SSE_REGs) ;\ -} - - -#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - -#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - -#define DumS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - - - /* Byte swap Masks to ensure that rest of the words are filled with zero's. */ - static const unsigned long mBYTE_FLIP_MASK_16[] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_15[] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_7 [] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x8080808008090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_2 [] = - { 0x0405060700010203, 0x8080808080808080, 0x8080808080808080, 0x8080808080808080 } ; - - static const unsigned long mMAPtoW_I_7[] = - { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0302010080808080 } ; - static const unsigned long mMAP1toW_I_2[] = - { 0x8080808080808080, 0x0706050403020100, 0x8080808080808080, 0x8080808080808080 } ; - static const unsigned long mMAP2toW_I_2[] = - { 0x8080808080808080, 0x8080808080808080, 0x0f0e0d0c0b0a0908, 0x8080808080808080 } ; - static const unsigned long mMAP3toW_I_2[] = - { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0706050403020100 } ; - -static int Transform_AVX2(Sha256* sha256) -{ - - #ifdef WOLFSSL_SMALL_STACK - word32* W_K; - W_K = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (W_K == NULL) - return MEMORY_E; - #else - word32 W_K[64] ; - #endif - - MOVE_to_REG(W_I_16, sha256->buffer[0]); BYTE_SWAP(W_I_16, mBYTE_FLIP_MASK_16[0]) ; - MOVE_to_REG(W_I_15, sha256->buffer[1]); BYTE_SWAP(W_I_15, mBYTE_FLIP_MASK_15[0]) ; - MOVE_to_REG(W_I, sha256->buffer[8]) ; BYTE_SWAP(W_I, mBYTE_FLIP_MASK_16[0]) ; - MOVE_to_REG(W_I_7, sha256->buffer[16-7]) ; BYTE_SWAP(W_I_7, mBYTE_FLIP_MASK_7[0]) ; - MOVE_to_REG(W_I_2, sha256->buffer[16-2]) ; BYTE_SWAP(W_I_2, mBYTE_FLIP_MASK_2[0]) ; - - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - ADD_MEM(W_K_TEMP, W_I_16, K[0]) ; - MOVE_to_MEM(W_K[0], W_K_TEMP) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,1) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,2) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,3) ; - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,4) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,5) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,6) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,7) ; - - ADD_MEM(YMM_TEMP0, W_I, K[8]) ; - MOVE_to_MEM(W_K[8], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - - MOVE_to_REG(YMM_TEMP0, K[16]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[16], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - - MOVE_to_REG(YMM_TEMP0, K[24]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[24], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - - MOVE_to_REG(YMM_TEMP0, K[32]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[32], YMM_TEMP0) ; - - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - - MOVE_to_REG(YMM_TEMP0, K[40]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[40], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - - MOVE_to_REG(YMM_TEMP0, K[48]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[48], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - MOVE_to_REG(YMM_TEMP0, K[56]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[56], YMM_TEMP0) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - #ifdef WOLFSSL_SMALL_STACK - XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return 0; -} - -#endif /* HAVE_INTEL_AVX2 */ -#endif /* HAVE_FIPS */ - -#endif /* NO_SHA256 */ - +/* sha256.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 + */ + +/* code submitted by raphael.huck@efixo.com */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include + +#if !defined(NO_SHA256) +#ifdef HAVE_FIPS + +int wc_InitSha256(Sha256* sha) +{ + return InitSha256_fips(sha); +} + + +int wc_Sha256Update(Sha256* sha, const byte* data, word32 len) +{ + return Sha256Update_fips(sha, data, len); +} + + +int wc_Sha256Final(Sha256* sha, byte* out) +{ + return Sha256Final_fips(sha, out); +} + + +int wc_Sha256Hash(const byte* data, word32 len, byte* out) +{ + return Sha256Hash(data, len, out); +} + +#else /* else build without fips */ + +#if !defined(NO_SHA256) && !defined(WOLFSSL_TI_HASH) + /* defined in port/ti/ti_sha256.c */ + +#if !defined (ALIGN32) + #if defined (__GNUC__) + #define ALIGN32 __attribute__ ( (aligned (32))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN32 __declspec (align (32)) + #else + #define ALIGN32 + #endif +#endif + +#ifdef WOLFSSL_PIC32MZ_HASH +#define wc_InitSha256 wc_InitSha256_sw +#define wc_Sha256Update wc_Sha256Update_sw +#define wc_Sha256Final wc_Sha256Final_sw +#endif + +#ifdef HAVE_FIPS + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS +#endif + +#if defined(USE_INTEL_SPEEDUP) +#define HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX2 + +#if defined(DEBUG_XMM) +#include "stdio.h" +#endif + +#endif + +#if defined(HAVE_INTEL_AVX2) +#define HAVE_INTEL_RORX +#endif + + +/***** +Intel AVX1/AVX2 Macro Control Structure + +#define HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX2 + +#define HAVE_INTEL_RORX + + +int InitSha256(Sha256* sha256) { + Save/Recover XMM, YMM + ... +} + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform() ; Function prototype +#else + Transform() { } + int Sha256Final() { + Save/Recover XMM, YMM + ... + } +#endif + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + #if defined(HAVE_INTEL_RORX + #define RND with rorx instuction + #else + #define RND + #endif +#endif + +#if defined(HAVE_INTEL_AVX1) + + #define XMM Instructions/inline asm + + int Transform() { + Stitched Message Sched/Round + } + +#elif defined(HAVE_INTEL_AVX2) + + #define YMM Instructions/inline asm + + int Transform() { + More granural Stitched Message Sched/Round + } + +*/ + + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + +/* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + +#ifndef _MSC_VER + #define cpuid(reg, leaf, sub)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (leaf), "c"(sub)); + + #define XASM_LINK(f) asm(f) +#else + + #include + #define cpuid(a,b) __cpuid((int*)a,b) + + #define XASM_LINK(f) + +#endif /* _MSC_VER */ + +#define EAX 0 +#define EBX 1 +#define ECX 2 +#define EDX 3 + +#define CPUID_AVX1 0x1 +#define CPUID_AVX2 0x2 +#define CPUID_RDRAND 0x4 +#define CPUID_RDSEED 0x8 +#define CPUID_BMI2 0x10 /* MULX, RORX */ + +#define IS_INTEL_AVX1 (cpuid_flags&CPUID_AVX1) +#define IS_INTEL_AVX2 (cpuid_flags&CPUID_AVX2) +#define IS_INTEL_BMI2 (cpuid_flags&CPUID_BMI2) +#define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) +#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) + +static word32 cpuid_check = 0 ; +static word32 cpuid_flags = 0 ; + +static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { + int got_intel_cpu=0; + unsigned int reg[5]; + + reg[4] = '\0' ; + cpuid(reg, 0, 0); + if(memcmp((char *)&(reg[EBX]), "Genu", 4) == 0 && + memcmp((char *)&(reg[EDX]), "ineI", 4) == 0 && + memcmp((char *)&(reg[ECX]), "ntel", 4) == 0) { + got_intel_cpu = 1; + } + if (got_intel_cpu) { + cpuid(reg, leaf, sub); + return((reg[num]>>bit)&0x1) ; + } + return 0 ; +} + +static int set_cpuid_flags(void) { + if(cpuid_check==0) { + if(cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1 ;} + if(cpuid_flag(7, 0, EBX, 5)){ cpuid_flags |= CPUID_AVX2 ; } + if(cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } + if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ; } + if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ; } + cpuid_check = 1 ; + return 0 ; + } + return 1 ; +} + + +/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha512 */ +static int Transform(Sha256* sha256); + +#if defined(HAVE_INTEL_AVX1) +static int Transform_AVX1(Sha256 *sha256) ; +#endif +#if defined(HAVE_INTEL_AVX2) +static int Transform_AVX2(Sha256 *sha256) ; +static int Transform_AVX1_RORX(Sha256 *sha256) ; +#endif + +static int (*Transform_p)(Sha256* sha256) /* = _Transform */; + +#define XTRANSFORM(sha256, B) (*Transform_p)(sha256) + +static void set_Transform(void) { + if(set_cpuid_flags())return ; + +#if defined(HAVE_INTEL_AVX2) + if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ + Transform_p = Transform_AVX1_RORX; return ; + Transform_p = Transform_AVX2 ; + /* for avoiding warning,"not used" */ + } +#endif +#if defined(HAVE_INTEL_AVX1) + Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : Transform) ; return ; +#endif + Transform_p = Transform ; return ; +} + +#else + #if defined(FREESCALE_MMCAU) + #define XTRANSFORM(sha256, B) Transform(sha256, B) + #else + #define XTRANSFORM(sha256, B) Transform(sha256) + #endif +#endif + +/* Dummy for saving MM_REGs on behalf of Transform */ +#if defined(HAVE_INTEL_AVX2)&& !defined(HAVE_INTEL_AVX1) +#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ + "%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15") +#elif defined(HAVE_INTEL_AVX1) +#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ + "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10",\ + "xmm11","xmm12","xmm13","xmm14","xmm15") +#else +#define SAVE_XMM_YMM +#endif + +#ifdef WOLFSSL_PIC32MZ_HASH +#define InitSha256 InitSha256_sw +#define Sha256Update Sha256Update_sw +#define Sha256Final Sha256Final_sw +#endif + +#include +#include + +#ifdef NO_INLINE + #include +#else + #include +#endif + +#ifdef FREESCALE_MMCAU + #include "cau_api.h" +#endif + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +int wc_InitSha256(Sha256* sha256) +{ + #ifdef FREESCALE_MMCAU + cau_sha256_initialize_output(sha256->digest); + #else + sha256->digest[0] = 0x6A09E667L; + sha256->digest[1] = 0xBB67AE85L; + sha256->digest[2] = 0x3C6EF372L; + sha256->digest[3] = 0xA54FF53AL; + sha256->digest[4] = 0x510E527FL; + sha256->digest[5] = 0x9B05688CL; + sha256->digest[6] = 0x1F83D9ABL; + sha256->digest[7] = 0x5BE0CD19L; + #endif + + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + set_Transform() ; /* choose best Transform function under this runtime environment */ +#endif + + return 0; +} + + +#if !defined(FREESCALE_MMCAU) +static const ALIGN32 word32 K[64] = { + 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, + 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, + 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, + 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, + 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L, + 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L, + 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, + 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, + 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L, + 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L, + 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, + 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, + 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L +}; + +#endif + +#if defined(FREESCALE_MMCAU) + +static int Transform(Sha256* sha256, byte* buf) +{ + cau_sha256_hash_n(buf, 1, sha256->digest); + + return 0; +} + +#endif /* FREESCALE_MMCAU */ + +#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) +#define R(x, n) (((x)&0xFFFFFFFFU)>>(n)) + +#define S(x, n) rotrFixed(x, n) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = (h) + Sigma1((e)) + Ch((e), (f), (g)) + K[(i)] + W[(i)]; \ + t1 = Sigma0((a)) + Maj((a), (b), (c)); \ + (d) += t0; \ + (h) = t0 + t1; + +#if !defined(FREESCALE_MMCAU) +static int Transform(Sha256* sha256) +{ + word32 S[8], t0, t1; + int i; + +#ifdef WOLFSSL_SMALL_STACK + word32* W; + + W = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (W == NULL) + return MEMORY_E; +#else + word32 W[64]; +#endif + + /* Copy context->state[] to working vars */ + for (i = 0; i < 8; i++) + S[i] = sha256->digest[i]; + + for (i = 0; i < 16; i++) + W[i] = sha256->buffer[i]; + + for (i = 16; i < 64; i++) + W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; + + for (i = 0; i < 64; i += 8) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + } + + /* Add the working vars back into digest state[] */ + for (i = 0; i < 8; i++) { + sha256->digest[i] += S[i]; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +#endif /* #if !defined(FREESCALE_MMCAU) */ + +static INLINE void AddLength(Sha256* sha256, word32 len) +{ + word32 tmp = sha256->loLen; + if ( (sha256->loLen += len) < tmp) + sha256->hiLen++; /* carry low to high */ +} + +int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) +{ + + /* do block size increments */ + byte* local = (byte*)sha256->buffer; + + SAVE_XMM_YMM ; /* for Intel AVX */ + + while (len) { + word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); + XMEMCPY(&local[sha256->buffLen], data, add); + + sha256->buffLen += add; + data += add; + len -= add; + + if (sha256->buffLen == SHA256_BLOCK_SIZE) { + int ret; + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords(sha256->buffer, sha256->buffer, + SHA256_BLOCK_SIZE); + #endif + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + AddLength(sha256, SHA256_BLOCK_SIZE); + sha256->buffLen = 0; + } + } + + return 0; +} + +int wc_Sha256Final(Sha256* sha256, byte* hash) +{ + byte* local = (byte*)sha256->buffer; + int ret; + + SAVE_XMM_YMM ; /* for Intel AVX */ + + AddLength(sha256, sha256->buffLen); /* before adding pads */ + + local[sha256->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha256->buffLen > SHA256_PAD_SIZE) { + XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen); + sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + #endif + + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + sha256->buffLen = 0; + } + XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen); + + /* put lengths in bits */ + sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) + + (sha256->hiLen << 3); + sha256->loLen = sha256->loLen << 3; + + /* store lengths */ + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); + XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, + sizeof(word32)); + + #if defined(FREESCALE_MMCAU) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + /* Kinetis requires only these bytes reversed */ + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(IS_INTEL_AVX1 || IS_INTEL_AVX2) + #endif + ByteReverseWords(&sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], + &sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], + 2 * sizeof(word32)); + #endif + + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + #if defined(LITTLE_ENDIAN_ORDER) + ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE); + #endif + XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE); + + return wc_InitSha256(sha256); /* reset state */ +} + + + +int wc_Sha256Hash(const byte* data, word32 len, byte* hash) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Sha256* sha256; +#else + Sha256 sha256[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL) + return MEMORY_E; +#endif + + if ((ret = wc_InitSha256(sha256)) != 0) { + WOLFSSL_MSG("InitSha256 failed"); + } + else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { + WOLFSSL_MSG("Sha256Update failed"); + } + else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { + WOLFSSL_MSG("Sha256Final failed"); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#ifdef WOLFSSL_TI_HASH +#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif +int wc_Sha256GetHash(Sha256* sha256, byte* hash) +{ +#if defined(WOLFSS_TI_HASH) + return wc_Sha256GetHash_TI(sha256, hash) ; +#else + int ret ; + Sha256 save = *sha256 ; + ret = wc_Sha256Final(sha256, hash) ; + *sha256 = save ; + return ret ; +#endif +} + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + +#define _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d ;\ + d = sha256->digest[0]; __asm__ volatile("movl %0, %"#S_0::"r"(d):SSE_REGs) ;\ + d = sha256->digest[1]; __asm__ volatile("movl %0, %"#S_1::"r"(d):SSE_REGs) ;\ + d = sha256->digest[2]; __asm__ volatile("movl %0, %"#S_2::"r"(d):SSE_REGs) ;\ + d = sha256->digest[3]; __asm__ volatile("movl %0, %"#S_3::"r"(d):SSE_REGs) ;\ + d = sha256->digest[4]; __asm__ volatile("movl %0, %"#S_4::"r"(d):SSE_REGs) ;\ + d = sha256->digest[5]; __asm__ volatile("movl %0, %"#S_5::"r"(d):SSE_REGs) ;\ + d = sha256->digest[6]; __asm__ volatile("movl %0, %"#S_6::"r"(d):SSE_REGs) ;\ + d = sha256->digest[7]; __asm__ volatile("movl %0, %"#S_7::"r"(d):SSE_REGs) ;\ +} + +#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d ; \ + __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ; sha256->digest[0] += d;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ; sha256->digest[1] += d;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ; sha256->digest[2] += d;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ; sha256->digest[3] += d;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ; sha256->digest[4] += d;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ; sha256->digest[5] += d;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ; sha256->digest[6] += d;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ; sha256->digest[7] += d;\ +} + + +#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + +#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + + + + +#define S_0 %r15d +#define S_1 %r10d +#define S_2 %r11d +#define S_3 %r12d +#define S_4 %r13d +#define S_5 %r14d +#define S_6 %ebx +#define S_7 %r9d + +#define SSE_REGs "%edi", "%ecx", "%esi", "%edx", "%ebx","%r8","%r9","%r10","%r11","%r12","%r13","%r14","%r15" + +#if defined(HAVE_INTEL_RORX) +#define RND_STEP_RORX_1(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("rorx $6, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ + +#define RND_STEP_RORX_2(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("rorx $11, %"#e",%%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ +__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ +__asm__ volatile("rorx $25, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ + +#define RND_STEP_RORX_3(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ +__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ + +#define RND_STEP_RORX_4(a,b,c,d,e,f,g,h,i)\ +/*__asm__ volatile("movl %0, %%edx\n\t"::"m"(w_k):"%edx");*/\ +__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ +__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ +__asm__ volatile("rorx $2, %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ +__asm__ volatile("rorx $13, %"#a", %%edi\n\t":::"%edi",SSE_REGs);/* edi = a>>13 */\ + +#define RND_STEP_RORX_5(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("rorx $22, %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ +__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs);/* edi = (a>>2) ^ (a>>13) */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma0(a) */\ + +#define RND_STEP_RORX_6(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ +__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ +__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c*/\ +__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ + +#define RND_STEP_RORX_7(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ +__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ +__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ + +#define RND_STEP_RORX_8(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ +__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ +__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs); \ +__asm__ volatile("movl %r8d, "#h"\n\t"); + +#endif + +#define RND_STEP_1(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs);\ +__asm__ volatile("roll $26, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ +__asm__ volatile("movl %"#e", %%edi\n\t":::"%edi",SSE_REGs);\ + +#define RND_STEP_2(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("roll $21, %%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ +__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ +__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e */\ +__asm__ volatile("roll $7, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ + +#define RND_STEP_3(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ +__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ + +#define RND_STEP_4(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ +__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ +__asm__ volatile("movl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a */\ +__asm__ volatile("roll $30, %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ +__asm__ volatile("movl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a */\ +__asm__ volatile("roll $19, %%edi\n\t":::"%edi",SSE_REGs); /* edi = a>>13 */\ +__asm__ volatile("movl %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a */\ + +#define RND_STEP_5(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("roll $10, %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ +__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs); /* edi = (a>>2) ^ (a>>13) */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs);/* edx = Sigma0(a) */\ + +#define RND_STEP_6(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ +__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ +__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c */\ +__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ + +#define RND_STEP_7(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ +__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ +__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ + +#define RND_STEP_8(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ +__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ + /* r8b = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */\ +__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs);\ + /* r8b = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */\ +__asm__ volatile("movl %%r8d, %"#h"\n\t":::"%r8", SSE_REGs); \ + /* h = h + w_k + Sigma1(e) + Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ + +#define RND_X(a,b,c,d,e,f,g,h,i) \ + RND_STEP_1(a,b,c,d,e,f,g,h,i); \ + RND_STEP_2(a,b,c,d,e,f,g,h,i); \ + RND_STEP_3(a,b,c,d,e,f,g,h,i); \ + RND_STEP_4(a,b,c,d,e,f,g,h,i); \ + RND_STEP_5(a,b,c,d,e,f,g,h,i); \ + RND_STEP_6(a,b,c,d,e,f,g,h,i); \ + RND_STEP_7(a,b,c,d,e,f,g,h,i); \ + RND_STEP_8(a,b,c,d,e,f,g,h,i); + +#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + + +#define RND_1_3(a,b,c,d,e,f,g,h,i) {\ + RND_STEP_1(a,b,c,d,e,f,g,h,i); \ + RND_STEP_2(a,b,c,d,e,f,g,h,i); \ + RND_STEP_3(a,b,c,d,e,f,g,h,i); \ +} + +#define RND_4_6(a,b,c,d,e,f,g,h,i) {\ + RND_STEP_4(a,b,c,d,e,f,g,h,i); \ + RND_STEP_5(a,b,c,d,e,f,g,h,i); \ + RND_STEP_6(a,b,c,d,e,f,g,h,i); \ +} + +#define RND_7_8(a,b,c,d,e,f,g,h,i) {\ + RND_STEP_7(a,b,c,d,e,f,g,h,i); \ + RND_STEP_8(a,b,c,d,e,f,g,h,i); \ +} + +#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + + +#define RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + +#define RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + +#define RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + +#define FOR(cnt, init, max, inc, loop) \ + __asm__ volatile("movl $"#init", %0\n\t"#loop":"::"m"(cnt):) +#define END(cnt, init, max, inc, loop) \ + __asm__ volatile("addl $"#inc", %0\n\tcmpl $"#max", %0\n\tjle "#loop"\n\t":"=m"(cnt)::) ; + +#endif /* defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) */ + +#if defined(HAVE_INTEL_AVX1) /* inline Assember for Intel AVX1 instructions */ + +#define VPALIGNR(op1,op2,op3,op4) __asm__ volatile("vpalignr $"#op4", %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPADDD(op1,op2,op3) __asm__ volatile("vpaddd %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSRLD(op1,op2,op3) __asm__ volatile("vpsrld $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSRLQ(op1,op2,op3) __asm__ volatile("vpsrlq $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSLLD(op1,op2,op3) __asm__ volatile("vpslld $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPOR(op1,op2,op3) __asm__ volatile("vpor %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPXOR(op1,op2,op3) __asm__ volatile("vpxor %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSHUFD(op1,op2,op3) __asm__ volatile("vpshufd $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSHUFB(op1,op2,op3) __asm__ volatile("vpshufb %"#op3", %"#op2", %"#op1:::XMM_REGs) + +#define MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, SHUF_00BA, SHUF_DC00,\ + a,b,c,d,e,f,g,h,_i)\ + RND_STEP_1(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP0, X3, X2, 4) ;\ + RND_STEP_2(a,b,c,d,e,f,g,h,_i);\ + VPADDD (XTMP0, XTMP0, X0) ;\ + RND_STEP_3(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ + RND_STEP_4(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1, 7) ;\ + RND_STEP_5(a,b,c,d,e,f,g,h,_i);\ + VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ + RND_STEP_6(a,b,c,d,e,f,g,h,_i);\ + VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ + RND_STEP_7(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1,18) ;\ + RND_STEP_8(a,b,c,d,e,f,g,h,_i);\ +\ + RND_STEP_1(h,a,b,c,d,e,f,g,_i+1);\ + VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ + RND_STEP_2(h,a,b,c,d,e,f,g,_i+1);\ + VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ + RND_STEP_3(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP1) ;\ + RND_STEP_4(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ + RND_STEP_5(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ + RND_STEP_6(h,a,b,c,d,e,f,g,_i+1);\ + VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ + RND_STEP_7(h,a,b,c,d,e,f,g,_i+1);\ + VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ + RND_STEP_8(h,a,b,c,d,e,f,g,_i+1);\ +\ + RND_STEP_1(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ + RND_STEP_2(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ + RND_STEP_3(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ + RND_STEP_4(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_5(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ + RND_STEP_6(g,h,a,b,c,d,e,f,_i+2);\ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ + RND_STEP_7(g,h,a,b,c,d,e,f,_i+2);\ + VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ + RND_STEP_8(g,h,a,b,c,d,e,f,_i+2);\ +\ + RND_STEP_1(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ + RND_STEP_2(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ + RND_STEP_3(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ + RND_STEP_4(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ + RND_STEP_5(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_6(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ + RND_STEP_7(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ + RND_STEP_8(f,g,h,a,b,c,d,e,_i+3);\ + VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ + +#if defined(HAVE_INTEL_RORX) + +#define MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, \ + XFER, SHUF_00BA, SHUF_DC00,a,b,c,d,e,f,g,h,_i)\ + RND_STEP_RORX_1(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP0, X3, X2, 4) ;\ + RND_STEP_RORX_2(a,b,c,d,e,f,g,h,_i);\ + VPADDD (XTMP0, XTMP0, X0) ;\ + RND_STEP_RORX_3(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ + RND_STEP_RORX_4(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1, 7) ;\ + RND_STEP_RORX_5(a,b,c,d,e,f,g,h,_i);\ + VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ + RND_STEP_RORX_6(a,b,c,d,e,f,g,h,_i);\ + VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ + RND_STEP_RORX_7(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1,18) ;\ + RND_STEP_RORX_8(a,b,c,d,e,f,g,h,_i);\ +\ + RND_STEP_RORX_1(h,a,b,c,d,e,f,g,_i+1);\ + VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ + RND_STEP_RORX_2(h,a,b,c,d,e,f,g,_i+1);\ + VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ + RND_STEP_RORX_3(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP1) ;\ + RND_STEP_RORX_4(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ + RND_STEP_RORX_5(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ + RND_STEP_RORX_6(h,a,b,c,d,e,f,g,_i+1);\ + VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ + RND_STEP_RORX_7(h,a,b,c,d,e,f,g,_i+1);\ + VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ + RND_STEP_RORX_8(h,a,b,c,d,e,f,g,_i+1);\ +\ + RND_STEP_RORX_1(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ + RND_STEP_RORX_2(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ + RND_STEP_RORX_3(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ + RND_STEP_RORX_4(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_RORX_5(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ + RND_STEP_RORX_6(g,h,a,b,c,d,e,f,_i+2);\ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ + RND_STEP_RORX_7(g,h,a,b,c,d,e,f,_i+2);\ + VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ + RND_STEP_RORX_8(g,h,a,b,c,d,e,f,_i+2);\ +\ + RND_STEP_RORX_1(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ + RND_STEP_RORX_2(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ + RND_STEP_RORX_3(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ + RND_STEP_RORX_4(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ + RND_STEP_RORX_5(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_RORX_6(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ + RND_STEP_RORX_7(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ + RND_STEP_RORX_8(f,g,h,a,b,c,d,e,_i+3);\ + VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ + +#endif + + +#define W_K_from_buff\ + __asm__ volatile("vmovdqu %0, %%xmm4\n\t"\ + "vpshufb %%xmm13, %%xmm4, %%xmm4\n\t"\ + :: "m"(sha256->buffer[0]):"%xmm4") ;\ + __asm__ volatile("vmovdqu %0, %%xmm5\n\t"\ + "vpshufb %%xmm13, %%xmm5, %%xmm5\n\t"\ + ::"m"(sha256->buffer[4]):"%xmm5") ;\ + __asm__ volatile("vmovdqu %0, %%xmm6\n\t"\ + "vpshufb %%xmm13, %%xmm6, %%xmm6\n\t"\ + ::"m"(sha256->buffer[8]):"%xmm6") ;\ + __asm__ volatile("vmovdqu %0, %%xmm7\n\t"\ + "vpshufb %%xmm13, %%xmm7, %%xmm7\n\t"\ + ::"m"(sha256->buffer[12]):"%xmm7") ;\ + +#define _SET_W_K_XFER(reg, i)\ + __asm__ volatile("vpaddd %0, %"#reg", %%xmm9"::"m"(K[i]):XMM_REGs) ;\ + __asm__ volatile("vmovdqa %%xmm9, %0":"=m"(W_K[i])::XMM_REGs) ; + +#define SET_W_K_XFER(reg, i) _SET_W_K_XFER(reg, i) + +static const ALIGN32 word64 mSHUF_00BA[] = { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF } ; /* shuffle xBxA -> 00BA */ +static const ALIGN32 word64 mSHUF_DC00[] = { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 } ; /* shuffle xDxC -> DC00 */ +static const ALIGN32 word64 mBYTE_FLIP_MASK[] = { 0x0405060700010203, 0x0c0d0e0f08090a0b } ; + + +#define _Init_Masks(mask1, mask2, mask3)\ +__asm__ volatile("vmovdqu %0, %"#mask1 ::"m"(mBYTE_FLIP_MASK[0])) ;\ +__asm__ volatile("vmovdqu %0, %"#mask2 ::"m"(mSHUF_00BA[0])) ;\ +__asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])) ; + +#define Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)\ + _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) + +#define X0 %xmm4 +#define X1 %xmm5 +#define X2 %xmm6 +#define X3 %xmm7 +#define X_ X0 + +#define XTMP0 %xmm0 +#define XTMP1 %xmm1 +#define XTMP2 %xmm2 +#define XTMP3 %xmm3 +#define XTMP4 %xmm8 +#define XTMP5 %xmm9 +#define XFER %xmm10 + +#define SHUF_00BA %xmm11 /* shuffle xBxA -> 00BA */ +#define SHUF_DC00 %xmm12 /* shuffle xDxC -> DC00 */ +#define BYTE_FLIP_MASK %xmm13 + +#define XMM_REGs /* Registers are saved in Sha256Update/Finel */ + /*"xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13" */ + +static int Transform_AVX1(Sha256* sha256) +{ + + word32 W_K[64] ; /* temp for W+K */ + + #if defined(DEBUG_XMM) + int i, j ; + word32 xmm[29][4*15] ; + #endif + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; + W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + SET_W_K_XFER(X0, 0) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; + SET_W_K_XFER(X1, 4) ; + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; + SET_W_K_XFER(X2, 8) ; + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + SET_W_K_XFER(X3, 12) ; + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; + SET_W_K_XFER(X0, 16) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + SET_W_K_XFER(X1, 20) ; + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; + SET_W_K_XFER(X2, 24) ; + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + SET_W_K_XFER(X3, 28) ; + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; + SET_W_K_XFER(X0, 32) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + SET_W_K_XFER(X1, 36) ; + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; + SET_W_K_XFER(X2, 40) ; + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + SET_W_K_XFER(X3, 44) ; + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; + + SET_W_K_XFER(X0, 48) ; + SET_W_K_XFER(X1, 52) ; + SET_W_K_XFER(X2, 56) ; + SET_W_K_XFER(X3, 60) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + #if defined(DEBUG_XMM) + for(i=0; i<29; i++) { + for(j=0; j<4*14; j+=4) + printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, + xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; + printf("\n") ; + } + + for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; + #endif + + return 0; +} + +#if defined(HAVE_INTEL_RORX) +static int Transform_AVX1_RORX(Sha256* sha256) +{ + + word32 W_K[64] ; /* temp for W+K */ + + #if defined(DEBUG_XMM) + int i, j ; + word32 xmm[29][4*15] ; + #endif + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; + W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + SET_W_K_XFER(X0, 0) ; + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; + SET_W_K_XFER(X1, 4) ; + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; + SET_W_K_XFER(X2, 8) ; + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + SET_W_K_XFER(X3, 12) ; + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; + SET_W_K_XFER(X0, 16) ; + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + SET_W_K_XFER(X1, 20) ; + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; + SET_W_K_XFER(X2, 24) ; + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + SET_W_K_XFER(X3, 28) ; + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; + SET_W_K_XFER(X0, 32) ; + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + SET_W_K_XFER(X1, 36) ; + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; + SET_W_K_XFER(X2, 40) ; + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + SET_W_K_XFER(X3, 44) ; + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; + + SET_W_K_XFER(X0, 48) ; + SET_W_K_XFER(X1, 52) ; + SET_W_K_XFER(X2, 56) ; + SET_W_K_XFER(X3, 60) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + #if defined(DEBUG_XMM) + for(i=0; i<29; i++) { + for(j=0; j<4*14; j+=4) + printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, + xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; + printf("\n") ; + } + + for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; + #endif + + return 0; +} +#endif /* HAVE_INTEL_RORX */ + +#endif /* HAVE_INTEL_AVX1 */ + + +#if defined(HAVE_INTEL_AVX2) + +#define _MOVE_to_REG(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" ":: "m"(mem):YMM_REGs) ; +#define _MOVE_to_MEM(mem, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" : "=m"(mem)::YMM_REGs) ; +#define _BYTE_SWAP(ymm, map) __asm__ volatile("vpshufb %0, %%"#ymm", %%"#ymm"\n\t"\ + :: "m"(map):YMM_REGs) ; +#define _MOVE_128(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"#map", %%"\ + #ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; +#define _MOVE_BYTE(ymm0, ymm1, map) __asm__ volatile("vpshufb %0, %%"#ymm1", %%"\ + #ymm0"\n\t":: "m"(map):YMM_REGs) ; +#define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrld $"#bits", %%"\ + #src", %%"#dest"\n\tvpslld $32-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ + #temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; +#define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrld $"#bits", %%"\ + #src", %%"#dest" ":::YMM_REGs) ; +#define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _ADD(dest, src1, src2) __asm__ volatile("vpaddd %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddd %0, %%"#src1", %%"\ + #dest" "::"m"(mem):YMM_REGs) ; +#define _BLEND(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ + #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; + +#define _EXTRACT_XMM_0(xmm, mem) __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_1(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_2(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_3(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_4(ymm, xmm, mem)\ + __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ;\ + __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_5(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_6(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_7(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; + +#define _SWAP_YMM_HL(ymm) __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ; +#define SWAP_YMM_HL(ymm) _SWAP_YMM_HL(ymm) + +#define MOVE_to_REG(ymm, mem) _MOVE_to_REG(ymm, mem) +#define MOVE_to_MEM(mem, ymm) _MOVE_to_MEM(mem, ymm) +#define BYTE_SWAP(ymm, map) _BYTE_SWAP(ymm, map) +#define MOVE_128(ymm0, ymm1, ymm2, map) _MOVE_128(ymm0, ymm1, ymm2, map) +#define MOVE_BYTE(ymm0, ymm1, map) _MOVE_BYTE(ymm0, ymm1, map) +#define XOR(dest, src1, src2) _XOR(dest, src1, src2) +#define OR(dest, src1, src2) _OR(dest, src1, src2) +#define ADD(dest, src1, src2) _ADD(dest, src1, src2) +#define ADD_MEM(dest, src1, mem) _ADD_MEM(dest, src1, mem) +#define BLEND(map, dest, src1, src2) _BLEND(map, dest, src1, src2) + +#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); +#define AVX2_S(dest, src, bits) S_TMP(dest, src, bits, S_TEMP) +#define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) + +#define GAMMA0(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); \ + XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); XOR(dest, G_TEMP, dest) ; +#define GAMMA0_1(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); +#define GAMMA0_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); \ + XOR(dest, G_TEMP, dest) ; + +#define GAMMA1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); \ + XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); XOR(dest, G_TEMP, dest) ; +#define GAMMA1_1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); +#define GAMMA1_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); \ + XOR(dest, G_TEMP, dest) ; + +#define FEEDBACK1_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP1toW_I_2[0]) ; \ + BLEND(0x0c, W_I_2, YMM_TEMP0, W_I_2) ; +#define FEEDBACK2_to_W_I_2 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ; \ + MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAP2toW_I_2[0]) ; BLEND(0x30, W_I_2, YMM_TEMP0, W_I_2) ; +#define FEEDBACK3_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP3toW_I_2[0]) ; \ + BLEND(0xc0, W_I_2, YMM_TEMP0, W_I_2) ; + +#define FEEDBACK_to_W_I_7 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ;\ + MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAPtoW_I_7[0]) ; BLEND(0x80, W_I_7, YMM_TEMP0, W_I_7) ; + +#undef voitle + +#define W_I_16 ymm8 +#define W_I_15 ymm9 +#define W_I_7 ymm10 +#define W_I_2 ymm11 +#define W_I ymm12 +#define G_TEMP ymm13 +#define S_TEMP ymm14 +#define YMM_TEMP0 ymm15 +#define YMM_TEMP0x xmm15 +#define W_I_TEMP ymm7 +#define W_K_TEMP ymm15 +#define W_K_TEMPx xmm15 + +#define YMM_REGs /* Registers are saved in Sha256Update/Finel */ + /* "%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15"*/ + + +#define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + +#define MOVE_7_to_15(w_i_15, w_i_7)\ + __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + +#define MOVE_I_to_7(w_i_7, w_i)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ + +#define MOVE_I_to_2(w_i_2, w_i)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ + +#define ROTATE_W(w_i_16, w_i_15, w_i_7, w_i_2, w_i)\ + MOVE_15_to_16(w_i_16, w_i_15, w_i_7) ; \ + MOVE_7_to_15(w_i_15, w_i_7) ; \ + MOVE_I_to_7(w_i_7, w_i) ; \ + MOVE_I_to_2(w_i_2, w_i) ;\ + +#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d ;\ + __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[0] += d;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[1] += d;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[2] += d;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[3] += d;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[4] += d;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[5] += d;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[6] += d;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[7] += d;\ +} + +#define _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d[8] ;\ + __asm__ volatile("movl %"#S_0", %0":"=r"(d[0])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d[1])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d[2])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d[3])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d[4])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d[5])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d[6])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d[7])::SSE_REGs) ;\ + printf("S[0..7]=%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);\ + __asm__ volatile("movl %0, %"#S_0::"r"(d[0]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_1::"r"(d[1]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_2::"r"(d[2]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_3::"r"(d[3]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_4::"r"(d[4]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_5::"r"(d[5]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_6::"r"(d[6]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_7::"r"(d[7]):SSE_REGs) ;\ +} + + +#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + +#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + +#define DumS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + + + /* Byte swap Masks to ensure that rest of the words are filled with zero's. */ + static const unsigned long mBYTE_FLIP_MASK_16[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; + static const unsigned long mBYTE_FLIP_MASK_15[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; + static const unsigned long mBYTE_FLIP_MASK_7 [] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x8080808008090a0b } ; + static const unsigned long mBYTE_FLIP_MASK_2 [] = + { 0x0405060700010203, 0x8080808080808080, 0x8080808080808080, 0x8080808080808080 } ; + + static const unsigned long mMAPtoW_I_7[] = + { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0302010080808080 } ; + static const unsigned long mMAP1toW_I_2[] = + { 0x8080808080808080, 0x0706050403020100, 0x8080808080808080, 0x8080808080808080 } ; + static const unsigned long mMAP2toW_I_2[] = + { 0x8080808080808080, 0x8080808080808080, 0x0f0e0d0c0b0a0908, 0x8080808080808080 } ; + static const unsigned long mMAP3toW_I_2[] = + { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0706050403020100 } ; + +static int Transform_AVX2(Sha256* sha256) +{ + + #ifdef WOLFSSL_SMALL_STACK + word32* W_K; + W_K = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (W_K == NULL) + return MEMORY_E; + #else + word32 W_K[64] ; + #endif + + MOVE_to_REG(W_I_16, sha256->buffer[0]); BYTE_SWAP(W_I_16, mBYTE_FLIP_MASK_16[0]) ; + MOVE_to_REG(W_I_15, sha256->buffer[1]); BYTE_SWAP(W_I_15, mBYTE_FLIP_MASK_15[0]) ; + MOVE_to_REG(W_I, sha256->buffer[8]) ; BYTE_SWAP(W_I, mBYTE_FLIP_MASK_16[0]) ; + MOVE_to_REG(W_I_7, sha256->buffer[16-7]) ; BYTE_SWAP(W_I_7, mBYTE_FLIP_MASK_7[0]) ; + MOVE_to_REG(W_I_2, sha256->buffer[16-2]) ; BYTE_SWAP(W_I_2, mBYTE_FLIP_MASK_2[0]) ; + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + ADD_MEM(W_K_TEMP, W_I_16, K[0]) ; + MOVE_to_MEM(W_K[0], W_K_TEMP) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,1) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,2) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,3) ; + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,4) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,5) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,6) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,7) ; + + ADD_MEM(YMM_TEMP0, W_I, K[8]) ; + MOVE_to_MEM(W_K[8], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; + GAMMA1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; + + MOVE_to_REG(YMM_TEMP0, K[16]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[16], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; + GAMMA1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; + + MOVE_to_REG(YMM_TEMP0, K[24]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[24], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; + GAMMA1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; + + MOVE_to_REG(YMM_TEMP0, K[32]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[32], YMM_TEMP0) ; + + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; + + MOVE_to_REG(YMM_TEMP0, K[40]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[40], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; + + MOVE_to_REG(YMM_TEMP0, K[48]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[48], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + + MOVE_to_REG(YMM_TEMP0, K[56]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[56], YMM_TEMP0) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + #ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return 0; +} + +#endif /* HAVE_INTEL_AVX2 */ + +#endif /* WOLFSSL_TI_HAHS */ + +#endif /* HAVE_FIPS */ + +#endif /* NO_SHA256 */ + diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index ba8d89400..94e4466f7 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/wolfssl/wolfcrypt/md5.h @@ -1,81 +1,100 @@ -/* md5.h - * - * 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 - */ - -#ifndef WOLF_CRYPT_MD5_H -#define WOLF_CRYPT_MD5_H - -#include - -#ifndef NO_MD5 - -#ifdef HAVE_FIPS - #define wc_InitMd5 InitMd5 - #define wc_Md5Update Md5Update - #define wc_Md5Final Md5Final - #define wc_Md5Hash Md5Hash -#endif - -#ifdef __cplusplus - extern "C" { -#endif - - -/* in bytes */ -enum { -#ifdef STM32F2_HASH - MD5_REG_SIZE = 4, /* STM32 register size, bytes */ -#endif - MD5 = 0, /* hash type unique */ - MD5_BLOCK_SIZE = 64, - MD5_DIGEST_SIZE = 16, - MD5_PAD_SIZE = 56 -}; - -#if defined(WOLFSSL_PIC32MZ_HASH) -#include "port/pic32/pic32mz-crypt.h" -#endif - -/* MD5 digest */ -typedef struct Md5 { - word32 buffLen; /* in bytes */ - word32 loLen; /* length in bytes */ - word32 hiLen; /* length in bytes */ - word32 buffer[MD5_BLOCK_SIZE / sizeof(word32)]; - #if !defined(WOLFSSL_PIC32MZ_HASH) - word32 digest[MD5_DIGEST_SIZE / sizeof(word32)]; - #else - word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; - pic32mz_desc desc ; /* Crypt Engine descripter */ - #endif -} Md5; - -WOLFSSL_API void wc_InitMd5(Md5*); -WOLFSSL_API void wc_Md5Update(Md5*, const byte*, word32); -WOLFSSL_API void wc_Md5Final(Md5*, byte*); -WOLFSSL_API int wc_Md5Hash(const byte*, word32, byte*); - - -#ifdef __cplusplus - } /* extern "C" */ -#endif - -#endif /* NO_MD5 */ -#endif /* WOLF_CRYPT_MD5_H */ +/* md5.h + * + * 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 + */ + +#ifndef WOLF_CRYPT_MD5_H +#define WOLF_CRYPT_MD5_H + +#include + +#ifndef NO_MD5 + +#ifdef HAVE_FIPS + #define wc_InitMd5 InitMd5 + #define wc_Md5Update Md5Update + #define wc_Md5Final Md5Final + #define wc_Md5Hash Md5Hash +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* in bytes */ +enum { +#ifdef STM32F2_HASH + MD5_REG_SIZE = 4, /* STM32 register size, bytes */ +#endif + MD5 = 0, /* hash type unique */ + MD5_BLOCK_SIZE = 64, + MD5_DIGEST_SIZE = 16, + MD5_PAD_SIZE = 56 +}; + +#if defined(WOLFSSL_PIC32MZ_HASH) +#include "port/pic32/pic32mz-crypt.h" +#endif + +#ifdef TI_HASH_TEST +#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + + +#ifndef WOLFSSL_TI_HASH + +/* MD5 digest */ +typedef struct Md5 { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[MD5_BLOCK_SIZE / sizeof(word32)]; + #if !defined(WOLFSSL_PIC32MZ_HASH) + word32 digest[MD5_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; + pic32mz_desc desc ; /* Crypt Engine descripter */ + #endif + +#ifdef TI_HASH_TEST + wolfssl_TI_Hash ti ; +#endif + +} Md5; + +#if defined(TI_HASH_TEST) +void wc_Md5GetHash_ti(Md5* md5, byte* hash) ; +#endif + +#else /* WOLFSSL_TI_HASH */ + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + +WOLFSSL_API void wc_InitMd5(Md5*); +WOLFSSL_API void wc_Md5Update(Md5*, const byte*, word32); +WOLFSSL_API void wc_Md5Final(Md5*, byte*); +WOLFSSL_API int wc_Md5Hash(const byte*, word32, byte*); +WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_MD5 */ +#endif /* WOLF_CRYPT_MD5_H */ diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index 9fdabed39..46dce03d0 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/wolfssl/wolfcrypt/sha.h @@ -1,80 +1,88 @@ -/* sha.h - * - * 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 - */ - -#ifndef WOLF_CRYPT_SHA_H -#define WOLF_CRYPT_SHA_H - -#include - -#ifndef NO_SHA - -#ifdef HAVE_FIPS -/* for fips @wc_fips */ -#include -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -#ifndef HAVE_FIPS /* avoid redefining structs */ -/* in bytes */ -enum { -#ifdef STM32F2_HASH - SHA_REG_SIZE = 4, /* STM32 register size, bytes */ -#endif - SHA = 1, /* hash type unique */ - SHA_BLOCK_SIZE = 64, - SHA_DIGEST_SIZE = 20, - SHA_PAD_SIZE = 56 -}; - -#ifdef WOLFSSL_PIC32MZ_HASH -#include "port/pic32/pic32mz-crypt.h" -#endif - -/* Sha digest */ -typedef struct Sha { - word32 buffLen; /* in bytes */ - word32 loLen; /* length in bytes */ - word32 hiLen; /* length in bytes */ - word32 buffer[SHA_BLOCK_SIZE / sizeof(word32)]; - #ifndef WOLFSSL_PIC32MZ_HASH - word32 digest[SHA_DIGEST_SIZE / sizeof(word32)]; - #else - word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; - pic32mz_desc desc; /* Crypt Engine descripter */ - #endif -} Sha; -#endif /* HAVE_FIPS */ - -WOLFSSL_API int wc_InitSha(Sha*); -WOLFSSL_API int wc_ShaUpdate(Sha*, const byte*, word32); -WOLFSSL_API int wc_ShaFinal(Sha*, byte*); -WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); - -#ifdef __cplusplus - } /* extern "C" */ -#endif - -#endif /* NO_SHA */ -#endif /* WOLF_CRYPT_SHA_H */ - +/* sha.h + * + * 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 + */ + +#ifndef WOLF_CRYPT_SHA_H +#define WOLF_CRYPT_SHA_H + +#include + +#ifndef NO_SHA + +#ifdef HAVE_FIPS +/* for fips @wc_fips */ +#include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefining structs */ +/* in bytes */ +enum { +#ifdef STM32F2_HASH + SHA_REG_SIZE = 4, /* STM32 register size, bytes */ +#endif + SHA = 1, /* hash type unique */ + SHA_BLOCK_SIZE = 64, + SHA_DIGEST_SIZE = 20, + SHA_PAD_SIZE = 56 +}; + +#ifdef WOLFSSL_PIC32MZ_HASH +#include "port/pic32/pic32mz-crypt.h" +#endif + +#ifndef WOLFSSL_TI_HASH + +/* Sha digest */ +typedef struct Sha { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[SHA_BLOCK_SIZE / sizeof(word32)]; + #ifndef WOLFSSL_PIC32MZ_HASH + word32 digest[SHA_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; + pic32mz_desc desc; /* Crypt Engine descripter */ + #endif +} Sha; + +#else /* WOLFSSL_TI_HASH */ + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha(Sha*); +WOLFSSL_API int wc_ShaUpdate(Sha*, const byte*, word32); +WOLFSSL_API int wc_ShaFinal(Sha*, byte*); +WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); +WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA */ +#endif /* WOLF_CRYPT_SHA_H */ + diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 5dbe2d74b..86616e320 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -1,80 +1,86 @@ -/* sha256.h - * - * 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 - */ - -/* code submitted by raphael.huck@efixo.com */ - -#ifndef WOLF_CRYPT_SHA256_H -#define WOLF_CRYPT_SHA256_H - -#include - -#ifndef NO_SHA256 - -#ifdef HAVE_FIPS - /* for fips @wc_fips */ - #include -#endif - - -#ifdef __cplusplus - extern "C" { -#endif - -#ifndef HAVE_FIPS /* avoid redefinition of structs */ -#ifdef WOLFSSL_PIC32MZ_HASH - #include "port/pic32/pic32mz-crypt.h" -#endif - -/* in bytes */ -enum { - SHA256 = 2, /* hash type unique */ - SHA256_BLOCK_SIZE = 64, - SHA256_DIGEST_SIZE = 32, - SHA256_PAD_SIZE = 56 -}; - - -/* Sha256 digest */ -typedef struct Sha256 { - word32 buffLen; /* in bytes */ - word32 loLen; /* length in bytes */ - word32 hiLen; /* length in bytes */ - word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)]; - word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)]; - #ifdef WOLFSSL_PIC32MZ_HASH - pic32mz_desc desc ; /* Crypt Engine descripter */ - #endif -} Sha256; - -#endif /* HAVE_FIPS */ - -WOLFSSL_API int wc_InitSha256(Sha256*); -WOLFSSL_API int wc_Sha256Update(Sha256*, const byte*, word32); -WOLFSSL_API int wc_Sha256Final(Sha256*, byte*); -WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); - -#ifdef __cplusplus - } /* extern "C" */ -#endif - -#endif /* NO_SHA256 */ -#endif /* WOLF_CRYPT_SHA256_H */ - +/* sha256.h + * + * 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 + */ + +/* code submitted by raphael.huck@efixo.com */ + +#ifndef WOLF_CRYPT_SHA256_H +#define WOLF_CRYPT_SHA256_H + +#include + +#ifndef NO_SHA256 + +#ifdef HAVE_FIPS + /* for fips @wc_fips */ + #include +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefinition of structs */ +#ifdef WOLFSSL_PIC32MZ_HASH + #include "port/pic32/pic32mz-crypt.h" +#endif + +/* in bytes */ +enum { + SHA256 = 2, /* hash type unique */ + SHA256_BLOCK_SIZE = 64, + SHA256_DIGEST_SIZE = 32, + SHA256_PAD_SIZE = 56 +}; + +#ifndef WOLFSSL_TI_HASH + +/* Sha256 digest */ +typedef struct Sha256 { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)]; + word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)]; + #ifdef WOLFSSL_PIC32MZ_HASH + pic32mz_desc desc ; /* Crypt Engine descripter */ + #endif +} Sha256; + +#else /* WOLFSSL_TI_HASH */ + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha256(Sha256*); +WOLFSSL_API int wc_Sha256Update(Sha256*, const byte*, word32); +WOLFSSL_API int wc_Sha256Final(Sha256*, byte*); +WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); +WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA256 */ +#endif /* WOLF_CRYPT_SHA256_H */ + From 527013ec1edae29e5cdf1169a9ced00c0e7a6559 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Thu, 21 May 2015 14:16:09 +0900 Subject: [PATCH 03/21] corrected NL code --- wolfcrypt/src/md5.c | 852 ++++---- wolfcrypt/src/port/ti/ti-aes.c | 1096 +++++----- wolfcrypt/src/sha.c | 946 ++++----- wolfcrypt/src/sha256.c | 3562 ++++++++++++++++---------------- wolfssl/wolfcrypt/md5.h | 200 +- wolfssl/wolfcrypt/sha.h | 176 +- wolfssl/wolfcrypt/sha256.h | 172 +- 7 files changed, 3502 insertions(+), 3502 deletions(-) diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index a3e76eda8..6c2e45d9f 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -1,426 +1,426 @@ -/* md5.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 - -#if !defined(NO_MD5) && !defined(WOLFSSL_TI_HASH) - -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitMd5 wc_InitMd5_sw -#define wc_Md5Update wc_Md5Update_sw -#define wc_Md5Final wc_Md5Final_sw -#endif - -#include -#include - -#ifdef NO_INLINE - #include -#else - #include -#endif - -#ifdef FREESCALE_MMCAU - #include "cau_api.h" - #define XTRANSFORM(S,B) cau_md5_hash_n((B), 1, (unsigned char*)(S)->digest) -#else - #define XTRANSFORM(S,B) Transform((S)) -#endif - - -#ifdef STM32F2_HASH - /* - * STM32F2 hardware MD5 support through the STM32F2 standard peripheral - * library. Documentation located in STM32F2xx Standard Peripheral Library - * document (See note in README). - */ - #include "stm32f2xx.h" - - void wc_InitMd5(Md5* md5) - { - /* STM32F2 struct notes: - * md5->buffer = first 4 bytes used to hold partial block if needed - * md5->buffLen = num bytes currently stored in md5->buffer - * md5->loLen = num bytes that have been written to STM32 FIFO - */ - XMEMSET(md5->buffer, 0, MD5_REG_SIZE); - - md5->buffLen = 0; - md5->loLen = 0; - - /* initialize HASH peripheral */ - HASH_DeInit(); - - /* configure algo used, algo mode, datatype */ - HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); - HASH->CR |= (HASH_AlgoSelection_MD5 | HASH_AlgoMode_HASH - | HASH_DataType_8b); - - /* reset HASH processor */ - HASH->CR |= HASH_CR_INIT; - } - - void wc_Md5Update(Md5* md5, const byte* data, word32 len) - { - word32 i = 0; - word32 fill = 0; - word32 diff = 0; - - /* if saved partial block is available */ - if (md5->buffLen > 0) { - fill = 4 - md5->buffLen; - - /* if enough data to fill, fill and push to FIFO */ - if (fill <= len) { - XMEMCPY((byte*)md5->buffer + md5->buffLen, data, fill); - HASH_DataIn(*(uint32_t*)md5->buffer); - - data += fill; - len -= fill; - md5->loLen += 4; - md5->buffLen = 0; - } else { - /* append partial to existing stored block */ - XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); - md5->buffLen += len; - return; - } - } - - /* write input block in the IN FIFO */ - for (i = 0; i < len; i += 4) - { - diff = len - i; - if (diff < 4) { - /* store incomplete last block, not yet in FIFO */ - XMEMSET(md5->buffer, 0, MD5_REG_SIZE); - XMEMCPY((byte*)md5->buffer, data, diff); - md5->buffLen = diff; - } else { - HASH_DataIn(*(uint32_t*)data); - data+=4; - } - } - - /* keep track of total data length thus far */ - md5->loLen += (len - md5->buffLen); - } - - void wc_Md5Final(Md5* md5, byte* hash) - { - __IO uint16_t nbvalidbitsdata = 0; - - /* finish reading any trailing bytes into FIFO */ - if (md5->buffLen > 0) { - HASH_DataIn(*(uint32_t*)md5->buffer); - md5->loLen += md5->buffLen; - } - - /* calculate number of valid bits in last word of input data */ - nbvalidbitsdata = 8 * (md5->loLen % MD5_REG_SIZE); - - /* configure number of valid bits in last word of the data */ - HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); - - /* start HASH processor */ - HASH_StartDigest(); - - /* wait until Busy flag == RESET */ - while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} - - /* read message digest */ - md5->digest[0] = HASH->HR[0]; - md5->digest[1] = HASH->HR[1]; - md5->digest[2] = HASH->HR[2]; - md5->digest[3] = HASH->HR[3]; - - ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); - - XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); - - wc_InitMd5(md5); /* reset state */ - } - -#elif defined(WOLFSSL_IT_HASH) - - /* defined in port/ti_md5.c */ - -#else /* CTaoCrypt software implementation */ - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - -#ifdef TI_HASH_TEST -void wc_InitMd5_ti(Md5* md5) ; -void wc_Md5Update_ti(Md5* md5, const byte* data, word32 len) ; -void wc_Md5Final_ti(Md5* md5, byte* hash) ; -#endif - -void wc_InitMd5(Md5* md5) -{ - md5->digest[0] = 0x67452301L; - md5->digest[1] = 0xefcdab89L; - md5->digest[2] = 0x98badcfeL; - md5->digest[3] = 0x10325476L; - - md5->buffLen = 0; - md5->loLen = 0; - md5->hiLen = 0; - -#ifdef TI_HASH_TEST - wc_InitMd5_ti(md5) ; -#endif -} - -#ifndef FREESCALE_MMCAU - -static void Transform(Md5* md5) -{ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -#define MD5STEP(f, w, x, y, z, data, s) \ - w = rotlFixed(w + f(x, y, z) + data, s) + x - - /* Copy context->state[] to working vars */ - word32 a = md5->digest[0]; - word32 b = md5->digest[1]; - word32 c = md5->digest[2]; - word32 d = md5->digest[3]; - - MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); - - /* Add the working vars back into digest state[] */ - md5->digest[0] += a; - md5->digest[1] += b; - md5->digest[2] += c; - md5->digest[3] += d; -} - -#endif /* FREESCALE_MMCAU */ - - -static INLINE void AddLength(Md5* md5, word32 len) -{ - word32 tmp = md5->loLen; - if ( (md5->loLen += len) < tmp) - md5->hiLen++; /* carry low to high */ -} - - -void wc_Md5Update(Md5* md5, const byte* data, word32 len) -{ - /* do block size increments */ - byte* local = (byte*)md5->buffer; - - while (len) { - word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); - XMEMCPY(&local[md5->buffLen], data, add); - - md5->buffLen += add; - data += add; - len -= add; - - if (md5->buffLen == MD5_BLOCK_SIZE) { - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif - XTRANSFORM(md5, local); - AddLength(md5, MD5_BLOCK_SIZE); - md5->buffLen = 0; - } - } -#ifdef TI_HASH_TEST - wc_Md5Update_ti(md5, data, len) ; -#endif - -} - - -void wc_Md5Final(Md5* md5, byte* hash) -{ - byte* local = (byte*)md5->buffer; - - AddLength(md5, md5->buffLen); /* before adding pads */ - - local[md5->buffLen++] = 0x80; /* add 1 */ - - /* pad with zeros */ - if (md5->buffLen > MD5_PAD_SIZE) { - XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen); - md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen; - - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif - XTRANSFORM(md5, local); - md5->buffLen = 0; - } - XMEMSET(&local[md5->buffLen], 0, MD5_PAD_SIZE - md5->buffLen); - - /* put lengths in bits */ - md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) + - (md5->hiLen << 3); - md5->loLen = md5->loLen << 3; - - /* store lengths */ - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif - /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); - XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); - - XTRANSFORM(md5, local); - #ifdef BIG_ENDIAN_ORDER - ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); - #endif - XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); - - wc_InitMd5(md5); /* reset state */ - -#ifdef TI_HASH_TEST - wc_Md5Final_ti(md5, hash) ; -#endif -} - -#endif /* STM32F2_HASH */ - - -int wc_Md5Hash(const byte* data, word32 len, byte* hash) -{ -#ifdef WOLFSSL_SMALL_STACK - Md5* md5; -#else - Md5 md5[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (md5 == NULL) - return MEMORY_E; -#endif - - wc_InitMd5(md5); - wc_Md5Update(md5, data, len); - wc_Md5Final(md5, hash); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return 0; -} - -#if defined(WOLFSSL_TI_HASH)||defined(TI_HASH_TEST) -#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif -void wc_Md5GetHash(Md5* md5, byte* hash) -{ -#if defined(WOLFSSL_TI_HASH) || defined(TI_HASH_TEST) - wc_Md5GetHash_ti(md5, hash) ; -#else - Md5 save = *md5 ; - wc_Md5Final(md5, hash) ; - *md5 = save ; -#endif -} -#endif /* NO_MD5 */ +/* md5.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 + +#if !defined(NO_MD5) && !defined(WOLFSSL_TI_HASH) + +#ifdef WOLFSSL_PIC32MZ_HASH +#define wc_InitMd5 wc_InitMd5_sw +#define wc_Md5Update wc_Md5Update_sw +#define wc_Md5Final wc_Md5Final_sw +#endif + +#include +#include + +#ifdef NO_INLINE + #include +#else + #include +#endif + +#ifdef FREESCALE_MMCAU + #include "cau_api.h" + #define XTRANSFORM(S,B) cau_md5_hash_n((B), 1, (unsigned char*)(S)->digest) +#else + #define XTRANSFORM(S,B) Transform((S)) +#endif + + +#ifdef STM32F2_HASH + /* + * STM32F2 hardware MD5 support through the STM32F2 standard peripheral + * library. Documentation located in STM32F2xx Standard Peripheral Library + * document (See note in README). + */ + #include "stm32f2xx.h" + + void wc_InitMd5(Md5* md5) + { + /* STM32F2 struct notes: + * md5->buffer = first 4 bytes used to hold partial block if needed + * md5->buffLen = num bytes currently stored in md5->buffer + * md5->loLen = num bytes that have been written to STM32 FIFO + */ + XMEMSET(md5->buffer, 0, MD5_REG_SIZE); + + md5->buffLen = 0; + md5->loLen = 0; + + /* initialize HASH peripheral */ + HASH_DeInit(); + + /* configure algo used, algo mode, datatype */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + HASH->CR |= (HASH_AlgoSelection_MD5 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + } + + void wc_Md5Update(Md5* md5, const byte* data, word32 len) + { + word32 i = 0; + word32 fill = 0; + word32 diff = 0; + + /* if saved partial block is available */ + if (md5->buffLen > 0) { + fill = 4 - md5->buffLen; + + /* if enough data to fill, fill and push to FIFO */ + if (fill <= len) { + XMEMCPY((byte*)md5->buffer + md5->buffLen, data, fill); + HASH_DataIn(*(uint32_t*)md5->buffer); + + data += fill; + len -= fill; + md5->loLen += 4; + md5->buffLen = 0; + } else { + /* append partial to existing stored block */ + XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); + md5->buffLen += len; + return; + } + } + + /* write input block in the IN FIFO */ + for (i = 0; i < len; i += 4) + { + diff = len - i; + if (diff < 4) { + /* store incomplete last block, not yet in FIFO */ + XMEMSET(md5->buffer, 0, MD5_REG_SIZE); + XMEMCPY((byte*)md5->buffer, data, diff); + md5->buffLen = diff; + } else { + HASH_DataIn(*(uint32_t*)data); + data+=4; + } + } + + /* keep track of total data length thus far */ + md5->loLen += (len - md5->buffLen); + } + + void wc_Md5Final(Md5* md5, byte* hash) + { + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (md5->buffLen > 0) { + HASH_DataIn(*(uint32_t*)md5->buffer); + md5->loLen += md5->buffLen; + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (md5->loLen % MD5_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + md5->digest[0] = HASH->HR[0]; + md5->digest[1] = HASH->HR[1]; + md5->digest[2] = HASH->HR[2]; + md5->digest[3] = HASH->HR[3]; + + ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); + + XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); + + wc_InitMd5(md5); /* reset state */ + } + +#elif defined(WOLFSSL_IT_HASH) + + /* defined in port/ti_md5.c */ + +#else /* CTaoCrypt software implementation */ + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + +#ifdef TI_HASH_TEST +void wc_InitMd5_ti(Md5* md5) ; +void wc_Md5Update_ti(Md5* md5, const byte* data, word32 len) ; +void wc_Md5Final_ti(Md5* md5, byte* hash) ; +#endif + +void wc_InitMd5(Md5* md5) +{ + md5->digest[0] = 0x67452301L; + md5->digest[1] = 0xefcdab89L; + md5->digest[2] = 0x98badcfeL; + md5->digest[3] = 0x10325476L; + + md5->buffLen = 0; + md5->loLen = 0; + md5->hiLen = 0; + +#ifdef TI_HASH_TEST + wc_InitMd5_ti(md5) ; +#endif +} + +#ifndef FREESCALE_MMCAU + +static void Transform(Md5* md5) +{ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, data, s) \ + w = rotlFixed(w + f(x, y, z) + data, s) + x + + /* Copy context->state[] to working vars */ + word32 a = md5->digest[0]; + word32 b = md5->digest[1]; + word32 c = md5->digest[2]; + word32 d = md5->digest[3]; + + MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); + + /* Add the working vars back into digest state[] */ + md5->digest[0] += a; + md5->digest[1] += b; + md5->digest[2] += c; + md5->digest[3] += d; +} + +#endif /* FREESCALE_MMCAU */ + + +static INLINE void AddLength(Md5* md5, word32 len) +{ + word32 tmp = md5->loLen; + if ( (md5->loLen += len) < tmp) + md5->hiLen++; /* carry low to high */ +} + + +void wc_Md5Update(Md5* md5, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local = (byte*)md5->buffer; + + while (len) { + word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); + XMEMCPY(&local[md5->buffLen], data, add); + + md5->buffLen += add; + data += add; + len -= add; + + if (md5->buffLen == MD5_BLOCK_SIZE) { + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif + XTRANSFORM(md5, local); + AddLength(md5, MD5_BLOCK_SIZE); + md5->buffLen = 0; + } + } +#ifdef TI_HASH_TEST + wc_Md5Update_ti(md5, data, len) ; +#endif + +} + + +void wc_Md5Final(Md5* md5, byte* hash) +{ + byte* local = (byte*)md5->buffer; + + AddLength(md5, md5->buffLen); /* before adding pads */ + + local[md5->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (md5->buffLen > MD5_PAD_SIZE) { + XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen); + md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen; + + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif + XTRANSFORM(md5, local); + md5->buffLen = 0; + } + XMEMSET(&local[md5->buffLen], 0, MD5_PAD_SIZE - md5->buffLen); + + /* put lengths in bits */ + md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) + + (md5->hiLen << 3); + md5->loLen = md5->loLen << 3; + + /* store lengths */ + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); + XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); + + XTRANSFORM(md5, local); + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); + #endif + XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); + + wc_InitMd5(md5); /* reset state */ + +#ifdef TI_HASH_TEST + wc_Md5Final_ti(md5, hash) ; +#endif +} + +#endif /* STM32F2_HASH */ + + +int wc_Md5Hash(const byte* data, word32 len, byte* hash) +{ +#ifdef WOLFSSL_SMALL_STACK + Md5* md5; +#else + Md5 md5[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; +#endif + + wc_InitMd5(md5); + wc_Md5Update(md5, data, len); + wc_Md5Final(md5, hash); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +#if defined(WOLFSSL_TI_HASH)||defined(TI_HASH_TEST) +#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif +void wc_Md5GetHash(Md5* md5, byte* hash) +{ +#if defined(WOLFSSL_TI_HASH) || defined(TI_HASH_TEST) + wc_Md5GetHash_ti(md5, hash) ; +#else + Md5 save = *md5 ; + wc_Md5Final(md5, hash) ; + *md5 = save ; +#endif +} +#endif /* NO_MD5 */ diff --git a/wolfcrypt/src/port/ti/ti-aes.c b/wolfcrypt/src/port/ti/ti-aes.c index 11a0680b6..8ca83385c 100644 --- a/wolfcrypt/src/port/ti/ti-aes.c +++ b/wolfcrypt/src/port/ti/ti-aes.c @@ -1,548 +1,548 @@ -/* port/ti/ti-aes.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 - -#ifndef NO_AES - - -#if defined(WOLFSSL_TI_CRYPT) -#include -#include - -#include -#include -#include - -#include "inc/hw_aes.h" -#include "inc/hw_memmap.h" -#include "inc/hw_ints.h" -#include "driverlib/aes.h" -#include "driverlib/sysctl.h" -#include "driverlib/rom_map.h" -#include "driverlib/rom.h" - -static int AesSetIV(Aes* aes, const byte* iv) -{ - if (aes == NULL) - return BAD_FUNC_ARG; - - if (iv) - XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); - else - XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); - - return 0; -} - -WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, - int dir) -{ - if(!wolfSSL_TI_CCMInit())return 1 ; - if ((aes == NULL) || (key == NULL) || (iv == NULL)) - return BAD_FUNC_ARG; - if(!((dir == AES_ENCRYPTION) || (dir == AES_DECRYPTION))) - return BAD_FUNC_ARG; - - switch(len) { - case 16: aes->keylen = AES_CFG_KEY_SIZE_128BIT ; break ; - case 24: aes->keylen = AES_CFG_KEY_SIZE_192BIT ; break ; - case 32: aes->keylen = AES_CFG_KEY_SIZE_256BIT ; break ; - default: return BAD_FUNC_ARG; - } - - XMEMCPY(aes->key, key, len) ; - #ifdef WOLFSSL_AES_COUNTER - aes->left = 0; - #endif /* WOLFSSL_AES_COUNTER */ - return AesSetIV(aes, iv); -} - -#define AES_CFG_MODE_CTR_NOCTR AES_CFG_MODE_CTR+100 -#define IS_ALIGN16(p) (((unsigned int)(p)&0xf) == 0) - -static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode) -{ - wolfSSL_TI_lockCCM() ; - ROM_AESReset(AES_BASE); - ROM_AESConfigSet(AES_BASE, (aes->keylen | dir | - (mode==AES_CFG_MODE_CTR_NOCTR ? AES_CFG_MODE_CTR : mode))); - AESIVSet(AES_BASE, aes->reg); - ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); - if((dir == AES_CFG_DIR_DECRYPT)&& (mode == AES_CFG_MODE_CBC)) - /* if input and output same will overwrite input iv */ - XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - ROM_AESDataProcess(AES_BASE, (uint32_t *)in, (uint32_t *)out, sz); - wolfSSL_TI_unlockCCM() ; - - /* store iv for next call */ - if(mode == AES_CFG_MODE_CBC){ - if(dir == AES_CFG_DIR_ENCRYPT) - XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - else - XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - } - - if(mode == AES_CFG_MODE_CTR) { - do { - int i ; - for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { - if (++((byte *)aes->reg)[i]) - break ; - } - sz -= AES_BLOCK_SIZE ; - } while((int)sz > 0) ; - } - - return 0 ; -} - -static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode) -{ - const byte * in_p ; byte * out_p ; - word32 size ; - #define TI_BUFFSIZE 1024 - byte buff[TI_BUFFSIZE] ; - - if ((aes == NULL) || (in == NULL) || (out == NULL)) - return BAD_FUNC_ARG; - if(sz % AES_BLOCK_SIZE) - return BAD_FUNC_ARG; - - while(sz > 0) { - size = sz ; in_p = in ; out_p = out ; - if(!IS_ALIGN16(in)){ - size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; - XMEMCPY(buff, in, size) ; - in_p = (const byte *)buff ; - } - if(!IS_ALIGN16(out)){ - size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; - out_p = buff ; - } - - AesAlign16(aes, out_p, in_p, size, dir, mode) ; - - if(!IS_ALIGN16(out)){ - XMEMCPY(out, buff, size) ; - } - sz -= size ; in += size ; out += size ; - } - - return 0 ; -} - -WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesProcess(aes, out, in, sz, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CBC) ; -} - -WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesProcess(aes, out, in, sz, AES_CFG_DIR_DECRYPT, AES_CFG_MODE_CBC) ; -} - -#ifdef WOLFSSL_AES_COUNTER -WOLFSSL_API void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - char out_block[AES_BLOCK_SIZE] ; - int odd ; - int even ; - char *tmp ; /* (char *)aes->tmp, for short */ - - tmp = (char *)aes->tmp ; - if(aes->left) { - if((aes->left + sz) >= AES_BLOCK_SIZE){ - odd = AES_BLOCK_SIZE - aes->left ; - } else { - odd = sz ; - } - XMEMCPY(tmp+aes->left, in, odd) ; - if((odd+aes->left) == AES_BLOCK_SIZE){ - AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, - AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CTR) ; - XMEMCPY(out, out_block+aes->left, odd) ; - aes->left = 0 ; - XMEMSET(tmp, 0x0, AES_BLOCK_SIZE) ; - } - in += odd ; - out+= odd ; - sz -= odd ; - } - odd = sz % AES_BLOCK_SIZE ; /* if there is tail flagment */ - if(sz / AES_BLOCK_SIZE) { - even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE ; - AesProcess(aes, out, in, even, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CTR); - out += even ; - in += even ; - } - if(odd) { - XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left) ; - XMEMCPY(tmp+aes->left, in, odd) ; - AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, - AES_CFG_DIR_ENCRYPT, - AES_CFG_MODE_CTR_NOCTR /* Counter mode without counting IV */ - ); - XMEMCPY(out, out_block+aes->left,odd) ; - aes->left += odd ; - } -} -#endif - -/* AES-DIRECT */ -#if defined(WOLFSSL_AES_DIRECT) -WOLFSSL_API void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) -{ - AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CBC) ; -} -WOLFSSL_API void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) -{ - AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_DECRYPT, AES_CFG_MODE_CBC) ; -} -WOLFSSL_API int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, - const byte* iv, int dir) -{ - return(wc_AesSetKey(aes, key, len, iv, dir)) ; -} -#endif - - -#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) - -static int AesAuthSetKey(Aes* aes, const byte* key, word32 keySz) -{ - byte nonce[AES_BLOCK_SIZE]; - - if ((aes == NULL) || (key == NULL)) - return BAD_FUNC_ARG ; - if (!((keySz == 16) || (keySz == 24) || (keySz == 32))) - return BAD_FUNC_ARG ; - - XMEMSET(nonce, 0, sizeof(nonce)); - return wc_AesSetKey(aes, key, keySz, nonce, AES_ENCRYPTION); -} - - -static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz, word32 *M, word32 *L) -{ - if((aes == NULL)||(nonce == NULL)||(authTag== NULL)||(authIn == NULL)) - return BAD_FUNC_ARG; - if((inSz != 0) && ((out == NULL)||(in == NULL))) - return BAD_FUNC_ARG; - - switch(authTagSz){ - case 4: - *M = AES_CFG_CCM_M_4; break ; - case 6: - *M = AES_CFG_CCM_M_6; break ; - case 8: - *M = AES_CFG_CCM_M_8; break ; - case 10: - *M = AES_CFG_CCM_M_10; break ; - case 12: - *M = AES_CFG_CCM_M_12; break ; - case 14: - *M = AES_CFG_CCM_M_14; break ; - case 16: - *M = AES_CFG_CCM_M_16; break ; - default: - return 1 ; - } - - switch(nonceSz){ - case 7: - *L = AES_CFG_CCM_L_8; break ; - case 8: - *L = AES_CFG_CCM_L_7; break ; - case 9: - *L = AES_CFG_CCM_L_6; break ; - case 10: - *L = AES_CFG_CCM_L_5; break ; - case 11: - *L = AES_CFG_CCM_L_4; break ; - case 12: - *L = AES_CFG_CCM_L_3; break ; - case 13: - *L = AES_CFG_CCM_L_2; break ; - case 14: - *L = AES_CFG_CCM_L_1; break ; - default: - return 1; - } - return 0 ; -} - -static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, int mode) { - - if(mode == AES_CFG_MODE_CCM){ - XMEMSET(aes->reg, 0, 16) ; - switch(L){ - case AES_CFG_CCM_L_8: - aes->reg[0] = 0x7; break ; - case AES_CFG_CCM_L_7: - aes->reg[0] = 0x6; break ; - case AES_CFG_CCM_L_6: - aes->reg[0] = 0x5; break ; - case AES_CFG_CCM_L_5: - aes->reg[0] = 0x4; break ; - case AES_CFG_CCM_L_4: - aes->reg[0] = 0x3; break ; - case AES_CFG_CCM_L_3: - aes->reg[0] = 0x2; break ; - case AES_CFG_CCM_L_2: - aes->reg[0] = 0x1; break ; - case AES_CFG_CCM_L_1: - aes->reg[0] = 0x0; break ; - } - XMEMCPY(((byte *)aes->reg)+1, nonce, len) ; - } else { - byte *b = (byte *)aes->reg ; - XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); - XMEMCPY(aes->reg, nonce, len); - b[AES_BLOCK_SIZE-4] = 0 ; - b[AES_BLOCK_SIZE-3] = 0 ; - b[AES_BLOCK_SIZE-2] = 0 ; - b[AES_BLOCK_SIZE-1] = 1 ; - } -} - -#define RoundUp16(n) ((n+15)&0xfffffff0) -#define FREE_ALL \ - if(in_save) XFREE(in_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\ - if(out_save) XFREE(out_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\ - if(authIn_save)XFREE(authIn_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\ - if(nonce_save) XFREE(nonce_save, NULL, DYNAMIC_TYPE_TMP_BUFFER); - -static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz, int mode) -{ - word32 M, L ; - byte *in_a, *in_save ; - byte *out_a, *out_save ; - byte *authIn_a, *authIn_save ; - byte *nonce_a, *nonce_save ; - word32 tmpTag[4] ; - int ret ; - - if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L) - == BAD_FUNC_ARG)return BAD_FUNC_ARG ; - - /* 16 byte padding */ - in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ; - if((inSz%16)==0){ - in_save = NULL ; in_a = (byte *)in ; - out_save = NULL ; out_a = out ; - } else { - if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ - FREE_ALL; return MEMORY_E ; } - in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ; - - if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ - FREE_ALL; return MEMORY_E ; } - out_a = out_save ; - } - - if((authInSz%16)==0){ - authIn_save = NULL ; authIn_a = (byte *)authIn ; - } else { - if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ - FREE_ALL; return MEMORY_E ; } - authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ; - } - - if((nonceSz%16)==0){ - nonce_save = NULL ; nonce_a = (byte *)nonce ; - } else { - if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ - FREE_ALL; return MEMORY_E; } - nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ; - } - - /* do aes-ccm */ - AesAuthSetIv(aes, nonce, nonceSz, L, mode) ; - ROM_AESReset(AES_BASE); - ROM_AESConfigSet(AES_BASE, (aes->keylen | AES_CFG_DIR_ENCRYPT | - AES_CFG_CTR_WIDTH_128 | - mode | ((mode== AES_CFG_MODE_CCM) ? (L | M) : 0 ))) ; - ROM_AESIVSet(AES_BASE, aes->reg); - ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); - ret = ROM_AESDataProcessAuth(AES_BASE, (unsigned int*)in_a, (unsigned int *)out_a, inSz, - (unsigned int*)authIn_a, authInSz, (unsigned int *)tmpTag); - if(ret == false){ - XMEMSET(out, 0, inSz) ; - XMEMSET(authTag, 0, authTagSz) ; - } else { - XMEMCPY(out, out_a, inSz) ; - XMEMCPY(authTag, tmpTag, authTagSz) ; - } - - FREE_ALL; - return 0 ; -} - -static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz, int mode) -{ - word32 M, L ; - byte *in_a, *in_save ; - byte *out_a, *out_save ; - byte *authIn_a, *authIn_save ; - byte *nonce_a, *nonce_save ; - word32 tmpTag[4] ; - bool ret ; - - if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L) - == BAD_FUNC_ARG)return BAD_FUNC_ARG ; - - /* 16 byte padding */ - in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ; - if((inSz%16)==0){ - in_save = NULL ; in_a = (byte *)in ; - out_save = NULL ; out_a = out ; - } else { - if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ - FREE_ALL; return MEMORY_E;} - in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ; - - if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ - FREE_ALL; return MEMORY_E;} - out_a = out_save ; - } - - if((authInSz%16)==0){ - authIn_save = NULL ; authIn_a = (byte *)authIn ; - } else { - if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ - FREE_ALL; return MEMORY_E; } - authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ; - } - - if((nonceSz%16)==0){ - nonce_save = NULL ; nonce_a = (byte *)nonce ; - } else { - if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ - FREE_ALL; return MEMORY_E; } - nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ; - } - - /* do aes-ccm */ - AesAuthSetIv(aes, nonce, nonceSz, L, mode) ; - ROM_AESReset(AES_BASE); - ROM_AESConfigSet(AES_BASE, (aes->keylen | AES_CFG_DIR_DECRYPT | - AES_CFG_CTR_WIDTH_128 | - mode | ((mode== AES_CFG_MODE_CCM) ? (L | M) : 0 ))) ; - ROM_AESIVSet(AES_BASE, aes->reg); - ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); - ret = ROM_AESDataProcessAuth(AES_BASE, (unsigned int*)in_a, (unsigned int *)out_a, inSz, - (unsigned int*)authIn_a, authInSz, (unsigned int *)tmpTag); - if((ret == false) || (XMEMCMP(authTag, tmpTag, authTagSz) != 0)){ - XMEMSET(out, 0, inSz) ; - ret = false ; - } else { - XMEMCPY(out, out_a, inSz) ; - } - - FREE_ALL ; - return ret==true ? 0 : 1 ; -} -#endif - - -#ifdef HAVE_AESGCM -WOLFSSL_API int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) -{ - return AesAuthSetKey(aes, key, len) ; -} - -WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, - const byte* iv, word32 ivSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesAuthEncrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, - authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; -} -WOLFSSL_API int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, - const byte* iv, word32 ivSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesAuthDecrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, - authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; -} - -WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) -{ - return AesAuthSetKey(&gmac->aes, key, len) ; -} - -WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, - const byte* authIn, word32 authInSz, - byte* authTag, word32 authTagSz) -{ - return AesAuthEncrypt(&gmac->aes, NULL, NULL, 0, iv, ivSz, authTag, authTagSz, - authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; -} - -#endif /* HAVE_AESGCM */ - -#ifdef HAVE_AESCCM -WOLFSSL_API void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) -{ - AesAuthSetKey(aes, key, keySz) ; -} - -WOLFSSL_API void wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - AesAuthEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, - authIn, authInSz, AES_CFG_MODE_CCM) ; -} - -WOLFSSL_API int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesAuthDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, - authIn, authInSz, AES_CFG_MODE_CCM) ; -} -#endif /* HAVE_AESCCM */ - -#endif /* WOLFSSL_TI_CRYPT */ - -#endif /* NO_AES */ - - - +/* port/ti/ti-aes.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 + +#ifndef NO_AES + + +#if defined(WOLFSSL_TI_CRYPT) +#include +#include + +#include +#include +#include + +#include "inc/hw_aes.h" +#include "inc/hw_memmap.h" +#include "inc/hw_ints.h" +#include "driverlib/aes.h" +#include "driverlib/sysctl.h" +#include "driverlib/rom_map.h" +#include "driverlib/rom.h" + +static int AesSetIV(Aes* aes, const byte* iv) +{ + if (aes == NULL) + return BAD_FUNC_ARG; + + if (iv) + XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + else + XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); + + return 0; +} + +WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, + int dir) +{ + if(!wolfSSL_TI_CCMInit())return 1 ; + if ((aes == NULL) || (key == NULL) || (iv == NULL)) + return BAD_FUNC_ARG; + if(!((dir == AES_ENCRYPTION) || (dir == AES_DECRYPTION))) + return BAD_FUNC_ARG; + + switch(len) { + case 16: aes->keylen = AES_CFG_KEY_SIZE_128BIT ; break ; + case 24: aes->keylen = AES_CFG_KEY_SIZE_192BIT ; break ; + case 32: aes->keylen = AES_CFG_KEY_SIZE_256BIT ; break ; + default: return BAD_FUNC_ARG; + } + + XMEMCPY(aes->key, key, len) ; + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ + return AesSetIV(aes, iv); +} + +#define AES_CFG_MODE_CTR_NOCTR AES_CFG_MODE_CTR+100 +#define IS_ALIGN16(p) (((unsigned int)(p)&0xf) == 0) + +static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode) +{ + wolfSSL_TI_lockCCM() ; + ROM_AESReset(AES_BASE); + ROM_AESConfigSet(AES_BASE, (aes->keylen | dir | + (mode==AES_CFG_MODE_CTR_NOCTR ? AES_CFG_MODE_CTR : mode))); + AESIVSet(AES_BASE, aes->reg); + ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); + if((dir == AES_CFG_DIR_DECRYPT)&& (mode == AES_CFG_MODE_CBC)) + /* if input and output same will overwrite input iv */ + XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + ROM_AESDataProcess(AES_BASE, (uint32_t *)in, (uint32_t *)out, sz); + wolfSSL_TI_unlockCCM() ; + + /* store iv for next call */ + if(mode == AES_CFG_MODE_CBC){ + if(dir == AES_CFG_DIR_ENCRYPT) + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + else + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + + if(mode == AES_CFG_MODE_CTR) { + do { + int i ; + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++((byte *)aes->reg)[i]) + break ; + } + sz -= AES_BLOCK_SIZE ; + } while((int)sz > 0) ; + } + + return 0 ; +} + +static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode) +{ + const byte * in_p ; byte * out_p ; + word32 size ; + #define TI_BUFFSIZE 1024 + byte buff[TI_BUFFSIZE] ; + + if ((aes == NULL) || (in == NULL) || (out == NULL)) + return BAD_FUNC_ARG; + if(sz % AES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + while(sz > 0) { + size = sz ; in_p = in ; out_p = out ; + if(!IS_ALIGN16(in)){ + size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; + XMEMCPY(buff, in, size) ; + in_p = (const byte *)buff ; + } + if(!IS_ALIGN16(out)){ + size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; + out_p = buff ; + } + + AesAlign16(aes, out_p, in_p, size, dir, mode) ; + + if(!IS_ALIGN16(out)){ + XMEMCPY(out, buff, size) ; + } + sz -= size ; in += size ; out += size ; + } + + return 0 ; +} + +WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return AesProcess(aes, out, in, sz, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CBC) ; +} + +WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return AesProcess(aes, out, in, sz, AES_CFG_DIR_DECRYPT, AES_CFG_MODE_CBC) ; +} + +#ifdef WOLFSSL_AES_COUNTER +WOLFSSL_API void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + char out_block[AES_BLOCK_SIZE] ; + int odd ; + int even ; + char *tmp ; /* (char *)aes->tmp, for short */ + + tmp = (char *)aes->tmp ; + if(aes->left) { + if((aes->left + sz) >= AES_BLOCK_SIZE){ + odd = AES_BLOCK_SIZE - aes->left ; + } else { + odd = sz ; + } + XMEMCPY(tmp+aes->left, in, odd) ; + if((odd+aes->left) == AES_BLOCK_SIZE){ + AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, + AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CTR) ; + XMEMCPY(out, out_block+aes->left, odd) ; + aes->left = 0 ; + XMEMSET(tmp, 0x0, AES_BLOCK_SIZE) ; + } + in += odd ; + out+= odd ; + sz -= odd ; + } + odd = sz % AES_BLOCK_SIZE ; /* if there is tail flagment */ + if(sz / AES_BLOCK_SIZE) { + even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE ; + AesProcess(aes, out, in, even, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CTR); + out += even ; + in += even ; + } + if(odd) { + XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left) ; + XMEMCPY(tmp+aes->left, in, odd) ; + AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, + AES_CFG_DIR_ENCRYPT, + AES_CFG_MODE_CTR_NOCTR /* Counter mode without counting IV */ + ); + XMEMCPY(out, out_block+aes->left,odd) ; + aes->left += odd ; + } +} +#endif + +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) +WOLFSSL_API void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) +{ + AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CBC) ; +} +WOLFSSL_API void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) +{ + AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_DECRYPT, AES_CFG_MODE_CBC) ; +} +WOLFSSL_API int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) +{ + return(wc_AesSetKey(aes, key, len, iv, dir)) ; +} +#endif + + +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + +static int AesAuthSetKey(Aes* aes, const byte* key, word32 keySz) +{ + byte nonce[AES_BLOCK_SIZE]; + + if ((aes == NULL) || (key == NULL)) + return BAD_FUNC_ARG ; + if (!((keySz == 16) || (keySz == 24) || (keySz == 32))) + return BAD_FUNC_ARG ; + + XMEMSET(nonce, 0, sizeof(nonce)); + return wc_AesSetKey(aes, key, keySz, nonce, AES_ENCRYPTION); +} + + +static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz, word32 *M, word32 *L) +{ + if((aes == NULL)||(nonce == NULL)||(authTag== NULL)||(authIn == NULL)) + return BAD_FUNC_ARG; + if((inSz != 0) && ((out == NULL)||(in == NULL))) + return BAD_FUNC_ARG; + + switch(authTagSz){ + case 4: + *M = AES_CFG_CCM_M_4; break ; + case 6: + *M = AES_CFG_CCM_M_6; break ; + case 8: + *M = AES_CFG_CCM_M_8; break ; + case 10: + *M = AES_CFG_CCM_M_10; break ; + case 12: + *M = AES_CFG_CCM_M_12; break ; + case 14: + *M = AES_CFG_CCM_M_14; break ; + case 16: + *M = AES_CFG_CCM_M_16; break ; + default: + return 1 ; + } + + switch(nonceSz){ + case 7: + *L = AES_CFG_CCM_L_8; break ; + case 8: + *L = AES_CFG_CCM_L_7; break ; + case 9: + *L = AES_CFG_CCM_L_6; break ; + case 10: + *L = AES_CFG_CCM_L_5; break ; + case 11: + *L = AES_CFG_CCM_L_4; break ; + case 12: + *L = AES_CFG_CCM_L_3; break ; + case 13: + *L = AES_CFG_CCM_L_2; break ; + case 14: + *L = AES_CFG_CCM_L_1; break ; + default: + return 1; + } + return 0 ; +} + +static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, int mode) { + + if(mode == AES_CFG_MODE_CCM){ + XMEMSET(aes->reg, 0, 16) ; + switch(L){ + case AES_CFG_CCM_L_8: + aes->reg[0] = 0x7; break ; + case AES_CFG_CCM_L_7: + aes->reg[0] = 0x6; break ; + case AES_CFG_CCM_L_6: + aes->reg[0] = 0x5; break ; + case AES_CFG_CCM_L_5: + aes->reg[0] = 0x4; break ; + case AES_CFG_CCM_L_4: + aes->reg[0] = 0x3; break ; + case AES_CFG_CCM_L_3: + aes->reg[0] = 0x2; break ; + case AES_CFG_CCM_L_2: + aes->reg[0] = 0x1; break ; + case AES_CFG_CCM_L_1: + aes->reg[0] = 0x0; break ; + } + XMEMCPY(((byte *)aes->reg)+1, nonce, len) ; + } else { + byte *b = (byte *)aes->reg ; + XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, nonce, len); + b[AES_BLOCK_SIZE-4] = 0 ; + b[AES_BLOCK_SIZE-3] = 0 ; + b[AES_BLOCK_SIZE-2] = 0 ; + b[AES_BLOCK_SIZE-1] = 1 ; + } +} + +#define RoundUp16(n) ((n+15)&0xfffffff0) +#define FREE_ALL \ + if(in_save) XFREE(in_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\ + if(out_save) XFREE(out_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\ + if(authIn_save)XFREE(authIn_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\ + if(nonce_save) XFREE(nonce_save, NULL, DYNAMIC_TYPE_TMP_BUFFER); + +static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz, int mode) +{ + word32 M, L ; + byte *in_a, *in_save ; + byte *out_a, *out_save ; + byte *authIn_a, *authIn_save ; + byte *nonce_a, *nonce_save ; + word32 tmpTag[4] ; + int ret ; + + if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L) + == BAD_FUNC_ARG)return BAD_FUNC_ARG ; + + /* 16 byte padding */ + in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ; + if((inSz%16)==0){ + in_save = NULL ; in_a = (byte *)in ; + out_save = NULL ; out_a = out ; + } else { + if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E ; } + in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ; + + if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E ; } + out_a = out_save ; + } + + if((authInSz%16)==0){ + authIn_save = NULL ; authIn_a = (byte *)authIn ; + } else { + if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E ; } + authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ; + } + + if((nonceSz%16)==0){ + nonce_save = NULL ; nonce_a = (byte *)nonce ; + } else { + if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E; } + nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ; + } + + /* do aes-ccm */ + AesAuthSetIv(aes, nonce, nonceSz, L, mode) ; + ROM_AESReset(AES_BASE); + ROM_AESConfigSet(AES_BASE, (aes->keylen | AES_CFG_DIR_ENCRYPT | + AES_CFG_CTR_WIDTH_128 | + mode | ((mode== AES_CFG_MODE_CCM) ? (L | M) : 0 ))) ; + ROM_AESIVSet(AES_BASE, aes->reg); + ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); + ret = ROM_AESDataProcessAuth(AES_BASE, (unsigned int*)in_a, (unsigned int *)out_a, inSz, + (unsigned int*)authIn_a, authInSz, (unsigned int *)tmpTag); + if(ret == false){ + XMEMSET(out, 0, inSz) ; + XMEMSET(authTag, 0, authTagSz) ; + } else { + XMEMCPY(out, out_a, inSz) ; + XMEMCPY(authTag, tmpTag, authTagSz) ; + } + + FREE_ALL; + return 0 ; +} + +static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz, int mode) +{ + word32 M, L ; + byte *in_a, *in_save ; + byte *out_a, *out_save ; + byte *authIn_a, *authIn_save ; + byte *nonce_a, *nonce_save ; + word32 tmpTag[4] ; + bool ret ; + + if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L) + == BAD_FUNC_ARG)return BAD_FUNC_ARG ; + + /* 16 byte padding */ + in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ; + if((inSz%16)==0){ + in_save = NULL ; in_a = (byte *)in ; + out_save = NULL ; out_a = out ; + } else { + if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E;} + in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ; + + if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E;} + out_a = out_save ; + } + + if((authInSz%16)==0){ + authIn_save = NULL ; authIn_a = (byte *)authIn ; + } else { + if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E; } + authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ; + } + + if((nonceSz%16)==0){ + nonce_save = NULL ; nonce_a = (byte *)nonce ; + } else { + if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E; } + nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ; + } + + /* do aes-ccm */ + AesAuthSetIv(aes, nonce, nonceSz, L, mode) ; + ROM_AESReset(AES_BASE); + ROM_AESConfigSet(AES_BASE, (aes->keylen | AES_CFG_DIR_DECRYPT | + AES_CFG_CTR_WIDTH_128 | + mode | ((mode== AES_CFG_MODE_CCM) ? (L | M) : 0 ))) ; + ROM_AESIVSet(AES_BASE, aes->reg); + ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); + ret = ROM_AESDataProcessAuth(AES_BASE, (unsigned int*)in_a, (unsigned int *)out_a, inSz, + (unsigned int*)authIn_a, authInSz, (unsigned int *)tmpTag); + if((ret == false) || (XMEMCMP(authTag, tmpTag, authTagSz) != 0)){ + XMEMSET(out, 0, inSz) ; + ret = false ; + } else { + XMEMCPY(out, out_a, inSz) ; + } + + FREE_ALL ; + return ret==true ? 0 : 1 ; +} +#endif + + +#ifdef HAVE_AESGCM +WOLFSSL_API int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) +{ + return AesAuthSetKey(aes, key, len) ; +} + +WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + return AesAuthEncrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; +} +WOLFSSL_API int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + return AesAuthDecrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; +} + +WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) +{ + return AesAuthSetKey(&gmac->aes, key, len) ; +} + +WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz) +{ + return AesAuthEncrypt(&gmac->aes, NULL, NULL, 0, iv, ivSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; +} + +#endif /* HAVE_AESGCM */ + +#ifdef HAVE_AESCCM +WOLFSSL_API void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +{ + AesAuthSetKey(aes, key, keySz) ; +} + +WOLFSSL_API void wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + AesAuthEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_CCM) ; +} + +WOLFSSL_API int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + return AesAuthDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, + authIn, authInSz, AES_CFG_MODE_CCM) ; +} +#endif /* HAVE_AESCCM */ + +#endif /* WOLFSSL_TI_CRYPT */ + +#endif /* NO_AES */ + + + diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 2a91116a2..be2106cbd 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -1,473 +1,473 @@ -/* sha.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 - -#if !defined(NO_SHA) && !defined(WOLFSSL_TI_HASH) - -#include -#include -#include - -#ifdef NO_INLINE - #include -#else - #include -#endif - -/* fips wrapper calls, user can call direct */ -#ifdef HAVE_FIPS - int wc_InitSha(Sha* sha) - { - return InitSha_fips(sha); - } - - - int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) - { - return ShaUpdate_fips(sha, data, len); - } - - - int wc_ShaFinal(Sha* sha, byte* out) - { - return ShaFinal_fips(sha,out); - } - - int wc_ShaHash(const byte* data, word32 sz, byte* out) - { - return ShaHash(data, sz, out); - } - -#else /* else build without fips */ - -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitSha wc_InitSha_sw -#define wc_ShaUpdate wc_ShaUpdate_sw -#define wc_ShaFinal wc_ShaFinal_sw -#endif - - -#ifdef FREESCALE_MMCAU - #include "cau_api.h" - #define XTRANSFORM(S,B) cau_sha1_hash_n((B), 1, ((S))->digest) -#else - #define XTRANSFORM(S,B) Transform((S)) -#endif - -#ifdef STM32F2_HASH -/* - * STM32F2 hardware SHA1 support through the STM32F2 standard peripheral - * library. Documentation located in STM32F2xx Standard Peripheral Library - * document (See note in README). - */ -#include "stm32f2xx.h" -#include "stm32f2xx_hash.h" - -int wc_InitSha(Sha* sha) -{ - /* STM32F2 struct notes: - * sha->buffer = first 4 bytes used to hold partial block if needed - * sha->buffLen = num bytes currently stored in sha->buffer - * sha->loLen = num bytes that have been written to STM32 FIFO - */ - XMEMSET(sha->buffer, 0, SHA_REG_SIZE); - sha->buffLen = 0; - sha->loLen = 0; - - /* initialize HASH peripheral */ - HASH_DeInit(); - - /* configure algo used, algo mode, datatype */ - HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); - HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH - | HASH_DataType_8b); - - /* reset HASH processor */ - HASH->CR |= HASH_CR_INIT; - - return 0; -} - -int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) -{ - word32 i = 0; - word32 fill = 0; - word32 diff = 0; - - /* if saved partial block is available */ - if (sha->buffLen) { - fill = 4 - sha->buffLen; - - /* if enough data to fill, fill and push to FIFO */ - if (fill <= len) { - XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill); - HASH_DataIn(*(uint32_t*)sha->buffer); - - data += fill; - len -= fill; - sha->loLen += 4; - sha->buffLen = 0; - } else { - /* append partial to existing stored block */ - XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); - sha->buffLen += len; - return; - } - } - - /* write input block in the IN FIFO */ - for(i = 0; i < len; i += 4) - { - diff = len - i; - if ( diff < 4) { - /* store incomplete last block, not yet in FIFO */ - XMEMSET(sha->buffer, 0, SHA_REG_SIZE); - XMEMCPY((byte*)sha->buffer, data, diff); - sha->buffLen = diff; - } else { - HASH_DataIn(*(uint32_t*)data); - data+=4; - } - } - - /* keep track of total data length thus far */ - sha->loLen += (len - sha->buffLen); - - return 0; -} - -int wc_ShaFinal(Sha* sha, byte* hash) -{ - __IO uint16_t nbvalidbitsdata = 0; - - /* finish reading any trailing bytes into FIFO */ - if (sha->buffLen) { - HASH_DataIn(*(uint32_t*)sha->buffer); - sha->loLen += sha->buffLen; - } - - /* calculate number of valid bits in last word of input data */ - nbvalidbitsdata = 8 * (sha->loLen % SHA_REG_SIZE); - - /* configure number of valid bits in last word of the data */ - HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); - - /* start HASH processor */ - HASH_StartDigest(); - - /* wait until Busy flag == RESET */ - while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} - - /* read message digest */ - sha->digest[0] = HASH->HR[0]; - sha->digest[1] = HASH->HR[1]; - sha->digest[2] = HASH->HR[2]; - sha->digest[3] = HASH->HR[3]; - sha->digest[4] = HASH->HR[4]; - - ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); - - XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); - - return wc_InitSha(sha); /* reset state */ -} - -#elif defined(WOLFSSL_TI_HASH) - - /* defined in port/ti/ti_sha.c */ - -#else /* wc_ software implementation */ - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -int wc_InitSha(Sha* sha) -{ -#ifdef FREESCALE_MMCAU - cau_sha1_initialize_output(sha->digest); -#else - sha->digest[0] = 0x67452301L; - sha->digest[1] = 0xEFCDAB89L; - sha->digest[2] = 0x98BADCFEL; - sha->digest[3] = 0x10325476L; - sha->digest[4] = 0xC3D2E1F0L; -#endif - - sha->buffLen = 0; - sha->loLen = 0; - sha->hiLen = 0; - - return 0; -} - -#ifndef FREESCALE_MMCAU - -#define blk0(i) (W[i] = sha->buffer[i]) -#define blk1(i) (W[(i)&15] = \ -rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1)) - -#define f1(x,y,z) ((z)^((x) &((y)^(z)))) -#define f2(x,y,z) ((x)^(y)^(z)) -#define f3(x,y,z) (((x)&(y))|((z)&((x)|(y)))) -#define f4(x,y,z) ((x)^(y)^(z)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); - -static void Transform(Sha* sha) -{ - word32 W[SHA_BLOCK_SIZE / sizeof(word32)]; - - /* Copy context->state[] to working vars */ - word32 a = sha->digest[0]; - word32 b = sha->digest[1]; - word32 c = sha->digest[2]; - word32 d = sha->digest[3]; - word32 e = sha->digest[4]; - -#ifdef USE_SLOW_SHA - word32 t, i; - - for (i = 0; i < 16; i++) { - R0(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 20; i++) { - R1(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 40; i++) { - R2(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 60; i++) { - R3(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 80; i++) { - R4(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } -#else - /* nearly 1 K bigger in code size but 25% faster */ - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); -#endif - - /* Add the working vars back into digest state[] */ - sha->digest[0] += a; - sha->digest[1] += b; - sha->digest[2] += c; - sha->digest[3] += d; - sha->digest[4] += e; -} - -#endif /* FREESCALE_MMCAU */ - - -static INLINE void AddLength(Sha* sha, word32 len) -{ - word32 tmp = sha->loLen; - if ( (sha->loLen += len) < tmp) - sha->hiLen++; /* carry low to high */ -} - - -int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) -{ - /* do block size increments */ - byte* local = (byte*)sha->buffer; - - while (len) { - word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); - XMEMCPY(&local[sha->buffLen], data, add); - - sha->buffLen += add; - data += add; - len -= add; - - if (sha->buffLen == SHA_BLOCK_SIZE) { -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); -#endif - XTRANSFORM(sha, local); - AddLength(sha, SHA_BLOCK_SIZE); - sha->buffLen = 0; - } - } - - return 0; -} - - -int wc_ShaFinal(Sha* sha, byte* hash) -{ - byte* local = (byte*)sha->buffer; - - AddLength(sha, sha->buffLen); /* before adding pads */ - - local[sha->buffLen++] = 0x80; /* add 1 */ - - /* pad with zeros */ - if (sha->buffLen > SHA_PAD_SIZE) { - XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen); - sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen; - -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); -#endif - XTRANSFORM(sha, local); - sha->buffLen = 0; - } - XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen); - - /* put lengths in bits */ - sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + - (sha->hiLen << 3); - sha->loLen = sha->loLen << 3; - - /* store lengths */ -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); -#endif - /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); - XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); - -#ifdef FREESCALE_MMCAU - /* Kinetis requires only these bytes reversed */ - ByteReverseWords(&sha->buffer[SHA_PAD_SIZE/sizeof(word32)], - &sha->buffer[SHA_PAD_SIZE/sizeof(word32)], - 2 * sizeof(word32)); -#endif - - XTRANSFORM(sha, local); -#ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); -#endif - XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); - - return wc_InitSha(sha); /* reset state */ -} - -#endif /* STM32F2_HASH */ - - -int wc_ShaHash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha* sha; -#else - Sha sha[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha(sha)) != 0) { - WOLFSSL_MSG("wc_InitSha failed"); - } - else { - wc_ShaUpdate(sha, data, len); - wc_ShaFinal(sha, hash); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; - -} - -#ifdef WOLFSSL_TI_HASH -#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif -int wc_ShaGetHash(Sha* sha, byte* hash) -{ -#if defined(WOLFSS_TI_HASH) - wc_ShaGetHash_TI(sha, hash) ; -#else - int ret ; - Sha save = *sha ; - ret = wc_ShaFinal(sha, hash) ; - *sha = save ; - return ret ; -#endif -} - -#endif /* HAVE_FIPS */ -#endif /* NO_SHA */ - +/* sha.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 + +#if !defined(NO_SHA) && !defined(WOLFSSL_TI_HASH) + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #include +#endif + +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + int wc_InitSha(Sha* sha) + { + return InitSha_fips(sha); + } + + + int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) + { + return ShaUpdate_fips(sha, data, len); + } + + + int wc_ShaFinal(Sha* sha, byte* out) + { + return ShaFinal_fips(sha,out); + } + + int wc_ShaHash(const byte* data, word32 sz, byte* out) + { + return ShaHash(data, sz, out); + } + +#else /* else build without fips */ + +#ifdef WOLFSSL_PIC32MZ_HASH +#define wc_InitSha wc_InitSha_sw +#define wc_ShaUpdate wc_ShaUpdate_sw +#define wc_ShaFinal wc_ShaFinal_sw +#endif + + +#ifdef FREESCALE_MMCAU + #include "cau_api.h" + #define XTRANSFORM(S,B) cau_sha1_hash_n((B), 1, ((S))->digest) +#else + #define XTRANSFORM(S,B) Transform((S)) +#endif + +#ifdef STM32F2_HASH +/* + * STM32F2 hardware SHA1 support through the STM32F2 standard peripheral + * library. Documentation located in STM32F2xx Standard Peripheral Library + * document (See note in README). + */ +#include "stm32f2xx.h" +#include "stm32f2xx_hash.h" + +int wc_InitSha(Sha* sha) +{ + /* STM32F2 struct notes: + * sha->buffer = first 4 bytes used to hold partial block if needed + * sha->buffLen = num bytes currently stored in sha->buffer + * sha->loLen = num bytes that have been written to STM32 FIFO + */ + XMEMSET(sha->buffer, 0, SHA_REG_SIZE); + sha->buffLen = 0; + sha->loLen = 0; + + /* initialize HASH peripheral */ + HASH_DeInit(); + + /* configure algo used, algo mode, datatype */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + + return 0; +} + +int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +{ + word32 i = 0; + word32 fill = 0; + word32 diff = 0; + + /* if saved partial block is available */ + if (sha->buffLen) { + fill = 4 - sha->buffLen; + + /* if enough data to fill, fill and push to FIFO */ + if (fill <= len) { + XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill); + HASH_DataIn(*(uint32_t*)sha->buffer); + + data += fill; + len -= fill; + sha->loLen += 4; + sha->buffLen = 0; + } else { + /* append partial to existing stored block */ + XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); + sha->buffLen += len; + return; + } + } + + /* write input block in the IN FIFO */ + for(i = 0; i < len; i += 4) + { + diff = len - i; + if ( diff < 4) { + /* store incomplete last block, not yet in FIFO */ + XMEMSET(sha->buffer, 0, SHA_REG_SIZE); + XMEMCPY((byte*)sha->buffer, data, diff); + sha->buffLen = diff; + } else { + HASH_DataIn(*(uint32_t*)data); + data+=4; + } + } + + /* keep track of total data length thus far */ + sha->loLen += (len - sha->buffLen); + + return 0; +} + +int wc_ShaFinal(Sha* sha, byte* hash) +{ + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (sha->buffLen) { + HASH_DataIn(*(uint32_t*)sha->buffer); + sha->loLen += sha->buffLen; + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (sha->loLen % SHA_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + sha->digest[0] = HASH->HR[0]; + sha->digest[1] = HASH->HR[1]; + sha->digest[2] = HASH->HR[2]; + sha->digest[3] = HASH->HR[3]; + sha->digest[4] = HASH->HR[4]; + + ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); + + XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); + + return wc_InitSha(sha); /* reset state */ +} + +#elif defined(WOLFSSL_TI_HASH) + + /* defined in port/ti/ti_sha.c */ + +#else /* wc_ software implementation */ + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +int wc_InitSha(Sha* sha) +{ +#ifdef FREESCALE_MMCAU + cau_sha1_initialize_output(sha->digest); +#else + sha->digest[0] = 0x67452301L; + sha->digest[1] = 0xEFCDAB89L; + sha->digest[2] = 0x98BADCFEL; + sha->digest[3] = 0x10325476L; + sha->digest[4] = 0xC3D2E1F0L; +#endif + + sha->buffLen = 0; + sha->loLen = 0; + sha->hiLen = 0; + + return 0; +} + +#ifndef FREESCALE_MMCAU + +#define blk0(i) (W[i] = sha->buffer[i]) +#define blk1(i) (W[(i)&15] = \ +rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1)) + +#define f1(x,y,z) ((z)^((x) &((y)^(z)))) +#define f2(x,y,z) ((x)^(y)^(z)) +#define f3(x,y,z) (((x)&(y))|((z)&((x)|(y)))) +#define f4(x,y,z) ((x)^(y)^(z)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); +#define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); +#define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); +#define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); +#define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \ +rotlFixed((v),5); (w) = rotlFixed((w),30); + +static void Transform(Sha* sha) +{ + word32 W[SHA_BLOCK_SIZE / sizeof(word32)]; + + /* Copy context->state[] to working vars */ + word32 a = sha->digest[0]; + word32 b = sha->digest[1]; + word32 c = sha->digest[2]; + word32 d = sha->digest[3]; + word32 e = sha->digest[4]; + +#ifdef USE_SLOW_SHA + word32 t, i; + + for (i = 0; i < 16; i++) { + R0(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 20; i++) { + R1(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; i++) { + R2(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; i++) { + R3(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; i++) { + R4(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } +#else + /* nearly 1 K bigger in code size but 25% faster */ + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); +#endif + + /* Add the working vars back into digest state[] */ + sha->digest[0] += a; + sha->digest[1] += b; + sha->digest[2] += c; + sha->digest[3] += d; + sha->digest[4] += e; +} + +#endif /* FREESCALE_MMCAU */ + + +static INLINE void AddLength(Sha* sha, word32 len) +{ + word32 tmp = sha->loLen; + if ( (sha->loLen += len) < tmp) + sha->hiLen++; /* carry low to high */ +} + + +int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local = (byte*)sha->buffer; + + while (len) { + word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, add); + + sha->buffLen += add; + data += add; + len -= add; + + if (sha->buffLen == SHA_BLOCK_SIZE) { +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); +#endif + XTRANSFORM(sha, local); + AddLength(sha, SHA_BLOCK_SIZE); + sha->buffLen = 0; + } + } + + return 0; +} + + +int wc_ShaFinal(Sha* sha, byte* hash) +{ + byte* local = (byte*)sha->buffer; + + AddLength(sha, sha->buffLen); /* before adding pads */ + + local[sha->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha->buffLen > SHA_PAD_SIZE) { + XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen); + sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen; + +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); +#endif + XTRANSFORM(sha, local); + sha->buffLen = 0; + } + XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen); + + /* put lengths in bits */ + sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + + (sha->hiLen << 3); + sha->loLen = sha->loLen << 3; + + /* store lengths */ +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); +#endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); + XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); + +#ifdef FREESCALE_MMCAU + /* Kinetis requires only these bytes reversed */ + ByteReverseWords(&sha->buffer[SHA_PAD_SIZE/sizeof(word32)], + &sha->buffer[SHA_PAD_SIZE/sizeof(word32)], + 2 * sizeof(word32)); +#endif + + XTRANSFORM(sha, local); +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); +#endif + XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); + + return wc_InitSha(sha); /* reset state */ +} + +#endif /* STM32F2_HASH */ + + +int wc_ShaHash(const byte* data, word32 len, byte* hash) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Sha* sha; +#else + Sha sha[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return MEMORY_E; +#endif + + if ((ret = wc_InitSha(sha)) != 0) { + WOLFSSL_MSG("wc_InitSha failed"); + } + else { + wc_ShaUpdate(sha, data, len); + wc_ShaFinal(sha, hash); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; + +} + +#ifdef WOLFSSL_TI_HASH +#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif +int wc_ShaGetHash(Sha* sha, byte* hash) +{ +#if defined(WOLFSS_TI_HASH) + wc_ShaGetHash_TI(sha, hash) ; +#else + int ret ; + Sha save = *sha ; + ret = wc_ShaFinal(sha, hash) ; + *sha = save ; + return ret ; +#endif +} + +#endif /* HAVE_FIPS */ +#endif /* NO_SHA */ + diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index ec4eb918b..90f99a35b 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -1,1781 +1,1781 @@ -/* sha256.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 - */ - -/* code submitted by raphael.huck@efixo.com */ - -#ifdef HAVE_CONFIG_H - #include -#endif - -#include -#include - -#if !defined(NO_SHA256) -#ifdef HAVE_FIPS - -int wc_InitSha256(Sha256* sha) -{ - return InitSha256_fips(sha); -} - - -int wc_Sha256Update(Sha256* sha, const byte* data, word32 len) -{ - return Sha256Update_fips(sha, data, len); -} - - -int wc_Sha256Final(Sha256* sha, byte* out) -{ - return Sha256Final_fips(sha, out); -} - - -int wc_Sha256Hash(const byte* data, word32 len, byte* out) -{ - return Sha256Hash(data, len, out); -} - -#else /* else build without fips */ - -#if !defined(NO_SHA256) && !defined(WOLFSSL_TI_HASH) - /* defined in port/ti/ti_sha256.c */ - -#if !defined (ALIGN32) - #if defined (__GNUC__) - #define ALIGN32 __attribute__ ( (aligned (32))) - #elif defined(_MSC_VER) - /* disable align warning, we want alignment ! */ - #pragma warning(disable: 4324) - #define ALIGN32 __declspec (align (32)) - #else - #define ALIGN32 - #endif -#endif - -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitSha256 wc_InitSha256_sw -#define wc_Sha256Update wc_Sha256Update_sw -#define wc_Sha256Final wc_Sha256Final_sw -#endif - -#ifdef HAVE_FIPS - /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ - #define FIPS_NO_WRAPPERS -#endif - -#if defined(USE_INTEL_SPEEDUP) -#define HAVE_INTEL_AVX1 -#define HAVE_INTEL_AVX2 - -#if defined(DEBUG_XMM) -#include "stdio.h" -#endif - -#endif - -#if defined(HAVE_INTEL_AVX2) -#define HAVE_INTEL_RORX -#endif - - -/***** -Intel AVX1/AVX2 Macro Control Structure - -#define HAVE_INTEL_AVX1 -#define HAVE_INTEL_AVX2 - -#define HAVE_INTEL_RORX - - -int InitSha256(Sha256* sha256) { - Save/Recover XMM, YMM - ... -} - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - Transform() ; Function prototype -#else - Transform() { } - int Sha256Final() { - Save/Recover XMM, YMM - ... - } -#endif - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - #if defined(HAVE_INTEL_RORX - #define RND with rorx instuction - #else - #define RND - #endif -#endif - -#if defined(HAVE_INTEL_AVX1) - - #define XMM Instructions/inline asm - - int Transform() { - Stitched Message Sched/Round - } - -#elif defined(HAVE_INTEL_AVX2) - - #define YMM Instructions/inline asm - - int Transform() { - More granural Stitched Message Sched/Round - } - -*/ - - -#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - -/* Each platform needs to query info type 1 from cpuid to see if aesni is - * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts - */ - -#ifndef _MSC_VER - #define cpuid(reg, leaf, sub)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (leaf), "c"(sub)); - - #define XASM_LINK(f) asm(f) -#else - - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - -#define EAX 0 -#define EBX 1 -#define ECX 2 -#define EDX 3 - -#define CPUID_AVX1 0x1 -#define CPUID_AVX2 0x2 -#define CPUID_RDRAND 0x4 -#define CPUID_RDSEED 0x8 -#define CPUID_BMI2 0x10 /* MULX, RORX */ - -#define IS_INTEL_AVX1 (cpuid_flags&CPUID_AVX1) -#define IS_INTEL_AVX2 (cpuid_flags&CPUID_AVX2) -#define IS_INTEL_BMI2 (cpuid_flags&CPUID_BMI2) -#define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) -#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) - -static word32 cpuid_check = 0 ; -static word32 cpuid_flags = 0 ; - -static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { - int got_intel_cpu=0; - unsigned int reg[5]; - - reg[4] = '\0' ; - cpuid(reg, 0, 0); - if(memcmp((char *)&(reg[EBX]), "Genu", 4) == 0 && - memcmp((char *)&(reg[EDX]), "ineI", 4) == 0 && - memcmp((char *)&(reg[ECX]), "ntel", 4) == 0) { - got_intel_cpu = 1; - } - if (got_intel_cpu) { - cpuid(reg, leaf, sub); - return((reg[num]>>bit)&0x1) ; - } - return 0 ; -} - -static int set_cpuid_flags(void) { - if(cpuid_check==0) { - if(cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1 ;} - if(cpuid_flag(7, 0, EBX, 5)){ cpuid_flags |= CPUID_AVX2 ; } - if(cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } - if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ; } - if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ; } - cpuid_check = 1 ; - return 0 ; - } - return 1 ; -} - - -/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha512 */ -static int Transform(Sha256* sha256); - -#if defined(HAVE_INTEL_AVX1) -static int Transform_AVX1(Sha256 *sha256) ; -#endif -#if defined(HAVE_INTEL_AVX2) -static int Transform_AVX2(Sha256 *sha256) ; -static int Transform_AVX1_RORX(Sha256 *sha256) ; -#endif - -static int (*Transform_p)(Sha256* sha256) /* = _Transform */; - -#define XTRANSFORM(sha256, B) (*Transform_p)(sha256) - -static void set_Transform(void) { - if(set_cpuid_flags())return ; - -#if defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ - Transform_p = Transform_AVX1_RORX; return ; - Transform_p = Transform_AVX2 ; - /* for avoiding warning,"not used" */ - } -#endif -#if defined(HAVE_INTEL_AVX1) - Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : Transform) ; return ; -#endif - Transform_p = Transform ; return ; -} - -#else - #if defined(FREESCALE_MMCAU) - #define XTRANSFORM(sha256, B) Transform(sha256, B) - #else - #define XTRANSFORM(sha256, B) Transform(sha256) - #endif -#endif - -/* Dummy for saving MM_REGs on behalf of Transform */ -#if defined(HAVE_INTEL_AVX2)&& !defined(HAVE_INTEL_AVX1) -#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ - "%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15") -#elif defined(HAVE_INTEL_AVX1) -#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ - "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10",\ - "xmm11","xmm12","xmm13","xmm14","xmm15") -#else -#define SAVE_XMM_YMM -#endif - -#ifdef WOLFSSL_PIC32MZ_HASH -#define InitSha256 InitSha256_sw -#define Sha256Update Sha256Update_sw -#define Sha256Final Sha256Final_sw -#endif - -#include -#include - -#ifdef NO_INLINE - #include -#else - #include -#endif - -#ifdef FREESCALE_MMCAU - #include "cau_api.h" -#endif - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -int wc_InitSha256(Sha256* sha256) -{ - #ifdef FREESCALE_MMCAU - cau_sha256_initialize_output(sha256->digest); - #else - sha256->digest[0] = 0x6A09E667L; - sha256->digest[1] = 0xBB67AE85L; - sha256->digest[2] = 0x3C6EF372L; - sha256->digest[3] = 0xA54FF53AL; - sha256->digest[4] = 0x510E527FL; - sha256->digest[5] = 0x9B05688CL; - sha256->digest[6] = 0x1F83D9ABL; - sha256->digest[7] = 0x5BE0CD19L; - #endif - - sha256->buffLen = 0; - sha256->loLen = 0; - sha256->hiLen = 0; - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; /* choose best Transform function under this runtime environment */ -#endif - - return 0; -} - - -#if !defined(FREESCALE_MMCAU) -static const ALIGN32 word32 K[64] = { - 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, - 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, - 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, - 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, - 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L, - 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L, - 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, - 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, - 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L, - 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L, - 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, - 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, - 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L -}; - -#endif - -#if defined(FREESCALE_MMCAU) - -static int Transform(Sha256* sha256, byte* buf) -{ - cau_sha256_hash_n(buf, 1, sha256->digest); - - return 0; -} - -#endif /* FREESCALE_MMCAU */ - -#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) -#define R(x, n) (((x)&0xFFFFFFFFU)>>(n)) - -#define S(x, n) rotrFixed(x, n) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - -#define RND(a,b,c,d,e,f,g,h,i) \ - t0 = (h) + Sigma1((e)) + Ch((e), (f), (g)) + K[(i)] + W[(i)]; \ - t1 = Sigma0((a)) + Maj((a), (b), (c)); \ - (d) += t0; \ - (h) = t0 + t1; - -#if !defined(FREESCALE_MMCAU) -static int Transform(Sha256* sha256) -{ - word32 S[8], t0, t1; - int i; - -#ifdef WOLFSSL_SMALL_STACK - word32* W; - - W = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (W == NULL) - return MEMORY_E; -#else - word32 W[64]; -#endif - - /* Copy context->state[] to working vars */ - for (i = 0; i < 8; i++) - S[i] = sha256->digest[i]; - - for (i = 0; i < 16; i++) - W[i] = sha256->buffer[i]; - - for (i = 16; i < 64; i++) - W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; - - for (i = 0; i < 64; i += 8) { - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); - } - - /* Add the working vars back into digest state[] */ - for (i = 0; i < 8; i++) { - sha256->digest[i] += S[i]; - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return 0; -} - -#endif /* #if !defined(FREESCALE_MMCAU) */ - -static INLINE void AddLength(Sha256* sha256, word32 len) -{ - word32 tmp = sha256->loLen; - if ( (sha256->loLen += len) < tmp) - sha256->hiLen++; /* carry low to high */ -} - -int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) -{ - - /* do block size increments */ - byte* local = (byte*)sha256->buffer; - - SAVE_XMM_YMM ; /* for Intel AVX */ - - while (len) { - word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); - XMEMCPY(&local[sha256->buffLen], data, add); - - sha256->buffLen += add; - data += add; - len -= add; - - if (sha256->buffLen == SHA256_BLOCK_SIZE) { - int ret; - - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords(sha256->buffer, sha256->buffer, - SHA256_BLOCK_SIZE); - #endif - ret = XTRANSFORM(sha256, local); - if (ret != 0) - return ret; - - AddLength(sha256, SHA256_BLOCK_SIZE); - sha256->buffLen = 0; - } - } - - return 0; -} - -int wc_Sha256Final(Sha256* sha256, byte* hash) -{ - byte* local = (byte*)sha256->buffer; - int ret; - - SAVE_XMM_YMM ; /* for Intel AVX */ - - AddLength(sha256, sha256->buffLen); /* before adding pads */ - - local[sha256->buffLen++] = 0x80; /* add 1 */ - - /* pad with zeros */ - if (sha256->buffLen > SHA256_PAD_SIZE) { - XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen); - sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; - - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); - #endif - - ret = XTRANSFORM(sha256, local); - if (ret != 0) - return ret; - - sha256->buffLen = 0; - } - XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen); - - /* put lengths in bits */ - sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) + - (sha256->hiLen << 3); - sha256->loLen = sha256->loLen << 3; - - /* store lengths */ - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); - #endif - /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); - XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, - sizeof(word32)); - - #if defined(FREESCALE_MMCAU) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - /* Kinetis requires only these bytes reversed */ - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX1 || IS_INTEL_AVX2) - #endif - ByteReverseWords(&sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], - &sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], - 2 * sizeof(word32)); - #endif - - ret = XTRANSFORM(sha256, local); - if (ret != 0) - return ret; - - #if defined(LITTLE_ENDIAN_ORDER) - ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE); - #endif - XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE); - - return wc_InitSha256(sha256); /* reset state */ -} - - - -int wc_Sha256Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha256* sha256; -#else - Sha256 sha256[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha256(sha256)) != 0) { - WOLFSSL_MSG("InitSha256 failed"); - } - else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { - WOLFSSL_MSG("Sha256Update failed"); - } - else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { - WOLFSSL_MSG("Sha256Final failed"); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -#ifdef WOLFSSL_TI_HASH -#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif -int wc_Sha256GetHash(Sha256* sha256, byte* hash) -{ -#if defined(WOLFSS_TI_HASH) - return wc_Sha256GetHash_TI(sha256, hash) ; -#else - int ret ; - Sha256 save = *sha256 ; - ret = wc_Sha256Final(sha256, hash) ; - *sha256 = save ; - return ret ; -#endif -} - -#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - -#define _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ;\ - d = sha256->digest[0]; __asm__ volatile("movl %0, %"#S_0::"r"(d):SSE_REGs) ;\ - d = sha256->digest[1]; __asm__ volatile("movl %0, %"#S_1::"r"(d):SSE_REGs) ;\ - d = sha256->digest[2]; __asm__ volatile("movl %0, %"#S_2::"r"(d):SSE_REGs) ;\ - d = sha256->digest[3]; __asm__ volatile("movl %0, %"#S_3::"r"(d):SSE_REGs) ;\ - d = sha256->digest[4]; __asm__ volatile("movl %0, %"#S_4::"r"(d):SSE_REGs) ;\ - d = sha256->digest[5]; __asm__ volatile("movl %0, %"#S_5::"r"(d):SSE_REGs) ;\ - d = sha256->digest[6]; __asm__ volatile("movl %0, %"#S_6::"r"(d):SSE_REGs) ;\ - d = sha256->digest[7]; __asm__ volatile("movl %0, %"#S_7::"r"(d):SSE_REGs) ;\ -} - -#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ; \ - __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ; sha256->digest[0] += d;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ; sha256->digest[1] += d;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ; sha256->digest[2] += d;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ; sha256->digest[3] += d;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ; sha256->digest[4] += d;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ; sha256->digest[5] += d;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ; sha256->digest[6] += d;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ; sha256->digest[7] += d;\ -} - - -#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - -#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - - - - -#define S_0 %r15d -#define S_1 %r10d -#define S_2 %r11d -#define S_3 %r12d -#define S_4 %r13d -#define S_5 %r14d -#define S_6 %ebx -#define S_7 %r9d - -#define SSE_REGs "%edi", "%ecx", "%esi", "%edx", "%ebx","%r8","%r9","%r10","%r11","%r12","%r13","%r14","%r15" - -#if defined(HAVE_INTEL_RORX) -#define RND_STEP_RORX_1(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("rorx $6, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ - -#define RND_STEP_RORX_2(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("rorx $11, %"#e",%%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ -__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ -__asm__ volatile("rorx $25, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ - -#define RND_STEP_RORX_3(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ -__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ - -#define RND_STEP_RORX_4(a,b,c,d,e,f,g,h,i)\ -/*__asm__ volatile("movl %0, %%edx\n\t"::"m"(w_k):"%edx");*/\ -__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ -__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ -__asm__ volatile("rorx $2, %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ -__asm__ volatile("rorx $13, %"#a", %%edi\n\t":::"%edi",SSE_REGs);/* edi = a>>13 */\ - -#define RND_STEP_RORX_5(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("rorx $22, %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ -__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs);/* edi = (a>>2) ^ (a>>13) */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma0(a) */\ - -#define RND_STEP_RORX_6(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ -__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ -__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c*/\ -__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ - -#define RND_STEP_RORX_7(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ -__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ -__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ - -#define RND_STEP_RORX_8(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ -__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ -__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs); \ -__asm__ volatile("movl %r8d, "#h"\n\t"); - -#endif - -#define RND_STEP_1(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs);\ -__asm__ volatile("roll $26, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ -__asm__ volatile("movl %"#e", %%edi\n\t":::"%edi",SSE_REGs);\ - -#define RND_STEP_2(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("roll $21, %%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ -__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ -__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e */\ -__asm__ volatile("roll $7, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ - -#define RND_STEP_3(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ -__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ - -#define RND_STEP_4(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ -__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ -__asm__ volatile("movl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a */\ -__asm__ volatile("roll $30, %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ -__asm__ volatile("movl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a */\ -__asm__ volatile("roll $19, %%edi\n\t":::"%edi",SSE_REGs); /* edi = a>>13 */\ -__asm__ volatile("movl %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a */\ - -#define RND_STEP_5(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("roll $10, %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ -__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs); /* edi = (a>>2) ^ (a>>13) */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs);/* edx = Sigma0(a) */\ - -#define RND_STEP_6(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ -__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ -__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c */\ -__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ - -#define RND_STEP_7(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ -__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ -__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ - -#define RND_STEP_8(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ -__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ - /* r8b = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */\ -__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs);\ - /* r8b = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */\ -__asm__ volatile("movl %%r8d, %"#h"\n\t":::"%r8", SSE_REGs); \ - /* h = h + w_k + Sigma1(e) + Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ - -#define RND_X(a,b,c,d,e,f,g,h,i) \ - RND_STEP_1(a,b,c,d,e,f,g,h,i); \ - RND_STEP_2(a,b,c,d,e,f,g,h,i); \ - RND_STEP_3(a,b,c,d,e,f,g,h,i); \ - RND_STEP_4(a,b,c,d,e,f,g,h,i); \ - RND_STEP_5(a,b,c,d,e,f,g,h,i); \ - RND_STEP_6(a,b,c,d,e,f,g,h,i); \ - RND_STEP_7(a,b,c,d,e,f,g,h,i); \ - RND_STEP_8(a,b,c,d,e,f,g,h,i); - -#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - - -#define RND_1_3(a,b,c,d,e,f,g,h,i) {\ - RND_STEP_1(a,b,c,d,e,f,g,h,i); \ - RND_STEP_2(a,b,c,d,e,f,g,h,i); \ - RND_STEP_3(a,b,c,d,e,f,g,h,i); \ -} - -#define RND_4_6(a,b,c,d,e,f,g,h,i) {\ - RND_STEP_4(a,b,c,d,e,f,g,h,i); \ - RND_STEP_5(a,b,c,d,e,f,g,h,i); \ - RND_STEP_6(a,b,c,d,e,f,g,h,i); \ -} - -#define RND_7_8(a,b,c,d,e,f,g,h,i) {\ - RND_STEP_7(a,b,c,d,e,f,g,h,i); \ - RND_STEP_8(a,b,c,d,e,f,g,h,i); \ -} - -#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - - -#define RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - -#define RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - -#define RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - -#define FOR(cnt, init, max, inc, loop) \ - __asm__ volatile("movl $"#init", %0\n\t"#loop":"::"m"(cnt):) -#define END(cnt, init, max, inc, loop) \ - __asm__ volatile("addl $"#inc", %0\n\tcmpl $"#max", %0\n\tjle "#loop"\n\t":"=m"(cnt)::) ; - -#endif /* defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) */ - -#if defined(HAVE_INTEL_AVX1) /* inline Assember for Intel AVX1 instructions */ - -#define VPALIGNR(op1,op2,op3,op4) __asm__ volatile("vpalignr $"#op4", %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPADDD(op1,op2,op3) __asm__ volatile("vpaddd %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSRLD(op1,op2,op3) __asm__ volatile("vpsrld $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSRLQ(op1,op2,op3) __asm__ volatile("vpsrlq $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSLLD(op1,op2,op3) __asm__ volatile("vpslld $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPOR(op1,op2,op3) __asm__ volatile("vpor %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPXOR(op1,op2,op3) __asm__ volatile("vpxor %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSHUFD(op1,op2,op3) __asm__ volatile("vpshufd $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSHUFB(op1,op2,op3) __asm__ volatile("vpshufb %"#op3", %"#op2", %"#op1:::XMM_REGs) - -#define MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, SHUF_00BA, SHUF_DC00,\ - a,b,c,d,e,f,g,h,_i)\ - RND_STEP_1(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP0, X3, X2, 4) ;\ - RND_STEP_2(a,b,c,d,e,f,g,h,_i);\ - VPADDD (XTMP0, XTMP0, X0) ;\ - RND_STEP_3(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ - RND_STEP_4(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1, 7) ;\ - RND_STEP_5(a,b,c,d,e,f,g,h,_i);\ - VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ - RND_STEP_6(a,b,c,d,e,f,g,h,_i);\ - VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ - RND_STEP_7(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1,18) ;\ - RND_STEP_8(a,b,c,d,e,f,g,h,_i);\ -\ - RND_STEP_1(h,a,b,c,d,e,f,g,_i+1);\ - VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ - RND_STEP_2(h,a,b,c,d,e,f,g,_i+1);\ - VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ - RND_STEP_3(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP1) ;\ - RND_STEP_4(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ - RND_STEP_5(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ - RND_STEP_6(h,a,b,c,d,e,f,g,_i+1);\ - VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ - RND_STEP_7(h,a,b,c,d,e,f,g,_i+1);\ - VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ - RND_STEP_8(h,a,b,c,d,e,f,g,_i+1);\ -\ - RND_STEP_1(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ - RND_STEP_2(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ - RND_STEP_3(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ - RND_STEP_4(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_5(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ - RND_STEP_6(g,h,a,b,c,d,e,f,_i+2);\ - VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ - RND_STEP_7(g,h,a,b,c,d,e,f,_i+2);\ - VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ - RND_STEP_8(g,h,a,b,c,d,e,f,_i+2);\ -\ - RND_STEP_1(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ - RND_STEP_2(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ - RND_STEP_3(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ - RND_STEP_4(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ - RND_STEP_5(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_6(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ - RND_STEP_7(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ - RND_STEP_8(f,g,h,a,b,c,d,e,_i+3);\ - VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ - -#if defined(HAVE_INTEL_RORX) - -#define MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, \ - XFER, SHUF_00BA, SHUF_DC00,a,b,c,d,e,f,g,h,_i)\ - RND_STEP_RORX_1(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP0, X3, X2, 4) ;\ - RND_STEP_RORX_2(a,b,c,d,e,f,g,h,_i);\ - VPADDD (XTMP0, XTMP0, X0) ;\ - RND_STEP_RORX_3(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ - RND_STEP_RORX_4(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1, 7) ;\ - RND_STEP_RORX_5(a,b,c,d,e,f,g,h,_i);\ - VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ - RND_STEP_RORX_6(a,b,c,d,e,f,g,h,_i);\ - VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ - RND_STEP_RORX_7(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1,18) ;\ - RND_STEP_RORX_8(a,b,c,d,e,f,g,h,_i);\ -\ - RND_STEP_RORX_1(h,a,b,c,d,e,f,g,_i+1);\ - VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ - RND_STEP_RORX_2(h,a,b,c,d,e,f,g,_i+1);\ - VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ - RND_STEP_RORX_3(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP1) ;\ - RND_STEP_RORX_4(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ - RND_STEP_RORX_5(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ - RND_STEP_RORX_6(h,a,b,c,d,e,f,g,_i+1);\ - VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ - RND_STEP_RORX_7(h,a,b,c,d,e,f,g,_i+1);\ - VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ - RND_STEP_RORX_8(h,a,b,c,d,e,f,g,_i+1);\ -\ - RND_STEP_RORX_1(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ - RND_STEP_RORX_2(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ - RND_STEP_RORX_3(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ - RND_STEP_RORX_4(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_RORX_5(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ - RND_STEP_RORX_6(g,h,a,b,c,d,e,f,_i+2);\ - VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ - RND_STEP_RORX_7(g,h,a,b,c,d,e,f,_i+2);\ - VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ - RND_STEP_RORX_8(g,h,a,b,c,d,e,f,_i+2);\ -\ - RND_STEP_RORX_1(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ - RND_STEP_RORX_2(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ - RND_STEP_RORX_3(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ - RND_STEP_RORX_4(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ - RND_STEP_RORX_5(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_RORX_6(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ - RND_STEP_RORX_7(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ - RND_STEP_RORX_8(f,g,h,a,b,c,d,e,_i+3);\ - VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ - -#endif - - -#define W_K_from_buff\ - __asm__ volatile("vmovdqu %0, %%xmm4\n\t"\ - "vpshufb %%xmm13, %%xmm4, %%xmm4\n\t"\ - :: "m"(sha256->buffer[0]):"%xmm4") ;\ - __asm__ volatile("vmovdqu %0, %%xmm5\n\t"\ - "vpshufb %%xmm13, %%xmm5, %%xmm5\n\t"\ - ::"m"(sha256->buffer[4]):"%xmm5") ;\ - __asm__ volatile("vmovdqu %0, %%xmm6\n\t"\ - "vpshufb %%xmm13, %%xmm6, %%xmm6\n\t"\ - ::"m"(sha256->buffer[8]):"%xmm6") ;\ - __asm__ volatile("vmovdqu %0, %%xmm7\n\t"\ - "vpshufb %%xmm13, %%xmm7, %%xmm7\n\t"\ - ::"m"(sha256->buffer[12]):"%xmm7") ;\ - -#define _SET_W_K_XFER(reg, i)\ - __asm__ volatile("vpaddd %0, %"#reg", %%xmm9"::"m"(K[i]):XMM_REGs) ;\ - __asm__ volatile("vmovdqa %%xmm9, %0":"=m"(W_K[i])::XMM_REGs) ; - -#define SET_W_K_XFER(reg, i) _SET_W_K_XFER(reg, i) - -static const ALIGN32 word64 mSHUF_00BA[] = { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF } ; /* shuffle xBxA -> 00BA */ -static const ALIGN32 word64 mSHUF_DC00[] = { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 } ; /* shuffle xDxC -> DC00 */ -static const ALIGN32 word64 mBYTE_FLIP_MASK[] = { 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - - -#define _Init_Masks(mask1, mask2, mask3)\ -__asm__ volatile("vmovdqu %0, %"#mask1 ::"m"(mBYTE_FLIP_MASK[0])) ;\ -__asm__ volatile("vmovdqu %0, %"#mask2 ::"m"(mSHUF_00BA[0])) ;\ -__asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])) ; - -#define Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)\ - _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) - -#define X0 %xmm4 -#define X1 %xmm5 -#define X2 %xmm6 -#define X3 %xmm7 -#define X_ X0 - -#define XTMP0 %xmm0 -#define XTMP1 %xmm1 -#define XTMP2 %xmm2 -#define XTMP3 %xmm3 -#define XTMP4 %xmm8 -#define XTMP5 %xmm9 -#define XFER %xmm10 - -#define SHUF_00BA %xmm11 /* shuffle xBxA -> 00BA */ -#define SHUF_DC00 %xmm12 /* shuffle xDxC -> DC00 */ -#define BYTE_FLIP_MASK %xmm13 - -#define XMM_REGs /* Registers are saved in Sha256Update/Finel */ - /*"xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13" */ - -static int Transform_AVX1(Sha256* sha256) -{ - - word32 W_K[64] ; /* temp for W+K */ - - #if defined(DEBUG_XMM) - int i, j ; - word32 xmm[29][4*15] ; - #endif - - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ - - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - SET_W_K_XFER(X0, 0) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - SET_W_K_XFER(X1, 4) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; - SET_W_K_XFER(X2, 8) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - SET_W_K_XFER(X3, 12) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; - SET_W_K_XFER(X0, 16) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - SET_W_K_XFER(X1, 20) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; - SET_W_K_XFER(X2, 24) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - SET_W_K_XFER(X3, 28) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; - SET_W_K_XFER(X0, 32) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - SET_W_K_XFER(X1, 36) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; - SET_W_K_XFER(X2, 40) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - SET_W_K_XFER(X3, 44) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; - - SET_W_K_XFER(X0, 48) ; - SET_W_K_XFER(X1, 52) ; - SET_W_K_XFER(X2, 56) ; - SET_W_K_XFER(X3, 60) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - #if defined(DEBUG_XMM) - for(i=0; i<29; i++) { - for(j=0; j<4*14; j+=4) - printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, - xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; - printf("\n") ; - } - - for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; - #endif - - return 0; -} - -#if defined(HAVE_INTEL_RORX) -static int Transform_AVX1_RORX(Sha256* sha256) -{ - - word32 W_K[64] ; /* temp for W+K */ - - #if defined(DEBUG_XMM) - int i, j ; - word32 xmm[29][4*15] ; - #endif - - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ - - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - SET_W_K_XFER(X0, 0) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - SET_W_K_XFER(X1, 4) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; - SET_W_K_XFER(X2, 8) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - SET_W_K_XFER(X3, 12) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; - SET_W_K_XFER(X0, 16) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - SET_W_K_XFER(X1, 20) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; - SET_W_K_XFER(X2, 24) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - SET_W_K_XFER(X3, 28) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; - SET_W_K_XFER(X0, 32) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - SET_W_K_XFER(X1, 36) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; - SET_W_K_XFER(X2, 40) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - SET_W_K_XFER(X3, 44) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; - - SET_W_K_XFER(X0, 48) ; - SET_W_K_XFER(X1, 52) ; - SET_W_K_XFER(X2, 56) ; - SET_W_K_XFER(X3, 60) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - #if defined(DEBUG_XMM) - for(i=0; i<29; i++) { - for(j=0; j<4*14; j+=4) - printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, - xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; - printf("\n") ; - } - - for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; - #endif - - return 0; -} -#endif /* HAVE_INTEL_RORX */ - -#endif /* HAVE_INTEL_AVX1 */ - - -#if defined(HAVE_INTEL_AVX2) - -#define _MOVE_to_REG(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" ":: "m"(mem):YMM_REGs) ; -#define _MOVE_to_MEM(mem, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" : "=m"(mem)::YMM_REGs) ; -#define _BYTE_SWAP(ymm, map) __asm__ volatile("vpshufb %0, %%"#ymm", %%"#ymm"\n\t"\ - :: "m"(map):YMM_REGs) ; -#define _MOVE_128(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"#map", %%"\ - #ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; -#define _MOVE_BYTE(ymm0, ymm1, map) __asm__ volatile("vpshufb %0, %%"#ymm1", %%"\ - #ymm0"\n\t":: "m"(map):YMM_REGs) ; -#define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrld $"#bits", %%"\ - #src", %%"#dest"\n\tvpslld $32-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ - #temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; -#define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrld $"#bits", %%"\ - #src", %%"#dest" ":::YMM_REGs) ; -#define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _ADD(dest, src1, src2) __asm__ volatile("vpaddd %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddd %0, %%"#src1", %%"\ - #dest" "::"m"(mem):YMM_REGs) ; -#define _BLEND(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ - #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; - -#define _EXTRACT_XMM_0(xmm, mem) __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_1(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_2(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_3(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_4(ymm, xmm, mem)\ - __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ;\ - __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_5(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_6(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_7(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; - -#define _SWAP_YMM_HL(ymm) __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ; -#define SWAP_YMM_HL(ymm) _SWAP_YMM_HL(ymm) - -#define MOVE_to_REG(ymm, mem) _MOVE_to_REG(ymm, mem) -#define MOVE_to_MEM(mem, ymm) _MOVE_to_MEM(mem, ymm) -#define BYTE_SWAP(ymm, map) _BYTE_SWAP(ymm, map) -#define MOVE_128(ymm0, ymm1, ymm2, map) _MOVE_128(ymm0, ymm1, ymm2, map) -#define MOVE_BYTE(ymm0, ymm1, map) _MOVE_BYTE(ymm0, ymm1, map) -#define XOR(dest, src1, src2) _XOR(dest, src1, src2) -#define OR(dest, src1, src2) _OR(dest, src1, src2) -#define ADD(dest, src1, src2) _ADD(dest, src1, src2) -#define ADD_MEM(dest, src1, mem) _ADD_MEM(dest, src1, mem) -#define BLEND(map, dest, src1, src2) _BLEND(map, dest, src1, src2) - -#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); -#define AVX2_S(dest, src, bits) S_TMP(dest, src, bits, S_TEMP) -#define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) - -#define GAMMA0(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); \ - XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); XOR(dest, G_TEMP, dest) ; -#define GAMMA0_1(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); -#define GAMMA0_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); \ - XOR(dest, G_TEMP, dest) ; - -#define GAMMA1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); \ - XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); XOR(dest, G_TEMP, dest) ; -#define GAMMA1_1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); -#define GAMMA1_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); \ - XOR(dest, G_TEMP, dest) ; - -#define FEEDBACK1_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP1toW_I_2[0]) ; \ - BLEND(0x0c, W_I_2, YMM_TEMP0, W_I_2) ; -#define FEEDBACK2_to_W_I_2 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ; \ - MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAP2toW_I_2[0]) ; BLEND(0x30, W_I_2, YMM_TEMP0, W_I_2) ; -#define FEEDBACK3_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP3toW_I_2[0]) ; \ - BLEND(0xc0, W_I_2, YMM_TEMP0, W_I_2) ; - -#define FEEDBACK_to_W_I_7 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ;\ - MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAPtoW_I_7[0]) ; BLEND(0x80, W_I_7, YMM_TEMP0, W_I_7) ; - -#undef voitle - -#define W_I_16 ymm8 -#define W_I_15 ymm9 -#define W_I_7 ymm10 -#define W_I_2 ymm11 -#define W_I ymm12 -#define G_TEMP ymm13 -#define S_TEMP ymm14 -#define YMM_TEMP0 ymm15 -#define YMM_TEMP0x xmm15 -#define W_I_TEMP ymm7 -#define W_K_TEMP ymm15 -#define W_K_TEMPx xmm15 - -#define YMM_REGs /* Registers are saved in Sha256Update/Finel */ - /* "%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15"*/ - - -#define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - -#define MOVE_7_to_15(w_i_15, w_i_7)\ - __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - -#define MOVE_I_to_7(w_i_7, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ - -#define MOVE_I_to_2(w_i_2, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ - -#define ROTATE_W(w_i_16, w_i_15, w_i_7, w_i_2, w_i)\ - MOVE_15_to_16(w_i_16, w_i_15, w_i_7) ; \ - MOVE_7_to_15(w_i_15, w_i_7) ; \ - MOVE_I_to_7(w_i_7, w_i) ; \ - MOVE_I_to_2(w_i_2, w_i) ;\ - -#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ;\ - __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[0] += d;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[1] += d;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[2] += d;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[3] += d;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[4] += d;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[5] += d;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[6] += d;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[7] += d;\ -} - -#define _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d[8] ;\ - __asm__ volatile("movl %"#S_0", %0":"=r"(d[0])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d[1])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d[2])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d[3])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d[4])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d[5])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d[6])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d[7])::SSE_REGs) ;\ - printf("S[0..7]=%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);\ - __asm__ volatile("movl %0, %"#S_0::"r"(d[0]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_1::"r"(d[1]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_2::"r"(d[2]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_3::"r"(d[3]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_4::"r"(d[4]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_5::"r"(d[5]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_6::"r"(d[6]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_7::"r"(d[7]):SSE_REGs) ;\ -} - - -#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - -#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - -#define DumS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - - - /* Byte swap Masks to ensure that rest of the words are filled with zero's. */ - static const unsigned long mBYTE_FLIP_MASK_16[] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_15[] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_7 [] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x8080808008090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_2 [] = - { 0x0405060700010203, 0x8080808080808080, 0x8080808080808080, 0x8080808080808080 } ; - - static const unsigned long mMAPtoW_I_7[] = - { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0302010080808080 } ; - static const unsigned long mMAP1toW_I_2[] = - { 0x8080808080808080, 0x0706050403020100, 0x8080808080808080, 0x8080808080808080 } ; - static const unsigned long mMAP2toW_I_2[] = - { 0x8080808080808080, 0x8080808080808080, 0x0f0e0d0c0b0a0908, 0x8080808080808080 } ; - static const unsigned long mMAP3toW_I_2[] = - { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0706050403020100 } ; - -static int Transform_AVX2(Sha256* sha256) -{ - - #ifdef WOLFSSL_SMALL_STACK - word32* W_K; - W_K = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (W_K == NULL) - return MEMORY_E; - #else - word32 W_K[64] ; - #endif - - MOVE_to_REG(W_I_16, sha256->buffer[0]); BYTE_SWAP(W_I_16, mBYTE_FLIP_MASK_16[0]) ; - MOVE_to_REG(W_I_15, sha256->buffer[1]); BYTE_SWAP(W_I_15, mBYTE_FLIP_MASK_15[0]) ; - MOVE_to_REG(W_I, sha256->buffer[8]) ; BYTE_SWAP(W_I, mBYTE_FLIP_MASK_16[0]) ; - MOVE_to_REG(W_I_7, sha256->buffer[16-7]) ; BYTE_SWAP(W_I_7, mBYTE_FLIP_MASK_7[0]) ; - MOVE_to_REG(W_I_2, sha256->buffer[16-2]) ; BYTE_SWAP(W_I_2, mBYTE_FLIP_MASK_2[0]) ; - - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - ADD_MEM(W_K_TEMP, W_I_16, K[0]) ; - MOVE_to_MEM(W_K[0], W_K_TEMP) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,1) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,2) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,3) ; - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,4) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,5) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,6) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,7) ; - - ADD_MEM(YMM_TEMP0, W_I, K[8]) ; - MOVE_to_MEM(W_K[8], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - - MOVE_to_REG(YMM_TEMP0, K[16]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[16], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - - MOVE_to_REG(YMM_TEMP0, K[24]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[24], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - - MOVE_to_REG(YMM_TEMP0, K[32]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[32], YMM_TEMP0) ; - - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - - MOVE_to_REG(YMM_TEMP0, K[40]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[40], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - - MOVE_to_REG(YMM_TEMP0, K[48]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[48], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - MOVE_to_REG(YMM_TEMP0, K[56]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[56], YMM_TEMP0) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - #ifdef WOLFSSL_SMALL_STACK - XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return 0; -} - -#endif /* HAVE_INTEL_AVX2 */ - -#endif /* WOLFSSL_TI_HAHS */ - -#endif /* HAVE_FIPS */ - -#endif /* NO_SHA256 */ - +/* sha256.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 + */ + +/* code submitted by raphael.huck@efixo.com */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include + +#if !defined(NO_SHA256) +#ifdef HAVE_FIPS + +int wc_InitSha256(Sha256* sha) +{ + return InitSha256_fips(sha); +} + + +int wc_Sha256Update(Sha256* sha, const byte* data, word32 len) +{ + return Sha256Update_fips(sha, data, len); +} + + +int wc_Sha256Final(Sha256* sha, byte* out) +{ + return Sha256Final_fips(sha, out); +} + + +int wc_Sha256Hash(const byte* data, word32 len, byte* out) +{ + return Sha256Hash(data, len, out); +} + +#else /* else build without fips */ + +#if !defined(NO_SHA256) && !defined(WOLFSSL_TI_HASH) + /* defined in port/ti/ti_sha256.c */ + +#if !defined (ALIGN32) + #if defined (__GNUC__) + #define ALIGN32 __attribute__ ( (aligned (32))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN32 __declspec (align (32)) + #else + #define ALIGN32 + #endif +#endif + +#ifdef WOLFSSL_PIC32MZ_HASH +#define wc_InitSha256 wc_InitSha256_sw +#define wc_Sha256Update wc_Sha256Update_sw +#define wc_Sha256Final wc_Sha256Final_sw +#endif + +#ifdef HAVE_FIPS + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS +#endif + +#if defined(USE_INTEL_SPEEDUP) +#define HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX2 + +#if defined(DEBUG_XMM) +#include "stdio.h" +#endif + +#endif + +#if defined(HAVE_INTEL_AVX2) +#define HAVE_INTEL_RORX +#endif + + +/***** +Intel AVX1/AVX2 Macro Control Structure + +#define HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX2 + +#define HAVE_INTEL_RORX + + +int InitSha256(Sha256* sha256) { + Save/Recover XMM, YMM + ... +} + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform() ; Function prototype +#else + Transform() { } + int Sha256Final() { + Save/Recover XMM, YMM + ... + } +#endif + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + #if defined(HAVE_INTEL_RORX + #define RND with rorx instuction + #else + #define RND + #endif +#endif + +#if defined(HAVE_INTEL_AVX1) + + #define XMM Instructions/inline asm + + int Transform() { + Stitched Message Sched/Round + } + +#elif defined(HAVE_INTEL_AVX2) + + #define YMM Instructions/inline asm + + int Transform() { + More granural Stitched Message Sched/Round + } + +*/ + + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + +/* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + +#ifndef _MSC_VER + #define cpuid(reg, leaf, sub)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (leaf), "c"(sub)); + + #define XASM_LINK(f) asm(f) +#else + + #include + #define cpuid(a,b) __cpuid((int*)a,b) + + #define XASM_LINK(f) + +#endif /* _MSC_VER */ + +#define EAX 0 +#define EBX 1 +#define ECX 2 +#define EDX 3 + +#define CPUID_AVX1 0x1 +#define CPUID_AVX2 0x2 +#define CPUID_RDRAND 0x4 +#define CPUID_RDSEED 0x8 +#define CPUID_BMI2 0x10 /* MULX, RORX */ + +#define IS_INTEL_AVX1 (cpuid_flags&CPUID_AVX1) +#define IS_INTEL_AVX2 (cpuid_flags&CPUID_AVX2) +#define IS_INTEL_BMI2 (cpuid_flags&CPUID_BMI2) +#define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) +#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) + +static word32 cpuid_check = 0 ; +static word32 cpuid_flags = 0 ; + +static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { + int got_intel_cpu=0; + unsigned int reg[5]; + + reg[4] = '\0' ; + cpuid(reg, 0, 0); + if(memcmp((char *)&(reg[EBX]), "Genu", 4) == 0 && + memcmp((char *)&(reg[EDX]), "ineI", 4) == 0 && + memcmp((char *)&(reg[ECX]), "ntel", 4) == 0) { + got_intel_cpu = 1; + } + if (got_intel_cpu) { + cpuid(reg, leaf, sub); + return((reg[num]>>bit)&0x1) ; + } + return 0 ; +} + +static int set_cpuid_flags(void) { + if(cpuid_check==0) { + if(cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1 ;} + if(cpuid_flag(7, 0, EBX, 5)){ cpuid_flags |= CPUID_AVX2 ; } + if(cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } + if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ; } + if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ; } + cpuid_check = 1 ; + return 0 ; + } + return 1 ; +} + + +/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha512 */ +static int Transform(Sha256* sha256); + +#if defined(HAVE_INTEL_AVX1) +static int Transform_AVX1(Sha256 *sha256) ; +#endif +#if defined(HAVE_INTEL_AVX2) +static int Transform_AVX2(Sha256 *sha256) ; +static int Transform_AVX1_RORX(Sha256 *sha256) ; +#endif + +static int (*Transform_p)(Sha256* sha256) /* = _Transform */; + +#define XTRANSFORM(sha256, B) (*Transform_p)(sha256) + +static void set_Transform(void) { + if(set_cpuid_flags())return ; + +#if defined(HAVE_INTEL_AVX2) + if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ + Transform_p = Transform_AVX1_RORX; return ; + Transform_p = Transform_AVX2 ; + /* for avoiding warning,"not used" */ + } +#endif +#if defined(HAVE_INTEL_AVX1) + Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : Transform) ; return ; +#endif + Transform_p = Transform ; return ; +} + +#else + #if defined(FREESCALE_MMCAU) + #define XTRANSFORM(sha256, B) Transform(sha256, B) + #else + #define XTRANSFORM(sha256, B) Transform(sha256) + #endif +#endif + +/* Dummy for saving MM_REGs on behalf of Transform */ +#if defined(HAVE_INTEL_AVX2)&& !defined(HAVE_INTEL_AVX1) +#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ + "%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15") +#elif defined(HAVE_INTEL_AVX1) +#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ + "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10",\ + "xmm11","xmm12","xmm13","xmm14","xmm15") +#else +#define SAVE_XMM_YMM +#endif + +#ifdef WOLFSSL_PIC32MZ_HASH +#define InitSha256 InitSha256_sw +#define Sha256Update Sha256Update_sw +#define Sha256Final Sha256Final_sw +#endif + +#include +#include + +#ifdef NO_INLINE + #include +#else + #include +#endif + +#ifdef FREESCALE_MMCAU + #include "cau_api.h" +#endif + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +int wc_InitSha256(Sha256* sha256) +{ + #ifdef FREESCALE_MMCAU + cau_sha256_initialize_output(sha256->digest); + #else + sha256->digest[0] = 0x6A09E667L; + sha256->digest[1] = 0xBB67AE85L; + sha256->digest[2] = 0x3C6EF372L; + sha256->digest[3] = 0xA54FF53AL; + sha256->digest[4] = 0x510E527FL; + sha256->digest[5] = 0x9B05688CL; + sha256->digest[6] = 0x1F83D9ABL; + sha256->digest[7] = 0x5BE0CD19L; + #endif + + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + set_Transform() ; /* choose best Transform function under this runtime environment */ +#endif + + return 0; +} + + +#if !defined(FREESCALE_MMCAU) +static const ALIGN32 word32 K[64] = { + 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, + 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, + 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, + 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, + 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L, + 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L, + 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, + 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, + 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L, + 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L, + 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, + 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, + 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L +}; + +#endif + +#if defined(FREESCALE_MMCAU) + +static int Transform(Sha256* sha256, byte* buf) +{ + cau_sha256_hash_n(buf, 1, sha256->digest); + + return 0; +} + +#endif /* FREESCALE_MMCAU */ + +#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) +#define R(x, n) (((x)&0xFFFFFFFFU)>>(n)) + +#define S(x, n) rotrFixed(x, n) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = (h) + Sigma1((e)) + Ch((e), (f), (g)) + K[(i)] + W[(i)]; \ + t1 = Sigma0((a)) + Maj((a), (b), (c)); \ + (d) += t0; \ + (h) = t0 + t1; + +#if !defined(FREESCALE_MMCAU) +static int Transform(Sha256* sha256) +{ + word32 S[8], t0, t1; + int i; + +#ifdef WOLFSSL_SMALL_STACK + word32* W; + + W = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (W == NULL) + return MEMORY_E; +#else + word32 W[64]; +#endif + + /* Copy context->state[] to working vars */ + for (i = 0; i < 8; i++) + S[i] = sha256->digest[i]; + + for (i = 0; i < 16; i++) + W[i] = sha256->buffer[i]; + + for (i = 16; i < 64; i++) + W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; + + for (i = 0; i < 64; i += 8) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + } + + /* Add the working vars back into digest state[] */ + for (i = 0; i < 8; i++) { + sha256->digest[i] += S[i]; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +#endif /* #if !defined(FREESCALE_MMCAU) */ + +static INLINE void AddLength(Sha256* sha256, word32 len) +{ + word32 tmp = sha256->loLen; + if ( (sha256->loLen += len) < tmp) + sha256->hiLen++; /* carry low to high */ +} + +int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) +{ + + /* do block size increments */ + byte* local = (byte*)sha256->buffer; + + SAVE_XMM_YMM ; /* for Intel AVX */ + + while (len) { + word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); + XMEMCPY(&local[sha256->buffLen], data, add); + + sha256->buffLen += add; + data += add; + len -= add; + + if (sha256->buffLen == SHA256_BLOCK_SIZE) { + int ret; + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords(sha256->buffer, sha256->buffer, + SHA256_BLOCK_SIZE); + #endif + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + AddLength(sha256, SHA256_BLOCK_SIZE); + sha256->buffLen = 0; + } + } + + return 0; +} + +int wc_Sha256Final(Sha256* sha256, byte* hash) +{ + byte* local = (byte*)sha256->buffer; + int ret; + + SAVE_XMM_YMM ; /* for Intel AVX */ + + AddLength(sha256, sha256->buffLen); /* before adding pads */ + + local[sha256->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha256->buffLen > SHA256_PAD_SIZE) { + XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen); + sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + #endif + + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + sha256->buffLen = 0; + } + XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen); + + /* put lengths in bits */ + sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) + + (sha256->hiLen << 3); + sha256->loLen = sha256->loLen << 3; + + /* store lengths */ + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); + XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, + sizeof(word32)); + + #if defined(FREESCALE_MMCAU) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + /* Kinetis requires only these bytes reversed */ + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(IS_INTEL_AVX1 || IS_INTEL_AVX2) + #endif + ByteReverseWords(&sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], + &sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], + 2 * sizeof(word32)); + #endif + + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + #if defined(LITTLE_ENDIAN_ORDER) + ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE); + #endif + XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE); + + return wc_InitSha256(sha256); /* reset state */ +} + + + +int wc_Sha256Hash(const byte* data, word32 len, byte* hash) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Sha256* sha256; +#else + Sha256 sha256[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL) + return MEMORY_E; +#endif + + if ((ret = wc_InitSha256(sha256)) != 0) { + WOLFSSL_MSG("InitSha256 failed"); + } + else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { + WOLFSSL_MSG("Sha256Update failed"); + } + else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { + WOLFSSL_MSG("Sha256Final failed"); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#ifdef WOLFSSL_TI_HASH +#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif +int wc_Sha256GetHash(Sha256* sha256, byte* hash) +{ +#if defined(WOLFSS_TI_HASH) + return wc_Sha256GetHash_TI(sha256, hash) ; +#else + int ret ; + Sha256 save = *sha256 ; + ret = wc_Sha256Final(sha256, hash) ; + *sha256 = save ; + return ret ; +#endif +} + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + +#define _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d ;\ + d = sha256->digest[0]; __asm__ volatile("movl %0, %"#S_0::"r"(d):SSE_REGs) ;\ + d = sha256->digest[1]; __asm__ volatile("movl %0, %"#S_1::"r"(d):SSE_REGs) ;\ + d = sha256->digest[2]; __asm__ volatile("movl %0, %"#S_2::"r"(d):SSE_REGs) ;\ + d = sha256->digest[3]; __asm__ volatile("movl %0, %"#S_3::"r"(d):SSE_REGs) ;\ + d = sha256->digest[4]; __asm__ volatile("movl %0, %"#S_4::"r"(d):SSE_REGs) ;\ + d = sha256->digest[5]; __asm__ volatile("movl %0, %"#S_5::"r"(d):SSE_REGs) ;\ + d = sha256->digest[6]; __asm__ volatile("movl %0, %"#S_6::"r"(d):SSE_REGs) ;\ + d = sha256->digest[7]; __asm__ volatile("movl %0, %"#S_7::"r"(d):SSE_REGs) ;\ +} + +#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d ; \ + __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ; sha256->digest[0] += d;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ; sha256->digest[1] += d;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ; sha256->digest[2] += d;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ; sha256->digest[3] += d;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ; sha256->digest[4] += d;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ; sha256->digest[5] += d;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ; sha256->digest[6] += d;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ; sha256->digest[7] += d;\ +} + + +#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + +#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + + + + +#define S_0 %r15d +#define S_1 %r10d +#define S_2 %r11d +#define S_3 %r12d +#define S_4 %r13d +#define S_5 %r14d +#define S_6 %ebx +#define S_7 %r9d + +#define SSE_REGs "%edi", "%ecx", "%esi", "%edx", "%ebx","%r8","%r9","%r10","%r11","%r12","%r13","%r14","%r15" + +#if defined(HAVE_INTEL_RORX) +#define RND_STEP_RORX_1(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("rorx $6, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ + +#define RND_STEP_RORX_2(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("rorx $11, %"#e",%%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ +__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ +__asm__ volatile("rorx $25, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ + +#define RND_STEP_RORX_3(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ +__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ + +#define RND_STEP_RORX_4(a,b,c,d,e,f,g,h,i)\ +/*__asm__ volatile("movl %0, %%edx\n\t"::"m"(w_k):"%edx");*/\ +__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ +__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ +__asm__ volatile("rorx $2, %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ +__asm__ volatile("rorx $13, %"#a", %%edi\n\t":::"%edi",SSE_REGs);/* edi = a>>13 */\ + +#define RND_STEP_RORX_5(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("rorx $22, %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ +__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs);/* edi = (a>>2) ^ (a>>13) */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma0(a) */\ + +#define RND_STEP_RORX_6(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ +__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ +__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c*/\ +__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ + +#define RND_STEP_RORX_7(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ +__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ +__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ + +#define RND_STEP_RORX_8(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ +__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ +__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs); \ +__asm__ volatile("movl %r8d, "#h"\n\t"); + +#endif + +#define RND_STEP_1(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs);\ +__asm__ volatile("roll $26, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ +__asm__ volatile("movl %"#e", %%edi\n\t":::"%edi",SSE_REGs);\ + +#define RND_STEP_2(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("roll $21, %%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ +__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ +__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e */\ +__asm__ volatile("roll $7, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ + +#define RND_STEP_3(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ +__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ + +#define RND_STEP_4(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ +__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ +__asm__ volatile("movl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a */\ +__asm__ volatile("roll $30, %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ +__asm__ volatile("movl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a */\ +__asm__ volatile("roll $19, %%edi\n\t":::"%edi",SSE_REGs); /* edi = a>>13 */\ +__asm__ volatile("movl %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a */\ + +#define RND_STEP_5(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("roll $10, %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ +__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs); /* edi = (a>>2) ^ (a>>13) */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs);/* edx = Sigma0(a) */\ + +#define RND_STEP_6(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ +__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ +__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c */\ +__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ + +#define RND_STEP_7(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ +__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ +__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ + +#define RND_STEP_8(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ +__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ + /* r8b = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */\ +__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs);\ + /* r8b = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */\ +__asm__ volatile("movl %%r8d, %"#h"\n\t":::"%r8", SSE_REGs); \ + /* h = h + w_k + Sigma1(e) + Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ + +#define RND_X(a,b,c,d,e,f,g,h,i) \ + RND_STEP_1(a,b,c,d,e,f,g,h,i); \ + RND_STEP_2(a,b,c,d,e,f,g,h,i); \ + RND_STEP_3(a,b,c,d,e,f,g,h,i); \ + RND_STEP_4(a,b,c,d,e,f,g,h,i); \ + RND_STEP_5(a,b,c,d,e,f,g,h,i); \ + RND_STEP_6(a,b,c,d,e,f,g,h,i); \ + RND_STEP_7(a,b,c,d,e,f,g,h,i); \ + RND_STEP_8(a,b,c,d,e,f,g,h,i); + +#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + + +#define RND_1_3(a,b,c,d,e,f,g,h,i) {\ + RND_STEP_1(a,b,c,d,e,f,g,h,i); \ + RND_STEP_2(a,b,c,d,e,f,g,h,i); \ + RND_STEP_3(a,b,c,d,e,f,g,h,i); \ +} + +#define RND_4_6(a,b,c,d,e,f,g,h,i) {\ + RND_STEP_4(a,b,c,d,e,f,g,h,i); \ + RND_STEP_5(a,b,c,d,e,f,g,h,i); \ + RND_STEP_6(a,b,c,d,e,f,g,h,i); \ +} + +#define RND_7_8(a,b,c,d,e,f,g,h,i) {\ + RND_STEP_7(a,b,c,d,e,f,g,h,i); \ + RND_STEP_8(a,b,c,d,e,f,g,h,i); \ +} + +#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + + +#define RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + +#define RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + +#define RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + +#define FOR(cnt, init, max, inc, loop) \ + __asm__ volatile("movl $"#init", %0\n\t"#loop":"::"m"(cnt):) +#define END(cnt, init, max, inc, loop) \ + __asm__ volatile("addl $"#inc", %0\n\tcmpl $"#max", %0\n\tjle "#loop"\n\t":"=m"(cnt)::) ; + +#endif /* defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) */ + +#if defined(HAVE_INTEL_AVX1) /* inline Assember for Intel AVX1 instructions */ + +#define VPALIGNR(op1,op2,op3,op4) __asm__ volatile("vpalignr $"#op4", %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPADDD(op1,op2,op3) __asm__ volatile("vpaddd %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSRLD(op1,op2,op3) __asm__ volatile("vpsrld $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSRLQ(op1,op2,op3) __asm__ volatile("vpsrlq $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSLLD(op1,op2,op3) __asm__ volatile("vpslld $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPOR(op1,op2,op3) __asm__ volatile("vpor %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPXOR(op1,op2,op3) __asm__ volatile("vpxor %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSHUFD(op1,op2,op3) __asm__ volatile("vpshufd $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSHUFB(op1,op2,op3) __asm__ volatile("vpshufb %"#op3", %"#op2", %"#op1:::XMM_REGs) + +#define MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, SHUF_00BA, SHUF_DC00,\ + a,b,c,d,e,f,g,h,_i)\ + RND_STEP_1(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP0, X3, X2, 4) ;\ + RND_STEP_2(a,b,c,d,e,f,g,h,_i);\ + VPADDD (XTMP0, XTMP0, X0) ;\ + RND_STEP_3(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ + RND_STEP_4(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1, 7) ;\ + RND_STEP_5(a,b,c,d,e,f,g,h,_i);\ + VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ + RND_STEP_6(a,b,c,d,e,f,g,h,_i);\ + VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ + RND_STEP_7(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1,18) ;\ + RND_STEP_8(a,b,c,d,e,f,g,h,_i);\ +\ + RND_STEP_1(h,a,b,c,d,e,f,g,_i+1);\ + VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ + RND_STEP_2(h,a,b,c,d,e,f,g,_i+1);\ + VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ + RND_STEP_3(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP1) ;\ + RND_STEP_4(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ + RND_STEP_5(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ + RND_STEP_6(h,a,b,c,d,e,f,g,_i+1);\ + VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ + RND_STEP_7(h,a,b,c,d,e,f,g,_i+1);\ + VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ + RND_STEP_8(h,a,b,c,d,e,f,g,_i+1);\ +\ + RND_STEP_1(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ + RND_STEP_2(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ + RND_STEP_3(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ + RND_STEP_4(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_5(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ + RND_STEP_6(g,h,a,b,c,d,e,f,_i+2);\ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ + RND_STEP_7(g,h,a,b,c,d,e,f,_i+2);\ + VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ + RND_STEP_8(g,h,a,b,c,d,e,f,_i+2);\ +\ + RND_STEP_1(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ + RND_STEP_2(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ + RND_STEP_3(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ + RND_STEP_4(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ + RND_STEP_5(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_6(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ + RND_STEP_7(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ + RND_STEP_8(f,g,h,a,b,c,d,e,_i+3);\ + VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ + +#if defined(HAVE_INTEL_RORX) + +#define MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, \ + XFER, SHUF_00BA, SHUF_DC00,a,b,c,d,e,f,g,h,_i)\ + RND_STEP_RORX_1(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP0, X3, X2, 4) ;\ + RND_STEP_RORX_2(a,b,c,d,e,f,g,h,_i);\ + VPADDD (XTMP0, XTMP0, X0) ;\ + RND_STEP_RORX_3(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ + RND_STEP_RORX_4(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1, 7) ;\ + RND_STEP_RORX_5(a,b,c,d,e,f,g,h,_i);\ + VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ + RND_STEP_RORX_6(a,b,c,d,e,f,g,h,_i);\ + VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ + RND_STEP_RORX_7(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1,18) ;\ + RND_STEP_RORX_8(a,b,c,d,e,f,g,h,_i);\ +\ + RND_STEP_RORX_1(h,a,b,c,d,e,f,g,_i+1);\ + VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ + RND_STEP_RORX_2(h,a,b,c,d,e,f,g,_i+1);\ + VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ + RND_STEP_RORX_3(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP1) ;\ + RND_STEP_RORX_4(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ + RND_STEP_RORX_5(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ + RND_STEP_RORX_6(h,a,b,c,d,e,f,g,_i+1);\ + VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ + RND_STEP_RORX_7(h,a,b,c,d,e,f,g,_i+1);\ + VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ + RND_STEP_RORX_8(h,a,b,c,d,e,f,g,_i+1);\ +\ + RND_STEP_RORX_1(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ + RND_STEP_RORX_2(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ + RND_STEP_RORX_3(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ + RND_STEP_RORX_4(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_RORX_5(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ + RND_STEP_RORX_6(g,h,a,b,c,d,e,f,_i+2);\ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ + RND_STEP_RORX_7(g,h,a,b,c,d,e,f,_i+2);\ + VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ + RND_STEP_RORX_8(g,h,a,b,c,d,e,f,_i+2);\ +\ + RND_STEP_RORX_1(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ + RND_STEP_RORX_2(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ + RND_STEP_RORX_3(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ + RND_STEP_RORX_4(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ + RND_STEP_RORX_5(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_RORX_6(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ + RND_STEP_RORX_7(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ + RND_STEP_RORX_8(f,g,h,a,b,c,d,e,_i+3);\ + VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ + +#endif + + +#define W_K_from_buff\ + __asm__ volatile("vmovdqu %0, %%xmm4\n\t"\ + "vpshufb %%xmm13, %%xmm4, %%xmm4\n\t"\ + :: "m"(sha256->buffer[0]):"%xmm4") ;\ + __asm__ volatile("vmovdqu %0, %%xmm5\n\t"\ + "vpshufb %%xmm13, %%xmm5, %%xmm5\n\t"\ + ::"m"(sha256->buffer[4]):"%xmm5") ;\ + __asm__ volatile("vmovdqu %0, %%xmm6\n\t"\ + "vpshufb %%xmm13, %%xmm6, %%xmm6\n\t"\ + ::"m"(sha256->buffer[8]):"%xmm6") ;\ + __asm__ volatile("vmovdqu %0, %%xmm7\n\t"\ + "vpshufb %%xmm13, %%xmm7, %%xmm7\n\t"\ + ::"m"(sha256->buffer[12]):"%xmm7") ;\ + +#define _SET_W_K_XFER(reg, i)\ + __asm__ volatile("vpaddd %0, %"#reg", %%xmm9"::"m"(K[i]):XMM_REGs) ;\ + __asm__ volatile("vmovdqa %%xmm9, %0":"=m"(W_K[i])::XMM_REGs) ; + +#define SET_W_K_XFER(reg, i) _SET_W_K_XFER(reg, i) + +static const ALIGN32 word64 mSHUF_00BA[] = { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF } ; /* shuffle xBxA -> 00BA */ +static const ALIGN32 word64 mSHUF_DC00[] = { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 } ; /* shuffle xDxC -> DC00 */ +static const ALIGN32 word64 mBYTE_FLIP_MASK[] = { 0x0405060700010203, 0x0c0d0e0f08090a0b } ; + + +#define _Init_Masks(mask1, mask2, mask3)\ +__asm__ volatile("vmovdqu %0, %"#mask1 ::"m"(mBYTE_FLIP_MASK[0])) ;\ +__asm__ volatile("vmovdqu %0, %"#mask2 ::"m"(mSHUF_00BA[0])) ;\ +__asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])) ; + +#define Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)\ + _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) + +#define X0 %xmm4 +#define X1 %xmm5 +#define X2 %xmm6 +#define X3 %xmm7 +#define X_ X0 + +#define XTMP0 %xmm0 +#define XTMP1 %xmm1 +#define XTMP2 %xmm2 +#define XTMP3 %xmm3 +#define XTMP4 %xmm8 +#define XTMP5 %xmm9 +#define XFER %xmm10 + +#define SHUF_00BA %xmm11 /* shuffle xBxA -> 00BA */ +#define SHUF_DC00 %xmm12 /* shuffle xDxC -> DC00 */ +#define BYTE_FLIP_MASK %xmm13 + +#define XMM_REGs /* Registers are saved in Sha256Update/Finel */ + /*"xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13" */ + +static int Transform_AVX1(Sha256* sha256) +{ + + word32 W_K[64] ; /* temp for W+K */ + + #if defined(DEBUG_XMM) + int i, j ; + word32 xmm[29][4*15] ; + #endif + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; + W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + SET_W_K_XFER(X0, 0) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; + SET_W_K_XFER(X1, 4) ; + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; + SET_W_K_XFER(X2, 8) ; + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + SET_W_K_XFER(X3, 12) ; + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; + SET_W_K_XFER(X0, 16) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + SET_W_K_XFER(X1, 20) ; + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; + SET_W_K_XFER(X2, 24) ; + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + SET_W_K_XFER(X3, 28) ; + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; + SET_W_K_XFER(X0, 32) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + SET_W_K_XFER(X1, 36) ; + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; + SET_W_K_XFER(X2, 40) ; + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + SET_W_K_XFER(X3, 44) ; + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; + + SET_W_K_XFER(X0, 48) ; + SET_W_K_XFER(X1, 52) ; + SET_W_K_XFER(X2, 56) ; + SET_W_K_XFER(X3, 60) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + #if defined(DEBUG_XMM) + for(i=0; i<29; i++) { + for(j=0; j<4*14; j+=4) + printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, + xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; + printf("\n") ; + } + + for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; + #endif + + return 0; +} + +#if defined(HAVE_INTEL_RORX) +static int Transform_AVX1_RORX(Sha256* sha256) +{ + + word32 W_K[64] ; /* temp for W+K */ + + #if defined(DEBUG_XMM) + int i, j ; + word32 xmm[29][4*15] ; + #endif + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; + W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + SET_W_K_XFER(X0, 0) ; + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; + SET_W_K_XFER(X1, 4) ; + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; + SET_W_K_XFER(X2, 8) ; + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + SET_W_K_XFER(X3, 12) ; + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; + SET_W_K_XFER(X0, 16) ; + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + SET_W_K_XFER(X1, 20) ; + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; + SET_W_K_XFER(X2, 24) ; + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + SET_W_K_XFER(X3, 28) ; + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; + SET_W_K_XFER(X0, 32) ; + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + SET_W_K_XFER(X1, 36) ; + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; + SET_W_K_XFER(X2, 40) ; + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + SET_W_K_XFER(X3, 44) ; + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; + + SET_W_K_XFER(X0, 48) ; + SET_W_K_XFER(X1, 52) ; + SET_W_K_XFER(X2, 56) ; + SET_W_K_XFER(X3, 60) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + #if defined(DEBUG_XMM) + for(i=0; i<29; i++) { + for(j=0; j<4*14; j+=4) + printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, + xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; + printf("\n") ; + } + + for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; + #endif + + return 0; +} +#endif /* HAVE_INTEL_RORX */ + +#endif /* HAVE_INTEL_AVX1 */ + + +#if defined(HAVE_INTEL_AVX2) + +#define _MOVE_to_REG(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" ":: "m"(mem):YMM_REGs) ; +#define _MOVE_to_MEM(mem, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" : "=m"(mem)::YMM_REGs) ; +#define _BYTE_SWAP(ymm, map) __asm__ volatile("vpshufb %0, %%"#ymm", %%"#ymm"\n\t"\ + :: "m"(map):YMM_REGs) ; +#define _MOVE_128(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"#map", %%"\ + #ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; +#define _MOVE_BYTE(ymm0, ymm1, map) __asm__ volatile("vpshufb %0, %%"#ymm1", %%"\ + #ymm0"\n\t":: "m"(map):YMM_REGs) ; +#define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrld $"#bits", %%"\ + #src", %%"#dest"\n\tvpslld $32-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ + #temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; +#define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrld $"#bits", %%"\ + #src", %%"#dest" ":::YMM_REGs) ; +#define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _ADD(dest, src1, src2) __asm__ volatile("vpaddd %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddd %0, %%"#src1", %%"\ + #dest" "::"m"(mem):YMM_REGs) ; +#define _BLEND(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ + #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; + +#define _EXTRACT_XMM_0(xmm, mem) __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_1(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_2(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_3(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_4(ymm, xmm, mem)\ + __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ;\ + __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_5(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_6(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_7(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; + +#define _SWAP_YMM_HL(ymm) __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ; +#define SWAP_YMM_HL(ymm) _SWAP_YMM_HL(ymm) + +#define MOVE_to_REG(ymm, mem) _MOVE_to_REG(ymm, mem) +#define MOVE_to_MEM(mem, ymm) _MOVE_to_MEM(mem, ymm) +#define BYTE_SWAP(ymm, map) _BYTE_SWAP(ymm, map) +#define MOVE_128(ymm0, ymm1, ymm2, map) _MOVE_128(ymm0, ymm1, ymm2, map) +#define MOVE_BYTE(ymm0, ymm1, map) _MOVE_BYTE(ymm0, ymm1, map) +#define XOR(dest, src1, src2) _XOR(dest, src1, src2) +#define OR(dest, src1, src2) _OR(dest, src1, src2) +#define ADD(dest, src1, src2) _ADD(dest, src1, src2) +#define ADD_MEM(dest, src1, mem) _ADD_MEM(dest, src1, mem) +#define BLEND(map, dest, src1, src2) _BLEND(map, dest, src1, src2) + +#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); +#define AVX2_S(dest, src, bits) S_TMP(dest, src, bits, S_TEMP) +#define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) + +#define GAMMA0(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); \ + XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); XOR(dest, G_TEMP, dest) ; +#define GAMMA0_1(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); +#define GAMMA0_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); \ + XOR(dest, G_TEMP, dest) ; + +#define GAMMA1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); \ + XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); XOR(dest, G_TEMP, dest) ; +#define GAMMA1_1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); +#define GAMMA1_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); \ + XOR(dest, G_TEMP, dest) ; + +#define FEEDBACK1_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP1toW_I_2[0]) ; \ + BLEND(0x0c, W_I_2, YMM_TEMP0, W_I_2) ; +#define FEEDBACK2_to_W_I_2 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ; \ + MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAP2toW_I_2[0]) ; BLEND(0x30, W_I_2, YMM_TEMP0, W_I_2) ; +#define FEEDBACK3_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP3toW_I_2[0]) ; \ + BLEND(0xc0, W_I_2, YMM_TEMP0, W_I_2) ; + +#define FEEDBACK_to_W_I_7 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ;\ + MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAPtoW_I_7[0]) ; BLEND(0x80, W_I_7, YMM_TEMP0, W_I_7) ; + +#undef voitle + +#define W_I_16 ymm8 +#define W_I_15 ymm9 +#define W_I_7 ymm10 +#define W_I_2 ymm11 +#define W_I ymm12 +#define G_TEMP ymm13 +#define S_TEMP ymm14 +#define YMM_TEMP0 ymm15 +#define YMM_TEMP0x xmm15 +#define W_I_TEMP ymm7 +#define W_K_TEMP ymm15 +#define W_K_TEMPx xmm15 + +#define YMM_REGs /* Registers are saved in Sha256Update/Finel */ + /* "%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15"*/ + + +#define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + +#define MOVE_7_to_15(w_i_15, w_i_7)\ + __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + +#define MOVE_I_to_7(w_i_7, w_i)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ + +#define MOVE_I_to_2(w_i_2, w_i)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ + +#define ROTATE_W(w_i_16, w_i_15, w_i_7, w_i_2, w_i)\ + MOVE_15_to_16(w_i_16, w_i_15, w_i_7) ; \ + MOVE_7_to_15(w_i_15, w_i_7) ; \ + MOVE_I_to_7(w_i_7, w_i) ; \ + MOVE_I_to_2(w_i_2, w_i) ;\ + +#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d ;\ + __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[0] += d;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[1] += d;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[2] += d;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[3] += d;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[4] += d;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[5] += d;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[6] += d;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[7] += d;\ +} + +#define _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d[8] ;\ + __asm__ volatile("movl %"#S_0", %0":"=r"(d[0])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d[1])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d[2])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d[3])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d[4])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d[5])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d[6])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d[7])::SSE_REGs) ;\ + printf("S[0..7]=%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);\ + __asm__ volatile("movl %0, %"#S_0::"r"(d[0]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_1::"r"(d[1]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_2::"r"(d[2]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_3::"r"(d[3]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_4::"r"(d[4]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_5::"r"(d[5]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_6::"r"(d[6]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_7::"r"(d[7]):SSE_REGs) ;\ +} + + +#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + +#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + +#define DumS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + + + /* Byte swap Masks to ensure that rest of the words are filled with zero's. */ + static const unsigned long mBYTE_FLIP_MASK_16[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; + static const unsigned long mBYTE_FLIP_MASK_15[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; + static const unsigned long mBYTE_FLIP_MASK_7 [] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x8080808008090a0b } ; + static const unsigned long mBYTE_FLIP_MASK_2 [] = + { 0x0405060700010203, 0x8080808080808080, 0x8080808080808080, 0x8080808080808080 } ; + + static const unsigned long mMAPtoW_I_7[] = + { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0302010080808080 } ; + static const unsigned long mMAP1toW_I_2[] = + { 0x8080808080808080, 0x0706050403020100, 0x8080808080808080, 0x8080808080808080 } ; + static const unsigned long mMAP2toW_I_2[] = + { 0x8080808080808080, 0x8080808080808080, 0x0f0e0d0c0b0a0908, 0x8080808080808080 } ; + static const unsigned long mMAP3toW_I_2[] = + { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0706050403020100 } ; + +static int Transform_AVX2(Sha256* sha256) +{ + + #ifdef WOLFSSL_SMALL_STACK + word32* W_K; + W_K = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (W_K == NULL) + return MEMORY_E; + #else + word32 W_K[64] ; + #endif + + MOVE_to_REG(W_I_16, sha256->buffer[0]); BYTE_SWAP(W_I_16, mBYTE_FLIP_MASK_16[0]) ; + MOVE_to_REG(W_I_15, sha256->buffer[1]); BYTE_SWAP(W_I_15, mBYTE_FLIP_MASK_15[0]) ; + MOVE_to_REG(W_I, sha256->buffer[8]) ; BYTE_SWAP(W_I, mBYTE_FLIP_MASK_16[0]) ; + MOVE_to_REG(W_I_7, sha256->buffer[16-7]) ; BYTE_SWAP(W_I_7, mBYTE_FLIP_MASK_7[0]) ; + MOVE_to_REG(W_I_2, sha256->buffer[16-2]) ; BYTE_SWAP(W_I_2, mBYTE_FLIP_MASK_2[0]) ; + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + ADD_MEM(W_K_TEMP, W_I_16, K[0]) ; + MOVE_to_MEM(W_K[0], W_K_TEMP) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,1) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,2) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,3) ; + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,4) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,5) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,6) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,7) ; + + ADD_MEM(YMM_TEMP0, W_I, K[8]) ; + MOVE_to_MEM(W_K[8], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; + GAMMA1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; + + MOVE_to_REG(YMM_TEMP0, K[16]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[16], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; + GAMMA1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; + + MOVE_to_REG(YMM_TEMP0, K[24]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[24], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; + GAMMA1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; + + MOVE_to_REG(YMM_TEMP0, K[32]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[32], YMM_TEMP0) ; + + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; + + MOVE_to_REG(YMM_TEMP0, K[40]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[40], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; + + MOVE_to_REG(YMM_TEMP0, K[48]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[48], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + + MOVE_to_REG(YMM_TEMP0, K[56]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[56], YMM_TEMP0) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + #ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return 0; +} + +#endif /* HAVE_INTEL_AVX2 */ + +#endif /* WOLFSSL_TI_HAHS */ + +#endif /* HAVE_FIPS */ + +#endif /* NO_SHA256 */ + diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index 94e4466f7..f7d7c150a 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/wolfssl/wolfcrypt/md5.h @@ -1,100 +1,100 @@ -/* md5.h - * - * 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 - */ - -#ifndef WOLF_CRYPT_MD5_H -#define WOLF_CRYPT_MD5_H - -#include - -#ifndef NO_MD5 - -#ifdef HAVE_FIPS - #define wc_InitMd5 InitMd5 - #define wc_Md5Update Md5Update - #define wc_Md5Final Md5Final - #define wc_Md5Hash Md5Hash -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -/* in bytes */ -enum { -#ifdef STM32F2_HASH - MD5_REG_SIZE = 4, /* STM32 register size, bytes */ -#endif - MD5 = 0, /* hash type unique */ - MD5_BLOCK_SIZE = 64, - MD5_DIGEST_SIZE = 16, - MD5_PAD_SIZE = 56 -}; - -#if defined(WOLFSSL_PIC32MZ_HASH) -#include "port/pic32/pic32mz-crypt.h" -#endif - -#ifdef TI_HASH_TEST -#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif - - -#ifndef WOLFSSL_TI_HASH - -/* MD5 digest */ -typedef struct Md5 { - word32 buffLen; /* in bytes */ - word32 loLen; /* length in bytes */ - word32 hiLen; /* length in bytes */ - word32 buffer[MD5_BLOCK_SIZE / sizeof(word32)]; - #if !defined(WOLFSSL_PIC32MZ_HASH) - word32 digest[MD5_DIGEST_SIZE / sizeof(word32)]; - #else - word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; - pic32mz_desc desc ; /* Crypt Engine descripter */ - #endif - -#ifdef TI_HASH_TEST - wolfssl_TI_Hash ti ; -#endif - -} Md5; - -#if defined(TI_HASH_TEST) -void wc_Md5GetHash_ti(Md5* md5, byte* hash) ; -#endif - -#else /* WOLFSSL_TI_HASH */ - #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif - -WOLFSSL_API void wc_InitMd5(Md5*); -WOLFSSL_API void wc_Md5Update(Md5*, const byte*, word32); -WOLFSSL_API void wc_Md5Final(Md5*, byte*); -WOLFSSL_API int wc_Md5Hash(const byte*, word32, byte*); -WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); - -#ifdef __cplusplus - } /* extern "C" */ -#endif - -#endif /* NO_MD5 */ -#endif /* WOLF_CRYPT_MD5_H */ +/* md5.h + * + * 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 + */ + +#ifndef WOLF_CRYPT_MD5_H +#define WOLF_CRYPT_MD5_H + +#include + +#ifndef NO_MD5 + +#ifdef HAVE_FIPS + #define wc_InitMd5 InitMd5 + #define wc_Md5Update Md5Update + #define wc_Md5Final Md5Final + #define wc_Md5Hash Md5Hash +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* in bytes */ +enum { +#ifdef STM32F2_HASH + MD5_REG_SIZE = 4, /* STM32 register size, bytes */ +#endif + MD5 = 0, /* hash type unique */ + MD5_BLOCK_SIZE = 64, + MD5_DIGEST_SIZE = 16, + MD5_PAD_SIZE = 56 +}; + +#if defined(WOLFSSL_PIC32MZ_HASH) +#include "port/pic32/pic32mz-crypt.h" +#endif + +#ifdef TI_HASH_TEST +#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + + +#ifndef WOLFSSL_TI_HASH + +/* MD5 digest */ +typedef struct Md5 { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[MD5_BLOCK_SIZE / sizeof(word32)]; + #if !defined(WOLFSSL_PIC32MZ_HASH) + word32 digest[MD5_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; + pic32mz_desc desc ; /* Crypt Engine descripter */ + #endif + +#ifdef TI_HASH_TEST + wolfssl_TI_Hash ti ; +#endif + +} Md5; + +#if defined(TI_HASH_TEST) +void wc_Md5GetHash_ti(Md5* md5, byte* hash) ; +#endif + +#else /* WOLFSSL_TI_HASH */ + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + +WOLFSSL_API void wc_InitMd5(Md5*); +WOLFSSL_API void wc_Md5Update(Md5*, const byte*, word32); +WOLFSSL_API void wc_Md5Final(Md5*, byte*); +WOLFSSL_API int wc_Md5Hash(const byte*, word32, byte*); +WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_MD5 */ +#endif /* WOLF_CRYPT_MD5_H */ diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index 46dce03d0..b5ff4908d 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/wolfssl/wolfcrypt/sha.h @@ -1,88 +1,88 @@ -/* sha.h - * - * 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 - */ - -#ifndef WOLF_CRYPT_SHA_H -#define WOLF_CRYPT_SHA_H - -#include - -#ifndef NO_SHA - -#ifdef HAVE_FIPS -/* for fips @wc_fips */ -#include -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -#ifndef HAVE_FIPS /* avoid redefining structs */ -/* in bytes */ -enum { -#ifdef STM32F2_HASH - SHA_REG_SIZE = 4, /* STM32 register size, bytes */ -#endif - SHA = 1, /* hash type unique */ - SHA_BLOCK_SIZE = 64, - SHA_DIGEST_SIZE = 20, - SHA_PAD_SIZE = 56 -}; - -#ifdef WOLFSSL_PIC32MZ_HASH -#include "port/pic32/pic32mz-crypt.h" -#endif - -#ifndef WOLFSSL_TI_HASH - -/* Sha digest */ -typedef struct Sha { - word32 buffLen; /* in bytes */ - word32 loLen; /* length in bytes */ - word32 hiLen; /* length in bytes */ - word32 buffer[SHA_BLOCK_SIZE / sizeof(word32)]; - #ifndef WOLFSSL_PIC32MZ_HASH - word32 digest[SHA_DIGEST_SIZE / sizeof(word32)]; - #else - word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; - pic32mz_desc desc; /* Crypt Engine descripter */ - #endif -} Sha; - -#else /* WOLFSSL_TI_HASH */ - #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif - -#endif /* HAVE_FIPS */ - -WOLFSSL_API int wc_InitSha(Sha*); -WOLFSSL_API int wc_ShaUpdate(Sha*, const byte*, word32); -WOLFSSL_API int wc_ShaFinal(Sha*, byte*); -WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); -WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); - -#ifdef __cplusplus - } /* extern "C" */ -#endif - -#endif /* NO_SHA */ -#endif /* WOLF_CRYPT_SHA_H */ - +/* sha.h + * + * 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 + */ + +#ifndef WOLF_CRYPT_SHA_H +#define WOLF_CRYPT_SHA_H + +#include + +#ifndef NO_SHA + +#ifdef HAVE_FIPS +/* for fips @wc_fips */ +#include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefining structs */ +/* in bytes */ +enum { +#ifdef STM32F2_HASH + SHA_REG_SIZE = 4, /* STM32 register size, bytes */ +#endif + SHA = 1, /* hash type unique */ + SHA_BLOCK_SIZE = 64, + SHA_DIGEST_SIZE = 20, + SHA_PAD_SIZE = 56 +}; + +#ifdef WOLFSSL_PIC32MZ_HASH +#include "port/pic32/pic32mz-crypt.h" +#endif + +#ifndef WOLFSSL_TI_HASH + +/* Sha digest */ +typedef struct Sha { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[SHA_BLOCK_SIZE / sizeof(word32)]; + #ifndef WOLFSSL_PIC32MZ_HASH + word32 digest[SHA_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; + pic32mz_desc desc; /* Crypt Engine descripter */ + #endif +} Sha; + +#else /* WOLFSSL_TI_HASH */ + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha(Sha*); +WOLFSSL_API int wc_ShaUpdate(Sha*, const byte*, word32); +WOLFSSL_API int wc_ShaFinal(Sha*, byte*); +WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); +WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA */ +#endif /* WOLF_CRYPT_SHA_H */ + diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 86616e320..d022d3ac5 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -1,86 +1,86 @@ -/* sha256.h - * - * 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 - */ - -/* code submitted by raphael.huck@efixo.com */ - -#ifndef WOLF_CRYPT_SHA256_H -#define WOLF_CRYPT_SHA256_H - -#include - -#ifndef NO_SHA256 - -#ifdef HAVE_FIPS - /* for fips @wc_fips */ - #include -#endif - - -#ifdef __cplusplus - extern "C" { -#endif - -#ifndef HAVE_FIPS /* avoid redefinition of structs */ -#ifdef WOLFSSL_PIC32MZ_HASH - #include "port/pic32/pic32mz-crypt.h" -#endif - -/* in bytes */ -enum { - SHA256 = 2, /* hash type unique */ - SHA256_BLOCK_SIZE = 64, - SHA256_DIGEST_SIZE = 32, - SHA256_PAD_SIZE = 56 -}; - -#ifndef WOLFSSL_TI_HASH - -/* Sha256 digest */ -typedef struct Sha256 { - word32 buffLen; /* in bytes */ - word32 loLen; /* length in bytes */ - word32 hiLen; /* length in bytes */ - word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)]; - word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)]; - #ifdef WOLFSSL_PIC32MZ_HASH - pic32mz_desc desc ; /* Crypt Engine descripter */ - #endif -} Sha256; - -#else /* WOLFSSL_TI_HASH */ - #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif - -#endif /* HAVE_FIPS */ - -WOLFSSL_API int wc_InitSha256(Sha256*); -WOLFSSL_API int wc_Sha256Update(Sha256*, const byte*, word32); -WOLFSSL_API int wc_Sha256Final(Sha256*, byte*); -WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); -WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); - -#ifdef __cplusplus - } /* extern "C" */ -#endif - -#endif /* NO_SHA256 */ -#endif /* WOLF_CRYPT_SHA256_H */ - +/* sha256.h + * + * 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 + */ + +/* code submitted by raphael.huck@efixo.com */ + +#ifndef WOLF_CRYPT_SHA256_H +#define WOLF_CRYPT_SHA256_H + +#include + +#ifndef NO_SHA256 + +#ifdef HAVE_FIPS + /* for fips @wc_fips */ + #include +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefinition of structs */ +#ifdef WOLFSSL_PIC32MZ_HASH + #include "port/pic32/pic32mz-crypt.h" +#endif + +/* in bytes */ +enum { + SHA256 = 2, /* hash type unique */ + SHA256_BLOCK_SIZE = 64, + SHA256_DIGEST_SIZE = 32, + SHA256_PAD_SIZE = 56 +}; + +#ifndef WOLFSSL_TI_HASH + +/* Sha256 digest */ +typedef struct Sha256 { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)]; + word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)]; + #ifdef WOLFSSL_PIC32MZ_HASH + pic32mz_desc desc ; /* Crypt Engine descripter */ + #endif +} Sha256; + +#else /* WOLFSSL_TI_HASH */ + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha256(Sha256*); +WOLFSSL_API int wc_Sha256Update(Sha256*, const byte*, word32); +WOLFSSL_API int wc_Sha256Final(Sha256*, byte*); +WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); +WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA256 */ +#endif /* WOLF_CRYPT_SHA256_H */ + From d24c7f070cb1c39764aa6599b67f99ad0c719837 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Thu, 21 May 2015 18:12:43 +0900 Subject: [PATCH 04/21] files cleaned --- src/include.am | 5 +-- wolfcrypt/src/md5.c | 25 ----------- wolfcrypt/src/sha.c | 7 ---- wolfcrypt/src/sha256.c | 7 ---- wolfssl/wolfcrypt/port/ti/ti-ccm.h | 40 ++++++++++++++++++ wolfssl/wolfcrypt/port/ti/ti-hash.h | 64 +++++++++++++++++++++++++++++ 6 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 wolfssl/wolfcrypt/port/ti/ti-ccm.h create mode 100644 wolfssl/wolfcrypt/port/ti/ti-hash.h diff --git a/src/include.am b/src/include.am index 1dcf24a2b..f65331b4c 100644 --- a/src/include.am +++ b/src/include.am @@ -74,7 +74,8 @@ endif src_libwolfssl_la_SOURCES += \ wolfcrypt/src/logging.c \ wolfcrypt/src/wc_port.c \ - wolfcrypt/src/error.c + wolfcrypt/src/error.c\ + wolfcrypt/src/port/ti/ti-hash.c if BUILD_MEMORY src_libwolfssl_la_SOURCES += wolfcrypt/src/memory.c @@ -191,8 +192,6 @@ if BUILD_PKCS7 src_libwolfssl_la_SOURCES += wolfcrypt/src/pkcs7.c endif -src_libwolfssl_la_SOURCES += wolfcrypt/src/port/ti/ti-hash.c - # ssl files src_libwolfssl_la_SOURCES += \ src/internal.c \ diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index 6c2e45d9f..64c2ff15a 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -180,12 +180,6 @@ #endif /* WOLFSSL_HAVE_MIN */ -#ifdef TI_HASH_TEST -void wc_InitMd5_ti(Md5* md5) ; -void wc_Md5Update_ti(Md5* md5, const byte* data, word32 len) ; -void wc_Md5Final_ti(Md5* md5, byte* hash) ; -#endif - void wc_InitMd5(Md5* md5) { md5->digest[0] = 0x67452301L; @@ -196,10 +190,6 @@ void wc_InitMd5(Md5* md5) md5->buffLen = 0; md5->loLen = 0; md5->hiLen = 0; - -#ifdef TI_HASH_TEST - wc_InitMd5_ti(md5) ; -#endif } #ifndef FREESCALE_MMCAU @@ -328,10 +318,6 @@ void wc_Md5Update(Md5* md5, const byte* data, word32 len) md5->buffLen = 0; } } -#ifdef TI_HASH_TEST - wc_Md5Update_ti(md5, data, len) ; -#endif - } @@ -376,10 +362,6 @@ void wc_Md5Final(Md5* md5, byte* hash) XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); wc_InitMd5(md5); /* reset state */ - -#ifdef TI_HASH_TEST - wc_Md5Final_ti(md5, hash) ; -#endif } #endif /* STM32F2_HASH */ @@ -410,17 +392,10 @@ int wc_Md5Hash(const byte* data, word32 len, byte* hash) return 0; } -#if defined(WOLFSSL_TI_HASH)||defined(TI_HASH_TEST) -#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif void wc_Md5GetHash(Md5* md5, byte* hash) { -#if defined(WOLFSSL_TI_HASH) || defined(TI_HASH_TEST) - wc_Md5GetHash_ti(md5, hash) ; -#else Md5 save = *md5 ; wc_Md5Final(md5, hash) ; *md5 = save ; -#endif } #endif /* NO_MD5 */ diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index be2106cbd..d1b2dc572 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -452,20 +452,13 @@ int wc_ShaHash(const byte* data, word32 len, byte* hash) } -#ifdef WOLFSSL_TI_HASH -#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif int wc_ShaGetHash(Sha* sha, byte* hash) { -#if defined(WOLFSS_TI_HASH) - wc_ShaGetHash_TI(sha, hash) ; -#else int ret ; Sha save = *sha ; ret = wc_ShaFinal(sha, hash) ; *sha = save ; return ret ; -#endif } #endif /* HAVE_FIPS */ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 90f99a35b..93e94666d 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -576,20 +576,13 @@ int wc_Sha256Hash(const byte* data, word32 len, byte* hash) return ret; } -#ifdef WOLFSSL_TI_HASH -#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif int wc_Sha256GetHash(Sha256* sha256, byte* hash) { -#if defined(WOLFSS_TI_HASH) - return wc_Sha256GetHash_TI(sha256, hash) ; -#else int ret ; Sha256 save = *sha256 ; ret = wc_Sha256Final(sha256, hash) ; *sha256 = save ; return ret ; -#endif } #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) diff --git a/wolfssl/wolfcrypt/port/ti/ti-ccm.h b/wolfssl/wolfcrypt/port/ti/ti-ccm.h new file mode 100644 index 000000000..f0fb24799 --- /dev/null +++ b/wolfssl/wolfcrypt/port/ti/ti-ccm.h @@ -0,0 +1,40 @@ +/* port/ti/ti_ccm.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 + +#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) + +bool wolfSSL_TI_CCMInit(void) ; + +#ifndef SINGLE_THREADED +void wolfSSL_TI_lockCCM() ; +void wolfSSL_TI_unlockCCM() ; +#else +#define wolfSSL_TI_lockCCM() +#define wolfSSL_TI_unlockCCM() +#endif + +#endif diff --git a/wolfssl/wolfcrypt/port/ti/ti-hash.h b/wolfssl/wolfcrypt/port/ti/ti-hash.h new file mode 100644 index 000000000..505ccc498 --- /dev/null +++ b/wolfssl/wolfcrypt/port/ti/ti-hash.h @@ -0,0 +1,64 @@ +/* port/ti/ti-hash.h + * + * 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 + */ + +#ifndef WOLF_CRYPT_TI_HASH_H +#define WOLF_CRYPT_TI_HASH_H + +#include + +#ifndef WOLFSSL_TI_INITBUFF +#define WOLFSSL_TI_INITBUFF 64 +#endif + +#define WOLFSSL_MAX_HASH_SIZE 64 + +typedef struct { + byte *msg ; + word32 used ; + word32 len ; + byte hash[WOLFSSL_MAX_HASH_SIZE] ; +} wolfssl_TI_Hash ; + + +#ifndef TI_HASH_TEST +#if !defined(NO_MD5) +typedef wolfssl_TI_Hash Md5 ; + +#endif +#if !defined(NO_SHA) +typedef wolfssl_TI_Hash Sha ; +#endif +#if !defined(NO_SHA256) +typedef wolfssl_TI_Hash Sha256 ; +#endif + +#if defined(HAVE_SHA224) +typedef wolfssl_TI_Hash Sha224 ; +#define SHA224_DIGEST_SIZE 28 + +WOLFSSL_API int wc_InitSha224(Sha224* sha224) ; +WOLFSSL_API int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) ; +WOLFSSL_API int wc_Sha224Final(Sha224* sha224, byte* hash) ; +WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) ; + +#endif +#endif +#endif /* WOLF_CRYPT_TI_HASH_H */ From ce8b4e0cdc2022fac9c1118709aa0e73a1c0cedb Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Thu, 21 May 2015 18:26:35 +0900 Subject: [PATCH 05/21] Added ti-hash.c --- wolfcrypt/src/md5.c | 2 +- wolfcrypt/src/port/ti/ti-hash.c | 128 ++++++++++++-------------------- wolfcrypt/src/sha.c | 2 +- wolfcrypt/src/sha256.c | 2 +- 4 files changed, 50 insertions(+), 84 deletions(-) diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index 64c2ff15a..d5bb17b63 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -166,7 +166,7 @@ #elif defined(WOLFSSL_IT_HASH) - /* defined in port/ti_md5.c */ + /* defined in port/ti_hash.c */ #else /* CTaoCrypt software implementation */ diff --git a/wolfcrypt/src/port/ti/ti-hash.c b/wolfcrypt/src/port/ti/ti-hash.c index 7647dcdb4..4b7f49a20 100644 --- a/wolfcrypt/src/port/ti/ti-hash.c +++ b/wolfcrypt/src/port/ti/ti-hash.c @@ -20,9 +20,15 @@ */ +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + #include -#if defined(WOLFSSL_TI_HASH)||defined(TI_HASH_TEST) +#if defined(WOLFSSL_TI_HASH) #ifdef __cplusplus extern "C" { @@ -39,7 +45,7 @@ #include #include -#if !defined(TI_HASH_TEST) +#ifndef TI_DUMMY_BUILD #include "inc/hw_memmap.h" #include "inc/hw_shamd5.h" #include "inc/hw_ints.h" @@ -47,6 +53,11 @@ #include "driverlib/sysctl.h" #include "driverlib/rom_map.h" #include "driverlib/rom.h" +#else +#define SHAMD5_ALGO_MD5 1 +#define SHAMD5_ALGO_SHA1 2 +#define SHAMD5_ALGO_SHA256 3 +bool wolfSSL_TI_CCMInit(void) { return true ; } #endif static int hashInit(wolfssl_TI_Hash *hash) { @@ -76,50 +87,33 @@ static int hashUpdate(wolfssl_TI_Hash *hash, const byte* data, word32 len) return 0 ; } -static int hashFinal(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) +static int hashGetHash(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) { - #if !defined(TI_HASH_TEST) uint32_t h[16] ; - +#ifndef TI_DUMMY_BUILD wolfSSL_TI_lockCCM() ; ROM_SHAMD5Reset(SHAMD5_BASE); ROM_SHAMD5ConfigSet(SHAMD5_BASE, algo); ROM_SHAMD5DataProcess(SHAMD5_BASE, (uint32_t *)hash->msg, hash->used, h); - XMEMCPY(result, h, hsize) ; wolfSSL_TI_unlockCCM() ; - #else - (void) result ; +#else + (void) hash ; (void) algo ; - (void) hsize ; - #endif +#endif + XMEMCPY(result, h, hsize) ; + + return 0 ; +} + +static int hashFinal(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) +{ + hashGetHash(hash, result, algo, hsize) ; XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); hashInit(hash) ; return 0 ; } -static int hashGetHash(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) -{ - #if !defined(TI_HASH_TEST) - uint32_t h[16] ; - - wolfSSL_TI_lockCCM() ; - ROM_SHAMD5Reset(SHAMD5_BASE); - ROM_SHAMD5ConfigSet(SHAMD5_BASE, algo); - ROM_SHAMD5DataProcess(SHAMD5_BASE, - (uint32_t *)hash->msg, hash->used, h); - XMEMCPY(result, h, hsize) ; - wolfSSL_TI_unlockCCM() ; - #else - (void) hash ; - (void) result ; - (void) algo ; - (void) hsize ; - #endif - return 0 ; -} - -#ifndef TI_HASH_TEST static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word32 hsize) { int ret = 0; @@ -149,82 +143,39 @@ static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word3 return ret; } -#endif #if !defined(NO_MD5) - -#ifdef TI_HASH_TEST -#define SHAMD5_ALGO_MD5 1 -void wc_InitMd5_ti(Md5* md5) ; -void wc_Md5Update_ti(Md5* md5, const byte* data, word32 len); -void wc_Md5Final_ti(Md5* md5, byte* hash); -bool wolfSSL_TI_CCMInit(void) ; -bool wolfSSL_TI_CCMInit(void) { return true ; } -#endif - -#ifdef TI_HASH_TEST -void wc_InitMd5_ti(Md5* md5) -#else -void wc_InitMd5(Md5* md5) -#endif +WOLFSSL_API void wc_InitMd5(Md5* md5) { if (md5 == NULL) return ; if(!wolfSSL_TI_CCMInit())return ; - #ifdef TI_HASH_TEST - hashInit(&(md5->ti)) ; - #else hashInit((wolfssl_TI_Hash *)md5) ; - #endif } -#ifdef TI_HASH_TEST -void wc_Md5Update_ti(Md5* md5, const byte* data, word32 len) -#else -void wc_Md5Update(Md5* md5, const byte* data, word32 len) -#endif +WOLFSSL_API void wc_Md5Update(Md5* md5, const byte* data, word32 len) { - #ifdef TI_HASH_TEST - hashUpdate(&(md5->ti), data, len) ; - #else hashUpdate((wolfssl_TI_Hash *)md5, data, len) ; - #endif } -#ifdef TI_HASH_TEST -void wc_Md5Final_ti(Md5* md5, byte* hash) -#else -void wc_Md5Final(Md5* md5, byte* hash) -#endif +WOLFSSL_API void wc_Md5Final(Md5* md5, byte* hash) { - #ifdef TI_HASH_TEST - hashFinal(&(md5->ti), hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; - #else hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; - #endif } - -void wc_Md5GetHash_ti(Md5* md5, byte* hash) +WOLFSSL_API void wc_Md5GetHash(Md5* md5, byte* hash) { - hashGetHash(&(md5->ti), hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; - #ifdef TI_HASH_TEST - wc_Md5Final(md5, hash) ; - #endif + hashGetHash(md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; } -#ifndef TI_HASH_TEST WOLFSSL_API int wc_Md5Hash(const byte*data, word32 len, byte*hash) { return hashHash(data, len, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; } -#endif #endif /* NO_MD5 */ -#ifndef TI_HASH_TEST #if !defined(NO_SHA) - WOLFSSL_API int wc_InitSha(Sha* sha) { if (sha == NULL) @@ -242,6 +193,12 @@ WOLFSSL_API int wc_ShaFinal(Sha* sha, byte* hash) { return hashFinal((wolfssl_TI_Hash *)sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; } + +WOLFSSL_API int wc_ShaGetHash(Sha* sha, byte* hash) +{ + return hashGetHash(sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; +} + WOLFSSL_API int wc_ShaHash(const byte*data, word32 len, byte*hash) { return hashHash(data, len, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; @@ -268,6 +225,11 @@ WOLFSSL_API int wc_Sha224Final(Sha224* sha224, byte* hash) return hashFinal((wolfssl_TI_Hash *)sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; } +WOLFSSL_API int wc_Sha224GetHash(Sha224* sha224, byte* hash) +{ + return hashGetHash(sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; +} + WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) { return hashHash(data, len, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; @@ -294,11 +256,15 @@ WOLFSSL_API int wc_Sha256Final(Sha256* sha256, byte* hash) return hashFinal((wolfssl_TI_Hash *)sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; } +WOLFSSL_API int wc_Sha256GetHash(Sha256* sha256, byte* hash) +{ + return hashGetHash(sha256, hash, SHAMD5_ALGO_SHA256, SHA_DIGEST_SIZE) ; +} + WOLFSSL_API int wc_Sha256Hash(const byte* data, word32 len, byte*hash) { return hashHash(data, len, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; } #endif -#endif /* TI_HASH_TEST */ #endif diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index d1b2dc572..78f2640f0 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -198,7 +198,7 @@ int wc_ShaFinal(Sha* sha, byte* hash) #elif defined(WOLFSSL_TI_HASH) - /* defined in port/ti/ti_sha.c */ + /* defined in port/ti/ti_hash.c */ #else /* wc_ software implementation */ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 93e94666d..a204637f4 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -57,7 +57,7 @@ int wc_Sha256Hash(const byte* data, word32 len, byte* out) #else /* else build without fips */ #if !defined(NO_SHA256) && !defined(WOLFSSL_TI_HASH) - /* defined in port/ti/ti_sha256.c */ + /* defined in port/ti/ti_hash.c */ #if !defined (ALIGN32) #if defined (__GNUC__) From 5bcce85de41d499fa6af0c9c921d692b36fdc409 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Thu, 21 May 2015 18:34:51 +0900 Subject: [PATCH 06/21] md5.h cleaned --- wolfssl/wolfcrypt/md5.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index f7d7c150a..b1f775c4c 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/wolfssl/wolfcrypt/md5.h @@ -71,17 +71,8 @@ typedef struct Md5 { word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; pic32mz_desc desc ; /* Crypt Engine descripter */ #endif - -#ifdef TI_HASH_TEST - wolfssl_TI_Hash ti ; -#endif - } Md5; -#if defined(TI_HASH_TEST) -void wc_Md5GetHash_ti(Md5* md5, byte* hash) ; -#endif - #else /* WOLFSSL_TI_HASH */ #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" #endif From aaa1fe813a8ce8f9ebcbf55ef719d462672a6d80 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Fri, 22 May 2015 09:55:49 +0900 Subject: [PATCH 07/21] Added aes.c/des3.c --- wolfcrypt/benchmark/benchmark.c | 6 ++--- wolfcrypt/src/aes.c | 40 ++++++++++++++++++++++++++------- wolfcrypt/src/des3.c | 3 +++ wolfssl/wolfcrypt/aes.h | 3 +++ 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 9c27980e7..bd5fd27f5 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -1846,9 +1846,9 @@ void bench_ed25519KeySign(void) return ( ns / CLOCK * 2.0); } -#elif defined(WOLFSSL_IAR_ARM) || defined (WOLFSSL_MDK_ARM) - #warning "Write your current_time()" - double current_time(int reset) { return 0.0 ; } +#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) + extern double current_time(int reset); + #elif defined FREERTOS diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 896ee147d..9e80e9839 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -230,6 +230,10 @@ void wc_AesFreeCavium(Aes* aes) word32 length); static int wc_AesCaviumCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 length); +#elif defined(WOLFSSL_TI_CRYPT) + + /* defined in port/ti_aes.c */ + #else /* using CTaoCrypt software AES implementation */ #define NEED_AES_TABLES @@ -1505,6 +1509,11 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { return wc_AesSetKey(aes, userKey, keylen, iv, dir); } + +#elif defined(WOLFSSL_TI_CRYPT) + + /* defined in port/ti_md5.c */ + #else static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) @@ -1775,17 +1784,21 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, #elif defined(WOLFSSL_PIC32MZ_CRYPT) #error "PIC32MZ doesn't yet support AES direct" + #elif defined(WOLFSSL_TI_CRYPT) + + /* defined in port/ti_aes.c */ + #else /* Allow direct access to one block encrypt */ void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) { - return wc_AesEncrypt(aes, in, out); + wc_AesEncrypt(aes, in, out); } /* Allow direct access to one block decrypt */ void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) { - return wc_AesDecrypt(aes, in, out); + wc_AesDecrypt(aes, in, out); } #endif /* FREESCALE_MMCAU, AES direct block */ @@ -2309,6 +2322,10 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, return 0 ; } +#elif defined(WOLFSSL_TI_CRYPT) + + /* defined in port/ti_aes.c */ + #else int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { @@ -2589,7 +2606,10 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, #elif defined(FREESCALE_MMCAU) #error "Freescale mmCAU doesn't currently support AES-CTR mode" - + + #elif defined(WOLFSSL_TI_CRYPT) + /* defined in port/ti/ti_aes.c */ + #else /* Increment AES counter */ static INLINE void IncrementAesCounter(byte* inOutCtr) @@ -2671,7 +2691,7 @@ enum { CTR_SZ = 4 }; - +#if !defined(WOLFSSL_TI_CRYPT) static INLINE void InitGcmCounter(byte* inOutCtr) { inOutCtr[AES_BLOCK_SIZE - 4] = 0; @@ -2776,6 +2796,10 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) if (ret == 0) { #ifdef FREESCALE_MMCAU cau_aes_encrypt(iv, rk, aes->rounds, aes->H); + + #elif defined(WOLFSSL_TI_CRYPT) + /* defined in port/ti/ti_aes.c */ + #else wc_AesEncrypt(aes, iv, aes->H); #endif @@ -3289,8 +3313,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, } #endif /* end GCM_WORD32 */ - - + int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, byte* authTag, word32 authTagSz, @@ -3445,8 +3468,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, } return 0; } - - +#endif WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) { @@ -3478,6 +3500,7 @@ WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, #endif +#if !defined(WOLFSSL_TI_CRYPT) void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) { byte nonce[AES_BLOCK_SIZE]; @@ -3758,6 +3781,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, return result; } +#endif /* WOLFCRYPT_TI_CRYPT */ #endif /* HAVE_AESCCM */ diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index 5edb7f79e..62e0ef12c 100644 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -944,6 +944,9 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); return 0; } +#elif defined(WOLFSSL_TI_CRYPT) + /* defined in port/ti/ti-des3.c */ + #else /* CTaoCrypt software implementation */ /* permuted choice table (key) */ diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 5b6ad6a83..a94ad0801 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -113,6 +113,9 @@ typedef struct Aes { word32 iv_ce [AES_BLOCK_SIZE /sizeof(word32)] ; int keylen ; #endif +#ifdef WOLFSSL_TI_CRYPT + int keylen ; +#endif } Aes; From 559404137e8bcb2bcad712b786f585d9299b2579 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Wed, 27 May 2015 18:37:19 +0900 Subject: [PATCH 08/21] moving xxxGetHash to hash.c --- wolfcrypt/benchmark/benchmark.c | 3 +- wolfcrypt/src/hash.c | 66 +++++++++++++++++++++++++++++++++ wolfcrypt/src/md5.c | 6 --- wolfcrypt/src/sha.c | 9 ----- wolfcrypt/src/sha256.c | 9 ----- 5 files changed, 67 insertions(+), 26 deletions(-) create mode 100644 wolfcrypt/src/hash.c diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index bd5fd27f5..838a80e34 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -1846,9 +1846,8 @@ void bench_ed25519KeySign(void) return ( ns / CLOCK * 2.0); } -#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) +#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || defined(WOLFSSL_USER_TIME) extern double current_time(int reset); - #elif defined FREERTOS diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c new file mode 100644 index 000000000..7a6e51f3b --- /dev/null +++ b/wolfcrypt/src/hash.c @@ -0,0 +1,66 @@ +/* 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 + +#if !defined(NO_MD5) && !defined(WOLFSSL_TI_HASH) + +#include +void wc_Md5GetHash(Md5* md5, byte* hash) +{ + Md5 save = *md5 ; + wc_Md5Final(md5, hash) ; + *md5 = save ; +} +#endif + +#if !defined(NO_SHA) && !defined(WOLFSSL_TI_HASH) + +#include + +int wc_ShaGetHash(Sha* sha, byte* hash) +{ + int ret ; + Sha save = *sha ; + ret = wc_ShaFinal(sha, hash) ; + *sha = save ; + return ret ; +} +#endif + +#if !defined(NO_SHA256) && !defined(WOLFSSL_TI_HASH) + +#include + +int wc_Sha256GetHash(Sha256* sha256, byte* hash) +{ + int ret ; + Sha256 save = *sha256 ; + ret = wc_Sha256Final(sha256, hash) ; + *sha256 = save ; + return ret ; +} + +#endif diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index d5bb17b63..db1e21f87 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -392,10 +392,4 @@ int wc_Md5Hash(const byte* data, word32 len, byte* hash) return 0; } -void wc_Md5GetHash(Md5* md5, byte* hash) -{ - Md5 save = *md5 ; - wc_Md5Final(md5, hash) ; - *md5 = save ; -} #endif /* NO_MD5 */ diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 78f2640f0..f67f88ddc 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -452,15 +452,6 @@ int wc_ShaHash(const byte* data, word32 len, byte* hash) } -int wc_ShaGetHash(Sha* sha, byte* hash) -{ - int ret ; - Sha save = *sha ; - ret = wc_ShaFinal(sha, hash) ; - *sha = save ; - return ret ; -} - #endif /* HAVE_FIPS */ #endif /* NO_SHA */ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index a204637f4..7342d836f 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -576,15 +576,6 @@ int wc_Sha256Hash(const byte* data, word32 len, byte* hash) return ret; } -int wc_Sha256GetHash(Sha256* sha256, byte* hash) -{ - int ret ; - Sha256 save = *sha256 ; - ret = wc_Sha256Final(sha256, hash) ; - *sha256 = save ; - return ret ; -} - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) #define _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ From 902799ef755270bb992aa645c7514cb35fae6e66 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Wed, 27 May 2015 19:34:11 +0900 Subject: [PATCH 09/21] adding ti hash/crypt to include.am --- src/include.am | 6 +++--- wolfcrypt/src/include.am | 8 ++++++++ wolfssl/wolfcrypt/include.am | 4 +++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/include.am b/src/include.am index f65331b4c..161a9cd91 100644 --- a/src/include.am +++ b/src/include.am @@ -49,7 +49,8 @@ endif src_libwolfssl_la_SOURCES += \ wolfcrypt/src/hmac.c \ wolfcrypt/src/random.c \ - wolfcrypt/src/sha256.c + wolfcrypt/src/sha256.c \ + wolfcrypt/src/hash.c if BUILD_RSA src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c @@ -74,8 +75,7 @@ endif src_libwolfssl_la_SOURCES += \ wolfcrypt/src/logging.c \ wolfcrypt/src/wc_port.c \ - wolfcrypt/src/error.c\ - wolfcrypt/src/port/ti/ti-hash.c + wolfcrypt/src/error.c if BUILD_MEMORY src_libwolfssl_la_SOURCES += wolfcrypt/src/memory.c diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index a6e815427..299921579 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -38,3 +38,11 @@ EXTRA_DIST += \ wolfcrypt/src/fp_sqr_comba_8.i \ wolfcrypt/src/fp_sqr_comba_9.i \ wolfcrypt/src/fp_sqr_comba_small_set.i + +EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ + wolfcrypt/src/port/ti/ti-des3.c \ + wolfcrypt/src/port/ti/ti-hash.c \ + wolfcrypt/src/port/ti/ti-ccm.c \ + wolfcrypt/src/port/pic32/pic32mz-hash.c + + diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 2603f117c..26a7759b3 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -52,5 +52,7 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/mpi_superclass.h noinst_HEADERS+= \ - wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h + wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ + wolfssl/wolfcrypt/port/ti/ti-hash.h \ + wolfssl/wolfcrypt/port/ti/ti-ccm.h From d67168d53928e32f8c532e5b8986e01ce87fd093 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Thu, 28 May 2015 20:40:53 +0900 Subject: [PATCH 10/21] aes.c cleaned. ti-has.c, ti-aes.c, ti-des3.c are included in each respective algorithm source file. --- wolfcrypt/src/aes.c | 43 ++++++++++----------------------- wolfcrypt/src/des3.c | 9 ++++--- wolfcrypt/src/md5.c | 13 ++++++---- wolfcrypt/src/port/ti/ti-hash.c | 8 +++--- wolfcrypt/src/sha.c | 12 +++++---- wolfcrypt/src/sha256.c | 13 +++++++--- wolfcrypt/src/wc_port.c | 5 +++- wolfssl/internal.h | 2 ++ wolfssl/wolfcrypt/hash.h | 35 +++++++++++++++++++++++++++ wolfssl/wolfcrypt/md5.h | 6 ----- wolfssl/wolfcrypt/sha.h | 1 - wolfssl/wolfcrypt/sha256.h | 1 - 12 files changed, 88 insertions(+), 60 deletions(-) create mode 100644 wolfssl/wolfcrypt/hash.h diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 9e80e9839..85f01a0d1 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -174,6 +174,11 @@ void wc_AesFreeCavium(Aes* aes) } #endif #else /* HAVE_FIPS */ + +#ifdef WOLFSSL_TI_CRYPT +#include +#else + #include #include #ifdef NO_INLINE @@ -230,10 +235,6 @@ void wc_AesFreeCavium(Aes* aes) word32 length); static int wc_AesCaviumCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 length); -#elif defined(WOLFSSL_TI_CRYPT) - - /* defined in port/ti_aes.c */ - #else /* using CTaoCrypt software AES implementation */ #define NEED_AES_TABLES @@ -1509,11 +1510,6 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { return wc_AesSetKey(aes, userKey, keylen, iv, dir); } - -#elif defined(WOLFSSL_TI_CRYPT) - - /* defined in port/ti_md5.c */ - #else static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) @@ -1784,10 +1780,6 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, #elif defined(WOLFSSL_PIC32MZ_CRYPT) #error "PIC32MZ doesn't yet support AES direct" - #elif defined(WOLFSSL_TI_CRYPT) - - /* defined in port/ti_aes.c */ - #else /* Allow direct access to one block encrypt */ void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) @@ -2322,10 +2314,6 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, return 0 ; } -#elif defined(WOLFSSL_TI_CRYPT) - - /* defined in port/ti_aes.c */ - #else int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { @@ -2606,10 +2594,7 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, #elif defined(FREESCALE_MMCAU) #error "Freescale mmCAU doesn't currently support AES-CTR mode" - - #elif defined(WOLFSSL_TI_CRYPT) - /* defined in port/ti/ti_aes.c */ - + #else /* Increment AES counter */ static INLINE void IncrementAesCounter(byte* inOutCtr) @@ -2691,7 +2676,7 @@ enum { CTR_SZ = 4 }; -#if !defined(WOLFSSL_TI_CRYPT) + static INLINE void InitGcmCounter(byte* inOutCtr) { inOutCtr[AES_BLOCK_SIZE - 4] = 0; @@ -2796,10 +2781,6 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) if (ret == 0) { #ifdef FREESCALE_MMCAU cau_aes_encrypt(iv, rk, aes->rounds, aes->H); - - #elif defined(WOLFSSL_TI_CRYPT) - /* defined in port/ti/ti_aes.c */ - #else wc_AesEncrypt(aes, iv, aes->H); #endif @@ -3313,7 +3294,8 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, } #endif /* end GCM_WORD32 */ - + + int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, byte* authTag, word32 authTagSz, @@ -3468,7 +3450,8 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, } return 0; } -#endif + + WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) { @@ -3500,7 +3483,6 @@ WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, #endif -#if !defined(WOLFSSL_TI_CRYPT) void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) { byte nonce[AES_BLOCK_SIZE]; @@ -3781,7 +3763,6 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, return result; } -#endif /* WOLFCRYPT_TI_CRYPT */ #endif /* HAVE_AESCCM */ @@ -3909,6 +3890,8 @@ static int AesCaviumCbcDecrypt(Aes* aes, byte* out, const byte* in, #endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_TI_CRYPT */ + #endif /* HAVE_FIPS */ #endif /* NO_AES */ diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index 62e0ef12c..f886ecdc7 100644 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -129,6 +129,11 @@ void wc_Des3_FreeCavium(Des3* des3) #endif /* HAVE_CAVIUM */ #else /* build without fips */ + +#if defined(WOLFSSL_TI_CRYPT) + #include +#else + #include #include @@ -943,9 +948,6 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); PIC32_DECRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC); return 0; } - -#elif defined(WOLFSSL_TI_CRYPT) - /* defined in port/ti/ti-des3.c */ #else /* CTaoCrypt software implementation */ @@ -1671,5 +1673,6 @@ static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, } #endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_TI_CRYPT */ #endif /* HAVE_FIPS */ #endif /* NO_DES3 */ diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index db1e21f87..02a24ec15 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -26,7 +26,12 @@ #include -#if !defined(NO_MD5) && !defined(WOLFSSL_TI_HASH) +#if !defined(NO_MD5) + +#if defined(WOLFSSL_TI_HASH) + #define WOLFSSL_TI_MD5 + #include +#else #ifdef WOLFSSL_PIC32MZ_HASH #define wc_InitMd5 wc_InitMd5_sw @@ -164,10 +169,6 @@ wc_InitMd5(md5); /* reset state */ } -#elif defined(WOLFSSL_IT_HASH) - - /* defined in port/ti_hash.c */ - #else /* CTaoCrypt software implementation */ #ifndef WOLFSSL_HAVE_MIN @@ -392,4 +393,6 @@ int wc_Md5Hash(const byte* data, word32 len, byte* hash) return 0; } +#endif /* WOLFSSL_TI_HASH */ + #endif /* NO_MD5 */ diff --git a/wolfcrypt/src/port/ti/ti-hash.c b/wolfcrypt/src/port/ti/ti-hash.c index 4b7f49a20..f2885298f 100644 --- a/wolfcrypt/src/port/ti/ti-hash.c +++ b/wolfcrypt/src/port/ti/ti-hash.c @@ -144,7 +144,7 @@ static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word3 return ret; } -#if !defined(NO_MD5) +#if !defined(NO_MD5) && defined(WOLFSSL_TI_MD5) WOLFSSL_API void wc_InitMd5(Md5* md5) { if (md5 == NULL) @@ -175,7 +175,7 @@ WOLFSSL_API int wc_Md5Hash(const byte*data, word32 len, byte*hash) #endif /* NO_MD5 */ -#if !defined(NO_SHA) +#if !defined(NO_SHA) && defined(WOLFSSL_TI_SHA) WOLFSSL_API int wc_InitSha(Sha* sha) { if (sha == NULL) @@ -206,7 +206,7 @@ WOLFSSL_API int wc_ShaHash(const byte*data, word32 len, byte*hash) #endif /* NO_SHA */ -#if defined(HAVE_SHA224) +#if defined(HAVE_SHA224) && defined(WOLFSSL_TI_SHA224) WOLFSSL_API int wc_InitSha224(Sha224* sha224) { if (sha224 == NULL) @@ -237,7 +237,7 @@ WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) #endif /* HAVE_SHA224 */ -#if !defined(NO_SHA256) +#if !defined(NO_SHA256) && defined(WOLFSSL_TI_SHA256) WOLFSSL_API int wc_InitSha256(Sha256* sha256) { if (sha256 == NULL) diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index f67f88ddc..f710603cb 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -26,7 +26,7 @@ #include -#if !defined(NO_SHA) && !defined(WOLFSSL_TI_HASH) +#if !defined(NO_SHA) #include #include @@ -64,6 +64,11 @@ #else /* else build without fips */ +#if defined(WOLFSSL_TI_HASH) + #define WOLFSSL_TI_SHA + #include +#else + #ifdef WOLFSSL_PIC32MZ_HASH #define wc_InitSha wc_InitSha_sw #define wc_ShaUpdate wc_ShaUpdate_sw @@ -196,10 +201,6 @@ int wc_ShaFinal(Sha* sha, byte* hash) return wc_InitSha(sha); /* reset state */ } -#elif defined(WOLFSSL_TI_HASH) - - /* defined in port/ti/ti_hash.c */ - #else /* wc_ software implementation */ #ifndef WOLFSSL_HAVE_MIN @@ -453,5 +454,6 @@ int wc_ShaHash(const byte* data, word32 len, byte* hash) } #endif /* HAVE_FIPS */ +#endif /* WOLFSSL_TI_HASH */ #endif /* NO_SHA */ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 7342d836f..bc40798de 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -56,8 +56,13 @@ int wc_Sha256Hash(const byte* data, word32 len, byte* out) #else /* else build without fips */ -#if !defined(NO_SHA256) && !defined(WOLFSSL_TI_HASH) - /* defined in port/ti/ti_hash.c */ +#if !defined(NO_SHA256) && defined(WOLFSSL_TI_HASH) + #define WOLFSSL_TI_SHA256 + #ifdef HAVE_SHA224 + #define WOLFSSL_TI_SHA224 + #endif + #include +#else #if !defined (ALIGN32) #if defined (__GNUC__) @@ -1757,9 +1762,9 @@ static int Transform_AVX2(Sha256* sha256) #endif /* HAVE_INTEL_AVX2 */ -#endif /* WOLFSSL_TI_HAHS */ - #endif /* HAVE_FIPS */ +#endif /* WOLFSSL_TI_HAHS */ + #endif /* NO_SHA256 */ diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 864ac2490..953a16be4 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -649,4 +649,7 @@ int UnLockMutex(wolfSSL_Mutex *m) #endif /* USE_WINDOWS_API */ #endif /* SINGLE_THREADED */ - + +#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) + #include /* initialize and Mutex for TI Crypt Engine */ +#endif diff --git a/wolfssl/internal.h b/wolfssl/internal.h index edba235dc..854ea57fb 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -88,6 +88,8 @@ #include #endif +#include + #ifdef WOLFSSL_CALLBACKS #include #include diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h new file mode 100644 index 000000000..bbc2d8b95 --- /dev/null +++ b/wolfssl/wolfcrypt/hash.h @@ -0,0 +1,35 @@ +/* hash.h + * + * 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 + */ + +#ifndef WOLF_CRYPT_HASH_H +#define WOLF_CRYPT_HASH_H + +#ifndef NO_MD5 +WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); +#endif +#ifndef NO_SHA +WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); +#endif +#ifndef NO_SHA256 +WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); +#endif + +#endif diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index b1f775c4c..d0b134b6a 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/wolfssl/wolfcrypt/md5.h @@ -52,11 +52,6 @@ enum { #include "port/pic32/pic32mz-crypt.h" #endif -#ifdef TI_HASH_TEST -#include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif - - #ifndef WOLFSSL_TI_HASH /* MD5 digest */ @@ -81,7 +76,6 @@ WOLFSSL_API void wc_InitMd5(Md5*); WOLFSSL_API void wc_Md5Update(Md5*, const byte*, word32); WOLFSSL_API void wc_Md5Final(Md5*, byte*); WOLFSSL_API int wc_Md5Hash(const byte*, word32, byte*); -WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index b5ff4908d..80a2c9832 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/wolfssl/wolfcrypt/sha.h @@ -77,7 +77,6 @@ WOLFSSL_API int wc_InitSha(Sha*); WOLFSSL_API int wc_ShaUpdate(Sha*, const byte*, word32); WOLFSSL_API int wc_ShaFinal(Sha*, byte*); WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); -WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index d022d3ac5..7cf6d8677 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -75,7 +75,6 @@ WOLFSSL_API int wc_InitSha256(Sha256*); WOLFSSL_API int wc_Sha256Update(Sha256*, const byte*, word32); WOLFSSL_API int wc_Sha256Final(Sha256*, byte*); WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); -WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); #ifdef __cplusplus } /* extern "C" */ From e4580c34616dece28a56f442b086bd9ceec8561b Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Thu, 28 May 2015 20:50:22 +0900 Subject: [PATCH 11/21] adding hash.h to include.am --- wolfssl/wolfcrypt/include.am | 1 + 1 file changed, 1 insertion(+) diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 26a7759b3..1f3a726b8 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -20,6 +20,7 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/ge_operations.h \ wolfssl/wolfcrypt/error-crypt.h \ wolfssl/wolfcrypt/fips_test.h \ + wolfssl/wolfcrypt/hash.h \ wolfssl/wolfcrypt/hc128.h \ wolfssl/wolfcrypt/hmac.h \ wolfssl/wolfcrypt/integer.h \ From 644f7a4cdbe671968ffd5073cf883b67e89e7327 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Mon, 1 Jun 2015 14:32:36 +0900 Subject: [PATCH 12/21] ti-hash.c included in wc_port.c --- wolfcrypt/src/md5.c | 3 +-- wolfcrypt/src/port/ti/ti-hash.c | 8 ++++---- wolfcrypt/src/sha.c | 3 +-- wolfcrypt/src/sha256.c | 6 +----- wolfcrypt/src/wc_port.c | 3 ++- 5 files changed, 9 insertions(+), 14 deletions(-) diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index 02a24ec15..fbf732add 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -29,8 +29,7 @@ #if !defined(NO_MD5) #if defined(WOLFSSL_TI_HASH) - #define WOLFSSL_TI_MD5 - #include + /* #include included by wc_port.c */ #else #ifdef WOLFSSL_PIC32MZ_HASH diff --git a/wolfcrypt/src/port/ti/ti-hash.c b/wolfcrypt/src/port/ti/ti-hash.c index f2885298f..4b7f49a20 100644 --- a/wolfcrypt/src/port/ti/ti-hash.c +++ b/wolfcrypt/src/port/ti/ti-hash.c @@ -144,7 +144,7 @@ static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word3 return ret; } -#if !defined(NO_MD5) && defined(WOLFSSL_TI_MD5) +#if !defined(NO_MD5) WOLFSSL_API void wc_InitMd5(Md5* md5) { if (md5 == NULL) @@ -175,7 +175,7 @@ WOLFSSL_API int wc_Md5Hash(const byte*data, word32 len, byte*hash) #endif /* NO_MD5 */ -#if !defined(NO_SHA) && defined(WOLFSSL_TI_SHA) +#if !defined(NO_SHA) WOLFSSL_API int wc_InitSha(Sha* sha) { if (sha == NULL) @@ -206,7 +206,7 @@ WOLFSSL_API int wc_ShaHash(const byte*data, word32 len, byte*hash) #endif /* NO_SHA */ -#if defined(HAVE_SHA224) && defined(WOLFSSL_TI_SHA224) +#if defined(HAVE_SHA224) WOLFSSL_API int wc_InitSha224(Sha224* sha224) { if (sha224 == NULL) @@ -237,7 +237,7 @@ WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) #endif /* HAVE_SHA224 */ -#if !defined(NO_SHA256) && defined(WOLFSSL_TI_SHA256) +#if !defined(NO_SHA256) WOLFSSL_API int wc_InitSha256(Sha256* sha256) { if (sha256 == NULL) diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index f710603cb..be8cf17af 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -65,8 +65,7 @@ #else /* else build without fips */ #if defined(WOLFSSL_TI_HASH) - #define WOLFSSL_TI_SHA - #include + /* #include included by wc_port.c */ #else #ifdef WOLFSSL_PIC32MZ_HASH diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index bc40798de..f9f02b003 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -57,11 +57,7 @@ int wc_Sha256Hash(const byte* data, word32 len, byte* out) #else /* else build without fips */ #if !defined(NO_SHA256) && defined(WOLFSSL_TI_HASH) - #define WOLFSSL_TI_SHA256 - #ifdef HAVE_SHA224 - #define WOLFSSL_TI_SHA224 - #endif - #include + /* #include included by wc_port.c */ #else #if !defined (ALIGN32) diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 953a16be4..419033751 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -651,5 +651,6 @@ int UnLockMutex(wolfSSL_Mutex *m) #endif /* SINGLE_THREADED */ #if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) - #include /* initialize and Mutex for TI Crypt Engine */ + #include /* initialize and Mutex for TI Crypt Engine */ + #include /* md5, sha1, sha224, sha256 */ #endif From fe3253e618e86cb5a87f5fc4dc86cc39bb3e126d Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Mon, 1 Jun 2015 20:02:20 +0900 Subject: [PATCH 13/21] IAR/EWARM wolfSSL name change --- .../Projects/CyaSSL-Lib/CyaSSL-Lib.eww | 16 - .../CyaSSL-Lib/wolfCrypt-benchmark.ewp | 1877 ----------------- .../CyaSSL-Lib/wolfCrypt-benchmark.icf | 32 - .../Projects/CyaSSL-Lib/wolfCrypt-test.ewp | 1877 ----------------- .../Projects/CyaSSL-Lib/wolfCrypt-test.icf | 31 - .../benchmark-main.c | 8 +- .../Projects/benchmark/current_time.c | 66 + .../wolfCrypt-benchmark.ewd | 1457 +------------ .../benchmark/wolfCrypt-benchmark.ewp | 981 +++++++++ .../Projects/common/minimum-startup.c | 52 + IDE/IAR-EWARM/Projects/common/wolfssl.icf | 11 + .../wolfSSL-Lib.ewd} | 200 +- .../CyaSSL-Lib.ewp => lib/wolfSSL-Lib.ewp} | 314 +-- .../Projects/{CyaSSL-Lib => test}/test-main.c | 5 +- .../Projects/test/wolfCrypt-test.ewd | 1374 ++++++++++++ .../Projects/test/wolfCrypt-test.ewp | 978 +++++++++ IDE/IAR-EWARM/Projects/user_settings.h | 14 + IDE/IAR-EWARM/Projects/wolfssl.eww | 224 ++ IDE/IAR-EWARM/README | 28 +- wolfcrypt/benchmark/benchmark.c | 2 +- wolfssl/wolfcrypt/settings.h | 11 - 21 files changed, 4171 insertions(+), 5387 deletions(-) delete mode 100644 IDE/IAR-EWARM/Projects/CyaSSL-Lib/CyaSSL-Lib.eww delete mode 100644 IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.ewp delete mode 100644 IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.icf delete mode 100644 IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-test.ewp delete mode 100644 IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-test.icf rename IDE/IAR-EWARM/Projects/{CyaSSL-Lib => benchmark}/benchmark-main.c (88%) create mode 100644 IDE/IAR-EWARM/Projects/benchmark/current_time.c rename IDE/IAR-EWARM/Projects/{CyaSSL-Lib => benchmark}/wolfCrypt-benchmark.ewd (50%) create mode 100644 IDE/IAR-EWARM/Projects/benchmark/wolfCrypt-benchmark.ewp create mode 100644 IDE/IAR-EWARM/Projects/common/minimum-startup.c create mode 100644 IDE/IAR-EWARM/Projects/common/wolfssl.icf rename IDE/IAR-EWARM/Projects/{CyaSSL-Lib/wolfCrypt-test.ewd => lib/wolfSSL-Lib.ewd} (94%) rename IDE/IAR-EWARM/Projects/{CyaSSL-Lib/CyaSSL-Lib.ewp => lib/wolfSSL-Lib.ewp} (91%) rename IDE/IAR-EWARM/Projects/{CyaSSL-Lib => test}/test-main.c (93%) create mode 100644 IDE/IAR-EWARM/Projects/test/wolfCrypt-test.ewd create mode 100644 IDE/IAR-EWARM/Projects/test/wolfCrypt-test.ewp create mode 100644 IDE/IAR-EWARM/Projects/user_settings.h create mode 100644 IDE/IAR-EWARM/Projects/wolfssl.eww diff --git a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/CyaSSL-Lib.eww b/IDE/IAR-EWARM/Projects/CyaSSL-Lib/CyaSSL-Lib.eww deleted file mode 100644 index 9702cae02..000000000 --- a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/CyaSSL-Lib.eww +++ /dev/null @@ -1,16 +0,0 @@ - - - - - $WS_DIR$\CyaSSL-Lib.ewp - - - $WS_DIR$\wolfCrypt-benchmark.ewp - - - $WS_DIR$\wolfCrypt-test.ewp - - - - - diff --git a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.ewp b/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.ewp deleted file mode 100644 index d61e0a0e9..000000000 --- a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.ewp +++ /dev/null @@ -1,1877 +0,0 @@ - - - - 2 - - Debug - - ARM - - 1 - - General - 3 - - 22 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 29 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 1 - - - - - - - - - CUSTOM - 3 - - - - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - - - - - - ILINK - 0 - - 16 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 1 - - - - - - - BILINK - 0 - - - - - Release - - ARM - - 0 - - General - 3 - - 22 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 29 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 0 - - - - - - - - - CUSTOM - 3 - - - - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - - - - - - ILINK - 0 - - 16 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 0 - - - - - - - BILINK - 0 - - - - - $PROJ_DIR$\benchmark-main.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\benchmark\benchmark.c - - - - diff --git a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.icf b/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.icf deleted file mode 100644 index a4ab009ee..000000000 --- a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.icf +++ /dev/null @@ -1,32 +0,0 @@ -/*###ICF### Section handled by ICF editor, don't touch! ****/ -/*-Editor annotation file-*/ -/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ -/*-Specials-*/ -define symbol __ICFEDIT_intvec_start__ = 0x00000000; -/*-Memory Regions-*/ -define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; -define symbol __ICFEDIT_region_ROM_end__ = 0x0007FFFF; -define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; -define symbol __ICFEDIT_region_RAM_end__ = 0x2000FFFF; -/*-Sizes-*/ -define symbol __ICFEDIT_size_cstack__ = 0x2000; -define symbol __ICFEDIT_size_heap__ = 0x2000; -/**** End of ICF editor section. ###ICF###*/ - - -define memory mem with size = 4G; -define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; -define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; - -define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; -define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; - -initialize by copy { readwrite }; -//initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application -do not initialize { section .noinit }; - -place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; - -place in ROM_region { readonly }; -place in RAM_region { readwrite, - block CSTACK, block HEAP }; \ No newline at end of file diff --git a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-test.ewp b/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-test.ewp deleted file mode 100644 index 60e146e43..000000000 --- a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-test.ewp +++ /dev/null @@ -1,1877 +0,0 @@ - - - - 2 - - Debug - - ARM - - 1 - - General - 3 - - 22 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 29 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 1 - - - - - - - - - CUSTOM - 3 - - - - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - - - - - - ILINK - 0 - - 16 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 1 - - - - - - - BILINK - 0 - - - - - Release - - ARM - - 0 - - General - 3 - - 22 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 29 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 0 - - - - - - - - - CUSTOM - 3 - - - - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - - - - - - ILINK - 0 - - 16 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 0 - - - - - - - BILINK - 0 - - - - - $PROJ_DIR$\test-main.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\test\test.c - - - - diff --git a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-test.icf b/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-test.icf deleted file mode 100644 index 211d253d4..000000000 --- a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-test.icf +++ /dev/null @@ -1,31 +0,0 @@ -/*###ICF### Section handled by ICF editor, don't touch! ****/ -/*-Editor annotation file-*/ -/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ -/*-Specials-*/ -define symbol __ICFEDIT_intvec_start__ = 0x0; -/*-Memory Regions-*/ -define symbol __ICFEDIT_region_ROM_start__ = 0x0; -define symbol __ICFEDIT_region_ROM_end__ = 0x000FFFFF; -define symbol __ICFEDIT_region_RAM_start__ = 0x1FFF0000; -define symbol __ICFEDIT_region_RAM_end__ = 0x2000FFFF; -/*-Sizes-*/ -define symbol __ICFEDIT_size_cstack__ = 0x2000; -define symbol __ICFEDIT_size_heap__ = 0x3000; -/**** End of ICF editor section. ###ICF###*/ - - -define memory mem with size = 4G; -define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; -define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; - -define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; -define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; - -initialize by copy { readwrite }; -do not initialize { section .noinit }; - -place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; - -place in ROM_region { readonly }; -place in RAM_region { readwrite, - block CSTACK, block HEAP }; \ No newline at end of file diff --git a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/benchmark-main.c b/IDE/IAR-EWARM/Projects/benchmark/benchmark-main.c similarity index 88% rename from IDE/IAR-EWARM/Projects/CyaSSL-Lib/benchmark-main.c rename to IDE/IAR-EWARM/Projects/benchmark/benchmark-main.c index 113fc4d23..d8f559d4c 100644 --- a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/benchmark-main.c +++ b/IDE/IAR-EWARM/Projects/benchmark/benchmark-main.c @@ -19,7 +19,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#include "stdio.h" +#ifdef HAVE_CONFIG_H + #include +#endif + +#include typedef struct func_args { int argc; @@ -29,6 +33,7 @@ typedef struct func_args { func_args args = { 0 } ; +extern double current_time(int reset) ; extern int benchmark_test(void *args) ; main(void) { @@ -37,4 +42,3 @@ main(void) { } - diff --git a/IDE/IAR-EWARM/Projects/benchmark/current_time.c b/IDE/IAR-EWARM/Projects/benchmark/current_time.c new file mode 100644 index 000000000..7d42cfc02 --- /dev/null +++ b/IDE/IAR-EWARM/Projects/benchmark/current_time.c @@ -0,0 +1,66 @@ +/* current-time.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_TI_CURRTIME +#include +#include +#include + +#include "inc/hw_ints.h" +#include "inc/hw_memmap.h" +#include "inc/hw_timer.h" +#include "driverlib/rom.h" +#include "driverlib/sysctl.h" +#include "driverlib/timer.h" + +void InitTimer(void) { + uint32_t ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | + SYSCTL_OSC_MAIN | + SYSCTL_USE_PLL | + SYSCTL_CFG_VCO_480), 120000000); + + printf("Clock=%dMHz\n", ui32SysClock/1000000) ; + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); + ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); + ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, -1); + ROM_TimerEnable(TIMER0_BASE, TIMER_A); +} + +static int initFlag = false ; +double current_time(int reset) +{ + if(!initFlag)InitTimer() ; + initFlag = true ; + if(reset)ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, -1); + return (double)(-(int)ROM_TimerValueGet(TIMER0_BASE, TIMER_A ))/120000000.0 ; +} + +#else + +double current_time(int reset) { return 0.0 ; } + +#endif \ No newline at end of file diff --git a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.ewd b/IDE/IAR-EWARM/Projects/benchmark/wolfCrypt-benchmark.ewd similarity index 50% rename from IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.ewd rename to IDE/IAR-EWARM/Projects/benchmark/wolfCrypt-benchmark.ewd index 0bf90e8eb..3f908a2d3 100644 --- a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/wolfCrypt-benchmark.ewd +++ b/IDE/IAR-EWARM/Projects/benchmark/wolfCrypt-benchmark.ewd @@ -12,7 +12,7 @@ C-SPY 2 - 25 + 26 1 1 + + + + + + @@ -245,7 +269,7 @@ @@ -421,7 +469,7 @@ - - - - IARROM_ID - 2 - - 1 - 1 - 1 - - - - - - - - - IJET_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JLINK_ID - 2 - - 15 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LMIFTDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - MACRAIGOR_ID - 2 - - 3 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - PEMICRO_ID - 2 - - 1 - 1 - 1 - - - - - - - - - - - - - - - - - - - RDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - - - - - - - STLINK_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - - THIRDPARTY_ID - 2 - - 0 - 1 - 1 - - - - - - - - XDS100_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - - - - $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\PowerPac\PowerPacRTOS.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\Quadros\Quadros_EWB6_Plugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin - 0 - - - $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin - 1 - - - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin - 0 - - - $EW_DIR$\common\plugins\SymList\SymList.ENU.ewplugin - 1 - - - $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin - 0 - - - - - Release - - ARM - - 0 - - C-SPY - 2 - - 25 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ARMSIM_ID - 2 - - 1 - 1 - 0 - - - - - - - - ANGEL_ID - 2 - - 0 - 1 - 0 - - - - - - - - - - - - CMSISDAP_ID - 2 - - 0 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GDBSERVER_ID - 2 - - 0 - 1 - 0 - - - - - - - @@ -1740,14 +491,14 @@ 1 1 - 0 + 1 @@ -1971,7 +744,7 @@ 15 1 - 0 + 1 @@ -257,7 +281,7 @@ CMSISDAP_ID 2 - 0 + 2 1 1 + + + + + + @@ -472,7 +520,7 @@ IJET_ID 2 - 2 + 3 1 1 + @@ -677,7 +729,7 @@ 1 @@ -1554,7 +1626,7 @@ CMSISDAP_ID 2 - 0 + 2 1 0 + + + + + + @@ -1769,7 +1865,7 @@ IJET_ID 2 - 2 + 3 1 0 + @@ -1974,7 +2074,7 @@ 0 @@ -602,6 +612,7 @@ + 0 @@ -924,7 +935,7 @@ @@ -961,7 +972,7 @@ - CyaSSL + Config + + $PROJ_DIR$\..\..\..\..\wolfssl\wolfcrypt\settings.h + + + $PROJ_DIR$\..\user_settings.h + + + + wolfCrypt + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\aes.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\arc4.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\asm.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\asn.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\blake2b.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\camellia.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\chacha.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\chacha20_poly1305.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\coding.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\compress.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\curve25519.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\des3.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\dh.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\dsa.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\ecc.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\ecc_fp.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\ed25519.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\error.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\fe_operations.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\ge_operations.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\hc128.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\hmac.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\integer.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\logging.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\md2.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\md4.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\md5.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\memory.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\misc.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\pkcs7.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\poly1305.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\pwdbased.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\rabbit.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\random.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\ripemd.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\rsa.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\sha.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\sha256.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\sha512.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\tfm.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\wc_port.c + + + + wolfSSL $PROJ_DIR$\..\..\..\..\src\crl.c @@ -1893,108 +2049,6 @@ $PROJ_DIR$\..\..\..\..\src\tls.c - - wolfCrypt - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\aes.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\arc4.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\asm.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\asn.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\blake2b.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\camellia.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\coding.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\compress.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\des3.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\dh.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\dsa.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\ecc.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\ecc_fp.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\error.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\hc128.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\hmac.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\integer.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\logging.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\md2.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\md4.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\md5.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\memory.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\misc.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\wc_port.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\pwdbased.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\rabbit.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\random.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\ripemd.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\rsa.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\sha.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\sha256.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\sha512.c - - - $PROJ_DIR$\..\..\..\..\ctaocrypt\src\tfm.c - - diff --git a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/test-main.c b/IDE/IAR-EWARM/Projects/test/test-main.c similarity index 93% rename from IDE/IAR-EWARM/Projects/CyaSSL-Lib/test-main.c rename to IDE/IAR-EWARM/Projects/test/test-main.c index 5ebfe3219..ad78746d5 100644 --- a/IDE/IAR-EWARM/Projects/CyaSSL-Lib/test-main.c +++ b/IDE/IAR-EWARM/Projects/test/test-main.c @@ -28,9 +28,10 @@ typedef struct func_args { func_args args = { 0 } ; -extern int ctaocrypt_test(void *args) ; +extern int wolfcrypt_test(void *args) ; main(void) { - ctaocrypt_test(&args) ; + wolfcrypt_test(&args) ; return 0; } + diff --git a/IDE/IAR-EWARM/Projects/test/wolfCrypt-test.ewd b/IDE/IAR-EWARM/Projects/test/wolfCrypt-test.ewd new file mode 100644 index 000000000..3f908a2d3 --- /dev/null +++ b/IDE/IAR-EWARM/Projects/test/wolfCrypt-test.ewd @@ -0,0 +1,1374 @@ + + + + 2 + + Debug + + ARM + + 1 + + C-SPY + 2 + + 26 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + ANGEL_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + + CMSISDAP_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IARROM_ID + 2 + + 1 + 1 + 1 + + + + + + + + + IJET_ID + 2 + + 6 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 15 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + MACRAIGOR_ID + 2 + + 3 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + PEMICRO_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + RDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + + + + + + + STLINK_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + XDS100_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Quadros\Quadros_EWB7_Plugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\SymList\SymList.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + + diff --git a/IDE/IAR-EWARM/Projects/test/wolfCrypt-test.ewp b/IDE/IAR-EWARM/Projects/test/wolfCrypt-test.ewp new file mode 100644 index 000000000..ec45ce948 --- /dev/null +++ b/IDE/IAR-EWARM/Projects/test/wolfCrypt-test.ewp @@ -0,0 +1,978 @@ + + + + 2 + + Debug + + ARM + + 1 + + General + 3 + + 22 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 31 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 9 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + + Config + + $PROJ_DIR$\..\user_settings.h + + + + Lib + + $PROJ_DIR$\..\lib\ewarm\Exe\wolfSSL-Lib.a + + + + Source + + $PROJ_DIR$\..\common\minimum-startup.c + + + $PROJ_DIR$\test-main.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\test\test.c + + + + + diff --git a/IDE/IAR-EWARM/Projects/user_settings.h b/IDE/IAR-EWARM/Projects/user_settings.h new file mode 100644 index 000000000..5e4f36e9a --- /dev/null +++ b/IDE/IAR-EWARM/Projects/user_settings.h @@ -0,0 +1,14 @@ + +#define NO_MAIN_DRIVER +#define BENCH_EMBEDDED +#define SINGLE_THREADED +#define NO_FILESYSTEM +#define NO_WRITEV +#define WOLFSSL_USER_IO +#define NO_DEV_RANDOM +#define USE_CERT_BUFFERS_2048 +#define WOLFSSL_USER_CURRTIME + +#define CUSTOM_RAND_GENERATE custom_rand_generate +/* warning "write a real random seed!!!!, just for testing now" */ +static int custom_rand_generate(void) { return 0 ; } \ No newline at end of file diff --git a/IDE/IAR-EWARM/Projects/wolfssl.eww b/IDE/IAR-EWARM/Projects/wolfssl.eww new file mode 100644 index 000000000..b080e4115 --- /dev/null +++ b/IDE/IAR-EWARM/Projects/wolfssl.eww @@ -0,0 +1,224 @@ + + + + + $WS_DIR$\benchmark\wolfCrypt-benchmark.ewp + + + $WS_DIR$\test\wolfCrypt-test.ewp + + + $WS_DIR$\lib\wolfSSL-Lib.ewp + + + + All Examples + + driverlib + Debug + + + grlib + Debug + + + usblib + Debug + + + aes128_cbc_decrypt + Debug + + + aes128_cbc_encrypt + Debug + + + aes128_ccm_decrypt + Debug + + + aes128_ccm_encrypt + Debug + + + aes128_cmac + Debug + + + aes128_ecb_decrypt + Debug + + + aes128_ecb_encrypt + Debug + + + aes128_gcm_decrypt + Debug + + + aes128_gcm_encrypt + Debug + + + bitband + Debug + + + blinky + Debug + + + boot_demo_uart + Debug + + + boot_demo_usb + Debug + + + calibrate + Debug + + + crc32 + Debug + + + enet_io + Debug + + + enet_lwip + Debug + + + enet_uip + Debug + + + fontview + Debug + + + gpio_jtag + Debug + + + grlib_demo + Debug + + + hello + Debug + + + hello_widget + Debug + + + hibernate + Debug + + + interrupts + Debug + + + lang_demo + Debug + + + mpu_fault + Debug + + + qs_weather + Debug + + + scribble + Debug + + + sd_card + Debug + + + sha1_hash + Debug + + + sha1_hmac + Debug + + + synth + Debug + + + tamper + Debug + + + tdes_cbc_decrypt + Debug + + + tdes_cbc_encrypt + Debug + + + timers + Debug + + + uart_echo + Debug + + + udma_demo + Debug + + + usb_dev_bulk + Debug + + + usb_dev_keyboard + Debug + + + usb_dev_msc + Debug + + + usb_host_hub + Debug + + + usb_host_msc + Debug + + + usb_otg_mouse + Debug + + + usb_stick_demo + Debug + + + usb_stick_update + Debug + + + watchdog + Debug + + + + + + diff --git a/IDE/IAR-EWARM/README b/IDE/IAR-EWARM/README index f393cae30..2731104ea 100644 --- a/IDE/IAR-EWARM/README +++ b/IDE/IAR-EWARM/README @@ -7,38 +7,38 @@ In order to generate project for specific target MPU, take following steps. Included Project Files ----------------------- -1. Workspace: CyaSSL-Lib.eww - The workspace includes CyaSSL-Lib library and wolfCrypt-test, wolfCrypt-benchmark - executable projects. The library project generates full set library of wolfCrypt - and CyaSSL functions. +1. Workspace: wolfssl.eww + The workspace includes wolfSSL-Lib library and wolfCrypt-test, wolfCrypt-benchmark + executable projects. -2. Test suites Project: wolfCrypt-test.ewp +2. wolfSSL-Lib Project: lib/wolfSSL-lib.ewp + generates full set library of wolfCrypt and wolfSSL functions. + +3. Test suites Project: test/wolfCrypt-test.ewp generates test.out test suites executable -3. Benchmark Project: wolfCrypt-benchmark.ewp +4. Benchmark Project: benchmark/wolfCrypt-benchmark.ewp generates benchmark.out benchmark executable Set Up Steps ------------ 0. Default Setting Default Target of the projects are set to Cortex-M3 Simulator. - For check the projects, you can build and download to the simulator. + user_settings.h includes default options for the projects. + You can build and download the to the simulator. Open Terminal I/O window, by "view"->"Terminal I/O", and start execution. 1. Project option settings For each project,... General Options: Choose appropriate "Target" options - For executable projects,... +2. For executable projects,... Add "SystemInit" and "startup" for your MPU Debugger: Choose your debug "Driver" -2. For benchmark project,... - Write your own "current_time" benchmark timer under "defined(CYASSL_IAR_ARM)" in benchmark.c - -3. settings.h - Uncomment the "CYASSL_IAR_ARM" define located in: - /cyassl/ctaocrypt/settings. +3. For benchmark project,... + Choose option for current_time function. + Or write own "current_time" benchmark timer with WOLFSSL_USER_CURRTIME option. 4. Build and download Go to "Project->Make" and "Download and Debug" in Menu bar for EWARM build and download. diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 838a80e34..f284774f3 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -1846,7 +1846,7 @@ void bench_ed25519KeySign(void) return ( ns / CLOCK * 2.0); } -#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || defined(WOLFSSL_USER_TIME) +#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || defined(WOLFSSL_USER_CURRTIME) extern double current_time(int reset); #elif defined FREERTOS diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 8148c40a2..f59ef5180 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -153,17 +153,6 @@ #define NO_FILESYSTEM #endif -#if defined(WOLFSSL_IAR_ARM) - #define NO_MAIN_DRIVER - #define SINGLE_THREADED - #define USE_CERT_BUFFERS_1024 - #define BENCH_EMBEDDED - #define NO_FILESYSTEM - #define NO_WRITEV - #define WOLFSSL_USER_IO - #define BENCH_EMBEDDED -#endif - #ifdef MICROCHIP_PIC32 /* #define WOLFSSL_MICROCHIP_PIC32MZ */ #define SIZEOF_LONG_LONG 8 From 7584af3d368cddba89d07a94104db3e5c70884f0 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Fri, 5 Jun 2015 13:23:54 +0900 Subject: [PATCH 14/21] Adding hash.c --- .../Projects/benchmark/ewarm/Exe/benchmark.sim | Bin 0 -> 79551 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 IDE/IAR-EWARM/Projects/benchmark/ewarm/Exe/benchmark.sim diff --git a/IDE/IAR-EWARM/Projects/benchmark/ewarm/Exe/benchmark.sim b/IDE/IAR-EWARM/Projects/benchmark/ewarm/Exe/benchmark.sim new file mode 100644 index 0000000000000000000000000000000000000000..3a85061fd416d84ce7acffca068ebd00cb380361 GIT binary patch literal 79551 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 literal 0 HcmV?d00001 From 7433dcb95cbe59a4ae3a1a057ac418580f37f04c Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Fri, 5 Jun 2015 13:26:32 +0900 Subject: [PATCH 15/21] Adding hash.c --- .../Projects/benchmark/ewarm/Exe/benchmark.sim | Bin 79551 -> 0 bytes IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp | 7 +++++++ 2 files changed, 7 insertions(+) delete mode 100644 IDE/IAR-EWARM/Projects/benchmark/ewarm/Exe/benchmark.sim diff --git a/IDE/IAR-EWARM/Projects/benchmark/ewarm/Exe/benchmark.sim b/IDE/IAR-EWARM/Projects/benchmark/ewarm/Exe/benchmark.sim deleted file mode 100644 index 3a85061fd416d84ce7acffca068ebd00cb380361..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79551 zcmb>TbPQqu0YnuDLcmUt*{)y}PGA-GKRn!|9xx~}HW(%_DikDaOz3jsoc|rH-jGblVrP)JBf0I6ln;M~ceB=X=u2E%Jd1}`~-A51)lUNZ?rYz&fd;NZ9bB3Z#C z6PWybk?8|FgM(ay;{oT10tfh+UI!L3yne_~;QnE2=LS|c9yf*+|G%&K&!FM(p{s#m zB`91wet>w*4GgMkZUzrP_JC}$*zF<5Fo9tPqlWx#<{1n#8D2Xw8vbCCxw(^Jrl%aE zCc{MG+c2?CxELo~%n~kk^%lbnhMi0kSXTW1-uS;vhGB-rX66|T9R>xtGN7=M`OQAT z0u)y4Ah#9#w{YX!@BtiZj0!9hStqbfWLUwllHr5N4|WFT3m{YC{=a>m+bvTLNLgn+L@!8S%_iuyjHu}$?0J8hTRu(s2w>3_U z8$2&4WMpPEI*HtBlX;O*$iVvH@-IdPj{TsRwYiX$@giZ9Q(gk=t&LKi3=FTG7+61? z{iU4oFyloAgA${*{B7Y6%xr8I41X|HEBs)p4w5O8`*CqL2g3*92E!jr*$O|HvV~+} ztY|qH3r4@WsF~5_#C)q$3Y0XUf@ zc3lhHb=(({G9Dysa!NySUEME`-hjOf47x8rIP$qM>UC^jbrW}!aZ|r#>GuD7(|-mX zh7WTa7!(&KC?+r{C1*U$VAMYFX-WfwN|21=4<_$fPW$$Q=pY$nR>P;}29O9y=H+dU z4SQdFXavQr-Y@0}3ZS@UfQW(e0;2-MM8*kB6H7KStTJ>1rNFbGyv)IN0Tc%X{~X*P zYAxL~-2Q*J{Ljh&kxBli0hQrb;Mbe>`@>h}+nR0`ZVVq%e;j?yDqtwZeF4OC{K5W! zVLvP#OYHWLvq-SaVAPbp{R5PXn2dff=^WY#O2d{3f}r#Y7O8@YaKJ^3pdvSKS!6Km z+>wy8kzob@36{03FZdazyx?bG0JB(D@SkV_@mBo*F7%H<0pj)#TUasrGEMQ-*ct}AREOt0A3&pFI>Fm+b=!4#PyXY2Om>W4iA?hFhcw(`0$ z>Naj*akIazn9=LRa~o7@C?q6gFlw0Hc4T;v!3YXn2i6ZWc0R~pQ1+8%)MI$<$|QeV z>;p49+XbT^Os5roFrAK;sh9h4aT_?T89~#Zv@DEOCI@4|=r@|Ws+hB+v^Jj9Zqbw9%XP!c``7)c3@!rVEl9KCVu4y83sSZ z1g8G}{Q2-}W?@F9*HW__g5(4p6n=;aD1u^+f#HFt9ESy?rr_;E9gz6qx!u$e1db>6 z+fE%?U>4JDrVa+JmlqThI2btgFHB%iD1fGSP_9nMVA2qC6T9^wgF}(^!U~J}$B6BO{Nq+oy~D9O@S~{a`rY{E7!GFWhkE^KrT0j>Dgi%lN%w z28#tZOa}4ge4zZv4V!+j9XRv(xUkaPD%wcb-s zG2zm4lEDo+3uxQ%pe5dx{A+Zz*Ij>|Bt*pa3dSKxLMQ+X5$E zH`WV^ZvVe){{@9? zO{vaJ44PIK7!^7koaC^3UGH>ZWr${?&c5!3^*hwF z)bofrsQzH8j(-)wBYpua{;%J`&bf?*=@lPe8IN8=K2)vWD|U8}`uqkl2VGfETt2^O zw~^x`Bco!1!VifAg$zawmD>+85FyXB8xro4@G#y5PRWW10&tNcs0ceqgaK4TYwYxp zQ%Jb}965v-7z(!XxH0Omx*6Qo$jHo4kU-R3EFVh$Gcqt;1l3&ydok-SmJj*=H8K<> zG!tHc<7%?pqSr1=ljJ<*7CN!rHu}L7sr-W}62$v)E0KZaL&Sej&ib%b)Q#P3MFyir z=LQ}(IX6(<$i%?#VRFNQ3`Px?i%beEAGH6oPq?rVQuae?be2_+lDp{#I|D1YPA~Zl zsrNzZh5s{8FxUyI=`(+WTnnm`A-WkSFid1v(c;83k@W(@N>IMi{KLY)agjlRX@aqv zmK(!Lkgl!&S=>Oh*Kbgb;{IC!+@jEMWBkzemr=v+f<^|DhT83y84hxtG6El%ncTnq zFJ}0_2C9=!&vBK!7$o=eVgm=`MMeer2ZleGv}ZZ7>_?^9FGBdt7aio@USw3@egHDP z@2_Tt0|TQb^X-=zoE0b88Ll{NWB|KM(apk*@x$i7V4uK6SU#Nj0TSuXVAPh`&z-@b z4T>Emh5~m+ZPweTGo&kSvwQ4k_`tYB`myfI56*mU^Ea@%8Duc1Gipq9W54|&gQ4O8 zd&K_y4@?XWAK9CkRxnOrTg|nCVFKSOv6VtA{(rao1Ok%4sv%ZJ#1tTP!E zI2xEHIDBIC;G4my5q?{62FM-3SNK-)tzi71^$TR`+9s|Uj2d>gd1rD|9ALM)$}>Y` z)&wWk3tX#&R&uRi{IK_z?gOD&T(f66soa)w6Pi8CN#ZuwY{u74jH0ucUOO{&%1x4E zP-b`#EyFcuv6Ij(k&cZ&7#@_k@?JLl!Q^T5gXv|7>xWC=T7{oy0@o_8l|n0+9>7db z0=quDi3@Dk!=E4*r8F&n&NPEzC(8u38H^eSK7DE6oWTf+rH}6$*k`iMn&>2aYl;jg zWk382%_l6LkJx8%PFUo`K85wxLTDS0<-_g2oHN;G-2EYOfbq2h1A}st94MCyxba+> z%?xsx^Q$;!g&$0od>6O zfQxa##TYc0_JdTiO}KJ_=>gjehMgP}m}W3)sNQA;$AjWkmN_CbTAWxfFs%|=$+Uv; z1N$$L2Ot*1hok=lJ~HyNTws|3kz;$10O~97vrJ%G#k5jr1>=XK;MhCY$UK8-W`~o| ztsWWH8K5u;|I5f=|D|+2^DNd0i=3EI!Xx-E>rAE@cYkn@5FQ{G|Nmyb9u^`D8ued{ z*E4}bg=xb7Z(1laYDhA&C^C{rG6G04O#4A*F-j2|j~ZhgS0!M-2FV_V6$g5iS^IFw#qfaqhrz_$t{&iEnur~U)B znS8S*I;q_jbOWUrsoR1x`DXEf(=8`jy5%F7ZUrXrf!)CL0A>RlIQ01&d1kQ8>;UH$ zCU6Q?`>FqcX(kucW~NyaouqE_&g7Z}$uX>GHWQm;n7}y(V#7&r9=X(z_ka(a7eGD) z`BdsQ=S;R)Y+xS>qS?bn(1#oo*uY`O^Z*vxQ^EGkYhand1NI@)DlTvu-TFiS0oP2B z&pB43xmGYefY}i7lZ7GiBHs*yjrB6_uK&L+T$}%a zi6!Cz#|%ad_6uw?m^4^!an4}qVA5c?1nRppv3NaLo53=JQN!foh73jx){9K54BbHa zDgKAX1H%lETjg(eIZ1%r33lbD4Ahc~Y5r~}zFXoQJRQrOxIpDrrO^*2&*e@ZFF{;q z;0AIX#7xegEDS;yk3VNx!GA((9fL~S3x0-~FZdal)`3`3EBH_Nxq(Ycf*80QU)UfCwuRy2oCdL#Vk;Ovy!;1pkx2`vc4CIs zPHb0%W-w}0+!h6^Ex9T)Lttj36YE93RZ`$QU;1DBffP7zE8P}!lbSWrNfIe<%c7+} zzImIS_-=`H@OSKk#B8R~52ng}P9HBp^0d?nP@V>v%=keD?8~>!A~O`gDPCxm+)AMp z3?FR%>phU0DKu-Mlj?0jH#xA4qBDhN34zm+BASgt^ENvPLTv=sfp8lkb)d)up;baF z_s1hzW@%v;Z4p9&gzp*3Q5BR9CT z5xzA|rV!ND`^5-pIkI&;=AOknVUrX0G{mR}%ZH#}yfe9GaLogi=AinpOisX!8&Vrq zI=>1B*M{sL7q3wy7q~9un!&J>2V562 zL+e7eE1-JUkxWQvS)U zVE7;jHse(jtX}PtVVwaA+0{Qm^=c5fUftxxj1sELe}d{&CL%)>RHGt?DyaTr)L=ph zRhSrZsKUfhLlq>-1P)b5n~8k}8@N5tC&LMLw?Ek3-`0WJN1L43QQYnQ6VyIpBhuZV z82bNh_c~D80kw@lErIRpKrI|l`{@6-btp2ckYpC3$jn8OnSvw(Yb~9+(EUsTTJ5uEYc}unU+Tz|3a?=g-TH0?>8<-zp|>DW&vR?*S9I zlme9*pc)9dltOO@fJ!NRWd@|I0<{8Q<{$eDDl?`xihx^8tQUk~kL0oYavfy)o;KY9;@z^yHiy`Y*v5~;O?-Vb6UU@xSs0ri4l=HCa` z(;FJZW`Ock#u^@QONR^G(&2@+bT;hH|G>mH_W`H}4=NWm-9Y8yyWbiQG_kaBUZJ;e zaMpv6P|yIka3E&R_`}AKc@fl}Isxi|&+Ks0zTN1A9MafKmxR`NqM-H@yv_r)l9bjm zsKLf!nZRSQO3<-bvj;3QS7l5D_kbXFxBb?7z%*-ulhW-bP zYmN0cs2#=h8`Mtw|I5HleZz;n23wdixHBd@3EiIMBzgNl#>otjn?OC_2DwgX-*>W; zz%8B*){Zq!OqUGyFe((d8~kAMH2lF7xyI@JC4)WwAO0H@xEt(YP$+OO*vjVCv4Pi3 z#EnUT`9tA9<_Qwek@o`VYzk!DonbYD5~Llc`Gbvt^#a3+f8V$MGH~PAP_UP2#>$Ki zC$<|TBGe68I4Xxw>zA~Z@jg(Q4Yz;a^?$RwF+5;U2hCNyZ$ymE9{BX45i~;1{DJG=qlXL%pjIs3YNl0e zD?#zG<0oh=8E)WTtqx0kd&Cz*se7@Kw z#kHc)-VP>q z^%kV&2c_txKN<8GK7MK7n87m>G^Wjbflw0G~RO{9Wven>NlNCM;q?})gLe$ zvcO?@w*geLLt6Ea`m*b%4z#{hzAfkmsxOgy>=^as{M}CcaGSY6=?`u*W?g9jwsUa< zD7WqUBRT=pXJllb1)f=ER1lgdJV9h4+X}Xo|Gr=U37WYCl>>}FyB;tqg5vevFE*69 zRyOdcl>BYZ8Ei;##s-cvHk3Gni6O@sOzi3{NP8Y+*XbWj3JmJZA9DUMXh=@jaDlyn zQ9*oy*mQ~MOyFK!&ri@yJj(@8{BHdb?q>UdQ4v&1E&O%=*}9CIKR6iLoOt&8e_-J8 z|G>zzWg{r(^M3T;>wCe^z_)_`#4xMcX%lv`+4Yy12Cx&J@(CD@kLz~>D zkBmG#SN1a-|6qFQ{wj`L?FUmO-v>qx(1@M8+o!9rnOEiykAH(^T@mpGnp4zB&;-vZ zf=q+VfI#LoG%@BiG%@BiG!t&#(#T-g37W};&1-PGHD=7oSm?xZabkibXf1)G_5;=o zxr}vAinq5qN#8z}aX*9YwJRI@YghJda{J{#;mq`aVL#7DMxHgU{I|CMV0f_Y2SdX# zSI*03KbT&c|6uAo=KB5;quZ1O2{*mVSNRZJ;U{L;*apMP1!;1_?y*X}%x4*OVUN!o`WNq<->2$IS za|0+{v3LCD2F;d$=Evh-h4C?bkZS&l5=iw zhw653V36JSk&*A=#br)f7nZnc+*$7k*`mNFjD z+ zrI~T`2SbDZ2L`@h8J{y=WH9P{aSOdI@`0I67!(H8#y^-=FMrL&zWg;GJ9`5tRk3&Y zzq)P*ikmVyg&$1SuP-j)umP#fHvYj>{Y`q=Yd$u%2A+>BJZv5QuddmFLY1unBxm%4 zDH|g1*5C%0b3>DBYiNVZwV}x!Yd8j%JJ!HqkRo^J;t|(|PZr?VS^S!h8I&#<*_b=- zfMd{LpEcnlj7|)P7=3|X57nQeeJ@^ z_S%JQt=u*_26cu9^)kzygl=v7!Ej*f4~7R{TzM{={$M%@Dh0l{ez@c**XekYe_{fo z8>}1v+vjlpS-}>@jKC>_WU{J_lO{_TG$`vta+bxs`ngJe?V7(OyF ze81SuA$)`RBj(t3)lk8%M^DjgE2$Uo(o$n0Yb-Ho_3Gu?)O=3PiGA0Fg{! z^7BOwJ;qy1s_YL`^>*xMR%O23tG8u8iz=%ssE$AJLwqHJ#)(9y3;rJ%IT)0f8W@v9}EgF5;PJr z5>_On$OxEjae8%Idd1)Gcm9B8MtQ$V*Y17sp?}E?hut%09LQkkI0%^!WO4Xt-O?z- z_<@BH6v_g>89yER$iyW0o9Uy#Z^jP|a)Q4ZJ~*&A@T~oz!Z33NLxv-RrwoVYw*4#` z{NH9;@PF&%D1X4H!Fh4!jQc-IIzT2L_{!h_Ql0$(rccvMzw;W%(zb{o&9c zI1ywH$4&+n(Ffo#7nz9?<|*JX2a&87KqM2G{CrVp27@AFfnx!`!j#`1z6s1=`^d=Y z;VONL^CJ_N&lVq^H^Y((1ak@vp*cr>K@)7pc#IlnP-34 zOi+*l#f;()F$VrsGiUOz`2RiZFAIaje*P5>A67LB&A9(#PCG*f$WI`XjsGwyFnzfC zp99j8W100B+l^Jb>=u)b z;O%8Hg$zs|7XN2tVE7Q($T*96!X_t1q;WN-5A*+9WU$WUli1?4Wxtvmr(VOSWeoxf zOdqQMvoJ7xuy15gU{D0DKDpAMss{n~UMw#rRh< z`J_PNvu%Dbt>pU6$zc402`?L@7o_gVMQ4@++@3PgJR6;qelS^Yy4~`CLyKin!>5N0 ztg|LMt=KQ<#-iEq=~e?G3>3j(aJ>Or7|24yfMv!8CzV@lZXo~v{s;2^{sxHuLvEAq zdzJ^BdN*%_=7WMBfe~!68KyBPmCG>CVANN*E&hR-N7;=X z6wctafk85$w&?eZ`#FT*VnVXU(3OMraxfN*esi(Qi5uKHVfxVd4^dZHP<<_@f*aEZ z_kX(|ERjiIVESPFj}MvyHa}ocVASEBz%zw+0`qOY8Ho%`A6)*i%;272ks&&PK|ypT zqh{P~mYKgY_-3=t6X^h@(LSdW`}siYgE<-X+24+Tb*xJ8s?86k*`QV}=Wmvu zlE3=?`M>h>^nVrUss4j$w*RYpmi`|Y`N}vLK4>)9{9xL>{RhJW?%yoGrGIt(lKR#8 z)BlyHm;b9MFZCZxtNmZyw8W>TOb(`s?;{i6^^13Z2pr&h&A^i4x?}(H9}E*j=QzmB zmYF2uDYw9B@onxIj2fD^`DSp#`)QiHxxxK3?uoLX)j5oy-v7;=FfrtHvM@1l-wnKq zhe3m7zlR+6gv%G09&pcK*vUJAdj?~_ z2G$AEt7gu$aQpZD=|9lQ2<1kumEtQnI~ZOwid(vYYL`0jJhXTtgWA%MjGO`wEZrDC z#Qb4UWMSBu;P8RFaqkZm1&|2`+(G)88_Q(;T)A&qxG`pUF$BqQXzkd~r1|6)NLTRh z$IrQDxXFO)MscABR<OmwyysVEmx-1Elw91FBhf8_Hw^%t5u}%iA+%Fk~>OImr2c zVC3H9#xh}}8-u#&1CUAVf~>1pS1^9y0-JFdY6j~HhWpf;KQeMFTx6L6 z8pRjB$fW1+VM+rie;@cXp@DUV1A~JMhsK`$tTUK25^u4t1ey5zSHgoCGY(|1%ry8R zxWGe>WrF_)e(qDB8%#o8u`&3+^5VL3fl-fRKZB0UMN|`5peEe<#ryzb*5Tiv5M!TM zbP?i5i2JfHZhp@Bk&$!hYfc81Uko4Eote~Dx~{y)pvDi?w;ZZ33`L*+#WI<7PW!*r zuSd1_3Dn+szaBq_*xL@(Z-$~@|6)CZ`!CiH2iSS9vaXU|$-08!L)L#524xggG8cD# zWaO;>Qm}r>41=A>?&iP93QvWzX7Hb21*b<)8l5!<)URhyVO{a}`-C5$^wax;Yo74T zJ|{7>b`8@9+drUo4bumWKZtfsnT+rZ0n;|8m$wz%U@e-bW(*9P7NEA=2Y+5S&`M{G zj4MAFCO}sBO>hIPs{H%C7Cfex->9I#^x?;E(0B$1cx^Vrhtx(j$VyASKsP2gdC>Z` zY{wrg+0im;8JnHNL9KoyK0g|t9gTngwpK!7d z6qL#6XY6xQy>;&g3z9esR9y1by&oJ%;v7(M-dp#6@W92(WX}EIDd77kzy~tx?CszT zu?*(d*NlS`JY}>qgk)zrZNIITQN~av!}Yq6$y;Wg6W8lzMuXdY89_f-s@Yy&H{(l) zmVv04=cIDm4=(P9Brb8g4=&z^B+hgD99;Zdf`B2&oM@RcnR!m4b=P>hyg z)Yby6oabTqz||1+gC)C+#Z#t?2UHh=dhK5?&gPK101=1u<2hxKdDz&|pdM`YlZz`~ zGctL)?%5y6!1UqAFO7_c84fZG4;=$aYsc7oKy@!4?^W|3Ot1I+ zU`XKm&79`{%8d`ypZ9+y=cn_7DLejE0Ef~A^B+vvY`>Y`fmF%;Y6I2CZe=_mdH+}U z>_D<{&SJm%{z2ux!A#llk&y#t(w&R@J~HrIUD)%3!Jyb>%?}2H*_-Zj`@eE__J0-Z z4C3ot*z<$Qz}jWa4<SrWmR5Elp zO>pD71&Zk({|q*Q#u6d={(XP=??DEmKErEwM$ky1?(JXf+*b{MFr8-V;P}l0S{LpV z1R4X=_J4K9rkX<*v`6JNTL;H)zC5{KJ%9XP`9S3je=tGCK`Ie);2Z_k{SY)VcDhPN zF#|LCuY61f>{o zyY0fpdKm`}@e3eQ1WXEo$94>LeB zW}um~$)I^cr4!E$e=wZ{jbeXsJ$Q*>#h>rz{&=`Se4_jEgA@w2t>d z2GfViAK+EoOdn!?oP5nG$f%GhrJm5? z@GwL1ha>|yT$?~U4I$(7Vs4<3`oat+nTbv!w~otv$f#ss`d|t-x$r_!#)pJmPUQ)# zw{}9;)iQn1|6!Q1AY(&<{|5#>^^8XuA2JyAzqlFRj(>H$LfZ{Ic6^%kH_uo9SFYe) z4WNB4{;#gufyR+*Ib=a&lhyIg;=lU7`@eGc^M4iRr|^U6^?z=oA55>AfAjs5`_+yj zlPd=r;RKB@KfK8Ek&&re3Z%ZvY0v&h2F4FB{wrjB%y5tag*2#+;IL%W5WIb=qY7Ly z@Z9d|2m-U%Z+mrUfmuwqxxhP53=$Z2Zh-Gu_~Xy&*1v(zjY)y=!?ORdlqLvDY5ky- zh8Qo{l(7;%UcfogC__8rqJ)nOXtdyd!(^u|`{mul-B|S-KHUKKm6yv@GBAGV2KSYB zHiG)fyPO!OBf^vML;HV?48sf#i590N`&ryLbs9c>ZV*sl{E+;goq^%Q{6?d1*R{j55@DLP-4;v;s?bt8n#-i2m={8afuKEWW z@wovW?Ld#gW&dC?D0B-Hb8Y`XF?Xl|7IR_Xm_x)F>jO|czXXqDq&<8Ejnlyrk1J^y zkAgIh$Mb*pJXkJM!NB<8@LzW5c*hpdc!xgA1lH+n6PRza&j97fGk;m8Xk>6qU{K(g z$*7rd`&9<}Y(=+gKNuQBJFflUInd#{Vt)sy&BY1IMW7K6N6>B~lo1bBoFg9buOc`Y zK4>D1d9V^O=7FgO)Fwk7^|*GC?==JKQYXlW2gh94h{p=2g||U#b~JCZ&tO3s@n8Xu zc(9<1c)-MvM?7F+=p!C1;1Lg&84NqwCV*CwKxTwNy-5~uzY;WG%m8MwtoZXi6+Ys@ z2_Es#*(orKed)rZ;kF^;#t#mG?hPHFF<1rANUn$* zXwKO%!$~4YM%0Z%x8c*hhDN6?`?=ki-B`67K3#7}$XMYdbZfoLgA7ny-uVN{o7);e z_24e2bfnsf@xzTj2B6tf0S<{)rzQJY-8gj{K79d~ubcmXa_MZyc&u)~ZU0y7OgDZo z7~J^5bKn|$M0UmgKDW;VMr3I{4!IIMCcELbVuor0gHpE4gA8c-%4X}vcER)qQ@6qo zrf%eY%cjsWS4bAdik5@1VDy`d-BMjnT(>~AsOuj@`3jmhr%pQ%RIalBS@4iUi(yj3 zrw0vRJn_nrq+Wil8TKZyTkft0HZ;Br-$aRSp+<_XNVS!QH1Fn&<@%`k&;f?1K{uAurm64#eJB(l!`wIROs&1fl zlZ-2Vf8Y6!K>@Tscg=pbnV>!Y+~8Izs14uX#tTaK44Ke2{4wzP2aF$r;p+{Ou&lRX z{NVdb6I3cHfL7ex_`z`C1t^CY?D@#Z&*o-xTjm2ZA2(<&!`uCp3wW2T+7G7c<=mjw z-{*_*ujcTmUXba4$@#yUVh56s=~&L~_sWGOg(ZbY?FW~vkRztin|#=_T}9PF<>cvijU;Ntwq$bHKd)Sh0k|CSraM@EiauQT{p?Dv0_!L{on zBR~6VPd=^NQXiN(Ky7Q#EQs9?rk$Yrn)^4WF{o`li$m%HR2(!HXH19<(#!Rm)A-3n zhS$yvr`cJqD1KmMz8%f{o0$PNJGT&A6D+)KkOA7ms*%8;1X?4ab(>)}XpIPXPO!S3 zB}k^82eKOE+r=du3?HOH^JCedks{E@9As_^#xwrG1ebxaQ=sE;ptyk452k421XNl> zGlTKN_aCtFG~JgU{Mp=EHyC6vOmJuTE5qXkDs3Ks`q~_@@#32e%u^W@7CD6Fplm=(H4;hRT*xcOR3_7;|U^w95Eby!6YX*x0PcDN+gD%hA z9}E*fD=-3NJY3m7GV!_IVw?e5&)Xmq|LSm+&{cyUOuP4i%N3sA{;#~bLGx6hF8;4v z!LwAk40=D9R_pS_zY6BmxPV_RNab5@Y-*%_wSxM_UbzgqJfOKR&`3T=^|gz!oA>=- zU=aP)@HK-am%)KYmq+gh6Su+zsOSe*mRyiXv@3%yk0@4AF07)LFEY#slChWFCKD~! zQ{pc0&e)M|W?E~_C77(N94r%n5S;e+u1{SVg5R4_1nV26*Mz(Zc2VFKfHP@ZL;QOUsYf$u-VRD%qb z2@DD>GZ{6LZhy*Po~`M|H4oJLy8A=pfLO;JtUWLXj2;*p-X53+sQiV_IkOSb|H4!Q zDw8q#Uu^53{V$ezu>RKur}?)*bG@1%ID|x-%D;yhpc4la5*XFW+t!0}12r@Q# z_6JJ?)5JM5Htd`@gCXOMAillvQFpGs
      ~=LpO#MzrXwc;@HUIcJ~2jjSgs}X5x&)8GN&tXDoAD;+6<1 zvDq0uNPyO(t~UO`w0qTSZmw0Y`S=$6V0ch3x8VoF0{>UH?EGJOf$MjLA55!3Yigfg zjDIzQgW-b{NMAK*ofYz$TNWO~np<{I%W5@fr87*0dxJZCMXo!BYv-jc_S4+@5w>5k{Ee~_YeeinPE#TF!T434R(%`kWXmT=m8(@&7NbR&aWzMQ}VPq+WyAN~TZ;W+t&L%`t!f8)fN468icAgfF` z8p~w%IdR|eKwI?!(skqK;g2G$UKALL+~$V@QDlz6CkGV1?yLY>i_e-A2id+A$f5@255I7(*;Hi?u$a;onxRL zHfZg_pYIjm9rWxMATy^9bsMvb7`uQHxwFunF<@^)MJnv<15 z?d}hr1L_^!PCTzYd8WBp-HLy8w2JSl-4CYKpw%5*zuA9D{b~cP@Br6uIzO0Jf8&mS z70SWzLAAl|2h;97;Jz+9v~7&85|@f^+@O9dsCELGc-^uRj3Fl?(V)mMpA{&n&F^8$B< zuMY~CGA24PUv|!zB{9*7>2gB`gT~j31@8BMM6fevOx)@JrNOW0I?2#>%9?2R?Fu zdch0~uNgU*pt5WiKrEO{lZ2?-($^de3tlsGGQZ~FcK*Q3aN-9G!)jNJ{fr+H{%KT# z&WmIG5dClGM*)6|{fr;N{%y!?b>h7EA;ZJvL&C8i5*r*oFfyF}!NQRHupqP5iTmP) z3=fwL3CDhjfMgg?|6mbt_`%H(_b?-a;R7=xqo%`$wG9V24lpoIIKZKxVRh;14~_-z zGZ-f9b>i61_(APos4Iw8`j?TxFcYM1!|Q|m68jlHNd9A(!S?z91H(rR#x7U(3x=6p zt_MCeHQf5aBe2q`_F}jz+eL<11{sWs6CFC74HC*8Xc)9Rv0gC9Yqij= z_6+l#tRDp!*fW-IWPHHk#-73cQG}5zgF%aFKl?`kFzfS0kO@qe859{47#}cxIP!Pb zM+Sbg3okO+UNe4SCin9=LRagjY?`Oa6F1yC0jB&a?x$ZT@uxP0q}0K*C=k^QHB zh!mXqAy5D^W6|I38$m7?ynOtJ!~)Gs&5eytYWpn{`x6;IO!=FUX|WMvXGLOrB1nDL zU&a}(l8r7I84er{3>gXjuWqt>LSx4B2loU8UFAz`uaAO4kA0ULEH?B18e}N^V*PlM zo#hIn;z|b&XM+T`2RpzaqO-rrjqyX=-{U_xHk|swv*Gj)js>TG@Dx-&h<_!i$g!V6 zLHWYQuMPGZ`{fnnE-n1pP{6>$@PUJ&(P81&h9DsxrVlJk6G3ceX`TZg`52f#Fflhs z9gv#o!0`H_!9iKgUyPraJ}@$Zc3GYNA;Z9+boz&g!s#CZ3T&?%7>hELeldK$&Cd9B zMj`tZMrGz-3?BrX3la|gVAvr0Kwg70gKs~Bf&<5akCF_WzZgC+JP>sA%DBXFiNVWN zfIG{|grlDd5O2g8QbKO_WBL;SNr_<>PoN5(`ajr|jx zxGx|0!L#Au4-Sw|8BYJ;5nxa_{X>EQ6uP(naD3!o*!$vHzwXOlzN~Kde>5;NWVCGH z*!llE@4x#$3Yb}DHe@(T=o>o7DZXN0V42zI)bL?NBkR{2Wg9arHyUL$NHjS$e3;+Z z=yc%2oJPhETmLX<$n9rw1N9?CJ~Hw%e3;m1kWrZ7;L_-1kYKT&(XB9HMP|cpjZBV> zElv!VbP^d9J|vnX9{VBE!1_^xalZ#cMn)3oJO_;=1_j2C984z@1QQx$1Pm24E+tG# z_e>k3PPV}_%PV}ha^%WMrd zHc&n0yX5KmOvs7N34a+g95Ngvm?r33Fnr`-6#T%>$a(?9I{1-;k?{jNBZmYir*$}) z>}Qw`I%Ax}fN=uLM-E1Y84MpKxIpUtKQM5w_^1Io8}uUwBTOHcq=VF|#1{z;9~c<} z6B;Bm6de-^Js2`yBr?tbm6V`T<=tZamIodJOPk!KK4Uq1LKSh ziA*yX9(1{}E1mkmqQLc$g^^3P$%*?TBlnlfyFW7V@7T}y;q-5Y89SU9KFn-5Abn8s z2!~fj5JwP$7ue>?gad&JItrIqUmsy){HVdU!A(E|RFZD|t&ySdiv^nZ7CLY^Yb3Be z*pQ)_+2N$Kzrl_1!-C)26HY)%tcHIHSq~VwIQBCr!E>FG94OZnfpQuLB&P*S^Duv4 zVV()fbuKDAhd%N#v3y`+xg;edz0iT_^+m%|vI@VLJ~Mw{WMX>l$n-0bLAg57I+68t z6JvIU@-L<@Pr&(&^$MfH1P2M{j0FA!nFsP(;Jl_3#Bu1OBoo6grcVqHB;C9-Zgbpb zXm%2~aG9U+bu%;bM*)@~2IUL}?GG10=|S+adcw}c{|WmO_#SA%^BCLZ;|cu(sTT<=Gg)Q@Nvui))hPi9EHfNFFf({0ux(%j=e`fU3<}`X z)62lX!_A9 zen?Hl$e%HPBjW=>H-1n}#UuDY&*HZ<*81xohc#+A1R7-JQ zWKXbQ5WM&*GXYvpB_vFEu8`U0#Cq8v6I4r;Cz^v}F7OwFe)9!|%yy?Wm-i*2)=MT*Dr2Z;E{zkKTl2ZM)e zHatEuK2&1+$B59yn?Ga}5OJdX02U`6t|I$kank;C|3*-Z2wmQnc=LyV0CKCL^5@MT zA`BKAK{3JvjuBAJmiH48?x3{Ea}g9Tpm6rUh!_7?H`o>Ql`pZpJ`TzeoPKUQpshmh zp9&cYzu2K=*-i%zXN3gz2cR=SK(^`ZXLDoxVEGet7UkE3bqPm*@Js;N5dTU-fnz^| zqVk0ekamQk+@%Fy8wxpj7(Z|@b~r46w<9Ki*v`^C2S4&Lg4z+CQYWQmI557xU~o`Y z1JRCPWKhaV)JlAr$nv_8At^)Y7vtyK?4b4+8@L6*_)*X~F@Y6SrfD*O+7F7J90xy2 zGIIQ4{K)V?z|9HVesFT-zi^750os1>gti|PGrOJmFUuypO<0>C_&_PMF=K+0#{P*; zte4Lwv?jbrSed|}!1`eCix2LMACBw*`EErbh}3=g!I#C2L9N3LKI=4F)-*eWXkMscd~Y4(0G1P!i_=0<|2ch%|*~z=MD^xP8`mO85|A_AJQ8goj4pE zUK#O3@&9@;=~jbIbtc;f1d`7$aS6_IJCnxiMxkXnwlrkjbF&;Ua?`!v}-L1sMxo zb1*c!Hhj=(1f}!?A5r4*KDjEPN4dm@5ef)h7V$m-!rcLkXW$YiRZ$G z3{aW_wdXg2+w&XY?Rhq6d!CJ8dmdy0tUb^0;m&_hd*0&02c(j+&k0geid_7JR8p!v zfR*C{3>#2d^b8+%{)gpFP>bFm(*T?k)%IH?wkI-tSoOak6E$x#d|2>*_eTMKo=Y6B zxfwt;VL<|j)gbAZ;rM}((J^7#1CI~P3LJaUNjcc+JM`;VQA8;lsjzajp#?wl#du*qTY3bY1X|LDvLpsun~^)k+T( zGFzQkFKc9i(sX{JJ~%uB|7{1?HG-G-CZeZi=YN=~+4A46j{^Lhmps8~mh&|m11ufe zL({Prw7=^0gL}c19~=$-uWqm^=xXd|_#picbUu{&g)2WqCNNB8f%Icp^`Z3-!w2qv z3K(y2#FYg<%$G3;>eSSAa_co&D@?3?F{{J^F)V!tozG6Hfl%C^-3pC*a5r zjs-`4h-`qQj8FXxAD;aMrHoJgpfy0v8(7^AxE*l&s(b&(8Lx&9?2X*IhWiE7SwC_! z9OwAYpqTNGL-7~e2T)7X>B0eLh7XJkZIaNI2FG`X8$UP#Ag#$APM{dw@%QQvjtQ== z9QzqQZ2Id9rq}&NRBtA3Wf8;fWs{6Hfl%X#l0?iGSTcFf(K% zR7i4|!b0-zgM}G8ofBny7_}60hDqN zFa&^8tjFJLKR7n{f&Jz5Hx5kO{Y6$`{`V%>f2_YaK7v}!ApbSHa$LUsgNI>*6U)Vu z;NCaS1d#s}!Tu{qSoNBnV}~T;1W-GLai&KC;|z}<3=PXO{9j$?+VxR^ACx}0|GIBJ z`-5Qt%j;7N;5714gX^-JfWF0k&JjiHw;=Oc0dST{+ger+e(4Gq7t>JY~% zc8=F9oMu;)Kqva}Gki#CS|ZirG{NP-huEgf%pNC(4>uaFaVY2&T)OguXTkD}5OCZE z{Mq9KO3OZf62LX{hS#7z6T=6WKdeZ7Ce6%#r@+fUGZs4eUEJkrdr<@0XVOUUac%gZ z+XQN>A7ppz5lMvWYA>zz|r&~LsLU#Kj@r9lfN%AUuJYTHGKHn2pT7Ok@({w zq;0PO?`thU>T7L(&hX*+?=8=tXDrKH?!dt2e_L1PEA!EO5hl-`!t`lDESTL}psKUf-aA7*BDx^i4xk&%<= z;IabT*Gf!a2uyqk>OuLxx&Y2)4K8M&-c|u9&x3kd3?Bl2Zv>|T-`}7Z1gYKd`V>E? zoOAij`uY^8lwj<0V!NQ3+2;i6ZG8mywzfO5fl~nEFRqUr&KmGhT9D5`qqLyj*7t;c z30X)zEnZMhivi>}P^-?<6*Nlg=?WXA<%G8CI0?4uKqeqsbsvAhdRvG%LG5iJVnz7@ zELIS`Ert&le(m1~ayMpgi{ZneUy$Aw#7Mzi^5prKk1KQUD*#+urF??wLb@B&?!S)8XxD31I1IX=Zji30{^-SdjQ6VF`Hj2-eqP zyL=|0CE-B==#H)h;5G>VFO4h*IgKRli&uY~0FOK}X#BYd%Iz9Spz!|x6IAv=`e8r7 z=R#y>C}fJc-Qu{!An4ZW1R6JFe9g*n;6r{R^9N>jMtz14S&go)4Ik1QZ~R~>h<|mw z&f#NXqwoi2e*TLeI21Hg_8Z7HIUV>A*?9lQ9;Sv22Zo8#9Zm;61U7m<+~_2Axl39= z>%a%MM&=KU3lB{LE{GC(6*9tlq1@vHy|=L~0X9ROO%w&0)M!$p}BT*WRv z$Z(Kob87gY4bshIH255{2Y2Jq6gY8d-87%O58;%Q#;CY)4@Vt$qtHX!p2FT0}Xe9AR{mi;1L)H_y`OKw3Ox`sg!>H z1Ju*AzHkF&45kA*1|xd$2Fe(WI#O@X!4-M_hT+4ZAIHJ1V`1?8%?*^X7={ma|$9GAi64a9Pe8m8bAI{gT@V2tV1BfhU+VTdcE$-Kh3{K$G;*_A^7UlNu zd%@q;ZlJtS`6I$@?~70U3=E)gQ_%S75AeN}3~DMnK_mHXzu4T2z-=1+OW<~{8mLWk zjN=;vC=V_9$idF2Y~*I?cK?S5!~gH$|JcB7W4?_XX5tS(`qO@~F$i6#0FS%!?B`Hq zQ3TZqPExC!I`(V1DS~eT3HSk8g}L#!f!n9O5O+982z+2>=D2WDO8zqV_NpI@x*Gcx zelY0@GZ<_UaT9eDu+-SE@Y06i*9}j05Q~SwW52@>7Trz;h&qq`3_lok4fYhcpOlaQ zvrn^YfawBvMg@isK|9zzIWjmlg3i2V^8mStBZ1WuGy=gX#h6gw&amHsn?b>!n@Pc= zn@J&Qb2mH3g&;Y>AB@%vApAk4p_~2N#b$Pg4+;$o`vt7nFB@#x_`*U!z-qw@3xS`P z4E6-GtL)$SfxL7cCJWv za0auQE0P_W!K}j-$qt7LK<2SP&C`7eTK96{#|MGF4W1kvnk*Ap+(0cpP;2m4Ba4!z z8}o|)-$nkjC~3+vt@!_)|38ZoD`;M6#sBY|U^WjUXbltdf94sCT#O(73o?B8FW~r! zL4j!|7Z=lq|3V-!r&o-MjI)Hfm_Pg%28lVpVp3w5Ez8CF;lC(I%=HzsvT8=_D+34S z2?-euuM8cSCM?KkcxB|kIN?D?!z*J4h6(q7OyDqnz&k(ShgyPtMx6uCd=Po(2SY)* z1NXc-2j*#9^8sOV4W4{z%Y?%7V}IYCLuo1I3_1wzz;=%OFtM?0v#A< z39&##Fa2Q92y|drB~$@YbLj_zPN0KQX45N1HpW>@SoJc%^%}E4bThA#=7Z>Gc-_nl zF(V0N1}DQTMyzHq!_8p+%8(2(g$czCi$MB0m}fCy)z1Xi57EnrqW2Ll zhS#mEtX~^a*{Axy;&X-Z8B#f?`oH2plIH^PU0G&ARCvmrjE{|nCgTDVOi46Z&l9}~iUaw<# z-NwQT+KG_E^0gs^?MpqIN(Re^dY2Lh9*}4T+n0K`5{EfI7*a|cxaXBPsBy7<_%Fut z;lGI6D;5?1S0*mZQy5-%vVeCpV3@&)WX5c;85~&6V4A}4x`Ty%-sK+*7T10-V3@=F zrQSK&Vb%`@mt+UFImr$(Tp$;K@`TGPW@XR_v;Qk&XNIp00gRIwGC(Qh;tvK1h7a`) zOke7m0vs5>)H`}OO#Q(i;^DwL)58HZ5Bk3{aA26gqQp0YdFB7_hJX2HuqZLDWRL~j z}NJhyEOc|*8-~W}7 zlfw@dZEWJ6av+(f7eVtQ{GaAHb6?o;QG(y=!j6v${0txZ8}dJ_VF2#}Z2pvS|3`($ zwI2)z{9iHYfzpBhmxchw*L{2eKlmQ-eW>^Ad&R@!|BA^EBnKD&QqKnxkN?&54@nHF zRw$40bswWcOz;nNfreK+3?2>!iS;st86FM=i5oLK95y5dIDAOt(wEpTV7Bk#(FaAD z_kVm5rnMV3K;7^G>;{9Rj~N~g9Qp-G3?Et>3^P3(HY5c&d`OZo+y4Ah=1otKYxqAU z7zh7QH$V@WdKp|{!>$jOAsjk<0zdd3fI_hO6%Vs<(zPEf2SBXiq-#Goz^u(lptBc1 zVxN;tF8IF^28Ag&POgDYdxXaeGdRwW;s6{k{;!zf@pXF>$W4r|n;H4O)cZNa6lQ|# z1;vX&vWG)K@ zz^?@POKh(jnAl!7GK*(i{=snI&<}>!3Lxj6!yjm#TmrdK(6`437ctZ{^o?wG&TQo0w`|gJN^G+xn5-_qEs>6D4?Y2 z#`5tC!~gHoez83Ou^1E?l(^k^+~f{G_qjHoSPVLWiGh)Ufq{vEfq{jAfq{d8fk6P& z4rE|paA06yXkcJqkY-?DFbi1zB``SEvF`8^aj9u>>Q<+-S6hE{oh!dO;@6tV%#Xc8 ze;Fuz%Pm_wvFuETst?oGKi8l7Uq7vNw86zxt$%USR?n!7_tK?zsm|bg<@)fzzgVVH z{lh{Zd>R)|ck4a&^K$m{_7)RZu7n?mlaDQG&3J~x|}%Km(_Ww zw4$=_OSWCa%)5m<)wlUS+$X-a<3rjSg_B#X&eckI-A`^ZlzN(A95~&zJ~-(?dCJC? zb=kXR7Bv2wqRsI$BEzFV@~>-ud(OQn+kaFCDPJyL{fNoCD7;_(vDWI)GGo0t!6 z)t^;;v~4Me`Q=aT8U~w|?pNNG#mp4bB=%NY=6u(rEtShZd}9B+@KL7U*)O+JukK@I zlTR|a*!6GOk-5QoCJRD8FEV=A#ajCM+Y-w+&D^WrCpfUpFN_Nm$lLp~OVQ4j?e4U7 ztaf+Z_CE97+8Z*FHTFnh{uMTs|Dpj2D!*q)PJg-g+8Jku&hmLT)Au^P*wE44$!-xX z`TX{~6P4~LjB_T zYK-6ad@YJOYMtg{QujN$Ow+mh&N1cF8GqhxOaAy|$EiDp*9BUWog9>=3o8g7YpGT7 zYW-om`;ws1&vm&AHIIAi&y)RZu<6d5pf=tMj}MmTh;7!MxwBy9FOMmLN+~bhkM#Um zA!Ywz!3~|-u=f*;m5%#)wjaD`ar57zQ$1$fS7w}V{JKozUe!{yzU{Y`>|bmDWUiGC z@1%-=*=ORjlHBS-4hi>ud$Hrjgt+gPdSBNcZraxnJHKY~h0K+@SMxUush+o@cU#})tWZ1qMIthfar>+{D`xpOr{+z4R`=}xDvtAe6ra5ieSdTI^Ihl6 z^1ZHb&VO~SW`pMXO-l?7mF=|*rYt>nAZ?MU`5wQLWv80{Y`8Gtf#{9p#$Gd6K7POT z#*r`JY`y-siQ>K2e9L?{ymt=qU3KO@%d{ttw_cnl-I3+9Ltf`#ePF5^%d5D#v8FwY z#U<^(^c=Z=N6Dsd4!U%El5v>8OJVnGxjl*3XI1emH18An5!q=Y{Q8~x%5$bC6Su#8 zD)Z20qkC24{Y!J~i$8@{o)eMSZ+^V^)!FaC(X0N(i{#thZ@cYM(fE1&DZ3*XJ9SJ{ zEaDv&A1XR5E5@VxXivANjfUe?-v5P+D=hDA=HZz0WXp{S2g6blTTWLOY%{uA5|iWM z6u#ra@-Kk_sg8BQOT?uP$EjOQ%U*4L+I6n{$B18RRx>~Lp8U%|AvCva?YFWs9TR<+ zzN%h->i_4o*3s)OrfLm~leYFpZM^3xy-PKn@0II}1OH+lmg*m7`ry+jG~KOt@z2ZI z$Kv~$pU;^jI<+cy|Le%0skfT7wH+VC*C?D!vpQG1#p`~ugrU^aCgZ^A3H8BAuH`8kAFRvX-LjzZpNuxg&nX!m z1rdK;`z3SkO=zT|A z{k&+w!!A~%*WZ?uzG>#Re4pU3YJOoHn?T;)z%E6*pKN!h*|OT*UAOm{uUl`(#I3PM z3R$nPvE+*eB>ew9LsI4C-fPpH9XijRa`KP_xa%tjh>3K&FH25prNnGSz9+fF2BqO$K@*^&-1qYr!P_l6r zmll%c<>cc&-u-Fqify_(SIUW;ko*|l%3iwO=kCmRyA$dc|5aoBKL2Y`%pU7Bm!oyR zqfIoOyUUI#pT6_w?Y4}MPj)2VF}!}NHQ7l(X}Yk3;IS436|dG>+ufIb82wx)xKQ(W zuKqk(Z-Y&DJ_oh&zIlAG{DRnK?VOzjD`$F45&V_%(p{xAb=kHZ5)#%%POKtyJ`z3R&be>GA2;e;vpEcX9E+k2~ z_uHWzHzvIJZmAcy{&3URhS>T0CSS;`(Y>0#Qb_gu=9z0wSl3DjEKi>EB5$|#?dl4( zvz!uWN5uWedl zxL(;_%W%rlV+Lu9Ob_hwD=|OS^k>wtv8O}1J2g-eVZt*f6ce7 zcf)&UU*A<{LRh9fxxe+|yvH3`KGO0!2X_Rfy4Ammo6BO_!x&rA{;SxL`?sEK`sS!h zwY zc-m-mPv!mZ$hg9?a5E3by(e34%sCjAGNI*kb>cRos|7JR9wp&BE;xM&3|Q`17n~|C zb$E%o)wH9A0)1_az&fxnO`|yDNVWv`_MxhUGy^E(`&OY|DpZR(GB+;pJa`(Tk z3YvN=a^Dr*=8}lZiVr+BGf(!poH$gP)!Fx@qB3G;w%tzkyM+(;ZS(K=Aih@NWZIf@ zwOg$2CrfxqJ#8`!oStADoa9=cvhhKA_U@K-jsIj8aQvL2?NJbs;o2|x_uiEDoa&(M zKZ;i?U-m9~#3cVXygxKeYxV0*>>6A3nGYRpn^kRoc`1j6!Ke29%A1xlGwsR}dmGbq zzDrxCa`~h!?4Lh;%Jf_K=vM04FRW}=_nBOjPg-`Q>z|&<+~CiP7KC=O8a@2Br1W(& zx8<7zhgI(jd>~-p7@936%ZV`Q=^7gx$h3;HVH81&Few>s8<^KlG<~D63 zkGFzyYYL)r{EGPg{{G*}A7-)6R_>~*9voD62saWZ8@oY>FpUnUK z-Ihz!W=qeTc%Z@m=$*tx3guCm-a;~BQj;HX?OJf)sg{zB^8;xiS#eH2Zr<)sYmaZ! z-MKwVZ~zT17be(~P~#_#jhiemPBO>;SF{X5#E&bhlxQ~C6rV{f-* z{CTn?`J>_WQ+JY`1X`yHJ18A%Q4sWMtyS55>4)vlb%I8k$8#6Xll9i$bmy}{8}FN- zgXI?95OZbbm^r1-4aXX-+d+uGDe5zZ0VBB1mS3QiertQCqOSpgQIi_!plD$1C=#s!oc1Kh!bW9c>ig%C|D?0pW509#iMz<&Lf5)jSEDITV zIPPuUa%0Yuu#^c0Pgf_l7+o#cmg7+pv*UtOcwoTtFLlAGj#7u0h+9pIQ@1{yy;}aG z>)bV~BYt^LW`3*?`paPLx7@OhiDhTLs`@bb|GED3==IZDY7H)?Tl*I$-SdpvsG2Ul z%XJ3dtJsGJ{vBp2)o&E~;M2Q!x?A?KpO=}R$M=g)oil0w>#E$Tw<3eC=r-?*xU5*> zshRnp&*j9)(yY!yUn(m5W@g((sNXHzxo?~Q!w=$XJ5HvpQK;QwbuL-L>;BUwL#gQr z#(_z$^}!n-l&9=&S(p7!WYa**HGTHbU)LsEatZ{O=4ZzGUu01+EV%X!zXsX zg^w~*&wjbZc6A@?MfoI?BVGTNnamB=TeKkbGpo_Vt|g_fzj0f>X?9rkJ|T{6e&OCg zfjqmPU5e9e+3wz5$7<*6w)fe@t-T?Itg%N}@~^NZ{1*+7RQWyQ+Vq!uJI^>fq?gaT zxnZx<3-*rg&gT}hJIW zeEeY+t+sMk*O{qX>T;#rgG?mFZnBBPJ#Eh-=s615dRU*f>8>5|R~{=Huq&{IvFXx9-jr+eA*RlnZZ_{J7qS zz4YDgyE7O6O{o7qUyU(l&(|WCqt* zS=d2odW(YKvDR7@uS-8{cdrvP`guHep{A_2{=7S%4L0$<32H09@c5v1j@agvGj|pU z{_>dOu9Wg}#gU#r3#9Bngx%1oReC?cxc#`F=gor`EqeYfIyJ+L`^vKOjbE2)+^f2! z*0nLm{?Tg&i{tlOZ|eC1&Wh`Qn^@L+&DYs?!}~KKzN? zry4)6-)VOw!$QYI$~pFdx}e*OCI-@kv?)YQ~Ge*E~crKP21Q&UsZ?Afzt z>+9?5|NsC0e|vj-yNQX3Nnc-IpR=>Gvx|$1%aJ2Tj@-L<@7~LoFJGQMefo4rNJvO^ zb#?WWDO08x85tQZTefW3p+kobDJv^0+uGXNzI*rXosW-?&(x_?r*d<1b2~XXIsN+e z>(}AKhY$Pt`T22haB%49>FF(8xNu=wT3VWhhK9z?n>TN&sHmuH+O%m?Sy@?GbaZs| zqD6}qd3t(!=H}++c6WDoU%YtnqN=K@YEe;9(T^WLeti4(?ORGpN=jQ>TU$m(M#hX8 zGiHd1iHTjga^=dBB}C>lw`t<43`Sa(`pF4N%+=mYzK5W^tWy`Z?&z=<*7Z*>P zHf`FPHEY(Cl$4YxDJdyEfByXW+O=!fnwpxLwzjsmK6>=%(a)bhf0~<{o4k4%ySsn<`0=BZl$2CqVPT=HtgNi2rl#i6qeqW+c6N5==jZ2d z-@bi&Qc_Y9A0Hpzs#U92Nk~XY?Ay0*pR}~J^q)U}{)B~vh1uEJ*?D_=dmlS??AWDC zmo8OSR#qw~C@9RDHEY)G+qZ8YIB?*=zkmP!Ra8_|oIQK?Y*bWK)R!+`zR1hV%iq0w z_wI@nD^?gA8yk0Ybab$@v$G#Re*Czhp`qc%jT<)#2?+@a2nYy7Mn*=etE;OwG&D54 zdGqE?e0+R-LPA19U|?WieSLlX%9SfuN=iyfZr!?dtCyFT7cVa_udc4H?$f7FpH@{> zRn4D2fBxjjlP8}%dGh3(IdkT`fB*jdf&~i}Jb3Wnfwi@@wXd(Q@49vC)@f;JX?^|r z_3MTW8#bIcapJ`5*RNmi-o1Objg5^>b8~ZZaBy(&%$YN1CMG5(ii?YjYinz3v#_wR z)YaA1?b@|#S9y7P`L%1;uBoZ1sXcu7@L^_VW~PXUh)8mBa&l;BXsDv1q9P9u4^M4v zZLPpo0WFFB5?W0gSS~1NN$dxWH8NjhnZq#U-*?a7OdACD3T$oK0O31=`3wvnw#svY z&VB-&o6qpUy#X`|Suf}Iih)t^12ezCMaB%Hj6es*grW?`j6es+giRTZ8G#Os37;|! zW&}DMOptkC=*FT1o)tdb^NN|788ioc+PMP62G0ziZU(c#bHk?(gV~1*7-WOwo?K-4 z_=Sn(;}`H*QEz_;D1q3ZRe}6J1WX0Y81#2s1dW1z*!y8C=&qP6KU5eMq(JVJcVqb4 zRlxs%L7(Bn{syrhjM4%>7_|c(Sbs1|*UMe`p(5xhcjSkPAc)1F`TC-OzRzVX&`2xT zrX4@{6<9to3vyKi$#8*OtI4&~LGJriw^ytTpjE;G7eVK9dpKw$6lP>(csOJvY|L1Z z;o-0%;bX>&3=fAF39=6~+{pJe$ZrDn3gEGy4NhRF(U zjH~~B|MQcTf%PKG*RCSQm7tq8Ui{Z^W8Ls!FX$|WkNymE8RqC`IVnI&x~6?K=Y8Ne(*5J zKHywoNp`*#P~u$a;P&^s_CEph-5(kFIX((-EWF4tgJCno{lvNb$v=i!mTsIY{(f)& z$1n?GBGW&W`K&7-vm`xk3tsREh|K_%1sh)Q1n{opU9s>5Pk^8s7s{Ft&T>qV_fm~`?|l3Gcae#87F{Z4ix&JlRz-#K`|m=e(MK^0IF+l{oqkR%xi;O09xC^ zI{VZQ4gpX(%Q_h}&wb+ui@~WMJPHvGpwl5hC*gWHocO`Pz`OFs4<3d9hZ8?|7+6>Q z{~q!W6elY|@uA^=fe|G%K_L!uzaMt@uVSD}dswgf$jDWZfjy)v z5(Lc9-Hhy7kozHFyfXncgnuOva`TeEp!JFC!Qtx%4_|(_z5@)iATFMd-Nlg5okvXg z;&N-T10pRDcB%hg))@`2A`4h2fYJyHL&K|+;FCo_X{X^;NC7DIfYMIGt0N4s)MNUW zb%xR$Wh|~_onYh!T3L$eepq_MCd0u1vH_b64+AT>KH&HRDG@nWfl5Tdm0~mge!up| z$c+;$Tlt4UK^(lA1k{!h(306Np{1bJx`FQ^<7x&K230jTb+-?PVdBge8Ky9<{`>vV zKTr+xVXK&%fF7jvBkyK&+4U7WxU3YoXpy0r;o)GBkeN}D;o(q`urgyuhKIwBgqImV zGCUl9B*;FnaML8ae6(@{?Fae$z4(uSseqk;-l0or8;#sF-7MVxei!@$kp6N&mVF8muVMV1wVS(6#rVsy_j0)HkiYl5u z{9`IA*i_N~~OLP>BE4`LR=u@%6>R6Ce3GJO$!^b^Ks> zeUQPy#X+w3hX4bE0%-S`<^_ol%uKu=y?7I?WatPF7b`~A!>2E`R085uzC0=ZBE<~9b<8K?}(L2?W~ z7%hK-+{M6kfn`;o6ptZ;(y4;30nm^z+*Zqc>s`#5xK|sIvhde{nW!{er zoV*_yxM1$f{_O^@tr=z*W_UO-OejREtv4do)*n%7YlamRv`3W~R%*EY{T}j*K>-x< z3=bS+99-EhA=<|bT3;^+*bA5mmTkTCKKotF0X-`S0KJr0dtWK3l!ocUD>18`o2(`sX$^$vd1p+1XxO`%CoKulKJbBR8FN zckko=@ZtBHwQC*IuUy&uchREwSL@fi?w>P9`TLS3!PAP0o=t+U@LUZE34?{xrkV4zvT|*mHA|n9ot@82NJwRNLxZ&K zqeu7EUcWw@sjlvKcGIT%`K6_=q&Yc-<~29Vmgwk2=t)VL=t@hQZOY5L^DZiC%kKpX zqQ3+n`^5zHG}LPKfYV2uOBzPrA7E_aPYE>ix+o-#uaqlzCD7FDvVc+v(H2H}~yJ_qMbwy65FJ<%*Bbj296R8@$e+Z_U1N zVYk-%_eYAoe@9Nqm@bl+OHYO&P#`^ky9|8gv zxY*cK?3zDc_3?@o-k$>l7yVnjIQD>pLqk`8KkM2_lkE4*ovY|!VNt;H_3Ov`d-fzB z+_tT}^wzEQ$%=|j1_A;KQvd%y<@@~kZ|OSn2}M6pOsaK92b|!ZBNfhTx@JSIVvh1Phw(r#2z{{KkxG8z3OjkJvaAOPj4?{%GIkIFZub+ zd9ZS&=a!tD8^6NB*06v1@>%uOtMltqQ&06(RegE6Zk@XX2ZzAbUAyu-Dk?tYtEzex z>FLF&$jDfHT(&Iy_?9ijfya(bSAOy0bj{tn3+I%Syik;vx4Y}@J?+lky@_qz-Mp<` zUHlUY3LZGw+0`7`y0vgsTH2W#9v%}|nVH!bzkT~I#K$MII5F{1ys2r{&+zbd7k2K< zoY>YT9&zyCOm$gVtDW=asargJcvJYtkJp=L%+NL#6ja)snR%(;=FOFzeSPf9r%W;4 zHhZ?NlAN5)r1o}Eg_kc+dY(Ji{y#KyRfUE|K-K;GOZ$6zn13u>7}?O-$tljuD|KuC z{#3(f&#oVHa%$O;k#XU$qhr&CnKL!Zb#symnul9XbR`zDrsZ;%~O-=H1PoC^_sIC3g{_EF!(a6Y6uif4IPJa0Cn|tkA$2V85 zY))UaDE{yI^{%hx%u(LIWJ&P%qM|3$4jh;ry?uM>p}&70%1oYYyG~8bC(Fz%C(7Qw z&hh*AuS{poH2a&FWW+388u;bu(~Bk_KmOz>EPOQi#*Nj*hK5POqM};%EG!&6$B$19 zQdV|LJ$!g>oP>md#8tsioI=vg&9d`!bRtTmq)harrOkBn^6qSkirVsS!Gh@DK|xEtSzDL+Uc0tE zar5TdbDEk#)sG+FwbR#+D{N^Io*o>$?CZsgJ2OD}|Lxm@ItmI734i`PmfyIs@ zwzpYXSN5Gg-Rrh*U;0f;%OYB@>$Cz7$|$VqvSV|JN80u;7D@O@+(+`Kr5Ctnhvu z7`W*3;>EH592^=B^!KxNO`2rCcJ5roJr))P9$&wHWZAPP`Tn+T$H(t`IDNY5A{UpAGveZUmPd|E z4qv`J^iy5kpC((|D)*F>6Ki5)cRiPsG}10Eel|5B;lP5%M#&le{_`&0xwE)lNy#Nm zODm*q!UXHp9Ua`wZf-rN-n~1nxnoE6Wf2h#n|t?`SH{KddBn{vCVTt#+Oh`^Zd)4} zrG!~omH2USiO6|+PP)y;#>1te;*k>*v*XF3L-S)VU*4OyW{vavq@*LuCQh_mF?Fip zk|$3tn^#tT>VE$Gs?muP-OlFbd6Bufx3>58GWJ}(x-rGiZ_cHaD?K0N3GLx-xWSH7NJOp%O?h03yJ;UBkb zDL#Je*z~{`FHS4py}Picq~ygMd3ifUZ|`Y$_wG%+)7{P6*44$|T2Sy{f}LHB)7Gtp zN7B;Htn%=faD$ndjrH5N?~HtWGD3-ohZdWfX2pkxulu=kXXb^rHt~rE56+B`m9Nwyu4E4`}e2bdiLzPp_5a~v5brh zI~*OG4$qvaxj|Pqs+^x+PH@A9>eC@1EB@@>oqJ78Ovftu*wW;hA1yWI?`D=)f9tLO z^q==r_O-p)`S&*FADtL-)F2_ifRTxrG5y@ibnUQO?SIcD|6SjjbbYn&v(;s9W|f`l zcRkf4Key>*r^CtGU+uNO-i!W<-1Iuqz3-&^hu_>E);hjfdu4O_l|}J?7p-@FwSJEB z{y9s6zb`3zGOg&q?C1mAOAl@T`%vcZWZQL<)qJwl%yOd4?CTuuzkg-=ex}*~j7dg} z$HbzBONKp9mSpLt($`c!-x4n(dy0S0pbg$d#ed#y% zSr&O)dQG|K%^2&hkiz@Cd7!3coq5|0aIl!}#f@i>AADoN*D?vlKrvIsC}-&`-;8{@w2JL2?rJ=G)m5B^q+Up|IXt2J4!BTN?IXxS`(~SPw3!o?r`fl z<@WBl=DQu)mv@M0*ofR)UU@HW&!aeQFIKVOGJ*#bJA^3 zHXbfE6^|U1m>o}I4$Y4}ba`*yc*6-eseDQt@M1bGUvvYoUk>&!oGZF|MKd*>Z{aK>r<<~ z^i{2Mf4PoBK!Rge{?%O-A37>jz4BG{Vv6)+EL3Ecg@0VOrTF-kW77kVy*RD>;_kwl zyCpB?l*rpD%6m_{>%BMe&fad`w(c(e)~uQUgc}~rY^==R zzB7K~lM&)eJhV8`G%MaTeBICRotYPQwuw({J2*4qpsba;>^$|I^B&%`c=+SB@Q)eV zn`a0r84G4!+MRiGWx>rp_RhX3#>=P7*4;K+&PGYDU360W%aaN(&$WA=3tja;R3o55 zW@jyYvq*pcDbbl7pG=7yQNQRTY) za)SIDs!wkSS@9=ickZ>_Vmel0$Cf51|7fYHc{j7X{9A8z^?%+^pRVoA&c3%XKYwD# z(W40g1_n&bjEv`2rl*J1YHL52{P%Bb()H`U&sMK~Gpnqu-}Tff`MFI^oen2Y{%WtS zeJ}d!*QVEzk$orK-G6g`_~7_v?b^-hSFXhWU9`yc)%x|y`{&FF{=Q_%lW9dov!f3j zC_S`&`$L((e{I)Ip6rvQrj`?BW>)8DZ~v9)`}b!5GiNelOiTj5EM0oh4jvYksX@n&yQL~C&y72L*g!)WJCEtRA%6zS@wkChBX<7C)ICy8q zMR5Kawcfw?f4XYbTe082+m1Rr&${mGn-*$pEI6gLwd=gA>q~*3KUvtA znEo}^*Dv@G5K!S_W23rj{(SGpD^@J}92gk;Z}H-W0}c+XUH$#`YbQ-o+%tD>fro{~ zN0zT&lke}@Q+{yUw)LgAZaF0@Dk>NV2t1Yg|Nk%F=g<3dFI{T%IeS(@goj7XR9N`1 z{+l=Z9>&L;E}A~Q#~uFBok_QaZ$lwHqbV~w;WC7(?# zEd z(4oC~moGcNU$f@OvZN%-6%!{KE}1&@viXxIpSmk6uNpmn-tBziL|&x1`K|4_xr{x% zy&F@mUY&Ev&(HJ0%9S^^qBix&%P?%sVdr=-MAQC@!9U2pHi zJA3!?wsm*&w{~?sm{3qq<78)7cx3C=Gpo|lCfxAwU}I%w{?7RAn~V@2-=W2ciCOWc zrt5x&hi6{cxl?>%TieWtg9okDWo6ZO&YO4B;^D*B!asg!Z=Nwj$yiYE((cU6l?69% zvUm3N884qQMR(im*)~dYa-x&k+fORIeA(`K?%b;Xp`ig48X8Nh?%!wb@9ByBv2Y=0 zLuaRyI4^JNt^ND28$Ns1a?Hu;!j6oLro)bonj2=$j4IdFl@sLWuRgtD!-_v4A-UIf z@7A#r69dgxg4P#+<}*QS1VHo9+1c6IpgCdC{IG$6fdL~UBO_?O8Z-wAn%@PjO90KK zgXaA~bK#&h3848_&|D{I-2i9~7c}Sm;lqayYuBz_3!2{ttqlOpk%Q)BL390}H36Xc zV$i%ZXg(h_XA7E31+9w!&8>sxoP#| zy`cGh(EK=Pz8f@W4w}0L%^QQ(Zh+>EL36#JH36V`bI@80(E1C|+5*r#F=(9w0|NsC zXiWlWKK#$0KYu`T+MqQNpfw+$H5j0|bW2N1OVFG(XsrcktpRAhAGEgM{rmUtL38e) zwI0sS&d#7YYS276Xl@_01_3m;4_apcn*Ro^e*n!~Qvt2lsI0841g(Vt&EJF8KIG=+=7QFJfY#W6)~$fn3V_y* zfYvU6)**n_T7cG-fYu3s)&PLkwSeaGLF*Mj>r_B%TtI6lKn}j-96;+SKx-F3 zYcD|S7(nYEKsvtUJ3#AFKk&X}V?b+EKx;riYh6HVDM0H7K>rz1L zRX}TBKNQwB7-< z9tgD70krnUV(a}Md)yS<7(XQaU}a#v%Kzy`0^^6C9~y2(dl?iMKB)cxodclsgW*H; z4~7p_KNvo&{K4=+>nFp9vY!ke-u<|_RKtz&L&*<@5Bq;Ie0cto;e*02kVy6qh7aMt z7(VR%1u>gJ!Dw&6R^7Ku-4`~nxG{XF`@yo}@Asnr8XFni_&=2-Fn$R7q5gp3!_1!> z-Z^xAc$d&6se1p1N}B(dhGe#{4M~P>AoV5xbLGBXWcZ--li`EnPscYB+&LQ|uHpU3 z@PX|o!w0^f{GVJB7(ZzLVE7>RGhjp61Bk7cHZXkX`|)91@7>$Rw-}?xo3_b|ECnu`#;vC zfMg;5ezAc;ng3IO5dWtJL6#MaAB2B0GO%3W|1>9n;X}oL=?4rS_Wxk`Aor8ugTxQU z5Bk3#ZUv>5fFBGWqJA)Zu>ZmE!QuzQ2Zta0pE?2SiP;*bB|*ZgPrQ2c}O!`*)nvvq$kd;q0LogWMz1b;Am z;QGPvLFfnnrVdl2s(gOyi`#)Y7Gk$om55#(6%=qE78#Wicq+|FJM&%giQ%m3>`Q~sO{oGX|=i2Q)$)fNYa4>kW3AAo!XiU)`dAQfN#L2LlAE&u=j z9{Ky;VtKnWmI_&XP}jTtdV+NIZbJ`Q?9zjXWz@KD7RX$#OnOk^6L!WhF@T_)mySGaMK`sQ(ju z!1!V6f6$2)|Gx|W|Ns5RzyIGq{`>#^=Rf{WDGm%D#Qy#N&iG$p!_MadTXo;Ebg%uY zQ_G;hG(k#f=?eZ&C62$pPyV}f1 zQ1?$^BP2#9{dIrv|NG5<94i*jFd6V3;5XRjc#=|MyM*SY|MRO-fwB2o4M884MF7SF^2B zTnRGo$p8P}-TpCr&;pg#KNvpn{NVrO;K1;~=PyW>@jvg^q}si2Sh@xFGP!ZP`F~+Z zEO2LFnE#f2cJLcXZN?9u_ONgMfbuUW zmot7?x7RZ-vn0sRT_G(oGbc5Li@`CqI5@S$JGBxjqN7lhTB2a9pbC<64F)yk6ckib z6jX~9O7iow6;w_2jMEf~QOo@t7vyXL4iF;M2RS-9d4?zu?LS`^Q?T*GhBqiKgEJDb#2f=d zu!kc#W*M29VKt5+I3v->)GV|hC9xzGn+k}$TV`Hj4mN3!dvrmD6YDqEvecr={Jd0! z^wg4K1-GKil*CGf{IoPZ1_lO@zk`Ys5s8+Ifgvc^5oB~~UUE@oK}lwQ9yGa{fzoGg zW=>8fJk2JSr7Pr@r51tIXO^TEC4!U}gUl#SR0t?d%E?StaD|uy^$JK1Vtz_01?Hz@ zq-Iy9q$cO5Ac8PCF;BfjAt^O4IU_f*C>vD8F}QeulT3DMr9ygY9@K#f3aX^|1<8!W z^rF<%+|;}hP)a1l41*>{4yGnXMurUwIoRfK2=9tyv)N;C^((_cf0yOg-g_NWRhM~j zX<9H>%*4Bk4ozvQFidp`A;#tB{Mz!4>7?x}uUobU z-RvYYFN(XdFZP|UJx$y)*PvJH^OVb_=NFVd`!q>js(^JBOLMrv?^|V)EdpMs|4n{p z^K|%=3uy7dh9lbINq44POLGchuNgX3jatmu*} zCOab+-CAFA;v}=0#V?OPz6N=($~w>ae`~*IWaXA;ArxV*#M`h&cfG!lT~cvETE>J; z`R?K@+NZXwZ5KEs{Ie>FYqHSC$;3qH|K1>c_#Izvt^|2H8t+% zh_yekZR3iia~cbl`x&*1%2e=ukofo7+g$tQ!|%TWk45af!N&ad0JB7B_l$oVzg@8X zm3+WL@;JkL-M5NwQW9Bu|@fAjb zs_*KjDXzR$HoZ5kZqvjIW_pWd_kV1Cd%!MXN7Ve)4G&($#+Qa2_YLg3B5$(H?4yBv z;7olcW<~}^rY1&)AVFh?qc>Ahw?5!nD%tneC4|Rx`x?dB59`cXXDJkCuTS$aZU&-bsTDC4R-AK#C4bHmp7ukBc{=-VHQ zv(uvE>bA|;{kiMSuM^uRlrG>a&;A?f8pZQ}YVWy!v%g99aWCX~cdYX6+{D%x$sG4H z9RHUl-F~90dsig=npcWenrFzI$E_024V@lc&{0@W!Y{ATxodU94U3y@nY-Vg>0Vg8 z{L>SQ*lVTpJNUxR-e`%`EdIK%@>Z4n{^I5Xx%0bCL=WUhLQ)ba&!ArdbQU22X8-N;>FcTGgMT6C_QW&58-uJRx^yz*Fnx7aaEQS`f$tMAH(Y0-OCYrn5Z6<()nA$WH3AA`j@F1ycPQ0)JG z@aJ0Dchk;K_e=;tN_gY}DH;h1#Bn^F&^B30-&C z*Jn{Cts(Y0iS+#lc z6L0U3aE7#0+|{cBbz^Dz?Kh6`nlcW} zuOq{*uk>5Jt|0y5;*UAk`={~su2~%#k#dy9Y*S4ZK01~9Z?UfP^r<=dSGQPv`#II%*N-`>+S^0|&**KA zzII3IjV@=jz14*se(LgfwBD^*85zr-EZEF_rKDk7ZIbK$FotX=1_pzzCpWOTIY8Gs z@w(|9&^w@@8Q@ z_J_dl$Xo^nt_=TIMnzl+%o$M*N+0-*f*qI>xHF<0{9hRbK}3aknqM(FgG8HOF**6a z+T;WgXZm1_qc0HoKW_tr3je1c9{itjfXH`< z4lEVCA1(M~)L0(K=rZ1tQDb;up|-_o%YHStB_Czja%IGR@Fev8U`R-lkZwHw13QW3?DwsPVYhsc> zYGCe#tcytjsS|SqvIUbTq+HAi$PP@tkRq5fA$wx7KuTcFh3t#T0Vxa$a-g+^{U4yY zNuHr`1J8a9H_%OhN^X{J|G&TdC$PIxuG8@(Kg-7kCf1J}4FA91|94;~qrSv`0R@(? z4Mmo24wC=BU;S6GGi9UMMh+!IH~x3A7*O!&bHo-VFXv z5+)qVK|ffk+h3WAvwyJXIsTbdkL7g_56kO5zB@k{j=@g4I{ul}4U&+@vR{oW6T$Jc)_6oTXsX0*RDBij|V zU{{n=_AT0a;tREYg7*~SM0=4|l z`n915B5wR2LT|xo1B()FI~3f0eZTgHMTv2xg6yyF7ymGADA)^HOMagNvNBxEjp2h+ z11L2h_Qi2v?2D6sz*u2a5$M2JP*mYq5$NDpu&JW4BG93+;8VrHia>{h1xA&Om4Ob7 zg+-N)m4Ob9g_|lHD+3)G3qMsJtPFHGSjh7AKoQH=1BIZ|cVqr@D1q3ZTW34|aF}wK zG3f7w?uKJvur$gIlM~}( zvo+OKl@;Y>l@Z}#VPs-qU_wmlok= z(ln7*)i;;ZFxFKx&@oiEP%_oiGE$LMXn-C#rT{&F40I3~3-n+z&;ex(ER0}^fq{{M zg@uukg@KWgg@qA(Xc+yj0D%k&4WJ|11QXvL2d!N4`w1bf+6OC#3A;<+zmQ%4(un0tH5eO{sG$!GFO0s19UbDV@-N6WW`L3aBRJtOFf@Y90jUS^L6HWcLFRxkNE|E=PB09O zP%)5^U<^tOAoUClaC1O*AiEc)2b5tz2>|A9P~rvK4bqRreIT_UHIS?Wib)P821W)a zP?Uhhz~>Z##5f$FVoVH-91c)5P7I9TBm+9jkcoi-tOmpeWmN|TMh=j?69XeCVnA#L zh#Uh0NF1C>7$9s0sM#R3ATNXDK=wi00#011Q3RR;zEkQj*X0AYj8U~mAb2Zuh`3XySPoRGK->h9Vt}XxxeH{60%&-g zi9vydi33!!f`SH=vl&>JI20HdI6&eGEFd)?y-W-YEYQGZf$9N8A6P9DC`dTK@*wpr zV7(wQ1_c&KE(DniVk>|W1;{v%8YEf)RQiD30X7@tCQwNNHiH3V2FP5fo4{rv*dTXt zfZYi*6Kn?)SPZHb<_=J?5ArJqsCZKVB>(|XK!b!G1X#dP;UEAC8j#aKG`Ip00Luxm zFfa(PfY_iw1*HT~jRHyrATtC&iHSjgg~5RVj0GTS!RCMo2L=`-wP14@96)A*f*xeI z064Zm`a$MF;su6 zz#{NrE2AoF0fVxv8-t2#L7NQQ560+REaZRPk2e|AT4h9jFdopaNOt)xaeEW9}?ibXEXsg-gZi zjcqdPV{Ig#Y!dmwc7XK<+kxew=`Q~_3H@Mvy)QObrtK9UTeRHUO^iPnvtM3hEpRCS zweL4Yr0_E{ zT?%4waP)Kx`N+tUbJv}t=p%zuz()p#z}GB+3%@o9#_V@|#lyH^ug@#iKn8^kds)G@ zi|k+TC^L@L($;`B$(Tzc2-A56=jlUYd zuY1kT!uX5*ACLL*j|z+ozu3Q@aPWJ@zz6fgqUXjR7@Rl%YW~i$f77p~f8{RR_D`g@ ze^lVp-_P`m@AGbl;~y3Hlz#F3v)J$aijR4hLyAn(bC4TEz;4L@z`*GLg+W~WwKIR$ zen~g+*N*&KpTpdJ)2|Ot1D1 zqn`5}*H?#?onHk73+=zeG>IviLxt7#)j>taR{?>SULR1H>8N^z{o;mS4c`QQv3*Rr zz@VUD#_?d|uf}g19gcleU{d(S^hwZpgMs1U}W=uRl>q`m!RZwnYp&A_$Hb2ejJyw$ezAT1gP z&kj)zxlR)t6JIkk3VvyjXT6vrm&D3+As3v+6u&eGI&+kMWN-%A==ho?@WY-0cTlK^ zUQ+(R;2iYInT`8`|0^G!J+B@4S#I#~rpcM;ZNK~ad4tqU$ADLkY@pkSo;>H+FZ0@& zUt>Qg#_vA2*sAQQ?4jbL;>+^k;13ng4ZlBr&;O^kW@}cGzgA$iF!v~okj&B6GLH#raK6Um6HinNj zpqiP1*}=hyA5@%uu;FG#n+<>Jny6X@`EENcf)czYA%2IV2|U$ z&%%s{KMOO1LIIT9SuUl>IWTxSHb_J|o@4^0l8wJVe`EeFCb;M~Tj}-J2NYI1GF>W@ zLy`Z-{98_N(QiJeJoBY>9~t>TDms}QUrh)sV|9Dgr-y1z1BN+%uh{rd)nK*jJM(XG z!9~B>O)rDplKzo_oo7FTlluoo_O#De)%{<|8SdZ^`Pz^oa(6F#DX7GG%@+{(nk7*1 zYlA$b!~yN-_4!br==kA*Bj|3$4~=`-b2%Jd@dY@3X%K|wW;QNRZf0X*c;LYJi|zA6 z2MOm*4x-L{4@`7K?i~B5z~cJKfi;&y;TPK{QD@Mdiwhliof#CtHiFAI9!8Ko3<~kD zAguE{CrLy*!pop<`z5*Uw|`V%1C>B*kP?VZ=@;8Ki~YvVyBuUTK9Nk3(|=y?WcY!> zapSMXFD&~(xpavnx6Kx?E{0!h9~U|t`KZ9A0M=#byuiUmTI~56C#n6Ql61Y32&fcg z1DB#~`$44{yMbGxo6LU4SFC{`w*|d&=Hb|X&>6&LQ1Ji4ASU+Ok$=X1vDeQ09Q#3R zmHh{uSs#G-Jo^*fK;<1+EyMjE1qXFsesE@W>)4=^bM=S9gR4JOCS+!>&svpz^@mQw z>uine6qgbgoum@iyw`ku{;%%U1^9&g>ic%it;{7asSGaa{s7+f0y-1{;vBS z|MSQEYX9!;@;=EO%nSL|{@q@p-KoLx0Dsu8h7S%B8Oa@BUd*qC4-FD4k|%(9A-@_v z9FTaCJOj+rNYPK$aAR1>qQsoRlJ!_(&L)=MEZ^mL>Ur3Hvy?pHX8XIbv9T^q@_WVLs+#Qi ziph0p@}XA@tOs5(G8}%z#PlHfQ4)i~!B@;o3Mom+sY#&Gq>cYTe*L*upGGZ z!{h+xVhDnkNhxsaO8)@gd;y}HZaax zkd~Hq?DNBR?88K*CbN zjb-Nl?_&QM6j;F{yaroY+yp-`Gqi3Hb>q4q0FL3mzd)mcAb*AYXWd}17sT=hvp{2a zGHwDotsB_gK&M5SU1kTzjo!boA1vIJIUWu>a~oa>I#}j5ykc~4{lUU5U;~o*nd9ML znFo>q$wOo+b3rm54m)!|;viXw_)n-f$P7WSETe;f4#=z%ml$;1F2MG{L(Zsy*#GWt zMGnYhn9U3mEc1SV%>{`vIxtSynNtCASsut`OcN|~e}MTQ+Zi30Cp=_lSiyD`^}MS@ z4t}(Ao)D)ydCIZ=VAOtp5fqLe_JV3Y&^ZmfZekyp894Tfeqd&hcayzf;r9Kz%kTJC z3>+N$^FP!uNL;XTGj#j;-RGCJo0FR(_?(2W|Df|9K(kejzZ~4Ye>eUOsU;vMLb!oX zgkWH}|072HU3PLd04X8r|`Vu;^}$C&9lX2iOc;T zYuwzj*rqLU;d*To(*BBzhvyXwPtPlMp2semUGD#wk{0K}^7@-~*DDsDwk+0ZJg>NU zdR}qyq`R=aX6L#8qarQMh5Pk3^_ExMJjb$Frt!RD=jnOH!t=;wlgs@dF==5g?61o* zx?i!gvAyD8yYRzcLE9^Co+U0n=18g$~n#~$%n_W6yvGB0G{%ywd zijC*O4~q>wuQ+)2xZH8M|3jb*7at9kp7nl1#?v&a{y5}%X=X-4u(({UsUEKjR*RW5LasEEZ z`#+A9?vrfKVVKVH`kPtbD;9QhhxS)|?0Z}o=I?R2|6@fd#8!}*>JH@&`&_u@gY279 z3bN~a9>_e94jy(JNw)bmlJ|c!l-fx0z5WscGK>8c4?D=TeUfo5_kU!R?vrGBz0IxV z6&u)n=?;5bxWTrBfNe3iLD<3$w#5O9EzDqBG_cyj0QQjp7JJsX-2d^X1mqWFTduj> z|M8{-(8cur20wpjZLLJ`30e9k2~0;27z7#m)|i4H>Z6X5iT9d&SPa$AuAWG6&e? zave}yfJ}zO_m^T&C?QPNk-Y!oNiisVkj;g-`a&@%Y>-W62AjO67!>{plR@FK2F+Y< zu#4wlm<$Q^4h)moz$TZVnS9OVra!8CndaL_UiC+JFDSiS@JDwo=lne`XZ#^<&3VPb z4odah^Y^)&0GqizFYgr_J17U)NV3kikvt4GbxTMJJgtNB)qb$4Wo~J&_}D?|oPGWt zm)&49zw5xvWSYOvWjltM9P@1?H({8`Jb$0$Iy5u6=I?P?g=Qwp{CzIVFwA6_ZzH)7 z!%VjM`y}V0nR&!zCc;FHj#q5##&xVZ> zj;RkN8dLYa_yD>y%n@|{k+>VnM;=!B2MQSnK02`NbL!Y{=Vs*Q=;k2#Nyg#-ruyB9$%_=2sxZY*vI z8HyQP5=~AlA9>i4;OabN6cQSgx^kaxk)ev|;%1eKxo)R{95Y z@}&=>hTD(tlm4-JJV;^lP)KF-NJwS#Sda=bJ0W2~0;sPGT7%yST9KW;cW&>&_53wowT`vB3%ePtV4Ujq_r{Ed%=O=0x;IAu|G)2gOsA6IgzU+M zGye8DS1wcJ*y5R_D)-G{v%`VFs5rG%$G5$V70|yHEaJk{_-x^g6TdG%e|Gkv;x%^j z!|l9Rzq}QRa%Fw_c;%19@BiFn%1`g|(du=w{Pn-_TVcCW;@n&wi>H5GUhP}5^87vT z1n=G73ij;ZcdTx<#xM1SuUZY>UtyK)V6nV#<>u3wx1ar}StOqtw&sY7lIEA`|FxW# zD^FQ%xnT02!;#Uclg{w;*M52b|6*)QtAE{!{0Gl;{)sp_QnZWP4(2dU(A-u zB$?KCyxPPf5rEWEbYw-;x<$ zGxPYr+Q;ggwL7ut6)PVfIJYtJmAELofLy@%ni_GXyxI-*vBQDmKTHm!I)FmswL~AfzjJmcx4zm9 z_4jVR5|;};a{Y(R0g!sTOb`jNt?AVkHa!QBu4%8fura^> zntc2R$AK~z|5sc2nC70ANONI({W<4fR;fc>W~sx!j8ccDSA1-84q*=dufCRwz23so znJjY7+e%wz-tJu)O}1Hb)ZVj=vfEvP&K8 zvPvEHWtM{N-J96=iixf5)gHD&iGSId61JJ84s}_j4*#I?Ew47Q{Y?bf$@uz9BHQad zJdqNqF08LVrp=Y~f3=0DCX;DiiNn6E5(m31h|N8(7};!+roGz4w#}t317!QxygivE z4*#-B9O|-499my(Wb1jw#s(T^6??sjX`V|>(jo~^T9_l@|7t7K-^_g(r4Dx4r4IYD zAZ`SO)83?MuQsx6aru`4vi(brEhrqbOC3Pr+45>18!QwzGR|@No0KWR`1(&`tc3ro zEsQl;c9|s(`?5$A4HnXnM637Lu8TF4un;JOIgp zQWGEFKd?$rXij^zl?@b@AYG8~1f}gSEcH zwS}kW)g~UE*IRk^W^Zu;$5ckCLtO?Wq-qoTUTtIpr9Yn6|8hW~yDw{w%PNV#pjgi= zbpVBI&#QfGps-|m{U-^Q@@7fw1*g1EDYBAGbHFhLim?nxc>PIedbNiQ6kcMlH!|8~ zCrZ?0lsN3mEO7vZEF`QpvDqYoQW4|puZf@#i`h!H0dngQezig5cCGP*|Ia!y%`1)TW&uc~&|5sZX_k!{&D6M5VzT)HNe#OjP>cIGl zj}4>?F~`Se2afZ7Sx&E5xVc|3a)VL>(<>IJ z-hXwUC652lcu?#DDl2$iGxPbs+QMv;^)CaG2LEM&TnTbvi37;35F5Xg6iWO_N|Zo$ zV{MilC~iSuY-e6Lu+eggRe6c2?G$u4`6L2mpE3P(2oS6f*uv;SshI@D%l zI{eMfbZ~hEs>41Ovb|6%a}RFd=Yfl6{d zzPb!Ys4GEX&j@uV$d@LP$A7Rq0Hu-7X*{plKyl6YHyc#qfWtDw?-esR&PpBlUNM7x z2Z`;y3CQ8NnTcukzpP@1y3AsSe;J@q1No-d0TgziaPxolxwuf`cLK62w=mXZfJ!1* z{sFlV6lx&Xfx^=!5u_7RZX?`=oP%(=trna=U@37k)9;LZ*~JcaS;Y?fGI6fPwg6q4Fd7v~0sUx1blsdS) zVg%=1P;J5TiV+;2noC_d%ceh z)TT&tIsU`u0Nd-YX^aHwh*oeNv6+YG^(H3&SD<=glLTfx0rC~7o&eRmVy`zd@5}0v zc#Tp|fc&;M0oiY2ueY%L%L4h1X)df41M*F&1CJy~HOP;D6F`34;$jCa(Q7jxZ4FSa z0;vJ{%Qg|}Grqd)9+y%V*4KaX_GXlV+Z>>_5lCHaV$Z8BY|~zCW&_t^*?pi|45@Yi zsR6ZJ_JC_Um@ocigM5MBhWVQa@&%}N0>u!>7fka&zNiJ2npu$c5Xd}``)!jz?g#k_ zR5#aUK;tO~Q4c`k6XcIta4QE?+wIGM`QvXUYTIRR60$%3Wq|wvNtdPIwoBiuJ!~Mm zVR7*{2^1S3Ux3_Nn{`?O6msBJ8#E=^g3}wwHz1$XW$H+xr$~@LYT;=OD&IN^dr-Y~E!4!s>g)WS#LK`?< z?_qRI<$S$`u`!kF^=8I{;C?-N-}b}9ONVDxHbp^3twH1XEFXC|Y#{x8_U%p``_0{~ z+%(-BT)uz*{!byJR`Q#)1-Qqrb&=&G4+DoHwmZKa2;2n@>d(LYfn%gV@4!XKs5fzA z1sc$?g0J7#g2xIt6hZDH*H!a=fJOpfqYPiaH)D)4kZ(S0Ou~ZU`}e?qkkJYohVS3K z!Q&H&KUhBcu!$%cU^)5SAfW(@XhFgTETS6{K4203kYJF>$OT#t4q6xP_=*9%Cfpzq zv^VDacdmb29tH_q9tx>k9to*j9t%>rJRYEoi7b45Gw;qG>Hcd6lTKkvLtLH*6SzDX z6S+Jc6S+Ja6S+JOCUSW)CUJQ>CUJQ-Cc)+=K%)fd&p5MM*QM_+`kZHD_0@lAeGp$@ zPX_Dk)i;~vCC@&H28|-HyB*kY{Rhv2>puiGT>l|5VRz>BA2J87|4?{v{fA1!t}KQX z>>qU)SyTdlutYojV2MtVgR#)*w-*Ig8mI*R;K&L5VZ-D9>YHopt1{QtSJTu2f5^nF zlk|VJ!L{|(2hrA77Z?J6IK(taYDlDjW?s3UTm_gT?>VAJx`Zdqi7b)ugVH z=y=7)%KD0jwe=MT>ne$WA1u+UBtZ7AlJI|3W!m~`7wct-)>peiS4nuk;$r1|#mdV4 zii^$E86^K%we{6z(biYRsViLiUh%NXI<&sxV_o3_GG&De$dnZ>{;!HmTVHKrJ?PT< zYE$S67q3@LtlY0yS-D;@v6(u9Q@olDOvW>(f$oUE;{cv#ng%~=OF zXPt}xs|wTBS36igyR^RA5xUOB=@kbn*DF?5rdJ$nrp_Sw->R*zc8j*Ys!mM|vnYO;#$NI>n_0_)6H7*{n_*g|9I9~CwnL2}Hf2p><+9lfh zsw(xhMCU7R@Jv$cD^Awe;E;I@4w=^y{;z6GTVL&Aoh8xwYES5E3BOl7tQ@acS@~Y^ zu$el8=;8)>quDE5UAA33kg$7ynnqrme3wvz~BieYH7s zrHjuiW>&setgJk*nAuF7LGnLTTVL%EZGBady4s}+JgUP1o}F3^HfJ^1oYgM=uPRMj zU+rYQ=hFIWXXt7d=U1GpJg-<;nO||TnL2~y|EadV+9%rjsxEbvOVcY3@K{Nx!z!>T ztH7qLa`AsvZQA;3H|rIb)>pejSGjn;;%1d~;C#i+X6l?Gx5}md%j0!FG6GzFBv@od zxL71sWO}$%B<{$Rkl2y{sT9N=X&sH9fO-(aU8WtYf&E z@N)U#AJ7;ssNB?HAh%rp`j=`d{Xrl9CEo_*lDXwKqGYc74XUZO z|25bRs#93VtLv0lKJqYXxPAW~{u?xpTi}rKv|#TH{Vu18F6M>je;?So^!C=5(TBn; zKMH<~T+(De>1v$J>KUupZ!ktT3+-z)R5@JB6Iv3xujt>#dkxFk?#wRvIQ!ti%-K)c z-1ogdHuoU^nT0$m`8qFkSGAOQ-C4OI=2pkgvYe2OhyQ&XgsYrDFIqO{(hTpeFwUW?$6Vy@KPTv=s$Cl58Y>J&{{_+tMe?=-0u z1>N3<76;}WmwYklq6*v0YpteyUkVmv35XqBBFT|sF6UG3p}uv`29wP^GL~MeZut41 zniKswUoYcbQ-4W*^3n>CiW4myOvihE{ogm?bxy#N?~8x#`&3bQjNv0Ab0a&;1%V%o z(w!R{*?(PR%GmUg(Qu-(;D-i#mi+-gSoFU=2gwR<1d+d=ACM|=Kk%bP0JP4HLGi$k z28Dx(2NMn^A51!!dNAc++QD>C-6F7+#qG+E1_nkA@rx`U3mD#ifBK*0V*Z!g976ZMjkCU#u*Kgif#_l-@nWMVp{S3d+`5IHwG1fjrkvPS&Sce zxdpm0t@!X=^cP4Zk45zX(`qL-j*kM2Akl5VL8AFAQV&4>jQh{#w%OHUfBuIi7QxFP zvqJxyOKossxn$|4;r8|W*I%|SnrfKhuhch2Y<0LK-NGod^q0V<)-NN{rkzE3@hG$|NGC+Z57X}U42 z`0#z-PmsIvSaKh5ta$(Z)jxxsEGyoBfA&vfBZ&XyAINX<55(qktY-gcz{LJBfDxq2 z|98V~meuSZ9hlfZCV)lUep~DY-KxN`;?wu1KR{*{vM4-Yfa)q>WLWX}`w?)+l(2|A zU|7Ze(E%)0@)xAGn1$;BNH@cZkKYgfQ`ngQp@@a?LH>t)7LY48{sXyb-M=q8E!^IJ zKk$#;ZJ!e)?1V0Z{I>m{ozxB|mP>|i0d8NvhyU8-66gjJzwpn_4H9}FUf(|k9g8d6 zdOG`;edJf)=M%!7~gx!?EA>T|NY`Z zC%OISB*cC&<}m0nUrdo&;KXoQXk-3|6D)!cPD(K7@LgHpx)F3!9gC7%gxmM;f3rWWeAGYvjYYYgV3Q zSLMs%AL{vKFK9@JePCv1yO1j*@PqMmy`0Z07L^|tw{ZwuV5xAgaDT<3(heqdWsg^s z$$|Kw6#L;K!vh<)1j%M6=1U*;SGywD{n@`0I${eq_q zXa)M7kBmHiuNV}*UtGc=d_kaM(htT1KCc)QCjDRn)10!CelQS=~BfePkFkc=qSYrO2^9V9@w>HUC351E?kh<&R~5B|y0f%-3>T zDCyw#;d|x}gN-1$Re$q8^nztHBrOsk^(N>p7tpRv{}2BS_}myLOmH*EaFk(~ILpl; z)<8q@BI7F1-5&qHJN{?Th~LjJ!ytii27?Cg6@v`NSSC%z{SGpYG7hnf8Y~w*Vm)OT zGz=41!0urJ#aTO}!igUZ48d-oJmcW@|9jkj294}15I)C80fztIL;o{qB*8@#82*3v z`Olyc2^TS7`2XGcKZ8a9*hUu_CQXiy4xFB#a92;1>2h_soD|!jr2-0f<`{`Zt~QrJ zp)PyDOH%j)GYcCe)K5dg^T);690C^vDncq;UNI<40h64vS1O|AKzvYWgVF#fv?sYr zTxQf*v7g)@m~b$$z#Y^+d;eYfH>j<( z_l1DN`|qN=bzgq)Zraf320E>;YXhjqBk%V9yZrA4H~&{B7+5td_A{zjU1t1X{R?!C zPQwjc zLUn_5gJh$@t%y8U@dr$+z1-MVa)R5NfBu2m7Wu3^4V9!;&~O8p4lx^ac5GyVA0l0V9?^7#Bw#z z38ap9V#B6-8Nmk(io6p!AMnofbY;E3__~pq>9sSXfhF(6dKs&VMIQ|qximjqwye<8 zWWM14;lClzL|KsQ<+U`~!RFS>KuqSD1Tu+dBIg4hG?RExOj`THf`R{Ag@a`U;|GiX z92>=dFmm_)uwt0|!-^q8gK58IMTTaQ0_%kw4VL{D6*(Hr7Yh|Y^7S%;D_ACo|6ugq z@==vR^MZ^8!-qo+4Dw7G4xjcl2wO0Gc-+8g!SG>6LxUW{2d_p4Iff6)jSg}k`E?Bp z@(dqj8Xe>-FM!0)H8{wrTsR=deF3EQc*6lXh7U&?EFY>W^!{*RU{tVusF9(O5b%Q~ zTO)ya8qXZi>6Qj=|G!K9WN~AApybA&XyC^9;psnyjV;n_Q`8@V!q)~gKF6(@z@T{c zB?F`23g!uSUotSV%oE(nv6E-krj1N&Li`I}GYJ_OUD}i^XQj1bzq%0vr^7480#43Z zp&a`eG-TYEFEGzqEIG^R#pMN(%oC1$v|;3#!8WnciSw3&6vqVrZ|@8D{;*)+Z~%qj zn+FUU4j*4N%>7}(!0KyoVtAS(6^#`D^P12CM zkfFhLAxnejLXL*ag+dLE3z83@{*=~8;GV(Ja0tfN2JsJyA9~5axC15zQB$x1m7lQU zfkwswS%nYmOj-$-UNSIp7-=PdLV!V&=_>0CT}7@3AU8L%gLvAC%nuH*vtDJLp`gg{ zgG<0chINAA3f7q%63i16-56Fde0ch^0qoiw4c-fd8WQ`nG&nC}n$P+G6ykwDSm5Ce z@?nMs^F>gYH*Dg5kOXBP*u?svL_=bKl?Dq~4iY=yFk{!d3R2CW2?~3S3oaiN7%DVW zF0#%rfV$05hIJyt4=x8Ou!}U^7(U$j0rlA}(tY;zhwuYN1=b0O5byorBEb0omgZO| z$ZYKT!RWxGz&e3<2J1`*DUO*AQfxCFq&R0fNU_g!km8!@A_a1}1G~T#1%=)p4h#%x zoDUe41y(VvbZ}$%Q1ypF!{I|~Lz&Dnr_Z-p=kb1Y;pTcEja1Tt|Sxj!;;Z+88Bn{D3RA3PgS%?ZL`4kwB^Mt>MIY~kiG&tRL$ zK9BJ=12-q!O-vIqHX~g08OcRl^Ei-v#{1{QPKbNH+=hfe{nyO3urOeF0P^wvZwYG= zVe#cRgT`l2d1asoD);-7G}JC+Xvkj3(%`s|qoIDGP=n<{iH7opDh-|s3J*9SDVTvH z;lfJ>Wex+51W7jmH_(|>TnRxxSh%?o7!*->o46lvWx(VdHnAY_4vK^JB>eJYb>ni= z&&=22*w3NDdchH#xap@%)W{Cl$)RI*aVjW}vm0GCP_R~O|6$Fb`{1#-hg+bVk{jcPbAOinW>8-F znu!TivMl?^$Ze$+=f-?{?hgioK;Px8cf521d~7)hz45 zarZ%id-umgey$4&*$f&U``Hv&u5j$%{V|=N@gk#wLULlp!OvU)4xj!PO>mOA$id9A zUm=4*gYzP@!h%GQ{zMBY4YSMqpF9#d9w3WpUgrO#llUNmS?Sw%iJ$u(GHQt30-fK! z^$(+l;B5v~1_h9<3Kt({7$`CRVAS@Kd6Y2shlN6-7SH|)r3fYd2T2(YpZ*ypewGVz zl}btgwX2^#=l^si@XB-kPd5TDKIbY(%knCWMb-zLANZLVelY6#ztWW4`H_*I@wTVjm#dy~G5Z;mK;l2I9)HgJQINq> zYNOMR{d{g_n+zC0uF${I;ly@}Wu>EpX9b7miv9eG47V5*SynYkFgz%e6Z*ku=^)qb z^z#D0Cd);TDzAzl8Lt8c4W_Fs>&s+xWz9Af$njn|D9Kd;N`F>bpp<7}U}Zf^0(4_3 zqvofppm=up__m=yP9gc_1CYxh;lugIW`E-c21k$|bT_$wnjVnh?Cp8~hrz@NzdwG} z-E{OLJJ+s{jQkVaWI!R59{=i80sB=aH*YrsH%qra-vfWJx$(O>xOuvP#Qa}nasB!3 z{sWYM8r(YFo?krsk||x~!70#fsA}f^A`j5@8=~m{^Ih`?$PAEPkQvV}f?R6kX6^Rp zJKrym8+U(9<5$eS|6|4kp8c#Jxfs|K+$2QwR_qs61C^u#;Lv2$vjw@8k@3T1h0VV|d|-Ipz`ppkJF|gtkR0O=Cfk=6IqVqq z7(a5b--en|@r&Vu*&jrFulm8DSZh|3^adU0J)v%qVA?l8I}jTKc@2Y>}OPDP*lq9lQ7$~!D+{SHaD|P zh73|y8l6~forpEnSh3$yf#H^c!YRohIaoUIlxueSdBIYH>Eel42bmM0pc=kju1qFZ zMt9TP9~J@(Q;j!Sxhc3Yd|>{;4=!~p~qS~qmMiMuh~VpQY*G(p|- zg95|ep9T(T8XWsmWW+C|YdCypY7qIz!hhgXOM{DR!>7guP`Q^P!@$mT#m#lc{ta#_ zn|8cr;qch+|AB!+Wz&m{m6?n>s<*sk43xP;Kski@7N}I>WM{gnrzjW_BqQ;fg@4EX z6CW8^R5mSeNp#xax+*aQg?(6qE z|5juwNSJ|jfK>}{vNMBJD>jBW$gD^-+qA(IWc!N@ko`t(4<$jiAN;o>(?DWHBFGIH zN%aqQeoW*SyXgO+fK%dun=1>{PZ9e!xb67J2=)EWkLmm(`~5$-a{7NrFCRq`t6mq~GAP~-i`!NKu>ONn6xB%;J!EnaLrsGK)hZGrPlS&wdUmjU@0+&gLJmv-;c^6j&a- z$a0W*kyJ0opy0j{w5xGN#sYT+jTH%>E`rMQPkS@6a!RUv7#Q*r^BDXb{TMRy(ilAb z+!zcPkj{bN0i6T!`}^O04A65Rm@i>H1%kyHdJ2T8UceoslNW?QCok~cP5#CD?X^SO zD`r+9CyD*89~fB=NCbXlVC1;a5V!<6e*tv%0_zPP-qp^a(-*eh zWqPpM8Du(WtQmwE6!||LF$(%&XwdA$e3=P!V|GS?yQd7h=9kN$c_rPKKm70i_@Q|J z#~Z^AH^B@^hx68Df0EyYG9KV@<&gS)h6)CykwTA%n zZ>Grs&IdoUC^EmEpx`O9;rGW68-9QN0UD!r`LB>@k-@;keic-^a9mKxaQM*Rppd}) zz#_xp3j>2ig8vr=hn*QG*_p05$T4dCyk)R4Q%)g+!`Z;u;e&vK3dn67N)I^P{(qPI zuaJ2EM}dGvh5}e8=-v>}o#Gt(8C2OW?EL-XE9=HwxeS?|zdwNOX8W&@sF30Cs#O7G z7K4LAf`i-M7oYkSGB_L@K7jb3y9pQ={ueMXunI6d;CI;YfZu^Z4+DdOA45ZL zGy}tdSO$iM0tN=5Dh39IT84&cGZ+}8w=*y_>}ELd;v7Rt)hz~)Jq!%L7#daxF*4{H zGBTLuF@o%L0G~?4z+eYDpoxKjVFCEOB?bnQ5Kx`Rz@S~g23DZ~CK(vi86e`|1FaYs z7y_W`rPe?ch)>}JGsI@Ff@u*j$-p4o06r@WY(9tuKA4DsfdOPL=sYQqJ3yx)B|z23 zGVp*|AoD>CKk#Wz3=EEIAokmU1Q{3@tQsKpfyx$;5Xd|b4Rfb*0>u4_2_Rb;800{b z3=9mi2SBzV+%EwYhq)Kz4zLQ9FAN3@1`G{{PcjxV6f!h?_{Fq|VG{#G`()s#C6dhPWy_z4cx^FqU`M0!faQO7UkbTD7w;bHP zZ&|nxeC7)1aN@YgK7&Dpfthtb+YAN`CRIjNp$Ci_?6=rfFnsv*k5Pl^HiHU-D#ru% zS+I6C`y>}B{}2C785CJoFnl=jUur&^8~;WI1&ao=op)byC^IN9C^CHb{$J<_JNYH-eAyTYImvVZ>DtK9S7UgJLfkU@j*O4v@&_!h_| z_5VRVllgBiax;9~*Es*}Y3^MQ5wZnP*)7}*AJ;d|e|wC3^+QHI!Hb+T7&KHiv0Y)* zS+jrs+kM>g-|pw0_YlI{%RT??F7D|ML23l9q`__S`p=-@w4Z$jgU0-~3%D6Rwl~gy zyNSE`A;X8B|4NFC2?&*@NGexzGkh#+od0$yciuygUXT3@dOTMdJ{0{|RAfxx+5oES z_P*ih&i}yRxc9}E*1Ip+zv_ETD*a8B)NZo5B%f!Mv6Q5jg2O5j2|q|NGb9cVDt7|Ns8+H%J92P5%Ba`inuy!5h>9XZW!E z?|~1K8yJ;ry%|32{Oj;(Vgsme!|-AD-@7lFlr8r&C|G!c@c-`@elvWi`orP|N{bLT zegya4ZoOnuzV(uY@&EVzzai#7{W<@wE;vMgf4~0|WX}KZ8-IiByY-Sm85A!6zpsR< zJ^vHrZ;;C+{((Zxz|GO^_xEYw5dZ!C095xRux|d1HVq6a3{x1CSiG55Fnmb-w_-D+ zhWQ1j2Mqh+ch4{|G@P}rPn);k8RRY+@SQXPpdyfgf#HEY1H%OS_m;o@Iq8Aq9~@v{ zc;LXm@L)ek4j~RIus+m-NCf`ypF!d5OC|>P2Mh{~o=gxs>p{K(-D3nw>kPWG`$2s! zP}+2SBfvfPEfY6r#)4}DC@q81al=;7?PI}j1hqlp|G#hh3sT3p7hwwn!-xG)UIQ8p z;vNW^@(v{Lq2L#|kAZ>VM@sshJs=4vR%kSS3zBcxd|L!0ACS(r7+Lg$wz!l4hEUu;M`k-EZ=Y={ya!tLcSRse;e$b7NN+e|2YkkPx$p8tUurZ zFS`FufaR;|O+n@#2r)(pUxqu$M?vxt*ZzaeXRu5`iJt>&bq|5$8^^S>l5Z$Gw*p1pXg6qPjKM*R!5Jj4af}Bw z{Y)ud4$?27Z4J&}2cE_*Mb^*o&UrdWe!;WD;P_FP+Pf7+9(-giBr{{=f8Ccqe01Nk zb&I+&Z-I_67IrxCTx0~dT3GfofLbjeo`&=l(9D4FLq-k$TcBBq$-fvixNb9iIP@D- zPJw6O->`Kr^4$C4OAjNwHN!Z`MGCZv1ymES{SB&#nV>Z>8>}Yo0hv41YnnI1hpu0o zm+rn~P-aj7)vv$4zxoH7TS$?Ei1m5?|GxbPhz+VU85Fub|9@Zq160C;>d4>UkNyDF zQ=mHP*Y~skV0C1(N3-Xz???YNdo_Fi|33W(sK)#Ceeb_UuSW0x-}|Bbt^ex1>b?Je zZ-?^N{;Tz>_5T089?D<(uiC5H`~UZHD1Yw1O0P=q|KIbW{HfrY2IP)k-xL2s+|UiK zHx)Mh|9<5c$Teqog6z)q$o2g7z4jkOjrafHHxkjpAA z+9TBS*LP2_yA<3s-F|%+{SO+s`~O|^N03{z+yC!^a61_k0z7|xHwN3N@WB7W0S8~t zU*EO=LEI#v?d{?1`Rltf)GkSFPY+kmU*Dy{W`o8Ze|>)r*8A`K^Zy{X{QLg+KhuW2 zZ`is)si6UU-zF%|K<<|JkoWxc{qJ9SFM02O-_L{n|LgnLzp`Gk-v7QIhw|V4mG+YM z{`Y-9l>hXvq?e@kzwg_j{JVd}y~Mr$eP0jdU;PWZDO1Et#Cz`xhJb(H7lU#H!-xNf zdK**+ez5<3Pjml`ABXI}Z2osfYUW}4q|+HU^WBcyA3G^@>qy}ld#{&WQ&c=J*?*6p zK6B>GoA!Ialj=|H=k1yGU8c6)4phfipT2FsdYKX5Q?*dLnj?Ga@2QvA@jX=&6?VC7 z?=Je?-sOJm5AJm#cK@2RQyaE2xk2h>uYU{=7#Lu6^A|S`smy^^+nf(Gk81;WXm)H*)@nB#$xv80*?Lv^8(q+(DS2LZy zUzC5qVI_PSw0g_&6{Di#D@MnFA1u~F@{0St9TtCNw9$FR%p>!m!T$4wlbaaiIgCL1 zg5)&zPkhD9|Ko3S(zZ$=6{?+_dM|v^n>_JweU##DZofkR8e_(KX=D_qI znj`*|5fk`~QdX7ypcG%`_~kMa12=;K1A}70UPi6+Hw(6k@F-jWnY8Iw)7K*(6(<|&zA*h332oTq@QM}01NkY);T4NR!Cr$c&Kb-f7@QatrJ1F< zofBC0GiNYpb6n(oz?^ZH-}RLXi%UW@19O6>oJ+=IrY~2O!K$1yq@0}+INS{O6u862 zwx)nj2<3d>_==e);FS+g&?_Du=1Vi3IQCC)DsUIs-|f`o1RArzufE%fV?Rip$o`p5 zAbkuBkb80xGC)06P#?C#iTz?i1_N}KN&EtnLcv~zouKyg%>RrU8Mhd9`EP^NaZ2?% zaa~TxV9@Z{KmV-(_x!hp+%0bzxEU1+_BuMPbV|%%yOsZ0F3>^J@fAZrLW0u+2f5@7 zS4l=C){mwPNuT9|O*I%lFgPYBFkemtpAu8BmqAJNqdY&$Eu{=)kceqQLWYybg&;ZA zj7g3MJ}NL@a-Qqp`sz}VYKH1BhHt4EtiPB)8#^l}Bxfl9V)&YxkdVRQyy+u@e?kKD z4c?0i6$jY4t}0|W$S5QzWN7S6$Z(KJ0MB9->`ln%aDvREeY?m2x(x_iVlXg#_z$Tn zKh#hB{pmCFZy~`0FBuFA+?_HGedY>s`1HScmJ{bi#|%zpmi-JF3>u&rx&n75g#vfy zjA#Z(?5bXH_+;!nODaf;QA_@|sTSL9#|)599TPzNpoAYVDl&bLXP)WcDL09Y{i;)j zpo5o#Qvy?lpfiIK(*q_jpD96bBdE^`8qX|npWwuE5f<<47iK!Kf<_a;XYX3Rxpa6L|6e_k-XbHps1@zV(rp42+<@36sL!7X>|aJ3*>6!Kd4u{>Q=~v7b@L;R8?O z|L@DdeR;Nr5Hlsb|9|iO&wCN%zF*(p{Q{Yy`~V^+?EU|H?LY2IAUOu*U*GS8WkGg; z*3}mDFe>qQ|Nq|dPwWO*g%YdxukUBUYW{yO2HV1@a2eXS0>|%(IR_X{%yF>xvhn`) zeaA0Qne+d<&p(s>^WR!>&wp#h9sEW>```D*KmWgL|7COg_x%gFHR1oE!pX$@*Z29q zAZ-pw?qA=te?#hHDQ$fZea~OtCxYby+#=n6eUJT}|ACQ7+x!1_GjL0Q^#+5IhWG#P z;{OhOsBHk%(Z9Y|f?EbEUMk+dz8C)j(f_`?f_vq^zGs8`_JMDtxD~t5NB?3_0@azie;{TB{{ppt0^dk;gZTfxEB=}PmT|TA1891-2h~TQ`U%1Z_c_4* zS5Tey>B-eS&tG`k{r}&;hk;>&ji6q5;{y8t`v_;Dp8mo;_TDd+I&KeQwCCRY`PPeq z9(z#V7E;r{1BU?2)?eQr{ep-;`V9&tNJ#wn4XXKneP{XwY6XBap}d2;A4Bt%W2a?PIuLKR)E^tFx zBKw&X7!{Z{fNH`21|T~B10w^77T6N-gGIV>BU6TRhL8k@!5wy&{VP8*vOJau`oZGu z{DZ}tQ~u}0H_rw3K-MOTd}QQr+Q4<8_Xh(5qY}eP&~54LKNvL_FDkf+?FFTAvAqpj z88n!#fM)cV_A)3if%uw?7eOpW4aN&h8cY`%KCt{?+6%hPnrScS#8e&zQ3ghZFWg=uQ08>_W9>VVq;HUxG21<0eGrBEw`f*WUuMPtPgAW4(gWtD~z;mA%7&$T=z7#NU zB<%m}-@pHJe!u?*hJuIh1h_zTgT2cC{}$W~pwU|JknqEQ|NnzVZaW}}0xZVxf%^x8 z2IGbQ-w*v~Pyo3CG!_aHWmEu}(Xf@tKXn+0mwPb{~NBB0{~pfG{yh` diff --git a/IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp b/IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp index 04c1d6840..3888c46f6 100644 --- a/IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp +++ b/IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp @@ -169,6 +169,9 @@