mirror of
https://git.yoctoproject.org/poky
synced 2026-06-06 03:52:39 +02:00
Backport the fix from https://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git; a=commit;h=bf76acbf0da6b0f245e491bec12c0f0a1b5be7c9 (From OE-Core rev: 3b827eff306c484d78d61b259cd5d4eef8df381c) Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
159 lines
5.0 KiB
Diff
159 lines
5.0 KiB
Diff
From ef570e3d2773c12126e7d3fcdc4db9ef80a5e214 Mon Sep 17 00:00:00 2001
|
|
From: NIIBE Yutaka <gniibe@fsij.org>
|
|
Date: Fri, 25 Aug 2017 18:13:28 +0900
|
|
Subject: [PATCH] ecc: Add input validation for X25519.
|
|
|
|
* cipher/ecc.c (ecc_decrypt_raw): Add input validation.
|
|
* mpi/ec.c (ec_p_init): Use scratch buffer for bad points.
|
|
(_gcry_mpi_ec_bad_point): New.
|
|
|
|
--
|
|
|
|
Following is the paper describing the attack:
|
|
|
|
May the Fourth Be With You: A Microarchitectural Side Channel Attack
|
|
on Real-World Applications of Curve25519
|
|
by Daniel Genkin, Luke Valenta, and Yuval Yarom
|
|
|
|
In the current implementation, we do output checking and it results an
|
|
error for those bad points. However, when attacked, the computation
|
|
will done with leak of private key, even it will results errors. To
|
|
mitigate leak, we added input validation.
|
|
|
|
Note that we only list bad points with MSB=0. By X25519, MSB is
|
|
always cleared.
|
|
|
|
In future, we should implement constant-time field computation. Then,
|
|
this input validation could be removed, if performance is important
|
|
and we are sure for no leak.
|
|
|
|
CVE-id: CVE-2017-0379
|
|
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
|
|
|
|
Upstream-Status: Backport
|
|
CVE: CVE-2017-0379
|
|
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
|
|
---
|
|
cipher/ecc.c | 17 +++++++++++++++--
|
|
mpi/ec.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++---
|
|
src/mpi.h | 1 +
|
|
3 files changed, 64 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/cipher/ecc.c b/cipher/ecc.c
|
|
index e25bf09..4e3e5b1 100644
|
|
--- a/cipher/ecc.c
|
|
+++ b/cipher/ecc.c
|
|
@@ -1628,9 +1628,22 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
|
|
if (DBG_CIPHER)
|
|
log_printpnt ("ecc_decrypt kG", &kG, NULL);
|
|
|
|
- if (!(flags & PUBKEY_FLAG_DJB_TWEAK)
|
|
+ if ((flags & PUBKEY_FLAG_DJB_TWEAK))
|
|
+ {
|
|
/* For X25519, by its definition, validation should not be done. */
|
|
- && !_gcry_mpi_ec_curve_point (&kG, ec))
|
|
+ /* (Instead, we do output check.)
|
|
+ *
|
|
+ * However, to mitigate secret key leak from our implementation,
|
|
+ * we also do input validation here. For constant-time
|
|
+ * implementation, we can remove this input validation.
|
|
+ */
|
|
+ if (_gcry_mpi_ec_bad_point (&kG, ec))
|
|
+ {
|
|
+ rc = GPG_ERR_INV_DATA;
|
|
+ goto leave;
|
|
+ }
|
|
+ }
|
|
+ else if (!_gcry_mpi_ec_curve_point (&kG, ec))
|
|
{
|
|
rc = GPG_ERR_INV_DATA;
|
|
goto leave;
|
|
diff --git a/mpi/ec.c b/mpi/ec.c
|
|
index a0f7357..4c16603 100644
|
|
--- a/mpi/ec.c
|
|
+++ b/mpi/ec.c
|
|
@@ -396,6 +396,29 @@ ec_get_two_inv_p (mpi_ec_t ec)
|
|
}
|
|
|
|
|
|
+static const char *curve25519_bad_points[] = {
|
|
+ "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
+ "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
+ "0x00b8495f16056286fdb1329ceb8d09da6ac49ff1fae35616aeb8413b7c7aebe0",
|
|
+ "0x57119fd0dd4e22d8868e1c58c45c44045bef839c55b1d0b1248c50a3bc959c5f",
|
|
+ "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec",
|
|
+ "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
|
|
+ "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
|
|
+ NULL
|
|
+};
|
|
+
|
|
+static gcry_mpi_t
|
|
+scanval (const char *string)
|
|
+{
|
|
+ gpg_err_code_t rc;
|
|
+ gcry_mpi_t val;
|
|
+
|
|
+ rc = _gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
|
|
+ if (rc)
|
|
+ log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (rc));
|
|
+ return val;
|
|
+}
|
|
+
|
|
|
|
/* This function initialized a context for elliptic curve based on the
|
|
field GF(p). P is the prime specifying this field, A is the first
|
|
@@ -434,9 +457,17 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
|
|
|
|
_gcry_mpi_ec_get_reset (ctx);
|
|
|
|
- /* Allocate scratch variables. */
|
|
- for (i=0; i< DIM(ctx->t.scratch); i++)
|
|
- ctx->t.scratch[i] = mpi_alloc_like (ctx->p);
|
|
+ if (model == MPI_EC_MONTGOMERY)
|
|
+ {
|
|
+ for (i=0; i< DIM(ctx->t.scratch) && curve25519_bad_points[i]; i++)
|
|
+ ctx->t.scratch[i] = scanval (curve25519_bad_points[i]);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* Allocate scratch variables. */
|
|
+ for (i=0; i< DIM(ctx->t.scratch); i++)
|
|
+ ctx->t.scratch[i] = mpi_alloc_like (ctx->p);
|
|
+ }
|
|
|
|
/* Prepare for fast reduction. */
|
|
/* FIXME: need a test for NIST values. However it does not gain us
|
|
@@ -1572,3 +1603,17 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx)
|
|
|
|
return res;
|
|
}
|
|
+
|
|
+
|
|
+int
|
|
+_gcry_mpi_ec_bad_point (gcry_mpi_point_t point, mpi_ec_t ctx)
|
|
+{
|
|
+ int i;
|
|
+ gcry_mpi_t x_bad;
|
|
+
|
|
+ for (i = 0; (x_bad = ctx->t.scratch[i]); i++)
|
|
+ if (!mpi_cmp (point->x, x_bad))
|
|
+ return 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/src/mpi.h b/src/mpi.h
|
|
index b5385b5..aeba7f8 100644
|
|
--- a/src/mpi.h
|
|
+++ b/src/mpi.h
|
|
@@ -296,6 +296,7 @@ void _gcry_mpi_ec_mul_point (mpi_point_t result,
|
|
gcry_mpi_t scalar, mpi_point_t point,
|
|
mpi_ec_t ctx);
|
|
int _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx);
|
|
+int _gcry_mpi_ec_bad_point (gcry_mpi_point_t point, mpi_ec_t ctx);
|
|
|
|
gcry_mpi_t _gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx);
|
|
|
|
--
|
|
1.8.3.1
|
|
|