[crypto/asn1] Fix multiple SCA vulnerabilities during RSA key validation.
authorCesar Pereida Garcia <cesar.pereidagarcia@tut.fi>
Thu, 5 Sep 2019 09:13:11 +0000 (12:13 +0300)
committerMatt Caswell <matt@openssl.org>
Fri, 6 Sep 2019 15:11:27 +0000 (16:11 +0100)
This commit addresses multiple side-channel vulnerabilities present
during RSA key validation.
Private key parameters are re-computed using variable-time functions.

This issue was discovered and reported by the NISEC group at TAU Finland.

Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9779)

crypto/asn1/x_bignum.c
crypto/rsa/rsa_lib.c

index d7abca6c769835754d6abc334679ef11bd543a85..c5e892900e1665b75bd23a4b6cd8ebf12f15834e 100644 (file)
@@ -130,9 +130,20 @@ static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
 static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                          int utype, char *free_cont, const ASN1_ITEM *it)
 {
-    if (!*pval)
-        bn_secure_new(pval, it);
-    return bn_c2i(pval, cont, len, utype, free_cont, it);
+    int ret;
+    BIGNUM *bn;
+
+    if (!*pval && !bn_secure_new(pval, it))
+        return 0;
+
+    ret = bn_c2i(pval, cont, len, utype, free_cont, it);
+    if (!ret)
+        return 0;
+
+    /* Set constant-time flag for all secure BIGNUMS */
+    bn = (BIGNUM *)*pval;
+    BN_set_flags(bn, BN_FLG_CONSTTIME);
+    return ret;
 }
 
 static int bn_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
index f337a0df0862c88f2bee19bbba709f12a2dc552d..e7fdbc2aabe839a98a317f3656cad664e6cdffcc 100644 (file)
@@ -325,6 +325,7 @@ int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
     if (d != NULL) {
         BN_clear_free(r->d);
         r->d = d;
+        BN_set_flags(r->d, BN_FLG_CONSTTIME);
     }
 
     return 1;
@@ -342,10 +343,12 @@ int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
     if (p != NULL) {
         BN_clear_free(r->p);
         r->p = p;
+        BN_set_flags(r->p, BN_FLG_CONSTTIME);
     }
     if (q != NULL) {
         BN_clear_free(r->q);
         r->q = q;
+        BN_set_flags(r->q, BN_FLG_CONSTTIME);
     }
 
     return 1;
@@ -364,14 +367,17 @@ int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
     if (dmp1 != NULL) {
         BN_clear_free(r->dmp1);
         r->dmp1 = dmp1;
+        BN_set_flags(r->dmp1, BN_FLG_CONSTTIME);
     }
     if (dmq1 != NULL) {
         BN_clear_free(r->dmq1);
         r->dmq1 = dmq1;
+        BN_set_flags(r->dmq1, BN_FLG_CONSTTIME);
     }
     if (iqmp != NULL) {
         BN_clear_free(r->iqmp);
         r->iqmp = iqmp;
+        BN_set_flags(r->iqmp, BN_FLG_CONSTTIME);
     }
 
     return 1;