Coverage Report

Created: 2026-10-27 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/dsa/dsa.cc
Line
Count
Source
1
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/dsa.h>
16
17
#include <string.h>
18
19
#include <utility>
20
21
#include <openssl/bn.h>
22
#include <openssl/dh.h>
23
#include <openssl/digest.h>
24
#include <openssl/engine.h>
25
#include <openssl/err.h>
26
#include <openssl/ex_data.h>
27
#include <openssl/mem.h>
28
#include <openssl/rand.h>
29
#include <openssl/sha2.h>
30
31
#include "../fipsmodule/bn/internal.h"
32
#include "../fipsmodule/dh/internal.h"
33
#include "../internal.h"
34
#include "../mem_internal.h"
35
#include "internal.h"
36
37
38
using namespace bssl;
39
40
static_assert(OPENSSL_DSA_MAX_MODULUS_BITS <=
41
                  BN_MONTGOMERY_MAX_WORDS * BN_BITS2,
42
              "Max DSA size too big for Montgomery arithmetic");
43
44
// Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of
45
// Miller-Rabin.
46
0
#define DSS_prime_checks 50
47
48
static int dsa_sign_setup(const DSAImpl *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
49
                          BIGNUM **out_r);
50
51
static ExDataClass g_ex_data_class;
52
53
6.84k
DSA *DSA_new() { return New<DSAImpl>(); }
54
55
6.84k
DSAImpl::DSAImpl() : RefCounted(CheckSubClass()) {
56
6.84k
  CRYPTO_new_ex_data(&ex_data);
57
6.84k
}
58
59
6.84k
DSAImpl::~DSAImpl() { CRYPTO_free_ex_data(&g_ex_data_class, &ex_data); }
60
61
906
void DSA_free(DSA *dsa) {
62
906
  if (dsa == nullptr) {
63
0
    return;
64
0
  }
65
906
  auto *impl = FromOpaque(dsa);
66
906
  impl->DecRefInternal();
67
906
}
68
69
0
int DSA_up_ref(DSA *dsa) {
70
0
  auto *impl = FromOpaque(dsa);
71
0
  impl->UpRefInternal();
72
0
  return 1;
73
0
}
74
75
0
DSA *DSA_dup_ref(const DSA *dsa) {
76
0
  if (dsa == nullptr) {
77
0
    return nullptr;
78
0
  }
79
0
  return FromOpaque(dsa)->DupRefInternal();
80
0
}
81
82
0
unsigned DSA_bits(const DSA *dsa) {
83
0
  return BN_num_bits(FromOpaque(dsa)->p.get());
84
0
}
85
86
0
const BIGNUM *DSA_get0_pub_key(const DSA *dsa) {
87
0
  return FromOpaque(dsa)->pub_key.get();
88
0
}
89
90
0
const BIGNUM *DSA_get0_priv_key(const DSA *dsa) {
91
0
  return FromOpaque(dsa)->priv_key.get();
92
0
}
93
94
0
const BIGNUM *DSA_get0_p(const DSA *dsa) { return FromOpaque(dsa)->p.get(); }
95
96
0
const BIGNUM *DSA_get0_q(const DSA *dsa) { return FromOpaque(dsa)->q.get(); }
97
98
0
const BIGNUM *DSA_get0_g(const DSA *dsa) { return FromOpaque(dsa)->g.get(); }
99
100
void DSA_get0_key(const DSA *dsa, const BIGNUM **out_pub_key,
101
0
                  const BIGNUM **out_priv_key) {
102
0
  auto *impl = FromOpaque(dsa);
103
0
  if (out_pub_key != nullptr) {
104
0
    *out_pub_key = impl->pub_key.get();
105
0
  }
106
0
  if (out_priv_key != nullptr) {
107
0
    *out_priv_key = impl->priv_key.get();
108
0
  }
109
0
}
110
111
void DSA_get0_pqg(const DSA *dsa, const BIGNUM **out_p, const BIGNUM **out_q,
112
0
                  const BIGNUM **out_g) {
113
0
  auto *impl = FromOpaque(dsa);
114
0
  if (out_p != nullptr) {
115
0
    *out_p = impl->p.get();
116
0
  }
117
0
  if (out_q != nullptr) {
118
0
    *out_q = impl->q.get();
119
0
  }
120
0
  if (out_g != nullptr) {
121
0
    *out_g = impl->g.get();
122
0
  }
123
0
}
124
125
0
int DSA_set0_key(DSA *dsa, BIGNUM *pub_key, BIGNUM *priv_key) {
126
0
  auto *impl = FromOpaque(dsa);
127
128
0
  if (impl->pub_key == nullptr && pub_key == nullptr) {
129
0
    return 0;
130
0
  }
131
132
0
  if (pub_key != nullptr) {
133
0
    impl->pub_key.reset(pub_key);
134
0
  }
135
0
  if (priv_key != nullptr) {
136
0
    impl->priv_key.reset(priv_key);
137
0
  }
138
139
0
  return 1;
140
0
}
141
142
0
int DSA_set0_pqg(DSA *dsa, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
143
0
  auto *impl = FromOpaque(dsa);
144
145
0
  if ((impl->p == nullptr && p == nullptr) ||
146
0
      (impl->q == nullptr && q == nullptr) ||
147
0
      (impl->g == nullptr && g == nullptr)) {
148
0
    return 0;
149
0
  }
150
151
0
  if (p != nullptr) {
152
0
    impl->p.reset(p);
153
0
  }
154
0
  if (q != nullptr) {
155
0
    impl->q.reset(q);
156
0
  }
157
0
  if (g != nullptr) {
158
0
    impl->g.reset(g);
159
0
  }
160
161
0
  impl->method_mont_p = nullptr;
162
0
  impl->method_mont_q = nullptr;
163
0
  return 1;
164
0
}
165
166
int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
167
                               size_t seed_len, int *out_counter,
