aboutsummaryrefslogtreecommitdiff
path: root/client/wolfssl/wolfcrypt/src/port/cavium
diff options
context:
space:
mode:
authorauth12 <[email protected]>2020-07-19 11:57:04 -0700
committerGitHub <[email protected]>2020-07-19 11:57:04 -0700
commit1bae439a35a3aadca6772716aaeea8c8a0991114 (patch)
treef8eab7a7bae237ad697feecfae26b17bab91b16e /client/wolfssl/wolfcrypt/src/port/cavium
parentMore placeholders and general plan. (diff)
parentMerge branch 'master' into windows (diff)
downloadloader-1bae439a35a3aadca6772716aaeea8c8a0991114.tar.xz
loader-1bae439a35a3aadca6772716aaeea8c8a0991114.zip
Merge pull request #1 from auth12/windows
Windows
Diffstat (limited to 'client/wolfssl/wolfcrypt/src/port/cavium')
-rw-r--r--client/wolfssl/wolfcrypt/src/port/cavium/README.md3
-rw-r--r--client/wolfssl/wolfcrypt/src/port/cavium/README_Octeon.md3
-rw-r--r--client/wolfssl/wolfcrypt/src/port/cavium/cavium_nitrox.c0
-rw-r--r--client/wolfssl/wolfcrypt/src/port/cavium/cavium_octeon_sync.c879
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 */