From 01703281cccc48e13033353dc7585123f810014e Mon Sep 17 00:00:00 2001 From: Todd Ouska Date: Thu, 31 Jan 2013 15:55:29 -0800 Subject: [PATCH] add cavium RSA to ctaocrypt --- ctaocrypt/benchmark/benchmark.c | 7 + ctaocrypt/src/asn.c | 67 +++++++++ ctaocrypt/src/rsa.c | 247 +++++++++++++++++++++++++++++++- ctaocrypt/test/test.c | 8 +- cyassl/ctaocrypt/rsa.h | 19 +++ cyassl/ctaocrypt/types.h | 3 +- 6 files changed, 347 insertions(+), 4 deletions(-) diff --git a/ctaocrypt/benchmark/benchmark.c b/ctaocrypt/benchmark/benchmark.c index 06decc84d..268815896 100644 --- a/ctaocrypt/benchmark/benchmark.c +++ b/ctaocrypt/benchmark/benchmark.c @@ -650,6 +650,10 @@ void bench_rsa(void) bytes = fread(tmp, 1, sizeof(tmp), file); #endif /* USE_CERT_BUFFERS */ +#ifdef HAVE_CAVIUM + if (RsaInitCavium(&rsaKey, CAVIUM_DEV_ID) != 0) + printf("RSA init cavium failed\n"); +#endif InitRng(&rng); InitRsaKey(&rsaKey, 0); bytes = RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes); @@ -684,6 +688,9 @@ void bench_rsa(void) fclose(file); #endif FreeRsaKey(&rsaKey); +#ifdef HAVE_CAVIUM + RsaFreeCavium(&rsaKey); +#endif } #endif diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index 96cba9cd4..931c22dd3 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -531,11 +531,78 @@ static int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, #ifndef NO_RSA + +#ifdef HAVE_CAVIUM + +static int GetCaviumInt(byte** buff, word16* buffSz, const byte* input, + word32* inOutIdx, word32 maxIdx, void* heap) +{ + word32 i = *inOutIdx; + byte b = input[i++]; + int length; + + if (b != ASN_INTEGER) + return ASN_PARSE_E; + + if (GetLength(input, &i, &length, maxIdx) < 0) + return ASN_PARSE_E; + + if ( (b = input[i++]) == 0x00) + length--; + else + i--; + + *buffSz = (word16)length; + *buff = XMALLOC(*buffSz, heap, DYNAMIC_TYPE_CAVIUM_RSA); + if (*buff == NULL) + return MEMORY_E; + + XMEMCPY(*buff, input + i, *buffSz); + + *inOutIdx = i + length; + return 0; +} + +static int CaviumRsaPrivateKeyDecode(const byte* input, word32* inOutIdx, + RsaKey* key, word32 inSz) +{ + int version, length; + void* h = key->heap; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, inOutIdx, &version) < 0) + return ASN_PARSE_E; + + key->type = RSA_PRIVATE; + + if (GetCaviumInt(&key->c_n, &key->c_nSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_e, &key->c_eSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_d, &key->c_dSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_p, &key->c_pSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_q, &key->c_qSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_dP, &key->c_dP_Sz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_dQ, &key->c_dQ_Sz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_u, &key->c_uSz, input, inOutIdx, inSz, h) < 0 ) + return ASN_RSA_KEY_E; + + return 0; +} + + +#endif /* HAVE_CAVIUM */ + int RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { int version, length; +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) + return CaviumRsaPrivateKeyDecode(input, inOutIdx, key, inSz); +#endif + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; diff --git a/ctaocrypt/src/rsa.c b/ctaocrypt/src/rsa.c index 06ad74351..bcbf0b80b 100644 --- a/ctaocrypt/src/rsa.c +++ b/ctaocrypt/src/rsa.c @@ -39,6 +39,18 @@ #endif #endif +#ifdef HAVE_CAVIUM + static void InitCaviumRsaKey(RsaKey* key, void* heap); + static void FreeCaviumRsaKey(RsaKey* key); + static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); + static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); + static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); + static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); +#endif enum { RSA_PUBLIC_ENCRYPT = 0, @@ -58,6 +70,11 @@ enum { void InitRsaKey(RsaKey* key, void* heap) { +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) + return InitCaviumRsaKey(key, heap); +#endif + key->type = -1; /* haven't decided yet */ key->heap = heap; @@ -75,6 +92,12 @@ void InitRsaKey(RsaKey* key, void* heap) void FreeRsaKey(RsaKey* key) { (void)key; + +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) + return FreeCaviumRsaKey(key); +#endif + /* TomsFastMath doesn't use memory allocation */ #ifndef USE_FAST_MATH if (key->type == RSA_PRIVATE) { @@ -249,8 +272,14 @@ done: int RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, RNG* rng) { - int sz = mp_unsigned_bin_size(&key->n), ret; + int sz, ret; +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) + return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key); +#endif + + sz = mp_unsigned_bin_size(&key->n); if (sz > (int)outLen) return RSA_BUFFER_E; @@ -270,6 +299,15 @@ int RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) { int plainLen, ret; +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) { + ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key); + if (ret > 0) + *out = in; + return ret; + } +#endif + if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key)) < 0) { return ret; @@ -288,6 +326,11 @@ int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, byte* tmp; byte* pad = 0; +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) + return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); +#endif + tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); if (tmp == NULL) { return MEMORY_E; @@ -316,6 +359,15 @@ int RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) { int plainLen, ret; +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) { + ret = CaviumRsaSSL_Verify(in, inLen, in, inLen, key); + if (ret > 0) + *out = in; + return ret; + } +#endif + if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key)) < 0) { return ret; @@ -334,6 +386,11 @@ int RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, byte* tmp; byte* pad = 0; +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) + return CaviumRsaSSL_Verify(in, inLen, out, outLen, key); +#endif + tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); if (tmp == NULL) { return MEMORY_E; @@ -362,8 +419,14 @@ int RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, int RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, RNG* rng) { - int sz = mp_unsigned_bin_size(&key->n), ret; + int sz, ret; +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) + return CaviumRsaSSL_Sign(in, inLen, out, outLen, key); +#endif + + sz = mp_unsigned_bin_size(&key->n); if (sz > (int)outLen) return RSA_BUFFER_E; @@ -381,6 +444,10 @@ int RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, int RsaEncryptSize(RsaKey* key) { +#ifdef HAVE_CAVIUM + if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) + return key->c_nSz; +#endif return mp_unsigned_bin_size(&key->n); } @@ -561,4 +628,180 @@ int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng) #endif /* CYASSL_KEY_GEN */ + +#ifdef HAVE_CAVIUM + +#include +#include "cavium_common.h" + +/* Initiliaze RSA for use with Nitrox device */ +int RsaInitCavium(RsaKey* rsa, int devId) +{ + if (rsa == NULL) + return -1; + + if (CspAllocContext(CONTEXT_SSL, &rsa->contextHandle, devId) != 0) + return -1; + + rsa->devId = devId; + rsa->magic = CYASSL_RSA_CAVIUM_MAGIC; + + return 0; +} + + +/* Free RSA from use with Nitrox device */ +void RsaFreeCavium(RsaKey* rsa) +{ + if (rsa == NULL) + return; + + CspFreeContext(CONTEXT_SSL, rsa->contextHandle, rsa->devId); + rsa->magic = 0; +} + + +/* Initialize cavium RSA key */ +static void InitCaviumRsaKey(RsaKey* key, void* heap) +{ + if (key == NULL) + return; + + key->heap = heap; + key->type = -1; /* don't know yet */ + + key->c_n = NULL; + key->c_e = NULL; + key->c_d = NULL; + key->c_p = NULL; + key->c_q = NULL; + key->c_dP = NULL; + key->c_dQ = NULL; + key->c_u = NULL; + + key->c_nSz = 0; + key->c_eSz = 0; + key->c_dSz = 0; + key->c_pSz = 0; + key->c_qSz = 0; + key->c_dP_Sz = 0; + key->c_dQ_Sz = 0; + key->c_uSz = 0; +} + + +/* Free cavium RSA key */ +static void FreeCaviumRsaKey(RsaKey* key) +{ + if (key == NULL) + return; + + XFREE(key->c_n, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_e, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_d, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_p, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_q, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_dP, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_dQ, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_u, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + + InitCaviumRsaKey(key, key->heap); /* reset pointers */ +} + + +static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 requestId; + word32 ret; + + if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->c_nSz) + return -1; + + ret = CspPkcs1v15Enc(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_eSz, + (word16)inLen, key->c_n, key->c_e, (byte*)in, out, + &requestId, key->devId); + if (ret != 0) { + CYASSL_MSG("Cavium Enc BT2 failed"); + return -1; + } + return key->c_nSz; +} + + +static INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (c[0] << 8) | (c[1]); +} + + +static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 requestId; + word32 ret; + word16 outSz = (word16)outLen; + + if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) + return -1; + + ret = CspPkcs1v15CrtDec(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_q, + key->c_dQ, key->c_p, key->c_dP, key->c_u, + (byte*)in, &outSz, out, &requestId, key->devId); + if (ret != 0) { + CYASSL_MSG("Cavium CRT Dec BT2 failed"); + return -1; + } + ato16((const byte*)&outSz, &outSz); + + return outSz; +} + + +static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 requestId; + word32 ret; + + if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen < + (word32)key->c_nSz) + return -1; + + ret = CspPkcs1v15CrtEnc(CAVIUM_BLOCKING, BT1, key->c_nSz, (word16)inLen, + key->c_q, key->c_dQ, key->c_p, key->c_dP, key->c_u, + (byte*)in, out, &requestId, key->devId); + if (ret != 0) { + CYASSL_MSG("Cavium CRT Enc BT1 failed"); + return -1; + } + return key->c_nSz; +} + + +static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 requestId; + word32 ret; + word16 outSz = (word16)outLen; + + if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) + return -1; + + ret = CspPkcs1v15Dec(CAVIUM_BLOCKING, BT1, key->c_nSz, key->c_eSz, + key->c_n, key->c_e, (byte*)in, &outSz, out, + &requestId, key->devId); + if (ret != 0) { + CYASSL_MSG("Cavium Dec BT1 failed"); + return -1; + } + outSz = ntohs(outSz); + + return outSz; +} + + +#endif /* HAVE_CAVIUM */ + #endif /* NO_RSA */ diff --git a/ctaocrypt/test/test.c b/ctaocrypt/test/test.c index feb9c1a99..05ddf08f5 100644 --- a/ctaocrypt/test/test.c +++ b/ctaocrypt/test/test.c @@ -2108,7 +2108,10 @@ int rsa_test(void) bytes = fread(tmp, 1, FOURK_BUF, file); #endif /* USE_CERT_BUFFERS */ - + +#ifdef HAVE_CAVIUM + RsaInitCavium(&key, CAVIUM_DEV_ID); +#endif InitRsaKey(&key, 0); ret = RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes); if (ret != 0) return -41; @@ -2488,6 +2491,9 @@ int rsa_test(void) #endif /* CYASSL_CERT_GEN */ FreeRsaKey(&key); +#ifdef HAVE_CAVIUM + RsaFreeCavium(&key); +#endif free(tmp); return 0; diff --git a/cyassl/ctaocrypt/rsa.h b/cyassl/ctaocrypt/rsa.h index c029e4b09..41486f3e8 100644 --- a/cyassl/ctaocrypt/rsa.h +++ b/cyassl/ctaocrypt/rsa.h @@ -32,6 +32,7 @@ extern "C" { #endif +#define CYASSL_RSA_CAVIUM_MAGIC 0xBEEF0006 enum { RSA_PUBLIC = 0, @@ -43,6 +44,20 @@ typedef struct RsaKey { mp_int n, e, d, p, q, dP, dQ, u; int type; /* public or private */ void* heap; /* for user memory overrides */ +#ifdef HAVE_CAVIUM + int devId; /* nitrox device id */ + word32 magic; /* using cavium magic */ + word64 contextHandle; /* nitrox context memory handle */ + byte* c_n; /* cavium byte buffers for key parts */ + byte* c_e; + byte* c_d; + byte* c_p; + byte* c_q; + byte* c_dP; + byte* c_dQ; + byte* c_u; /* sizes in bytes */ + word16 c_nSz, c_eSz, c_dSz, c_pSz, c_qSz, c_dP_Sz, c_dQ_Sz, c_uSz; +#endif } RsaKey; @@ -72,6 +87,10 @@ CYASSL_API int RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey*, CYASSL_API int RsaKeyToDer(RsaKey*, byte* output, word32 inLen); #endif +#ifdef HAVE_CAVIUM + CYASSL_API int RsaInitCavium(RsaKey*, int); + CYASSL_API void RsaFreeCavium(RsaKey*); +#endif #ifdef __cplusplus diff --git a/cyassl/ctaocrypt/types.h b/cyassl/ctaocrypt/types.h index b33c37e9a..bf1db9f2e 100644 --- a/cyassl/ctaocrypt/types.h +++ b/cyassl/ctaocrypt/types.h @@ -230,7 +230,8 @@ enum { DYNAMIC_TYPE_LIBZ = 36, DYNAMIC_TYPE_ECC = 37, DYNAMIC_TYPE_TMP_BUFFER = 38, - DYNAMIC_TYPE_CAVIUM_TMP = 40 + DYNAMIC_TYPE_CAVIUM_TMP = 40, + DYNAMIC_TYPE_CAVIUM_RSA = 41 }; /* stack protection */