xref: /openbsd-src/lib/libcrypto/dsa/dsa_asn1.c (revision ff0e7be1ebbcc809ea8ad2b6dafe215824da9e46)
1 /* $OpenBSD: dsa_asn1.c,v 1.30 2023/03/25 09:09:28 tb 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/bn.h>
65 #include <openssl/dsa.h>
66 #include <openssl/err.h>
67 
68 #include "dsa_local.h"
69 
70 /* Override the default new methods */
71 static int
72 sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
73 {
74 	if (operation == ASN1_OP_NEW_PRE) {
75 		DSA_SIG *sig;
76 
77 		if ((sig = DSA_SIG_new()) == NULL) {
78 			DSAerror(ERR_R_MALLOC_FAILURE);
79 			return 0;
80 		}
81 		*pval = (ASN1_VALUE *)sig;
82 		return 2;
83 	}
84 	return 1;
85 }
86 
87 static const ASN1_AUX DSA_SIG_aux = {
88 	.app_data = NULL,
89 	.flags = 0,
90 	.ref_offset = 0,
91 	.ref_lock = 0,
92 	.asn1_cb = sig_cb,
93 	.enc_offset = 0,
94 };
95 static const ASN1_TEMPLATE DSA_SIG_seq_tt[] = {
96 	{
97 		.flags = 0,
98 		.tag = 0,
99 		.offset = offsetof(DSA_SIG, r),
100 		.field_name = "r",
101 		.item = &BIGNUM_it,
102 	},
103 	{
104 		.flags = 0,
105 		.tag = 0,
106 		.offset = offsetof(DSA_SIG, s),
107 		.field_name = "s",
108 		.item = &BIGNUM_it,
109 	},
110 };
111 
112 const ASN1_ITEM DSA_SIG_it = {
113 	.itype = ASN1_ITYPE_SEQUENCE,
114 	.utype = V_ASN1_SEQUENCE,
115 	.templates = DSA_SIG_seq_tt,
116 	.tcount = sizeof(DSA_SIG_seq_tt) / sizeof(ASN1_TEMPLATE),
117 	.funcs = &DSA_SIG_aux,
118 	.size = sizeof(DSA_SIG),
119 	.sname = "DSA_SIG",
120 };
121 
122 
123 DSA_SIG *
124 d2i_DSA_SIG(DSA_SIG **a, const unsigned char **in, long len)
125 {
126 	return (DSA_SIG *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
127 	    &DSA_SIG_it);
128 }
129 
130 int
131 i2d_DSA_SIG(const DSA_SIG *a, unsigned char **out)
132 {
133 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSA_SIG_it);
134 }
135 
136 void
137 DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
138 {
139 	if (pr != NULL)
140 		*pr = sig->r;
141 	if (ps != NULL)
142 		*ps = sig->s;
143 }
144 
145 int
146 DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
147 {
148 	if (r == NULL || s == NULL)
149 		return 0;
150 
151 	BN_free(sig->r);
152 	sig->r = r;
153 	BN_free(sig->s);
154 	sig->s = s;
155 
156 	return 1;
157 }
158 
159 /* Override the default free and new methods */
160 static int
161 dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
162 {
163 	if (operation == ASN1_OP_NEW_PRE) {
164 		*pval = (ASN1_VALUE *)DSA_new();
165 		if (*pval)
166 			return 2;
167 		return 0;
168 	} else if (operation == ASN1_OP_FREE_PRE) {
169 		DSA_free((DSA *)*pval);
170 		*pval = NULL;
171 		return 2;
172 	}
173 	return 1;
174 }
175 
176 static const ASN1_AUX DSAPrivateKey_aux = {
177 	.app_data = NULL,
178 	.flags = 0,
179 	.ref_offset = 0,
180 	.ref_lock = 0,
181 	.asn1_cb = dsa_cb,
182 	.enc_offset = 0,
183 };
184 static const ASN1_TEMPLATE DSAPrivateKey_seq_tt[] = {
185 	{
186 		.flags = 0,
187 		.tag = 0,
188 		.offset = offsetof(DSA, version),
189 		.field_name = "version",
190 		.item = &LONG_it,
191 	},
192 	{
193 		.flags = 0,
194 		.tag = 0,
195 		.offset = offsetof(DSA, p),
196 		.field_name = "p",
197 		.item = &BIGNUM_it,
198 	},
199 	{
200 		.flags = 0,
201 		.tag = 0,
202 		.offset = offsetof(DSA, q),
203 		.field_name = "q",
204 		.item = &BIGNUM_it,
205 	},
206 	{
207 		.flags = 0,
208 		.tag = 0,
209 		.offset = offsetof(DSA, g),
210 		.field_name = "g",
211 		.item = &BIGNUM_it,
212 	},
213 	{
214 		.flags = 0,
215 		.tag = 0,
216 		.offset = offsetof(DSA, pub_key),
217 		.field_name = "pub_key",
218 		.item = &BIGNUM_it,
219 	},
220 	{
221 		.flags = 0,
222 		.tag = 0,
223 		.offset = offsetof(DSA, priv_key),
224 		.field_name = "priv_key",
225 		.item = &BIGNUM_it,
226 	},
227 };
228 
229 const ASN1_ITEM DSAPrivateKey_it = {
230 	.itype = ASN1_ITYPE_SEQUENCE,
231 	.utype = V_ASN1_SEQUENCE,
232 	.templates = DSAPrivateKey_seq_tt,
233 	.tcount = sizeof(DSAPrivateKey_seq_tt) / sizeof(ASN1_TEMPLATE),
234 	.funcs = &DSAPrivateKey_aux,
235 	.size = sizeof(DSA),
236 	.sname = "DSA",
237 };
238 
239 
240 DSA *
241 d2i_DSAPrivateKey(DSA **a, const unsigned char **in, long len)
242 {
243 	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
244 	    &DSAPrivateKey_it);
245 }
246 
247 int
248 i2d_DSAPrivateKey(const DSA *a, unsigned char **out)
249 {
250 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPrivateKey_it);
251 }
252 
253 static const ASN1_AUX DSAparams_aux = {
254 	.app_data = NULL,
255 	.flags = 0,
256 	.ref_offset = 0,
257 	.ref_lock = 0,
258 	.asn1_cb = dsa_cb,
259 	.enc_offset = 0,
260 };
261 static const ASN1_TEMPLATE DSAparams_seq_tt[] = {
262 	{
263 		.flags = 0,
264 		.tag = 0,
265 		.offset = offsetof(DSA, p),
266 		.field_name = "p",
267 		.item = &BIGNUM_it,
268 	},
269 	{
270 		.flags = 0,
271 		.tag = 0,
272 		.offset = offsetof(DSA, q),
273 		.field_name = "q",
274 		.item = &BIGNUM_it,
275 	},
276 	{
277 		.flags = 0,
278 		.tag = 0,
279 		.offset = offsetof(DSA, g),
280 		.field_name = "g",
281 		.item = &BIGNUM_it,
282 	},
283 };
284 
285 const ASN1_ITEM DSAparams_it = {
286 	.itype = ASN1_ITYPE_SEQUENCE,
287 	.utype = V_ASN1_SEQUENCE,
288 	.templates = DSAparams_seq_tt,
289 	.tcount = sizeof(DSAparams_seq_tt) / sizeof(ASN1_TEMPLATE),
290 	.funcs = &DSAparams_aux,
291 	.size = sizeof(DSA),
292 	.sname = "DSA",
293 };
294 
295 
296 DSA *
297 d2i_DSAparams(DSA **a, const unsigned char **in, long len)
298 {
299 	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
300 	    &DSAparams_it);
301 }
302 
303 int
304 i2d_DSAparams(const DSA *a, unsigned char **out)
305 {
306 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAparams_it);
307 }
308 
309 DSA *
310 d2i_DSAparams_bio(BIO *bp, DSA **a)
311 {
312 	return ASN1_item_d2i_bio(&DSAparams_it, bp, a);
313 }
314 
315 int
316 i2d_DSAparams_bio(BIO *bp, DSA *a)
317 {
318 	return ASN1_item_i2d_bio(&DSAparams_it, bp, a);
319 }
320 
321 DSA *
322 d2i_DSAparams_fp(FILE *fp, DSA **a)
323 {
324 	return ASN1_item_d2i_fp(&DSAparams_it, fp, a);
325 }
326 
327 int
328 i2d_DSAparams_fp(FILE *fp, DSA *a)
329 {
330 	return ASN1_item_i2d_fp(&DSAparams_it, fp, a);
331 }
332 
333 static const ASN1_AUX DSAPublicKey_aux = {
334 	.app_data = NULL,
335 	.flags = 0,
336 	.ref_offset = 0,
337 	.ref_lock = 0,
338 	.asn1_cb = dsa_cb,
339 	.enc_offset = 0,
340 };
341 static const ASN1_TEMPLATE DSAPublicKey_seq_tt[] = {
342 	{
343 		.flags = 0,
344 		.tag = 0,
345 		.offset = offsetof(DSA, pub_key),
346 		.field_name = "pub_key",
347 		.item = &BIGNUM_it,
348 	},
349 	{
350 		.flags = 0,
351 		.tag = 0,
352 		.offset = offsetof(DSA, p),
353 		.field_name = "p",
354 		.item = &BIGNUM_it,
355 	},
356 	{
357 		.flags = 0,
358 		.tag = 0,
359 		.offset = offsetof(DSA, q),
360 		.field_name = "q",
361 		.item = &BIGNUM_it,
362 	},
363 	{
364 		.flags = 0,
365 		.tag = 0,
366 		.offset = offsetof(DSA, g),
367 		.field_name = "g",
368 		.item = &BIGNUM_it,
369 	},
370 };
371 
372 const ASN1_ITEM DSAPublicKey_it = {
373 	.itype = ASN1_ITYPE_SEQUENCE,
374 	.utype = V_ASN1_SEQUENCE,
375 	.templates = DSAPublicKey_seq_tt,
376 	.tcount = sizeof(DSAPublicKey_seq_tt) / sizeof(ASN1_TEMPLATE),
377 	.funcs = &DSAPublicKey_aux,
378 	.size = sizeof(DSA),
379 	.sname = "DSA",
380 };
381 
382 DSA *
383 d2i_DSAPublicKey(DSA **a, const unsigned char **in, long len)
384 {
385 	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
386 	    &DSAPublicKey_it);
387 }
388 
389 int
390 i2d_DSAPublicKey(const DSA *a, unsigned char **out)
391 {
392 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPublicKey_it);
393 }
394 
395 DSA *
396 DSAparams_dup(DSA *dsa)
397 {
398 	return ASN1_item_dup(&DSAparams_it, dsa);
399 }
400 
401 int
402 DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
403     unsigned int *out_siglen, DSA *dsa)
404 {
405 	DSA_SIG *s;
406 	int siglen;
407 	int ret = 0;
408 
409 	*out_siglen = 0;
410 
411 	if ((s = DSA_do_sign(dgst, dlen, dsa)) == NULL)
412 		goto err;
413 
414 	if ((siglen = i2d_DSA_SIG(s, &sig)) < 0)
415 		goto err;
416 
417 	*out_siglen = siglen;
418 
419 	ret = 1;
420  err:
421 	DSA_SIG_free(s);
422 
423 	return ret;
424 }
425 
426 /*
427  * data has already been hashed (probably with SHA or SHA-1).
428  * returns
429  *      1: correct signature
430  *      0: incorrect signature
431  *     -1: error
432  */
433 int
434 DSA_verify(int type, const unsigned char *dgst, int dgst_len,
435     const unsigned char *sigbuf, int siglen, DSA *dsa)
436 {
437 	DSA_SIG *s = NULL;
438 	unsigned char *der = NULL;
439 	const unsigned char *p;
440 	int ret = -1;
441 
442 	p = sigbuf;
443 	if ((s = d2i_DSA_SIG(NULL, &p, siglen)) == NULL)
444 		goto err;
445 
446 	/* Ensure signature uses DER and doesn't have trailing garbage */
447 	if (i2d_DSA_SIG(s, &der) != siglen)
448 		goto err;
449 
450 	if (memcmp(der, sigbuf, siglen) != 0)
451 		goto err;
452 
453 	ret = DSA_do_verify(dgst, dgst_len, s, dsa);
454  err:
455 	free(der);
456 	DSA_SIG_free(s);
457 
458 	return ret;
459 }
460