Blame SOURCES/openssl-1.0.2k-cve-2018-0495.patch

bbd2dd
diff -up openssl-1.0.2k/crypto/bn/bn_div.c.rohnp-fix openssl-1.0.2k/crypto/bn/bn_div.c
bbd2dd
--- openssl-1.0.2k/crypto/bn/bn_div.c.rohnp-fix	2017-01-26 14:22:03.000000000 +0100
bbd2dd
+++ openssl-1.0.2k/crypto/bn/bn_div.c	2018-08-14 10:57:21.592518702 +0200
bbd2dd
@@ -290,6 +290,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const
bbd2dd
     wnum.neg = 0;
bbd2dd
     wnum.d = &(snum->d[loop]);
bbd2dd
     wnum.top = div_n;
bbd2dd
+    wnum.flags = BN_FLG_STATIC_DATA;
bbd2dd
     /*
bbd2dd
      * only needed when BN_ucmp messes up the values between top and max
bbd2dd
      */
bbd2dd
diff -up openssl-1.0.2k/crypto/bn/bn_exp.c.rohnp-fix openssl-1.0.2k/crypto/bn/bn_exp.c
bbd2dd
--- openssl-1.0.2k/crypto/bn/bn_exp.c.rohnp-fix	2017-01-26 14:22:03.000000000 +0100
bbd2dd
+++ openssl-1.0.2k/crypto/bn/bn_exp.c	2018-08-14 10:57:21.596518798 +0200
bbd2dd
@@ -466,17 +466,17 @@ int BN_mod_exp_mont(BIGNUM *rr, const BI
bbd2dd
         ret = 1;
bbd2dd
         goto err;
bbd2dd
     }
bbd2dd
-    if (!BN_to_montgomery(val[0], aa, mont, ctx))
bbd2dd
+    if (!bn_to_mont_fixed_top(val[0], aa, mont, ctx))
bbd2dd
         goto err;               /* 1 */
bbd2dd
 
bbd2dd
     window = BN_window_bits_for_exponent_size(bits);
bbd2dd
     if (window > 1) {
bbd2dd
-        if (!BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx))
bbd2dd
+        if (!bn_mul_mont_fixed_top(d, val[0], val[0], mont, ctx))
bbd2dd
             goto err;           /* 2 */
bbd2dd
         j = 1 << (window - 1);
bbd2dd
         for (i = 1; i < j; i++) {
bbd2dd
             if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
bbd2dd
-                !BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx))
bbd2dd
+                !bn_mul_mont_fixed_top(val[i], val[i - 1], d, mont, ctx))
bbd2dd
                 goto err;
bbd2dd
         }
bbd2dd
     }
bbd2dd
@@ -498,19 +498,15 @@ int BN_mod_exp_mont(BIGNUM *rr, const BI
bbd2dd
         for (i = 1; i < j; i++)
bbd2dd
             r->d[i] = (~m->d[i]) & BN_MASK2;
bbd2dd
         r->top = j;
bbd2dd
-        /*
bbd2dd
-         * Upper words will be zero if the corresponding words of 'm' were
bbd2dd
-         * 0xfff[...], so decrement r->top accordingly.
bbd2dd
-         */
bbd2dd
-        bn_correct_top(r);
bbd2dd
+        r->flags |= BN_FLG_FIXED_TOP;
bbd2dd
     } else
bbd2dd
 #endif
bbd2dd
-    if (!BN_to_montgomery(r, BN_value_one(), mont, ctx))
bbd2dd
+    if (!bn_to_mont_fixed_top(r, BN_value_one(), mont, ctx))
bbd2dd
         goto err;
bbd2dd
     for (;;) {
bbd2dd
         if (BN_is_bit_set(p, wstart) == 0) {
bbd2dd
             if (!start) {
bbd2dd
-                if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
bbd2dd
+                if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
bbd2dd
                     goto err;
bbd2dd
             }
bbd2dd
             if (wstart == 0)
bbd2dd
@@ -541,12 +537,12 @@ int BN_mod_exp_mont(BIGNUM *rr, const BI
bbd2dd
         /* add the 'bytes above' */
bbd2dd
         if (!start)
bbd2dd
             for (i = 0; i < j; i++) {
bbd2dd
-                if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
bbd2dd
+                if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
bbd2dd
                     goto err;
bbd2dd
             }
bbd2dd
 
bbd2dd
         /* wvalue will be an odd number < 2^window */
bbd2dd
-        if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx))
bbd2dd
+        if (!bn_mul_mont_fixed_top(r, r, val[wvalue >> 1], mont, ctx))
bbd2dd
             goto err;
bbd2dd
 
bbd2dd
         /* move the 'window' down further */
bbd2dd
@@ -556,6 +552,11 @@ int BN_mod_exp_mont(BIGNUM *rr, const BI
bbd2dd
         if (wstart < 0)
bbd2dd
             break;
bbd2dd
     }
bbd2dd
+    /*
bbd2dd
+     * Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
bbd2dd
+     * removes padding [if any] and makes return value suitable for public
bbd2dd
+     * API consumer.
bbd2dd
+     */
bbd2dd
 #if defined(SPARC_T4_MONT)
bbd2dd
     if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
bbd2dd
         j = mont->N.top;        /* borrow j */
bbd2dd
@@ -674,7 +675,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBU
bbd2dd
     }
bbd2dd
 
bbd2dd
     b->top = top;
bbd2dd
-    bn_correct_top(b);
bbd2dd
+    b->flags |= BN_FLG_FIXED_TOP;
bbd2dd
     return 1;
bbd2dd
 }
bbd2dd
 
bbd2dd
@@ -841,16 +842,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr
bbd2dd
         tmp.top = top;
bbd2dd
     } else
bbd2dd
 #endif
bbd2dd
-    if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx))
bbd2dd
+    if (!bn_to_mont_fixed_top(&tmp, BN_value_one(), mont, ctx))
bbd2dd
         goto err;
bbd2dd
 
bbd2dd
     /* prepare a^1 in Montgomery domain */
bbd2dd
     if (a->neg || BN_ucmp(a, m) >= 0) {
bbd2dd
         if (!BN_mod(&am, a, m, ctx))
bbd2dd
             goto err;
bbd2dd
-        if (!BN_to_montgomery(&am, &am, mont, ctx))
bbd2dd
+        if (!bn_to_mont_fixed_top(&am, &am, mont, ctx))
bbd2dd
             goto err;
bbd2dd
-    } else if (!BN_to_montgomery(&am, a, mont, ctx))
bbd2dd
+    } else if (!bn_to_mont_fixed_top(&am, a, mont, ctx))
bbd2dd
         goto err;
