Files
m241Neelima/components/ip_net2-6.9/ipcavium/src/ipcavium_crypto_api.c
T
2026-07-30 11:19:44 +05:30

2195 lines
67 KiB
C

/*
*
* OCTEON SDK
*
* Copyright (c) 2007 Cavium Networks. All rights reserved.
*
* This file, which is part of the OCTEON SDK which also includes the
* OCTEON SDK Package from Cavium Networks, contains proprietary and
* confidential information of Cavium Networks and in some cases its
* suppliers.
*
* Any licensed reproduction, distribution, modification, or other use of
* this file or the confidential information or patented inventions
* embodied in this file is subject to your license agreement with Cavium
* Networks. Unless you and Cavium Networks have agreed otherwise in
* writing, the applicable license terms can be found at:
* licenses/cavium-license-type2.txt
*
* All other use and disclosure is prohibited.
*
* Contact Cavium Networks at info@caviumnetworks.com for more information.
*
*/
#define NULL 0
#define uint8_t unsigned char
#define int16_t short int
#define uint16_t unsigned short int
#define int32_t signed int
#define uint32_t unsigned int
#define int64_t signed long long
#define uint64_t unsigned long long
#define cvmx_likely(x) __builtin_expect(!!(x), 1)
#define cvmx_unlikely(x) __builtin_expect(!!(x), 0)
/* turn the variable name into a string */
#define CVMX_TMP_STR(x) CVMX_TMP_STR2(x)
#define CVMX_TMP_STR2(x) #x
#define CVMX_PREFETCH0(address) CVMX_PREFETCH(address, 0)
#define CVMX_PREFETCH128(address) CVMX_PREFETCH(address, 128)
/* a normal prefetch */
#define CVMX_PREFETCH(address, offset) CVMX_PREFETCH_PREF0(address, offset)
/* normal prefetches that use the pref instruction */
#define CVMX_PREFETCH_PREF0(address, offset) __asm__ __volatile__ ("pref 0, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address) )
/* misc v2 stuff */
#define CVMX_ROTR(result, input1, shiftconst) __asm__ ("rotr %[rd],%[rs]," CVMX_TMP_STR(shiftconst) : [rd] "=d" (result) : [rs] "d" (input1))
#define CVMX_ROTRV(result, input1, input2) __asm__ ("rotrv %[rd],%[rt],%[rs]" : [rd] "=d" (result) : [rt] "d" (input1) , [rs] "d" (input2))
#define CVMX_DROTR(result, input1, shiftconst) __asm__ ("drotr %[rd],%[rs]," CVMX_TMP_STR(shiftconst) : [rd] "=d" (result) : [rs] "d" (input1))
#define CVMX_DROTRV(result, input1, input2) __asm__ ("drotrv %[rd],%[rt],%[rs]" : [rd] "=d" (result) : [rt] "d" (input1) , [rs] "d" (input2))
#define CVMX_SEB(result, input1) __asm__ ("seb %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
#define CVMX_SEH(result, input1) __asm__ ("seh %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
#define CVMX_DSBH(result, input1) __asm__ ("dsbh %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
#define CVMX_DSHD(result, input1) __asm__ ("dshd %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
#define CVMX_WSBH(result, input1) __asm__ ("wsbh %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
/* Endian swap */
#define CVMX_ES64(result, input) \
do {\
CVMX_DSBH(result, input); \
CVMX_DSHD(result, result); \
} while (0)
/* Useful crypto ASM's */
/* CRC */
#define CVMX_MT_CRC_POLYNOMIAL(val) __asm__ __volatile__ ("dmtc2 %[rt],0x4200" : : [rt] "d" (val))
#define CVMX_MT_CRC_IV(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0201" : : [rt] "d" (val))
#define CVMX_MT_CRC_LEN(val) __asm__ __volatile__ ("dmtc2 %[rt],0x1202" : : [rt] "d" (val))
#define CVMX_MT_CRC_BYTE(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0204" : : [rt] "d" (val))
#define CVMX_MT_CRC_HALF(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0205" : : [rt] "d" (val))
#define CVMX_MT_CRC_WORD(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0206" : : [rt] "d" (val))
#define CVMX_MT_CRC_DWORD(val) __asm__ __volatile__ ("dmtc2 %[rt],0x1207" : : [rt] "d" (val))
#define CVMX_MT_CRC_VAR(val) __asm__ __volatile__ ("dmtc2 %[rt],0x1208" : : [rt] "d" (val))
#define CVMX_MT_CRC_POLYNOMIAL_REFLECT(val) __asm__ __volatile__ ("dmtc2 %[rt],0x4210" : : [rt] "d" (val))
#define CVMX_MT_CRC_IV_REFLECT(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0211" : : [rt] "d" (val))
#define CVMX_MT_CRC_BYTE_REFLECT(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0214" : : [rt] "d" (val))
#define CVMX_MT_CRC_HALF_REFLECT(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0215" : : [rt] "d" (val))
#define CVMX_MT_CRC_WORD_REFLECT(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0216" : : [rt] "d" (val))
#define CVMX_MT_CRC_DWORD_REFLECT(val) __asm__ __volatile__ ("dmtc2 %[rt],0x1217" : : [rt] "d" (val))
#define CVMX_MT_CRC_VAR_REFLECT(val) __asm__ __volatile__ ("dmtc2 %[rt],0x1218" : : [rt] "d" (val))
#define CVMX_MF_CRC_POLYNOMIAL(val) __asm__ __volatile__ ("dmfc2 %[rt],0x0200" : [rt] "=d" (val) : )
#define CVMX_MF_CRC_IV(val) __asm__ __volatile__ ("dmfc2 %[rt],0x0201" : [rt] "=d" (val) : )
#define CVMX_MF_CRC_IV_REFLECT(val) __asm__ __volatile__ ("dmfc2 %[rt],0x0203" : [rt] "=d" (val) : )
#define CVMX_MF_CRC_LEN(val) __asm__ __volatile__ ("dmfc2 %[rt],0x0202" : [rt] "=d" (val) : )
/* MD5 and SHA-1 */
/* pos can be 0-6 */
#define CVMX_MT_HSH_DAT(val,pos) __asm__ __volatile__ ("dmtc2 %[rt],0x0040+" CVMX_TMP_STR(pos) : : [rt] "d" (val))
#define CVMX_MT_HSH_DATZ(pos) __asm__ __volatile__ ("dmtc2 $0,0x0040+" CVMX_TMP_STR(pos) : : )
/* pos can be 0-14 */
#define CVMX_MT_HSH_DATW(val,pos) __asm__ __volatile__ ("dmtc2 %[rt],0x0240+" CVMX_TMP_STR(pos) : : [rt] "d" (val))
#define CVMX_MT_HSH_DATWZ(pos) __asm__ __volatile__ ("dmtc2 $0,0x0240+" CVMX_TMP_STR(pos) : : )
#define CVMX_MT_HSH_STARTMD5(val) __asm__ __volatile__ ("dmtc2 %[rt],0x4047" : : [rt] "d" (val))
#define CVMX_MT_HSH_STARTSHA(val) __asm__ __volatile__ ("dmtc2 %[rt],0x4057" : : [rt] "d" (val))
#define CVMX_MT_HSH_STARTSHA256(val) __asm__ __volatile__ ("dmtc2 %[rt],0x404f" : : [rt] "d" (val))
#define CVMX_MT_HSH_STARTSHA512(val) __asm__ __volatile__ ("dmtc2 %[rt],0x424f" : : [rt] "d" (val))
/* pos can be 0-3 */
#define CVMX_MT_HSH_IV(val,pos) __asm__ __volatile__ ("dmtc2 %[rt],0x0048+" CVMX_TMP_STR(pos) : : [rt] "d" (val))
/* pos can be 0-7 */
#define CVMX_MT_HSH_IVW(val,pos) __asm__ __volatile__ ("dmtc2 %[rt],0x0250+" CVMX_TMP_STR(pos) : : [rt] "d" (val))
/* pos can be 0-6 */
#define CVMX_MF_HSH_DAT(val,pos) __asm__ __volatile__ ("dmfc2 %[rt],0x0040+" CVMX_TMP_STR(pos) : [rt] "=d" (val) : )
/* pos can be 0-14 */
#define CVMX_MF_HSH_DATW(val,pos) __asm__ __volatile__ ("dmfc2 %[rt],0x0240+" CVMX_TMP_STR(pos) : [rt] "=d" (val) : )
/* pos can be 0-3 */
#define CVMX_MF_HSH_IV(val,pos) __asm__ __volatile__ ("dmfc2 %[rt],0x0048+" CVMX_TMP_STR(pos) : [rt] "=d" (val) : )
/* pos can be 0-7 */
#define CVMX_MF_HSH_IVW(val,pos) __asm__ __volatile__ ("dmfc2 %[rt],0x0250+" CVMX_TMP_STR(pos) : [rt] "=d" (val) : )
/* 3DES */
/* pos can be 0-2 */
#define CVMX_MT_3DES_KEY(val,pos) __asm__ __volatile__ ("dmtc2 %[rt],0x0080+" CVMX_TMP_STR(pos) : : [rt] "d" (val))
#define CVMX_MT_3DES_IV(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0084" : : [rt] "d" (val))
#define CVMX_MT_3DES_ENC_CBC(val) __asm__ __volatile__ ("dmtc2 %[rt],0x4088" : : [rt] "d" (val))
#define CVMX_MT_3DES_ENC(val) __asm__ __volatile__ ("dmtc2 %[rt],0x408a" : : [rt] "d" (val))
#define CVMX_MT_3DES_DEC_CBC(val) __asm__ __volatile__ ("dmtc2 %[rt],0x408c" : : [rt] "d" (val))
#define CVMX_MT_3DES_DEC(val) __asm__ __volatile__ ("dmtc2 %[rt],0x408e" : : [rt] "d" (val))
#define CVMX_MT_3DES_RESULT(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0098" : : [rt] "d" (val))
/* pos can be 0-2 */
#define CVMX_MF_3DES_KEY(val,pos) __asm__ __volatile__ ("dmfc2 %[rt],0x0080+" CVMX_TMP_STR(pos) : [rt] "=d" (val) : )
#define CVMX_MF_3DES_IV(val) __asm__ __volatile__ ("dmfc2 %[rt],0x0084" : [rt] "=d" (val) : )
#define CVMX_MF_3DES_RESULT(val) __asm__ __volatile__ ("dmfc2 %[rt],0x0088" : [rt] "=d" (val) : )
/* AES */
#define CVMX_MT_AES_ENC_CBC0(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0108" : : [rt] "d" (val))
#define CVMX_MT_AES_ENC_CBC1(val) __asm__ __volatile__ ("dmtc2 %[rt],0x3109" : : [rt] "d" (val))
#define CVMX_MT_AES_ENC0(val) __asm__ __volatile__ ("dmtc2 %[rt],0x010a" : : [rt] "d" (val))
#define CVMX_MT_AES_ENC1(val) __asm__ __volatile__ ("dmtc2 %[rt],0x310b" : : [rt] "d" (val))
#define CVMX_MT_AES_DEC_CBC0(val) __asm__ __volatile__ ("dmtc2 %[rt],0x010c" : : [rt] "d" (val))
#define CVMX_MT_AES_DEC_CBC1(val) __asm__ __volatile__ ("dmtc2 %[rt],0x310d" : : [rt] "d" (val))
#define CVMX_MT_AES_DEC0(val) __asm__ __volatile__ ("dmtc2 %[rt],0x010e" : : [rt] "d" (val))
#define CVMX_MT_AES_DEC1(val) __asm__ __volatile__ ("dmtc2 %[rt],0x310f" : : [rt] "d" (val))
/* pos can be 0-3 */
#define CVMX_MT_AES_KEY(val,pos) __asm__ __volatile__ ("dmtc2 %[rt],0x0104+" CVMX_TMP_STR(pos) : : [rt] "d" (val))
/* pos can be 0-1 */
#define CVMX_MT_AES_IV(val,pos) __asm__ __volatile__ ("dmtc2 %[rt],0x0102+" CVMX_TMP_STR(pos) : : [rt] "d" (val))
#define CVMX_MT_AES_KEYLENGTH(val) __asm__ __volatile__ ("dmtc2 %[rt],0x0110" : : [rt] "d" (val)) /* write the keylen */
/* pos can be 0-1 */
#define CVMX_MT_AES_RESULT(val,pos) __asm__ __volatile__ ("dmtc2 %[rt],0x0100+" CVMX_TMP_STR(pos) : : [rt] "d" (val))
/* pos can be 0-1 */
#define CVMX_MF_AES_RESULT(val,pos) __asm__ __volatile__ ("dmfc2 %[rt],0x0100+" CVMX_TMP_STR(pos) : [rt] "=d" (val) : )
/* pos can be 0-1 */
#define CVMX_MF_AES_IV(val,pos) __asm__ __volatile__ ("dmfc2 %[rt],0x0102+" CVMX_TMP_STR(pos) : [rt] "=d" (val) : )
/* pos can be 0-3 */
#define CVMX_MF_AES_KEY(val,pos) __asm__ __volatile__ ("dmfc2 %[rt],0x0104+" CVMX_TMP_STR(pos) : [rt] "=d" (val) : )
#define CVMX_MF_AES_KEYLENGTH(val) __asm__ __volatile__ ("dmfc2 %[rt],0x0110" : [rt] "=d" (val) : ) /* read the keylen */
#define CVMX_MF_AES_DAT0(val) __asm__ __volatile__ ("dmfc2 %[rt],0x0111" : [rt] "=d" (val) : ) /* first piece of input data */
#define MAX_PKT_SIZE 65535
#define ESP_HEADER_LENGTH 8
#define DES_CBC_IV_LENGTH 8
#define AES_CBC_IV_LENGTH 16
#define AES_CTR_IV_LENGTH 8
#define ESP_HMAC_LEN 12
#define IP_HEADER_LENGTH 20
#define AH_HEADER_LENGTH 24
/* Parallelized version for better performance */
#define ESP_HEADER_LENGTH 8
#define DES_CBC_IV_LENGTH 8
#define _CVMX_MT_HSH_DAT(dat, next, flag) { \
if (next == 0) { \
next = 1; \
CVMX_MT_HSH_DAT (dat, 0); \
} else if (next == 1) { \
next = 2; \
CVMX_MT_HSH_DAT (dat, 1); \
} else if (next == 2) { \
next = 3; \
CVMX_MT_HSH_DAT (dat, 2); \
} else if (next == 3) { \
next = 4; \
CVMX_MT_HSH_DAT (dat, 3); \
} else if (next == 4) { \
next = 5; \
CVMX_MT_HSH_DAT (dat, 4); \
} else if (next == 5) { \
next = 6; \
CVMX_MT_HSH_DAT (dat, 5); \
} else if (next == 6) { \
next = 7; \
CVMX_MT_HSH_DAT (dat, 6); \
} else { \
if(flag ==2 ) \
CVMX_MT_HSH_STARTSHA256 (dat); \
else if(flag ==1 ) \
CVMX_MT_HSH_STARTSHA (dat); \
else if(flag ==0) \
CVMX_MT_HSH_STARTMD5 (dat); \
next = 0; \
} \
}
#define CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr) \
do { \
CVMX_MT_AES_ENC_CBC0 (in1); \
CVMX_MT_AES_ENC_CBC1 (in2); \
rptr[0]=out1; \
rptr[1]=out2; \
in1=*dptr++; \
in2=*dptr++; \
CVMX_MF_AES_RESULT (out1, 0); \
CVMX_MF_AES_RESULT (out2, 1); \
} \
while(0)
#define CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr) \
do { \
CVMX_MT_AES_DEC_CBC0 (in1); \
CVMX_MT_AES_DEC_CBC1 (in2); \
rptr[0]=out1; \
rptr[1]=out2; \
in1=*aptr++; \
in2=*aptr++; \
CVMX_MF_AES_RESULT (out1, 0); \
CVMX_MF_AES_RESULT (out2, 1); \
} \
while(0)
#if 1
/* Disable prefetct due to pending ttcp performance. Research with smartbits? */
#define prefetch_packet(a,b) do { } while (0)
#else
static __inline__ void prefetch_packet(uint8_t *pptr, uint16_t pktlen)
{
/* Align pointer to cache-line by decrveasing address */
pptr = (uint8_t *)((unsigned long )pptr & ~127);
switch (pktlen >> 7)
{
case 0:
/* first cache line already prefetched by receive routine */
CVMX_PREFETCH(pptr, 128);
break;
case 1:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
break;
case 2:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
break;
case 3:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
CVMX_PREFETCH(pptr, 512);
break;
case 4:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
CVMX_PREFETCH(pptr, 512);
CVMX_PREFETCH(pptr, 640);
break;
case 5:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
CVMX_PREFETCH(pptr, 512);
CVMX_PREFETCH(pptr, 640);
CVMX_PREFETCH(pptr, 768);
break;
case 6:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
CVMX_PREFETCH(pptr, 512);
CVMX_PREFETCH(pptr, 640);
CVMX_PREFETCH(pptr, 768);
CVMX_PREFETCH(pptr, 896);
break;
case 7:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
CVMX_PREFETCH(pptr, 512);
CVMX_PREFETCH(pptr, 640);
CVMX_PREFETCH(pptr, 768);
CVMX_PREFETCH(pptr, 896);
CVMX_PREFETCH(pptr, 1024);
break;
case 8:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
CVMX_PREFETCH(pptr, 512);
CVMX_PREFETCH(pptr, 640);
CVMX_PREFETCH(pptr, 768);
CVMX_PREFETCH(pptr, 896);
CVMX_PREFETCH(pptr, 1024);
CVMX_PREFETCH(pptr, 1152);
break;
case 9:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
CVMX_PREFETCH(pptr, 512);
CVMX_PREFETCH(pptr, 640);
CVMX_PREFETCH(pptr, 768);
CVMX_PREFETCH(pptr, 896);
CVMX_PREFETCH(pptr, 1024);
CVMX_PREFETCH(pptr, 1152);
CVMX_PREFETCH(pptr, 1280);
break;
case 10:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
CVMX_PREFETCH(pptr, 512);
CVMX_PREFETCH(pptr, 640);
CVMX_PREFETCH(pptr, 768);
CVMX_PREFETCH(pptr, 896);
CVMX_PREFETCH(pptr, 1024);
CVMX_PREFETCH(pptr, 1152);
CVMX_PREFETCH(pptr, 1280);
CVMX_PREFETCH(pptr, 1408);
break;
default:
CVMX_PREFETCH(pptr, 128);
CVMX_PREFETCH(pptr, 256);
CVMX_PREFETCH(pptr, 384);
CVMX_PREFETCH(pptr, 512);
CVMX_PREFETCH(pptr, 640);
CVMX_PREFETCH(pptr, 768);
CVMX_PREFETCH(pptr, 896);
CVMX_PREFETCH(pptr, 1024);
CVMX_PREFETCH(pptr, 1152);
CVMX_PREFETCH(pptr, 1280);
CVMX_PREFETCH(pptr, 1408);
CVMX_PREFETCH(pptr, 1536);
break;
}
}
#endif
static __inline__ void hash_key_sha1(uint64_t *buf, uint64_t pad)
{
CVMX_MT_HSH_DAT(buf[0] ^ pad, 0);
CVMX_MT_HSH_DAT(buf[1] ^ pad, 1);
CVMX_MT_HSH_DAT(buf[2] ^ pad, 2);
CVMX_MT_HSH_DAT(pad, 3);
CVMX_MT_HSH_DAT(pad, 4);
CVMX_MT_HSH_DAT(pad, 5);
CVMX_MT_HSH_DAT(pad, 6);
CVMX_MT_HSH_STARTSHA(pad);
}
static __inline__ void hash_key_md5(uint64_t *buf, uint64_t pad)
{
CVMX_MT_HSH_DAT(buf[0] ^ pad, 0);
CVMX_MT_HSH_DAT(buf[1] ^ pad, 1);
CVMX_MT_HSH_DAT(pad, 2);
CVMX_MT_HSH_DAT(pad, 3);
CVMX_MT_HSH_DAT(pad, 4);
CVMX_MT_HSH_DAT(pad, 5);
CVMX_MT_HSH_DAT(pad, 6);
CVMX_MT_HSH_STARTMD5(pad);
}
static __inline__ void load_aes_key_and_iv(uint16_t aes_key_len, uint8_t *aes_key, uint8_t *aes_iv)
{
CVMX_MT_AES_KEY (((uint64_t *)aes_key)[0], 0);
CVMX_MT_AES_KEY (((uint64_t *)aes_key)[1], 1);
if (cvmx_likely(aes_key_len == 32))
{
CVMX_MT_AES_KEY (((uint64_t *)aes_key)[2], 2);
CVMX_MT_AES_KEY (((uint64_t *)aes_key)[3], 3);
CVMX_MT_AES_KEYLENGTH (3);
}
else
{
if (aes_key_len == 16)
{
CVMX_MT_AES_KEY (0x0ULL, 2);
CVMX_MT_AES_KEY (0x0ULL, 3);
CVMX_MT_AES_KEYLENGTH (1);
}
else
{
/* 24 bytes AES key */
CVMX_MT_AES_KEY (((uint64_t *)aes_key)[2], 2);
CVMX_MT_AES_KEY (0x0ULL, 3);
CVMX_MT_AES_KEYLENGTH (2);
}
}
CVMX_MT_AES_IV (((uint64_t *)aes_iv)[0], 0);
CVMX_MT_AES_IV (((uint64_t *)aes_iv)[1], 1);
}
int AES_cbc_sha1_encrypt(uint16_t aes_key_len, uint8_t *aes_key, uint16_t sha1_keylen, uint8_t *sha1_key, uint8_t *espheader, uint8_t *aes_iv, uint8_t *pktptr, uint16_t pktlen, uint8_t *outptr, uint16_t *outlen)
{
uint64_t *dptr, *rptr;
uint64_t sha1[3] = {
0x67452301EFCDAB89ULL,
0x98BADCFE10325476ULL,
0xC3D2E1F000000000ULL
};
uint32_t dlen;
register int sha1_next;
register uint64_t in1, in2, out1, out2;
uint64_t sha_key[3];
uint64_t inner_sha[3];
register uint64_t ipad = 0x3636363636363636ULL;
register uint64_t opad = 0x5c5c5c5c5c5c5c5cULL;
register uint64_t zero = 0x0ULL;
prefetch_packet(pktptr, pktlen);
sha_key[0] = ((uint64_t *)sha1_key)[0];
sha_key[1] = ((uint64_t *)sha1_key)[1];
((uint32_t *)sha_key)[4] = ((uint32_t *)sha1_key)[4];
((uint32_t *)sha_key)[5] = 0;
/* Load AES Key and IV */
load_aes_key_and_iv(aes_key_len, aes_key, aes_iv);
/* Load SHA1 IV */
CVMX_MT_HSH_IV (sha1[0], 0);
CVMX_MT_HSH_IV (sha1[1], 1);
CVMX_MT_HSH_IV (sha1[2], 2);
/* Load key xor ipad */
hash_key_sha1(sha_key, ipad);
/* setup arguments */
dptr = (uint64_t *) pktptr;
((uint64_t *)outptr)[0]=((uint64_t *)espheader)[0];
((uint64_t *)outptr)[1]=((uint64_t *)aes_iv)[0];
((uint64_t *)outptr)[2]=((uint64_t *)aes_iv)[1];
rptr = (uint64_t *)(outptr+ESP_HEADER_LENGTH+AES_CBC_IV_LENGTH);
in1=*dptr++;
in2=*dptr++;
/* Load ESP header & AES IV into hash unit */
CVMX_MT_HSH_DAT(((uint64_t *)espheader)[0], 0);
CVMX_MT_HSH_DAT(((uint64_t *)aes_iv)[0], 1);
CVMX_MT_HSH_DAT(((uint64_t *)aes_iv)[1], 2);
sha1_next = 3;
/* Start encryption */
/* load first block of data to AES uint */
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
dlen = pktlen - 16;
/* Loop through input */
/* Assumed that data is 16 byte aligned */
while (dlen >= 32) {
in1 = *dptr++;
in2 = *dptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
switch (sha1_next)
{
case 0:
CVMX_MT_HSH_DAT (out1, 0);
CVMX_MT_HSH_DAT (out2, 1);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 2);
CVMX_MT_HSH_DAT (out2, 3);
sha1_next = 4;
break;
case 1:
CVMX_MT_HSH_DAT (out1, 1);
CVMX_MT_HSH_DAT (out2, 2);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 3);
CVMX_MT_HSH_DAT (out2, 4);
sha1_next = 5;
break;
case 2:
CVMX_MT_HSH_DAT (out1, 2);
CVMX_MT_HSH_DAT (out2, 3);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 4);
CVMX_MT_HSH_DAT (out2, 5);
sha1_next = 6;
break;
case 3:
CVMX_MT_HSH_DAT (out1, 3);
CVMX_MT_HSH_DAT (out2, 4);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 5);
CVMX_MT_HSH_DAT (out2, 6);
sha1_next = 7;
break;
case 4:
CVMX_MT_HSH_DAT (out1, 4);
CVMX_MT_HSH_DAT (out2, 5);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 6);
CVMX_MT_HSH_STARTSHA (out2);
sha1_next = 0;
break;
case 5:
CVMX_MT_HSH_DAT (out1, 5);
CVMX_MT_HSH_DAT (out2, 6);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_STARTSHA (out1);
CVMX_MT_HSH_DAT (out2, 0);
sha1_next = 1;
break;
case 6:
CVMX_MT_HSH_DAT (out1, 6);
CVMX_MT_HSH_STARTSHA (out2);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 0);
CVMX_MT_HSH_DAT (out2, 1);
sha1_next = 2;
break;
case 7:
CVMX_MT_HSH_STARTSHA (out1);
CVMX_MT_HSH_DAT (out2, 0);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 1);
CVMX_MT_HSH_DAT (out2, 2);
sha1_next = 3;
break;
default:
return -1;
}
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
rptr[2]=out1;
rptr[3]=out2;
rptr+=4;
dlen-=32;
}
if(dlen) {
in1 = *dptr++;
in2 = *dptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (out1, sha1_next, 1);
_CVMX_MT_HSH_DAT (out2, sha1_next, 1);
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
}
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[0], 0);
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[1], 1);
/* Finish inner hash */
switch (sha1_next)
{
case 1:
CVMX_MT_HSH_DAT (out1, 1);
CVMX_MT_HSH_DAT (out2, 2);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 3:
CVMX_MT_HSH_DAT (out1, 3);
CVMX_MT_HSH_DAT (out2, 4);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 5:
CVMX_MT_HSH_DAT (out1, 5);
CVMX_MT_HSH_DAT (out2, 6);
CVMX_MT_HSH_STARTSHA(0x8000000000000000ULL);
CVMX_MT_HSH_DAT(zero, 0);
CVMX_MT_HSH_DAT(zero, 1);
CVMX_MT_HSH_DAT(zero, 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 7:
CVMX_MT_HSH_STARTSHA(out1);
CVMX_MT_HSH_DAT(out2, 0);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 1);
CVMX_MT_HSH_DAT(zero, 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
default:
return -1;
}
CVMX_MT_HSH_STARTSHA((pktlen + ESP_HEADER_LENGTH + AES_CBC_IV_LENGTH + 64) * 8);
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_sha[0], 0);
CVMX_MF_HSH_IV (inner_sha[1], 1);
CVMX_MF_HSH_IV (inner_sha[2], 2);
/* Initialize hash unit */
CVMX_MT_HSH_IV (sha1[0], 0);
CVMX_MT_HSH_IV (sha1[1], 1);
CVMX_MT_HSH_IV (sha1[2], 2);
/* Load key xor opad */
hash_key_sha1(sha_key, opad);
CVMX_MT_HSH_DAT(inner_sha[0], 0);
CVMX_MT_HSH_DAT(inner_sha[1], 1);
*(uint32_t *)((uint8_t *)inner_sha + 20) = 0x80000000;
CVMX_MT_HSH_DAT(inner_sha[2], 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
CVMX_MT_HSH_STARTSHA((uint64_t)((64 + 20) * 8));
/* Get the HMAC */
CVMX_MF_HSH_IV (rptr[0], 0);
CVMX_MF_HSH_IV (sha1[1], 1);
((uint32_t *)rptr)[2] = sha1[1] >> 32;
return 0;
}
int AES_cbc_sha1_decrypt(uint16_t aes_key_len, uint8_t *aes_key, uint16_t sha1_keylen, uint8_t *sha1_key, uint8_t *aes_iv, uint8_t *pktptr, uint16_t pktlen, uint8_t *outptr, uint16_t *outlen, uint8_t compdigest)
{
uint64_t *aptr, *rptr;
register uint64_t in1,in2,out1,out2;
uint64_t sha1[3] = {
0x67452301EFCDAB89ULL,
0x98BADCFE10325476ULL,
0xC3D2E1F000000000ULL
};
uint32_t dlen ;
register uint32_t sha1_next;
uint64_t sha_key[3];
uint64_t inner_sha[3];
register uint64_t ipad = 0x3636363636363636ULL;
register uint64_t opad = 0x5c5c5c5c5c5c5c5cULL;
register uint64_t zero = 0x0ULL;
(void)compdigest;
prefetch_packet(pktptr, pktlen);
sha_key[0] = ((uint64_t *)sha1_key)[0];
sha_key[1] = ((uint64_t *)sha1_key)[1];
((uint32_t *)sha_key)[4] = ((uint32_t *)sha1_key)[4];
((uint32_t *)sha_key)[5] = 0;
/* Load AES Key and IV */
load_aes_key_and_iv(aes_key_len, aes_key, aes_iv);
/* Load SHA1 IV */
CVMX_MT_HSH_IV (sha1[0], 0);
CVMX_MT_HSH_IV (sha1[1], 1);
CVMX_MT_HSH_IV (sha1[2], 2);
/* Load key xor ipad */
hash_key_sha1(sha_key, ipad);
/* setup enc/hmac args */
aptr = (uint64_t *)pktptr;
rptr = (uint64_t *)(outptr+ESP_HEADER_LENGTH+AES_CBC_IV_LENGTH);
/*load header and IV to hash uint */
CVMX_MT_HSH_DAT(*aptr++, 0);
CVMX_MT_HSH_DAT(*aptr++, 1);
CVMX_MT_HSH_DAT(*aptr++, 2);
in1=*aptr++;
in2=*aptr++;
/* Load first block of data to AES Unit */
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
dlen = pktlen-ESP_HEADER_LENGTH-AES_CBC_IV_LENGTH-12-16;
/* Load first block of data to hash Unit */
CVMX_MT_HSH_DAT(in1, 3);
CVMX_MT_HSH_DAT(in2, 4);
sha1_next = 5;
/* Loop through input */
while (dlen >= 32) {
in1=*aptr++;
in2=*aptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
switch (sha1_next)
{
case 0:
CVMX_MT_HSH_DAT (in1, 0);
CVMX_MT_HSH_DAT (in2, 1);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 2);
CVMX_MT_HSH_DAT (in2, 3);
sha1_next = 4;
break;
case 1:
CVMX_MT_HSH_DAT (in1, 1);
CVMX_MT_HSH_DAT (in2, 2);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 3);
CVMX_MT_HSH_DAT (in2, 4);
sha1_next = 5;
break;
case 2:
CVMX_MT_HSH_DAT (in1, 2);
CVMX_MT_HSH_DAT (in2, 3);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 4);
CVMX_MT_HSH_DAT (in2, 5);
sha1_next = 6;
break;
case 3:
CVMX_MT_HSH_DAT (in1, 3);
CVMX_MT_HSH_DAT (in2, 4);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 5);
CVMX_MT_HSH_DAT (in2, 6);
sha1_next = 7;
break;
case 4:
CVMX_MT_HSH_DAT (in1, 4);
CVMX_MT_HSH_DAT (in2, 5);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 6);
CVMX_MT_HSH_STARTSHA (in2);
sha1_next = 0;
break;
case 5:
CVMX_MT_HSH_DAT (in1, 5);
CVMX_MT_HSH_DAT (in2, 6);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_STARTSHA (in1);
CVMX_MT_HSH_DAT (in2, 0);
sha1_next = 1;
break;
case 6:
CVMX_MT_HSH_DAT (in1, 6);
CVMX_MT_HSH_STARTSHA (in2);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 0);
CVMX_MT_HSH_DAT (in2, 1);
sha1_next = 2;
break;
case 7:
CVMX_MT_HSH_STARTSHA (in1);
CVMX_MT_HSH_DAT (in2, 0);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 1);
CVMX_MT_HSH_DAT (in2, 2);
sha1_next = 3;
break;
default:
return -1;
}
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
rptr[2]=out1;
rptr[3]=out2;
rptr+=4;
dlen-=32;
}
if(dlen) {
in1=*aptr++;
in2=*aptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (in1, sha1_next, 1);
_CVMX_MT_HSH_DAT (in2, sha1_next, 1);
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
}
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
pktlen = pktlen -12 ;
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[0], 0);
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[1], 1);
/* Finish inner hash */
switch (sha1_next)
{
case 1:
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 1);
CVMX_MT_HSH_DAT(zero, 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 3:
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 5:
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 7:
CVMX_MT_HSH_STARTSHA(0x8000000000000000ULL);
CVMX_MT_HSH_DAT(zero, 0);
CVMX_MT_HSH_DAT(zero, 1);
CVMX_MT_HSH_DAT(zero, 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
default:
return -1;
}
CVMX_MT_HSH_STARTSHA((pktlen + 64) * 8);
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_sha[0], 0);
CVMX_MF_HSH_IV (inner_sha[1], 1);
CVMX_MF_HSH_IV (inner_sha[2], 2);
/* Initialize hash unit */
CVMX_MT_HSH_IV (sha1[0], 0);
CVMX_MT_HSH_IV (sha1[1], 1);
CVMX_MT_HSH_IV (sha1[2], 2);
/* Load key xor opad */
hash_key_sha1(sha_key, opad);
CVMX_MT_HSH_DAT(inner_sha[0], 0);
CVMX_MT_HSH_DAT(inner_sha[1], 1);
*(uint32_t *)((uint8_t *)inner_sha + 20) = 0x80000000;
CVMX_MT_HSH_DAT(inner_sha[2], 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
CVMX_MT_HSH_STARTSHA((uint64_t)((64 + 20) * 8));
/* Get the HMAC */
CVMX_MF_HSH_IV ((((uint64_t *)&outptr[pktlen])[0]), 0);
CVMX_MF_HSH_IV (sha1[1], 1);
((uint32_t *)&outptr[pktlen])[2] = sha1[1] >> 32;
return 0;
}
int DES_ede3_cbc_sha1_encrypt(uint8_t *des_key, uint16_t sha1_keylen, uint8_t *sha1_key, uint8_t *espheader, uint8_t *des_iv, uint8_t *pktptr, uint16_t pktlen, uint8_t *outptr, uint16_t *outlen)
{
uint64_t *dptr, *aptr,*rptr;
register uint64_t in,out;
register int sha1_next;
uint64_t sha1[3] = {
0x67452301EFCDAB89ULL,
0x98BADCFE10325476ULL,
0xC3D2E1F000000000ULL
};
uint32_t dlen;
uint64_t sha_key[3];
uint64_t inner_sha[3];
prefetch_packet(pktptr, pktlen);
sha_key[0] = ((uint64_t *)sha1_key)[0];
sha_key[1] = ((uint64_t *)sha1_key)[1];
((uint32_t *)sha_key)[4] = ((uint32_t *)sha1_key)[4];
((uint32_t *)sha_key)[5] = 0;
/* load 3DES Key and IV */
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[0], 0);
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[1], 1);
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[2], 2);
CVMX_MT_3DES_IV (*((uint64_t *)des_iv));
/* Load SHA1 IV */
CVMX_MT_HSH_IV (sha1[0], 0);
CVMX_MT_HSH_IV (sha1[1], 1);
CVMX_MT_HSH_IV (sha1[2], 2);
/* Load key xor ipad */
hash_key_sha1(sha_key, 0x3636363636363636ULL);
/* Load esp header and IV */
CVMX_MT_HSH_DAT(((uint64_t *)espheader)[0], 0);
CVMX_MT_HSH_DAT(((uint64_t *)des_iv)[0], 1);
sha1_next = 2;
/* setup enc/hmac args */
dptr = (uint64_t *) pktptr;
dlen = pktlen;
((uint64_t *)outptr)[0]=((uint64_t *)espheader)[0];
((uint64_t *)outptr)[1]=((uint64_t *)des_iv)[0];
rptr= (uint64_t *)(outptr+ESP_HEADER_LENGTH+DES_CBC_IV_LENGTH);
aptr = (uint64_t *)rptr;
/* Start encryption */
in=*dptr++;
/* load first block of data to DES uint */
CVMX_MT_3DES_ENC_CBC (in);
dlen -=8;
/* Loop through input */
/* Assumed that data is 8 byte aligned */
while (dlen >= 16) {
in =*dptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (out, sha1_next, 1);
CVMX_MT_3DES_ENC_CBC (in);
rptr[0]=out;
rptr++;
in =*dptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (out, sha1_next, 1);
CVMX_MT_3DES_ENC_CBC (in);
rptr[0]=out;
rptr++;
dlen -= 16;
}
if(dlen) {
in =*dptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (out, sha1_next, 1);
CVMX_MT_3DES_ENC_CBC (in);
rptr[0]=out;
rptr++;
}
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (out, sha1_next, 1);
rptr[0]=out;
rptr++;
CVMX_MF_3DES_IV (*((uint64_t *)des_iv));
/* Finish inner hash */
{
int chunk_len=(pktlen +ESP_HEADER_LENGTH + DES_CBC_IV_LENGTH) & 63;
uint8_t i=0;
if(chunk_len == 56) {
chunk_len = 72;
} else
chunk_len = 64-chunk_len;
in = (pktlen+ ESP_HEADER_LENGTH + DES_CBC_IV_LENGTH + 64) * 8;
_CVMX_MT_HSH_DAT (0x8000000000000000ULL, sha1_next, 1);
chunk_len-=16;
while ( i< chunk_len) {
_CVMX_MT_HSH_DAT (0x0ULL, sha1_next, 1);
i += 8;
}
_CVMX_MT_HSH_DAT (in, sha1_next, 1);
}
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_sha[0], 0);
CVMX_MF_HSH_IV (inner_sha[1], 1);
CVMX_MF_HSH_IV (inner_sha[2], 2);
/* Initialize hash unit */
CVMX_MT_HSH_IV (sha1[0], 0);
CVMX_MT_HSH_IV (sha1[1], 1);
CVMX_MT_HSH_IV (sha1[2], 2);
/* Load key xor opad */
hash_key_sha1(sha_key, 0x5c5c5c5c5c5c5c5cULL);
CVMX_MT_HSH_DAT(inner_sha[0], 0);
CVMX_MT_HSH_DAT(inner_sha[1], 1);
*(uint32_t *)((uint8_t *)inner_sha + 20) = 0x80000000;
CVMX_MT_HSH_DAT(inner_sha[2], 2);
CVMX_MT_HSH_DAT(0x0ULL, 3);
CVMX_MT_HSH_DAT(0x0ULL, 4);
CVMX_MT_HSH_DAT(0x0ULL, 5);
CVMX_MT_HSH_DAT(0x0ULL, 6);
CVMX_MT_HSH_STARTSHA((uint64_t)((64 + 20) * 8));
/* Get the HMAC */
CVMX_MF_HSH_IV (rptr[0], 0);
CVMX_MF_HSH_IV (sha1[1], 1);
((uint32_t *)rptr)[2] = sha1[1] >> 32;
return 0;
}
int DES_ede3_cbc_sha1_decrypt(uint8_t *des_key, uint16_t sha1_keylen, uint8_t *sha1_key, uint8_t *des_iv, uint8_t *pktptr, uint16_t pktlen,uint8_t *outptr, uint16_t *outlen,uint8_t compdigest)
{
uint64_t *dptr, *aptr,*rptr;
register uint64_t in,out;
register int sha1_next;
uint64_t sha1[3] = {
0x67452301EFCDAB89ULL,
0x98BADCFE10325476ULL,
0xC3D2E1F000000000ULL
};
uint32_t dlen;
uint64_t sha_key[3];
uint64_t inner_sha[3];
(void)compdigest;
prefetch_packet(pktptr, pktlen);
sha_key[0] = ((uint64_t *)sha1_key)[0];
sha_key[1] = ((uint64_t *)sha1_key)[1];
((uint32_t *)sha_key)[4] = ((uint32_t *)sha1_key)[4];
((uint32_t *)sha_key)[5] = 0;
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[0], 0);
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[1], 1);
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[2], 2);
CVMX_MT_3DES_IV (*((uint64_t *)des_iv));
/* Load SHA1 IV */
CVMX_MT_HSH_IV (sha1[0], 0);
CVMX_MT_HSH_IV (sha1[1], 1);
CVMX_MT_HSH_IV (sha1[2], 2);
/* Load key xor ipad */
hash_key_sha1(sha_key, 0x3636363636363636ULL);
/* setup enc/hmac args */
aptr = (uint64_t *)pktptr;
dptr = (uint64_t *)(pktptr+ESP_HEADER_LENGTH+DES_CBC_IV_LENGTH);
dlen = pktlen -ESP_HEADER_LENGTH-DES_CBC_IV_LENGTH-12;
((uint64_t *)outptr)[0]=((uint64_t *)pktptr)[0];
((uint64_t *)outptr)[1]=((uint64_t *)pktptr)[1];
rptr= (uint64_t *)(outptr+ESP_HEADER_LENGTH+DES_CBC_IV_LENGTH);
/* load ESP_HEADER and IV to hash unit */
CVMX_MT_HSH_DAT(*aptr++, 0);
CVMX_MT_HSH_DAT(*aptr++, 1);
in=*aptr++;
/* Load first block of data to hash Unit */
CVMX_MT_HSH_DAT(in, 2);
sha1_next = 3;
/* Load first block of data to DES Unit */
CVMX_MT_3DES_DEC_CBC (in);
dlen -=8;
/* Loop through input */
while (dlen >= 16) {
in =*aptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (in, sha1_next, 1);
CVMX_MT_3DES_DEC_CBC(in);
rptr[0]=out;
rptr++;
in =*aptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (in, sha1_next, 1);
CVMX_MT_3DES_DEC_CBC(in);
rptr[0]=out;
rptr++;
dlen-=16;
}
if(dlen) {
in =*aptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (in, sha1_next, 1);
CVMX_MT_3DES_DEC_CBC(in);
rptr[0]=out;
rptr++;
}
CVMX_MF_3DES_RESULT (out);
rptr[0]=out;
rptr++;
pktlen = pktlen - 12;
CVMX_MF_3DES_IV (*((uint64_t *)des_iv));
/* Finish Inner hash */
{
int chunk_len=pktlen & 63;
uint8_t i=0;
if(chunk_len == 56) {
chunk_len = 72;
} else
chunk_len = 64-chunk_len;
_CVMX_MT_HSH_DAT (0x8000000000000000ULL, sha1_next, 1);
in = (pktlen+ 64) * 8;
chunk_len-=16;
while ( i< chunk_len) {
_CVMX_MT_HSH_DAT (0x0ULL, sha1_next, 1);
i += 8;
}
_CVMX_MT_HSH_DAT (in, sha1_next, 1);
}
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_sha[0], 0);
CVMX_MF_HSH_IV (inner_sha[1], 1);
CVMX_MF_HSH_IV (inner_sha[2], 2);
/* Initialize hash unit */
CVMX_MT_HSH_IV (sha1[0], 0);
CVMX_MT_HSH_IV (sha1[1], 1);
CVMX_MT_HSH_IV (sha1[2], 2);
/* Load key xor opad */
hash_key_sha1(sha_key, 0x5c5c5c5c5c5c5c5cULL);
CVMX_MT_HSH_DAT(inner_sha[0], 0);
CVMX_MT_HSH_DAT(inner_sha[1], 1);
*(uint32_t *)((uint8_t *)inner_sha + 20) = 0x80000000;
CVMX_MT_HSH_DAT(inner_sha[2], 2);
CVMX_MT_HSH_DAT(0x0ULL, 3);
CVMX_MT_HSH_DAT(0x0ULL, 4);
CVMX_MT_HSH_DAT(0x0ULL, 5);
CVMX_MT_HSH_DAT(0x0ULL, 6);
CVMX_MT_HSH_STARTSHA((uint64_t)((64 + 20) * 8));
/* Get the HMAC */
CVMX_MF_HSH_IV ((((uint64_t *)&outptr[pktlen])[0]), 0);
CVMX_MF_HSH_IV (sha1[1], 1);
((uint32_t *)&outptr[pktlen])[2] = sha1[1] >> 32;
return 0;
}
int DES_ede3_cbc_md5_encrypt(uint8_t *des_key, uint16_t auth_keylen, uint8_t *auth_key, uint8_t *espheader, uint8_t *des_iv, uint8_t *pktptr, uint16_t pktlen, uint8_t *outptr, uint16_t *outlen)
{
uint64_t *dptr, *aptr,*rptr;
register uint64_t in,out;
register int hash_next;
uint64_t md5[2] = {
0x0123456789abcdefULL,
0xfedcba9876543210ULL
};
uint32_t dlen;
uint64_t sha_key[2];
uint64_t inner_hash[2];
prefetch_packet(pktptr, pktlen);
sha_key[0] = ((uint64_t *)auth_key)[0];
sha_key[1] = ((uint64_t *)auth_key)[1];
/* load 3DES Key */
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[0], 0);
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[1], 1);
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[2], 2);
CVMX_MT_3DES_IV (*((uint64_t *)des_iv));
/* Load SHA1 IV */
CVMX_MT_HSH_IV (md5[0], 0);
CVMX_MT_HSH_IV (md5[1], 1);
/* Load key xor ipad */
hash_key_md5(sha_key, 0x3636363636363636ULL);
/* load esp header and des_iv */
CVMX_MT_HSH_DAT(((uint64_t *)espheader)[0], 0);
CVMX_MT_HSH_DAT(((uint64_t *)des_iv)[0], 1);
hash_next = 2;
/* Copy header & setup enc/hmac args */
dptr = (uint64_t *)pktptr;
in=*dptr++;
dlen = pktlen;
((uint64_t *)outptr)[0]=((uint64_t *)espheader)[0];
((uint64_t *)outptr)[1]=((uint64_t *)des_iv)[0];
rptr = (uint64_t *)(outptr+ESP_HEADER_LENGTH+DES_CBC_IV_LENGTH);
aptr = rptr;
/* Start encryption */
/* load first block of data to DES uint */
CVMX_MT_3DES_ENC_CBC (in);
dlen -=8;
/* Loop through input */
/* Assumed that data is 8 byte aligned */
while (dlen >= 16) {
in=*dptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (out, hash_next, 0);
CVMX_MT_3DES_ENC_CBC (in);
rptr[0]=out;
in=*dptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (out, hash_next, 0);
CVMX_MT_3DES_ENC_CBC (in);
rptr[1]=out;
rptr+=2;
dlen-=16;
}
if(dlen) {
in=*dptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (out, hash_next, 0);
CVMX_MT_3DES_ENC_CBC (in);
rptr[0]=out;
rptr++;
}
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (out, hash_next, 0);
rptr[0]=out;
rptr++;
CVMX_MF_3DES_IV (*((uint64_t *)des_iv));
/* Finish inner hash */
{
int chunk_len=(pktlen+ESP_HEADER_LENGTH + DES_CBC_IV_LENGTH) & 63;
uint8_t i=0;
if(chunk_len == 56) {
chunk_len = 72;
} else
chunk_len = 64-chunk_len;
_CVMX_MT_HSH_DAT (0x8000000000000000ULL, hash_next, 0);
CVMX_ES64(in,((pktlen+ESP_HEADER_LENGTH +DES_CBC_IV_LENGTH+64) * 8));
chunk_len-=16;
while ( i< chunk_len) {
_CVMX_MT_HSH_DAT (0x0ULL, hash_next, 0);
i += 8;
}
_CVMX_MT_HSH_DAT (in, hash_next, 0);
}
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_hash[0], 0);
CVMX_MF_HSH_IV (inner_hash[1], 1);
/* Initialize hash unit */
CVMX_MT_HSH_IV (md5[0], 0);
CVMX_MT_HSH_IV (md5[1], 1);
/* Load key xor opad */
hash_key_md5(sha_key, 0x5c5c5c5c5c5c5c5cULL);
CVMX_MT_HSH_DAT(inner_hash[0], 0);
CVMX_MT_HSH_DAT(inner_hash[1], 1);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
CVMX_MT_HSH_DAT(0x0ULL, 3);
CVMX_MT_HSH_DAT(0x0ULL, 4);
CVMX_MT_HSH_DAT(0x0ULL, 5);
CVMX_MT_HSH_DAT(0x0ULL, 6);
in=(16+64)*8;
CVMX_ES64(in,in);
CVMX_MT_HSH_STARTMD5(in);
/* Get the HMAC */
CVMX_MF_HSH_IV (rptr[0], 0);
CVMX_MF_HSH_IV (md5[1], 1);
((uint32_t *)rptr)[2] = md5[1] >> 32;
return 0;
}
int DES_ede3_cbc_md5_decrypt(uint8_t *des_key, uint16_t auth_keylen, uint8_t *auth_key, uint8_t *des_iv, uint8_t *pktptr, uint16_t pktlen,uint8_t *outptr, uint16_t *outlen,uint8_t compdigest)
{
uint64_t *dptr, *aptr,*rptr;
register uint64_t in,out;
register int hash_next;
uint64_t md5[2] = {
0x0123456789abcdefULL,
0xfedcba9876543210ULL
};
uint32_t dlen;
uint64_t sha_key[2];
uint64_t inner_hash[2];
(void)compdigest;
prefetch_packet(pktptr, pktlen);
sha_key[0] = ((uint64_t *)auth_key)[0];
sha_key[1] = ((uint64_t *)auth_key)[1];
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[0], 0);
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[1], 1);
CVMX_MT_3DES_KEY (((uint64_t *)des_key)[2], 2);
CVMX_MT_3DES_IV (*((uint64_t *)des_iv));
/* Load SHA1 IV */
CVMX_MT_HSH_IV (md5[0], 0);
CVMX_MT_HSH_IV (md5[1], 1);
/* Load key xor ipad */
hash_key_md5(sha_key, 0x3636363636363636ULL);
/* setup enc/hmac args */
aptr = (uint64_t *)pktptr;
dptr = (uint64_t *)(pktptr+ESP_HEADER_LENGTH+DES_CBC_IV_LENGTH);
dlen = pktlen -ESP_HEADER_LENGTH-DES_CBC_IV_LENGTH-12;
((uint64_t *)outptr)[0]=((uint64_t *)pktptr)[0];
((uint64_t *)outptr)[1]=((uint64_t *)pktptr)[1];
rptr = (uint64_t *)(outptr+ESP_HEADER_LENGTH+DES_CBC_IV_LENGTH);
/* Load esp header and IV to hash unit */
CVMX_MT_HSH_DAT(*aptr++, 0);
CVMX_MT_HSH_DAT(*aptr++, 1);
in=*aptr++;
/* Load first block of data to DES Unit */
CVMX_MT_3DES_DEC_CBC (in);
/* Load first block of data to hash Unit */
CVMX_MT_HSH_DAT(in, 2);
hash_next = 3;
dlen -=8;
/* Loop through input */
while (dlen >= 16) {
in=*aptr++;
CVMX_MF_3DES_RESULT (out);
CVMX_MT_3DES_DEC_CBC(in);
_CVMX_MT_HSH_DAT (in, hash_next, 0);
rptr[0]=out;
in=*aptr++;
CVMX_MF_3DES_RESULT (out);
CVMX_MT_3DES_DEC_CBC(in);
_CVMX_MT_HSH_DAT (in, hash_next, 0);
rptr[1]=out;
rptr+=2;
dlen-=16;
}
if(dlen) {
in=*aptr++;
CVMX_MF_3DES_RESULT (out);
_CVMX_MT_HSH_DAT (in, hash_next, 0);
CVMX_MT_3DES_DEC_CBC(in);
rptr[0]=out;
rptr++;
}
CVMX_MF_3DES_RESULT (out);
rptr[0]=out;
rptr++;
pktlen = pktlen -12;
CVMX_MF_3DES_IV (*((uint64_t *)des_iv));
/* Finish Inner hash */
{
int chunk_len=pktlen& 63;
uint8_t i=0;
if(chunk_len == 56) {
chunk_len = 72;
} else
chunk_len = 64-chunk_len;
_CVMX_MT_HSH_DAT (0x8000000000000000ULL, hash_next, 0);
CVMX_ES64(in, ((pktlen +64) * 8));
chunk_len-=16;
while ( i< chunk_len) {
_CVMX_MT_HSH_DAT (0x0ULL, hash_next, 0);
i += 8;
}
_CVMX_MT_HSH_DAT (in, hash_next, 0);
}
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_hash[0], 0);
CVMX_MF_HSH_IV (inner_hash[1], 1);
/* Initialize hash unit */
CVMX_MT_HSH_IV (md5[0], 0);
CVMX_MT_HSH_IV (md5[1], 1);
/* Load key xor opad */
hash_key_md5(sha_key, 0x5c5c5c5c5c5c5c5cULL);
CVMX_MT_HSH_DAT(inner_hash[0], 0);
CVMX_MT_HSH_DAT(inner_hash[1], 1);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
CVMX_MT_HSH_DAT(0x0ULL, 3);
CVMX_MT_HSH_DAT(0x0ULL, 4);
CVMX_MT_HSH_DAT(0x0ULL, 5);
CVMX_MT_HSH_DAT(0x0ULL, 6);
in=(16+64)*8;
CVMX_ES64(in,in);
CVMX_MT_HSH_STARTMD5(in);
/* Get the HMAC */
CVMX_MF_HSH_IV ((((uint64_t *)&outptr[pktlen])[0]), 0);
CVMX_MF_HSH_IV (md5[1], 1);
((uint32_t *)&outptr[pktlen])[2] = md5[1] >> 32;
return 0;
}
int AES_cbc_md5_decrypt(uint16_t aes_key_len, uint8_t *aes_key, uint16_t auth_keylen, uint8_t *auth_key, uint8_t *aes_iv, uint8_t *pktptr, uint16_t pktlen, uint8_t *outptr, uint16_t *outlen, uint8_t compdigest)
{
uint64_t *dptr, *aptr,*rptr;
register uint64_t in1,in2,out1,out2;
register int hash_next;
uint64_t md5[2] = {
0x0123456789abcdefULL,
0xfedcba9876543210ULL
};
uint32_t dlen;
uint64_t sha_key[2];
uint64_t inner_hash[2];
(void)compdigest;
prefetch_packet(pktptr, pktlen);
/* Load AES Key and IV */
load_aes_key_and_iv(aes_key_len, aes_key, aes_iv);
sha_key[0] = ((uint64_t *)auth_key)[0];
sha_key[1] = ((uint64_t *)auth_key)[1];
/* Load MD5 IV */
CVMX_MT_HSH_IV (md5[0], 0);
CVMX_MT_HSH_IV (md5[1], 1);
/* Load key xor ipad */
hash_key_md5(sha_key, 0x3636363636363636ULL);
/* Setup dec/hmac args */
dptr = (uint64_t *) (pktptr+ESP_HEADER_LENGTH+AES_CBC_IV_LENGTH) ;
dlen = pktlen -ESP_HEADER_LENGTH-AES_CBC_IV_LENGTH-12;
aptr = (uint64_t *) pktptr ;
((uint64_t *)outptr)[0]=((uint64_t *)pktptr)[0];
((uint64_t *)outptr)[1]=((uint64_t *)pktptr)[1];
((uint64_t *)outptr)[2]=((uint64_t *)pktptr)[2];
rptr= (uint64_t *)(outptr+ESP_HEADER_LENGTH+AES_CBC_IV_LENGTH);
/* Load esp header and IV to hash unit */
CVMX_MT_HSH_DAT(*aptr++, 0);
CVMX_MT_HSH_DAT(*aptr++, 1);
CVMX_MT_HSH_DAT(*aptr++, 2);
in1=*aptr++;
in2=*aptr++;
/* Load first block of data to hash Unit */
CVMX_MT_HSH_DAT(in1, 3);
CVMX_MT_HSH_DAT(in2, 4);
hash_next = 5;
/* Load first block of data to AES Unit */
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
dlen -= 16;
/* Loop through input */
while (dlen >= 32) {
in1=*aptr++;
in2=*aptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (in1, hash_next, 0);
_CVMX_MT_HSH_DAT (in2, hash_next, 0);
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
rptr[0]=out1;
rptr[1]=out2;
in1=*aptr++;
in2=*aptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (in1, hash_next, 0);
_CVMX_MT_HSH_DAT (in2, hash_next, 0);
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
rptr[2]=out1;
rptr[3]=out2;
rptr+=4;
dlen -=32;
}
if(dlen) {
in1=*aptr++;
in2=*aptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (in1, hash_next, 0);
_CVMX_MT_HSH_DAT (in2, hash_next, 0);
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
}
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
pktlen = pktlen -12;
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[0], 0);
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[1], 1);
/* Finish Inner hash */
{
int chunk_len=pktlen & 63;
uint8_t i=0;
if(chunk_len == 56) {
chunk_len = 72;
} else
chunk_len = 64-chunk_len;
in1=(pktlen + 64) *8;
CVMX_ES64(in1,in1);
_CVMX_MT_HSH_DAT (0x8000000000000000ULL, hash_next, 0);
chunk_len-=16;
while ( i< chunk_len) {
_CVMX_MT_HSH_DAT (0x0ULL, hash_next, 0);
i += 8;
}
_CVMX_MT_HSH_DAT (in1, hash_next, 0);
}
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_hash[0], 0);
CVMX_MF_HSH_IV (inner_hash[1], 1);
/* Initialize hash unit */
CVMX_MT_HSH_IV (md5[0], 0);
CVMX_MT_HSH_IV (md5[1], 1);
/* Load key xor opad */
hash_key_md5(sha_key, 0x5c5c5c5c5c5c5c5cULL);
CVMX_MT_HSH_DAT(inner_hash[0], 0);
CVMX_MT_HSH_DAT(inner_hash[1], 1);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
CVMX_MT_HSH_DAT(0x0ULL, 3);
CVMX_MT_HSH_DAT(0x0ULL, 4);
CVMX_MT_HSH_DAT(0x0ULL, 5);
CVMX_MT_HSH_DAT(0x0ULL, 6);
in1=(16+64)*8;
CVMX_ES64(in1,in1);
CVMX_MT_HSH_STARTMD5(in1);
/* Get the HMAC */
CVMX_MF_HSH_IV ((((uint64_t *)&outptr[pktlen])[0]), 0);
CVMX_MF_HSH_IV (md5[1], 1);
((uint32_t *)&outptr[pktlen])[2] = md5[1] >> 32;
return 0;
}
int AES_cbc_md5_encrypt(uint16_t aes_key_len, uint8_t *aes_key, uint16_t auth_keylen, uint8_t *auth_key, uint8_t *espheader, uint8_t *aes_iv, uint8_t *pktptr, uint16_t pktlen, uint8_t *outptr, uint16_t *outlen)
{
uint64_t *dptr, *aptr,*rptr;
register uint64_t in1,in2,out1,out2;
register int hash_next;
uint32_t dlen;
uint64_t md5[2] = {
0x0123456789abcdefULL,
0xfedcba9876543210ULL
};
uint64_t sha_key[2];
uint64_t inner_hash[3];
prefetch_packet(pktptr, pktlen);
sha_key[0] = ((uint64_t *)auth_key)[0];
sha_key[1] = ((uint64_t *)auth_key)[1];
/* Load AES Key and IV */
load_aes_key_and_iv(aes_key_len, aes_key, aes_iv);
/* Load SHA1 IV */
CVMX_MT_HSH_IV (md5[0], 0);
CVMX_MT_HSH_IV (md5[1], 1);
/* Load key xor ipad */
hash_key_md5(sha_key, 0x3636363636363636ULL);
/* load esp header and aes_iv */
CVMX_MT_HSH_DAT(((uint64_t *)espheader)[0], 0);
CVMX_MT_HSH_DAT(((uint64_t *)aes_iv)[0], 1);
CVMX_MT_HSH_DAT(((uint64_t *)aes_iv)[1], 2);
hash_next = 3;
/* setup enc/hmac args */
dptr = (uint64_t *)pktptr;
dlen = pktlen;
in1=*dptr++;
in2=*dptr++;
((uint64_t *)outptr)[0]=((uint64_t *)espheader)[0];
((uint64_t *)outptr)[1]=((uint64_t *)aes_iv)[0];
((uint64_t *)outptr)[2]=((uint64_t *)aes_iv)[1];
rptr = (uint64_t *)(outptr+ESP_HEADER_LENGTH+AES_CBC_IV_LENGTH);
aptr = (uint64_t *)rptr;
/* Start encryption */
/* load first block of data to AES uint */
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
dlen -=16;
/* Loop through input */
/* Assumed that data is 16 byte aligned */
while (dlen >= 32) {
in1=*dptr++;
in2=*dptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (out1, hash_next, 0);
_CVMX_MT_HSH_DAT (out2, hash_next, 0);
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
rptr[0]=out1;
rptr[1]=out2;
in1=*dptr++;
in2=*dptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (out1, hash_next, 0);
_CVMX_MT_HSH_DAT (out2, hash_next, 0);
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
rptr[2]=out1;
rptr[3]=out2;
dlen -=32;
rptr+=4;
}
if(dlen) {
in1=*dptr++;
in2=*dptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (out1, hash_next, 0);
_CVMX_MT_HSH_DAT (out2, hash_next, 0);
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
}
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (out1, hash_next, 0);
_CVMX_MT_HSH_DAT (out2, hash_next, 0);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[0], 0);
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[1], 1);
/* Finish inner hash */
{
int chunk_len=(pktlen+ESP_HEADER_LENGTH+AES_CBC_IV_LENGTH) & 63;
uint8_t i=0;
if(chunk_len == 56) {
chunk_len = 72;
} else
chunk_len = 64-chunk_len;
in1 = (pktlen+ESP_HEADER_LENGTH + AES_CBC_IV_LENGTH +64)*8;
CVMX_ES64(in1,in1);
chunk_len-=16;
_CVMX_MT_HSH_DAT (0x8000000000000000ULL, hash_next, 0);
while ( i< chunk_len) {
_CVMX_MT_HSH_DAT (0x0ULL, hash_next, 0);
i += 8;
}
_CVMX_MT_HSH_DAT (in1, hash_next, 0);
}
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_hash[0], 0);
CVMX_MF_HSH_IV (inner_hash[1], 1);
/* Initialize hash unit */
CVMX_MT_HSH_IV (md5[0], 0);
CVMX_MT_HSH_IV (md5[1], 1);
/* Load key xor opad */
hash_key_md5(sha_key, 0x5c5c5c5c5c5c5c5cULL);
CVMX_MT_HSH_DAT(inner_hash[0], 0);
CVMX_MT_HSH_DAT(inner_hash[1], 1);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
CVMX_MT_HSH_DAT(0x0ULL, 3);
CVMX_MT_HSH_DAT(0x0ULL, 4);
CVMX_MT_HSH_DAT(0x0ULL, 5);
CVMX_MT_HSH_DAT(0x0ULL, 6);
in1=(16+64)*8;
CVMX_ES64(in1,in1);
CVMX_MT_HSH_STARTMD5(in1);
/* Get the HMAC */
CVMX_MF_HSH_IV (rptr[0], 0);
CVMX_MF_HSH_IV (md5[1], 1);
((uint32_t *)rptr)[2] = md5[1] >> 32;
return 0;
}
int AES_cbc_sha1_encrypt_fast(uint16_t aes_key_len, uint8_t *aes_key, uint8_t *espheader, uint8_t *aes_iv, uint8_t *pktptr, uint16_t pktlen, uint8_t *outptr, uint8_t *ictx, uint8_t *octx)
{
uint64_t *dptr, *rptr;
uint32_t dlen;
uint64_t inner_sha[3];
register uint64_t in1,in2,out1,out2;
register uint64_t zero = 0x0ULL;
register uint32_t sha1_next;
prefetch_packet(pktptr, pktlen);
/* Load SHA1 IV */
CVMX_MT_HSH_IV (((uint64_t *)ictx)[0], 0);
CVMX_MT_HSH_IV (((uint64_t *)ictx)[1], 1);
CVMX_MT_HSH_IV (((uint64_t *)ictx)[2], 2);
/* Load AES Key and IV */
load_aes_key_and_iv(aes_key_len, aes_key, aes_iv);
/* setup arguments */
dptr = (uint64_t *) pktptr;
((uint64_t *)outptr)[0]=((uint64_t *)espheader)[0];
((uint64_t *)outptr)[1]=((uint64_t *)aes_iv)[0];
((uint64_t *)outptr)[2]=((uint64_t *)aes_iv)[1];
rptr = (uint64_t *)(outptr+ESP_HEADER_LENGTH+AES_CBC_IV_LENGTH);
in1=*dptr++;
in2=*dptr++;
/* Load ESP header & AES IV into hash unit */
CVMX_MT_HSH_DAT(((uint64_t *)espheader)[0], 0);
CVMX_MT_HSH_DAT(((uint64_t *)aes_iv)[0], 1);
CVMX_MT_HSH_DAT(((uint64_t *)aes_iv)[1], 2);
sha1_next = 3;
/* Start encryption */
/* load first block of data to AES uint */
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
dlen = pktlen - 16;
/* Loop through input */
/* Assumed that data is 16 byte aligned */
while (dlen >= 32) {
in1 = *dptr++;
in2 = *dptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
switch (sha1_next)
{
case 0:
CVMX_MT_HSH_DAT (out1, 0);
CVMX_MT_HSH_DAT (out2, 1);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 2);
CVMX_MT_HSH_DAT (out2, 3);
sha1_next = 4;
break;
case 1:
CVMX_MT_HSH_DAT (out1, 1);
CVMX_MT_HSH_DAT (out2, 2);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 3);
CVMX_MT_HSH_DAT (out2, 4);
sha1_next = 5;
break;
case 2:
CVMX_MT_HSH_DAT (out1, 2);
CVMX_MT_HSH_DAT (out2, 3);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 4);
CVMX_MT_HSH_DAT (out2, 5);
sha1_next = 6;
break;
case 3:
CVMX_MT_HSH_DAT (out1, 3);
CVMX_MT_HSH_DAT (out2, 4);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 5);
CVMX_MT_HSH_DAT (out2, 6);
sha1_next = 7;
break;
case 4:
CVMX_MT_HSH_DAT (out1, 4);
CVMX_MT_HSH_DAT (out2, 5);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 6);
CVMX_MT_HSH_STARTSHA (out2);
sha1_next = 0;
break;
case 5:
CVMX_MT_HSH_DAT (out1, 5);
CVMX_MT_HSH_DAT (out2, 6);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_STARTSHA (out1);
CVMX_MT_HSH_DAT (out2, 0);
sha1_next = 1;
break;
case 6:
CVMX_MT_HSH_DAT (out1, 6);
CVMX_MT_HSH_STARTSHA (out2);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 0);
CVMX_MT_HSH_DAT (out2, 1);
sha1_next = 2;
break;
case 7:
CVMX_MT_HSH_STARTSHA (out1);
CVMX_MT_HSH_DAT (out2, 0);
CVMX_AES_ENC(in1, in2, out1, out2, rptr, dptr);
CVMX_MT_HSH_DAT (out1, 1);
CVMX_MT_HSH_DAT (out2, 2);
sha1_next = 3;
break;
default:
return -1;
}
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
rptr[2]=out1;
rptr[3]=out2;
rptr+=4;
dlen-=32;
}
if(dlen) {
in1 = *dptr++;
in2 = *dptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (out1, sha1_next, 1);
_CVMX_MT_HSH_DAT (out2, sha1_next, 1);
CVMX_MT_AES_ENC_CBC0 (in1);
CVMX_MT_AES_ENC_CBC1 (in2);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
}
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[0], 0);
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[1], 1);
/* Finish inner hash */
switch (sha1_next)
{
case 1:
CVMX_MT_HSH_DAT (out1, 1);
CVMX_MT_HSH_DAT (out2, 2);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 3:
CVMX_MT_HSH_DAT (out1, 3);
CVMX_MT_HSH_DAT (out2, 4);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 5:
CVMX_MT_HSH_DAT (out1, 5);
CVMX_MT_HSH_DAT (out2, 6);
CVMX_MT_HSH_STARTSHA(0x8000000000000000ULL);
CVMX_MT_HSH_DAT(zero, 0);
CVMX_MT_HSH_DAT(zero, 1);
CVMX_MT_HSH_DAT(zero, 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 7:
CVMX_MT_HSH_STARTSHA(out1);
CVMX_MT_HSH_DAT(out2, 0);
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 1);
CVMX_MT_HSH_DAT(zero, 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
default:
return -1;
}
CVMX_MT_HSH_STARTSHA((pktlen + ESP_HEADER_LENGTH + AES_CBC_IV_LENGTH + 64) * 8);
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_sha[0], 0);
CVMX_MF_HSH_IV (inner_sha[1], 1);
CVMX_MF_HSH_IV (inner_sha[2], 2);
/* Load SHA1 IV */
CVMX_MT_HSH_IV (((uint64_t *)octx)[0], 0);
CVMX_MT_HSH_IV (((uint64_t *)octx)[1], 1);
CVMX_MT_HSH_IV (((uint64_t *)octx)[2], 2);
CVMX_MT_HSH_DAT(inner_sha[0], 0);
CVMX_MT_HSH_DAT(inner_sha[1], 1);
*(uint32_t *)((uint8_t *)inner_sha + 20) = 0x80000000;
CVMX_MT_HSH_DAT(inner_sha[2], 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
CVMX_MT_HSH_STARTSHA((uint64_t)((64 + 20) * 8));
/* Get the HMAC */
CVMX_MF_HSH_IV (rptr[0], 0);
CVMX_MF_HSH_IV (inner_sha[1], 1);
((uint32_t *)rptr)[2] = inner_sha[1] >> 32;
return 0;
}
int AES_cbc_sha1_decrypt_fast(uint16_t aes_key_len, uint8_t *aes_key, uint8_t *aes_iv, uint8_t *pktptr, uint16_t pktlen, uint8_t *outptr, uint8_t *ictx, uint8_t *octx)
{
uint64_t *aptr, *rptr;
uint32_t dlen;
uint64_t inner_sha[3];
register uint64_t in1,in2,out1,out2;
register uint64_t zero = 0x0ULL;
register uint32_t sha1_next;
prefetch_packet(pktptr, pktlen);
/* Load SHA1 IV */
CVMX_MT_HSH_IV (((uint64_t *)ictx)[0], 0);
CVMX_MT_HSH_IV (((uint64_t *)ictx)[1], 1);
CVMX_MT_HSH_IV (((uint64_t *)ictx)[2], 2);
/* Load AES Key and IV */
load_aes_key_and_iv(aes_key_len, aes_key, aes_iv);
/* setup enc/hmac args */
aptr = (uint64_t *)pktptr;
rptr = (uint64_t *)(outptr+ESP_HEADER_LENGTH+AES_CBC_IV_LENGTH);
/*load header and IV to hash uint */
CVMX_MT_HSH_DAT(*aptr++, 0);
CVMX_MT_HSH_DAT(*aptr++, 1);
CVMX_MT_HSH_DAT(*aptr++, 2);
in1=*aptr++;
in2=*aptr++;
/* Load first block of data to AES Unit */
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
dlen = pktlen-ESP_HEADER_LENGTH-AES_CBC_IV_LENGTH-12-16;
/* Load first block of data to hash Unit */
CVMX_MT_HSH_DAT(in1, 3);
CVMX_MT_HSH_DAT(in2, 4);
sha1_next = 5;
/* Loop through input */
while (dlen >= 32) {
in1=*aptr++;
in2=*aptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
switch (sha1_next)
{
case 0:
CVMX_MT_HSH_DAT (in1, 0);
CVMX_MT_HSH_DAT (in2, 1);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 2);
CVMX_MT_HSH_DAT (in2, 3);
sha1_next = 4;
break;
case 1:
CVMX_MT_HSH_DAT (in1, 1);
CVMX_MT_HSH_DAT (in2, 2);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 3);
CVMX_MT_HSH_DAT (in2, 4);
sha1_next = 5;
break;
case 2:
CVMX_MT_HSH_DAT (in1, 2);
CVMX_MT_HSH_DAT (in2, 3);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 4);
CVMX_MT_HSH_DAT (in2, 5);
sha1_next = 6;
break;
case 3:
CVMX_MT_HSH_DAT (in1, 3);
CVMX_MT_HSH_DAT (in2, 4);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 5);
CVMX_MT_HSH_DAT (in2, 6);
sha1_next = 7;
break;
case 4:
CVMX_MT_HSH_DAT (in1, 4);
CVMX_MT_HSH_DAT (in2, 5);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 6);
CVMX_MT_HSH_STARTSHA (in2);
sha1_next = 0;
break;
case 5:
CVMX_MT_HSH_DAT (in1, 5);
CVMX_MT_HSH_DAT (in2, 6);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_STARTSHA (in1);
CVMX_MT_HSH_DAT (in2, 0);
sha1_next = 1;
break;
case 6:
CVMX_MT_HSH_DAT (in1, 6);
CVMX_MT_HSH_STARTSHA (in2);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 0);
CVMX_MT_HSH_DAT (in2, 1);
sha1_next = 2;
break;
case 7:
CVMX_MT_HSH_STARTSHA (in1);
CVMX_MT_HSH_DAT (in2, 0);
CVMX_AES_DEC(in1, in2, out1, out2, rptr, aptr);
CVMX_MT_HSH_DAT (in1, 1);
CVMX_MT_HSH_DAT (in2, 2);
sha1_next = 3;
break;
default:
return -1;
}
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
rptr[2]=out1;
rptr[3]=out2;
rptr+=4;
dlen-=32;
}
if(dlen) {
in1=*aptr++;
in2=*aptr++;
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
_CVMX_MT_HSH_DAT (in1, sha1_next, 1);
_CVMX_MT_HSH_DAT (in2, sha1_next, 1);
CVMX_MT_AES_DEC_CBC0 (in1);
CVMX_MT_AES_DEC_CBC1 (in2);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
}
CVMX_MF_AES_RESULT (out1, 0);
CVMX_MF_AES_RESULT (out2, 1);
rptr[0]=out1;
rptr[1]=out2;
rptr+=2;
pktlen = pktlen -12 ;
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[0], 0);
CVMX_MF_AES_IV (((uint64_t *)aes_iv)[1], 1);
/* Finish inner hash */
switch (sha1_next)
{
case 1:
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 1);
CVMX_MT_HSH_DAT(zero, 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 3:
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 5:
CVMX_MT_HSH_DAT(0x8000000000000000ULL, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
case 7:
CVMX_MT_HSH_STARTSHA(0x8000000000000000ULL);
CVMX_MT_HSH_DAT(zero, 0);
CVMX_MT_HSH_DAT(zero, 1);
CVMX_MT_HSH_DAT(zero, 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
break;
default:
return -1;
}
CVMX_MT_HSH_STARTSHA((pktlen + 64) * 8);
/* Get the inner hash of HMAC */
CVMX_MF_HSH_IV (inner_sha[0], 0);
CVMX_MF_HSH_IV (inner_sha[1], 1);
CVMX_MF_HSH_IV (inner_sha[2], 2);
/* Load SHA1 IV */
CVMX_MT_HSH_IV (((uint64_t *)octx)[0], 0);
CVMX_MT_HSH_IV (((uint64_t *)octx)[1], 1);
CVMX_MT_HSH_IV (((uint64_t *)octx)[2], 2);
CVMX_MT_HSH_DAT(inner_sha[0], 0);
CVMX_MT_HSH_DAT(inner_sha[1], 1);
*(uint32_t *)((uint8_t *)inner_sha + 20) = 0x80000000;
CVMX_MT_HSH_DAT(inner_sha[2], 2);
CVMX_MT_HSH_DAT(zero, 3);
CVMX_MT_HSH_DAT(zero, 4);
CVMX_MT_HSH_DAT(zero, 5);
CVMX_MT_HSH_DAT(zero, 6);
CVMX_MT_HSH_STARTSHA((uint64_t)((64 + 20) * 8));
/* Get the HMAC */
CVMX_MF_HSH_IV ((((uint64_t *)&outptr[pktlen])[0]), 0);
CVMX_MF_HSH_IV (inner_sha[1], 1);
((uint32_t *)&outptr[pktlen])[2] = inner_sha[1] >> 32;
return 0;
}
unsigned int hw_crc32(unsigned int *buf, unsigned int num)
{
unsigned int ret, i;
CVMX_MT_CRC_POLYNOMIAL(0x1edc6f41);
CVMX_MT_CRC_IV(0);
for (i=0; i<num; i++)
CVMX_MT_CRC_WORD(buf[i]);
CVMX_MF_CRC_IV(ret);
return ret;
}
unsigned short hw_crc16(unsigned int *buf, unsigned int num)
{
unsigned int ret, i;
CVMX_MT_CRC_POLYNOMIAL((0x1021) << 16);
CVMX_MT_CRC_IV((0xffff) << 16);
for (i=0; i<num; i++)
CVMX_MT_CRC_WORD(buf[i]);
CVMX_MF_CRC_IV(ret);
return ret >> 16;
}
unsigned int hw_crc32_one_word(unsigned int w)
{
unsigned int ret;
CVMX_MT_CRC_POLYNOMIAL(0x1edc6f41);
CVMX_MT_CRC_IV(0);
CVMX_MT_CRC_WORD(w);
CVMX_MF_CRC_IV(ret);
return ret;
}