168
0
                               unsigned long *out_h, BN_GENCB *cb) {
169
0
  auto *impl = FromOpaque(dsa);
170
171
0
  if (bits > OPENSSL_DSA_MAX_MODULUS_BITS) {
172
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_INVALID_PARAMETERS);
173
0
    return 0;
174
0
  }
175
176
0
  unsigned char seed[SHA256_DIGEST_LENGTH];
177
0
  unsigned char md[SHA256_DIGEST_LENGTH];
178
0
  unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
179
0
  BIGNUM *r0, *W, *X, *c, *test;
180
0
  BIGNUM *g = nullptr, *q = nullptr, *p = nullptr;
181
0
  int k, n = 0, m = 0;
182
0
  int counter = 0;
183
0
  int r = 0;
184
0
  unsigned int h = 2;
185
0
  const EVP_MD *evpmd;
186
187
0
  evpmd = (bits >= 2048) ? EVP_sha256() : EVP_sha1();
188
0
  size_t qsize = EVP_MD_size(evpmd);
189
190
0
  if (bits < 512) {
191
0
    bits = 512;
192
0
  }
193
194
0
  bits = (bits + 63) / 64 * 64;
195
196
0
  if (seed_in != nullptr) {
197
0
    if (seed_len < qsize) {
198
0
      return 0;
199
0
    }
200
0
    if (seed_len > qsize) {
201
      // Only consume as much seed as is expected.
202
0
      seed_len = qsize;
203
0
    }
204
0
    OPENSSL_memcpy(seed, seed_in, seed_len);
205
0
  }
206
207
0
  UniquePtr<BN_CTX> ctx(BN_CTX_new());
208
0
  if (ctx == nullptr) {
209
0
    return 0;
210
0
  }
211
0
  BN_CTXScope scope(ctx.get());
212
213
0
  r0 = BN_CTX_get(ctx.get());
214
0
  g = BN_CTX_get(ctx.get());
215
0
  W = BN_CTX_get(ctx.get());
216
0
  q = BN_CTX_get(ctx.get());
217
0
  X = BN_CTX_get(ctx.get());
218
0
  c = BN_CTX_get(ctx.get());
219
0
  p = BN_CTX_get(ctx.get());
220
0
  test = BN_CTX_get(ctx.get());
221
222
0
  if (test == nullptr || !BN_lshift(test, BN_value_one(), bits - 1)) {
223
0
    return 0;
224
0
  }