bbd2dd
 
bbd2dd
 #if defined(SPARC_T4_MONT)
bbd2dd
@@ -1117,14 +1118,14 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr
bbd2dd
          * performance advantage of sqr over mul).
bbd2dd
          */
bbd2dd
         if (window > 1) {
bbd2dd
-            if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx))
bbd2dd
+            if (!bn_mul_mont_fixed_top(&tmp, &am, &am, mont, ctx))
bbd2dd
                 goto err;
bbd2dd
             if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2,
bbd2dd
                                               window))
bbd2dd
                 goto err;
bbd2dd
             for (i = 3; i < numPowers; i++) {
bbd2dd
                 /* Calculate a^i = a^(i-1) * a */
bbd2dd
-                if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx))
bbd2dd
+                if (!bn_mul_mont_fixed_top(&tmp, &am, &tmp, mont, ctx))
bbd2dd
                     goto err;
bbd2dd
                 if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i,
bbd2dd
                                                   window))
bbd2dd
@@ -1148,7 +1149,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr
bbd2dd
 
bbd2dd
             /* Scan the window, squaring the result as we go */
bbd2dd
             for (i = 0; i < window; i++, bits--) {
bbd2dd
-                if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx))
bbd2dd
+                if (!bn_mul_mont_fixed_top(&tmp, &tmp, &tmp, mont, ctx))
bbd2dd
                     goto err;
bbd2dd
                 wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
bbd2dd
             }
bbd2dd
@@ -1161,12 +1162,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr
bbd2dd
                 goto err;
bbd2dd
 
bbd2dd
             /* Multiply the result into the intermediate result */
bbd2dd
-            if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx))
bbd2dd
+            if (!bn_mul_mont_fixed_top(&tmp, &tmp, &am, mont, ctx))
bbd2dd
                 goto err;
bbd2dd
         }
bbd2dd
     }
bbd2dd
 
bbd2dd
-    /* Convert the final result from montgomery to standard format */
bbd2dd
+    /*
bbd2dd
+     * Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
bbd2dd
+     * removes padding [if any] and makes return value suitable for public
bbd2dd
+     * API consumer.
bbd2dd
+     */
bbd2dd
 #if defined(SPARC_T4_MONT)
bbd2dd
     if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
bbd2dd
         am.d[0] = 1;            /* borrow am */
bbd2dd
diff -up openssl-1.0.2k/crypto/bn/bn.h.rohnp-fix openssl-1.0.2k/crypto/bn/bn.h
bbd2dd
--- openssl-1.0.2k/crypto/bn/bn.h.rohnp-fix	2018-06-20 17:44:01.752387208 +0200
bbd2dd
+++ openssl-1.0.2k/crypto/bn/bn.h	2018-08-14 10:57:21.592518702 +0200
bbd2dd
@@ -702,6 +702,16 @@ BIGNUM *bn_dup_expand(const BIGNUM *a, i
bbd2dd
 /* We only need assert() when debugging */
bbd2dd
 #  include <assert.h>
bbd2dd
 
bbd2dd
+/*
bbd2dd
+ * The new BN_FLG_FIXED_TOP flag marks vectors that were not treated with
bbd2dd
+ * bn_correct_top, in other words such vectors are permitted to have zeros
bbd2dd
+ * in most significant limbs. Such vectors are used internally to achieve
bbd2dd
+ * execution time invariance for critical operations with private keys.
bbd2dd
+ * It's BN_DEBUG-only flag, because user application is not supposed to
bbd2dd
+ * observe it anyway. Moreover, optimizing compiler would actually remove
bbd2dd
+ * all operations manipulating the bit in question in non-BN_DEBUG build.
bbd2dd
+ */
bbd2dd
+#  define BN_FLG_FIXED_TOP 0x10000
bbd2dd
 #  ifdef BN_DEBUG_RAND
bbd2dd
 /* To avoid "make update" cvs wars due to BN_DEBUG, use some tricks */
bbd2dd
 #   ifndef RAND_pseudo_bytes
bbd2dd
@@ -734,8 +744,10 @@ int RAND_pseudo_bytes(unsigned char *buf
bbd2dd
         do { \
bbd2dd
                 const BIGNUM *_bnum2 = (a); \
bbd2dd
                 if (_bnum2 != NULL) { \
bbd2dd
-                        assert((_bnum2->top == 0) || \
bbd2dd
-                                (_bnum2->d[_bnum2->top - 1] != 0)); \
bbd2dd
+                        int _top = _bnum2->top; \
bbd2dd
+                        assert((_top == 0) || \
bbd2dd
+                               (_bnum2->flags & BN_FLG_FIXED_TOP) || \
bbd2dd
+                               (_bnum2->d[_top - 1] != 0)); \
bbd2dd
                         bn_pollute(_bnum2); \
bbd2dd
                 } \
bbd2dd
         } while(0)
bbd2dd
@@ -753,6 +765,7 @@ int RAND_pseudo_bytes(unsigned char *buf
bbd2dd
 
bbd2dd
 # else                          /* !BN_DEBUG */
bbd2dd
 
bbd2dd
+#  define BN_FLG_FIXED_TOP 0
bbd2dd
 #  define bn_pollute(a)
bbd2dd
 #  define bn_check_top(a)
bbd2dd
 #  define bn_fix_top(a)           bn_correct_top(a)
bbd2dd
diff -up openssl-1.0.2k/crypto/bn/bn_lcl.h.rohnp-fix openssl-1.0.2k/crypto/bn/bn_lcl.h
bbd2dd
--- openssl-1.0.2k/crypto/bn/bn_lcl.h.rohnp-fix	2018-06-20 17:44:01.748387114 +0200
bbd2dd
+++ openssl-1.0.2k/crypto/bn/bn_lcl.h	2018-08-14 10:57:21.596518798 +0200
bbd2dd
@@ -113,6 +113,7 @@
bbd2dd
 # define HEADER_BN_LCL_H
bbd2dd
 
bbd2dd
 # include <openssl/bn.h>
bbd2dd
+# include "bn_int.h"
bbd2dd
 
bbd2dd
 #ifdef  __cplusplus
bbd2dd
 extern "C" {
bbd2dd
diff -up openssl-1.0.2k/crypto/bn/bn_lib.c.rohnp-fix openssl-1.0.2k/crypto/bn/bn_lib.c
bbd2dd
--- openssl-1.0.2k/crypto/bn/bn_lib.c.rohnp-fix	2017-01-26 14:22:03.000000000 +0100
bbd2dd
+++ openssl-1.0.2k/crypto/bn/bn_lib.c	2018-08-14 10:57:21.592518702 +0200
bbd2dd
@@ -290,8 +290,6 @@ static BN_ULONG *bn_expand_internal(cons
bbd2dd
     const BN_ULONG *B;
bbd2dd
     int i;
bbd2dd
 
bbd2dd
-    bn_check_top(b);
bbd2dd
-
bbd2dd
     if (words > (INT_MAX / (4 * BN_BITS2))) {
bbd2dd
         BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG);
bbd2dd
         return NULL;
bbd2dd
@@ -425,8 +423,6 @@ BIGNUM *bn_dup_expand(const BIGNUM *b, i
bbd2dd
 
bbd2dd
 BIGNUM *bn_expand2(BIGNUM *b, int words)
bbd2dd
 {
bbd2dd
-    bn_check_top(b);
bbd2dd
-
bbd2dd
     if (words > b->dmax) {
bbd2dd
         BN_ULONG *a = bn_expand_internal(b, words);
bbd2dd
         if (!a)
bbd2dd
@@ -460,7 +456,6 @@ BIGNUM *bn_expand2(BIGNUM *b, int words)
bbd2dd
         assert(A == &(b->d[b->dmax]));
bbd2dd
     }
bbd2dd
 #endif
bbd2dd
-    bn_check_top(b);
bbd2dd
     return b;
bbd2dd
 }
bbd2dd
 
bbd2dd
@@ -572,6 +567,7 @@ void BN_clear(BIGNUM *a)
bbd2dd
         OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0]));
bbd2dd
     a->top = 0;
bbd2dd
     a->neg = 0;
bbd2dd
+    a->flags &= ~BN_FLG_FIXED_TOP;
bbd2dd
 }
bbd2dd
 
bbd2dd
 BN_ULONG BN_get_word(const BIGNUM *a)
bbd2dd
@@ -592,6 +588,7 @@ int BN_set_word(BIGNUM *a, BN_ULONG w)
bbd2dd
     a->neg = 0;
bbd2dd
     a->d[0] = w;
bbd2dd
     a->top = (w ? 1 : 0);
bbd2dd
+    a->flags &= ~BN_FLG_FIXED_TOP;
bbd2dd
     bn_check_top(a);
bbd2dd
     return (1);
bbd2dd
 }
bbd2dd
@@ -738,6 +735,7 @@ int BN_set_bit(BIGNUM *a, int n)
bbd2dd
         for (k = a->top; k < i + 1; k++)
bbd2dd
             a->d[k] = 0;
bbd2dd
         a->top = i + 1;
bbd2dd
+        a->flags &= ~BN_FLG_FIXED_TOP;
bbd2dd
     }
