Coverage Report

Created: 2022-12-08 06:09

/src/libgcrypt/cipher/ecc-ecdh.c
Line
Count
Source (jump to first uncovered line)
1
/* ecc-ecdh.c  -  Elliptic Curve Diffie-Hellman key agreement
2
 * Copyright (C) 2019 g10 Code GmbH
3
 *
4
 * This file is part of Libgcrypt.
5
 *
6
 * Libgcrypt is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as
8
 * published by the Free Software Foundation; either version 2.1 of
9
 * the License, or (at your option) any later version.
10
 *
11
 * Libgcrypt is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
18
 * SPDX-License-Identifier: LGPL-2.1+
19
 */
20
21
#include <config.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <errno.h>
26
27
#include "g10lib.h"
28
#include "mpi.h"
29
#include "cipher.h"
30
#include "context.h"
31
#include "ec-context.h"
32
#include "ecc-common.h"
33
34
0
#define ECC_CURVE25519_BYTES 32
35
0
#define ECC_CURVE448_BYTES   56
36
37
static gpg_err_code_t
38
prepare_ec (mpi_ec_t *r_ec, const char *name)
39
0
{
40
0
  int flags = 0;
41
42
0
  if (!strcmp (name, "Curve25519"))
43
0
    flags = PUBKEY_FLAG_DJB_TWEAK;
44
45
0
  return _gcry_mpi_ec_internal_new (r_ec, &flags, "ecc_mul_point", NULL, name);
46
0
}
47
48
unsigned int
49
_gcry_ecc_get_algo_keylen (int curveid)
50
0
{
51
0
  unsigned int len = 0;
52
53
0
  if (curveid == GCRY_ECC_CURVE25519)
54
0
    len = ECC_CURVE25519_BYTES;
55
0
  else if (curveid == GCRY_ECC_CURVE448)
56
0
    len = ECC_CURVE448_BYTES;
57
58
0
  return len;
59
0
}
60
61
gpg_error_t
62
_gcry_ecc_mul_point (int curveid, unsigned char *result,
63
                     const unsigned char *scalar, const unsigned char *point)
64
0
{
65
0
  unsigned int nbits;
66
0
  unsigned int nbytes;
67
0
  const char *curve;
68
0
  gpg_err_code_t err;
69
0
  gcry_mpi_t mpi_k;
70
0
  mpi_ec_t ec;
71
0
  mpi_point_struct Q;
72
0
  gcry_mpi_t x;
73
0
  unsigned int len;
74
0
  unsigned char *buf;
75
76
0
  if (curveid == GCRY_ECC_CURVE25519)
77
0
    curve = "Curve25519";
78
0
  else if (curveid == GCRY_ECC_CURVE448)
79
0
    curve = "X448";
80
0
  else
81
0
    return gpg_error (GPG_ERR_UNKNOWN_CURVE);
82
83
0
  err = prepare_ec (&ec, curve);
84
0
  if (err)
85
0
    return err;
86
87
0
  nbits = ec->nbits;
88
0
  nbytes = (nbits + 7)/8;
89
90
0
  mpi_k = _gcry_mpi_set_opaque_copy (NULL, scalar, nbytes*8);
91
0
  x = mpi_new (nbits);
92
0
  point_init (&Q);
93
94
0
  if (point)
95
0
    {
96
0
      gcry_mpi_t mpi_u = _gcry_mpi_set_opaque_copy (NULL, point, nbytes*8);
97
0
      mpi_point_struct P;
98
99
0
      point_init (&P);
100
0
      err = _gcry_ecc_mont_decodepoint (mpi_u, ec, &P);
101
0
      _gcry_mpi_release (mpi_u);
102
0
      if (err)
103
0
        goto leave;
104
0
      _gcry_mpi_ec_mul_point (&Q, mpi_k, &P, ec);
105
0
      point_free (&P);
106
0
    }
107
0
  else
108
0
    _gcry_mpi_ec_mul_point (&Q, mpi_k, ec->G, ec);
109
110
0
  _gcry_mpi_ec_get_affine (x, NULL, &Q, ec);
111
112
0
  buf = _gcry_mpi_get_buffer (x, nbytes, &len, NULL);
113
0
  if (!buf)
114
0
    err = gpg_error_from_syserror ();
115
0
  else
116
0
    {
117
0
      memcpy (result, buf, nbytes);
118
0
      xfree (buf);
119
0
    }
120
121
0
 leave:
122
0
  _gcry_mpi_release (x);
123
0
  point_free (&Q);
124
0
  _gcry_mpi_release (mpi_k);
125
0
  _gcry_mpi_ec_free (ec);
126
0
  return err;
127
0
}