forked from wolfSSL/wolfssl
Adds new wc_RsaSetNonblockTime
API and WC_RSA_NONBLOCK_TIME
build option. This new function configures the maximum amount of blocking time in microseconds. It uses a pre-computed table along with the CPU speed in megahertz to determine if the next operation can be completed within the maximum blocking time provided.
This commit is contained in:
@ -791,3 +791,81 @@ WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen);
|
|||||||
\sa none
|
\sa none
|
||||||
*/
|
*/
|
||||||
WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng);
|
WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup RSA
|
||||||
|
|
||||||
|
\brief This function sets the non-blocking RSA context. When a RsaNb context
|
||||||
|
is set it enables fast math based non-blocking exptmod, which splits the RSA
|
||||||
|
function into many smaller operations.
|
||||||
|
Enabled when WC_RSA_NONBLOCK is defined.
|
||||||
|
|
||||||
|
\return 0 Success
|
||||||
|
\return BAD_FUNC_ARG Returned if key or nb is null.
|
||||||
|
|
||||||
|
\param key The RSA key structure
|
||||||
|
\param nb The RSA non-blocking structure for this RSA key to use.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
\code
|
||||||
|
int ret, count = 0;
|
||||||
|
RsaKey key;
|
||||||
|
RsaNb nb;
|
||||||
|
|
||||||
|
wc_RsaInitKey(&key, NULL);
|
||||||
|
|
||||||
|
// Enable non-blocking RSA mode - provide context
|
||||||
|
ret = wc_RsaSetNonBlock(key, &nb);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = wc_RsaSSL_Sign(in, inLen, out, outSz, key, rng);
|
||||||
|
count++; // track number of would blocks
|
||||||
|
if (ret == FP_WOULDBLOCK) {
|
||||||
|
// do "other" work here
|
||||||
|
}
|
||||||
|
} while (ret == FP_WOULDBLOCK);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("RSA non-block sign: size %d, %d times\n", ret, count);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\sa wc_RsaSetNonBlockTime
|
||||||
|
*/
|
||||||
|
WOLFSSL_API int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup RSA
|
||||||
|
|
||||||
|
\brief This function configures the maximum amount of blocking time in
|
||||||
|
microseconds. It uses a pre-computed table (see tfm.c exptModNbInst) along
|
||||||
|
with the CPU speed in megahertz to determine if the next operation can be
|
||||||
|
completed within the maximum blocking time provided.
|
||||||
|
Enabled when WC_RSA_NONBLOCK_TIME is defined.
|
||||||
|
|
||||||
|
\return 0 Success
|
||||||
|
\return BAD_FUNC_ARG Returned if key is null or wc_RsaSetNonBlock was not
|
||||||
|
previously called and key->nb is null.
|
||||||
|
|
||||||
|
\param key The RSA key structure.
|
||||||
|
\param maxBlockUs Maximum time to block microseconds.
|
||||||
|
\param cpuMHz CPU speed in megahertz.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
\code
|
||||||
|
RsaKey key;
|
||||||
|
RsaNb nb;
|
||||||
|
|
||||||
|
wc_RsaInitKey(&key, NULL);
|
||||||
|
wc_RsaSetNonBlock(key, &nb);
|
||||||
|
wc_RsaSetNonBlockTime(&key, 4000, 160); // Block Max = 4 ms, CPU = 160MHz
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\sa wc_RsaSetNonBlock
|
||||||
|
*/
|
||||||
|
WOLFSSL_API int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs,
|
||||||
|
word32 cpuMHz);
|
||||||
|
@ -55,7 +55,9 @@ Possible RSA enable options:
|
|||||||
* WOLFSSL_KEY_GEN: Allows Private Key Generation default: off
|
* WOLFSSL_KEY_GEN: Allows Private Key Generation default: off
|
||||||
* RSA_LOW_MEM: NON CRT Private Operations, less memory default: off
|
* RSA_LOW_MEM: NON CRT Private Operations, less memory default: off
|
||||||
* WC_NO_RSA_OAEP: Disables RSA OAEP padding default: on (not defined)
|
* WC_NO_RSA_OAEP: Disables RSA OAEP padding default: on (not defined)
|
||||||
|
* WC_RSA_NONBLOCK: Enables support for RSA non-blocking default: off
|
||||||
|
* WC_RSA_NONBLOCK_TIME:Enables support for time based blocking default: off
|
||||||
|
* time calculation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2813,7 +2815,7 @@ int wc_RsaEncryptSize(RsaKey* key)
|
|||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mp_unsigned_bin_size(&key->n);
|
ret = mp_unsigned_bin_size(&key->n);
|
||||||
|
|
||||||
#ifdef WOLF_CRYPTO_DEV
|
#ifdef WOLF_CRYPTO_DEV
|
||||||
if (ret == 0 && key->devId != INVALID_DEVID) {
|
if (ret == 0 && key->devId != INVALID_DEVID) {
|
||||||
@ -3386,6 +3388,19 @@ int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#ifdef WC_RSA_NONBLOCK_TIME
|
||||||
|
int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, word32 cpuMHz)
|
||||||
|
{
|
||||||
|
if (key == NULL || key->nb == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate maximum number of instructions to block */
|
||||||
|
key->nb->exptmod.maxBlockInst = cpuMHz * maxBlockUs;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* WC_RSA_NONBLOCK_TIME */
|
||||||
#endif /* WC_RSA_NONBLOCK */
|
#endif /* WC_RSA_NONBLOCK */
|
||||||
|
|
||||||
#endif /* NO_RSA */
|
#endif /* NO_RSA */
|
||||||
|
@ -1196,15 +1196,80 @@ int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
|
|||||||
|
|
||||||
#ifdef WC_RSA_NONBLOCK
|
#ifdef WC_RSA_NONBLOCK
|
||||||
|
|
||||||
|
#ifdef WC_RSA_NONBLOCK_TIME
|
||||||
|
/* User can override the check-time at build-time using the
|
||||||
|
* FP_EXPTMOD_NB_CHECKTIME macro to define your own function */
|
||||||
|
#ifndef FP_EXPTMOD_NB_CHECKTIME
|
||||||
|
/* instruction count for each type of operation */
|
||||||
|
/* array lookup is using TFM_EXPTMOD_NB_* states */
|
||||||
|
static const word32 exptModNbInst[TFM_EXPTMOD_NB_COUNT] = {
|
||||||
|
#ifdef TFM_PPC32
|
||||||
|
#ifdef _DEBUG
|
||||||
|
11098, 8701, 3971, 178394, 858093, 1040, 822, 178056, 181574, 90883, 184339, 236813
|
||||||
|
#else
|
||||||
|
7050, 2554, 3187, 43178, 200422, 384, 275, 43024, 43550, 30450, 46270, 61376
|
||||||
|
#endif
|
||||||
|
#elif defined(TFM_X86_64)
|
||||||
|
#ifdef _DEBUG
|
||||||
|
954, 2377, 858, 19027, 90840, 287, 407, 20140, 7874, 11385, 8005, 6151
|
||||||
|
#else
|
||||||
|
765, 1007, 771, 5216, 34993, 248, 193, 4975, 4201, 3947, 4275, 3811
|
||||||
|
#endif
|
||||||
|
#else /* software only fast math */
|
||||||
|
#ifdef _DEBUG
|
||||||
|
798, 2245, 802, 16657, 66920, 352, 186, 16997, 16145, 12789, 16742, 15006
|
||||||
|
#else
|
||||||
|
775, 1084, 783, 4692, 37510, 207, 183, 4374, 4392, 3097, 4442, 4079
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static int fp_exptmod_nb_checktime(exptModNb_t* nb)
|
||||||
|
{
|
||||||
|
word32 totalInst;
|
||||||
|
|
||||||
|
/* if no max time has been set then stop (do not block) */
|
||||||
|
if (nb->maxBlockInst == 0 || nb->state >= TFM_EXPTMOD_NB_COUNT) {
|
||||||
|
return TFM_EXPTMOD_NB_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if instruction table not set then use maxBlockInst as simple counter */
|
||||||
|
if (exptModNbInst[nb->state] == 0) {
|
||||||
|
if (++nb->totalInst < nb->maxBlockInst)
|
||||||
|
return TFM_EXPTMOD_NB_CONTINUE;
|
||||||
|
|
||||||
|
nb->totalInst = 0; /* reset counter */
|
||||||
|
return TFM_EXPTMOD_NB_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get total instruction count including next operation */
|
||||||
|
totalInst = nb->totalInst + exptModNbInst[nb->state];
|
||||||
|
/* if the next operation can completed within the maximum then continue */
|
||||||
|
if (totalInst <= nb->maxBlockInst) {
|
||||||
|
return TFM_EXPTMOD_NB_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TFM_EXPTMOD_NB_STOP;
|
||||||
|
}
|
||||||
|
#define FP_EXPTMOD_NB_CHECKTIME(nb) fp_exptmod_nb_checktime((nb))
|
||||||
|
#endif /* !FP_EXPTMOD_NB_CHECKTIME */
|
||||||
|
#endif /* WC_RSA_NONBLOCK_TIME */
|
||||||
|
|
||||||
/* non-blocking version of timing resistant fp_exptmod function */
|
/* non-blocking version of timing resistant fp_exptmod function */
|
||||||
/* supports cache resistance */
|
/* supports cache resistance */
|
||||||
int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y)
|
int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y)
|
||||||
{
|
{
|
||||||
int err;
|
int err, ret = FP_WOULDBLOCK;
|
||||||
|
|
||||||
if (nb == NULL)
|
if (nb == NULL)
|
||||||
return FP_VAL;
|
return FP_VAL;
|
||||||
|
|
||||||
|
#ifdef WC_RSA_NONBLOCK_TIME
|
||||||
|
nb->totalInst = 0;
|
||||||
|
do {
|
||||||
|
nb->totalInst += exptModNbInst[nb->state];
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (nb->state) {
|
switch (nb->state) {
|
||||||
case TFM_EXPTMOD_NB_INIT:
|
case TFM_EXPTMOD_NB_INIT:
|
||||||
/* now setup montgomery */
|
/* now setup montgomery */
|
||||||
@ -1224,7 +1289,7 @@ int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y)
|
|||||||
|
|
||||||
case TFM_EXPTMOD_NB_MONT:
|
case TFM_EXPTMOD_NB_MONT:
|
||||||
/* mod m -> R[0] */
|
/* mod m -> R[0] */
|
||||||
fp_montgomery_calc_normalization (&nb->R[0], P);
|
fp_montgomery_calc_normalization(&nb->R[0], P);
|
||||||
|
|
||||||
nb->state = TFM_EXPTMOD_NB_MONT_RED;
|
nb->state = TFM_EXPTMOD_NB_MONT_RED;
|
||||||
break;
|
break;
|
||||||
@ -1338,10 +1403,17 @@ int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y)
|
|||||||
fp_copy(&nb->R[0], Y);
|
fp_copy(&nb->R[0], Y);
|
||||||
|
|
||||||
nb->state = TFM_EXPTMOD_NB_INIT;
|
nb->state = TFM_EXPTMOD_NB_INIT;
|
||||||
return FP_OKAY;
|
ret = FP_OKAY;
|
||||||
|
break;
|
||||||
} /* switch */
|
} /* switch */
|
||||||
|
|
||||||
return FP_WOULDBLOCK;
|
#ifdef WC_RSA_NONBLOCK_TIME
|
||||||
|
/* determine if maximum blocking time has been reached */
|
||||||
|
} while (ret == FP_WOULDBLOCK &&
|
||||||
|
FP_EXPTMOD_NB_CHECKTIME(nb) == TFM_EXPTMOD_NB_CONTINUE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WC_RSA_NONBLOCK */
|
#endif /* WC_RSA_NONBLOCK */
|
||||||
|
@ -9383,6 +9383,13 @@ static int rsa_nb_test(RsaKey* key, const byte* in, word32 inLen, byte* out,
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
#ifdef WC_RSA_NONBLOCK_TIME
|
||||||
|
/* Enable time based RSA blocking. 8 microseconds max (3.1GHz) */
|
||||||
|
ret = wc_RsaSetNonBlockTime(key, 8, 3100);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
do {
|
do {
|
||||||
ret = wc_RsaSSL_Sign(in, inLen, out, outSz, key, rng);
|
ret = wc_RsaSSL_Sign(in, inLen, out, outSz, key, rng);
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
#ifndef USE_FAST_MATH
|
#ifndef USE_FAST_MATH
|
||||||
#error RSA non-blocking mode only supported using fast math
|
#error RSA non-blocking mode only supported using fast math
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef TFM_TIMING_RESISTANT
|
||||||
|
#error RSA non-blocking mode only supported with timing resistance enabled
|
||||||
|
#endif
|
||||||
|
|
||||||
/* RSA bounds check is not supported with RSA non-blocking mode */
|
/* RSA bounds check is not supported with RSA non-blocking mode */
|
||||||
#undef NO_RSA_BOUNDS_CHECK
|
#undef NO_RSA_BOUNDS_CHECK
|
||||||
@ -268,6 +271,10 @@ WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef WC_RSA_NONBLOCK
|
#ifdef WC_RSA_NONBLOCK
|
||||||
WOLFSSL_API int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb);
|
WOLFSSL_API int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb);
|
||||||
|
#ifdef WC_RSA_NONBLOCK_TIME
|
||||||
|
WOLFSSL_API int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs,
|
||||||
|
word32 cpuMHz);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -554,6 +554,7 @@ enum tfmExptModNbState {
|
|||||||
TFM_EXPTMOD_NB_SQR,
|
TFM_EXPTMOD_NB_SQR,
|
||||||
TFM_EXPTMOD_NB_SQR_RED,
|
TFM_EXPTMOD_NB_SQR_RED,
|
||||||
TFM_EXPTMOD_NB_RED,
|
TFM_EXPTMOD_NB_RED,
|
||||||
|
TFM_EXPTMOD_NB_COUNT /* last item for total state count only */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -562,13 +563,25 @@ typedef struct {
|
|||||||
#else
|
#else
|
||||||
fp_int R[2];
|
fp_int R[2];
|
||||||
#endif
|
#endif
|
||||||
fp_digit buf, mp;
|
fp_digit buf;
|
||||||
|
fp_digit mp;
|
||||||
int bitcnt;
|
int bitcnt;
|
||||||
int digidx;
|
int digidx;
|
||||||
int y;
|
int y;
|
||||||
int state; /* tfmExptModNbState */
|
int state; /* tfmExptModNbState */
|
||||||
|
#ifdef WC_RSA_NONBLOCK_TIME
|
||||||
|
word32 maxBlockInst; /* maximum instructions to block */
|
||||||
|
word32 totalInst; /* tracks total instructions */
|
||||||
|
#endif
|
||||||
} exptModNb_t;
|
} exptModNb_t;
|
||||||
|
|
||||||
|
#ifdef WC_RSA_NONBLOCK_TIME
|
||||||
|
enum {
|
||||||
|
TFM_EXPTMOD_NB_STOP = 0, /* stop and return FP_WOULDBLOCK */
|
||||||
|
TFM_EXPTMOD_NB_CONTINUE = 1, /* keep blocking */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* non-blocking version of timing resistant fp_exptmod function */
|
/* non-blocking version of timing resistant fp_exptmod function */
|
||||||
/* supports cache resistance */
|
/* supports cache resistance */
|
||||||
int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y);
|
int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y);
|
||||||
|
Reference in New Issue
Block a user