bbd2dd
 
bbd2dd
     a->d[i] |= (((BN_ULONG)1) << j);
bbd2dd
diff -up openssl-1.0.2k/crypto/bn/bn_mod.c.rohnp-fix openssl-1.0.2k/crypto/bn/bn_mod.c
bbd2dd
--- openssl-1.0.2k/crypto/bn/bn_mod.c.rohnp-fix	2017-01-26 14:22:03.000000000 +0100
bbd2dd
+++ openssl-1.0.2k/crypto/bn/bn_mod.c	2018-08-14 10:57:21.601518919 +0200
bbd2dd
@@ -149,18 +149,73 @@ int BN_mod_add(BIGNUM *r, const BIGNUM *
bbd2dd
 
bbd2dd
 /*
bbd2dd
  * BN_mod_add variant that may be used if both a and b are non-negative and
bbd2dd
- * less than m
bbd2dd
+ * less than m. The original algorithm was
bbd2dd
+ *
bbd2dd
+ *    if (!BN_uadd(r, a, b))
bbd2dd
+ *       return 0;
bbd2dd
+ *    if (BN_ucmp(r, m) >= 0)
bbd2dd
+ *       return BN_usub(r, r, m);
bbd2dd
+ *
bbd2dd
+ * which is replaced with addition, subtracting modulus, and conditional
bbd2dd
+ * move depending on whether or not subtraction borrowed.
bbd2dd
  */
bbd2dd
-int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
bbd2dd
-                     const BIGNUM *m)
bbd2dd
+int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
bbd2dd
+                         const BIGNUM *m)
bbd2dd
 {
bbd2dd
-    if (!BN_uadd(r, a, b))
bbd2dd
+    size_t i, ai, bi, mtop = m->top;
bbd2dd
+    BN_ULONG storage[1024 / BN_BITS2];
bbd2dd
+    BN_ULONG carry, temp, mask, *rp, *tp = storage;
bbd2dd
+    const BN_ULONG *ap, *bp;
bbd2dd
+
bbd2dd
+    if (bn_wexpand(r, m->top) == NULL)
bbd2dd
         return 0;
bbd2dd
-    if (BN_ucmp(r, m) >= 0)
bbd2dd
-        return BN_usub(r, r, m);
bbd2dd
+
bbd2dd
+    if (mtop > sizeof(storage) / sizeof(storage[0])
bbd2dd
+        && (tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG))) == NULL)
bbd2dd
+	return 0;
bbd2dd
+
bbd2dd
+    ap = a->d != NULL ? a->d : tp;
bbd2dd
+    bp = b->d != NULL ? b->d : tp;
bbd2dd
+
bbd2dd
+    for (i = 0, ai = 0, bi = 0, carry = 0; i < mtop;) {
bbd2dd
+        mask = (BN_ULONG)0 - ((i - a->top) >> (8 * sizeof(i) - 1));
bbd2dd
+        temp = ((ap[ai] & mask) + carry) & BN_MASK2;
bbd2dd
+        carry = (temp < carry);
bbd2dd
+
bbd2dd
+        mask = (BN_ULONG)0 - ((i - b->top) >> (8 * sizeof(i) - 1));
bbd2dd
+        tp[i] = ((bp[bi] & mask) + temp) & BN_MASK2;
bbd2dd
+        carry += (tp[i] < temp);
bbd2dd
+
bbd2dd
+        i++;
bbd2dd
+        ai += (i - a->dmax) >> (8 * sizeof(i) - 1);
bbd2dd
+        bi += (i - b->dmax) >> (8 * sizeof(i) - 1);
bbd2dd
+    }
bbd2dd
+    rp = r->d;
bbd2dd
+    carry -= bn_sub_words(rp, tp, m->d, mtop);
bbd2dd
+    for (i = 0; i < mtop; i++) {
bbd2dd
+        rp[i] = (carry & tp[i]) | (~carry & rp[i]);
bbd2dd
+        ((volatile BN_ULONG *)tp)[i] = 0;
bbd2dd
+    }
bbd2dd
+    r->top = mtop;
bbd2dd
+    r->neg = 0;
bbd2dd
+
bbd2dd
+    if (tp != storage)
bbd2dd
+        OPENSSL_free(tp);
bbd2dd
+
bbd2dd
     return 1;
