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