Skip to content

Commit

Permalink
RSA: convert to bin with length in constant time
Browse files Browse the repository at this point in the history
Add mp_to_unsigned_bin_len_ct() which puts a number into a buffer with
padding in constant time.
Call mp_to_unsigned_bin_len_ct() in RSA when encoding result of
exponentiation.
  • Loading branch information
SparkiDev committed Oct 20, 2023
1 parent 1abaa94 commit fcf1406
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 1 deletion.
2 changes: 1 addition & 1 deletion wolfcrypt/src/rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -2693,7 +2693,7 @@ static int RsaFunctionSync(const byte* in, word32 inLen, byte* out,
}

if (ret == 0) {
if (mp_to_unsigned_bin_len(tmp, out, (int)*outLen) != MP_OKAY)
if (mp_to_unsigned_bin_len_ct(tmp, out, (int)*outLen) != MP_OKAY)
ret = MP_TO_E;
}
#else
Expand Down
67 changes: 67 additions & 0 deletions wolfcrypt/src/sp_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -17774,6 +17774,73 @@ int sp_to_unsigned_bin_len(const sp_int* a, byte* out, int outSz)
return err;
}

/* Convert the multi-precision number to an array of bytes in big-endian format.
*
* Constant-time implementation.
*
* The array must be large enough for encoded number - use mp_unsigned_bin_size
* to calculate the number of bytes required.
* Front-pads the output array with zeros to make number the size of the array.
*
* @param [in] a SP integer.
* @param [out] out Array to put encoding into.
* @param [in] outSz Size of the array in bytes.
*
* @return MP_OKAY on success.
* @return MP_VAL when a or out is NULL.
*/
int sp_to_unsigned_bin_len_ct(const sp_int* a, byte* out, int outSz)
{
int err = MP_OKAY;

/* Validate parameters. */
if ((a == NULL) || (out == NULL) || (outSz < 0)) {
err = MP_VAL;
}

#if SP_WORD_SIZE > 8
if (err == MP_OKAY) {
/* Start at the end of the buffer - least significant byte. */
int j;
unsigned int i;
sp_digit mask = (sp_digit)-1;
sp_int_digit d;

/* Put each digit in. */
i = 0;
for (j = outSz - 1; j >= 0; ) {
int b;
d = a->dp[i];
/* Place each byte of a digit into the buffer. */
for (b = 0; (j >= 0) && (b < SP_WORD_SIZEOF); b++) {
out[j--] = (byte)(d & mask);
d >>= 8;
}
mask &= (sp_digit)0 - (i < a->used - 1);
i += (unsigned int)(1 & mask);
}
}
#else
if ((err == MP_OKAY) && ((unsigned int)outSz < a->used)) {
err = MP_VAL;
}
if (err == MP_OKAY) {
unsigned int i;
int j;
sp_digit mask = (sp_digit)-1;

i = 0;
for (j = outSz - 1; j >= 0; j--) {
out[j] = a->dp[i] & mask;
mask &= (sp_digit)0 - (i < a->used - 1);
i += (unsigned int)(1 & mask);
}
}
#endif

return err;
}

#if defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && \
!defined(WOLFSSL_RSA_VERIFY_ONLY)
/* Store the number in big-endian format in array at an offset.
Expand Down
1 change: 1 addition & 0 deletions wolfssl/wolfcrypt/integer.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ MP_API int mp_unsigned_bin_size(const mp_int * a);
MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c);
MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b);
MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b);
#define mp_to_unsigned_bin_len_ct mp_to_unsigned_bin_len
MP_API int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c);
MP_API int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
MP_API int mp_exptmod_ex (mp_int * G, mp_int * X, int digits, mp_int * P,
Expand Down
2 changes: 2 additions & 0 deletions wolfssl/wolfcrypt/sp_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,7 @@ MP_API int sp_unsigned_bin_size(const sp_int* a);
MP_API int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz);
MP_API int sp_to_unsigned_bin(const sp_int* a, byte* out);
MP_API int sp_to_unsigned_bin_len(const sp_int* a, byte* out, int outSz);
MP_API int sp_to_unsigned_bin_len_ct(const sp_int* a, byte* out, int outSz);
#ifdef WOLFSSL_SP_MATH_ALL
MP_API int sp_to_unsigned_bin_at_pos(int o, const sp_int* a,
unsigned char* out);
Expand Down Expand Up @@ -1158,6 +1159,7 @@ WOLFSSL_LOCAL void sp_memzero_check(sp_int* sp);
#define mp_read_unsigned_bin sp_read_unsigned_bin
#define mp_to_unsigned_bin sp_to_unsigned_bin
#define mp_to_unsigned_bin_len sp_to_unsigned_bin_len
#define mp_to_unsigned_bin_len_ct sp_to_unsigned_bin_len_ct
#define mp_to_unsigned_bin_at_pos sp_to_unsigned_bin_at_pos
#define mp_read_radix sp_read_radix
#define mp_tohex sp_tohex
Expand Down
1 change: 1 addition & 0 deletions wolfssl/wolfcrypt/tfm.h
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,7 @@ MP_API int mp_unsigned_bin_size(const mp_int * a);
MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c);
MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b);
MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b);
#define mp_to_unsigned_bin_len_ct mp_to_unsigned_bin_len
MP_API int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c);

MP_API int mp_sub_d(fp_int *a, fp_digit b, fp_int *c);
Expand Down

0 comments on commit fcf1406

Please sign in to comment.