Coverage Report

Created: 2026-06-15 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/dsa/dsa_asn1.cc
Line
Count
Source
1
// Copyright 1999-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 <assert.h>
18
19
#include <openssl/bn.h>
20
#include <openssl/bytestring.h>
21
#include <openssl/err.h>
22
#include <openssl/mem.h>
23
24
#include "../bytestring/internal.h"
25
#include "../mem_internal.h"
26
#include "internal.h"
27
28
29
using namespace bssl;
30
31
// This function is in dsa_asn1.c rather than dsa.c because it is reachable from
32
// `EVP_PKEY` parsers. This makes it easier for the static linker to drop most
33
// of the DSA implementation.
34
4.29k
int bssl::dsa_check_key(const DSAImpl *dsa) {
35
4.29k
  if (!dsa->p || !dsa->q || !dsa->g) {
36
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS);
37
0
    return 0;
38
0
  }
39
40
  // Fully checking for invalid DSA groups is expensive, so security and
41
  // correctness of the signature scheme depend on how `dsa` was computed. I.e.
42
  // we leave "assurance of domain parameter validity" from FIPS 186-4 to the
43
  // caller. However, we check bounds on all values to avoid DoS vectors even
44
  // when domain parameters are invalid. In particular, signing will infinite
45
  // loop if `g` is zero.
46
4.29k
  if (BN_is_negative(dsa->p.get()) || BN_is_negative(dsa->q.get()) ||
47
4.29k
      BN_is_zero(dsa->p.get()) || BN_is_zero(dsa->q.get()) ||
48
4.27k
      !BN_is_odd(dsa->p.get()) || !BN_is_odd(dsa->q.get()) ||
49
      // `q` must be a prime divisor of `p - 1`, which implies `q < p`.
50
4.18k
      BN_cmp(dsa->q.get(), dsa->p.get()) >= 0 ||
51
      // `g` is in the multiplicative group of `p`.
52
3.81k
      BN_is_negative(dsa->g.get()) || BN_is_zero(dsa->g.get()) ||
53
3.72k
      BN_cmp(dsa->g.get(), dsa->p.get()) >= 0) {
54
1.02k
    OPENSSL_PUT_ERROR(DSA, DSA_R_INVALID_PARAMETERS);
55
1.02k
    return 0;
56
1.02k
  }
57
58
  // FIPS 186-4 allows only three different sizes for q.
59
3.26k
  unsigned q_bits = BN_num_bits(dsa->q.get());
60
3.26k
  if (q_bits != 160 && q_bits != 224 && q_bits != 256) {
61
1.28k
    OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_Q_VALUE);
62
1.28k
    return 0;
63
1.28k
  }
64
65
  // Bound `dsa->p` to avoid a DoS vector. Note this limit is much larger than
66
  // the one in FIPS 186-4, which only allows L = 1024, 2048, and 3072.
67
1.98k
  if (BN_num_bits(dsa->p.get()) > OPENSSL_DSA_MAX_MODULUS_BITS) {
68
16
    OPENSSL_PUT_ERROR(DSA, DSA_R_MODULUS_TOO_LARGE);
69
16
    return 0;
70
16
  }
71
72
1.96k
  if (dsa->pub_key != nullptr) {
73
    // The public key is also in the multiplicative group of `p`.
74
13
    if (BN_is_negative(dsa->pub_key.get()) || BN_is_zero(dsa->pub_key.get()) ||
75
12
        BN_cmp(dsa->pub_key.get(), dsa->p.get()) >= 0) {
76
3
      OPENSSL_PUT_ERROR(DSA, DSA_R_INVALID_PARAMETERS);
77
3
      return 0;
78
3
    }
79
13
  }
80
81
1.96k
  if (dsa->priv_key != nullptr) {
82
    // The private key is a non-zero element of the scalar field, determined by
83
    // `q`.
84
930
    if (BN_is_negative(dsa->priv_key.get()) ||
85
930
        constant_time_declassify_int(BN_is_zero(dsa->priv_key.get())) ||
86
921
        constant_time_declassify_int(
87
921
            BN_cmp(dsa->priv_key.get(), dsa->q.get()) >= 0)) {
88
17
      OPENSSL_PUT_ERROR(DSA, DSA_R_INVALID_PARAMETERS);
89
17
      return 0;
90
17
    }
91
930
  }
