[OpenWrt-Devel,RFC,18.06-alt,1/1] wolfssl: fixes for CVE-2018-16870 & CVE-2019-13628
diff mbox series

Message ID 20190805174541.20539-1-cotequeiroz@gmail.com
State Accepted
Delegated to: Hauke Mehrtens
Headers show
Series
  • [OpenWrt-Devel,RFC,18.06-alt,1/1] wolfssl: fixes for CVE-2018-16870 & CVE-2019-13628
Related show

Commit Message

Eneas U de Queiroz Aug. 5, 2019, 5:45 p.m. UTC
CVE-2018-16870: medium-severity, new variant of the Bleichenbacher
attack to perform downgrade attacks against TLS, which may lead to
leakage of sensible data. Backported from 3.15.7.

CVE-2019-13628 (currently assigned-only): potential leak of nonce sizes
when performing ECDSA signing operations. The leak is considered to be
difficult to exploit but it could potentially be used maliciously to
perform a lattice based timing attack. Backported from 4.1.0.

Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
---
This is an alternative to updating 18.06 to 4.1.0, just backporting the
patches.  This has been tested on x86_64 with the package's testsuite,
in addition to regular run-testing on WRT3200ACM, using uhttpd,
uclient-fetch, and curl.

CVE-2019-13628's patch applied cleanly, but the other one needed many
adjustments.

 package/libs/wolfssl/Makefile                 |   5 +-
 ...nstant-time-when-Block-Type-2-messag.patch | 584 ++++++++++++++++++
 .../020-Improve-nonce-use-in-ECC-mulmod.patch | 100 +++
 3 files changed, 687 insertions(+), 2 deletions(-)
 create mode 100644 package/libs/wolfssl/patches/010-Make-RsaUnPad-constant-time-when-Block-Type-2-messag.patch
 create mode 100644 package/libs/wolfssl/patches/020-Improve-nonce-use-in-ECC-mulmod.patch

Patch
diff mbox series

diff --git a/package/libs/wolfssl/Makefile b/package/libs/wolfssl/Makefile
index a01a8949aa..6f29cd668d 100644
--- a/package/libs/wolfssl/Makefile
+++ b/package/libs/wolfssl/Makefile
@@ -9,7 +9,7 @@  include $(TOPDIR)/rules.mk
 
 PKG_NAME:=wolfssl
 PKG_VERSION:=3.15.3-stable
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).zip
 # PKG_SOURCE_URL:=https://www.wolfssl.com/
@@ -21,7 +21,8 @@  PKG_INSTALL:=1
 PKG_USE_MIPS16:=0
 PKG_BUILD_PARALLEL:=1
 PKG_LICENSE:=GPL-2.0+
-PKG_CPE_ID:=cpe:/a:yassl:cyassl
+PKG_MAINTAINER:=Eneas U de Queiroz <cotequeiroz@gmail.com>
+PKG_CPE_ID:=cpe:/a:wolfssl:wolfssl
 
 PKG_CONFIG_DEPENDS:=\
 	CONFIG_WOLFSSL_HAS_AES_CCM CONFIG_WOLFSSL_HAS_AES_GCM \
