Coverage Report

Created: 2022-12-08 06:10

/src/libgcrypt/cipher/ecc-gost.c
Line
Count
Source (jump to first uncovered line)
1
/* ecc-gots.c  -  Elliptic Curve GOST signatures
2
 * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
3
 * Copyright (C) 2013 Dmitry Eremin-Solenikov
4
 *
5
 * This file is part of Libgcrypt.
6
 *
7
 * Libgcrypt is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation; either version 2.1 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * Libgcrypt is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
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
#include "pubkey-internal.h"
34
35
36
/* Compute an GOST R 34.10-01/-12 signature.
37
 * Return the signature struct (r,s) from the message hash.  The caller
38
 * must have allocated R and S.
39
 */
40
gpg_err_code_t
41
_gcry_ecc_gost_sign (gcry_mpi_t input, mpi_ec_t ec,
42
                     gcry_mpi_t r, gcry_mpi_t s)
43
0
{
44
0
  gpg_err_code_t rc = 0;
45
0
  gcry_mpi_t k, dr, sum, ke, x, e;
46
0
  mpi_point_struct I;
47
0
  gcry_mpi_t hash;
48
0
  unsigned int qbits;
49
50
0
  if (DBG_CIPHER)
51
0
    log_mpidump ("gost sign hash  ", input );
52
53
0
  qbits = mpi_get_nbits (ec->n);
54
55
  /* Convert the INPUT into an MPI if needed.  */
56
0
  rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
57
0
  if (rc)
58
0
    return rc;
59
60
0
  k = NULL;
61
0
  dr = mpi_alloc (0);
62
0
  sum = mpi_alloc (0);
63
0
  ke = mpi_alloc (0);
64
0
  e = mpi_alloc (0);
65
0
  x = mpi_alloc (0);
66
0
  point_init (&I);
67
68
0
  mpi_mod (e, input, ec->n); /* e = hash mod n */
69
70
0
  if (!mpi_cmp_ui (e, 0))
71
0
    mpi_set_ui (e, 1);
72
73
  /* Two loops to avoid R or S are zero.  This is more of a joke than
74
     a real demand because the probability of them being zero is less
75
     than any hardware failure.  Some specs however require it.  */
76
0
  do
77
0
    {
78
0
      do
79
0
        {
80
0
          mpi_free (k);
81
0
          k = _gcry_dsa_gen_k (ec->n, GCRY_STRONG_RANDOM);
82
83
0
          _gcry_dsa_modify_k (k, ec->n, qbits);
84
85
0
          _gcry_mpi_ec_mul_point (&I, k, ec->G, ec);
86
0
          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ec))
87
0
            {
88
0
              if (DBG_CIPHER)
89
0
                log_debug ("ecc sign: Failed to get affine coordinates\n");
90
0
              rc = GPG_ERR_BAD_SIGNATURE;
91
0
              goto leave;
92
0
            }
93
0
          mpi_mod (r, x, ec->n);  /* r = x mod n */
94
0
        }
95
0
      while (!mpi_cmp_ui (r, 0));
96
0
      mpi_mulm (dr, ec->d, r, ec->n); /* dr = d*r mod n  */
97
0
      mpi_mulm (ke, k, e, ec->n); /* ke = k*e mod n */
98
0
      mpi_addm (s, ke, dr, ec->n); /* sum = (k*e+ d*r) mod n  */
99
0
    }
100
0
  while (!mpi_cmp_ui (s, 0));
101
102
0
  if (DBG_CIPHER)
103
0
    {
104
0
      log_mpidump ("gost sign result r ", r);
105
0
      log_mpidump ("gost sign result s ", s);
106
0
    }
107
108
0
 leave:
109
0
  point_free (&I);
110
0
  mpi_free (x);
111
0
  mpi_free (e);
112
0
  mpi_free (ke);
113
0
  mpi_free (sum);
114
0
  mpi_free (dr);
115
0
  mpi_free (k);
116
117
0
  if (hash != input)
118
0
    mpi_free (hash);
119
120
0
  return rc;
121
0
}
122
123
124
/* Verify a GOST R 34.10-01/-12 signature.
125
 * Check if R and S verifies INPUT.
126
 */
