From f129b0e97730b47d62482fba9599db39b526f3d2 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 29 Mar 2021 14:36:52 +0200 Subject: [PATCH] gpg: Allow ECDH with a smartcard returning just the x-ccordinate. * g10/ecdh.c (extract_secret_x): Add extra safety check. Allow for x-only coordinate. --- g10/ecdh.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/g10/ecdh.c b/g10/ecdh.c index 9a1f535a0..d048951d7 100644 --- a/g10/ecdh.c +++ b/g10/ecdh.c @@ -101,9 +101,13 @@ extract_secret_x (byte **r_secret_x, 41 || X Since it may come with the prefix, the size of point is larger - than or equals to the size of an integer X. */ + than or equals to the size of an integer X. We also better check + that the provided shared point is not larger than the size needed + to represent the point. */ if (point_nbytes < secret_x_size) return gpg_error (GPG_ERR_BAD_DATA); + if (point_nbytes < nshared) + return gpg_error (GPG_ERR_BAD_DATA); /* Extract x component of the shared point: this is the actual shared secret. */ @@ -113,13 +117,18 @@ extract_secret_x (byte **r_secret_x, memcpy (secret_x, shared, nshared); - /* Remove the prefix. */ - if ((point_nbytes & 1)) - memmove (secret_x, secret_x+1, secret_x_size); + /* Wrangle the provided point unless only the x-component w/o any + * prefix was provided. */ + if (nshared != secret_x_size) + { + /* Remove the prefix. */ + if ((point_nbytes & 1)) + memmove (secret_x, secret_x+1, secret_x_size); - /* Clear the rest of data. */ - if (point_nbytes - secret_x_size) - memset (secret_x+secret_x_size, 0, point_nbytes-secret_x_size); + /* Clear the rest of data. */ + if (point_nbytes - secret_x_size) + memset (secret_x+secret_x_size, 0, point_nbytes-secret_x_size); + } if (DBG_CRYPTO) log_printhex (secret_x, secret_x_size, "ECDH shared secret X is:");