225
226
0
  for (;;) {
227
    // Find q.
228
0
    for (;;) {
229
      // step 1
230
0
      if (!BN_GENCB_call(cb, BN_GENCB_GENERATED, m++)) {
231
0
        return 0;
232
0
      }
233
234
0
      int use_random_seed = (seed_in == nullptr);
235
0
      if (use_random_seed) {
236
0
        if (!RAND_bytes(seed, qsize)) {
237
0
          return 0;
238
0
        }
239
        // DSA parameters are public.
240
0
        CONSTTIME_DECLASSIFY(seed, qsize);
241
0
      } else {
242
        // If we come back through, use random seed next time.
243
0
        seed_in = nullptr;
244
0
      }
245
0
      OPENSSL_memcpy(buf, seed, qsize);
246
0
      OPENSSL_memcpy(buf2, seed, qsize);
247
      // precompute "SEED + 1" for step 7:
248
0
      for (size_t i = qsize - 1; i < qsize; i--) {
249
0
        buf[i]++;
250
0
        if (buf[i] != 0) {
251
0
          break;
252
0
        }
253
0
      }
254
255
      // step 2
256
0
      if (!EVP_Digest(seed, qsize, md, nullptr, evpmd, nullptr) ||
257
0
          !EVP_Digest(buf, qsize, buf2, nullptr, evpmd, nullptr)) {
258
0
        return 0;
259
0
      }
260
0
      for (size_t i = 0; i < qsize; i++) {
261
0
        md[i] ^= buf2[i];
262
0
      }
263
264
      // step 3
265
0
      md[0] |= 0x80;
266
0
      md[qsize - 1] |= 0x01;
267
0
      if (!BN_bin2bn(md, qsize, q)) {
268
0
        return 0;
269
0
      }
270
271
      // step 4
272
0
      r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx.get(),
273
0
                                  use_random_seed, cb);
274
0
      if (r > 0) {
275
0
        break;
276
0
      }
277
0
      if (r != 0) {
278
0
        return 0;
279
0
      }
280
281
      // do a callback call
282
      // step 5
283
0
    }
284
285
0
    if (!BN_GENCB_call(cb, 2, 0) || !BN_GENCB_call(cb, 3, 0)) {
286
0
      return 0;
287
0
    }
288
289
    // step 6
290
0
    counter = 0;
291
    // "offset = 2"
292
293
0
    n = (bits - 1) / 160;
294
295
0
    for (;;) {
296
0
      if ((counter != 0) && !BN_GENCB_call(cb, BN_GENCB_GENERATED, counter)) {
297
0
        return 0;
298
0
      }
299
300
      // step 7
301
0
      BN_zero(W);
302
      // now 'buf' contains "SEED + offset - 1"
303
0
      for (k = 0; k <= n; k++) {
304
        // obtain "SEED + offset + k" by incrementing:
305
0
        for (size_t i = qsize - 1; i < qsize; i--) {
306
0
          buf[i]++;
307
0
          if (buf[i] != 0) {
308
0
            break;
309
0
          }
310
0
        }
311
312
0
        if (!EVP_Digest(buf, qsize, md, nullptr, evpmd, nullptr)) {
313
0
          return 0;
314
0
        }
315
316
        // step 8
317
0
        if (!BN_bin2bn(md, qsize, r0) || !BN_lshift(r0, r0, (qsize << 3) * k) ||
318
0
            !BN_add(W, W, r0)) {
319
0
          return 0;
320
0
        }
321
0
      }
322
323
      // more of step 8
324
0
      if (!BN_mask_bits(W, bits - 1) || !BN_copy(X, W) || !BN_add(X, X, test)) {
325
0
        return 0;
326
0
      }
327
328
      // step 9
329
0
      if (!BN_lshift1(r0, q) || !BN_mod(c, X, r0, ctx.get()) ||
330
0
          !BN_sub(r0, c, BN_value_one()) || !BN_sub(p, X, r0)) {
331
0
        return 0;
332
0
      }
333
334
      // step 10
335
0
      if (BN_cmp(p, test) >= 0) {
336
        // step 11
337
0
        r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx.get(), 1, cb);
338
0
        if (r > 0) {
339
0
          goto end;  // found it
340
0
        }
341
0
        if (r != 0) {
342
0
          return 0;
343
0
        }
344
0
      }
345
346
      // step 13
347
0
      counter++;
348
      // "offset = offset + n + 1"
349
350
      // step 14
351
0
      if (counter >= 4096) {
352
0
        break;
353
0
      }
354
0
    }
355
0
  }
356
0
end:
357
0
  if (!BN_GENCB_call(cb, 2, 1)) {
358
0
    return 0;
359
0
  }
360
361
  // We now need to generate g
362
  // Set r0=(p-1)/q
363
0
  if (!BN_sub(test, p, BN_value_one()) ||
364
0
      !BN_div(r0, nullptr, test, q, ctx.get())) {
365
0
    return 0;
366
0
  }
367
368
0
  UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new_for_modulus(p, ctx.get()));
369
0
  if (mont == nullptr || !BN_set_word(test, h)) {
370
0
    return 0;
371
0
  }
372
373
0
  for (;;) {
374
    // g=test^r0%p
375
0
    if (!BN_mod_exp_mont(g, test, r0, p, ctx.get(), mont.get())) {
376
0
      return 0;
377
0
    }
378
0
    if (!BN_is_one(g)) {
379
0
      break;
380
0
    }
381
0
    if (!BN_add(test, test, BN_value_one())) {
382
0
      return 0;
383
0
    }
384
0
    h++;
385
0
  }