bbd2dd
 }
bbd2dd
 
bbd2dd
+int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
bbd2dd
+                     const BIGNUM *m)
bbd2dd
+{
bbd2dd
+    int ret = bn_mod_add_fixed_top(r, a, b, m);
bbd2dd
+
bbd2dd
+    if (ret)
bbd2dd
+        bn_correct_top(r);
bbd2dd
+
bbd2dd
+    return ret;
bbd2dd
+}
bbd2dd
+
bbd2dd
 int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
bbd2dd
                BN_CTX *ctx)
bbd2dd
 {
bbd2dd
diff -up openssl-1.0.2k/crypto/bn/bn_mont.c.rohnp-fix openssl-1.0.2k/crypto/bn/bn_mont.c
bbd2dd
--- openssl-1.0.2k/crypto/bn/bn_mont.c.rohnp-fix	2018-08-14 10:57:21.589518629 +0200
bbd2dd
+++ openssl-1.0.2k/crypto/bn/bn_mont.c	2018-08-14 11:15:11.425320301 +0200
bbd2dd
@@ -56,7 +56,7 @@
bbd2dd
  * [including the GNU Public Licence.]
bbd2dd
  */
bbd2dd
 /* ====================================================================
bbd2dd
- * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
bbd2dd
+ * Copyright (c) 1998-2018 The OpenSSL Project.  All rights reserved.
bbd2dd
  *
bbd2dd
  * Redistribution and use in source and binary forms, with or without
bbd2dd
  * modification, are permitted provided that the following conditions
bbd2dd
@@ -123,12 +123,23 @@
bbd2dd
 #define MONT_WORD               /* use the faster word-based algorithm */
bbd2dd
 
bbd2dd
 #ifdef MONT_WORD
bbd2dd
-static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
bbd2dd
+static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
bbd2dd
 #endif
bbd2dd
 
bbd2dd
 int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
bbd2dd
                           BN_MONT_CTX *mont, BN_CTX *ctx)
bbd2dd
 {
bbd2dd
+    int ret = bn_mul_mont_fixed_top(r, a, b, mont, ctx);
bbd2dd
+
bbd2dd
+    bn_correct_top(r);
bbd2dd
+    bn_check_top(r);
bbd2dd
+
bbd2dd
+    return ret;
bbd2dd
+}
bbd2dd
+
bbd2dd
+int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
bbd2dd
+                          BN_MONT_CTX *mont, BN_CTX *ctx)
bbd2dd
+{
bbd2dd
     BIGNUM *tmp;
bbd2dd
     int ret = 0;
bbd2dd
 #if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
bbd2dd
@@ -140,8 +151,8 @@ int BN_mod_mul_montgomery(BIGNUM *r, con
bbd2dd
         if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
bbd2dd
             r->neg = a->neg ^ b->neg;
bbd2dd
             r->top = num;
bbd2dd
-            bn_correct_top(r);
bbd2dd
-            return (1);
bbd2dd
+            r->flags |= BN_FLG_FIXED_TOP;
bbd2dd
+            return 1;
bbd2dd
         }
bbd2dd
     }
bbd2dd
 #endif
bbd2dd
@@ -161,13 +172,12 @@ int BN_mod_mul_montgomery(BIGNUM *r, con
bbd2dd
     }
bbd2dd
     /* reduce from aRR to aR */
bbd2dd
 #ifdef MONT_WORD
bbd2dd
-    if (!BN_from_montgomery_word(r, tmp, mont))
bbd2dd
+    if (!bn_from_montgomery_word(r, tmp, mont))
bbd2dd
         goto err;
bbd2dd
 #else
bbd2dd
     if (!BN_from_montgomery(r, tmp, mont, ctx))
bbd2dd
         goto err;
bbd2dd
 #endif
bbd2dd
-    bn_check_top(r);
bbd2dd
     ret = 1;
bbd2dd
  err:
bbd2dd
     BN_CTX_end(ctx);
bbd2dd
@@ -175,7 +185,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, con
bbd2dd
 }
bbd2dd
 
bbd2dd
 #ifdef MONT_WORD