127
gpg_err_code_t
128
_gcry_ecc_gost_verify (gcry_mpi_t input, mpi_ec_t ec,
129
                       gcry_mpi_t r, gcry_mpi_t s)
130
0
{
131
0
  gpg_err_code_t err = 0;
132
0
  gcry_mpi_t e, x, z1, z2, v, rv, zero;
133
0
  mpi_point_struct Q, Q1, Q2;
134
135
0
  if (!_gcry_mpi_ec_curve_point (ec->Q, ec))
136
0
    return GPG_ERR_BROKEN_PUBKEY;
137
138
0
  if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, ec->n) < 0) )
139
0
    return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < r < n  failed.  */
140
0
  if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, ec->n) < 0) )
141
0
    return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < s < n  failed.  */
142
143
0
  x = mpi_alloc (0);
144
0
  e = mpi_alloc (0);
145
0
  z1 = mpi_alloc (0);
146
0
  z2 = mpi_alloc (0);
147
0
  v = mpi_alloc (0);
148
0
  rv = mpi_alloc (0);
149
0
  zero = mpi_alloc (0);
150
151
0
  point_init (&Q);
152
0
  point_init (&Q1);
153
0
  point_init (&Q2);
154
155
0
  mpi_mod (e, input, ec->n); /* e = hash mod n */
156
0
  if (!mpi_cmp_ui (e, 0))
157
0
    mpi_set_ui (e, 1);
158
0
  mpi_invm (v, e, ec->n); /* v = e^(-1) (mod n) */
159
0
  mpi_mulm (z1, s, v, ec->n); /* z1 = s*v (mod n) */
160
0
  mpi_mulm (rv, r, v, ec->n); /* rv = r*v (mod n) */
161
0
  mpi_subm (z2, zero, rv, ec->n); /* z2 = -r*v (mod n) */
162
163
0
  _gcry_mpi_ec_mul_point (&Q1, z1, ec->G, ec);
164
/*   log_mpidump ("Q1.x", Q1.x); */
165
/*   log_mpidump ("Q1.y", Q1.y); */
166
/*   log_mpidump ("Q1.z", Q1.z); */
167
0
  _gcry_mpi_ec_mul_point (&Q2, z2, ec->Q, ec);
168
/*   log_mpidump ("Q2.x", Q2.x); */
169
/*   log_mpidump ("Q2.y", Q2.y); */
170
/*   log_mpidump ("Q2.z", Q2.z); */
171
0
  _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ec);
172
/*   log_mpidump (" Q.x", Q.x); */
173
/*   log_mpidump (" Q.y", Q.y); */
174
/*   log_mpidump (" Q.z", Q.z); */
175
176
0
  if (!mpi_cmp_ui (Q.z, 0))
177
0
    {
178
0
      if (DBG_CIPHER)
179
0
          log_debug ("ecc verify: Rejected\n");
180
0
      err = GPG_ERR_BAD_SIGNATURE;
181
0
      goto leave;
182
0
    }
183
0
  if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ec))
184
0
    {
185
0
      if (DBG_CIPHER)
186
0
        log_debug ("ecc verify: Failed to get affine coordinates\n");
187
0
      err = GPG_ERR_BAD_SIGNATURE;
188
0
      goto leave;
189
0
    }
190
0
  mpi_mod (x, x, ec->n); /* x = x mod E_n */
191
0
  if (mpi_cmp (x, r))   /* x != r */
192
0
    {
193
0
      if (DBG_CIPHER)
194
0
        {
195
0
          log_mpidump ("     x", x);
196
0
          log_mpidump ("     r", r);
197
0
          log_mpidump ("     s", s);
198
0
          log_debug ("ecc verify: Not verified\n");
199
0
        }
200
0
      err = GPG_ERR_BAD_SIGNATURE;
201
0
      goto leave;
202
0
    }
203
0
  if (DBG_CIPHER)
204
0
    log_debug ("ecc verify: Accepted\n");
205
206
0
 leave:
207
0
  point_free (&Q2);
208
0
  point_free (&Q1);
209
0
  point_free (&Q);
210
0
  mpi_free (zero);
211
0
  mpi_free (rv);
212
0
  mpi_free (v);
213
0
  mpi_free (z2);
214
0
  mpi_free (z1);
215
0
  mpi_free (x);
216
0
  mpi_free (e);
217
0
  return err;
218
0
}