386
387
0
  if (!BN_GENCB_call(cb, 3, 1)) {
388
0
    return 0;
389
0
  }
390
391
0
  impl->p.reset(BN_dup(p));
392
0
  impl->q.reset(BN_dup(q));
393
0
  impl->g.reset(BN_dup(g));
394
0
  if (impl->p == nullptr || impl->q == nullptr || impl->g == nullptr) {
395
0
    return 0;
396
0
  }
397
0
  if (out_counter != nullptr) {
398
0
    *out_counter = counter;
399
0
  }
400
0
  if (out_h != nullptr) {
401
0
    *out_h = h;
402
0
  }
403
404
0
  return 1;
405
0
}
406
407
0
DSA *DSAparams_dup(const DSA *dsa) {
408
0
  auto *impl = FromOpaque(dsa);
409
0
  DSAImpl *ret = FromOpaque(DSA_new());
410
0
  if (ret == nullptr) {
411
0
    return nullptr;
412
0
  }
413
0
  ret->p.reset(BN_dup(impl->p.get()));
414
0
  ret->q.reset(BN_dup(impl->q.get()));
415
0
  ret->g.reset(BN_dup(impl->g.get()));
416
0
  if (ret->p == nullptr || ret->q == nullptr || ret->g == nullptr) {
417
0
    DSA_free(ret);
418
0
    return nullptr;
419
0
  }
420
0
  return ret;
421
0
}
422
423
0
int DSA_generate_key(DSA *dsa) {
424
0
  auto *impl = FromOpaque(dsa);
425
426
0
  if (!dsa_check_key(impl)) {
427
0
    return 0;
428
0
  }
429
430
0
  UniquePtr<BN_CTX> ctx(BN_CTX_new());
431
0
  UniquePtr<BIGNUM> pub_key(BN_new()), priv_key(BN_new());
432
0
  if (ctx == nullptr || pub_key == nullptr || priv_key == nullptr) {
433
0
    return 0;
434
0
  }
435
436
0
  if (!BN_rand_range_ex(priv_key.get(), 1, impl->q.get()) ||
437
0
      !BN_MONT_CTX_set_locked(&impl->method_mont_p, &impl->method_mont_lock,
438
0
                              impl->p.get(), ctx.get()) ||
439
0
      !BN_mod_exp_mont_consttime(pub_key.get(), impl->g.get(), priv_key.get(),
440
0
                                 impl->p.get(), ctx.get(),
441
0
                                 impl->method_mont_p.get())) {
442
0
    return 0;
443
0
  }
444
445
  // The public key is computed from the private key, but is public.
446
0
  bn_declassify(pub_key.get());
447
448
0
  impl->priv_key = std::move(priv_key);
449
0
  impl->pub_key = std::move(pub_key);
450
0
  return 1;
451
0
}
452
453
0
DSA_SIG *DSA_SIG_new() { return New<DSA_SIG>(); }
454
455
0
void DSA_SIG_free(DSA_SIG *sig) {
456
0
  if (!sig) {
457
0
    return;
458
0
  }
459
460
0
  BN_free(sig->r);
461
0
  BN_free(sig->s);
462
0
  Delete(sig);
463
0
}
464
465
void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **out_r,
466
0
                  const BIGNUM **out_s) {
467
0
  if (out_r != nullptr) {
468
0
    *out_r = sig->r;
469
0
  }
470
0
  if (out_s != nullptr) {
471
0
    *out_s = sig->s;
472
0
  }
473
0
}
474
475
0
int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) {
476
0
  if (r == nullptr || s == nullptr) {
477
0
    return 0;
478
0
  }
479
0
  BN_free(sig->r);
480
0
  BN_free(sig->s);
481
0
  sig->r = r;
482
0
  sig->s = s;
483
0
  return 1;
484
0
}
485
486
// mod_mul_consttime sets `r` to `a` * `b` modulo `mont->N`, treating `a` and
487
// `b` as secret. This function internally uses Montgomery reduction, but
488
// neither inputs nor outputs are in Montgomery form.
489
static int mod_mul_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
490
0
                             const BN_MONT_CTX *mont, BN_CTX *ctx) {
491
0
  BN_CTXScope scope(ctx);
492
0
  BIGNUM *tmp = BN_CTX_get(ctx);
493
  // `BN_mod_mul_montgomery` removes a factor of R, so we cancel it with a
494
  // single `BN_to_montgomery` which adds one factor of R.
495
0
  return tmp != nullptr &&  //
496
0
         BN_to_montgomery(tmp, a, mont, ctx) &&
497
0
         BN_mod_mul_montgomery(r, tmp, b, mont, ctx);
498
0
}
499
500
0
DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, const DSA *dsa) {
501
0
  auto *impl = FromOpaque(dsa);
502
503
0
  if (!dsa_check_key(impl)) {
504
0
    return nullptr;
505
0
  }
506
507
0
  if (impl->priv_key == nullptr) {
508
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS);
509
0
    return nullptr;
510
0
  }