92
93
1.94k
  return 1;
94
1.96k
}
95
96
12.1k
static int parse_integer(CBS *cbs, UniquePtr<BIGNUM> *out) {
97
12.1k
  assert(*out == nullptr);
98
12.1k
  out->reset(BN_new());
99
12.1k
  if (*out == nullptr) {
100
0
    return 0;
101
0
  }
102
12.1k
  return BN_parse_asn1_unsigned(cbs, out->get());
103
12.1k
}
104
105
2.78k
static int marshal_integer(CBB *cbb, BIGNUM *bn) {
106
2.78k
  if (bn == nullptr) {
107
    // A DSA object may be missing some components.
108
0
    OPENSSL_PUT_ERROR(DSA, ERR_R_PASSED_NULL_PARAMETER);
109
0
    return 0;
110
0
  }
111
2.78k
  return BN_marshal_asn1(cbb, bn);
112
2.78k
}
113
114
0
DSA_SIG *DSA_SIG_parse(CBS *cbs) {
115
0
  DSA_SIG *ret = DSA_SIG_new();
116
0
  if (ret == nullptr) {
117
0
    return nullptr;
118
0
  }
119
0
  CBS child;
120
0
  UniquePtr<BIGNUM> r, s;
121
0
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
122
0
      !parse_integer(&child, &r) ||
123
0
      !parse_integer(&child, &s) ||
124
0
      CBS_len(&child) != 0) {
125
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
126
0
    DSA_SIG_free(ret);
127
0
    return nullptr;
128
0
  }
129
0
  ret->r = r.release();
130
0
  ret->s = s.release();
131
0
  return ret;
132
0
}
133
134
0
int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig) {
135
0
  CBB child;
136
0
  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
137
0
      !marshal_integer(&child, sig->r) ||
138
0
      !marshal_integer(&child, sig->s) ||
139
0
      !CBB_flush(cbb)) {
140
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
141
0
    return 0;
142
0
  }
143
0
  return 1;
144
0
}
145
146
0
DSA *DSA_parse_public_key(CBS *cbs) {
147
0
  UniquePtr<DSAImpl> ret(FromOpaque(DSA_new()));
148
0
  if (ret == nullptr) {
149
0
    return nullptr;
150
0
  }
151
0
  CBS child;
152
0
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
153
0
      !parse_integer(&child, &ret->pub_key) ||
154
0
      !parse_integer(&child, &ret->p) ||
155
0
      !parse_integer(&child, &ret->q) ||
156
0
      !parse_integer(&child, &ret->g) ||
157
0
      CBS_len(&child) != 0) {
158
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
159
0
    return nullptr;
160
0
  }
161
0
  if (!dsa_check_key(ret.get())) {
162
0
    return nullptr;
163
0
  }
164
0
  return ret.release();
165
0
}
166
167
0
int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) {
168
0
  const auto *impl = FromOpaque(dsa);
169
170
0
  CBB child;
171
0
  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
172
0
      !marshal_integer(&child, impl->pub_key.get()) ||
173
0
      !marshal_integer(&child, impl->p.get()) ||
174
0
      !marshal_integer(&child, impl->q.get()) ||
175
0
      !marshal_integer(&child, impl->g.get()) || !CBB_flush(cbb)) {
176
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
177
0
    return 0;
178
0
  }
179
0
  return 1;
180
0
}
181
182
5.90k
DSA *DSA_parse_parameters(CBS *cbs) {
183
5.90k
  UniquePtr<DSAImpl> ret(FromOpaque(DSA_new()));
184
5.90k
  if (ret == nullptr) {
185
0
    return nullptr;
186
0
  }
187
5.90k
  CBS child;
188
5.90k
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
189
3.61k
      !parse_integer(&child, &ret->p) ||
190
3.08k
      !parse_integer(&child, &ret->q) ||
191
2.94k
      !parse_integer(&child, &ret->g) ||
192
3.01k
      CBS_len(&child) != 0) {
193
3.01k
    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
194
3.01k
    return nullptr;
195
3.01k
  }
