wireshark/wsutil/curve25519.c
John Thacker b80cdaa243 libgcrypt: Require version 1.8.0
Libgcrypt 1.8.x is required for a large amount of decryption
support and is the current LTS version of libgcrypt. The 1.6 and
1.7 series have been end-of-life since 2017-06-30 and 2019-06-30,
respectively.

The Linux distributions that have versions of libgcrypt before 1.8.0
are nearing or at end of support (RHEL7, SLES 12, Debian stretch,
Ubuntu 16.04LTS) and can be supported by the Wireshark 3.6 LTS release
series.

Remove an enormous amount of ifdefs based on libgcrypt versions
1.6.0, 1.7.0, and 1.8.0. There will be a second pass for the
commons defines HAVE_LIBGCRYPT_AEAD, HAVE_LIBGCRYPT_CHACHA20, and
HAVE_LIBGCRYPT_CHACHA20_POLY1305, which are now always defined.

The ISAKMP dissector has some comments noting that some workarounds
were used for libgcrypt 1.6 that aren't needed with 1.7; perhaps
that could be updated now.
2022-04-20 21:30:21 -04:00

103 lines
2.7 KiB
C

/* curve25519.c
* NaCl/Sodium-compatible API for Curve25519 cryptography.
*
* Copyright (c) 2018, Peter Wu <peter@lekensteyn.nl>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "curve25519.h"
#include "ws_attributes.h"
static inline void
copy_and_reverse(unsigned char *dest, const unsigned char *src, size_t n)
{
for (size_t i = 0; i < n; i++) {
dest[n - 1 - i] = src[i];
}
}
static int
x25519_mpi(unsigned char *q, const unsigned char *n, gcry_mpi_t mpi_p)
{
unsigned char priv_be[32];
unsigned char result_be[32];
size_t result_len = 0;
gcry_mpi_t mpi = NULL;
gcry_ctx_t ctx = NULL;
gcry_mpi_point_t P = NULL;
gcry_mpi_point_t Q = NULL;
int r = -1;
/* Default to infinity (all zeroes). */
memset(q, 0, 32);
/* Keys are in little-endian, but gcry_mpi_scan expects big endian. Convert
* keys and ensure that the result is a valid Curve25519 secret scalar. */
copy_and_reverse(priv_be, n, 32);
priv_be[0] &= 127;
priv_be[0] |= 64;
priv_be[31] &= 248;
gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, priv_be, 32, NULL);
if (gcry_mpi_ec_new(&ctx, NULL, "Curve25519")) {
/* Should not happen, possibly out-of-memory. */
goto leave;
}
/* Compute Q = nP */
Q = gcry_mpi_point_new(0);
P = gcry_mpi_point_set(NULL, mpi_p, NULL, GCRYMPI_CONST_ONE);
gcry_mpi_ec_mul(Q, mpi, P, ctx);
/* Note: mpi is reused to store the result. */
if (gcry_mpi_ec_get_affine(mpi, NULL, Q, ctx)) {
/* Infinity. */
goto leave;
}
if (gcry_mpi_print(GCRYMPI_FMT_USG, result_be, 32, &result_len, mpi)) {
/* Should not happen, possibly out-of-memory. */
goto leave;
}
copy_and_reverse(q, result_be, result_len);
r = 0;
leave:
gcry_mpi_point_release(P);
gcry_mpi_point_release(Q);
gcry_ctx_release(ctx);
gcry_mpi_release(mpi);
/* XXX erase priv_be and result_be */
return r;
}
int
crypto_scalarmult_curve25519(unsigned char *q, const unsigned char *n,
const unsigned char *p)
{
unsigned char p_be[32];
gcry_mpi_t mpi_p = NULL;
copy_and_reverse(p_be, p, 32);
/* Clear unused bit. */
p_be[0] &= 0x7f;
gcry_mpi_scan(&mpi_p, GCRYMPI_FMT_USG, p_be, 32, NULL);
int r = x25519_mpi(q, n, mpi_p);
gcry_mpi_release(mpi_p);
return r;
}
int
crypto_scalarmult_curve25519_base(unsigned char *q, const unsigned char *n)
{
gcry_mpi_t mpi_basepoint_x = gcry_mpi_set_ui(NULL, 9);
int r = x25519_mpi(q, n, mpi_basepoint_x);
gcry_mpi_release(mpi_basepoint_x);
return r;
}