511
512
0
  BIGNUM *kinv = nullptr, *r = nullptr, *s = nullptr;
513
0
  BIGNUM m;
514
0
  BIGNUM xr;
515
0
  BN_CTX *ctx = nullptr;
516
0
  DSA_SIG *ret = nullptr;
517
518
0
  BN_init(&m);
519
0
  BN_init(&xr);
520
0
  s = BN_new();
521
0
  {
522
0
    if (s == nullptr) {
523
0
      goto err;
524
0
    }
525
0
    ctx = BN_CTX_new();
526
0
    if (ctx == nullptr) {
527
0
      goto err;
528
0
    }
529
530
    // Cap iterations so that invalid parameters do not infinite loop. This does
531
    // not impact valid parameters because the probability of requiring even one
532
    // retry is negligible, let alone 32. Unfortunately, DSA was mis-specified,
533
    // so invalid parameters are reachable from most callers handling untrusted
534
    // private keys. (The `dsa_check_key` call above is not sufficient. Checking
535
    // whether arbitrary parameters form a valid DSA group is expensive.)
536
0
    static const int kMaxIterations = 32;
537
0
    int iters = 0;
538
0
  redo:
539
0
    if (!dsa_sign_setup(impl, ctx, &kinv, &r)) {
540
0
      goto err;
541
0
    }
542
543
0
    if (digest_len > BN_num_bytes(impl->q.get())) {
544
      // If the digest length is greater than the size of `impl->q` use the
545
      // BN_num_bits(impl->q) leftmost bits of the digest, see FIPS 186-3, 4.2.
546
      // Note the above check that `impl->q` is a multiple of 8 bits.
547
0
      digest_len = BN_num_bytes(impl->q.get());
548
0
    }
549
550
0
    if (BN_bin2bn(digest, digest_len, &m) == nullptr) {
551
0
      goto err;
552
0
    }
553
554
    // `m` is bounded by 2^(num_bits(q)), which is slightly looser than q. This
555
    // violates `bn_mod_add_consttime` and `mod_mul_consttime`'s preconditions.
556
    // (The underlying algorithms could accept looser bounds, but we reduce for
557
    // simplicity.)
558
0
    size_t q_width = bn_minimal_width(impl->q.get());
559
0
    if (!bn_resize_words(&m, q_width) || !bn_resize_words(&xr, q_width)) {
560
0
      goto err;
561
0
    }
562
0
    bn_reduce_once_in_place(m.d, 0 /* no carry word */, impl->q->d,
563
0
                            xr.d /* scratch space */, q_width);
564
565
    // Compute s = inv(k) (m + xr) mod q. Note `impl->method_mont_q` is
566
    // initialized by `dsa_sign_setup`.
567
0
    if (!mod_mul_consttime(&xr, impl->priv_key.get(), r,
568
0
                           impl->method_mont_q.get(), ctx) ||
569
0
        !bn_mod_add_consttime(s, &xr, &m, impl->q.get(), ctx) ||
570
0
        !mod_mul_consttime(s, s, kinv, impl->method_mont_q.get(), ctx)) {
571
0
      goto err;
572
0
    }
573
574
    // The signature is computed from the private key, but is public.
575
0
    bn_declassify(r);
576
0
    bn_declassify(s);
577
578
    // Redo if r or s is zero as required by FIPS 186-3: this is
579
    // very unlikely.
580
0
    if (BN_is_zero(r) || BN_is_zero(s)) {
581
0
      iters++;
582
0
      if (iters > kMaxIterations) {
583
0
        OPENSSL_PUT_ERROR(DSA, DSA_R_TOO_MANY_ITERATIONS);
584
0
        goto err;
585
0
      }
586
0
      goto redo;
587
0
    }
588
589
0
    ret = DSA_SIG_new();
590
0
    if (ret == nullptr) {
591
0
      goto err;
592
0
    }
593
0
    ret->r = r;
594
0
    ret->s = s;
595
0
  }
596
597
0
err:
598
0
  if (ret == nullptr) {
599
0
    OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB);
600
0
    BN_free(r);
