summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gnu/local.mk3
-rw-r--r--gnu/packages/nettle.scm11
-rw-r--r--gnu/packages/patches/nettle-3.5-CVE-2021-3580-pt1.patch276
-rw-r--r--gnu/packages/patches/nettle-3.5-CVE-2021-3580-pt2.patch163
-rw-r--r--gnu/packages/patches/nettle-3.5-check-_pkcs1_sec_decrypt-msg-len.patch78
5 files changed, 530 insertions, 1 deletions
diff --git a/gnu/local.mk b/gnu/local.mk
index fdbf2272ed..f1a6d69bf6 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1462,6 +1462,9 @@ dist_patch_DATA =						\
   %D%/packages/patches/netsurf-system-utf8proc.patch		\
   %D%/packages/patches/netsurf-y2038-tests.patch		\
   %D%/packages/patches/netsurf-longer-test-timeout.patch	\
+  %D%/packages/patches/nettle-3.5-check-_pkcs1_sec_decrypt-msg-len.patch \
+  %D%/packages/patches/nettle-3.5-CVE-2021-3580-pt1.patch	\
+  %D%/packages/patches/nettle-3.5-CVE-2021-3580-pt2.patch	\
   %D%/packages/patches/nfs4-acl-tools-0.3.7-fixpaths.patch	\
   %D%/packages/patches/ngircd-handle-zombies.patch		\
   %D%/packages/patches/network-manager-plugin-path.patch	\
diff --git a/gnu/packages/nettle.scm b/gnu/packages/nettle.scm
index 753e2d6e7e..3d394dc746 100644
--- a/gnu/packages/nettle.scm
+++ b/gnu/packages/nettle.scm
@@ -1,6 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
-;;; Copyright © 2016 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2016, 2021 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2017 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;;
@@ -25,6 +25,7 @@
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix build-system gnu)
+  #:use-module (gnu packages)
   #:use-module (gnu packages multiprecision)
   #:use-module (gnu packages m4))
 