bbd2dd
-static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
bbd2dd
+static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
bbd2dd
 {
bbd2dd
     BIGNUM *n;
bbd2dd
     BN_ULONG *ap, *np, *rp, n0, v, carry;
bbd2dd
@@ -205,28 +215,16 @@ static int BN_from_montgomery_word(BIGNU
bbd2dd
 # endif
bbd2dd
 
bbd2dd
     r->top = max;
bbd2dd
+    r->flags |= BN_FLG_FIXED_TOP;
bbd2dd
     n0 = mont->n0[0];
bbd2dd
 
bbd2dd
-# ifdef BN_COUNT
bbd2dd
-    fprintf(stderr, "word BN_from_montgomery_word %d * %d\n", nl, nl);
bbd2dd
-# endif
bbd2dd
+    /*
bbd2dd
+     * Add multiples of |n| to |r| until R = 2^(nl * BN_BITS2) divides it. On
bbd2dd
+     * input, we had |r| < |n| * R, so now |r| < 2 * |n| * R. Note that |r|
bbd2dd
+     * includes |carry| which is stored separately.
bbd2dd
+     */
bbd2dd
     for (carry = 0, i = 0; i < nl; i++, rp++) {
bbd2dd
-# ifdef __TANDEM
bbd2dd
-        {
bbd2dd
-            long long t1;
bbd2dd
-            long long t2;
bbd2dd
-            long long t3;
bbd2dd
-            t1 = rp[0] * (n0 & 0177777);
bbd2dd
-            t2 = 037777600000l;
bbd2dd
-            t2 = n0 & t2;
bbd2dd
-            t3 = rp[0] & 0177777;
bbd2dd
-            t2 = (t3 * t2) & BN_MASK2;
bbd2dd
-            t1 = t1 + t2;
bbd2dd
-            v = bn_mul_add_words(rp, np, nl, (BN_ULONG)t1);
bbd2dd
-        }
bbd2dd
-# else
bbd2dd
         v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2);
bbd2dd
-# endif
bbd2dd
         v = (v + carry + rp[nl]) & BN_MASK2;
bbd2dd
         carry |= (v != rp[nl]);
bbd2dd
         carry &= (v <= rp[nl]);
bbd2dd
@@ -236,52 +234,27 @@ static int BN_from_montgomery_word(BIGNU
bbd2dd
     if (bn_wexpand(ret, nl) == NULL)
bbd2dd
         return (0);
bbd2dd
     ret->top = nl;
bbd2dd
+    ret->flags |= BN_FLG_FIXED_TOP;
bbd2dd
     ret->neg = r->neg;
bbd2dd
 
bbd2dd
     rp = ret->d;
bbd2dd
-    ap = &(r->d[nl]);
bbd2dd
 
bbd2dd
-# define BRANCH_FREE 1
bbd2dd
-# if BRANCH_FREE
bbd2dd
-    {
bbd2dd
-        BN_ULONG *nrp;
bbd2dd
-        size_t m;
bbd2dd
+    /*
bbd2dd
+     * Shift |nl| words to divide by R. We have |ap| < 2 * |n|. Note that |ap|
bbd2dd
+     * includes |carry| which is stored separately.
bbd2dd
+     */
bbd2dd
+    ap = &(r->d[nl]);
bbd2dd
 
bbd2dd
-        v = bn_sub_words(rp, ap, np, nl) - carry;
bbd2dd
-        /*
bbd2dd
-         * if subtraction result is real, then trick unconditional memcpy
bbd2dd
-         * below to perform in-place "refresh" instead of actual copy.
bbd2dd
-         */
bbd2dd
-        m = (0 - (size_t)v);
bbd2dd
-        nrp =
bbd2dd
-            (BN_ULONG *)(((PTR_SIZE_INT) rp & ~m) | ((PTR_SIZE_INT) ap & m));
bbd2dd
-
bbd2dd
-        for (i = 0, nl -= 4; i < nl; i += 4) {
bbd2dd
-            BN_ULONG t1, t2, t3, t4;
bbd2dd
-
bbd2dd
-            t1 = nrp[i + 0];
bbd2dd
-            t2 = nrp[i + 1];
bbd2dd
-            t3 = nrp[i + 2];
bbd2dd
-            ap[i + 0] = 0;
bbd2dd
-            t4 = nrp[i + 3];
bbd2dd
-            ap[i + 1] = 0;
bbd2dd
-            rp[i + 0] = t1;
bbd2dd
-            ap[i + 2] = 0;
bbd2dd
-            rp[i + 1] = t2;
bbd2dd
-            ap[i + 3] = 0;
bbd2dd
-            rp[i + 2] = t3;
bbd2dd
-            rp[i + 3] = t4;
bbd2dd
-        }
bbd2dd
-        for (nl += 4; i < nl; i++)
bbd2dd
-            rp[i] = nrp[i], ap[i] = 0;
bbd2dd
+    carry -= bn_sub_words(rp, ap, np, nl);
bbd2dd
+    /*
bbd2dd
+     * |carry| is -1 if |ap| - |np| underflowed or zero if it did not. Note
bbd2dd
+     * |carry| cannot be 1. That would imply the subtraction did not fit in
bbd2dd
+     * |nl| words, and we know at most one subtraction is needed.
bbd2dd
+     */
bbd2dd
+    for (i = 0; i < nl; i++) {
bbd2dd
+        rp[i] = (carry & ap[i]) | (~carry & rp[i]);
bbd2dd
+        ap[i] = 0;
bbd2dd
     }
bbd2dd
-# else
bbd2dd
-    if (bn_sub_words(rp, ap, np, nl) - carry)
bbd2dd
-        memcpy(rp, ap, nl * sizeof(BN_ULONG));
bbd2dd
-# endif
bbd2dd
-    bn_correct_top(r);
bbd2dd
-    bn_correct_top(ret);
bbd2dd
-    bn_check_top(ret);
bbd2dd
 
bbd2dd
     return (1);
bbd2dd
 }
bbd2dd
@@ -295,8 +268,11 @@ int BN_from_montgomery(BIGNUM *ret, cons
bbd2dd
     BIGNUM *t;
bbd2dd
 
bbd2dd
     BN_CTX_start(ctx);
bbd2dd
-    if ((t = BN_CTX_get(ctx)) && BN_copy(t, a))
bbd2dd
-        retn = BN_from_montgomery_word(ret, t, mont);
bbd2dd
+    if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) {
bbd2dd
+        retn = bn_from_montgomery_word(ret, t, mont);
bbd2dd
+        bn_correct_top(ret);
bbd2dd
+        bn_check_top(ret);
bbd2dd
+    }
bbd2dd
     BN_CTX_end(ctx);
bbd2dd
 #else                           /* !MONT_WORD */
bbd2dd
     BIGNUM *t1, *t2;
bbd2dd
@@ -334,6 +310,12 @@ int BN_from_montgomery(BIGNUM *ret, cons
bbd2dd
     return (retn);
bbd2dd
 }
bbd2dd
 
bbd2dd
+int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
bbd2dd
+                         BN_CTX *ctx)
bbd2dd
+{
bbd2dd
+    return bn_mul_mont_fixed_top(r, a, &(mont->RR), mont, ctx);
bbd2dd
+}
bbd2dd
+
bbd2dd
 BN_MONT_CTX *BN_MONT_CTX_new(void)
bbd2dd
 {
bbd2dd
     BN_MONT_CTX *ret;
bbd2dd
@@ -370,7 +352,7 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont)
bbd2dd
 
bbd2dd
 int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
bbd2dd
 {
bbd2dd
-    int ret = 0;
bbd2dd
+    int i, ret = 0;
bbd2dd
     BIGNUM *Ri, *R;
bbd2dd
 
bbd2dd
     if (BN_is_zero(mod))
bbd2dd
@@ -382,6 +364,8 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, c
bbd2dd
     R = &(mont->RR);            /* grab RR as a temp */
bbd2dd
     if (!BN_copy(&(mont->N), mod))
bbd2dd
         goto err;               /* Set N */
bbd2dd
+    if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
bbd2dd
+        BN_set_flags(&(mont->N), BN_FLG_CONSTTIME);
bbd2dd
     mont->N.neg = 0;
bbd2dd
 
bbd2dd
 #ifdef MONT_WORD
bbd2dd
@@ -394,6 +378,9 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, c
bbd2dd
         tmod.dmax = 2;
bbd2dd
         tmod.neg = 0;
bbd2dd
 
bbd2dd
+        if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
bbd2dd
+            BN_set_flags(&tmod, BN_FLG_CONSTTIME);
bbd2dd
+
bbd2dd
         mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
bbd2dd
 
bbd2dd
 # if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)
bbd2dd
@@ -496,6 +483,11 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, c
bbd2dd
     if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx))
bbd2dd
         goto err;
bbd2dd
 
bbd2dd
+    for (i = mont->RR.top, ret = mont->N.top; i < ret; i++)
bbd2dd
+        mont->RR.d[i] = 0;
bbd2dd
+    mont->RR.top = ret;
bbd2dd
+    mont->RR.flags |= BN_FLG_FIXED_TOP;
bbd2dd
+
bbd2dd
     ret = 1;
bbd2dd
  err:
bbd2dd
     BN_CTX_end(ctx);
bbd2dd
diff -up openssl-1.0.2k/crypto/bn/bn_sqr.c.rohnp-fix openssl-1.0.2k/crypto/bn/bn_sqr.c
bbd2dd
--- openssl-1.0.2k/crypto/bn/bn_sqr.c.rohnp-fix	2017-01-26 14:22:03.000000000 +0100
bbd2dd
+++ openssl-1.0.2k/crypto/bn/bn_sqr.c	2018-08-14 10:57:21.593518726 +0200
bbd2dd
@@ -135,14 +135,8 @@ int BN_sqr(BIGNUM *r, const BIGNUM *a, B
bbd2dd
     }
bbd2dd
 
bbd2dd
     rr->neg = 0;
bbd2dd
-    /*
bbd2dd
-     * If the most-significant half of the top word of 'a' is zero, then the
bbd2dd
-     * square of 'a' will max-1 words.
bbd2dd
-     */
bbd2dd
-    if (a->d[al - 1] == (a->d[al - 1] & BN_MASK2l))
bbd2dd
-        rr->top = max - 1;
bbd2dd
-    else
bbd2dd
-        rr->top = max;
bbd2dd
+    rr->top = max;
bbd2dd
+    bn_correct_top(rr);
bbd2dd
     if (r != rr && BN_copy(r, rr) == NULL)
bbd2dd
         goto err;
bbd2dd
 
bbd2dd
diff -up openssl-1.0.2k/crypto/bn_int.h.rohnp-fix openssl-1.0.2k/crypto/bn_int.h
bbd2dd
--- openssl-1.0.2k/crypto/bn_int.h.rohnp-fix	2018-08-14 10:57:21.597518822 +0200
bbd2dd
+++ openssl-1.0.2k/crypto/bn_int.h	2018-08-14 10:57:21.599518871 +0200
bbd2dd
@@ -0,0 +1,13 @@
bbd2dd
+/*
bbd2dd
+ * Some BIGNUM functions assume most significant limb to be non-zero, which
bbd2dd
+ * is customarily arranged by bn_correct_top. Output from below functions
bbd2dd
+ * is not processed with bn_correct_top, and for this reason it may not be
bbd2dd
+ * returned out of public API. It may only be passed internally into other
bbd2dd
+ * functions known to support non-minimal or zero-padded BIGNUMs.
bbd2dd
+ */
bbd2dd
+int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
bbd2dd
+                          BN_MONT_CTX *mont, BN_CTX *ctx);
bbd2dd
+int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
bbd2dd
+                         BN_CTX *ctx);
bbd2dd
+int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
bbd2dd
+                         const BIGNUM *m);
bbd2dd
diff -up openssl-1.0.2k/crypto/dsa/dsa_ossl.c.rohnp-fix openssl-1.0.2k/crypto/dsa/dsa_ossl.c
bbd2dd
--- openssl-1.0.2k/crypto/dsa/dsa_ossl.c.rohnp-fix	2018-06-20 17:44:02.153396702 +0200
bbd2dd
+++ openssl-1.0.2k/crypto/dsa/dsa_ossl.c	2018-06-20 17:44:02.577406741 +0200
bbd2dd
@@ -136,8 +136,7 @@ const DSA_METHOD *DSA_OpenSSL(void)
bbd2dd
 static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