601
0
    BN_free(s);
602
0
  }
603
0
  BN_CTX_free(ctx);
604
0
  BN_clear_free(&m);
605
0
  BN_clear_free(&xr);
606
0
  BN_clear_free(kinv);
607
608
0
  return ret;
609
0
}
610
611
int DSA_do_verify(const uint8_t *digest, size_t digest_len, const DSA_SIG *sig,
612
0
                  const DSA *dsa) {
613
0
  int valid;
614
0
  if (!DSA_do_check_signature(&valid, digest, digest_len, sig, dsa)) {
615
0
    return -1;
616
0
  }
617
0
  return valid;
618
0
}
619
620
int DSA_do_check_signature(int *out_valid, const uint8_t *digest,
621
                           size_t digest_len, const DSA_SIG *sig,
622
0
                           const DSA *dsa) {
623
0
  auto *impl = FromOpaque(dsa);
624
625
0
  *out_valid = 0;
626
0
  if (!dsa_check_key(impl)) {
627
0
    return 0;
628
0
  }
629
630
0
  if (impl->pub_key == nullptr) {
631
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS);
632
0
    return 0;
633
0
  }
634
635
0
  int ret = 0;
636
0
  BIGNUM u1, u2, t1;
637
0
  BN_init(&u1);
638
0
  BN_init(&u2);
639
0
  BN_init(&t1);
640
0
  BN_CTX *ctx = BN_CTX_new();
641
0
  {
642
0
    if (ctx == nullptr) {
643
0
      goto err;
644
0
    }
645
646
0
    if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
647
0
        BN_ucmp(sig->r, impl->q.get()) >= 0) {
648
0
      ret = 1;
649
0
      goto err;
650
0
    }
651
0
    if (BN_is_zero(sig->s) || BN_is_negative(sig->s) ||
652
0
        BN_ucmp(sig->s, impl->q.get()) >= 0) {
653
0
      ret = 1;
654
0
      goto err;
655
0
    }
656
657
0
    if (!BN_MONT_CTX_set_locked(&impl->method_mont_p, &impl->method_mont_lock,
658
0
                                impl->p.get(), ctx) ||
659
0
        !BN_MONT_CTX_set_locked(&impl->method_mont_q, &impl->method_mont_lock,
660
0
                                impl->q.get(), ctx)) {
661
0
      goto err;
662
0
    }
663
664
    // Calculate W = inv(S) mod Q, in the Montgomery domain. This is slightly
665
    // more efficiently computed as FromMont(s)^-1 = (s * R^-1)^-1 = s^-1 * R,
666
    // instead of ToMont(s^-1) = s^-1 * R.
667
0
    if (!BN_from_montgomery(&u2, sig->s, impl->method_mont_q.get(), ctx) ||
668
0
        !BN_mod_inverse(&u2, &u2, impl->q.get(), ctx)) {
669
0
      goto err;
670
0
    }
671
672
    // save M in u1
673
0
    unsigned q_bits = BN_num_bits(impl->q.get());
674
0
    if (digest_len > (q_bits >> 3)) {
675
      // if the digest length is greater than the size of q use the
676
      // BN_num_bits(impl->q) leftmost bits of the digest, see
677
      // fips 186-3, 4.2
678
0
      digest_len = (q_bits >> 3);
679
0
    }
680
681
0
    if (BN_bin2bn(digest, digest_len, &u1) == nullptr) {
682
0
      goto err;
683
0
    }
684
685
    // u1 = M * w mod q. w was stored in the Montgomery domain while M was not,
686
    // so the result will already be out of the Montgomery domain.
687
0
    if (!BN_mod_mul_montgomery(&u1, &u1, &u2, impl->method_mont_q.get(), ctx)) {
688
0
      goto err;
689
0
    }
690
691
    // u2 = r * w mod q. w was stored in the Montgomery domain while r was not,
692
    // so the result will already be out of the Montgomery domain.
693
0
    if (!BN_mod_mul_montgomery(&u2, sig->r, &u2, impl->method_mont_q.get(),
694
0
                               ctx)) {
695
0
      goto err;
696
0
    }
697
698
0
    if (!BN_mod_exp2_mont(&t1, impl->g.get(), &u1, impl->pub_key.get(), &u2,
699
0
                          impl->p.get(), ctx, impl->method_mont_p.get())) {
700
0
      goto err;
701
0
    }
702
703
    // let u1 = u1 mod q
704
0
    if (!BN_mod(&u1, &t1, impl->q.get(), ctx)) {
705
0
      goto err;
706
0
    }
707
708
    // V is now in u1.  If the signature is correct, it will be
