Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/nettle/int/dsa-validate.c
Line
Count
Source (jump to first uncovered line)
1
/* dsa-keygen.c
2
 *
3
 * Generation of DSA keypairs
4
 */
5
6
/* nettle, low-level cryptographics library
7
 *
8
 * Copyright (C) 2013 Red Hat
9
 *  
10
 * The nettle library is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU Lesser General Public License as published by
12
 * the Free Software Foundation; either version 2.1 of the License, or (at your
13
 * option) any later version.
14
 * 
15
 * The nettle library is distributed in the hope that it will be useful, but
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
18
 * License for more details.
19
 * 
20
 * You should have received a copy of the GNU Lesser General Public License
21
 * along with the nettle library.  If not, see <https://www.gnu.org/licenses/>.
22
 */
23
24
#if HAVE_CONFIG_H
25
#include "config.h"
26
#endif
27
28
#include <stdlib.h>
29
#include <string.h>
30
31
#include <nettle/dsa.h>
32
#include "dsa-fips.h"
33
34
#include <nettle/bignum.h>
35
36
/* This validates the given p, q, g params using the provided
37
 * dss_params_validation_seeds.
38
 * 
39
 * The hash function used is SHA384.
40
 * 
41
 * pub: The output public key
42
 * key: The output private key
43
 * cert: A certificate that can be used to verify the generated parameters
44
 * index: 1 for digital signatures (DSA), 2 for key establishment (DH)
45
 * 
46
 */
47
int dsa_validate_dss_pqg(struct dsa_params *pub,
48
       struct dss_params_validation_seeds *cert,
49
       unsigned index)
50
0
{
51
0
  int ret;
52
0
  uint8_t domain_seed[MAX_PVP_SEED_SIZE * 3];
53
0
  unsigned domain_seed_size = 0;
54
55
0
  ret = _dsa_validate_dss_pq(pub, cert);
56
0
  if (ret == 0)
57
0
    return 0;
58
59
0
  domain_seed_size =
60
0
    cert->seed_length + cert->qseed_length + cert->pseed_length;
61
0
  memcpy(domain_seed, cert->seed, cert->seed_length);
62
0
  memcpy(&domain_seed[cert->seed_length], cert->pseed,
63
0
         cert->pseed_length);
64
0
  memcpy(&domain_seed[cert->seed_length + cert->pseed_length],
65
0
         cert->qseed, cert->qseed_length);
66
67
0
  ret = _dsa_validate_dss_g(pub, domain_seed_size, domain_seed, index);
68
0
  if (ret == 0)
69
0
    return 0;
70
71
0
  return 1;
72
0
}
73
74
int _dsa_validate_dss_g(struct dsa_params *pub, unsigned domain_seed_size,
75
      const uint8_t *domain_seed, unsigned index)
76
0
{
77
0
  int ret;
78
0
  unsigned p_bits, q_bits;
79
0
  struct dsa_params pub2;
80
0
  mpz_t r;
81
82
0
  p_bits = mpz_sizeinbase(pub->p, 2);
83
0
  q_bits = mpz_sizeinbase(pub->q, 2);
84
85
0
  ret = _dsa_check_qp_sizes(q_bits, p_bits, 0);
86
0
  if (ret == 0) {
87
0
    return 0;
88
0
  }
89
90
0
  mpz_init(r);
91
0
  dsa_params_init(&pub2);
92
93
0
  mpz_set(pub2.p, pub->p);
94
0
  mpz_set(pub2.q, pub->q);
95
96
  /* verify g */
97
0
  if (index > 255) {
98
0
    goto fail;
99
0
  }
100
101
  /* 2<= g <= p-1 */
102
0
  mpz_set(r, pub->p);
103
0
  mpz_sub_ui(r, r, 1);
104
0
  if (mpz_cmp_ui(pub->g, 2) < 0 || mpz_cmp(pub->g, r) >= 0) {
105
0
    goto fail;
106
0
  }
107
108
  /* g^q == 1 mod p */
109
0
  mpz_powm(r, pub->g, pub->q, pub->p);
110
0
  if (mpz_cmp_ui(r, 1) != 0) {
111
0
    goto fail;
112
0
  }
113
114
  /* repeat g generation */
115
0
  ret = _dsa_generate_dss_g(&pub2, domain_seed_size, domain_seed, NULL,
116
0
          NULL, index);
117
0
  if (ret == 0) {
118
0
    goto fail;
119
0
  }
120
121
0
  if (mpz_cmp(pub->g, pub2.g) != 0) {
122
0
    goto fail;
123
0
  }
124
125
  /* everything looks ok */
126
0
  ret = 1;
127
0
  goto finish;
128
129
0
fail:
130
0
  ret = 0;
131
132
0
finish:
133
0
  dsa_params_clear(&pub2);
134
0
  mpz_clear(r);
135
136
0
  return ret;
137
0
}
138
139
int _dsa_validate_dss_pq(struct dsa_params *pub,
140
       struct dss_params_validation_seeds *cert)