bbd2dd
 {
bbd2dd
     BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
bbd2dd
-    BIGNUM m;
bbd2dd
-    BIGNUM xr;
bbd2dd
+    BIGNUM *m, *blind, *blindm, *tmp;
bbd2dd
     BN_CTX *ctx = NULL;
bbd2dd
     int reason = ERR_R_BN_LIB;
bbd2dd
     DSA_SIG *ret = NULL;
bbd2dd
@@ -156,9 +155,6 @@ static DSA_SIG *dsa_do_sign(const unsign
bbd2dd
     }
bbd2dd
 #endif
bbd2dd
 
bbd2dd
-    BN_init(&m);
bbd2dd
-    BN_init(&xr);
bbd2dd
-
bbd2dd
     if (!dsa->p || !dsa->q || !dsa->g) {
bbd2dd
         reason = DSA_R_MISSING_PARAMETERS;
bbd2dd
         goto err;
bbd2dd
@@ -170,6 +166,14 @@ static DSA_SIG *dsa_do_sign(const unsign
bbd2dd
     ctx = BN_CTX_new();
bbd2dd
     if (ctx == NULL)
bbd2dd
         goto err;
bbd2dd
+    BN_CTX_start(ctx);
bbd2dd
+    m = BN_CTX_get(ctx);
bbd2dd
+    blind = BN_CTX_get(ctx);
bbd2dd
+    blindm = BN_CTX_get(ctx);
bbd2dd
+    tmp = BN_CTX_get(ctx);
bbd2dd
+    if (tmp == NULL)
bbd2dd
+        goto err;
bbd2dd
+
bbd2dd
  redo:
bbd2dd
     if ((dsa->kinv == NULL) || (dsa->r == NULL)) {
bbd2dd
         if (!DSA_sign_setup(dsa, ctx, &kinv, &r))
bbd2dd
@@ -189,20 +193,52 @@ static DSA_SIG *dsa_do_sign(const unsign
bbd2dd
          * 4.2
bbd2dd
          */
bbd2dd
         dlen = BN_num_bytes(dsa->q);
bbd2dd
-    if (BN_bin2bn(dgst, dlen, &m) == NULL)
bbd2dd
+    if (BN_bin2bn(dgst, dlen, m) == NULL)
bbd2dd
         goto err;
bbd2dd
 
bbd2dd
-    /* Compute  s = inv(k) (m + xr) mod q */
bbd2dd
-    if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx))
bbd2dd
-        goto err;               /* s = xr */
bbd2dd
-    if (!BN_add(s, &xr, &m))
bbd2dd
-        goto err;               /* s = m + xr */
bbd2dd
-    if (BN_cmp(s, dsa->q) > 0)
bbd2dd
-        if (!BN_sub(s, s, dsa->q))
bbd2dd
+    /*
bbd2dd
+     * The normal signature calculation is:
bbd2dd
+     *
bbd2dd
+     *   s := k^-1 * (m + r * priv_key) mod q
bbd2dd
+     *
bbd2dd
+     * We will blind this to protect against side channel attacks
bbd2dd
+     *
bbd2dd
+     *   s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod q
bbd2dd
+     */
bbd2dd
+
bbd2dd
+    /* Generate a blinding value */
bbd2dd
+    do {
bbd2dd
+        if (!BN_rand(blind, BN_num_bits(dsa->q) - 1, -1, 0))
bbd2dd
             goto err;
bbd2dd
+    } while (BN_is_zero(blind));
bbd2dd
+    BN_set_flags(blind, BN_FLG_CONSTTIME);
bbd2dd
+    BN_set_flags(blindm, BN_FLG_CONSTTIME);
bbd2dd
+    BN_set_flags(tmp, BN_FLG_CONSTTIME);
bbd2dd
+
bbd2dd
+    /* tmp := blind * priv_key * r mod q */
bbd2dd
+    if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->q, ctx))
bbd2dd
+        goto err;
bbd2dd
+    if (!BN_mod_mul(tmp, tmp, r, dsa->q, ctx))
bbd2dd
+        goto err;
bbd2dd
+
bbd2dd
+    /* blindm := blind * m mod q */
bbd2dd
+    if (!BN_mod_mul(blindm, blind, m, dsa->q, ctx))
bbd2dd
+        goto err;
bbd2dd
+
bbd2dd
+    /* s : = (blind * priv_key * r) + (blind * m) mod q */
bbd2dd
+    if (!BN_mod_add_quick(s, tmp, blindm, dsa->q))
bbd2dd
+        goto err;
bbd2dd
+
bbd2dd
+    /* s := s * k^-1 mod q */
bbd2dd
     if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))