709
    // equal to R.
710
0
    *out_valid = BN_ucmp(&u1, sig->r) == 0;
711
0
    ret = 1;
712
0
  }
713
714
0
err:
715
0
  if (ret != 1) {
716
0
    OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB);
717
0
  }
718
0
  BN_CTX_free(ctx);
719
0
  BN_free(&u1);
720
0
  BN_free(&u2);
721
0
  BN_free(&t1);
722
723
0
  return ret;
724
0
}
725
726
int DSA_sign(int type, const uint8_t *digest, size_t digest_len,
727
0
             uint8_t *out_sig, unsigned int *out_siglen, const DSA *dsa) {
728
0
  DSA_SIG *s = DSA_do_sign(digest, digest_len, dsa);
729
0
  if (s == nullptr) {
730
0
    *out_siglen = 0;
731
0
    return 0;
732
0
  }
733
734
0
  *out_siglen = i2d_DSA_SIG(s, &out_sig);
735
0
  DSA_SIG_free(s);
736
0
  return 1;
737
0
}
738
739
int DSA_verify(int type, const uint8_t *digest, size_t digest_len,
740
0
               const uint8_t *sig, size_t sig_len, const DSA *dsa) {
741
0
  int valid;
742
0
  if (!DSA_check_signature(&valid, digest, digest_len, sig, sig_len, dsa)) {
743
0
    return -1;
744
0
  }
745
0
  return valid;
746
0
}
747
748
int DSA_check_signature(int *out_valid, const uint8_t *digest,
749
                        size_t digest_len, const uint8_t *sig, size_t sig_len,
750
0
                        const DSA *dsa) {
751
0
  *out_valid = 0;
752
0
  DSA_SIG *s = nullptr;
753
0
  int ret = 0;
754
0
  uint8_t *der = nullptr;
755
756
0
  s = DSA_SIG_new();
757
0
  {
758
0
    if (s == nullptr) {
759
0
      goto err;
760
0
    }
761
762
0
    const uint8_t *sigp = sig;
763
0
    if (d2i_DSA_SIG(&s, &sigp, sig_len) == nullptr || sigp != sig + sig_len) {
764
0
      goto err;
765
0
    }
766
767
    // Ensure that the signature uses DER and doesn't have trailing garbage.
768
0
    int der_len = i2d_DSA_SIG(s, &der);
769
0
    if (der_len < 0 || (size_t)der_len != sig_len ||
770
0
        OPENSSL_memcmp(sig, der, sig_len)) {
771
0
      goto err;
772
0
    }
773
774
0
    ret = DSA_do_check_signature(out_valid, digest, digest_len, s, dsa);
775
0
  }
776
777
0
err:
778
0
  OPENSSL_free(der);
779
0
  DSA_SIG_free(s);
780
0
  return ret;
781
0
}
782
783
// der_len_len returns the number of bytes needed to represent a length of `len`
784
// in DER.
785
0
static size_t der_len_len(size_t len) {
786
0
  if (len < 0x80) {
787
0
    return 1;
788
0
  }
789
0
  size_t ret = 1;
790
0
  while (len > 0) {
791
0
    ret++;
792
0
    len >>= 8;
793
0
  }
794
0
  return ret;
795
0
}
796
797
0
int DSA_size(const DSA *dsa) {
798
0
  auto *impl = FromOpaque(dsa);
799
800
0
  if (impl->q == nullptr) {
801
0
    return 0;
802
0
  }
803
804
0
  size_t order_len = BN_num_bytes(impl->q.get());
805
  // Compute the maximum length of an `order_len` byte integer. Defensively
806
  // assume that the leading 0x00 is included.
807
0
  size_t integer_len = 1 /* tag */ + der_len_len(order_len + 1) + 1 + order_len;
808
0
  if (integer_len < order_len) {
809
0
    return 0;
810
0
  }
811
  // A DSA signature is two INTEGERs.
812
0
  size_t value_len = 2 * integer_len;
813
0
  if (value_len < integer_len) {
814
0
    return 0;
815
0
  }
816
  // Add the header.
817
0
  size_t ret = 1 /* tag */ + der_len_len(value_len) + value_len;
818
0
  if (ret < value_len) {
819
0
    return 0;
820
0
  }
821
0
  return ret;
822
0
}
823
824
static int dsa_sign_setup(const DSAImpl *dsa, BN_CTX *ctx, BIGNUM **out_kinv,
825
0
                          BIGNUM **out_r) {
826
0
  int ret = 0;
827
0
  BIGNUM k;
828
0
  BN_init(&k);
829
0
  BIGNUM *r = BN_new();
830
0
  BIGNUM *kinv = BN_new();
831
0
  if (r == nullptr || kinv == nullptr ||
832
      // Get random k
833
0
      !BN_rand_range_ex(&k, 1, dsa->q.get()) ||
834
0
      !BN_MONT_CTX_set_locked(&dsa->method_mont_p, &dsa->method_mont_lock,
835
0
                              dsa->p.get(), ctx) ||
836
0
      !BN_MONT_CTX_set_locked(&dsa->method_mont_q, &dsa->method_mont_lock,
837
0
                              dsa->q.get(), ctx) ||
838
      // Compute r = (g^k mod p) mod q
839
0
      !BN_mod_exp_mont_consttime(r, dsa->g.get(), &k, dsa->p.get(), ctx,
840
0
                                 dsa->method_mont_p.get())) {
841
0
    OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB);
842
0
    goto err;
843
0
  }
