1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-06-30 22:27:56 +02:00

g10: Fix ECDH, clarifying the format.

* g10/ecdh.c (pk_ecdh_encrypt_with_shared_point): Returns error when
it's short.  Clarify the format.  Handle other prefixes correctly.

--
With the scdaemon's change, there is no case NBYTES < SECRET_X_SIZE.
This fixes the break of ECDH with X25519.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2016-10-27 12:59:49 +09:00
parent 6bbd97d6c7
commit ca0ee4e381

View File

@ -135,27 +135,29 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
/* Expected size of the x component */ /* Expected size of the x component */
secret_x_size = (nbits+7)/8; secret_x_size = (nbits+7)/8;
if (nbytes > secret_x_size) /* Extract X from the result. It must be in the format of:
{ 04 || X || Y
/* Uncompressed format expected, so it must start with 04 */ 40 || X
if (secret_x[0] != (byte)0x04) 41 || X
{
return gpg_error (GPG_ERR_BAD_DATA);
}
/* Remove the "04" prefix of non-compressed format. */ Since it always comes with the prefix, it's larger than X. In
memmove (secret_x, secret_x+1, secret_x_size); old experimental version of libgcrypt, there is a case where it
returns X with no prefix of 40, so, nbytes == secret_x_size
/* Zeroize the y component following */ is allowed. */
if (nbytes > secret_x_size) if (nbytes < secret_x_size)
memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
}
else if (nbytes < secret_x_size)
{ {
/* Raw share secret (x coordinate), without leading zeros */ xfree (secret_x);
memmove (secret_x+(secret_x_size - nbytes), secret_x, nbytes); return gpg_error (GPG_ERR_BAD_DATA);
memset (secret_x, 0, secret_x_size - nbytes);
} }
/* Remove the prefix. */
if ((nbytes & 1))
memmove (secret_x, secret_x+1, secret_x_size);
/* Clear the rest of data. */
if (nbytes - secret_x_size)
memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
if (DBG_CRYPTO) if (DBG_CRYPTO)
log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size ); log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size );
} }