bbd2dd
         goto err;
bbd2dd
 
bbd2dd
+    /* s:= s * blind^-1 mod q */
bbd2dd
+    if (BN_mod_inverse(blind, blind, dsa->q, ctx) == NULL)
bbd2dd
+        goto err;
bbd2dd
+    if (!BN_mod_mul(s, s, blind, dsa->q, ctx))
bbd2dd
+        goto err;
bbd2dd
+
bbd2dd
     /*
bbd2dd
      * Redo if r or s is zero as required by FIPS 186-3: this is very
bbd2dd
      * unlikely.
bbd2dd
@@ -226,13 +262,12 @@ static DSA_SIG *dsa_do_sign(const unsign
bbd2dd
         BN_free(r);
bbd2dd
         BN_free(s);
bbd2dd
     }
bbd2dd
-    if (ctx != NULL)
bbd2dd
+    if (ctx != NULL) {
bbd2dd
+        BN_CTX_end(ctx);
bbd2dd
         BN_CTX_free(ctx);
bbd2dd
-    BN_clear_free(&m);
bbd2dd
-    BN_clear_free(&xr);
bbd2dd
-    if (kinv != NULL)           /* dsa->kinv is NULL now if we used it */
bbd2dd
-        BN_clear_free(kinv);
bbd2dd
-    return (ret);
bbd2dd
+    }
bbd2dd
+    BN_clear_free(kinv);
bbd2dd
+    return ret;
bbd2dd
 }
bbd2dd
 
bbd2dd
 static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
bbd2dd
diff -up openssl-1.0.2k/crypto/ecdsa/ecs_ossl.c.rohnp-fix openssl-1.0.2k/crypto/ecdsa/ecs_ossl.c
bbd2dd
--- openssl-1.0.2k/crypto/ecdsa/ecs_ossl.c.rohnp-fix	2018-06-20 17:44:02.205397934 +0200
bbd2dd
+++ openssl-1.0.2k/crypto/ecdsa/ecs_ossl.c	2018-08-14 11:18:02.062439755 +0200
bbd2dd
@@ -63,6 +63,7 @@
bbd2dd
 #ifdef OPENSSL_FIPS
bbd2dd
 # include <openssl/fips.h>
bbd2dd
 #endif
bbd2dd
+#include "bn_int.h"
bbd2dd
 
bbd2dd
 static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dlen,
bbd2dd
                                 const BIGNUM *, const BIGNUM *,
bbd2dd
@@ -98,6 +99,7 @@ static int ecdsa_sign_setup(EC_KEY *ecke
bbd2dd
     EC_POINT *tmp_point = NULL;
bbd2dd
     const EC_GROUP *group;
bbd2dd
     int ret = 0;
bbd2dd
+    int order_bits;
bbd2dd
 
bbd2dd
     if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) {
bbd2dd
         ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER);
bbd2dd
@@ -129,6 +131,13 @@ static int ecdsa_sign_setup(EC_KEY *ecke
bbd2dd
         goto err;
bbd2dd
     }
bbd2dd
 
