diff --git a/cipher/ecc-ecdh.c b/cipher/ecc-ecdh.c
index 4f1af7a5..bfd07d40 100644
--- a/cipher/ecc-ecdh.c
+++ b/cipher/ecc-ecdh.c
@@ -1,139 +1,142 @@
/* ecc-ecdh.c - Elliptic Curve Diffie-Hellman key agreement
* Copyright (C) 2019 g10 Code GmbH
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see .
* SPDX-License-Identifier: LGPL-2.1+
*/
#include
#include
#include
#include
#include
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
#include "context.h"
#include "ec-context.h"
#include "ecc-common.h"
#define ECC_CURVE25519_BITS 256
#define ECC_CURVE448_BITS 448
static mpi_ec_t
prepare_ec (const char *curve_name, elliptic_curve_t *E)
{
mpi_ec_t ec;
memset (E, 0, sizeof *E);
if (_gcry_ecc_fill_in_curve (0, curve_name, E, NULL))
return NULL;
ec = _gcry_mpi_ec_p_internal_new (E->model, E->dialect,
PUBKEY_FLAG_DJB_TWEAK, E->p, E->a, E->b);
return ec;
}
unsigned int
_gcry_ecc_get_algo_keylen (int algo)
{
unsigned int len = 0;
if (algo == GCRY_ECC_CURVE25519)
len = ECC_CURVE25519_BITS/8;
- else
+ else if (algo == GCRY_ECC_CURVE448)
len = ECC_CURVE448_BITS/8;
return len;
}
gpg_error_t
_gcry_ecc_mul_point (int algo, unsigned char *result,
const unsigned char *scalar, const unsigned char *point)
{
unsigned int nbits;
unsigned int nbytes;
const char *curve;
gpg_err_code_t err;
elliptic_curve_t E;
unsigned char buffer[ECC_CURVE448_BITS/8];
gcry_mpi_t mpi_k;
mpi_ec_t ec;
gcry_mpi_t mpi_u;
mpi_point_t Q;
gcry_mpi_t x;
unsigned int len;
int i;
unsigned char *buf;
if (algo == GCRY_ECC_CURVE25519)
{
nbits = ECC_CURVE25519_BITS;
curve = "Curve25519";
}
- else
+ else if (algo == GCRY_ECC_CURVE448)
{
nbits = ECC_CURVE448_BITS;
curve = "X448";
+ return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
}
+ else
+ return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
nbytes = nbits / 8;
mpi_k = mpi_new (nbits);
ec = prepare_ec (curve, &E);
mpi_u = mpi_new (nbits);
Q = mpi_point_new (nbits);
x = mpi_new (nbits);
memcpy (buffer, scalar, nbytes);
reverse_buffer (buffer, nbytes);
_gcry_mpi_set_buffer (mpi_k, buffer, nbytes, 0);
for (i = 0; i < mpi_get_nbits (E.h) - 1; i++)
mpi_clear_bit (mpi_k, i);
mpi_set_highbit (mpi_k, mpi_get_nbits (E.p) - 1);
if (point)
{
mpi_point_t P = mpi_point_new (nbits);
_gcry_mpi_set_buffer (mpi_u, point, nbytes, 0);
err = _gcry_ecc_mont_decodepoint (mpi_u, ec, P);
_gcry_mpi_release (mpi_u);
if (err)
goto leave;
_gcry_mpi_ec_mul_point (Q, mpi_k, P, ec);
_gcry_mpi_point_release (P);
}
else
_gcry_mpi_ec_mul_point (Q, mpi_k, &E.G, ec);
_gcry_mpi_ec_get_affine (x, NULL, Q, ec);
buf = _gcry_mpi_get_buffer (x, nbytes, &len, NULL);
if (!buf)
err = gpg_error_from_syserror ();
memcpy (result, buf, nbytes);
xfree (buf);
leave:
_gcry_mpi_release (x);
_gcry_mpi_point_release (Q);
_gcry_mpi_release (mpi_k);
return err;
}