summaryrefslogtreecommitdiffstats
path: root/comm/third_party/libgcrypt/cipher/ecc-ecdh.c
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/libgcrypt/cipher/ecc-ecdh.c')
-rw-r--r--comm/third_party/libgcrypt/cipher/ecc-ecdh.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/comm/third_party/libgcrypt/cipher/ecc-ecdh.c b/comm/third_party/libgcrypt/cipher/ecc-ecdh.c
new file mode 100644
index 0000000000..d6b8991af6
--- /dev/null
+++ b/comm/third_party/libgcrypt/cipher/ecc-ecdh.c
@@ -0,0 +1,127 @@
+/* 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 <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "mpi.h"
+#include "cipher.h"
+#include "context.h"
+#include "ec-context.h"
+#include "ecc-common.h"
+
+#define ECC_CURVE25519_BYTES 32
+#define ECC_CURVE448_BYTES 56
+
+static gpg_err_code_t
+prepare_ec (mpi_ec_t *r_ec, const char *name)
+{
+ int flags = 0;
+
+ if (!strcmp (name, "Curve25519"))
+ flags = PUBKEY_FLAG_DJB_TWEAK;
+
+ return _gcry_mpi_ec_internal_new (r_ec, &flags, "ecc_mul_point", NULL, name);
+}
+
+unsigned int
+_gcry_ecc_get_algo_keylen (int curveid)
+{
+ unsigned int len = 0;
+
+ if (curveid == GCRY_ECC_CURVE25519)
+ len = ECC_CURVE25519_BYTES;
+ else if (curveid == GCRY_ECC_CURVE448)
+ len = ECC_CURVE448_BYTES;
+
+ return len;
+}
+
+gpg_error_t
+_gcry_ecc_mul_point (int curveid, 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;
+ gcry_mpi_t mpi_k;
+ mpi_ec_t ec;
+ mpi_point_struct Q;
+ gcry_mpi_t x;
+ unsigned int len;
+ unsigned char *buf;
+
+ if (curveid == GCRY_ECC_CURVE25519)
+ curve = "Curve25519";
+ else if (curveid == GCRY_ECC_CURVE448)
+ curve = "X448";
+ else
+ return gpg_error (GPG_ERR_UNKNOWN_CURVE);
+
+ err = prepare_ec (&ec, curve);
+ if (err)
+ return err;
+
+ nbits = ec->nbits;
+ nbytes = (nbits + 7)/8;
+
+ mpi_k = _gcry_mpi_set_opaque_copy (NULL, scalar, nbytes*8);
+ x = mpi_new (nbits);
+ point_init (&Q);
+
+ if (point)
+ {
+ gcry_mpi_t mpi_u = _gcry_mpi_set_opaque_copy (NULL, point, nbytes*8);
+ mpi_point_struct P;
+
+ point_init (&P);
+ 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);
+ point_free (&P);
+ }
+ else
+ _gcry_mpi_ec_mul_point (&Q, mpi_k, ec->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 ();
+ else
+ {
+ memcpy (result, buf, nbytes);
+ xfree (buf);
+ }
+
+ leave:
+ _gcry_mpi_release (x);
+ point_free (&Q);
+ _gcry_mpi_release (mpi_k);
+ _gcry_mpi_ec_free (ec);
+ return err;
+}