1 /* $OpenBSD: dsa_asn1.c,v 1.25 2022/09/03 16:01:23 jsing Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 2000-2005 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 
59 #include <stdio.h>
60 #include <string.h>
61 
62 #include <openssl/asn1.h>
63 #include <openssl/asn1t.h>
64 #include <openssl/dsa.h>
65 #include <openssl/err.h>
66 
67 #include "dsa_locl.h"
68 
69 /* Override the default new methods */
70 static int
71 sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
72 {
73 	if (operation == ASN1_OP_NEW_PRE) {
74 		DSA_SIG *sig;
75 
76 		if ((sig = DSA_SIG_new()) == NULL) {
77 			DSAerror(ERR_R_MALLOC_FAILURE);
78 			return 0;
79 		}
80 		*pval = (ASN1_VALUE *)sig;
81 		return 2;
82 	}
83 	return 1;
84 }
85 
86 static const ASN1_AUX DSA_SIG_aux = {
87 	.app_data = NULL,
88 	.flags = 0,
89 	.ref_offset = 0,
90 	.ref_lock = 0,
91 	.asn1_cb = sig_cb,
92 	.enc_offset = 0,
93 };
94 static const ASN1_TEMPLATE DSA_SIG_seq_tt[] = {
95 	{
96 		.flags = 0,
97 		.tag = 0,
98 		.offset = offsetof(DSA_SIG, r),
99 		.field_name = "r",
100 		.item = &BIGNUM_it,
101 	},
102 	{
103 		.flags = 0,
104 		.tag = 0,
105 		.offset = offsetof(DSA_SIG, s),
106 		.field_name = "s",
107 		.item = &BIGNUM_it,
108 	},
109 };
110 
111 const ASN1_ITEM DSA_SIG_it = {
112 	.itype = ASN1_ITYPE_SEQUENCE,
113 	.utype = V_ASN1_SEQUENCE,
114 	.templates = DSA_SIG_seq_tt,
115 	.tcount = sizeof(DSA_SIG_seq_tt) / sizeof(ASN1_TEMPLATE),
116 	.funcs = &DSA_SIG_aux,
117 	.size = sizeof(DSA_SIG),
118 	.sname = "DSA_SIG",
119 };
120 
121 
122 DSA_SIG *
123 d2i_DSA_SIG(DSA_SIG **a, const unsigned char **in, long len)
124 {
125 	return (DSA_SIG *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
126 	    &DSA_SIG_it);
127 }
128 
129 int
130 i2d_DSA_SIG(const DSA_SIG *a, unsigned char **out)
131 {
132 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSA_SIG_it);
133 }
134 
135 void
136 DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
137 {
138 	if (pr != NULL)
139 		*pr = sig->r;
140 	if (ps != NULL)
141 		*ps = sig->s;
142 }
143 
144 int
145 DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
146 {
147 	if (r == NULL || s == NULL)
148 		return 0;
149 
150 	BN_clear_free(sig->r);
151 	sig->r = r;
152 	BN_clear_free(sig->s);
153 	sig->s = s;
154 
155 	return 1;
156 }
157 
158 /* Override the default free and new methods */
159 static int
160 dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
161 {
162 	if (operation == ASN1_OP_NEW_PRE) {
163 		*pval = (ASN1_VALUE *)DSA_new();
164 		if (*pval)
165 			return 2;
166 		return 0;
167 	} else if (operation == ASN1_OP_FREE_PRE) {
168 		DSA_free((DSA *)*pval);
169 		*pval = NULL;
170 		return 2;
171 	}
172 	return 1;
173 }
174 
175 static const ASN1_AUX DSAPrivateKey_aux = {
176 	.app_data = NULL,
177 	.flags = 0,
178 	.ref_offset = 0,
179 	.ref_lock = 0,
180 	.asn1_cb = dsa_cb,
181 	.enc_offset = 0,
182 };
183 static const ASN1_TEMPLATE DSAPrivateKey_seq_tt[] = {
184 	{
185 		.flags = 0,
186 		.tag = 0,
187 		.offset = offsetof(DSA, version),
188 		.field_name = "version",
189 		.item = &LONG_it,
190 	},
191 	{
192 		.flags = 0,
193 		.tag = 0,
194 		.offset = offsetof(DSA, p),
195 		.field_name = "p",
196 		.item = &BIGNUM_it,
197 	},
198 	{
199 		.flags = 0,
200 		.tag = 0,
201 		.offset = offsetof(DSA, q),
202 		.field_name = "q",
203 		.item = &BIGNUM_it,
204 	},
205 	{
206 		.flags = 0,
207 		.tag = 0,
208 		.offset = offsetof(DSA, g),
209 		.field_name = "g",
210 		.item = &BIGNUM_it,
211 	},
212 	{
213 		.flags = 0,
214 		.tag = 0,
215 		.offset = offsetof(DSA, pub_key),
216 		.field_name = "pub_key",
217 		.item = &BIGNUM_it,
218 	},
219 	{
220 		.flags = 0,
221 		.tag = 0,
222 		.offset = offsetof(DSA, priv_key),
223 		.field_name = "priv_key",
224 		.item = &BIGNUM_it,
225 	},
226 };
227 
228 const ASN1_ITEM DSAPrivateKey_it = {
229 	.itype = ASN1_ITYPE_SEQUENCE,
230 	.utype = V_ASN1_SEQUENCE,
231 	.templates = DSAPrivateKey_seq_tt,
232 	.tcount = sizeof(DSAPrivateKey_seq_tt) / sizeof(ASN1_TEMPLATE),
233 	.funcs = &DSAPrivateKey_aux,
234 	.size = sizeof(DSA),
235 	.sname = "DSA",
236 };
237 
238 
239 DSA *
240 d2i_DSAPrivateKey(DSA **a, const unsigned char **in, long len)
241 {
242 	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
243 	    &DSAPrivateKey_it);
244 }
245 
246 int
247 i2d_DSAPrivateKey(const DSA *a, unsigned char **out)
248 {
249 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPrivateKey_it);
250 }
251 
252 static const ASN1_AUX DSAparams_aux = {
253 	.app_data = NULL,
254 	.flags = 0,
255 	.ref_offset = 0,
256 	.ref_lock = 0,
257 	.asn1_cb = dsa_cb,
258 	.enc_offset = 0,
259 };
260 static const ASN1_TEMPLATE DSAparams_seq_tt[] = {
261 	{
262 		.flags = 0,
263 		.tag = 0,
264 		.offset = offsetof(DSA, p),
265 		.field_name = "p",
266 		.item = &BIGNUM_it,
267 	},
268 	{
269 		.flags = 0,
270 		.tag = 0,
271 		.offset = offsetof(DSA, q),
272 		.field_name = "q",
273 		.item = &BIGNUM_it,
274 	},
275 	{
276 		.flags = 0,
277 		.tag = 0,
278 		.offset = offsetof(DSA, g),
279 		.field_name = "g",
280 		.item = &BIGNUM_it,
281 	},
282 };
283 
284 const ASN1_ITEM DSAparams_it = {
285 	.itype = ASN1_ITYPE_SEQUENCE,
286 	.utype = V_ASN1_SEQUENCE,
287 	.templates = DSAparams_seq_tt,
288 	.tcount = sizeof(DSAparams_seq_tt) / sizeof(ASN1_TEMPLATE),
289 	.funcs = &DSAparams_aux,
290 	.size = sizeof(DSA),
291 	.sname = "DSA",
292 };
293 
294 
295 DSA *
296 d2i_DSAparams(DSA **a, const unsigned char **in, long len)
297 {
298 	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
299 	    &DSAparams_it);
300 }
301 
302 int
303 i2d_DSAparams(const DSA *a, unsigned char **out)
304 {
305 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAparams_it);
306 }
307 
308 DSA *
309 d2i_DSAparams_bio(BIO *bp, DSA **a)
310 {
311 	return ASN1_item_d2i_bio(&DSAparams_it, bp, a);
312 }
313 
314 int
315 i2d_DSAparams_bio(BIO *bp, DSA *a)
316 {
317 	return ASN1_item_i2d_bio(&DSAparams_it, bp, a);
318 }
319 
320 DSA *
321 d2i_DSAparams_fp(FILE *fp, DSA **a)
322 {
323 	return ASN1_item_d2i_fp(&DSAparams_it, fp, a);
324 }
325 
326 int
327 i2d_DSAparams_fp(FILE *fp, DSA *a)
328 {
329 	return ASN1_item_i2d_fp(&DSAparams_it, fp, a);
330 }
331 
332 static const ASN1_AUX DSAPublicKey_aux = {
333 	.app_data = NULL,
334 	.flags = 0,
335 	.ref_offset = 0,
336 	.ref_lock = 0,
337 	.asn1_cb = dsa_cb,
338 	.enc_offset = 0,
339 };
340 static const ASN1_TEMPLATE DSAPublicKey_seq_tt[] = {
341 	{
342 		.flags = 0,
343 		.tag = 0,
344 		.offset = offsetof(DSA, pub_key),
345 		.field_name = "pub_key",
346 		.item = &BIGNUM_it,
347 	},
348 	{
349 		.flags = 0,
350 		.tag = 0,
351 		.offset = offsetof(DSA, p),
352 		.field_name = "p",
353 		.item = &BIGNUM_it,
354 	},
355 	{
356 		.flags = 0,
357 		.tag = 0,
358 		.offset = offsetof(DSA, q),
359 		.field_name = "q",
360 		.item = &BIGNUM_it,
361 	},
362 	{
363 		.flags = 0,
364 		.tag = 0,
365 		.offset = offsetof(DSA, g),
366 		.field_name = "g",
367 		.item = &BIGNUM_it,
368 	},
369 };
370 
371 const ASN1_ITEM DSAPublicKey_it = {
372 	.itype = ASN1_ITYPE_SEQUENCE,
373 	.utype = V_ASN1_SEQUENCE,
374 	.templates = DSAPublicKey_seq_tt,
375 	.tcount = sizeof(DSAPublicKey_seq_tt) / sizeof(ASN1_TEMPLATE),
376 	.funcs = &DSAPublicKey_aux,
377 	.size = sizeof(DSA),
378 	.sname = "DSA",
379 };
380 
381 DSA *
382 d2i_DSAPublicKey(DSA **a, const unsigned char **in, long len)
383 {
384 	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
385 	    &DSAPublicKey_it);
386 }
387 
388 int
389 i2d_DSAPublicKey(const DSA *a, unsigned char **out)
390 {
391 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPublicKey_it);
392 }
393 
394 DSA *
395 DSAparams_dup(DSA *dsa)
396 {
397 	return ASN1_item_dup(&DSAparams_it, dsa);
398 }
399 
400 int
401 DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
402     unsigned int *siglen, DSA *dsa)
403 {
404 	DSA_SIG *s;
405 
406 	s = DSA_do_sign(dgst, dlen, dsa);
407 	if (s == NULL) {
408 		*siglen = 0;
409 		return 0;
410 	}
411 	*siglen = i2d_DSA_SIG(s,&sig);
412 	DSA_SIG_free(s);
413 	return 1;
414 }
415 
416 /*
417  * data has already been hashed (probably with SHA or SHA-1).
418  * returns
419  *      1: correct signature
420  *      0: incorrect signature
421  *     -1: error
422  */
423 int
424 DSA_verify(int type, const unsigned char *dgst, int dgst_len,
425     const unsigned char *sigbuf, int siglen, DSA *dsa)
426 {
427 	DSA_SIG *s;
428 	unsigned char *der = NULL;
429 	const unsigned char *p = sigbuf;
430 	int derlen = -1;
431 	int ret = -1;
432 
433 	s = DSA_SIG_new();
434 	if (s == NULL)
435 		return ret;
436 	if (d2i_DSA_SIG(&s, &p, siglen) == NULL)
437 		goto err;
438 	/* Ensure signature uses DER and doesn't have trailing garbage */
439 	derlen = i2d_DSA_SIG(s, &der);
440 	if (derlen != siglen || memcmp(sigbuf, der, derlen))
441 		goto err;
442 	ret = DSA_do_verify(dgst, dgst_len, s, dsa);
443 err:
444 	freezero(der, derlen);
445 	DSA_SIG_free(s);
446 	return ret;
447 }
448