xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/crypto/dsa/dsa_asn1.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /* Written by Dr Stephen N Henson ([email protected]) for the OpenSSL
2  * project 2000. */
3 /* ====================================================================
4  * Copyright (c) 2000-2005 The OpenSSL Project.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. All advertising materials mentioning features or use of this
19  *    software must display the following acknowledgment:
20  *    "This product includes software developed by the OpenSSL Project
21  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
22  *
23  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
24  *    endorse or promote products derived from this software without
25  *    prior written permission. For written permission, please contact
26  *    [email protected].
27  *
28  * 5. Products derived from this software may not be called "OpenSSL"
29  *    nor may "OpenSSL" appear in their names without prior written
30  *    permission of the OpenSSL Project.
31  *
32  * 6. Redistributions of any form whatsoever must retain the following
33  *    acknowledgment:
34  *    "This product includes software developed by the OpenSSL Project
35  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
38  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
48  * OF THE POSSIBILITY OF SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This product includes cryptographic software written by Eric Young
52  * ([email protected]).  This product includes software written by Tim
53  * Hudson ([email protected]). */
54 
55 #include <openssl/dsa.h>
56 
57 #include <assert.h>
58 
59 #include <openssl/bn.h>
60 #include <openssl/bytestring.h>
61 #include <openssl/err.h>
62 #include <openssl/mem.h>
63 
64 #include "internal.h"
65 #include "../bytestring/internal.h"
66 
67 
68 #define OPENSSL_DSA_MAX_MODULUS_BITS 10000
69 
70 // This function is in dsa_asn1.c rather than dsa.c because it is reachable from
71 // |EVP_PKEY| parsers. This makes it easier for the static linker to drop most
72 // of the DSA implementation.
dsa_check_key(const DSA * dsa)73 int dsa_check_key(const DSA *dsa) {
74   if (!dsa->p || !dsa->q || !dsa->g) {
75     OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS);
76     return 0;
77   }
78 
79   // Fully checking for invalid DSA groups is expensive, so security and
80   // correctness of the signature scheme depend on how |dsa| was computed. I.e.
81   // we leave "assurance of domain parameter validity" from FIPS 186-4 to the
82   // caller. However, we check bounds on all values to avoid DoS vectors even
83   // when domain parameters are invalid. In particular, signing will infinite
84   // loop if |g| is zero.
85   if (BN_is_negative(dsa->p) || BN_is_negative(dsa->q) || BN_is_zero(dsa->p) ||
86       BN_is_zero(dsa->q) || !BN_is_odd(dsa->p) || !BN_is_odd(dsa->q) ||
87       // |q| must be a prime divisor of |p - 1|, which implies |q < p|.
88       BN_cmp(dsa->q, dsa->p) >= 0 ||
89       // |g| is in the multiplicative group of |p|.
90       BN_is_negative(dsa->g) || BN_is_zero(dsa->g) ||
91       BN_cmp(dsa->g, dsa->p) >= 0) {
92     OPENSSL_PUT_ERROR(DSA, DSA_R_INVALID_PARAMETERS);
93     return 0;
94   }
95 
96   // FIPS 186-4 allows only three different sizes for q.
97   unsigned q_bits = BN_num_bits(dsa->q);
98   if (q_bits != 160 && q_bits != 224 && q_bits != 256) {
99     OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_Q_VALUE);
100     return 0;
101   }
102 
103   // Bound |dsa->p| to avoid a DoS vector. Note this limit is much larger than
104   // the one in FIPS 186-4, which only allows L = 1024, 2048, and 3072.
105   if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
106     OPENSSL_PUT_ERROR(DSA, DSA_R_MODULUS_TOO_LARGE);
107     return 0;
108   }
109 
110   if (dsa->pub_key != NULL) {
111     // The public key is also in the multiplicative group of |p|.
112     if (BN_is_negative(dsa->pub_key) || BN_is_zero(dsa->pub_key) ||
113         BN_cmp(dsa->pub_key, dsa->p) >= 0) {
114       OPENSSL_PUT_ERROR(DSA, DSA_R_INVALID_PARAMETERS);
115       return 0;
116     }
117   }
118 
119   if (dsa->priv_key != NULL) {
120     // The private key is a non-zero element of the scalar field, determined by
121     // |q|.
122     if (BN_is_negative(dsa->priv_key) ||
123         constant_time_declassify_int(BN_is_zero(dsa->priv_key)) ||
124         constant_time_declassify_int(BN_cmp(dsa->priv_key, dsa->q) >= 0)) {
125       OPENSSL_PUT_ERROR(DSA, DSA_R_INVALID_PARAMETERS);
126       return 0;
127     }
128   }
129 
130   return 1;
131 }
132 
parse_integer(CBS * cbs,BIGNUM ** out)133 static int parse_integer(CBS *cbs, BIGNUM **out) {
134   assert(*out == NULL);
135   *out = BN_new();
136   if (*out == NULL) {
137     return 0;
138   }
139   return BN_parse_asn1_unsigned(cbs, *out);
140 }
141 
marshal_integer(CBB * cbb,BIGNUM * bn)142 static int marshal_integer(CBB *cbb, BIGNUM *bn) {
143   if (bn == NULL) {
144     // A DSA object may be missing some components.
145     OPENSSL_PUT_ERROR(DSA, ERR_R_PASSED_NULL_PARAMETER);
146     return 0;
147   }
148   return BN_marshal_asn1(cbb, bn);
149 }
150 
DSA_SIG_parse(CBS * cbs)151 DSA_SIG *DSA_SIG_parse(CBS *cbs) {
152   DSA_SIG *ret = DSA_SIG_new();
153   if (ret == NULL) {
154     return NULL;
155   }
156   CBS child;
157   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
158       !parse_integer(&child, &ret->r) ||
159       !parse_integer(&child, &ret->s) ||
160       CBS_len(&child) != 0) {
161     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
162     DSA_SIG_free(ret);
163     return NULL;
164   }
165   return ret;
166 }
167 
DSA_SIG_marshal(CBB * cbb,const DSA_SIG * sig)168 int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig) {
169   CBB child;
170   if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
171       !marshal_integer(&child, sig->r) ||
172       !marshal_integer(&child, sig->s) ||
173       !CBB_flush(cbb)) {
174     OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
175     return 0;
176   }
177   return 1;
178 }
179 
DSA_parse_public_key(CBS * cbs)180 DSA *DSA_parse_public_key(CBS *cbs) {
181   DSA *ret = DSA_new();
182   if (ret == NULL) {
183     return NULL;
184   }
185   CBS child;
186   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
187       !parse_integer(&child, &ret->pub_key) ||
188       !parse_integer(&child, &ret->p) ||
189       !parse_integer(&child, &ret->q) ||
190       !parse_integer(&child, &ret->g) ||
191       CBS_len(&child) != 0) {
192     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
193     goto err;
194   }
195   if (!dsa_check_key(ret)) {
196     goto err;
197   }
198   return ret;
199 
200 err:
201   DSA_free(ret);
202   return NULL;
203 }
204 
DSA_marshal_public_key(CBB * cbb,const DSA * dsa)205 int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) {
206   CBB child;
207   if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
208       !marshal_integer(&child, dsa->pub_key) ||
209       !marshal_integer(&child, dsa->p) ||
210       !marshal_integer(&child, dsa->q) ||
211       !marshal_integer(&child, dsa->g) ||
212       !CBB_flush(cbb)) {
213     OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
214     return 0;
215   }
216   return 1;
217 }
218 
DSA_parse_parameters(CBS * cbs)219 DSA *DSA_parse_parameters(CBS *cbs) {
220   DSA *ret = DSA_new();
221   if (ret == NULL) {
222     return NULL;
223   }
224   CBS child;
225   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
226       !parse_integer(&child, &ret->p) ||
227       !parse_integer(&child, &ret->q) ||
228       !parse_integer(&child, &ret->g) ||
229       CBS_len(&child) != 0) {
230     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
231     goto err;
232   }
233   if (!dsa_check_key(ret)) {
234     goto err;
235   }
236   return ret;
237 
238 err:
239   DSA_free(ret);
240   return NULL;
241 }
242 
DSA_marshal_parameters(CBB * cbb,const DSA * dsa)243 int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) {
244   CBB child;
245   if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
246       !marshal_integer(&child, dsa->p) ||
247       !marshal_integer(&child, dsa->q) ||
248       !marshal_integer(&child, dsa->g) ||
249       !CBB_flush(cbb)) {
250     OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
251     return 0;
252   }
253   return 1;
254 }
255 
DSA_parse_private_key(CBS * cbs)256 DSA *DSA_parse_private_key(CBS *cbs) {
257   DSA *ret = DSA_new();
258   if (ret == NULL) {
259     return NULL;
260   }
261 
262   CBS child;
263   uint64_t version;
264   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
265       !CBS_get_asn1_uint64(&child, &version)) {
266     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
267     goto err;
268   }
269 
270   if (version != 0) {
271     OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION);
272     goto err;
273   }
274 
275   if (!parse_integer(&child, &ret->p) ||
276       !parse_integer(&child, &ret->q) ||
277       !parse_integer(&child, &ret->g) ||
278       !parse_integer(&child, &ret->pub_key) ||
279       !parse_integer(&child, &ret->priv_key) ||
280       CBS_len(&child) != 0) {
281     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
282     goto err;
283   }
284   if (!dsa_check_key(ret)) {
285     goto err;
286   }
287 
288   return ret;
289 
290 err:
291   DSA_free(ret);
292   return NULL;
293 }
294 
DSA_marshal_private_key(CBB * cbb,const DSA * dsa)295 int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) {
296   CBB child;
297   if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
298       !CBB_add_asn1_uint64(&child, 0 /* version */) ||
299       !marshal_integer(&child, dsa->p) ||
300       !marshal_integer(&child, dsa->q) ||
301       !marshal_integer(&child, dsa->g) ||
302       !marshal_integer(&child, dsa->pub_key) ||
303       !marshal_integer(&child, dsa->priv_key) ||
304       !CBB_flush(cbb)) {
305     OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
306     return 0;
307   }
308   return 1;
309 }
310 
d2i_DSA_SIG(DSA_SIG ** out_sig,const uint8_t ** inp,long len)311 DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) {
312   if (len < 0) {
313     return NULL;
314   }
315   CBS cbs;
316   CBS_init(&cbs, *inp, (size_t)len);
317   DSA_SIG *ret = DSA_SIG_parse(&cbs);
318   if (ret == NULL) {
319     return NULL;
320   }
321   if (out_sig != NULL) {
322     DSA_SIG_free(*out_sig);
323     *out_sig = ret;
324   }
325   *inp = CBS_data(&cbs);
326   return ret;
327 }
328 
i2d_DSA_SIG(const DSA_SIG * in,uint8_t ** outp)329 int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) {
330   CBB cbb;
331   if (!CBB_init(&cbb, 0) ||
332       !DSA_SIG_marshal(&cbb, in)) {
333     CBB_cleanup(&cbb);
334     return -1;
335   }
336   return CBB_finish_i2d(&cbb, outp);
337 }
338 
d2i_DSAPublicKey(DSA ** out,const uint8_t ** inp,long len)339 DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) {
340   if (len < 0) {
341     return NULL;
342   }
343   CBS cbs;
344   CBS_init(&cbs, *inp, (size_t)len);
345   DSA *ret = DSA_parse_public_key(&cbs);
346   if (ret == NULL) {
347     return NULL;
348   }
349   if (out != NULL) {
350     DSA_free(*out);
351     *out = ret;
352   }
353   *inp = CBS_data(&cbs);
354   return ret;
355 }
356 
i2d_DSAPublicKey(const DSA * in,uint8_t ** outp)357 int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) {
358   CBB cbb;
359   if (!CBB_init(&cbb, 0) ||
360       !DSA_marshal_public_key(&cbb, in)) {
361     CBB_cleanup(&cbb);
362     return -1;
363   }
364   return CBB_finish_i2d(&cbb, outp);
365 }
366 
d2i_DSAPrivateKey(DSA ** out,const uint8_t ** inp,long len)367 DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) {
368   if (len < 0) {
369     return NULL;
370   }
371   CBS cbs;
372   CBS_init(&cbs, *inp, (size_t)len);
373   DSA *ret = DSA_parse_private_key(&cbs);
374   if (ret == NULL) {
375     return NULL;
376   }
377   if (out != NULL) {
378     DSA_free(*out);
379     *out = ret;
380   }
381   *inp = CBS_data(&cbs);
382   return ret;
383 }
384 
i2d_DSAPrivateKey(const DSA * in,uint8_t ** outp)385 int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) {
386   CBB cbb;
387   if (!CBB_init(&cbb, 0) ||
388       !DSA_marshal_private_key(&cbb, in)) {
389     CBB_cleanup(&cbb);
390     return -1;
391   }
392   return CBB_finish_i2d(&cbb, outp);
393 }
394 
d2i_DSAparams(DSA ** out,const uint8_t ** inp,long len)395 DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) {
396   if (len < 0) {
397     return NULL;
398   }
399   CBS cbs;
400   CBS_init(&cbs, *inp, (size_t)len);
401   DSA *ret = DSA_parse_parameters(&cbs);
402   if (ret == NULL) {
403     return NULL;
404   }
405   if (out != NULL) {
406     DSA_free(*out);
407     *out = ret;
408   }
409   *inp = CBS_data(&cbs);
410   return ret;
411 }
412 
i2d_DSAparams(const DSA * in,uint8_t ** outp)413 int i2d_DSAparams(const DSA *in, uint8_t **outp) {
414   CBB cbb;
415   if (!CBB_init(&cbb, 0) ||
416       !DSA_marshal_parameters(&cbb, in)) {
417     CBB_cleanup(&cbb);
418     return -1;
419   }
420   return CBB_finish_i2d(&cbb, outp);
421 }
422