aboutsummaryrefslogtreecommitdiff
path: root/client/wolfssl/wolfcrypt/user-crypto/src/rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'client/wolfssl/wolfcrypt/user-crypto/src/rsa.c')
-rw-r--r--client/wolfssl/wolfcrypt/user-crypto/src/rsa.c2790
1 files changed, 2790 insertions, 0 deletions
diff --git a/client/wolfssl/wolfcrypt/user-crypto/src/rsa.c b/client/wolfssl/wolfcrypt/user-crypto/src/rsa.c
new file mode 100644
index 0000000..a9f5afd
--- /dev/null
+++ b/client/wolfssl/wolfcrypt/user-crypto/src/rsa.c
@@ -0,0 +1,2790 @@
+/* rsa.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * 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-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H /* configure options when using autoconf */
+ #include <config.h>
+#endif
+
+#include <wolfssl/options.h>
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_RSA
+
+#define USER_CRYPTO_ERROR -101
+
+#ifdef OPENSSL_EXTRA
+ #include <wolfssl/openssl/rsa.h> /* include for openssl compatibility */
+ #include <wolfssl/openssl/bn.h>
+#endif
+#include "user_rsa.h"
+
+#ifdef DEBUG_WOLFSSL /* debug done without variadric to allow older compilers */
+ #include <stdio.h>
+ #define USER_DEBUG(x) printf x
+#else
+ #define USER_DEBUG(x)
+#endif
+
+#define ASN_INTEGER 0x02
+#define ASN_BIT_STRING 0x03
+#define ASN_TAG_NULL 0x05
+#define ASN_OBJECT_ID 0x06
+
+
+/* Make sure compiler doesn't skip -- used from wolfSSL */
+static inline void ForceZero(const void* mem, word32 len)
+{
+ volatile byte* z = (volatile byte*)mem;
+
+ while (len--) *z++ = 0;
+}
+
+enum {
+ RSA_PUBLIC_ENCRYPT = 0,
+ RSA_PUBLIC_DECRYPT = 1,
+ RSA_PRIVATE_ENCRYPT = 2,
+ RSA_PRIVATE_DECRYPT = 3,
+
+ RSA_BLOCK_TYPE_1 = 1,
+ RSA_BLOCK_TYPE_2 = 2,
+
+ RSA_MIN_SIZE = 512,
+ RSA_MAX_SIZE = 4096, /* max allowed in IPP library */
+
+ RSA_MIN_PAD_SZ = 11 /* separator + 0 + pad value + 8 pads */
+};
+
+
+int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId)
+{
+
+ USER_DEBUG(("Entering wc_InitRsaKey\n"));
+
+ if (key == NULL)
+ return USER_CRYPTO_ERROR;
+
+ /* set full struct as 0 */
+ ForceZero(key, sizeof(RsaKey));
+
+ USER_DEBUG(("\tExit wc_InitRsaKey\n"));
+
+ (void)devId;
+ (void)heap;
+ return 0;
+}
+
+int wc_InitRsaKey(RsaKey* key, void* heap)
+{
+ return wc_InitRsaKey_ex(key, heap, INVALID_DEVID);
+}
+
+
+/* three functions needed for cert and key gen */
+#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)
+/* return 1 if there is a leading bit*/
+int wc_Rsa_leading_bit(void* bn)
+{
+ int ret = 0;
+ int dataSz;
+ Ipp32u* data;
+ Ipp32u q;
+ int qSz = sizeof(Ipp32u);
+
+ if (ippsExtGet_BN(NULL, &dataSz, NULL, bn) != ippStsNoErr) {
+ USER_DEBUG(("ippsExtGet_BN Rsa leading bit error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* convert from size in binary to Ipp32u */
+ dataSz = dataSz / 32 + ((dataSz % 32)? 1 : 0);
+ data = (Ipp32u*)XMALLOC(dataSz * sizeof(Ipp32u), NULL,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (data == NULL) {
+ USER_DEBUG(("Rsa leading bit memory error\n"));
+ return 0;
+ }
+
+ /* extract value from BN */
+ if (ippsExtGet_BN(NULL, NULL, data, bn) != ippStsNoErr) {
+ USER_DEBUG(("Rsa leading bit error\n"));
+ XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return 0;
+ }
+
+ /* use method like what's used in wolfssl tfm.c */
+ q = data[dataSz - 1];
+
+ ret = 0;
+ while (qSz > 0) {
+ if (q != 0)
+ ret = (q & 0x80) != 0;
+ q >>= 8;
+ qSz--;
+ }
+
+ XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+
+ return ret;
+}
+
+
+/* get the size in bytes of BN */
+int wc_Rsa_unsigned_bin_size(void* bn)
+{
+ int ret = 0;
+ if (ippsExtGet_BN(NULL, &ret, NULL, bn) != ippStsNoErr) {
+ USER_DEBUG(("Rsa unsigned bin size error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+ return (ret / 8) + ((ret % 8)? 1: 0); /* size in bytes */
+}
+
+#ifndef MP_OKAY
+#define MP_OKAY 0
+#endif
+
+/* extract the bn value to a unsigned byte array and return MP_OKAY on success */
+int wc_Rsa_to_unsigned_bin(void* bn, byte* in, int inLen)
+{
+ if (ippsGetOctString_BN((Ipp8u*)in, inLen, bn) != ippStsNoErr) {
+ USER_DEBUG(("Rsa to unsigned bin error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+ return MP_OKAY;
+}
+#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN || OPENSSL_EXTRA */
+
+
+#ifdef OPENSSL_EXTRA /* functions needed for openssl compatibility layer */
+static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, IppsBigNumState* in)
+{
+ IppStatus ret;
+ byte* data;
+ int sz;
+
+ USER_DEBUG(("Entering SetIndividualExternal\n"));
+
+ if (bn == NULL || in == NULL) {
+ USER_DEBUG(("inputs NULL error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (*bn == NULL) {
+ *bn = wolfSSL_BN_new();
+ if (*bn == NULL) {
+ USER_DEBUG(("SetIndividualExternal alloc failed\n"));
+ return USER_CRYPTO_ERROR;
+ }
+ }
+
+ /* get size of array needed and extract oct array of data */
+ ret = ippsGetSize_BN(in, &sz);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ data = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (data == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsGetOctString_BN(data, sz, in);
+ if (ret != ippStsNoErr) {
+ XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* store the data into a wolfSSL Big Number */
+ *bn = wolfSSL_BN_bin2bn(data, sz, *bn);
+
+ XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+
+ return 0;
+}
+
+
+static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, IppsBigNumState** mpi)
+{
+ int length, ctxSz, sz;
+ IppStatus ret;
+ Ipp8u* data;
+
+ USER_DEBUG(("Entering SetIndividualInternal\n"));
+
+ if (bn == NULL || bn->internal == NULL) {
+ USER_DEBUG(("bn NULL error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ length = wolfSSL_BN_num_bytes(bn);
+
+ /* if not IPP BN then create one */
+ if (*mpi == NULL) {
+ ret = ippsBigNumGetSize(length, &ctxSz);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ *mpi = (IppsBigNumState*)XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO);
+ if (*mpi == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsBigNumInit(length, *mpi);
+ if (ret != ippStsNoErr) {
+ XFREE(*mpi, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return USER_CRYPTO_ERROR;
+ }
+
+ }
+
+ /* get the size of array needed and check IPP BigNum */
+ if (ippsGetSize_BN(*mpi, &sz) != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ if (sz < length) {
+ USER_DEBUG(("big num size is too small\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ data = (Ipp8u*)XMALLOC(length, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (data == NULL)
+ return USER_CRYPTO_ERROR;
+
+ /* extract the wolfSSL BigNum and store it into IPP BigNum */
+ if (wolfSSL_BN_bn2bin(bn, data) < 0) {
+ XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ USER_DEBUG(("error in getting bin from wolfssl bn\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsSetOctString_BN(data, length, *mpi);
+ if (ret != ippStsNoErr) {
+ XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return USER_CRYPTO_ERROR;
+ }
+
+ XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+
+ return 0;
+}
+
+
+/* WolfSSL -> OpenSSL */
+int SetRsaExternal(WOLFSSL_RSA* rsa)
+{
+ RsaKey* key;
+ USER_DEBUG(("Entering SetRsaExternal\n"));
+
+ if (rsa == NULL || rsa->internal == NULL) {
+ USER_DEBUG(("rsa key NULL error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key = (RsaKey*)rsa->internal;
+
+ if (SetIndividualExternal(&rsa->n, key->n) != 0) {
+ USER_DEBUG(("rsa n key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->e, key->e) != 0) {
+ USER_DEBUG(("rsa e key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (key->type == RSA_PRIVATE) {
+ if (SetIndividualExternal(&rsa->d, key->dipp) != 0) {
+ USER_DEBUG(("rsa d key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->p, key->pipp) != 0) {
+ USER_DEBUG(("rsa p key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->q, key->qipp) != 0) {
+ USER_DEBUG(("rsa q key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->dmp1, key->dPipp) != 0) {
+ USER_DEBUG(("rsa dP key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->dmq1, key->dQipp) != 0) {
+ USER_DEBUG(("rsa dQ key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->iqmp, key->uipp) != 0) {
+ USER_DEBUG(("rsa u key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+ }
+
+ rsa->exSet = 1;
+
+ /* SSL_SUCCESS */
+ return 1;
+}
+
+
+/* Openssl -> WolfSSL */
+int SetRsaInternal(WOLFSSL_RSA* rsa)
+{
+ int ctxSz, pSz, qSz;
+ IppStatus ret;
+ RsaKey* key;
+ USER_DEBUG(("Entering SetRsaInternal\n"));
+
+ if (rsa == NULL || rsa->internal == NULL) {
+ USER_DEBUG(("rsa key NULL error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key = (RsaKey*)rsa->internal;
+
+ if (SetIndividualInternal(rsa->n, &key->n) != 0) {
+ USER_DEBUG(("rsa n key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (SetIndividualInternal(rsa->e, &key->e) != 0) {
+ USER_DEBUG(("rsa e key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* public key */
+ key->type = RSA_PUBLIC;
+
+ if (rsa->d != NULL) {
+ if (SetIndividualInternal(rsa->d, &key->dipp) != 0) {
+ USER_DEBUG(("rsa d key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* private key */
+ key->type = RSA_PRIVATE;
+ }
+
+ if (rsa->p != NULL &&
+ SetIndividualInternal(rsa->p, &key->pipp) != 0) {
+ USER_DEBUG(("rsa p key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (rsa->q != NULL &&
+ SetIndividualInternal(rsa->q, &key->qipp) != 0) {
+ USER_DEBUG(("rsa q key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (rsa->dmp1 != NULL &&
+ SetIndividualInternal(rsa->dmp1, &key->dPipp) != 0) {
+ USER_DEBUG(("rsa dP key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (rsa->dmq1 != NULL &&
+ SetIndividualInternal(rsa->dmq1, &key->dQipp) != 0) {
+ USER_DEBUG(("rsa dQ key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (rsa->iqmp != NULL &&
+ SetIndividualInternal(rsa->iqmp, &key->uipp) != 0) {
+ USER_DEBUG(("rsa u key error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ rsa->inSet = 1;
+
+ /* get sizes of IPP BN key states created from input */
+ ret = ippsGetSize_BN(key->n, &key->nSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsGetSize_BN(key->e, &key->eSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key->sz = key->nSz; /* set modulus size */
+
+ /* convert to size in bits */
+ key->nSz = key->nSz * 8;
+ key->eSz = key->eSz * 8;
+
+ /* set up public key state */
+ ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key->pPub = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (key->pPub == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_InitPublicKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (key->pipp != NULL && key->qipp != NULL && key->dipp != NULL &&
+ key->dPipp != NULL && key->dQipp != NULL && key->uipp != NULL) {
+ /* get bn sizes needed for private key set up */
+ ret = ippsGetSize_BN(key->pipp, &pSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsGetSize_BN(key->qipp, &qSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* store sizes needed for creating tmp private keys */
+ ret = ippsGetSize_BN(key->dipp, &key->dSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* convert to size in bits */
+ key->dSz = key->dSz * 8;
+ pSz = pSz * 8;
+ qSz = qSz * 8;
+
+ /* set up private key state */
+ ret = ippsRSA_GetSizePrivateKeyType2(pSz, qSz, &ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key->prvSz = ctxSz;
+ key->pPrv = (IppsRSAPrivateKeyState*)XMALLOC(ctxSz, 0,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (key->pPrv == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsRSA_InitPrivateKeyType2(pSz, qSz, key->pPrv, ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsRSA_SetPrivateKeyType2(key->pipp, key->qipp, key->dPipp,
+ key->dQipp, key->uipp, key->pPrv);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+ }
+
+ /* SSL_SUCCESS */
+ return 1;
+}
+#endif /* OPENSSLEXTRA */
+
+
+/* Padding scheme function used in wolfSSL for signing needed for matching
+ existing API signing scheme
+ input : the msg to be signed
+ inputLen : length of input msg
+ pkcsBlock : the outputted padded msg
+ pkcsBlockLen : length of outputted padded msg buffer
+ padValue : the padded value after first 00 , is either 01 or 02
+ rng : random number generator structure
+ */
+static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
+ word32 pkcsBlockLen, byte padValue, WC_RNG* rng)
+{
+ if (inputLen == 0 || pkcsBlockLen == 0) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ pkcsBlock[0] = 0x0; /* set first byte to zero and advance */
+ pkcsBlock++; pkcsBlockLen--;
+ pkcsBlock[0] = padValue; /* insert padValue */
+
+ if (padValue == RSA_BLOCK_TYPE_1) {
+ if (pkcsBlockLen < inputLen + 2) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* pad with 0xff bytes */
+ XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
+ }
+ else {
+ /* pad with non-zero random bytes */
+ word32 padLen, i;
+ int ret;
+
+ if (pkcsBlockLen < inputLen + 1) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ padLen = pkcsBlockLen - inputLen - 1;
+ ret = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
+
+ if (ret != 0)
+ return ret;
+
+ /* remove zeros */
+ for (i = 1; i < padLen; i++)
+ if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
+ }
+
+ pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */
+ XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+
+ return 0;
+}
+
+
+/* UnPad plaintext, set start to *output, return length of plaintext,
+ * < 0 on error */
+static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
+ byte **output, byte padValue)
+{
+ word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0,
+ invalid = 0,
+ i = 1,
+ outputLen;
+
+ if (pkcsBlockLen == 0) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (pkcsBlock[0] != 0x0) /* skip past zero */
+ invalid = 1;
+ pkcsBlock++; pkcsBlockLen--;
+
+ /* Require block type padValue */
+ invalid = (pkcsBlock[0] != padValue) || invalid;
+
+ /* verify the padding until we find the separator */
+ if (padValue == RSA_BLOCK_TYPE_1) {
+ while (i<pkcsBlockLen && pkcsBlock[i++] == 0xFF) {/* Null body */}
+ }
+ else {
+ while (i<pkcsBlockLen && pkcsBlock[i++]) {/* Null body */}
+ }
+
+ if(!(i==pkcsBlockLen || pkcsBlock[i-1]==0)) {
+ USER_DEBUG(("RsaUnPad error, bad formatting\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ outputLen = pkcsBlockLen - i;
+ invalid = (outputLen > maxOutputLen) || invalid;
+
+ if (invalid) {
+ USER_DEBUG(("RsaUnPad error, bad formatting\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ *output = (byte *)(pkcsBlock + i);
+ return outputLen;
+}
+
+
+/* Set up memory and structure for a Big Number
+ * returns ippStsNoErr on success
+ */
+static IppStatus init_bn(IppsBigNumState** in, int sz)
+{
+ int ctxSz;
+ IppStatus ret;
+
+ ret = ippsBigNumGetSize(sz, &ctxSz);
+ if (ret != ippStsNoErr) {
+ return ret;
+ }
+
+ *in = (IppsBigNumState*)XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO);
+ if (*in == NULL) {
+ return ippStsNoMemErr;
+ }
+
+ ret = ippsBigNumInit(sz, *in);
+ if (ret != ippStsNoErr) {
+ XFREE(*in, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ *in = NULL;
+ return ret;
+ }
+
+ return ippStsNoErr;
+}
+
+
+/* Set up memory and structure for a Montgomery struct
+ * returns ippStsNoErr on success
+ */
+static IppStatus init_mont(IppsMontState** mont, int* ctxSz,
+ IppsBigNumState* modul)
+{
+ int mSz;
+ Ipp32u* m;
+ IppStatus ret;
+
+ ret = ippsExtGet_BN(NULL, ctxSz, NULL, modul);
+ if (ret != ippStsNoErr) {
+ return ret;
+ }
+
+ /* convert bits to Ipp32u array size and round up
+ 32 is number of bits in type */
+ mSz = (*ctxSz/32)+((*ctxSz % 32)? 1: 0);
+ m = (Ipp32u*)XMALLOC(mSz * sizeof(Ipp32u), 0, DYNAMIC_TYPE_USER_CRYPTO);
+ if (m == NULL) {
+ XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return ippStsNoMemErr;
+ }
+
+ ret = ippsExtGet_BN(NULL, NULL, m, modul);
+ if (ret != ippStsNoErr) {
+ XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return ret;
+ }
+
+ ret = ippsMontGetSize(IppsSlidingWindows, mSz, ctxSz);
+ if (ret != ippStsNoErr) {
+ XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return ret;
+ }
+
+ /* 2. Allocate working buffer using malloc */
+ *mont = (IppsMontState*)XMALLOC(*ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO);
+ if (*mont == NULL) {
+ XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return ippStsNoMemErr;
+ }
+ ret = ippsMontInit(IppsSlidingWindows, mSz, *mont);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsMontInit error of %s\n", ippGetStatusString(ret)));
+ XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(*mont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ *mont = NULL;
+ return ret;
+ }
+
+ /* 3. Call the function MontSet to set big number module */
+ ret = ippsMontSet(m, mSz, *mont);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsMontSet error of %s\n", ippGetStatusString(ret)));
+ XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(*mont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ *mont = NULL;
+ return ret;
+ }
+
+ XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+
+ return ippStsNoErr;
+}
+
+
+
+int wc_FreeRsaKey(RsaKey* key)
+{
+ if (key == NULL)
+ return 0;
+
+ USER_DEBUG(("Entering wc_FreeRsaKey\n"));
+
+ if (key->pPub != NULL) {
+ XFREE(key->pPub, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->pPub = NULL;
+ }
+
+ if (key->pPrv != NULL) {
+ /* write over sensitive information */
+ ForceZero(key->pPrv, key->prvSz);
+ XFREE(key->pPrv, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->pPrv = NULL;
+ }
+
+ if (key->n != NULL) {
+ XFREE(key->n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->n = NULL;
+ }
+
+ if (key->e != NULL) {
+ XFREE(key->e, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->e = NULL;
+ }
+
+ if (key->dipp != NULL) {
+ XFREE(key->dipp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->dipp = NULL;
+ }
+
+ if (key->pipp != NULL) {
+ XFREE(key->pipp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->pipp = NULL;
+ }
+
+ if (key->qipp != NULL) {
+ XFREE(key->qipp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->qipp = NULL;
+ }
+
+ if (key->dPipp != NULL) {
+ XFREE(key->dPipp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->dPipp = NULL;
+ }
+
+ if (key->dQipp != NULL) {
+ XFREE(key->dQipp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->dQipp = NULL;
+ }
+
+ if (key->uipp != NULL) {
+ XFREE(key->uipp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ key->uipp = NULL;
+ }
+
+ USER_DEBUG(("\tExit wc_FreeRsaKey\n"));
+ (void)key;
+
+ return 0;
+}
+
+
+/* Some parsing functions from wolfSSL code needed to match wolfSSL API used */
+static int GetLength(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
+{
+ int length = 0;
+ word32 idx = *inOutIdx;
+ byte b;
+
+ *len = 0; /* default length */
+
+ if ((idx + 1) > maxIdx) { /* for first read */
+ USER_DEBUG(("GetLength bad index on input\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ b = input[idx++];
+ if (b >= 0x80) {
+ word32 bytes = b & 0x7F;
+
+ if ((idx + bytes) > maxIdx) { /* for reading bytes */
+ USER_DEBUG(("GetLength bad long length\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ while (bytes--) {
+ b = input[idx++];
+ length = (length << 8) | b;
+ }
+ }
+ else
+ length = b;
+
+ if ((idx + length) > maxIdx) { /* for user of length */
+ USER_DEBUG(("GetLength value exceeds buffer length\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ *inOutIdx = idx;
+ if (length > 0)
+ *len = length;
+
+ return length;
+}
+
+static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len,
+ word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+ byte b;
+ int length;
+
+ if ((idx + 1) > maxIdx)
+ return USER_CRYPTO_ERROR;
+
+ b = input[idx++];
+ if (b != tag)
+ return USER_CRYPTO_ERROR;
+
+ if (GetLength(input, &idx, &length, maxIdx) < 0)
+ return USER_CRYPTO_ERROR;
+
+ *len = length;
+ *inOutIdx = idx;
+ return length;
+}
+
+static int GetASNInt(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
+{
+ int ret;
+
+ ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx);
+ if (ret < 0)
+ return ret;
+
+ if (*len > 0) {
+ /* remove leading zero, unless there is only one 0x00 byte */
+ if ((input[*inOutIdx] == 0x00) && (*len > 1)) {
+ (*inOutIdx)++;
+ (*len)--;
+
+ if (*len > 0 && (input[*inOutIdx] & 0x80) == 0)
+ return USER_CRYPTO_ERROR;
+ }
+ }
+
+ return 0;
+}
+
+static int GetInt(IppsBigNumState** mpi, const byte* input, word32* inOutIdx,
+ word32 maxIdx)
+{
+ IppStatus ret;
+ word32 idx = *inOutIdx;
+ int length;
+ int ctxSz;
+
+ if (GetASNInt(input, &idx, &length, maxIdx) < 0) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsBigNumGetSize(length, &ctxSz);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ *mpi = (IppsBigNumState*)XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO);
+ if (*mpi == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsBigNumInit(length, *mpi);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsSetOctString_BN((Ipp8u*)input + idx, length, *mpi);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ *inOutIdx = idx + length;
+ return 0;
+}
+
+
+static int GetSequence(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
+{
+ int length = -1;
+ word32 idx = *inOutIdx;
+
+ if ((idx + 1) > maxIdx)
+ return USER_CRYPTO_ERROR;
+
+ if (input[idx++] != (0x10 | 0x20) ||
+ GetLength(input, &idx, &length, maxIdx) < 0)
+ return USER_CRYPTO_ERROR;
+
+ *len = length;
+ *inOutIdx = idx;
+
+ return length;
+}
+
+
+static int GetMyVersion(const byte* input, word32* inOutIdx,
+ int* version, word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+
+ if ((idx + 3) > maxIdx)
+ return USER_CRYPTO_ERROR;
+
+ if (input[idx++] != 0x02)
+ return USER_CRYPTO_ERROR;
+
+ if (input[idx++] != 0x01)
+ return USER_CRYPTO_ERROR;
+
+ *version = input[idx++];
+ *inOutIdx = idx;
+
+ return *version;
+}
+
+
+int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
+ word32 inSz)
+{
+ int version, length;
+ int ctxSz, pSz, qSz;
+ IppStatus ret;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ USER_DEBUG(("Entering wc_RsaPrivateKeyDecode\n"));
+
+ /* read in key information */
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return USER_CRYPTO_ERROR;
+
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+ return USER_CRYPTO_ERROR;
+
+ key->type = RSA_PRIVATE;
+
+ if (GetInt(&key->n, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->e, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->dipp, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->pipp, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->qipp, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->dPipp, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->dQipp, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->uipp, input, inOutIdx, inSz) < 0 )
+ return USER_CRYPTO_ERROR;
+
+ /* get sizes of IPP BN key states created from input */
+ ret = ippsGetSize_BN(key->n, &key->nSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsGetSize_BN(key->e, &key->eSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key->sz = key->nSz; /* set modulus size */
+
+ /* convert to size in bits */
+ key->nSz = key->nSz * 8;
+ key->eSz = key->eSz * 8;
+
+ /* set up public key state */
+ ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key->pPub = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (key->pPub == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_InitPublicKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_SetPublicKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* get bn sizes needed for private key set up */
+ ret = ippsGetSize_BN(key->pipp, &pSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsGetSize_BN(key->qipp, &qSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* store sizes needed for creating tmp private keys */
+ ret = ippsGetSize_BN(key->dipp, &key->dSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* convert to size in bits */
+ key->dSz = key->dSz * 8;
+ pSz = pSz * 8;
+ qSz = qSz * 8;
+
+ /* set up private key state */
+ ret = ippsRSA_GetSizePrivateKeyType2(pSz, qSz, &ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key->prvSz = ctxSz;
+ key->pPrv = (IppsRSAPrivateKeyState*)XMALLOC(ctxSz, 0,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (key->pPrv == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsRSA_InitPrivateKeyType2(pSz, qSz, key->pPrv, ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsRSA_SetPrivateKeyType2(key->pipp, key->qipp, key->dPipp,
+ key->dQipp, key->uipp, key->pPrv);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ USER_DEBUG(("\tExit wc_RsaPrivateKeyDecode\n"));
+
+ return 0;
+}
+
+
+int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx,
+ word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz)
+{
+ IppStatus ret = 0;
+ int length;
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+ byte b;
+#endif
+
+ if (input == NULL || inOutIdx == NULL) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ USER_DEBUG(("Entering wc_RsaPublicKeyDecode_ex\n"));
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return USER_CRYPTO_ERROR;
+
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+ if ((*inOutIdx + 1) > inSz)
+ return USER_CRYPTO_ERROR;
+
+ b = input[*inOutIdx];
+ if (b != ASN_INTEGER) {
+ /* not from decoded cert, will have algo id, skip past */
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return USER_CRYPTO_ERROR;
+
+ b = input[(*inOutIdx)++];
+ if (b != ASN_OBJECT_ID)
+ return USER_CRYPTO_ERROR;
+
+ if (GetLength(input, inOutIdx, &length, inSz) < 0)
+ return USER_CRYPTO_ERROR;
+
+ *inOutIdx += length; /* skip past */
+
+ /* could have NULL tag and 0 terminator, but may not */
+ b = input[(*inOutIdx)++];
+
+ if (b == ASN_TAG_NULL) {
+ b = input[(*inOutIdx)++];
+ if (b != 0)
+ return USER_CRYPTO_ERROR;
+ }
+ else {
+ /* go back, didn't have it */
+ (*inOutIdx)--;
+ }
+
+ /* should have bit tag length and seq next */
+ b = input[(*inOutIdx)++];
+ if (b != ASN_BIT_STRING)
+ return USER_CRYPTO_ERROR;
+
+ if (GetLength(input, inOutIdx, &length, inSz) <= 0)
+ return USER_CRYPTO_ERROR;
+
+ /* could have 0 */
+ b = input[(*inOutIdx)++];
+ if (b != 0)
+ (*inOutIdx)--;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return USER_CRYPTO_ERROR;
+ }
+#endif /* OPENSSL_EXTRA || RSA_DECODE_EXTRA */
+
+ /* Get modulus */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ if (ret < 0) {
+ return USER_CRYPTO_ERROR;
+ }
+ if (nSz)
+ *nSz = length;
+ if (n)
+ *n = &input[*inOutIdx];
+ *inOutIdx += length;
+
+ /* Get exponent */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ if (ret < 0) {
+ return USER_CRYPTO_ERROR;
+ }
+ if (eSz)
+ *eSz = length;
+ if (e)
+ *e = &input[*inOutIdx];
+ *inOutIdx += length;
+
+ USER_DEBUG(("\tExit wc_RsaPublicKeyDecode_ex\n"));
+
+ return ret;
+}
+
+/* read in a public RSA key */
+int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
+ word32 inSz)
+{
+ IppStatus ret;
+ const byte *n = NULL, *e = NULL;
+ word32 nSz = 0, eSz = 0;
+
+ if (key == NULL)
+ return USER_CRYPTO_ERROR;
+
+ USER_DEBUG(("Entering wc_RsaPublicKeyDecode\n"));
+
+ ret = wc_RsaPublicKeyDecode_ex(input, inOutIdx, inSz, &n, &nSz, &e, &eSz);
+ if (ret == 0) {
+ ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key);
+ }
+
+ USER_DEBUG(("\tExit RsaPublicKeyDecode\n"));
+
+ return ret;
+}
+
+/* import RSA public key elements (n, e) into RsaKey structure (key) */
+int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e,
+ word32 eSz, RsaKey* key)
+{
+ IppStatus ret;
+ int ctxSz;
+
+ USER_DEBUG(("Entering wc_RsaPublicKeyDecodeRaw\n"));
+
+ if (n == NULL || e == NULL || key == NULL)
+ return USER_CRYPTO_ERROR;
+
+ /* set up IPP key states -- read in n */
+ ret = init_bn(&key->n, nSz);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsSetOctString_BN((Ipp8u*)n, nSz, key->n);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ /* read in e */
+ ret = init_bn(&key->e, eSz);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsSetOctString_BN((Ipp8u*)e, eSz, key->e);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ /* store size and convert to binary */
+ key->sz = nSz;
+ nSz = nSz * 8;
+ eSz = eSz * 8;
+
+ /* set up public key state */
+ ret = ippsRSA_GetSizePublicKey(nSz, eSz, &ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key->pPub = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (key->pPub == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsRSA_InitPublicKey(nSz, eSz, key->pPub, ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_InitPublicKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsRSA_SetPublicKey(key->n,key->e, key->pPub);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_SetPublicKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ key->nSz = nSz;
+ key->eSz = eSz;
+ key->type = RSA_PUBLIC;
+
+ return 0;
+}
+
+
+/* encrypt using PKCS v15 */
+int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key, WC_RNG* rng)
+{
+ IppStatus ret;
+ Ipp8u* scratchBuffer;
+ int scratchSz;
+
+ if (key == NULL || in == NULL || out == NULL)
+ return USER_CRYPTO_ERROR;
+
+ if (key->pPub == NULL || outLen < key->sz)
+ return USER_CRYPTO_ERROR;
+
+ /* set size of scratch buffer */
+ ret = ippsRSA_GetBufferSizePublicKey(&scratchSz, key->pPub);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ scratchBuffer = (Ipp8u*)XMALLOC(scratchSz*(sizeof(Ipp8u)), 0,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (scratchBuffer == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsRSAEncrypt_PKCSv15((Ipp8u*)in, inLen, NULL, (Ipp8u*)out,
+ key->pPub, scratchBuffer);
+ if (ret != ippStsNoErr) {
+ XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ USER_DEBUG(("encrypt error of %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+
+ (void)rng;
+ return key->sz;
+}
+
+
+/* decrypt using PLCS v15 */
+int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key)
+{
+ IppStatus ret;
+ Ipp8u* scratchBuffer;
+ int scratchSz;
+ int outSz;
+
+ if (in == NULL || out == NULL || key == NULL)
+ return USER_CRYPTO_ERROR;
+
+ if (key->pPrv == NULL || inLen != key->sz)
+ return USER_CRYPTO_ERROR;
+
+ outSz = outLen;
+
+ /* set size of scratch buffer */
+ ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, key->pPrv);
+ if (ret != ippStsNoErr) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ scratchBuffer = (Ipp8u*)XMALLOC(scratchSz*(sizeof(Ipp8u)), 0,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (scratchBuffer == NULL) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* perform decryption using IPP */
+ ret = ippsRSADecrypt_PKCSv15((Ipp8u*)in, (Ipp8u*)out, &outSz, key->pPrv,
+ scratchBuffer);
+ if (ret != ippStsNoErr) {
+ XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ USER_DEBUG(("decrypt error of %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+
+ return outSz;
+}
+
+
+/* out is a pointer that is set to the location in byte array "in" where input
+ data has been decrypted */
+int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
+{
+ int outSz;
+ byte* tmp;
+
+ USER_DEBUG(("Entering wc_RsaPrivateDecryptInline\n"));
+
+ /* allocate a buffer for max decrypted text */
+ tmp = (byte*)XMALLOC(key->sz, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (tmp == NULL)
+ return USER_CRYPTO_ERROR;
+
+ outSz = wc_RsaPrivateDecrypt(in, inLen, tmp, key->sz, key);
+ if (outSz >= 0) {
+ XMEMCPY(in, tmp, outSz);
+ *out = in;
+ }
+ else {
+ XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return USER_CRYPTO_ERROR;
+ }
+
+ XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ USER_DEBUG(("\tExit wc_RsaPrivateDecryptInline\n"));
+
+ return outSz;
+}
+
+
+/* Used to clean up memory when exiting, clean up memory used */
+static int FreeHelper(IppsBigNumState* pTxt, IppsBigNumState* cTxt,
+ Ipp8u* scratchBuffer, void* pPub)
+{
+ if (pTxt != NULL)
+ XFREE(pTxt, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (cTxt != NULL)
+ XFREE(cTxt, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (scratchBuffer != NULL)
+ XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (pPub != NULL)
+ XFREE(pPub, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+
+ return 0;
+}
+
+
+/* for Rsa Verify
+ in : byte array to be verified
+ inLen : length of input array
+ out : pointer to location of in byte array that has been verified
+ */
+int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
+{
+
+ int ctxSz;
+ int scratchSz;
+ Ipp8u* scratchBuffer = NULL;
+ IppStatus ret;
+ IppsRSAPrivateKeyState* pPub = NULL;
+ IppsBigNumState* pTxt = NULL;
+ IppsBigNumState* cTxt = NULL;
+
+ USER_DEBUG(("Entering wc_RsaSSL_VerifyInline\n"));
+
+ if (key == NULL || key->n == NULL || key->e == NULL) {
+ USER_DEBUG(("n or e element was null\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (in == NULL || inLen == 0 || out == NULL)
+ return USER_CRYPTO_ERROR;
+
+ /* set up a private key state using public key values */
+ ret = ippsRSA_GetSizePrivateKeyType1(key->nSz, key->eSz, &ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ pPub = (IppsRSAPrivateKeyState*)XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO);
+ if (pPub == NULL)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsRSA_InitPrivateKeyType1(key->nSz, key->eSz, pPub, ctxSz);
+ if (ret != ippStsNoErr) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsRSA_SetPrivateKeyType1(key->n, key->e, pPub);
+ if (ret != ippStsNoErr) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n",
+ ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* set size of scratch buffer */
+ ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, pPub);
+ if (ret != ippStsNoErr) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ return USER_CRYPTO_ERROR;
+ }
+
+ scratchBuffer = (Ipp8u*)XMALLOC(scratchSz*(sizeof(Ipp8u)), 0,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (scratchBuffer == NULL) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* load plain and cipher into big num states */
+ ret = init_bn(&pTxt, key->sz);
+ if (ret != ippStsNoErr) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ return USER_CRYPTO_ERROR;
+ }
+ ret = ippsSetOctString_BN((Ipp8u*)in, key->sz, pTxt);
+ if (ret != ippStsNoErr) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* set up cipher to hold signature */
+ ret = init_bn(&cTxt, key->sz);
+ if (ret != ippStsNoErr) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ return USER_CRYPTO_ERROR;
+ }
+ ret = ippsSetOctString_BN((Ipp8u*)in, key->sz, cTxt);
+ if (ret != ippStsNoErr) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* decrypt using public key information */
+ ret = ippsRSA_Decrypt(cTxt, pTxt, pPub, scratchBuffer);
+ if (ret != ippStsNoErr) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ USER_DEBUG(("decrypt error of %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* extract big num struct to octet string */
+ ret = ippsGetOctString_BN((Ipp8u*)in, key->sz, pTxt);
+ if (ret != ippStsNoErr) {
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+ USER_DEBUG(("BN get string error of %s\n", ippGetStatusString(ret)));
+ return USER_CRYPTO_ERROR;
+ }
+
+ FreeHelper(pTxt, cTxt, scratchBuffer, pPub);
+
+ /* unpad the decrypted information and return size of array */
+ return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1);
+}
+
+
+/* sets up and call VerifyInline to verify a signature */
+int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key)
+{
+ int plainLen;
+ byte* tmp;
+ byte* pad = 0;
+
+ if (out == NULL || in == NULL || key == NULL)
+ return USER_CRYPTO_ERROR;
+
+ tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_USER_CRYPTO);
+ if (tmp == NULL) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ XMEMCPY(tmp, in, inLen);
+
+ /* verify signature and test if output buffer is large enough */
+ plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key);
+ if (plainLen < 0) {
+ XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return plainLen;
+ }
+
+ if (plainLen > (int)outLen)
+ plainLen = USER_CRYPTO_ERROR;
+ else
+ XMEMCPY(out, pad, plainLen);
+
+ ForceZero(tmp, inLen);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+
+ return plainLen;
+}
+
+
+/* Check if a > b , if so c = a mod b
+ return ippStsNoErr on success */
+static IppStatus reduce(IppsBigNumState* a, IppsBigNumState* b,
+ IppsBigNumState* c)
+{
+ IppStatus ret;
+
+ if ((ret = ippsMod_BN(a, b, c)) != ippStsNoErr)
+ return ret;
+
+ return ippStsNoErr;
+}
+
+
+static IppStatus exptmod(IppsBigNumState* a, IppsBigNumState* b,
+ IppsMontState* mont, IppsBigNumState* out, IppsBigNumState* one)
+{
+ IppStatus ret;
+
+ ret = ippsMontForm(a, mont, a);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsMontForm error of %s\n", ippGetStatusString(ret)));
+ return ret;
+ }
+
+ /* a = a^b mod mont */
+ ret = ippsMontExp(a, b, mont, out);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsMontExp error of %s\n", ippGetStatusString(ret)));
+ return ret;
+ }
+
+ /* convert back from montgomery */
+ ret = ippsMontMul(out, one, mont, out);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsMontMul error of %s\n", ippGetStatusString(ret)));
+ return ret;
+ }
+
+ return ippStsNoErr;
+}
+
+
+static void Free_BN(IppsBigNumState* bn)
+{
+ int sz, ctxSz;
+ IppStatus ret;
+
+ if (bn != NULL) {
+ ret = ippStsNoErr;
+ ret |= ippsGetSize_BN(bn, &sz);
+ ret |= ippsBigNumGetSize(sz, &ctxSz);
+ if (ret == ippStsNoErr) {
+ ForceZero(bn, ctxSz);
+ }
+ else {
+ USER_DEBUG(("Issue with clearing a struct in RsaSSL_Sign free\n"));
+ }
+ XFREE(bn, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ }
+}
+
+
+/* free up memory used during CRT sign operation */
+static void FreeSignHelper(IppsBigNumState* one, IppsBigNumState* tmp,
+ IppsBigNumState* tmpP, IppsBigNumState* tmpQ, IppsBigNumState* tmpa,
+ IppsBigNumState* tmpb)
+{
+ Free_BN(one);
+ Free_BN(tmp);
+ Free_BN(tmpP);
+ Free_BN(tmpQ);
+ Free_BN(tmpa);
+ Free_BN(tmpb);
+}
+
+
+/* for Rsa Sign */
+int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key, WC_RNG* rng)
+{
+ int sz, pSz, qSz;
+ IppStatus ret;
+ word32 outSz = outLen;
+
+ IppsMontState* pMont = NULL;
+ IppsMontState* qMont = NULL;
+
+ IppsBigNumState* one = NULL;
+ IppsBigNumState* tmp = NULL;
+ IppsBigNumState* tmpP = NULL;
+ IppsBigNumState* tmpQ = NULL;
+ IppsBigNumState* tmpa = NULL;
+ IppsBigNumState* tmpb = NULL;
+
+ IppsBigNumSGN sa, sb;
+
+ Ipp8u o[1];
+ o[0] = 1;
+
+ USER_DEBUG(("Entering wc_RsaSSL_Sign\n"));
+
+ if (in == NULL || out == NULL || key == NULL || rng == NULL) {
+ USER_DEBUG(("Bad argument to wc_RsaSSL_Sign\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ sz = key->sz;
+
+
+ /* sanity check on key being used */
+ if (key->pipp == NULL || key->qipp == NULL || key->uipp == NULL ||
+ key->dPipp == NULL || key->dQipp == NULL) {
+ USER_DEBUG(("Bad key argument to wc_RsaSSL_Sign\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (sz > (int)outLen) {
+ USER_DEBUG(("Bad argument outLen to wc_RsaSSL_Sign\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (sz < RSA_MIN_PAD_SZ) {
+ USER_DEBUG(("Key size is too small\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) {
+ USER_DEBUG(("Bad argument inLen to wc_RsaSSL_Sign\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* Set up needed pkcs v15 padding */
+ if (wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng) != 0) {
+ USER_DEBUG(("RSA Padding error\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* tmp = input to sign */
+ ret = init_bn(&tmp, sz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret)));
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+ ret = ippsSetOctString_BN(out, sz, tmp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsSetOctString_BN error of %s\n",
+ ippGetStatusString(ret)));
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* tmpP = tmp mod p */
+ ret = init_bn(&tmpP, sz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret)));
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* tmpQ = tmp mod q */
+ ret = init_bn(&tmpQ, sz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret)));
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* tmpa */
+ ret = init_bn(&tmpa, sz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret)));
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* tmpb */
+ ret = init_bn(&tmpb, sz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret)));
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* one : used for conversion from Montgomery to classical */
+ ret = init_bn(&one, sz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret)));
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+ ret = ippsSetOctString_BN(o, 1, one);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsSetOctString_BN error of %s\n",
+ ippGetStatusString(ret)));
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /**
+ Set up Montgomery state
+ */
+ ret = init_mont(&pMont, &pSz, key->pipp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("init_mont error of %s\n", ippGetStatusString(ret)));
+ if (pMont != NULL) {
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ }
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = init_mont(&qMont, &qSz, key->qipp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("init_mont error of %s\n", ippGetStatusString(ret)));
+ if (qMont != NULL) {
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ }
+ ForceZero(pMont, pSz);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /**
+ Check and reduce input
+ This is needed for calls to MontExp since required value of a < modulus
+ */
+ ret = reduce(tmp, key->pipp, tmpP);
+ if (ret != ippStsNoErr)
+ {
+ USER_DEBUG(("reduce error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = reduce(tmp, key->qipp, tmpQ);
+ if (ret != ippStsNoErr)
+ {
+ USER_DEBUG(("reduce error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* tmpa = (tmp mod p)^dP mod p */
+ ret = exptmod(tmpP, key->dPipp, pMont, tmpa, one);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("exptmod error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* tmpb = (tmp mod q)^dQ mod q */
+ ret = exptmod(tmpQ, key->dQipp, qMont, tmpb, one);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("exptmod error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* tmp = (tmpa - tmpb) * qInv (mod p) */
+ ret = ippsSub_BN(tmpa, tmpb, tmp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsSub_BN error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ ret = ippsMul_BN(tmp, key->uipp, tmp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsMul_BN error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* mod performed the same was as wolfSSL fp_mod -- tmpa is just scratch */
+ ret = ippsDiv_BN(tmp, key->pipp, tmpa, tmp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsDiv_BN error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* Check sign of values and perform conditional add */
+ ret = ippsExtGet_BN(&sa, NULL, NULL, tmp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsExtGet_BN error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+ ret = ippsExtGet_BN(&sb, NULL, NULL, key->pipp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsExtGet_BN error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+ if (sa != sb) {
+ ret = ippsAdd_BN(tmp, key->pipp, tmp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsAdd_BN error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+ }
+
+ /* tmp = tmpb + q * tmp */
+ ret = ippsMul_BN(tmp, key->qipp, tmp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsSub_BN error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+
+ ret = ippsAdd_BN(tmp, tmpb, tmp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsSub_BN error of %s\n", ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* Extract the output */
+ ret = ippsGetOctString_BN(out, sz, tmp);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetOctString_BN error of %s\n",
+ ippGetStatusString(ret)));
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+ return USER_CRYPTO_ERROR;
+ }
+
+ outSz = sz;
+
+ /* clear memory and free */
+ ForceZero(pMont, pSz);
+ ForceZero(qMont, qSz);
+ XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb);
+
+ return outSz;
+}
+
+
+int wc_RsaEncryptSize(RsaKey* key)
+{
+ if (key == NULL)
+ return 0;
+
+ return key->sz;
+}
+
+
+/* flatten RsaKey structure into individual elements (e, n) */
+int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n,
+ word32* nSz)
+{
+ int sz, bytSz;
+ IppStatus ret;
+
+ USER_DEBUG(("Entering wc_RsaFlattenPublicKey\n"));
+
+ if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL)
+ return USER_CRYPTO_ERROR;
+
+ bytSz = sizeof(byte) * 8;
+ ret = ippsExtGet_BN(NULL, &sz, NULL, key->e);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ /* sz is in bits change to bytes */
+ sz = (sz / bytSz) + ((sz % bytSz)? 1 : 0);
+
+ if (*eSz < (word32)sz)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsGetOctString_BN(e, sz, key->e);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ *eSz = (word32)sz;
+
+ /* flatten n */
+ ret = ippsExtGet_BN(NULL, &sz, NULL, key->n);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ /* sz is in bits change to bytes */
+ sz = (sz / bytSz) + ((sz % bytSz)? 1: 0);
+
+ if (*nSz < (word32)sz)
+ return USER_CRYPTO_ERROR;
+
+ ret = ippsGetOctString_BN(n, sz, key->n);
+ if (ret != ippStsNoErr)
+ return USER_CRYPTO_ERROR;
+
+ *nSz = (word32)sz;
+
+ return 0;
+}
+
+
+IppStatus wolfSSL_rng(Ipp32u* pData, int nBits, void* pEbsParams);
+IppStatus wolfSSL_rng(Ipp32u* pData, int nBits, void* pEbsParams)
+{
+ int nBytes;
+
+ if (pData == NULL) {
+ USER_DEBUG(("error with wolfSSL_rng argument\n"));
+ return ippStsErr;
+ }
+
+ nBytes = (nBits/8) + ((nBits % 8)? 1: 0);
+ if (wc_RNG_GenerateBlock((WC_RNG*)pEbsParams, (byte*)pData, nBytes) != 0) {
+ USER_DEBUG(("error in generating random wolfSSL block\n"));
+ return ippStsErr;
+ }
+
+ return ippStsNoErr;
+}
+
+
+#ifdef WOLFSSL_KEY_GEN
+/* Make an RSA key for size bits, with e specified, 65537 is a good e */
+int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng)
+{
+ IppStatus ret;
+ int scratchSz;
+ int i; /* for trys on calling make key */
+ int ctxSz;
+
+ IppsBigNumState* pSrcPublicExp = NULL;
+ Ipp8u* scratchBuffer = NULL;
+ Ipp8u eAry[8];
+ int trys = 8; /* Miller-Rabin test parameter */
+ IppsPrimeState* pPrime = NULL;
+
+ int qBitSz; /* size of q factor */
+ int bytSz; /* size of key in bytes */
+ int leng;
+
+ USER_DEBUG(("Entering wc_MakeRsaKey\n"));
+
+ /* get byte size and individual private key size -- round up */
+ qBitSz = (size / 2) + ((size % 2)? 1: 0);
+ bytSz = (size / 8) + ((size % 8)? 1: 0);
+
+ if (key == NULL || rng == NULL) {
+ USER_DEBUG(("Error, NULL argument passed in\n"));
+ return USER_CRYPTO_ERROR;
+ }
+
+ if (e < 3 || (e&1) == 0)
+ return USER_CRYPTO_ERROR;
+
+ if (size > RSA_MAX_SIZE || size < RSA_MIN_SIZE)
+ return USER_CRYPTO_ERROR;
+
+ key->type = RSA_PRIVATE;
+ key->sz = bytSz;
+
+ /* initialize prime number */
+ ret = ippsPrimeGetSize(size, &ctxSz); /* size in bits */
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsPrimeGetSize error of %s\n", ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ pPrime = (IppsPrimeState*)XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (pPrime == NULL) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ ret = ippsPrimeInit(size, pPrime);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsPrimeInit error of %s\n", ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* define RSA privete key type 2 */
+ /* length in bits of p and q factors */
+ ret = ippsRSA_GetSizePrivateKeyType2(qBitSz, qBitSz, &ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetSizePrivateKeyType2 error of %s\n",
+ ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ key->prvSz = ctxSz; /* used when freeing private key */
+ key->pPrv = (IppsRSAPrivateKeyState*)XMALLOC(ctxSz, NULL,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (key->pPrv == NULL) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* length in bits of p and q factors */
+ ret = ippsRSA_InitPrivateKeyType2(qBitSz, qBitSz, key->pPrv, ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_InitPrivateKeyType2 error of %s\n",
+ ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* allocate scratch buffer */
+ ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, key->pPrv);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetBufferSizePrivateKey error of %s\n",
+ ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ scratchBuffer = (Ipp8u*)XMALLOC(scratchSz, 0, DYNAMIC_TYPE_USER_CRYPTO);
+ if (scratchBuffer == NULL) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* set up initial value of pScrPublicExp */
+ leng = (int)sizeof(long); /* # of Ipp32u in long */
+
+ /* place the value of e into the array eAry then load into BN */
+ for (i = 0; i < leng; i++) {
+ eAry[i] = (e >> (8 * (leng - 1 - i))) & 0XFF;
+ }
+ ret = init_bn(&pSrcPublicExp, leng);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ ret = ippsSetOctString_BN(eAry, leng, pSrcPublicExp);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* initializing key->n */
+ ret = init_bn(&key->n, bytSz);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* initializing public exponent key->e */
+ ret = init_bn(&key->e, leng);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* private exponent key->dipp */
+ ret = init_bn(&key->dipp, bytSz);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* call IPP to generate keys, if inseficent entropy error call again */
+ ret = ippStsInsufficientEntropy;
+ while (ret == ippStsInsufficientEntropy) {
+ ret = ippsRSA_GenerateKeys(pSrcPublicExp, key->n, key->e,
+ key->dipp, key->pPrv, scratchBuffer, trys, pPrime,
+ wolfSSL_rng, rng);
+ if (ret == ippStsNoErr) {
+ break;
+ }
+
+ /* catch all errors other than entropy error */
+ if (ret != ippStsInsufficientEntropy) {
+ USER_DEBUG(("ippsRSA_GeneratKeys error of %s\n",
+ ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+ }
+
+ /* get bn sizes needed for private key set up */
+ ret = ippsExtGet_BN(NULL, &key->eSz, NULL, key->e);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ ret = ippsExtGet_BN(NULL, &key->nSz, NULL, key->n);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* set up public key state */
+ ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetSizePublicKey error %s nSz = %d eSz = %d\n",
+ ippGetStatusString(ret), key->nSz, key->eSz));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ key->pPub = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (key->pPub == NULL) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_InitPublicKey error %s\n",
+ ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_SetPublicKey error %s\n",
+ ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* get private key information for key struct */
+ leng = size/16; /* size of q, p, u, dP, dQ */
+ ret = init_bn(&key->pipp, leng);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* set up q BN for key */
+ ret = init_bn(&key->qipp, leng);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* set up dP BN for key */
+ ret = init_bn(&key->dPipp, leng);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* set up dQ BN for key */
+ ret = init_bn(&key->dQipp, leng);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* set up u BN for key */
+ ret = init_bn(&key->uipp, leng);
+ if (ret != ippStsNoErr) {
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+
+ /* get values from created key */
+ ret = ippsRSA_GetPrivateKeyType2(key->pipp, key->qipp, key->dPipp,
+ key->dQipp, key->uipp, key->pPrv);
+ if (ret != ippStsNoErr) {
+ USER_DEBUG(("ippsRSA_GetPrivateKeyType2 error %s\n",
+ ippGetStatusString(ret)));
+ ret = USER_CRYPTO_ERROR;
+ goto makeKeyEnd;
+ }
+ ret = 0; /* success case */
+
+makeKeyEnd:
+ /* clean up memory used */
+ XFREE(pSrcPublicExp, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(pPrime, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+
+ if (ret != 0) { /* with fail case free RSA components created */
+ wc_FreeRsaKey(key);
+ }
+
+ return ret;
+}
+
+#endif
+
+#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)
+
+/********** duplicate code needed -- future refactor */
+#define MAX_VERSION_SZ 5
+#define MAX_SEQ_SZ 5
+#define ASN_CONTEXT_SPECIFIC 0x80
+#define ASN_CONSTRUCTED 0x20
+#define ASN_LONG_LENGTH 0x80
+#define ASN_SEQUENCE 0x10
+#define RSA_INTS 8
+#define FALSE 0
+#define TRUE 1
+
+#define MAX_LENGTH_SZ 4
+#define RSAk 645
+#define keyType 2
+#define MAX_RSA_INT_SZ 517
+#define MAX_RSA_E_SZ 16
+#define MAX_ALGO_SZ 20
+
+static word32 BytePrecision(word32 value)
+{
+ word32 i;
+ for (i = sizeof(value); i; --i)
+ if (value >> ((i - 1) * WOLFSSL_BIT_SIZE))
+ break;
+
+ return i;
+}
+
+
+static int SetMyVersion(word32 version, byte* output, int header)
+{
+ int i = 0;
+
+ if (output == NULL)
+ return USER_CRYPTO_ERROR;
+
+ if (header) {
+ output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED;
+ output[i++] = ASN_BIT_STRING;
+ }
+ output[i++] = ASN_INTEGER;
+ output[i++] = 0x01;
+ output[i++] = (byte)version;
+
+ return i;
+}
+
+
+static word32 SetLength(word32 length, byte* output)
+{
+ word32 i = 0, j;
+
+ if (length < 0x80)
+ output[i++] = (byte)length;
+ else {
+ output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
+
+ for (j = BytePrecision(length); j; --j) {
+ output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE));
+ i++;
+ }
+ }
+
+ return i;
+}
+
+
+static word32 SetSequence(word32 len, byte* output)
+{
+ output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
+ return SetLength(len, output + 1) + 1;
+}
+
+
+static word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
+{
+ /* adding TAG_NULL and 0 to end */
+
+ /* RSA keyType */
+ #ifndef NO_RSA
+ static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00};
+ #endif /* NO_RSA */
+
+ int algoSz = 0;
+ int tagSz = 2; /* tag null and terminator */
+ word32 idSz, seqSz;
+ const byte* algoName = 0;
+ byte ID_Length[MAX_LENGTH_SZ];
+ byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */
+
+ if (type == keyType) { /* keyType */
+ switch (algoOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ algoSz = sizeof(RSA_AlgoID);
+ algoName = RSA_AlgoID;
+ break;
+ #endif /* NO_RSA */
+ default:
+ /* unknown key algo */
+ return 0;
+ }
+ }
+ else {
+ /* unknown algo type */
+ return 0;
+ }
+
+ idSz = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */
+ seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray);
+ /* +1 for object id, curveID of curveSz follows for ecc */
+ seqArray[seqSz++] = ASN_OBJECT_ID;
+
+ XMEMCPY(output, seqArray, seqSz);
+ XMEMCPY(output + seqSz, ID_Length, idSz);
+ XMEMCPY(output + seqSz + idSz, algoName, algoSz);
+
+ return seqSz + idSz + algoSz;
+
+}
+
+
+/* Write a public RSA key to output */
+static int SetRsaPublicKey(byte* output, RsaKey* key,
+ int outLen, int with_header)
+{
+#ifdef WOLFSSL_SMALL_STACK
+ byte* n = NULL;
+ byte* e = NULL;
+#else
+ byte n[MAX_RSA_INT_SZ];
+ byte e[MAX_RSA_E_SZ];
+#endif
+ byte seq[MAX_SEQ_SZ];
+ byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */
+ int nSz;
+ int eSz;
+ int seqSz;
+ int lenSz;
+ int idx;
+ int rawLen;
+ int leadingBit;
+ int err;
+
+ if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ)
+ return USER_CRYPTO_ERROR;
+
+ /* n */
+#ifdef WOLFSSL_SMALL_STACK
+ n = (byte*)XMALLOC(MAX_RSA_INT_SZ, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (n == NULL)
+ return USER_CRYPTO_ERROR;
+#endif
+
+ leadingBit = wc_Rsa_leading_bit(key->n);
+ rawLen = wc_Rsa_unsigned_bin_size(key->n);
+ if ((int)rawLen < 0) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ rawLen = rawLen + leadingBit;
+ n[0] = ASN_INTEGER;
+ nSz = SetLength(rawLen, n + 1) + 1; /* int tag */
+
+ if ( (nSz + rawLen) < MAX_RSA_INT_SZ) {
+ if (leadingBit)
+ n[nSz] = 0;
+ err = ippsGetOctString_BN((Ipp8u*)n + nSz, rawLen - leadingBit, key->n);
+ if (err == ippStsNoErr)
+ nSz += rawLen;
+ else {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+#endif
+ return USER_CRYPTO_ERROR;
+ }
+ }
+ else {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+#endif
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* e */
+#ifdef WOLFSSL_SMALL_STACK
+ e = (byte*)XMALLOC(MAX_RSA_E_SZ, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (e == NULL) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+#endif
+ return USER_CRYPTO_ERROR;
+ }
+#endif
+
+ leadingBit = wc_Rsa_leading_bit(key->e);
+ rawLen = wc_Rsa_unsigned_bin_size(key->e);
+ if ((int)rawLen < 0) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ rawLen = rawLen + leadingBit;
+ e[0] = ASN_INTEGER;
+ eSz = SetLength(rawLen, e + 1) + 1; /* int tag */
+
+ if ( (eSz + rawLen) < MAX_RSA_E_SZ) {
+ if (leadingBit)
+ e[eSz] = 0;
+ err = ippsGetOctString_BN((Ipp8u*)e + eSz, rawLen - leadingBit, key->e);
+ if (err == ippStsNoErr)
+ eSz += rawLen;
+ else {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+#endif
+ return USER_CRYPTO_ERROR;
+ }
+ }
+ else {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+#endif
+ return USER_CRYPTO_ERROR;
+ }
+
+ seqSz = SetSequence(nSz + eSz, seq);
+
+ /* check output size */
+ if ( (seqSz + nSz + eSz) > outLen) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+#endif
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* headers */
+ if (with_header) {
+ int algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+ byte* algo;
+
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ if (algo == NULL) {
+ XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ return USER_CRYPTO_ERROR;
+ }
+#else
+ byte algo[MAX_ALGO_SZ];
+#endif
+ algoSz = SetAlgoID(RSAk, algo, keyType, 0);
+ lenSz = SetLength(seqSz + nSz + eSz + 1, len);
+ len[lenSz++] = 0; /* trailing 0 */
+
+ /* write, 1 is for ASN_BIT_STRING */
+ idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output);
+
+ /* check output size */
+ if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(algo, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ #endif
+
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* bit string */
+ output[idx++] = ASN_BIT_STRING;
+ /* length */
+ XMEMCPY(output + idx, len, lenSz);
+ idx += lenSz;
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(algo, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+#endif
+ }
+ else
+ idx = 0;
+
+ /* seq */
+ XMEMCPY(output + idx, seq, seqSz);
+ idx += seqSz;
+ /* n */
+ XMEMCPY(output + idx, n, nSz);
+ idx += nSz;
+ /* e */
+ XMEMCPY(output + idx, e, eSz);
+ idx += eSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+ XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO);
+#endif
+
+ return idx;
+}
+
+
+static IppsBigNumState* GetRsaInt(RsaKey* key, int idx)
+{
+ if (idx == 0)
+ return key->n;
+ if (idx == 1)
+ return key->e;
+ if (idx == 2)
+ return key->dipp;
+ if (idx == 3)
+ return key->pipp;
+ if (idx == 4)
+ return key->qipp;
+ if (idx == 5)
+ return key->dPipp;
+ if (idx == 6)
+ return key->dQipp;
+ if (idx == 7)
+ return key->uipp;
+
+ return NULL;
+}
+
+
+/* Release Tmp RSA resources */
+static WC_INLINE void FreeTmpRsas(byte** tmps, void* heap)
+{
+ int i;
+
+ (void)heap;
+
+ for (i = 0; i < RSA_INTS; i++)
+ XFREE(tmps[i], heap, DYNAMIC_TYPE_USER_CRYPTO);
+}
+
+
+/* Convert RsaKey key to DER format, write to output (inLen), return bytes
+ written */
+int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
+{
+ word32 seqSz, verSz, rawLen, intTotalLen = 0;
+ word32 sizes[RSA_INTS];
+ int i, j, outLen, ret = 0, lbit;
+
+ byte seq[MAX_SEQ_SZ];
+ byte ver[MAX_VERSION_SZ];
+ byte* tmps[RSA_INTS];
+
+ USER_DEBUG(("Entering RsaKeyToDer\n"));
+
+ if (!key)
+ return USER_CRYPTO_ERROR;
+
+ if (key->type != RSA_PRIVATE)
+ return USER_CRYPTO_ERROR;
+
+ for (i = 0; i < RSA_INTS; i++)
+ tmps[i] = NULL;
+
+ /* write all big ints from key to DER tmps */
+ for (i = 0; i < RSA_INTS; i++) {
+ Ipp32u isZero;
+ IppsBigNumState* keyInt = GetRsaInt(key, i);
+
+ ippsCmpZero_BN(keyInt, &isZero); /* makes isZero 0 if true */
+ rawLen = wc_Rsa_unsigned_bin_size(keyInt);
+ if ((int)rawLen < 0) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* leading zero */
+ if (!isZero || wc_Rsa_leading_bit(keyInt))
+ lbit = 1;
+ else
+ lbit = 0;
+
+ rawLen += lbit;
+
+ tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
+ DYNAMIC_TYPE_USER_CRYPTO);
+ if (tmps[i] == NULL) {
+ ret = USER_CRYPTO_ERROR;
+ break;
+ }
+
+ tmps[i][0] = ASN_INTEGER;
+ sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */
+
+ if (sizes[i] <= MAX_SEQ_SZ) {
+ int err;
+
+ /* leading zero */
+ if (lbit)
+ tmps[i][sizes[i]-1] = 0x00;
+
+ /* extract data*/
+ err = ippsGetOctString_BN((Ipp8u*)(tmps[i] + sizes[i]),
+ rawLen - lbit, keyInt);
+ if (err == ippStsOk) {
+ sizes[i] += (rawLen-lbit); /* lbit included in rawLen */
+ intTotalLen += sizes[i];
+ ret = 0;
+ }
+ else {
+ ret = USER_CRYPTO_ERROR;
+ USER_DEBUG(("ippsGetOctString_BN error %s\n",
+ ippGetStatusString(err)));
+ break;
+ }
+ }
+ else {
+ ret = USER_CRYPTO_ERROR;
+ break;
+ }
+ }
+
+ if (ret != 0) {
+ FreeTmpRsas(tmps, key->heap);
+ return ret;
+ }
+
+ /* make headers */
+ verSz = SetMyVersion(0, ver, FALSE);
+ seqSz = SetSequence(verSz + intTotalLen, seq);
+
+ outLen = seqSz + verSz + intTotalLen;
+ if (output) {
+ if (outLen > (int)inLen) {
+ return USER_CRYPTO_ERROR;
+ }
+
+ /* write to output */
+ XMEMCPY(output, seq, seqSz);
+ j = seqSz;
+ XMEMCPY(output + j, ver, verSz);
+ j += verSz;
+
+ for (i = 0; i < RSA_INTS; i++) {
+ XMEMCPY(output + j, tmps[i], sizes[i]);
+ j += sizes[i];
+ }
+ }
+ FreeTmpRsas(tmps, key->heap);
+
+ return outLen;
+}
+
+
+/* Convert Rsa Public key to DER format, write to output (inLen), return bytes
+ written
+*/
+int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen)
+{
+ return SetRsaPublicKey(output, key, inLen, 1);
+}
+
+
+#endif /* WOLFSSL_KEY_GEN || OPENSSL_EXTRA */
+
+#ifdef WC_RSA_BLINDING
+
+int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng)
+{
+ if (key == NULL)
+ return USER_CRYPTO_ERROR;
+
+ (void)rng;
+
+ return 0;
+}
+
+#endif /* WC_RSA_BLINDING */
+
+#endif /* NO_RSA */
+