2195 lines
67 KiB
C
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;
|
|
}
|