141
0
{
142
0
  int ret;
143
0
  unsigned p_bits, q_bits;
144
0
  struct dsa_params pub2;
145
0
  struct dss_params_validation_seeds cert2;
146
0
  mpz_t r, s;
147
148
0
  p_bits = mpz_sizeinbase(pub->p, 2);
149
0
  q_bits = mpz_sizeinbase(pub->q, 2);
150
151
0
  ret = _dsa_check_qp_sizes(q_bits, p_bits, 0);
152
0
  if (ret == 0) {
153
0
    return 0;
154
0
  }
155
156
0
  mpz_init(r);
157
0
  mpz_init(s);
158
0
  dsa_params_init(&pub2);
159
160
0
  nettle_mpz_set_str_256_u(s, cert->seed_length, cert->seed);
161
162
  /* firstseed < 2^(N-1) */
163
0
  mpz_set_ui(r, 1);
164
0
  mpz_mul_2exp(r, r, q_bits - 1);
165
166
0
  if (mpz_cmp(s, r) < 0) {
167
0
    goto fail;
168
0
  }
169
170
  /* 2^N <= q */
171
0
  mpz_set_ui(r, 1);
172
0
  mpz_mul_2exp(r, r, q_bits);
173
174
0
  if (mpz_cmp(r, pub->q) <= 0) {
175
0
    goto fail;
176
0
  }
177
178
  /* 2^L <= p */
179
0
  mpz_set_ui(r, 1);
180
0
  mpz_mul_2exp(r, r, p_bits);
181
182
0
  if (mpz_cmp(r, pub->p) <= 0) {
183
0
    goto fail;
184
0
  }
185
186
  /* p-1 mod q != 0 */
187
0
  mpz_set(r, pub->p);
188
0
  mpz_sub_ui(r, r, 1);
189
190
0
  mpz_mod(r, r, pub->q);
191
0
  if (mpz_cmp_ui(r, 0) != 0) {
192
0
    goto fail;
193
0
  }
194
195
  /* replay the construction */
196
0
  ret = _dsa_generate_dss_pq(&pub2, &cert2, cert->seed_length, cert->seed,
197
0
           NULL, NULL, p_bits, q_bits);
198
0
  if (ret == 0) {
199
0
    goto fail;
200
0
  }
201
202
0
  if ((cert->pseed_length > 0 &&
203
0
       cert->pseed_length != cert2.pseed_length) ||
204
0
      (cert->qseed_length > 0 &&
205
0
       cert->qseed_length != cert2.qseed_length) ||
206
0
      (cert->pgen_counter > 0 &&
207
0
       cert->pgen_counter != cert2.pgen_counter) ||
208
0
      (cert->qgen_counter > 0 &&
209
0
       cert->qgen_counter != cert2.qgen_counter) ||
210
0
      (cert->qseed_length > 0 &&
211
0
       memcmp(cert->qseed, cert2.qseed, cert2.qseed_length) != 0) ||
212
0
      (cert->pseed_length > 0 &&
213
0
       memcmp(cert->pseed, cert2.pseed, cert2.pseed_length) != 0)) {
214
0
    goto fail;
215
0
  }
216
217
0
  if (mpz_cmp(pub->q, pub2.q) != 0) {
218
0
    goto fail;
219
0
  }
220
221
0
  if (mpz_cmp(pub->p, pub2.p) != 0) {
222
0
    goto fail;
223
0
  }
224
225
0
  if (mpz_sizeinbase(s, 2) < q_bits - 1) {
226
0
    goto fail;
227
0
  }
228
229
0
  ret = 1;
230
0
  goto finish;
231
232
0
fail:
233
0
  ret = 0;
234
235
0
finish:
236
0
  dsa_params_clear(&pub2);
237
0
  mpz_clear(r);
238
0
  mpz_clear(s);
239
240
0
  return ret;
241
0
}