diff options
Diffstat (limited to 'client/wolfssl/wolfcrypt/src/port/cavium')
4 files changed, 885 insertions, 0 deletions
diff --git a/client/wolfssl/wolfcrypt/src/port/cavium/README.md b/client/wolfssl/wolfcrypt/src/port/cavium/README.md new file mode 100644 index 0000000..b98d866 --- /dev/null +++ b/client/wolfssl/wolfcrypt/src/port/cavium/README.md @@ -0,0 +1,3 @@ +# Cavium Nitrox III/V Support + +Please contact wolfSSL at [email protected] to request an evaluation. diff --git a/client/wolfssl/wolfcrypt/src/port/cavium/README_Octeon.md b/client/wolfssl/wolfcrypt/src/port/cavium/README_Octeon.md new file mode 100644 index 0000000..b2670d0 --- /dev/null +++ b/client/wolfssl/wolfcrypt/src/port/cavium/README_Octeon.md @@ -0,0 +1,3 @@ +# Cavium Octeon III CN7300 + +Please contact wolfSSL at [email protected] to request an evaluation. diff --git a/client/wolfssl/wolfcrypt/src/port/cavium/cavium_nitrox.c b/client/wolfssl/wolfcrypt/src/port/cavium/cavium_nitrox.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/client/wolfssl/wolfcrypt/src/port/cavium/cavium_nitrox.c diff --git a/client/wolfssl/wolfcrypt/src/port/cavium/cavium_octeon_sync.c b/client/wolfssl/wolfcrypt/src/port/cavium/cavium_octeon_sync.c new file mode 100644 index 0000000..078e8cb --- /dev/null +++ b/client/wolfssl/wolfcrypt/src/port/cavium/cavium_octeon_sync.c @@ -0,0 +1,879 @@ +/* cavium_octeon_sync.c + * + * Copyright(C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL.(formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + *(at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <wolfssl/wolfcrypt/settings.h> +#include <wolfssl/wolfcrypt/error-crypt.h> +#include <wolfssl/wolfcrypt/wc_port.h> + +#ifdef HAVE_CAVIUM_OCTEON_SYNC + +/* Setting NO_MAIN_DRIVER here because this file ends up building + * in the library sources which doesn't have NO_MAIN_DRIVER set, + * as the library expects main to be somewhere else. */ +#undef NO_MAIN_DRIVER +#define NO_MAIN_DRIVER + +#include <wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include "cvmx.h" +#include "cvmx-asm.h" +#include "cvmx-key.h" +#include "cvmx-swap.h" + +#ifndef NO_DES3 + #include <wolfssl/wolfcrypt/des3.h> +#endif +#ifndef NO_AES + #include <wolfssl/wolfcrypt/aes.h> +#endif + +#define NOOPT __attribute__((optimize("O0"))) + +static int devId = 1234; + +#ifndef NO_DES3 +static int Octeon_Des3_CbcEncrypt(Des3* des3, + uint64_t *inp64, uint64_t *outp64, size_t inl) +{ + register uint64_t i0, r0; + uint64_t *key, *iv; + + if (des3 == NULL || inp64 == NULL || outp64 == NULL) + return BAD_FUNC_ARG; + + /* expects 64-bit aligned value */ + key = (uint64_t*)des3->devKey; + CVMX_MT_3DES_KEY(key[0], 0); + CVMX_MT_3DES_KEY(key[1], 1); + CVMX_MT_3DES_KEY(key[2], 2); + iv = (uint64_t*)des3->reg; + CVMX_MT_3DES_IV(iv[0]); + + CVMX_PREFETCH0(inp64); + + i0 = *inp64; + + /* DES3 assembly can handle 16-byte chunks */ + if (inl >= 16) { + CVMX_MT_3DES_ENC_CBC(i0); + inl -= 8; + inp64++; + outp64++; + + if (inl >= 8) { + i0 = inp64[0]; + CVMX_MF_3DES_RESULT(r0); + CVMX_MT_3DES_ENC_CBC(i0); + + for (;;) { + outp64[-1] = r0; + inl -= 8; + inp64++; + outp64++; + i0 = *inp64; + + if (inl < 8) + break; + + CVMX_PREFETCH(inp64, 64); + CVMX_MF_3DES_RESULT(r0); + CVMX_MT_3DES_ENC_CBC(i0); + } + } + CVMX_MF_3DES_RESULT(r0); + outp64[-1] = r0; + } + /* remainder */ + if (inl > 0) { + uint64_t r = 0; + if (inl <= 8) { + XMEMCPY(&r, inp64, inl); + CVMX_MT_3DES_ENC_CBC(r); + CVMX_MF_3DES_RESULT(*outp64); + } + else { + i0 = *inp64; + CVMX_MT_3DES_ENC_CBC(i0); + CVMX_MF_3DES_RESULT(*outp64); + inp64++, outp64++; + + XMEMCPY(&r, inp64, inl); + CVMX_MT_3DES_ENC_CBC(r); + CVMX_MF_3DES_RESULT(*outp64); + } + } + + CVMX_MT_3DES_IV(iv[0]); + + return 0; +} + +static int Octeon_Des3_CbcDecrypt(Des3* des3, + uint64_t *inp64, uint64_t *outp64, size_t inl) +{ + register uint64_t i0, r0; + uint64_t *key, *iv; + + if (des3 == NULL || inp64 == NULL || outp64 == NULL) + return BAD_FUNC_ARG; + + /* expects 64-bit aligned value */ + key = (uint64_t*)des3->devKey; + CVMX_MT_3DES_KEY(key[0], 0); + CVMX_MT_3DES_KEY(key[1], 1); + CVMX_MT_3DES_KEY(key[2], 2); + + iv = (uint64_t*)des3->reg; + CVMX_MT_3DES_IV(iv[0]); + + CVMX_PREFETCH0(inp64); + + i0 = *inp64; + + /* DES3 assembly can handle 16-byte chunks */ + if (inl >= 16) { + CVMX_MT_3DES_DEC_CBC(i0); + inl -= 8; + inp64++; + outp64++; + + if (inl >= 8) { + i0 = inp64[0]; + CVMX_MF_3DES_RESULT(r0); + CVMX_MT_3DES_DEC_CBC(i0); + + for (;;) { + outp64[-1] = r0; + inl -= 8; + inp64++; + outp64++; + i0 = *inp64; + + if (inl < 8) + break; + + CVMX_PREFETCH(inp64, 64); + CVMX_MF_3DES_RESULT(r0); + CVMX_MT_3DES_DEC_CBC(i0); + } + } + + CVMX_MF_3DES_RESULT(r0); + outp64[-1] = r0; + } + /* remainder */ + if (inl > 0) { + if (inl <= 8) { + uint64_t r = 0; + XMEMCPY(&r, inp64, inl); + CVMX_MT_3DES_DEC_CBC(r); + CVMX_MF_3DES_RESULT(*outp64); + } + else { + uint64_t r = 0; + i0 = *inp64; + CVMX_MT_3DES_DEC_CBC(i0); + CVMX_MF_3DES_RESULT(*outp64); + inp64++, outp64++; + + XMEMCPY(&r, inp64, inl); + CVMX_MT_3DES_DEC_CBC(r); + CVMX_MF_3DES_RESULT(*outp64); + } + } + + CVMX_MT_3DES_IV(iv[0]); + + return 0; +} +#endif /* !NO_DES3 */ + + +#ifndef NO_AES + +#ifdef HAVE_AES_CBC +static int Octeon_AesCbc_Encrypt(Aes *aes, + uint64_t *inp64, uint64_t *outp64, size_t inl) +{ + register uint64_t i0, i1, r0, r1; + uint64_t *key, *iv; + + if (aes == NULL || inp64 == NULL || outp64 == NULL) { + return BAD_FUNC_ARG; + } + + iv = (uint64_t*)aes->reg; + CVMX_MT_AES_IV(iv[0], 0); + CVMX_MT_AES_IV(iv[1], 1); + + key = (uint64_t*)aes->devKey; + CVMX_MT_AES_KEY(key[0], 0); + CVMX_MT_AES_KEY(key[1], 1); + CVMX_MT_AES_KEY(key[2], 2); + CVMX_MT_AES_KEY(key[3], 3); + + CVMX_MT_AES_KEYLENGTH(aes->keylen/8 - 1); + + CVMX_PREFETCH0(inp64); + + i0 = inp64[0]; + i1 = inp64[1]; + + /* AES assembly can handle 32-byte chunks */ + if (inl >= 32) { + CVMX_MT_AES_ENC_CBC0(i0); + CVMX_MT_AES_ENC_CBC1(i1); + inl -= 16; + inp64 += 2; + outp64 += 2; + + if (inl >= 16) { + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + i0 = inp64[0]; + i1 = inp64[1]; + CVMX_MT_AES_ENC_CBC0(i0); + CVMX_MT_AES_ENC_CBC1(i1); + + for (;;) { + outp64[-2] = r0; + outp64[-1] = r1; + outp64 += 2; + inp64 += 2; + inl -= 16; + i0 = inp64[0]; + i1 = inp64[1]; + + if (inl < 16) + break; + + CVMX_PREFETCH(inp64, 64); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + CVMX_MT_AES_ENC_CBC0(i0); + CVMX_MT_AES_ENC_CBC1(i1); + } + } + + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[-2] = r0; + outp64[-1] = r1; + } + /* remainder */ + if (inl > 0) { + uint64_t in64[2] = { 0, 0 }; + if (inl <= 16) { + XMEMCPY(in64, inp64, inl); + CVMX_MT_AES_ENC_CBC0(in64[0]); + CVMX_MT_AES_ENC_CBC1(in64[1]); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[0] = r0; + outp64[1] = r1; + } + else { + CVMX_MT_AES_ENC_CBC0(i0); + CVMX_MT_AES_ENC_CBC1(i1); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + inl -= 16; + outp64[0] = r0; + outp64[1] = r1; + inp64 += 2; + outp64 += 2; + XMEMCPY(in64, inp64, inl); + CVMX_MT_AES_ENC_CBC0(in64[0]); + CVMX_MT_AES_ENC_CBC1(in64[1]); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[0] = r0; + outp64[1] = r1; + } + } + + CVMX_MF_AES_IV(iv[0], 0); + CVMX_MF_AES_IV(iv[1], 1); + + return 0; +} + +static int Octeon_AesCbc_Decrypt(Aes *aes, + uint64_t *inp64, uint64_t *outp64, size_t inl) +{ + register uint64_t i0, i1, r0, r1; + uint64_t *key, *iv; + + if (aes == NULL || inp64 == NULL || outp64 == NULL) { + return BAD_FUNC_ARG; + } + + iv = (uint64_t*)aes->reg; + key = (uint64_t*)aes->devKey; + + CVMX_MT_AES_IV(iv[0], 0); + CVMX_MT_AES_IV(iv[1], 1); + + CVMX_MT_AES_KEY(key[0], 0); + CVMX_MT_AES_KEY(key[1], 1); + CVMX_MT_AES_KEY(key[2], 2); + CVMX_MT_AES_KEY(key[3], 3); + CVMX_MT_AES_KEYLENGTH(aes->keylen/8 - 1); + + CVMX_PREFETCH0(inp64); + + i0 = inp64[0]; + i1 = inp64[1]; + + /* AES assembly can handle 32-byte chunks */ + if (inl >= 32) { + CVMX_MT_AES_DEC_CBC0(i0); + CVMX_MT_AES_DEC_CBC1(i1); + inp64 += 2; + outp64 += 2; + inl -= 16; + + if (inl >= 16) { + i0 = inp64[0]; + i1 = inp64[1]; + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + CVMX_MT_AES_DEC_CBC0(i0); + CVMX_MT_AES_DEC_CBC1(i1); + + for (;;) { + outp64[-2] = r0; + outp64[-1] = r1; + outp64 += 2; + inp64 += 2; + inl -= 16; + i0 = inp64[0]; + i1 = inp64[1]; + + if (inl < 16) + break; + + CVMX_PREFETCH(inp64, 64); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + CVMX_MT_AES_DEC_CBC0(i0); + CVMX_MT_AES_DEC_CBC1(i1); + } + } + + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[-2] = r0; + outp64[-1] = r1; + } + /* remainder */ + if (inl > 0) { + uint64_t in64[2] = { 0, 0 }; + XMEMCPY(in64, inp64, inl); + CVMX_MT_AES_DEC_CBC0(in64[0]); + CVMX_MT_AES_DEC_CBC1(in64[1]); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[0] = r0; + outp64[1] = r1; + } + + CVMX_MF_AES_IV(iv[0], 0); + CVMX_MF_AES_IV(iv[1], 1); + + return 0; +} +#endif /* HAVE_AES_CBC */ + + +#ifdef HAVE_AESGCM + +#define CVM_AES_RD_RESULT_WR_DATA(in1, in2, out1, out2) \ + asm volatile(\ + ".set noreorder \n" \ + "dmfc2 %[r1],0x0100\n" \ + "dmfc2 %[r2],0x0101\n" \ + "dmtc2 %[r3],0x010a\n" \ + "dmtc2 %[r4],0x310b\n" \ + ".set reorder \n" \ + : [r1] "=&d"(in1) , [r2] "=&d"(in2) \ + : [r3] "d"(out1), [r4] "d"(out2)) + +static NOOPT void Octeon_GHASH_Restore(word16 poly, byte* h) +{ + word64* bigH = (word64*)h; + CVMX_MT_GFM_POLY((word64)poly); + CVMX_MT_GFM_MUL(bigH[0], 0); + CVMX_MT_GFM_MUL(bigH[1], 1); +} + + +static NOOPT void Octeon_GHASH_Init(word16 poly, byte* h) +{ + Octeon_GHASH_Restore(poly, h); + CVMX_MT_GFM_RESINP(0, 0); + CVMX_MT_GFM_RESINP(0, 1); +} + + +static NOOPT void Octeon_GHASH_Update(byte* in) +{ + word64* bigIn = (word64*)in; + CVMX_MT_GFM_XOR0(bigIn[0]); + CVMX_MT_GFM_XORMUL1(bigIn[1]); +} + + +static NOOPT void Octeon_GHASH_Final(byte* out, word64 authInSz, word64 inSz) +{ + word64* bigOut = (word64*)out; + + CVMX_MT_GFM_XOR0(authInSz * 8); + CVMX_MT_GFM_XORMUL1(inSz * 8); + CVMX_MF_GFM_RESINP(bigOut[0], 0); + CVMX_MF_GFM_RESINP(bigOut[1], 1); +} + + +/* Sets the Octeon key with the key found in the Aes record. */ +static NOOPT int Octeon_AesGcm_SetKey(Aes* aes) +{ + int ret = 0; + + if (aes == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + uint64_t* key = (uint64_t*)aes->devKey; + + CVMX_MT_AES_KEY(key[0], 0); + CVMX_MT_AES_KEY(key[1], 1); + CVMX_MT_AES_KEY(key[2], 2); + CVMX_MT_AES_KEY(key[3], 3); + CVMX_MT_AES_KEYLENGTH((aes->keylen / 8) - 1); + + if (!aes->keySet) { + uint64_t* bigH = (uint64_t*)aes->H; + CVMX_MT_AES_ENC0(0); + CVMX_MT_AES_ENC1(0); + CVMX_MF_AES_RESULT(bigH[0], 0); + CVMX_MF_AES_RESULT(bigH[1], 1); + aes->keySet = 1; + } + } + + return ret; +} + + +static NOOPT int Octeon_AesGcm_SetIV(Aes* aes, byte* iv, word32 ivSz) +{ + int ret = 0; + + if (aes == NULL || iv == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMSET((byte*)aes->reg, 0, sizeof(aes->reg)); + XMEMCPY((byte*)aes->reg, iv, ivSz); + aes->reg[3] = 1; + } + else { + int blocks, remainder, i; + byte aesBlock[AES_BLOCK_SIZE]; + + blocks = ivSz / AES_BLOCK_SIZE; + remainder = ivSz % AES_BLOCK_SIZE; + + for (i = 0; i < blocks; i++, iv += AES_BLOCK_SIZE) + Octeon_GHASH_Update(iv); + + XMEMSET(aesBlock, 0, sizeof(aesBlock)); + for (i = 0; i < remainder; i++) + aesBlock[i] = iv[i]; + Octeon_GHASH_Update(aesBlock); + + Octeon_GHASH_Final((byte*)aes->reg, 0, ivSz); + } + + aes->y0 = aes->reg[3]; + aes->reg[3]++; + + Octeon_GHASH_Init(0xe100, aes->H); + } + + return ret; +} + + +static NOOPT int Octeon_AesGcm_SetAAD(Aes* aes, byte* aad, word32 aadSz) +{ + word64* p; + ALIGN16 byte aesBlock[AES_BLOCK_SIZE]; + int blocks, remainder, i; + + if (aes == NULL || (aadSz != 0 && aad == NULL)) + return BAD_FUNC_ARG; + + if (aadSz == 0) + return 0; + + blocks = aadSz / AES_BLOCK_SIZE; + remainder = aadSz % AES_BLOCK_SIZE; + + Octeon_GHASH_Restore(0xe100, aes->H); + + p = (word64*)aesBlock; + + for (i = 0; i < blocks; i++, aad += AES_BLOCK_SIZE) { + CVMX_LOADUNA_INT64(p[0], aad, 0); + CVMX_LOADUNA_INT64(p[1], aad, 8); + CVMX_MT_GFM_XOR0(p[0]); + CVMX_MT_GFM_XORMUL1(p[1]); + } + + XMEMSET(aesBlock, 0, sizeof(aesBlock)); + + for (i = 0; i < remainder; i++) + aesBlock[i] = aad[i]; + + CVMX_MT_GFM_XOR0(p[0]); + CVMX_MT_GFM_XORMUL1(p[1]); + + return 0; +} + + +static int Octeon_AesGcm_SetEncrypt(Aes* aes, byte* in, byte* out, word32 inSz, + int encrypt) +{ + word32 i, blocks, remainder; + ALIGN16 byte aesBlockIn[AES_BLOCK_SIZE]; + ALIGN16 byte aesBlockOut[AES_BLOCK_SIZE]; + word64* pIn; + word64* pOut; + word64* pIv; + + if (aes == NULL || in == NULL || out == NULL) + return BAD_FUNC_ARG; + + pIn = (word64*)aesBlockIn; + pOut = (word64*)aesBlockOut; + pIv = (word64*)aes->reg; + + CVMX_PREFETCH0(in); + + CVMX_MT_AES_ENC0(pIv[0]); + CVMX_MT_AES_ENC1(pIv[1]); + + blocks = inSz / AES_BLOCK_SIZE; + remainder = inSz % AES_BLOCK_SIZE; + + for (i = 0; i < blocks; + i++, in += AES_BLOCK_SIZE, out += AES_BLOCK_SIZE) { + CVMX_PREFETCH128(in); + aes->reg[3]++; + + CVMX_LOADUNA_INT64(pIn[0], in, 0); + CVMX_LOADUNA_INT64(pIn[1], in, 8); + + CVM_AES_RD_RESULT_WR_DATA(pOut[0], pOut[1], pIv[0], pIv[1]); + + if (encrypt) { + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + CVMX_MT_GFM_XOR0(pOut[0]); + CVMX_MT_GFM_XORMUL1(pOut[1]); + } + else { + CVMX_MT_GFM_XOR0(pIn[0]); + CVMX_MT_GFM_XORMUL1(pIn[1]); + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + } + + CVMX_STOREUNA_INT64(pOut[0], out, 0); + CVMX_STOREUNA_INT64(pOut[1], out, 8); + } + + if (remainder > 0) { + ALIGN16 byte aesBlockMask[AES_BLOCK_SIZE]; + word64* pMask = (word64*)aesBlockMask; + + XMEMSET(aesBlockOut, 0, sizeof(aesBlockOut)); + XMEMSET(aesBlockMask, 0, sizeof(aesBlockMask)); + for (i = 0; i < remainder; i++) { + aesBlockIn[i] = in[i]; + aesBlockMask[i] = 0xFF; + } + + if (encrypt) { + CVMX_MF_AES_RESULT(pOut[0], 0); + CVMX_MF_AES_RESULT(pOut[1], 1); + + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + + pOut[0] &= pMask[0]; + pOut[1] &= pMask[1]; + + CVMX_MT_GFM_XOR0(pOut[0]); + CVMX_MT_GFM_XORMUL1(pOut[1]); + } + else { + CVMX_MT_GFM_XOR0(pIn[0]); + CVMX_MT_GFM_XORMUL1(pIn[1]); + + CVMX_MF_AES_RESULT(pOut[0], 0); + CVMX_MF_AES_RESULT(pOut[1], 1); + + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + + pOut[0] &= pMask[0]; + pOut[1] &= pMask[1]; + } + + for (i = 0; i < remainder; i++) + out[i] = aesBlockOut[i]; + } + + return 0; +} + + +static NOOPT int Octeon_AesGcm_Finalize(Aes* aes, word32 inSz, word32 aadSz, + byte* tag) +{ + word64 bigSz; + word64* pIv; + word64* pIn; + word64* pOut; + uint32_t countSave; + ALIGN16 byte aesBlockIn[AES_BLOCK_SIZE]; + ALIGN16 byte aesBlockOut[AES_BLOCK_SIZE]; + + countSave = aes->reg[3]; + aes->reg[3] = aes->y0; + + pIv = (word64*)aes->reg; + CVMX_MT_AES_ENC0(pIv[0]); + CVMX_MT_AES_ENC1(pIv[1]); + + bigSz = (word64)aadSz * 8; + CVMX_MT_GFM_XOR0(bigSz); + bigSz = (word64)inSz * 8; + CVMX_MT_GFM_XORMUL1(bigSz); + + aes->reg[3] = countSave; + + pIn = (word64*)aesBlockIn; + CVMX_MF_AES_RESULT(pIn[0], 0); + CVMX_MF_AES_RESULT(pIn[1], 1); + + pOut = (word64*)aesBlockOut; + CVMX_MF_GFM_RESINP(pOut[0], 0); + CVMX_MF_GFM_RESINP(pOut[1], 1); + + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + + CVMX_STOREUNA_INT64(pOut[0], tag, 0); + CVMX_STOREUNA_INT64(pOut[1], tag, 8); + + return 0; +} + + +static int Octeon_AesGcm_Encrypt(Aes* aes, byte* in, byte* out, word32 inSz, + byte* iv, word32 ivSz, byte* aad, word32 aadSz, byte* tag) +{ + int ret = 0; + + if (aes == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) + ret = Octeon_AesGcm_SetKey(aes); + + if (ret == 0) + ret = Octeon_AesGcm_SetIV(aes, iv, ivSz); + + if (ret == 0) + ret = Octeon_AesGcm_SetAAD(aes, aad, aadSz); + + if (ret == 0) + ret = Octeon_AesGcm_SetEncrypt(aes, in, out, inSz, 1); + + if (ret == 0) + ret = Octeon_AesGcm_Finalize(aes, inSz, aadSz, tag); + + return ret; +} + + +static int Octeon_AesGcm_Decrypt(Aes* aes, byte* in, byte* out, word32 inSz, + byte* iv, word32 ivSz, byte* aad, word32 aadSz, byte* tag) +{ + int ret = 0; + + if (aes == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) + ret = Octeon_AesGcm_SetKey(aes); + + if (ret == 0) + ret = Octeon_AesGcm_SetIV(aes, iv, ivSz); + + if (ret == 0) + ret = Octeon_AesGcm_SetAAD(aes, aad, aadSz); + + if (ret == 0) + ret = Octeon_AesGcm_SetEncrypt(aes, in, out, inSz, 0); + + if (ret == 0) + ret = Octeon_AesGcm_Finalize(aes, inSz, aadSz, tag); + + return ret; +} + +#endif /* HAVE_AESGCM */ + +#endif /* !NO_AES */ + +#ifdef WOLF_CRYPTO_CB + +#include <wolfssl/wolfcrypt/cryptocb.h> + + +static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) +{ + int ret = NOT_COMPILED_IN; /* return this to bypass HW and use SW */ + + if (info == NULL) + return BAD_FUNC_ARG; + +#ifdef DEBUG_WOLFSSL + printf("CryptoDevCb: Algo Type %d\n", info->algo_type); +#endif + + if (info->algo_type == WC_ALGO_TYPE_CIPHER) { +#if !defined(NO_AES) || !defined(NO_DES3) + #ifdef HAVE_AESGCM + if (info->cipher.type == WC_CIPHER_AES_GCM) { + if (info->cipher.enc) { + ret = Octeon_AesGcm_Encrypt( + info->cipher.aesgcm_enc.aes, + (byte*)info->cipher.aesgcm_enc.in, + (byte*)info->cipher.aesgcm_enc.out, + info->cipher.aesgcm_enc.sz, + (byte*)info->cipher.aesgcm_enc.iv, + info->cipher.aesgcm_enc.ivSz, + (byte*)info->cipher.aesgcm_enc.authIn, + info->cipher.aesgcm_enc.authInSz, + (byte*)info->cipher.aesgcm_enc.authTag); + } + else { + ret = Octeon_AesGcm_Decrypt( + info->cipher.aesgcm_dec.aes, + (byte*)info->cipher.aesgcm_dec.in, + (byte*)info->cipher.aesgcm_dec.out, + info->cipher.aesgcm_dec.sz, + (byte*)info->cipher.aesgcm_dec.iv, + info->cipher.aesgcm_dec.ivSz, + (byte*)info->cipher.aesgcm_dec.authIn, + info->cipher.aesgcm_dec.authInSz, + (byte*)info->cipher.aesgcm_dec.authTag); + } + } + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AES_CBC + if (info->cipher.type == WC_CIPHER_AES_CBC) { + if (info->cipher.enc) { + ret = Octeon_AesCbc_Encrypt( + info->cipher.aescbc.aes, + (word64*)info->cipher.aescbc.in, + (word64*)info->cipher.aescbc.out, + info->cipher.aescbc.sz); + } + else { + ret = Octeon_AesCbc_Decrypt( + info->cipher.aescbc.aes, + (word64*)info->cipher.aescbc.in, + (word64*)info->cipher.aescbc.out, + info->cipher.aescbc.sz); + } + } + #endif /* HAVE_AES_CBC */ + #ifndef NO_DES3 + if (info->cipher.type == WC_CIPHER_DES3) { + if (info->cipher.enc) { + ret = Octeon_Des3_CbcEncrypt( + info->cipher.des3.des, + (word64*)info->cipher.des3.in, + (word64*)info->cipher.des3.out, + info->cipher.des3.sz); + } + else { + ret = Octeon_Des3_CbcDecrypt( + info->cipher.des3.des, + (word64*)info->cipher.des3.in, + (word64*)info->cipher.des3.out, + info->cipher.des3.sz); + } + } + #endif /* !NO_DES3 */ +#endif /* !NO_AES || !NO_DES3 */ + } + + (void)devIdArg; + (void)ctx; + + return ret; +} + +int wc_CryptoCb_InitOcteon(void) +{ + if (wc_CryptoCb_RegisterDevice(devId, myCryptoDevCb, NULL) < 0) { + return INVALID_DEVID; + } + + return devId; +} + +void wc_CryptoCb_CleanupOcteon(int* id) +{ + wc_CryptoCb_UnRegisterDevice(*id); + *id = INVALID_DEVID; +} + +#endif /* WOLF_CRYPTO_CB */ + +#endif /* HAVE_CAVIUM_OCTEON_SYNC */ |