bbd2dd
+    /* Preallocate space */
bbd2dd
+    order_bits = BN_num_bits(order);
bbd2dd
+    if (!BN_set_bit(k, order_bits)
bbd2dd
+        || !BN_set_bit(r, order_bits)
bbd2dd
+        || !BN_set_bit(X, order_bits))
bbd2dd
+        goto err;
bbd2dd
+
bbd2dd
     do {
bbd2dd
         /* get random k */
bbd2dd
         do
bbd2dd
@@ -142,13 +151,19 @@ static int ecdsa_sign_setup(EC_KEY *ecke
bbd2dd
         /*
bbd2dd
          * We do not want timing information to leak the length of k, so we
bbd2dd
          * compute G*k using an equivalent scalar of fixed bit-length.
bbd2dd
+         *
bbd2dd
+         * We unconditionally perform both of these additions to prevent a
bbd2dd
+         * small timing information leakage.  We then choose the sum that is
bbd2dd
+         * one bit longer than the order.  This guarantees the code
bbd2dd
+         * path used in the constant time implementations elsewhere.
bbd2dd
+         *
bbd2dd
+         * TODO: revisit the BN_copy aiming for a memory access agnostic
bbd2dd
+         * conditional copy.
bbd2dd
          */
bbd2dd
-
bbd2dd
-        if (!BN_add(k, k, order))
bbd2dd
+        if (!BN_add(r, k, order)
bbd2dd
+            || !BN_add(X, r, order)
bbd2dd
+            || !BN_copy(k, BN_num_bits(r) > order_bits ? r : X))
bbd2dd
             goto err;
bbd2dd
-        if (BN_num_bits(k) <= BN_num_bits(order))
bbd2dd
-            if (!BN_add(k, k, order))
bbd2dd
-                goto err;
bbd2dd
 
bbd2dd
         /* compute r the x-coordinate of generator * k */
bbd2dd
         if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
bbd2dd
@@ -240,13 +255,14 @@ static ECDSA_SIG *ecdsa_do_sign(const un
bbd2dd
                                 EC_KEY *eckey)
bbd2dd
 {
bbd2dd
     int ok = 0, i;
bbd2dd
-    BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL;
bbd2dd
+    BIGNUM *kinv = NULL, *s, *m = NULL, *order = NULL;
bbd2dd
     const BIGNUM *ckinv;
bbd2dd
     BN_CTX *ctx = NULL;
bbd2dd
     const EC_GROUP *group;
bbd2dd
     ECDSA_SIG *ret;
bbd2dd
     ECDSA_DATA *ecdsa;
bbd2dd
     const BIGNUM *priv_key;
bbd2dd
+    BN_MONT_CTX *mont_data;
bbd2dd
 
bbd2dd
 #ifdef OPENSSL_FIPS
bbd2dd
     if (FIPS_selftest_failed()) {
bbd2dd
@@ -272,7 +288,7 @@ static ECDSA_SIG *ecdsa_do_sign(const un
bbd2dd
     s = ret->s;
bbd2dd
 
bbd2dd
     if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
bbd2dd
-        (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
bbd2dd
+        (m = BN_new()) == NULL) {
bbd2dd
         ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
bbd2dd
         goto err;
bbd2dd
     }
bbd2dd
@@ -281,6 +297,8 @@ static ECDSA_SIG *ecdsa_do_sign(const un
bbd2dd
         ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
bbd2dd
         goto err;
bbd2dd
     }
bbd2dd
+    mont_data = EC_GROUP_get_mont_data(group);
bbd2dd
+
bbd2dd
     i = BN_num_bits(order);
bbd2dd
     /*
bbd2dd
      * Need to truncate digest if it is too long: first truncate whole bytes.
bbd2dd
@@ -311,21 +329,33 @@ static ECDSA_SIG *ecdsa_do_sign(const un
bbd2dd
             }
bbd2dd
         }
bbd2dd
 
bbd2dd
-        if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
bbd2dd
-            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
bbd2dd
+        /*
bbd2dd
+         * With only one multiplicant being in Montgomery domain
bbd2dd
+         * multiplication yields real result without post-conversion.
bbd2dd
+         * Also note that all operations but last are performed with
bbd2dd
+         * zero-padded vectors. Last operation, BN_mod_mul_montgomery
bbd2dd
+         * below, returns user-visible value with removed zero padding.
bbd2dd
+         */
bbd2dd
+        if (!bn_to_mont_fixed_top(s, ret->r, mont_data, ctx)
bbd2dd
+            || !bn_mul_mont_fixed_top(s, s, priv_key, mont_data, ctx)) {
bbd2dd
             goto err;
bbd2dd
         }
bbd2dd
-        if (!BN_mod_add_quick(s, tmp, m, order)) {
bbd2dd
+        if (!bn_mod_add_fixed_top(s, s, m, order)) {
bbd2dd
             ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
bbd2dd
             goto err;
bbd2dd
         }
bbd2dd
-        if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
bbd2dd
+        /*
bbd2dd
+         * |s| can still be larger than modulus, because |m| can be. In
bbd2dd
+         * such case we count on Montgomery reduction to tie it up.
bbd2dd
+         */
bbd2dd
+        if (!bn_to_mont_fixed_top(s, s, mont_data, ctx)
bbd2dd
+            || !BN_mod_mul_montgomery(s, s, ckinv, mont_data, ctx)) {
bbd2dd
             ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
bbd2dd
             goto err;
bbd2dd
         }
bbd2dd
         if (BN_is_zero(s)) {
bbd2dd
             /*
bbd2dd
-             * if kinv and r have been supplied by the caller don't to
bbd2dd
+             * if kinv and r have been supplied by the caller don't
bbd2dd
              * generate new kinv and r values
bbd2dd
              */
bbd2dd
             if (in_kinv != NULL && in_r != NULL) {
bbd2dd
@@ -349,8 +379,6 @@ static ECDSA_SIG *ecdsa_do_sign(const un
bbd2dd
         BN_CTX_free(ctx);
bbd2dd
     if (m)
bbd2dd
         BN_clear_free(m);
bbd2dd
-    if (tmp)
bbd2dd
-        BN_clear_free(tmp);
bbd2dd
     if (order)
bbd2dd
         BN_free(order);
bbd2dd
     if (kinv)
bbd2dd
diff -up openssl-1.0.2k/crypto/Makefile.rohnp-fix openssl-1.0.2k/crypto/Makefile
bbd2dd
--- openssl-1.0.2k/crypto/Makefile.rohnp-fix	2018-06-20 17:44:02.467404137 +0200
bbd2dd
+++ openssl-1.0.2k/crypto/Makefile	2018-08-14 10:57:21.595518774 +0200
bbd2dd
@@ -45,7 +45,7 @@ SRC= $(LIBSRC)
bbd2dd
 EXHEADER= crypto.h opensslv.h opensslconf.h ebcdic.h symhacks.h \
bbd2dd
 	ossl_typ.h
bbd2dd
 HEADER=	cryptlib.h buildinf.h md32_common.h o_time.h o_str.h o_dir.h \
bbd2dd
-	constant_time_locl.h $(EXHEADER)
bbd2dd
+	constant_time_locl.h bn_int.h $(EXHEADER)
bbd2dd
 
bbd2dd
 ALL=    $(GENERAL) $(SRC) $(HEADER)
bbd2dd