196
2.88k
  if (!dsa_check_key(ret.get())) {
197
1.85k
    return nullptr;
198
1.85k
  }
199
1.03k
  return ret.release();
200
2.88k
}
201
202
928
int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) {
203
928
  const auto *impl = FromOpaque(dsa);
204
205
928
  CBB child;
206
928
  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
207
928
      !marshal_integer(&child, impl->p.get()) ||
208
928
      !marshal_integer(&child, impl->q.get()) ||
209
928
      !marshal_integer(&child, impl->g.get()) || !CBB_flush(cbb)) {
210
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
211
0
    return 0;
212
0
  }
213
928
  return 1;
214
928
}
215
216
624
DSA *DSA_parse_private_key(CBS *cbs) {
217
624
  UniquePtr<DSAImpl> ret(FromOpaque(DSA_new()));
218
624
  if (ret == nullptr) {
219
0
    return nullptr;
220
0
  }
221
222
624
  CBS child;
223
624
  uint64_t version;
224
624
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
225
624
      !CBS_get_asn1_uint64(&child, &version)) {
226
2
    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
227
2
    return nullptr;
228
2
  }
229
230
622
  if (version != 0) {
231
126
    OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION);
232
126
    return nullptr;
233
126
  }
234
235
496
  if (!parse_integer(&child, &ret->p) ||
236
493
      !parse_integer(&child, &ret->q) ||
237
492
      !parse_integer(&child, &ret->g) ||
238
491
      !parse_integer(&child, &ret->pub_key) ||
239
490
      !parse_integer(&child, &ret->priv_key) ||
240
489
      CBS_len(&child) != 0) {
241
7
    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
242
7
    return nullptr;
243
7
  }
244
489
  if (!dsa_check_key(ret.get())) {
245
483
    return nullptr;
246
483
  }
247
248
6
  return ret.release();
249
489
}
250
251
0
int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) {
252
0
  const auto *impl = FromOpaque(dsa);
253
254
0
  CBB child;
255
0
  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
256
0
      !CBB_add_asn1_uint64(&child, 0 /* version */) ||
257
0
      !marshal_integer(&child, impl->p.get()) ||
258
0
      !marshal_integer(&child, impl->q.get()) ||
259
0
      !marshal_integer(&child, impl->g.get()) ||
260
0
      !marshal_integer(&child, impl->pub_key.get()) ||
261
0
      !marshal_integer(&child, impl->priv_key.get()) || !CBB_flush(cbb)) {
262
0
    OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
263
0
    return 0;
264
0
  }
265
0
  return 1;
266
0
}
267
268
0
DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) {
269
0
  return D2IFromCBS(out_sig, inp, len, DSA_SIG_parse);
270
0
}
271
272
0
int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) {
273
0
  return I2DFromCBB(
274
0
      /*initial_capacity=*/256, outp,
275
0
      [&](CBB *cbb) -> bool { return DSA_SIG_marshal(cbb, in); });
276
0
}
277
278
0
DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) {
279
0
  return D2IFromCBS(out, inp, len, DSA_parse_public_key);
280
0
}
281
282
0
int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) {
283
0
  return I2DFromCBB(
284
0
      /*initial_capacity=*/256, outp,
285
0
      [&](CBB *cbb) -> bool { return DSA_marshal_public_key(cbb, in); });
286
0
}
287
288
0
DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) {
289
0
  return D2IFromCBS(out, inp, len, DSA_parse_private_key);
290
0
}
291
292
0
int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) {
293
0
  return I2DFromCBB(
294
0
      /*initial_capacity=*/256, outp,
295
0
      [&](CBB *cbb) -> bool { return DSA_marshal_private_key(cbb, in); });
296
0
}
297
298
0
DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) {
299
0
  return D2IFromCBS(out, inp, len, DSA_parse_parameters);
300
0
}
301
302
0
int i2d_DSAparams(const DSA *in, uint8_t **outp) {
303
0
  return I2DFromCBB(
304
0
      /*initial_capacity=*/256, outp,
305
0
      [&](CBB *cbb) -> bool { return DSA_marshal_parameters(cbb, in); });
306
0
}