@@ -1969,10 +1969,102 @@ int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
19691969 return ret ;
19701970}
19711971
1972+ /* Number of random blinding factors to try. A modulus with many small factors
1973+ * rejects most of them. */
1974+ #define BN_INVMOD_BLIND_TRIES 128
1975+
1976+ /* Compute r = a^-1 mod m with a blinded by a random factor.
1977+ *
1978+ * When a*b has no inverse, the factor b is tested by itself: if it has one then
1979+ * a has none, otherwise another factor is tried.
1980+ * Invert directly when there is no random number generator or no factor found:
1981+ * this API has no way to ask for blinding, so it must not start failing for
1982+ * lack of it. r may alias a or m.
1983+ *
1984+ * @param [in] a MP integer to invert.
1985+ * @param [in] m Big number that is the modulus.
1986+ * @param [out] r MP integer to hold the result.
1987+ * @return MP_OKAY on success.
1988+ * @return Other value on error, including when there is no inverse.
1989+ */
1990+ static int wolfssl_bn_invmod_blind (mp_int * a , const WOLFSSL_BIGNUM * m ,
1991+ mp_int * r )
1992+ {
1993+ mp_int * mod = (mp_int * )m -> internal ;
1994+ int err = MP_OKAY ;
1995+ int found = 0 ;
1996+ WOLFSSL_BIGNUM * t = wolfSSL_BN_new ();
1997+ #ifndef WC_NO_RNG
1998+ int i ;
1999+ WOLFSSL_BIGNUM * b = wolfSSL_BN_new ();
2000+ WOLFSSL_BIGNUM * ar = wolfSSL_BN_new ();
2001+
2002+ if ((t == NULL ) || (b == NULL ) || (ar == NULL )) {
2003+ err = MEMORY_E ;
2004+ }
2005+ if ((err == MP_OKAY ) && (mp_cmp_d (mod , 2 ) == MP_GT )) {
2006+ /* Reduce a once, as mp_invmod() would: a*b may not fit when a is much
2007+ * wider than m. */
2008+ err = mp_mod (a , mod , (mp_int * )ar -> internal );
2009+ for (i = 0 ; (err == MP_OKAY ) && (!found ) &&
2010+ (i < BN_INVMOD_BLIND_TRIES ) &&
2011+ (wolfSSL_BN_rand_range (b , m ) == 1 ); i ++ ) {
2012+ if (mp_iszero ((mp_int * )b -> internal )) {
2013+ continue ;
2014+ }
2015+ err = mp_mulmod ((mp_int * )ar -> internal , (mp_int * )b -> internal , mod ,
2016+ (mp_int * )t -> internal );
2017+ if (err == MP_OKAY ) {
2018+ err = mp_invmod ((mp_int * )t -> internal , mod ,
2019+ (mp_int * )t -> internal );
2020+ if (err == MP_OKAY ) {
2021+ err = mp_mulmod ((mp_int * )t -> internal , (mp_int * )b -> internal ,
2022+ mod , (mp_int * )t -> internal );
2023+ found = (err == MP_OKAY );
2024+ }
2025+ else if (err == WC_NO_ERR_TRACE (MP_VAL )) {
2026+ /* b has an inverse, so a has none: fail. Otherwise b
2027+ * shares a factor with m: try another. */
2028+ err = mp_invmod ((mp_int * )b -> internal , mod ,
2029+ (mp_int * )t -> internal );
2030+ if (err == MP_OKAY ) {
2031+ err = MP_VAL ;
2032+ }
2033+ else if (err == WC_NO_ERR_TRACE (MP_VAL )) {
2034+ err = MP_OKAY ;
2035+ }
2036+ }
2037+ }
2038+ }
2039+ }
2040+ #else
2041+ if (t == NULL ) {
2042+ err = MEMORY_E ;
2043+ }
2044+ #endif
2045+ if ((err == MP_OKAY ) && (!found )) {
2046+ err = mp_invmod (a , mod , (mp_int * )t -> internal );
2047+ }
2048+ if (err == MP_OKAY ) {
2049+ err = mp_copy ((mp_int * )t -> internal , r );
2050+ }
2051+
2052+ #ifndef WC_NO_RNG
2053+ wolfSSL_BN_clear_free (ar );
2054+ wolfSSL_BN_clear_free (b );
2055+ #endif
2056+ wolfSSL_BN_clear_free (t );
2057+
2058+ return err ;
2059+ }
2060+
19722061/* Calculate the modular inverse of a mod m into r. r = a^-1 mod m
19732062 *
19742063 * A new big number is allocated when r is NULL.
19752064 *
2065+ * The operand is blinded when a random blinding factor can be generated, and
2066+ * inverted unblinded otherwise. BN_FLG_CONSTTIME is not checked.
2067+ *
19762068 * @param [in, out] r Big number to hold result. May be NULL.
19772069 * @param [in] a Big number to invert.
19782070 * @param [in] m Big number that is the modulus.
@@ -2009,8 +2101,8 @@ WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a,
20092101 }
20102102
20112103 /* Compute inverse of a modulo n and return in r */
2012- if ((!err ) && (mp_invmod ((mp_int * )a -> internal , ( mp_int * ) m -> internal ,
2013- (mp_int * )r -> internal ) != MP_OKAY )) {
2104+ if ((!err ) && (wolfssl_bn_invmod_blind ((mp_int * )a -> internal ,
2105+ (const WOLFSSL_BIGNUM * ) m , ( mp_int * )r -> internal ) != MP_OKAY )) {
20142106 WOLFSSL_MSG ("mp_invmod() error" );
20152107 err = 1 ;
20162108 }
@@ -2153,6 +2245,9 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
21532245 ret = 0 ;
21542246 }
21552247 /* Dispose of buffer - no longer needed. */
2248+ if (buff != NULL ) {
2249+ ForceZero (buff , len );
2250+ }
21562251 XFREE (buff , NULL , DYNAMIC_TYPE_TMP_BUFFER );
21572252
21582253 /* Truncate to requested bit length when not a whole number of bytes. */
0 commit comments