844
  // Note `BN_mod` below is not constant-time and may leak information about
845
  // `r`. `dsa->p` may be significantly larger than `dsa->q`, so this is not
846
  // easily performed in constant-time with Montgomery reduction.
847
  //
848
  // However, `r` at this point is g^k (mod p). It is almost the value of `r`
849
  // revealed in the signature anyway (g^k (mod p) (mod q)), going from it to
850
  // `k` would require computing a discrete log.
851
0
  bn_declassify(r);
852
0
  if (!BN_mod(r, r, dsa->q.get(), ctx) ||
853
      // Compute part of 's = inv(k) (m + xr) mod q' using Fermat's Little
854
      // Theorem.
855
0
      !bn_mod_inverse_prime(kinv, &k, dsa->q.get(), ctx,
856
0
                            dsa->method_mont_q.get())) {
857
0
    OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB);
858
0
    goto err;
859
0
  }
860
861
0
  BN_clear_free(*out_kinv);
862
0
  *out_kinv = kinv;
863
0
  kinv = nullptr;
864
865
0
  BN_clear_free(*out_r);
866
0
  *out_r = r;
867
0
  r = nullptr;
868
869
0
  ret = 1;
870
871
0
err:
872
0
  BN_clear_free(&k);
873
0
  BN_clear_free(r);
874
0
  BN_clear_free(kinv);
875
0
  return ret;
876
0
}
877
878
int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
879
0
                         CRYPTO_EX_dup *dup_unused, CRYPTO_EX_free *free_func) {
880
0
  return CRYPTO_get_ex_new_index_ex(&g_ex_data_class, argl, argp, free_func);
881
0
}
882
883
0
int DSA_set_ex_data(DSA *dsa, int idx, void *arg) {
884
0
  auto *impl = FromOpaque(dsa);
885
0
  return CRYPTO_set_ex_data(&impl->ex_data, idx, arg);
886
0
}
887
888
0
void *DSA_get_ex_data(const DSA *dsa, int idx) {
889
0
  auto *impl = FromOpaque(dsa);
890
0
  return CRYPTO_get_ex_data(&impl->ex_data, idx);
891
0
}
892
893
0
static bool copy_bn(UniquePtr<BIGNUM> *dst, const BIGNUM *src) {
894
0
  UniquePtr<BIGNUM> copy;
895
0
  if (src) {
896
0
    copy.reset(BN_dup(src));
897
0
    if (!copy) {
898
0
      return false;
899
0
    }
900
0
  }
901
0
  *dst = std::move(copy);
902
0
  return true;
903
0
}
904
905
0
DH *DSA_dup_DH(const DSA *dsa) {
906
0
  auto *impl = FromOpaque(dsa);
907
0
  if (dsa == nullptr) {
908
0
    return nullptr;
909
0
  }
910
911
0
  UniquePtr<DH> ret(DH_new());
912
0
  auto *dh = FromOpaque(ret.get());
913
0
  if (ret == nullptr) {
914
0
    return nullptr;
915
0
  }
916
0
  if (impl->q != nullptr) {
917
0
    dh->priv_length = BN_num_bits(impl->q.get());
918
0
    if (!copy_bn(&dh->q, impl->q.get())) {
919
0
      return nullptr;
920
0
    }
921
0
  }
922
0
  if (!copy_bn(&dh->p, impl->p.get()) ||              //
923
0
      !copy_bn(&dh->g, impl->g.get()) ||              //
924
0
      !copy_bn(&dh->pub_key, impl->pub_key.get()) ||  //
925
0
      !copy_bn(&dh->priv_key, impl->priv_key.get())) {
926
0
    return nullptr;
927
0
  }
928
929
0
  return ret.release();
930
0
}