@@ -77,6 +78,7 @@ themselves.")
   ;; cannot use it yet.  So keep it separate.
   (package (inherit nettle-2)
     (version "3.5.1")
+    (replacement nettle-3.5/fixed)
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://gnu/nettle/nettle-"
@@ -91,6 +93,13 @@ themselves.")
         ;; at run time based on CPU features (starting from 3.1.)
         `(cons "--enable-fat" ,flags))))))
 
+(define nettle-3.5/fixed
+  (package-with-extra-patches
+   nettle-3.5
+   (search-patches "nettle-3.5-check-_pkcs1_sec_decrypt-msg-len.patch"
+                   "nettle-3.5-CVE-2021-3580-pt1.patch"
+                   "nettle-3.5-CVE-2021-3580-pt2.patch")))
+
 (define-public nettle-3.7
   (package (inherit nettle-3.5)
     (version "3.7.2")
diff --git a/gnu/packages/patches/nettle-3.5-CVE-2021-3580-pt1.patch b/gnu/packages/patches/nettle-3.5-CVE-2021-3580-pt1.patch
new file mode 100644
index 0000000000..4343c87795
--- /dev/null
+++ b/gnu/packages/patches/nettle-3.5-CVE-2021-3580-pt1.patch
@@ -0,0 +1,276 @@
+Copied from upstream nettle git repository.
+Removed changes to ChangeLog, to allow this patch to apply to nettle-3.5.
+
+From 485b5e2820a057e873b1ba812fdb39cae4adf98c Mon Sep 17 00:00:00 2001
+From: Niels Möller <nisse@lysator.liu.se>
+Date: Mon, 17 May 2021 20:55:26 +0200
+Subject: [PATCH 1/2] Change _rsa_sec_compute_root_tr to take a fix input size.
+
+Improves consistency with _rsa_sec_compute_root, and fixes zero-input bug.
+---
+ ChangeLog                    | 15 +++++++++
+ rsa-decrypt-tr.c             |  7 ++---
+ rsa-internal.h               |  4 +--
+ rsa-sec-decrypt.c            |  9 ++++--
+ rsa-sign-tr.c                | 61 +++++++++++++++++-------------------
+ testsuite/rsa-encrypt-test.c | 14 ++++++++-
+ 6 files changed, 68 insertions(+), 42 deletions(-)
+
+diff --git a/rsa-decrypt-tr.c b/rsa-decrypt-tr.c
+index 0224c0b7..927a8915 100644
+--- a/rsa-decrypt-tr.c
++++ b/rsa-decrypt-tr.c
+@@ -52,14 +52,13 @@ rsa_decrypt_tr(const struct rsa_public_key *pub,
+   mp_size_t key_limb_size;
+   int res;
+ 
+-  key_limb_size = NETTLE_OCTET_SIZE_TO_LIMB_SIZE(key->size);
++  key_limb_size = mpz_size(pub->n);
+ 
+   TMP_GMP_ALLOC (m, key_limb_size);
+   TMP_GMP_ALLOC (em, key->size);
++  mpz_limbs_copy(m, gibberish, key_limb_size);
+ 
+-  res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, m,
+-				  mpz_limbs_read(gibberish),
+-				  mpz_size(gibberish));
++  res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, m, m);
+ 
+   mpn_get_base256 (em, key->size, m, key_limb_size);
+ 
+diff --git a/rsa-internal.h b/rsa-internal.h
+index b828e451..f66a7df0 100644
+--- a/rsa-internal.h
++++ b/rsa-internal.h
+@@ -78,11 +78,11 @@ _rsa_sec_compute_root(const struct rsa_private_key *key,
+                       mp_limb_t *scratch);
+ 
+ /* Safe side-channel silent variant, using RSA blinding, and checking the
+- * result after CRT. */
++ * result after CRT. In-place calls, with x == m, is allowed. */
+ int
+ _rsa_sec_compute_root_tr(const struct rsa_public_key *pub,
+ 			 const struct rsa_private_key *key,
+ 			 void *random_ctx, nettle_random_func *random,
+-			 mp_limb_t *x, const mp_limb_t *m, size_t mn);
++			 mp_limb_t *x, const mp_limb_t *m);
+ 
+ #endif /* NETTLE_RSA_INTERNAL_H_INCLUDED */
+diff --git a/rsa-sec-decrypt.c b/rsa-sec-decrypt.c
+index 6866e7c8..fc4757a0 100644
+--- a/rsa-sec-decrypt.c
++++ b/rsa-sec-decrypt.c
+@@ -58,9 +58,12 @@ rsa_sec_decrypt(const struct rsa_public_key *pub,
+   TMP_GMP_ALLOC (m, mpz_size(pub->n));
+   TMP_GMP_ALLOC (em, key->size);
+ 
+-  res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, m,
+-				  mpz_limbs_read(gibberish),
+-				  mpz_size(gibberish));
++  /* We need a copy because m can be shorter than key_size,
++   * but _rsa_sec_compute_root_tr expect all inputs to be
++   * normalized to a key_size long buffer length */
++  mpz_limbs_copy(m, gibberish, mpz_size(pub->n));
++
++  res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, m, m);
+ 
+   mpn_get_base256 (em, key->size, m, mpz_size(pub->n));
+ 
+diff --git a/rsa-sign-tr.c b/rsa-sign-tr.c
+index f824c4ca..9e137c7a 100644
+--- a/rsa-sign-tr.c
++++ b/rsa-sign-tr.c
+@@ -131,35 +131,34 @@ int
+ _rsa_sec_compute_root_tr(const struct rsa_public_key *pub,
+ 			 const struct rsa_private_key *key,
+ 			 void *random_ctx, nettle_random_func *random,
+-			 mp_limb_t *x, const mp_limb_t *m, size_t mn)
++			 mp_limb_t *x, const mp_limb_t *m)
+ {
++  mp_size_t nn;
+   mpz_t mz;
+   mpz_t xz;
+   int res;
+ 
+-  mpz_init(mz);
+   mpz_init(xz);
+ 
+-  mpn_copyi(mpz_limbs_write(mz, mn), m, mn);
+-  mpz_limbs_finish(mz, mn);
++  nn = mpz_size (pub->n);
+ 
+-  res = rsa_compute_root_tr(pub, key, random_ctx, random, xz, mz);
++  res = rsa_compute_root_tr(pub, key, random_ctx, random, xz,
++			    mpz_roinit_n(mz, m, nn));
+ 
+   if (res)
+-    mpz_limbs_copy(x, xz, mpz_size(pub->n));
++    mpz_limbs_copy(x, xz, nn);
+ 
+-  mpz_clear(mz);
+   mpz_clear(xz);
+   return res;
+ }
+ #else
+ /* Blinds m, by computing c = m r^e (mod n), for a random r. Also
+-   returns the inverse (ri), for use by rsa_unblind. */
++   returns the inverse (ri), for use by rsa_unblind. Must have c != m,
++   no in-place operation.*/
+ static void
+ rsa_sec_blind (const struct rsa_public_key *pub,
+                void *random_ctx, nettle_random_func *random,
+-               mp_limb_t *c, mp_limb_t *ri, const mp_limb_t *m,
+-               mp_size_t mn)
++               mp_limb_t *c, mp_limb_t *ri, const mp_limb_t *m)
+ {
+   const mp_limb_t *ep = mpz_limbs_read (pub->e);
+   const mp_limb_t *np = mpz_limbs_read (pub->n);
+@@ -177,15 +176,15 @@ rsa_sec_blind (const struct rsa_public_key *pub,
+ 
+   /* c = m*(r^e) mod n */
+   itch = mpn_sec_powm_itch(nn, ebn, nn);
+-  i2 = mpn_sec_mul_itch(nn, mn);
++  i2 = mpn_sec_mul_itch(nn, nn);
+   itch = MAX(itch, i2);
+-  i2 = mpn_sec_div_r_itch(nn + mn, nn);
++  i2 = mpn_sec_div_r_itch(2*nn, nn);
+   itch = MAX(itch, i2);
+   i2 = mpn_sec_invert_itch(nn);
+   itch = MAX(itch, i2);
+ 
+-  TMP_GMP_ALLOC (tp, nn + mn + itch);
+-  scratch = tp + nn + mn;
++  TMP_GMP_ALLOC (tp, 2*nn  + itch);
++  scratch = tp + 2*nn;
+ 
+   /* ri = r^(-1) */
+   do
+@@ -198,9 +197,8 @@ rsa_sec_blind (const struct rsa_public_key *pub,
+   while (!mpn_sec_invert (ri, tp, np, nn, 2 * nn * GMP_NUMB_BITS, scratch));
+ 
+   mpn_sec_powm (c, rp, nn, ep, ebn, np, nn, scratch);
+-  /* normally mn == nn, but m can be smaller in some cases */
+-  mpn_sec_mul (tp, c, nn, m, mn, scratch);
+-  mpn_sec_div_r (tp, nn + mn, np, nn, scratch);
++  mpn_sec_mul (tp, c, nn, m, nn, scratch);
++  mpn_sec_div_r (tp, 2*nn, np, nn, scratch);
+   mpn_copyi(c, tp, nn);
+ 
+   TMP_GMP_FREE (r);
+@@ -208,7 +206,7 @@ rsa_sec_blind (const struct rsa_public_key *pub,
+   TMP_GMP_FREE (tp);
+ }
+ 
+-/* m = c ri mod n */
++/* m = c ri mod n. Allows x == c. */
+ static void
+ rsa_sec_unblind (const struct rsa_public_key *pub,
+                  mp_limb_t *x, mp_limb_t *ri, const mp_limb_t *c)
+@@ -299,7 +297,7 @@ int
+ _rsa_sec_compute_root_tr(const struct rsa_public_key *pub,
+ 			 const struct rsa_private_key *key,
+ 			 void *random_ctx, nettle_random_func *random,
+-			 mp_limb_t *x, const mp_limb_t *m, size_t mn)
++			 mp_limb_t *x, const mp_limb_t *m)
+ {
+   TMP_GMP_DECL (c, mp_limb_t);
+   TMP_GMP_DECL (ri, mp_limb_t);
+@@ -307,7 +305,7 @@ _rsa_sec_compute_root_tr(const struct rsa_public_key *pub,
+   size_t key_limb_size;
+   int ret;
+ 
+-  key_limb_size = NETTLE_OCTET_SIZE_TO_LIMB_SIZE(key->size);
++  key_limb_size = mpz_size(pub->n);
+ 
+   /* mpz_powm_sec handles only odd moduli. If p, q or n is even, the
+      key is invalid and rejected by rsa_private_key_prepare. However,
+@@ -321,19 +319,18 @@ _rsa_sec_compute_root_tr(const struct rsa_public_key *pub,
+     }
+ 
+   assert(mpz_size(pub->n) == key_limb_size);
+-  assert(mn <= key_limb_size);
+ 
+   TMP_GMP_ALLOC (c, key_limb_size);
+   TMP_GMP_ALLOC (ri, key_limb_size);
+   TMP_GMP_ALLOC (scratch, _rsa_sec_compute_root_itch(key));
+ 
+-  rsa_sec_blind (pub, random_ctx, random, x, ri, m, mn);
++  rsa_sec_blind (pub, random_ctx, random, c, ri, m);
+ 
+-  _rsa_sec_compute_root(key, c, x, scratch);
++  _rsa_sec_compute_root(key, x, c, scratch);
+ 
+-  ret = rsa_sec_check_root(pub, c, x);
++  ret = rsa_sec_check_root(pub, x, c);
+ 
+-  rsa_sec_unblind(pub, x, ri, c);
++  rsa_sec_unblind(pub, x, ri, x);
+ 
+   cnd_mpn_zero(1 - ret, x, key_limb_size);
+ 
+@@ -357,17 +354,17 @@ rsa_compute_root_tr(const struct rsa_public_key *pub,
+ 		    mpz_t x, const mpz_t m)
+ {
+   TMP_GMP_DECL (l, mp_limb_t);
++  mp_size_t nn = mpz_size(pub->n);
+   int res;
+ 
+-  mp_size_t l_size = NETTLE_OCTET_SIZE_TO_LIMB_SIZE(key->size);
+-  TMP_GMP_ALLOC (l, l_size);
++  TMP_GMP_ALLOC (l, nn);
++  mpz_limbs_copy(l, m, nn);
+ 
+-  res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, l,
+-				  mpz_limbs_read(m), mpz_size(m));
++  res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, l, l);
+   if (res) {
+-    mp_limb_t *xp = mpz_limbs_write (x, l_size);
+-    mpn_copyi (xp, l, l_size);
+-    mpz_limbs_finish (x, l_size);
++    mp_limb_t *xp = mpz_limbs_write (x, nn);
++    mpn_copyi (xp, l, nn);
++    mpz_limbs_finish (x, nn);
+   }
+ 
+   TMP_GMP_FREE (l);
+diff --git a/testsuite/rsa-encrypt-test.c b/testsuite/rsa-encrypt-test.c
+index 87525f78..d3bc374b 100644
+--- a/testsuite/rsa-encrypt-test.c
++++ b/testsuite/rsa-encrypt-test.c
+@@ -19,6 +19,7 @@ test_main(void)
+   uint8_t after;
+ 
+   mpz_t gibberish;
++  mpz_t zero;
+ 
+   rsa_private_key_init(&key);
+   rsa_public_key_init(&pub);
+@@ -101,6 +102,17 @@ test_main(void)
+   ASSERT(decrypted[decrypted_length] == after);
+   ASSERT(decrypted[0] == 'A');
+ 
++  /* Test zero input. */
++  mpz_init_set_ui (zero, 0);
++  decrypted_length = msg_length;
++  ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, zero));
++  ASSERT(!rsa_decrypt_tr(&pub, &key,
++			 &lfib, (nettle_random_func *) knuth_lfib_random,
++			 &decrypted_length, decrypted, zero));
++  ASSERT(!rsa_sec_decrypt(&pub, &key,
++			  &lfib, (nettle_random_func *) knuth_lfib_random,
++			  decrypted_length, decrypted, zero));
++  ASSERT(decrypted_length == msg_length);
+ 
+   /* Test invalid key. */
+   mpz_add_ui (key.q, key.q, 2);
+@@ -112,6 +124,6 @@ test_main(void)
+   rsa_private_key_clear(&key);
+   rsa_public_key_clear(&pub);
+   mpz_clear(gibberish);
++  mpz_clear(zero);
+   free(decrypted);
+ }
+-  
+-- 
+2.31.1
+
diff --git a/gnu/packages/patches/nettle-3.5-CVE-2021-3580-pt2.patch b/gnu/packages/patches/nettle-3.5-CVE-2021-3580-pt2.patch
new file mode 100644
index 0000000000..5f19bd80d3
--- /dev/null
+++ b/gnu/packages/patches/nettle-3.5-CVE-2021-3580-pt2.patch
@@ -0,0 +1,163 @@
+Copied from upstream nettle git repository.
+Removed changes to ChangeLog, to allow this patch to apply to nettle-3.5.
+
+From 0ad0b5df315665250dfdaa4a1e087f4799edaefe Mon Sep 17 00:00:00 2001
+From: Niels Möller <nisse@lysator.liu.se>
+Date: Mon, 17 May 2021 22:02:47 +0200
+Subject: [PATCH 2/2] Add input check to rsa_decrypt family of functions.
+
+---
+ ChangeLog                    |  8 ++++++++
+ rsa-decrypt-tr.c             |  4 ++++
+ rsa-decrypt.c                | 10 ++++++++++
+ rsa-sec-decrypt.c            |  4 ++++
+ rsa.h                        |  5 +++--
+ testsuite/rsa-encrypt-test.c | 38 ++++++++++++++++++++++++++++++------
+ 6 files changed, 61 insertions(+), 8 deletions(-)
+
+diff --git a/rsa-decrypt-tr.c b/rsa-decrypt-tr.c
+index 927a8915..4a9e9d74 100644
+--- a/rsa-decrypt-tr.c
++++ b/rsa-decrypt-tr.c
+@@ -52,6 +52,10 @@ rsa_decrypt_tr(const struct rsa_public_key *pub,
+   mp_size_t key_limb_size;
+   int res;
+ 
++  /* First check that input is in range. */
++  if (mpz_sgn (gibberish) < 0 || mpz_cmp (gibberish, pub->n) >= 0)
++    return 0;
++
+   key_limb_size = mpz_size(pub->n);
+ 
+   TMP_GMP_ALLOC (m, key_limb_size);
+diff --git a/rsa-decrypt.c b/rsa-decrypt.c
+index 7681439d..540d8baa 100644
+--- a/rsa-decrypt.c
++++ b/rsa-decrypt.c
+@@ -48,6 +48,16 @@ rsa_decrypt(const struct rsa_private_key *key,
+   int res;
+ 
+   mpz_init(m);
++
++  /* First check that input is in range. Since we don't have the
++     public key available here, we need to reconstruct n. */
++  mpz_mul (m, key->p, key->q);
++  if (mpz_sgn (gibberish) < 0 || mpz_cmp (gibberish, m) >= 0)
++    {
++      mpz_clear (m);
++      return 0;
++    }
++
+   rsa_compute_root(key, m, gibberish);
+ 
+   res = pkcs1_decrypt (key->size, m, length, message);
+diff --git a/rsa-sec-decrypt.c b/rsa-sec-decrypt.c
+index fc4757a0..4c98958d 100644
+--- a/rsa-sec-decrypt.c
++++ b/rsa-sec-decrypt.c
+@@ -55,6 +55,10 @@ rsa_sec_decrypt(const struct rsa_public_key *pub,
+   TMP_GMP_DECL (em, uint8_t);
+   int res;
+ 
++  /* First check that input is in range. */
++  if (mpz_sgn (gibberish) < 0 || mpz_cmp (gibberish, pub->n) >= 0)
++    return 0;
++
+   TMP_GMP_ALLOC (m, mpz_size(pub->n));
+   TMP_GMP_ALLOC (em, key->size);
+ 
+diff --git a/rsa.h b/rsa.h
+index 3b10155f..2dd35a2d 100644
+--- a/rsa.h
++++ b/rsa.h
+@@ -428,13 +428,14 @@ rsa_sec_decrypt(const struct rsa_public_key *pub,
+ 	        size_t length, uint8_t *message,
+ 	        const mpz_t gibberish);
+ 
+-/* Compute x, the e:th root of m. Calling it with x == m is allowed. */
++/* Compute x, the e:th root of m. Calling it with x == m is allowed.
++   It is required that 0 <= m < n. */
+ void
+ rsa_compute_root(const struct rsa_private_key *key,
+ 		 mpz_t x, const mpz_t m);
+ 
+ /* Safer variant, using RSA blinding, and checking the result after
+-   CRT. */
++   CRT. It is required that 0 <= m < n. */
+ int
+ rsa_compute_root_tr(const struct rsa_public_key *pub,
+ 		    const struct rsa_private_key *key,
+diff --git a/testsuite/rsa-encrypt-test.c b/testsuite/rsa-encrypt-test.c
+index d3bc374b..d1a440f6 100644
+--- a/testsuite/rsa-encrypt-test.c
++++ b/testsuite/rsa-encrypt-test.c
+@@ -19,11 +19,12 @@ test_main(void)
+   uint8_t after;
+ 
+   mpz_t gibberish;
+-  mpz_t zero;
++  mpz_t bad_input;
+ 
+   rsa_private_key_init(&key);
+   rsa_public_key_init(&pub);
+   mpz_init(gibberish);
++  mpz_init(bad_input);
+ 
+   knuth_lfib_init(&lfib, 17);
+   
+@@ -103,15 +104,40 @@ test_main(void)
+   ASSERT(decrypted[0] == 'A');
+ 
+   /* Test zero input. */
+-  mpz_init_set_ui (zero, 0);
++  mpz_set_ui (bad_input, 0);
+   decrypted_length = msg_length;
+-  ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, zero));
++  ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, bad_input));
+   ASSERT(!rsa_decrypt_tr(&pub, &key,
+ 			 &lfib, (nettle_random_func *) knuth_lfib_random,
+-			 &decrypted_length, decrypted, zero));
++			 &decrypted_length, decrypted, bad_input));
+   ASSERT(!rsa_sec_decrypt(&pub, &key,
+ 			  &lfib, (nettle_random_func *) knuth_lfib_random,
+-			  decrypted_length, decrypted, zero));
++			  decrypted_length, decrypted, bad_input));
++  ASSERT(decrypted_length == msg_length);
++
++  /* Test input that is slightly larger than n */
++  mpz_add(bad_input, gibberish, pub.n);
++  decrypted_length = msg_length;
++  ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, bad_input));
++  ASSERT(!rsa_decrypt_tr(&pub, &key,
++			 &lfib, (nettle_random_func *) knuth_lfib_random,
++			 &decrypted_length, decrypted, bad_input));
++  ASSERT(!rsa_sec_decrypt(&pub, &key,
++			  &lfib, (nettle_random_func *) knuth_lfib_random,
++			  decrypted_length, decrypted, bad_input));
++  ASSERT(decrypted_length == msg_length);
++
++  /* Test input that is considerably larger than n */
++  mpz_mul_2exp (bad_input, pub.n, 100);
++  mpz_add (bad_input, bad_input, gibberish);
++  decrypted_length = msg_length;
++  ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, bad_input));
++  ASSERT(!rsa_decrypt_tr(&pub, &key,
++			 &lfib, (nettle_random_func *) knuth_lfib_random,
++			 &decrypted_length, decrypted, bad_input));
++  ASSERT(!rsa_sec_decrypt(&pub, &key,
++			  &lfib, (nettle_random_func *) knuth_lfib_random,
++			  decrypted_length, decrypted, bad_input));
+   ASSERT(decrypted_length == msg_length);
+ 
+   /* Test invalid key. */
+@@ -124,6 +150,6 @@ test_main(void)
+   rsa_private_key_clear(&key);
+   rsa_public_key_clear(&pub);
+   mpz_clear(gibberish);
+-  mpz_clear(zero);
++  mpz_clear(bad_input);
+   free(decrypted);
+ }
+-- 
+2.31.1
+
diff --git a/gnu/packages/patches/nettle-3.5-check-_pkcs1_sec_decrypt-msg-len.patch b/gnu/packages/patches/nettle-3.5-check-_pkcs1_sec_decrypt-msg-len.patch
new file mode 100644
index 0000000000..297816e698
--- /dev/null
+++ b/gnu/packages/patches/nettle-3.5-check-_pkcs1_sec_decrypt-msg-len.patch
@@ -0,0 +1,78 @@
+Copied from upstream nettle git repository.
+Removed changes to ChangeLog, to allow this patch to apply to nettle-3.5.
+
+From 7616541e6eff73353bf682c62e3a68e4fe696707 Mon Sep 17 00:00:00 2001
+From: Niels Möller <nisse@lysator.liu.se>
+Date: Thu, 6 May 2021 21:29:56 +0200
+Subject: [PATCH] Add check that message length to _pkcs1_sec_decrypt is valid.
+
+* pkcs1-sec-decrypt.c (_pkcs1_sec_decrypt): Check that message
+length is valid, for given key size.
+* testsuite/rsa-sec-decrypt-test.c (test_main): Add test cases for
+calls to rsa_sec_decrypt specifying a too large message length.
+---
+ ChangeLog                        |  7 +++++++
+ pkcs1-sec-decrypt.c              |  4 +++-
+ testsuite/rsa-sec-decrypt-test.c | 17 ++++++++++++++++-
+ 3 files changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/pkcs1-sec-decrypt.c b/pkcs1-sec-decrypt.c
+index 4f13080e..16833691 100644
+--- a/pkcs1-sec-decrypt.c
++++ b/pkcs1-sec-decrypt.c
+@@ -63,7 +63,9 @@ _pkcs1_sec_decrypt (size_t length, uint8_t *message,
+   volatile int ok;
+   size_t i, t;
+ 
+-  assert (padded_message_length >= length);
++  /* Message independent branch */
++  if (length + 11 > padded_message_length)
++    return 0;
+ 
+   t = padded_message_length - length - 1;
+ 
+diff --git a/testsuite/rsa-sec-decrypt-test.c b/testsuite/rsa-sec-decrypt-test.c
+index fb0ed3a1..3419322e 100644
+--- a/testsuite/rsa-sec-decrypt-test.c
++++ b/testsuite/rsa-sec-decrypt-test.c
+@@ -55,6 +55,7 @@ rsa_decrypt_for_test(const struct rsa_public_key *pub,
+ #endif
+ 
+ #define PAYLOAD_SIZE 50
++#define DECRYPTED_SIZE 256
+ void
+ test_main(void)
+ {
+@@ -63,7 +64,7 @@ test_main(void)
+   struct knuth_lfib_ctx random_ctx;
+ 
+   uint8_t plaintext[PAYLOAD_SIZE];
+-  uint8_t decrypted[PAYLOAD_SIZE];
++  uint8_t decrypted[DECRYPTED_SIZE];
+   uint8_t verifybad[PAYLOAD_SIZE];
+   unsigned n_size = 1024;
+   mpz_t gibberish;
+@@ -99,6 +100,20 @@ test_main(void)
+                                     PAYLOAD_SIZE, decrypted, gibberish) == 1);
+       ASSERT (MEMEQ (PAYLOAD_SIZE, plaintext, decrypted));
+ 
++      ASSERT (pub.size > 10);
++      ASSERT (pub.size <= DECRYPTED_SIZE);
++
++      /* Check that too large message length is rejected, largest
++	 valid size is pub.size - 11. */
++      ASSERT (!rsa_decrypt_for_test (&pub, &key, &random_ctx,
++				     (nettle_random_func *) knuth_lfib_random,
++				     pub.size - 10, decrypted, gibberish));
++
++      /* This case used to result in arithmetic underflow and a crash. */
++      ASSERT (!rsa_decrypt_for_test (&pub, &key, &random_ctx,
++				     (nettle_random_func *) knuth_lfib_random,
++				     pub.size, decrypted, gibberish));
++
+       /* bad one */
+       memcpy(decrypted, verifybad, PAYLOAD_SIZE);
+       nettle_mpz_random_size(garbage, &random_ctx,
+-- 
+2.31.1
+