diff --git a/package/libs/wolfssl/patches/010-Make-RsaUnPad-constant-time-when-Block-Type-2-messag.patch b/package/libs/wolfssl/patches/010-Make-RsaUnPad-constant-time-when-Block-Type-2-messag.patch
new file mode 100644
index 0000000000..26ceaef4c5
--- /dev/null
+++ b/package/libs/wolfssl/patches/010-Make-RsaUnPad-constant-time-when-Block-Type-2-messag.patch
@@ -0,0 +1,584 @@ 
+From 278d54d95de9fa80b4ac9f6dd0f900841114ca8c Mon Sep 17 00:00:00 2001
+From: Sean Parkinson <sean@wolfssl.com>
+Date: Mon, 27 Aug 2018 10:16:40 +1000
+Subject: [PATCH] Make RsaUnPad constant time when Block Type 2 message
+
+(cherry picked from commit ab03f9291b040269ae21d33b9f01529ed8311728)
+[cherry-pick changes]
+Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
+
+diff --git a/src/internal.c b/src/internal.c
+index dfb3a2fe9..4b2477e7a 100644
+--- a/src/internal.c
++++ b/src/internal.c
+@@ -24766,26 +24766,22 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                          * indistinguishable from correctly formatted RSA blocks
+                          */
+ 
+-                        ret = args->lastErr;
+                         args->lastErr = 0; /* reset */
+ 
+                         /* build PreMasterSecret */
+                         ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
+                         ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
+-                        if (ret == 0 && args->sigSz == SECRET_LEN &&
+-                                                         args->output != NULL) {
++                        if (args->output != NULL) {
+                             XMEMCPY(&ssl->arrays->preMasterSecret[VERSION_SZ],
+-                                &args->output[VERSION_SZ],
+-                                SECRET_LEN - VERSION_SZ);
+-                        }
+-                        else {
+-                            /* preMasterSecret has RNG and version set */
+-                            /* return proper length and ignore error */
+-                            /* error will be caught as decryption error */
+-                            args->sigSz = SECRET_LEN;
+-                            ret = 0;
++                                    &args->output[VERSION_SZ],
++                                    SECRET_LEN - VERSION_SZ);
+                         }
+-
++                        /* preMasterSecret has RNG and version set
++                         * return proper length and ignore error
++                         * error will be caught as decryption error
++                         */
++                        args->sigSz = SECRET_LEN;
++                        ret = 0;
+                         break;
+                     } /* rsa_kea */
+                 #endif /* !NO_RSA */
+diff --git a/src/tls.c b/src/tls.c
+index 9f0c49497..cc985410a 100644
+--- a/src/tls.c
++++ b/src/tls.c
+@@ -1136,12 +1136,12 @@ static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in,
+             else if (k < maxLen)
+                 b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ];
+ 
+-            b = ctMaskSel(atEoc, b, 0x80);
++            b = ctMaskSel(atEoc, 0x80, b);
+             b &= ~pastEoc;
+             b &= ~isOutBlock | isEocBlock;
+ 
+             if (j >= blockSz - 8) {
+-                b = ctMaskSel(isOutBlock, b, lenBytes[j - (blockSz - 8)]);
++                b = ctMaskSel(isOutBlock, lenBytes[j - (blockSz - 8)], b);
+             }
+ 
+             hashBlock[j] = b;
+diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c
+index 84290c64f..2e1487061 100644
+--- a/wolfcrypt/src/integer.c
++++ b/wolfcrypt/src/integer.c
+@@ -321,6 +321,17 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+   return res;
+ }
+ 
++int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c)
++{
++    int i, len;
++
++    len = mp_unsigned_bin_size(a);
++
++    /* pad front w/ zeros to match length */
++    for (i = 0; i < c - len; i++)
++        b[i] = 0x00;
++    return mp_to_unsigned_bin(a, b + i);
++}
+ 
+ /* creates "a" then copies b into it */
+ int mp_init_copy (mp_int * a, mp_int * b)
+diff --git a/wolfcrypt/src/misc.c b/wolfcrypt/src/misc.c
+index f5017e356..1460d5164 100644
+--- a/wolfcrypt/src/misc.c
++++ b/wolfcrypt/src/misc.c
+@@ -341,10 +341,22 @@ STATIC INLINE byte ctMaskEq(int a, int b)
+     return 0 - (a == b);
+ }
+ 
+-/* Constant time - select b when mask is set and a otherwise. */
++/* Constant time - mask set when a != b. */
++STATIC INLINE byte ctMaskNotEq(int a, int b)
++{
++    return 0 - (a != b);
++}
++
++/* Constant time - select a when mask is set and b otherwise. */
+ STATIC INLINE byte ctMaskSel(byte m, byte a, byte b)
+ {
+-    return (a & ~m) | (b & m);
++    return (b & ~m) | (a & m);
++}
++
++/* Constant time - select integer a when mask is set and integer b otherwise. */
++STATIC INLINE int ctMaskSelInt(byte m, int a, int b)
++{
++    return (b & (~(int)(char)m)) | (a & ((int)(char)m));
+ }
+ 
+ /* Constant time - bit set when a <= b. */
+diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c
+index a4a7adcb0..af0413f1c 100644
+--- a/wolfcrypt/src/rsa.c
++++ b/wolfcrypt/src/rsa.c
+@@ -989,10 +989,8 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen,
+     ret += pkcsBlock[idx++] ^ 0x01; /* separator value is 0x01 */
+     ret += pkcsBlock[0]     ^ 0x00; /* Y, the first value, should be 0 */
+ 
+-    if (ret != 0) {
+-        WOLFSSL_MSG("RsaUnPad_OAEP: Padding Error");
+-        return BAD_PADDING_E;
+-    }
++    /* Return 0 data length on error. */
++    idx = ctMaskSelInt(ctMaskEq(ret, 0), idx, pkcsBlockLen);
+ 
+     /* adjust pointer to correct location in array and return size of M */
+     *output = (byte*)(pkcsBlock + idx);
+@@ -1078,48 +1076,60 @@ static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen,
+ /* UnPad plaintext, set start to *output, return length of plaintext,
+  * < 0 on error */
+ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
+-                                               byte **output, byte padValue)
++                    byte **output, byte padValue)
+ {
+-    word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0;
+-    word32 invalid = 0;
+-    word32 i = 1;
+-    word32 outputLen;
++    int    ret;
++    word32 i;
++    byte   invalid = 0;
+ 
+     if (output == NULL || pkcsBlockLen == 0) {
+         return BAD_FUNC_ARG;
+     }
+ 
+-    if (pkcsBlock[0] != 0x0) { /* skip past zero */
+-        invalid = 1;
+-    }
+-    pkcsBlock++; pkcsBlockLen--;
++    if (padValue == RSA_BLOCK_TYPE_1) {
++        /* First byte must be 0x00 and Second byte, block type, 0x01 */
++        if (pkcsBlock[0] != 0 || pkcsBlock[1] != RSA_BLOCK_TYPE_1) {
++            WOLFSSL_MSG("RsaUnPad error, invalid formatting");
++            return RSA_PAD_E;
++        }
+ 
+-    /* Require block type padValue */
+-    invalid = (pkcsBlock[0] != padValue) || invalid;
++        /* check the padding until we find the separator */
++        for (i = 2; i < pkcsBlockLen && pkcsBlock[i++] == 0xFF; ) { }
+ 
+-    /* verify the padding until we find the separator */
+-    if (padValue == RSA_BLOCK_TYPE_1) {
+-        while (i<pkcsBlockLen && pkcsBlock[i++] == 0xFF) {/* Null body */}
+-    }
+-    else {
+-        while (i<pkcsBlockLen && pkcsBlock[i++]) {/* Null body */}
+-    }
++        /* Minimum of 11 bytes of pre-message data and must have separator. */
++        if (i < RSA_MIN_PAD_SZ || pkcsBlock[i-1] != 0) {
++            WOLFSSL_MSG("RsaUnPad error, bad formatting");
++            return RSA_PAD_E;
++        }
+ 
+-    if (!(i==pkcsBlockLen || pkcsBlock[i-1]==0)) {
+-        WOLFSSL_MSG("RsaUnPad error, bad formatting");
+-        return RSA_PAD_E;
++        *output = (byte *)(pkcsBlock + i);
++        ret = pkcsBlockLen - i;
+     }
++    else {
++        word32 j;
++        byte   pastSep = 0;
++
++        /* Decrypted with private key - unpad must be constant time. */
++        for (i = 0, j = 2; j < pkcsBlockLen; j++) {
++           /* Update i if not passed the separator and at separator. */
++           i |= (~pastSep) & ctMaskEq(pkcsBlock[j], 0x00) & (j + 1);
++           pastSep |= ctMaskEq(pkcsBlock[j], 0x00);
++        }
+ 
+-    outputLen = pkcsBlockLen - i;
+-    invalid = (outputLen > maxOutputLen) || invalid;
++        /* Minimum of 11 bytes of pre-message data - including leading 0x00. */
++        invalid |= ctMaskLT(i, RSA_MIN_PAD_SZ);
++        /* Must have seen separator. */
++        invalid |= ~pastSep;
++        /* First byte must be 0x00. */
++        invalid |= ctMaskNotEq(pkcsBlock[0], 0x00);
++        /* Check against expected block type: padValue */
++        invalid |= ctMaskNotEq(pkcsBlock[1], padValue);
+ 
+-    if (invalid) {
+-        WOLFSSL_MSG("RsaUnPad error, invalid formatting");
+-        return RSA_PAD_E;
++        *output = (byte *)(pkcsBlock + i);
++        ret = ((int)~invalid) & (pkcsBlockLen - i);
+     }
+ 
+-    *output = (byte *)(pkcsBlock + i);
+-    return outputLen;
++    return ret;
+ }
+ 
+ /* helper function to direct unpadding
+@@ -1249,7 +1259,7 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out,
+     mp_int rnd, rndi;
+ #endif
+     int    ret = 0;
+-    word32 keyLen, len;
++    word32 keyLen;
+ #endif
+ 
+ #ifdef WOLFSSL_HAVE_SP_RSA
+@@ -1308,6 +1318,7 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out,
+     }
+ #endif
+ 
++#ifndef TEST_UNPAD_CONSTANT_TIME
+     if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
+         ERROR_OUT(MP_READ_E);
+ 
+@@ -1418,21 +1429,18 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out,
+         ERROR_OUT(RSA_BUFFER_E);
+     }
+ 
+-    len = mp_unsigned_bin_size(&tmp);
+-
+-    /* pad front w/ zeros to match key length */
+-    while (len < keyLen) {
+-        *out++ = 0x00;
+-        len++;
+-    }
+-
+     *outLen = keyLen;
+-
+-    /* convert */
+-    if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
++    if (mp_to_unsigned_bin_len(&tmp, out, keyLen) != MP_OKAY)
+         ERROR_OUT(MP_TO_E);
+ 
+ done:
++#else
++    (void)type;
++    (void)key;
++    (void)keyLen;
++    XMEMCPY(out, in, inLen);
++    *outLen = inLen;
++#endif
+     mp_clear(&tmp);
+ #ifdef WC_RSA_BLINDING
+     if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
+@@ -1633,6 +1641,7 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
+     }
+ #endif
+ 
++#ifndef TEST_UNPAD_CONSTANT_TIME
+ #ifndef NO_RSA_BOUNDS_CHECK
+     if (type == RSA_PRIVATE_DECRYPT &&
+         key->state == RSA_STATE_DECRYPT_EXPTMOD) {
+@@ -1667,6 +1676,7 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
+             return ret;
+     }
+ #endif /* NO_RSA_BOUNDS_CHECK */
++#endif
+ 
+ #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA)
+     if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
+@@ -1880,7 +1890,8 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out,
+ 
+         /* if not doing this inline then allocate a buffer for it */
+         if (outPtr == NULL) {
+-            key->data = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_WOLF_BIGINT);
++            key->data = (byte*)XMALLOC(inLen, key->heap,
++                                                      DYNAMIC_TYPE_WOLF_BIGINT);
+             key->dataIsAlloc = 1;
+             if (key->data == NULL) {
+                 ret = MEMORY_E;
+@@ -1909,20 +1920,29 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out,
+         ret = wc_RsaUnPad_ex(key->data, key->dataLen, &pad, pad_value, pad_type,
+                              hash, mgf, label, labelSz, saltLen,
+                              mp_count_bits(&key->n), key->heap);
+-        if (ret > 0 && ret <= (int)outLen && pad != NULL) {
++        if (rsa_type == RSA_PUBLIC_DECRYPT && ret > (int)outLen)
++            ret = RSA_BUFFER_E;
++        else if (ret >= 0 && pad != NULL) {
++            char c;
++
+             /* only copy output if not inline */
+             if (outPtr == NULL) {
+-                XMEMCPY(out, pad, ret);
++                word32 i, j;
++                int start = (int)((size_t)pad - (size_t)key->data);
++
++                for (i = 0, j = 0; j < key->dataLen; j++) {
++                    out[i] = key->data[j];
++                    c  = ctMaskGTE(j, start);
++                    c &= ctMaskLT(i, outLen);
++                    /* 0 - no add, -1 add */
++                    i += -c;
++                }
+             }
+-            else {
++            else
+                 *outPtr = pad;
+-            }
+-        }
+-        else if (ret >= 0) {
+-            ret = RSA_BUFFER_E;
+-        }
+-        if (ret < 0) {
+-            break;
++
++            ret = ctMaskSelInt(ctMaskLTE(ret, outLen), ret, RSA_BUFFER_E);
++            ret = ctMaskSelInt(ctMaskNotEq(ret, 0), ret, RSA_BUFFER_E);
+         }
+ 
+         key->state = RSA_STATE_DECRYPT_RES;
+@@ -1934,12 +1954,14 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out,
+             defined(HAVE_CAVIUM)
+         if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
+                                                    pad_type != WC_RSA_PSS_PAD) {
+-            /* convert result */
+-            byte* dataLen = (byte*)&key->dataLen;
+-            ret = (dataLen[0] << 8) | (dataLen[1]);
++            if (ret > 0) {
++                /* convert result */
++                byte* dataLen = (byte*)&key->dataLen;
++                ret = (dataLen[0] << 8) | (dataLen[1]);
+ 
+-            if (outPtr)
+-                *outPtr = in;
++                if (outPtr)
++                    *outPtr = in;
++            }
+         }
+     #endif
+         break;
+diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c
+index 74a37b6be..4ff618bca 100644
+--- a/wolfcrypt/src/sp_int.c
++++ b/wolfcrypt/src/sp_int.c
+@@ -286,7 +286,8 @@ int sp_leading_bit(sp_int* a)
+  * The array must be large enough for encoded number - use mp_unsigned_bin_size
+  * to calculate the number of bytes required.
+  *
+- * a  SP integer.
++ * a    SP integer.
++ * out  Array to put encoding into.
+  * returns MP_OKAY always.
+  */
+ int sp_to_unsigned_bin(sp_int* a, byte* out)
+@@ -305,6 +306,31 @@ int sp_to_unsigned_bin(sp_int* a, byte* out)
+     return MP_OKAY;
+ }
+ 
++/* Convert the big number to an array of bytes in big-endian format.
++ * 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 make number the size of the array.
++ *
++ * a      SP integer.
++ * out    Array to put encoding into.
++ * outSz  Size of the array.
++ * returns MP_OKAY always.
++ */
++int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz)
++{
++    int i, j, b;
++
++    j = outSz - 1;
++    for (i=0; j>=0; i++) {
++        for (b = 0; b < SP_WORD_SIZE; b += 8) {
++            out[j--] = a->dp[i] >> b;
++            if (j < 0)
++                break;
++        }
++    }
++
++    return MP_OKAY;
++}
+ /* Ensure the data in the big number is zeroed.
+  *
+  * a  SP integer.
+diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c
+index 664a74b54..6ebeeef8d 100644
+--- a/wolfcrypt/src/tfm.c
++++ b/wolfcrypt/src/tfm.c
+@@ -1964,6 +1964,48 @@ void fp_to_unsigned_bin(fp_int *a, unsigned char *b)
+   fp_reverse (b, x);
+ }
+ 
++int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c)
++{
++#if DIGIT_BIT == 64 || DIGIT_BIT == 32
++  int i, j, x;
++
++  for (x=c-1,j=0,i=0; x >= 0; x--) {
++     b[x] = (unsigned char)(a->dp[i] >> j);
++     j += 8;
++     i += j == DIGIT_BIT;
++     j &= DIGIT_BIT - 1;
++  }
++
++  return FP_OKAY;
++#else
++  int     x;
++#ifndef WOLFSSL_SMALL_STACK
++   fp_int t[1];
++#else
++   fp_int *t;
++#endif
++
++#ifdef WOLFSSL_SMALL_STACK
++   t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER);
++   if (t == NULL)
++       return FP_MEM;
++#endif
++
++  fp_init_copy(t, a);
++
++  for (x = 0; x < c; x++) {
++      b[x] = (unsigned char) (t->dp[0] & 255);
++      fp_div_2d (t, 8, t, NULL);
++  }
++  fp_reverse (b, x);
++
++#ifdef WOLFSSL_SMALL_STACK
++  XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
++#endif
++  return FP_OKAY;
++#endif
++}
++
+ int fp_unsigned_bin_size(fp_int *a)
+ {
+   int     size = fp_count_bits (a);
+@@ -2435,6 +2477,10 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+   return MP_OKAY;
+ }
+ 
++int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c)
++{
++  return fp_to_unsigned_bin_len(a, b, c);
++}
+ /* reads a unsigned char array, assumes the msb is stored first [big endian] */
+ int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+ {
+diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h
+index 14767b9ab..dd34d1342 100644
+--- a/wolfssl/wolfcrypt/integer.h
++++ b/wolfssl/wolfcrypt/integer.h
+@@ -277,6 +277,7 @@ MP_API int  mp_unsigned_bin_size(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);
++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);
+ /* end functions needed by Rsa */
+ 
+diff --git a/wolfssl/wolfcrypt/misc.h b/wolfssl/wolfcrypt/misc.h
+index 7cf4cff2a..cde3d99b2 100644
+--- a/wolfssl/wolfcrypt/misc.h
++++ b/wolfssl/wolfcrypt/misc.h
+@@ -97,7 +97,9 @@ WOLFSSL_LOCAL byte ctMaskGTE(int a, int b);
+ WOLFSSL_LOCAL byte ctMaskLT(int a, int b);
+ WOLFSSL_LOCAL byte ctMaskLTE(int a, int b);
+ WOLFSSL_LOCAL byte ctMaskEq(int a, int b);
++WOLFSSL_LOCAL byte ctMaskNotEq(int a, int b);
+ WOLFSSL_LOCAL byte ctMaskSel(byte m, byte a, byte b);
++WOLFSSL_LOCAL int  ctMaskSelInt(byte m, int a, int b);
+ WOLFSSL_LOCAL byte ctSetLTE(int a, int b);
+ 
+ #endif /* NO_INLINE */
+diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h
+index 51b9e2fb8..a421c4359 100644
+--- a/wolfssl/wolfcrypt/sp_int.h
++++ b/wolfssl/wolfcrypt/sp_int.h
+@@ -119,7 +119,8 @@ MP_API int sp_read_radix(sp_int* a, const char* in, int radix);
+ MP_API int sp_cmp(sp_int* a, sp_int* b);
+ MP_API int sp_count_bits(sp_int* a);
+ MP_API int sp_leading_bit(sp_int* a);
+-MP_API int sp_to_unsigned_bin(sp_int* a, byte* in);
++MP_API int sp_to_unsigned_bin(sp_int* a, byte* out);
++MP_API int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz);
+ MP_API void sp_forcezero(sp_int* a);
+ MP_API int sp_copy(sp_int* a, sp_int* b);
+ MP_API int sp_set(sp_int* a, sp_int_digit d);
+@@ -156,30 +157,31 @@ typedef sp_digit mp_digit;
+ 
+ #define mp_free(a)
+ 
+-#define mp_init                 sp_init
+-#define mp_init_multi           sp_init_multi
+-#define mp_clear                sp_clear
+-#define mp_read_unsigned_bin    sp_read_unsigned_bin
+-#define mp_unsigned_bin_size    sp_unsigned_bin_size
+-#define mp_read_radix           sp_read_radix
+-#define mp_cmp                  sp_cmp
+-#define mp_count_bits           sp_count_bits
+-#define mp_leading_bit          sp_leading_bit
+-#define mp_to_unsigned_bin      sp_to_unsigned_bin
+-#define mp_forcezero            sp_forcezero
+-#define mp_copy                 sp_copy
+-#define mp_set                  sp_set
+-#define mp_iszero               sp_iszero
+-#define mp_clamp                sp_clamp
+-#define mp_grow                 sp_grow
+-#define mp_sub_d                sp_sub_d
+-#define mp_cmp_d                sp_cmp_d
+-#define mp_mod                  sp_mod
+-#define mp_zero                 sp_zero
+-#define mp_add_d                sp_add_d
+-#define mp_lshd                 sp_lshd
+-#define mp_add                  sp_add
+-#define mp_isodd                sp_isodd
++#define mp_init                     sp_init
++#define mp_init_multi               sp_init_multi
++#define mp_clear                    sp_clear
++#define mp_read_unsigned_bin        sp_read_unsigned_bin
++#define mp_unsigned_bin_size        sp_unsigned_bin_size
++#define mp_read_radix               sp_read_radix
++#define mp_cmp                      sp_cmp
++#define mp_count_bits               sp_count_bits
++#define mp_leading_bit              sp_leading_bit
++#define mp_to_unsigned_bin          sp_to_unsigned_bin
++#define mp_to_unsigned_bin_len      sp_to_unsigned_bin_len
++#define mp_forcezero                sp_forcezero
++#define mp_copy                     sp_copy
++#define mp_set                      sp_set
++#define mp_iszero                   sp_iszero
++#define mp_clamp                    sp_clamp
++#define mp_grow                     sp_grow
++#define mp_sub_d                    sp_sub_d
++#define mp_cmp_d                    sp_cmp_d
++#define mp_mod                      sp_mod
++#define mp_zero                     sp_zero
++#define mp_add_d                    sp_add_d
++#define mp_lshd                     sp_lshd
++#define mp_add                      sp_add
++#define mp_isodd                    sp_isodd
+ 
+ #define MP_INT_DEFINED
+ 
+diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h
+index 43217f584..f5f249128 100644
+--- a/wolfssl/wolfcrypt/tfm.h
++++ b/wolfssl/wolfcrypt/tfm.h
+@@ -563,6 +563,7 @@ int fp_leading_bit(fp_int *a);
+ int fp_unsigned_bin_size(fp_int *a);
+ void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c);
+ void fp_to_unsigned_bin(fp_int *a, unsigned char *b);
++int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c);
+ int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b);
+ 
+ /*int fp_signed_bin_size(fp_int *a);*/
+@@ -686,6 +687,7 @@ MP_API int  mp_unsigned_bin_size(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);
++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);
+ MP_API int  mp_copy(fp_int* a, fp_int* b);
diff --git a/package/libs/wolfssl/patches/020-Improve-nonce-use-in-ECC-mulmod.patch b/package/libs/wolfssl/patches/020-Improve-nonce-use-in-ECC-mulmod.patch
new file mode 100644
index 0000000000..025d19cf1d
--- /dev/null
+++ b/package/libs/wolfssl/patches/020-Improve-nonce-use-in-ECC-mulmod.patch
@@ -0,0 +1,100 @@ 
+From ba4d612892bf6e3aae9cca7edce2a6d6b43e3e22 Mon Sep 17 00:00:00 2001
+From: Sean Parkinson <sean@wolfssl.com>
+Date: Wed, 17 Jul 2019 08:26:02 +1000
+Subject: [PATCH] Improve nonce use in ECC mulmod
+
+(cherry picked from commit 483f6a5acd9808b405306661c121aa6407464dc2)
+
+diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c
+index 8daa52e63..48e21396e 100644
+--- a/wolfcrypt/src/ecc.c
++++ b/wolfcrypt/src/ecc.c
+@@ -2039,7 +2039,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
+    #define M_POINTS 8
+    int           first = 1, bitbuf = 0, bitcpy = 0, j;
+ #else
+-   #define M_POINTS 3
++   #define M_POINTS 4
+ #endif
+ 
+    ecc_point     *tG, *M[M_POINTS];
+@@ -2253,7 +2253,9 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
+    mode   = 0;
+    bitcnt = 1;
+    buf    = 0;
+-   digidx = get_digit_count(k) - 1;
++   digidx = get_digit_count(modulus) - 1;
++   /* The order MAY be 1 bit longer than the modulus. */
++   digidx += (modulus->dp[digidx] >> (DIGIT_BIT-1));
+ 
+    /* perform ops */
+    if (err == MP_OKAY) {
+@@ -2272,25 +2274,53 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
+            i = (buf >> (DIGIT_BIT - 1)) & 1;
+            buf <<= 1;
+ 
+-           if (mode == 0 && i == 0) {
++           if (mode == 0) {
++               mode = i;
+                /* timing resistant - dummy operations */
+                if (err == MP_OKAY)
+-                   err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus,
+-                                                  mp);
+-               if (err == MP_OKAY)
+-                   err = ecc_projective_dbl_point(M[1], M[2], a, modulus, mp);
+-               if (err == MP_OKAY)
+-                   continue;
+-           }
+-
+-           if (mode == 0 && i == 1) {
+-               mode = 1;
+-               /* timing resistant - dummy operations */
+-               if (err == MP_OKAY)
+-                   err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus,
++                   err = ecc_projective_add_point(M[1], M[2], M[2], a, modulus,
+                                                   mp);
++#ifdef WC_NO_CACHE_RESISTANT
+                if (err == MP_OKAY)
+-                   err = ecc_projective_dbl_point(M[1], M[2], a, modulus, mp);
++                   err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp);
++#else
++               /* instead of using M[i] for double, which leaks key bit to cache
++                * monitor, use M[2] as temp, make sure address calc is constant,
++                * keep M[0] and M[1] in cache */
++              if (err == MP_OKAY)
++                  err = mp_copy((mp_int*)
++                             ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) +
++                               ((wolfssl_word)M[1]->x & wc_off_on_addr[i])),
++                             M[2]->x);
++              if (err == MP_OKAY)
++                  err = mp_copy((mp_int*)
++                             ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) +
++                               ((wolfssl_word)M[1]->y & wc_off_on_addr[i])),
++                             M[2]->y);
++              if (err == MP_OKAY)
++                  err = mp_copy((mp_int*)
++                             ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) +
++                               ((wolfssl_word)M[1]->z & wc_off_on_addr[i])),
++                             M[2]->z);
++              if (err == MP_OKAY)
++                  err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp);
++              /* copy M[2] back to M[i] */
++              if (err == MP_OKAY)
++                  err = mp_copy(M[2]->x,
++                             (mp_int*)
++                             ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) +
++                               ((wolfssl_word)M[1]->x & wc_off_on_addr[i])) );
++              if (err == MP_OKAY)
++                  err = mp_copy(M[2]->y,
++                             (mp_int*)
++                             ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) +
++                               ((wolfssl_word)M[1]->y & wc_off_on_addr[i])) );
++              if (err == MP_OKAY)
++                  err = mp_copy(M[2]->z,
++                             (mp_int*)
++                             ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) +
++                               ((wolfssl_word)M[1]->z & wc_off_on_addr[i])) );
++#endif
+                if (err == MP_OKAY)
+                    continue;
+            }