xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/crypto/evp/p_dsa_asn1.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /* Written by Dr Stephen N Henson ([email protected]) for the OpenSSL project
2  * 2006.
3  */
4 /* ====================================================================
5  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. All advertising materials mentioning features or use of this
20  *    software must display the following acknowledgment:
21  *    "This product includes software developed by the OpenSSL Project
22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23  *
24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25  *    endorse or promote products derived from this software without
26  *    prior written permission. For written permission, please contact
27  *    [email protected].
28  *
29  * 5. Products derived from this software may not be called "OpenSSL"
30  *    nor may "OpenSSL" appear in their names without prior written
31  *    permission of the OpenSSL Project.
32  *
33  * 6. Redistributions of any form whatsoever must retain the following
34  *    acknowledgment:
35  *    "This product includes software developed by the OpenSSL Project
36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49  * OF THE POSSIBILITY OF SUCH DAMAGE.
50  * ====================================================================
51  *
52  * This product includes cryptographic software written by Eric Young
53  * ([email protected]).  This product includes software written by Tim
54  * Hudson ([email protected]). */
55 
56 #include <openssl/evp.h>
57 
58 #include <openssl/digest.h>
59 #include <openssl/bn.h>
60 #include <openssl/bytestring.h>
61 #include <openssl/dsa.h>
62 #include <openssl/err.h>
63 
64 #include "../dsa/internal.h"
65 #include "internal.h"
66 
67 
dsa_pub_decode(EVP_PKEY * out,CBS * params,CBS * key)68 static int dsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
69   // See RFC 3279, section 2.3.2.
70 
71   // Parameters may or may not be present.
72   DSA *dsa;
73   if (CBS_len(params) == 0) {
74     dsa = DSA_new();
75     if (dsa == NULL) {
76       return 0;
77     }
78   } else {
79     dsa = DSA_parse_parameters(params);
80     if (dsa == NULL || CBS_len(params) != 0) {
81       OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
82       goto err;
83     }
84   }
85 
86   dsa->pub_key = BN_new();
87   if (dsa->pub_key == NULL) {
88     goto err;
89   }
90 
91   if (!BN_parse_asn1_unsigned(key, dsa->pub_key) ||
92       CBS_len(key) != 0) {
93     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
94     goto err;
95   }
96 
97   EVP_PKEY_assign_DSA(out, dsa);
98   return 1;
99 
100 err:
101   DSA_free(dsa);
102   return 0;
103 }
104 
dsa_pub_encode(CBB * out,const EVP_PKEY * key)105 static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) {
106   const DSA *dsa = key->pkey;
107   const int has_params = dsa->p != NULL && dsa->q != NULL && dsa->g != NULL;
108 
109   // See RFC 5480, section 2.
110   CBB spki, algorithm, oid, key_bitstring;
111   if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
112       !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
113       !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
114       !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
115       (has_params &&
116        !DSA_marshal_parameters(&algorithm, dsa)) ||
117       !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
118       !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
119       !BN_marshal_asn1(&key_bitstring, dsa->pub_key) ||
120       !CBB_flush(out)) {
121     OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
122     return 0;
123   }
124 
125   return 1;
126 }
127 
dsa_priv_decode(EVP_PKEY * out,CBS * params,CBS * key)128 static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
129   // See PKCS#11, v2.40, section 2.5.
130 
131   // Decode parameters.
132   BN_CTX *ctx = NULL;
133   DSA *dsa = DSA_parse_parameters(params);
134   if (dsa == NULL || CBS_len(params) != 0) {
135     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
136     goto err;
137   }
138 
139   dsa->priv_key = BN_new();
140   if (dsa->priv_key == NULL) {
141     goto err;
142   }
143   if (!BN_parse_asn1_unsigned(key, dsa->priv_key) ||
144       CBS_len(key) != 0) {
145     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
146     goto err;
147   }
148 
149   // To avoid DoS attacks when importing private keys, check bounds on |dsa|.
150   // This bounds |dsa->priv_key| against |dsa->q| and bounds |dsa->q|'s bit
151   // width.
152   if (!dsa_check_key(dsa)) {
153     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
154     goto err;
155   }
156 
157   // Calculate the public key.
158   ctx = BN_CTX_new();
159   dsa->pub_key = BN_new();
160   if (ctx == NULL || dsa->pub_key == NULL ||
161       !BN_mod_exp_mont_consttime(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p,
162                                  ctx, NULL)) {
163     goto err;
164   }
165 
166   BN_CTX_free(ctx);
167   EVP_PKEY_assign_DSA(out, dsa);
168   return 1;
169 
170 err:
171   BN_CTX_free(ctx);
172   DSA_free(dsa);
173   return 0;
174 }
175 
dsa_priv_encode(CBB * out,const EVP_PKEY * key)176 static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) {
177   const DSA *dsa = key->pkey;
178   if (dsa == NULL || dsa->priv_key == NULL) {
179     OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
180     return 0;
181   }
182 
183   // See PKCS#11, v2.40, section 2.5.
184   CBB pkcs8, algorithm, oid, private_key;
185   if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
186       !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
187       !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
188       !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
189       !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
190       !DSA_marshal_parameters(&algorithm, dsa) ||
191       !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
192       !BN_marshal_asn1(&private_key, dsa->priv_key) ||
193       !CBB_flush(out)) {
194     OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
195     return 0;
196   }
197 
198   return 1;
199 }
200 
int_dsa_size(const EVP_PKEY * pkey)201 static int int_dsa_size(const EVP_PKEY *pkey) {
202   const DSA *dsa = pkey->pkey;
203   return DSA_size(dsa);
204 }
205 
dsa_bits(const EVP_PKEY * pkey)206 static int dsa_bits(const EVP_PKEY *pkey) {
207   const DSA *dsa = pkey->pkey;
208   return BN_num_bits(DSA_get0_p(dsa));
209 }
210 
dsa_missing_parameters(const EVP_PKEY * pkey)211 static int dsa_missing_parameters(const EVP_PKEY *pkey) {
212   const DSA *dsa = pkey->pkey;
213   if (DSA_get0_p(dsa) == NULL || DSA_get0_q(dsa) == NULL ||
214       DSA_get0_g(dsa) == NULL) {
215     return 1;
216   }
217   return 0;
218 }
219 
dup_bn_into(BIGNUM ** out,BIGNUM * src)220 static int dup_bn_into(BIGNUM **out, BIGNUM *src) {
221   BIGNUM *a;
222 
223   a = BN_dup(src);
224   if (a == NULL) {
225     return 0;
226   }
227   BN_free(*out);
228   *out = a;
229 
230   return 1;
231 }
232 
dsa_copy_parameters(EVP_PKEY * to,const EVP_PKEY * from)233 static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
234   DSA *to_dsa = to->pkey;
235   const DSA *from_dsa = from->pkey;
236   if (!dup_bn_into(&to_dsa->p, from_dsa->p) ||
237       !dup_bn_into(&to_dsa->q, from_dsa->q) ||
238       !dup_bn_into(&to_dsa->g, from_dsa->g)) {
239     return 0;
240   }
241 
242   return 1;
243 }
244 
dsa_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)245 static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
246   const DSA *a_dsa = a->pkey;
247   const DSA *b_dsa = b->pkey;
248   return BN_cmp(DSA_get0_p(a_dsa), DSA_get0_p(b_dsa)) == 0 &&
249          BN_cmp(DSA_get0_q(a_dsa), DSA_get0_q(b_dsa)) == 0 &&
250          BN_cmp(DSA_get0_g(a_dsa), DSA_get0_g(b_dsa)) == 0;
251 }
252 
dsa_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)253 static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
254   const DSA *a_dsa = a->pkey;
255   const DSA *b_dsa = b->pkey;
256   return BN_cmp(DSA_get0_pub_key(b_dsa), DSA_get0_pub_key(a_dsa)) == 0;
257 }
258 
int_dsa_free(EVP_PKEY * pkey)259 static void int_dsa_free(EVP_PKEY *pkey) {
260   DSA_free(pkey->pkey);
261   pkey->pkey = NULL;
262 }
263 
264 const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
265     EVP_PKEY_DSA,
266     // 1.2.840.10040.4.1
267     {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01},
268     7,
269 
270     /*pkey_method=*/NULL,
271 
272     dsa_pub_decode,
273     dsa_pub_encode,
274     dsa_pub_cmp,
275 
276     dsa_priv_decode,
277     dsa_priv_encode,
278 
279     /*set_priv_raw=*/NULL,
280     /*set_pub_raw=*/NULL,
281     /*get_priv_raw=*/NULL,
282     /*get_pub_raw=*/NULL,
283     /*set1_tls_encodedpoint=*/NULL,
284     /*get1_tls_encodedpoint=*/NULL,
285 
286     /*pkey_opaque=*/NULL,
287 
288     int_dsa_size,
289     dsa_bits,
290 
291     dsa_missing_parameters,
292     dsa_copy_parameters,
293     dsa_cmp_parameters,
294 
295     int_dsa_free,
296 };
297 
EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX * ctx,int nbits)298 int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits) {
299   // BoringSSL does not support DSA in |EVP_PKEY_CTX|.
300   OPENSSL_PUT_ERROR(EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
301   return 0;
302 }
303 
EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX * ctx,int qbits)304 int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits) {
305   // BoringSSL does not support DSA in |EVP_PKEY_CTX|.
306   OPENSSL_PUT_ERROR(EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
307   return 0;
308 }
309 
EVP_PKEY_set1_DSA(EVP_PKEY * pkey,DSA * key)310 int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) {
311   if (EVP_PKEY_assign_DSA(pkey, key)) {
312     DSA_up_ref(key);
313     return 1;
314   }
315   return 0;
316 }
317 
EVP_PKEY_assign_DSA(EVP_PKEY * pkey,DSA * key)318 int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key) {
319   evp_pkey_set_method(pkey, &dsa_asn1_meth);
320   pkey->pkey = key;
321   return key != NULL;
322 }
323 
EVP_PKEY_get0_DSA(const EVP_PKEY * pkey)324 DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey) {
325   if (pkey->type != EVP_PKEY_DSA) {
326     OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DSA_KEY);
327     return NULL;
328   }
329   return pkey->pkey;
330 }
331 
EVP_PKEY_get1_DSA(const EVP_PKEY * pkey)332 DSA *EVP_PKEY_get1_DSA(const EVP_PKEY *pkey) {
333   DSA *dsa = EVP_PKEY_get0_DSA(pkey);
334   if (dsa != NULL) {
335     DSA_up_ref(dsa);
336   }
337   return dsa;
338 }
339