xref: /openbsd-src/lib/libcrypto/dsa/dsa_asn1.c (revision 6c6408334dbede3a2c0dcd9ff9c489157df0c856)
1 /* $OpenBSD: dsa_asn1.c,v 1.21 2018/02/20 17:48:35 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/dsa.h>
65 #include <openssl/err.h>
66 
67 /* Override the default new methods */
68 static int
69 sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
70 {
71 	if (operation == ASN1_OP_NEW_PRE) {
72 		DSA_SIG *sig;
73 
74 		sig = malloc(sizeof(DSA_SIG));
75 		if (!sig) {
76 			DSAerror(ERR_R_MALLOC_FAILURE);
77 			return 0;
78 		}
79 		sig->r = NULL;
80 		sig->s = NULL;
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 = &CBIGNUM_it,
102 	},
103 	{
104 		.flags = 0,
105 		.tag = 0,
106 		.offset = offsetof(DSA_SIG, s),
107 		.field_name = "s",
108 		.item = &CBIGNUM_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_clear_free(sig->r);
152 	sig->r = r;
153 	BN_clear_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 /*
334  * DSA public key is a bit trickier... its effectively a CHOICE type
335  * decided by a field called write_params which can either write out
336  * just the public key as an INTEGER or the parameters and public key
337  * in a SEQUENCE
338  */
339 
340 static const ASN1_TEMPLATE dsa_pub_internal_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 dsa_pub_internal_it = {
372 	.itype = ASN1_ITYPE_SEQUENCE,
373 	.utype = V_ASN1_SEQUENCE,
374 	.templates = dsa_pub_internal_seq_tt,
375 	.tcount = sizeof(dsa_pub_internal_seq_tt) / sizeof(ASN1_TEMPLATE),
376 	.funcs = NULL,
377 	.size = sizeof(DSA),
378 	.sname = "DSA",
379 };
380 
381 static const ASN1_AUX DSAPublicKey_aux = {
382 	.app_data = NULL,
383 	.flags = 0,
384 	.ref_offset = 0,
385 	.ref_lock = 0,
386 	.asn1_cb = dsa_cb,
387 	.enc_offset = 0,
388 };
389 static const ASN1_TEMPLATE DSAPublicKey_ch_tt[] = {
390 	{
391 		.flags = 0,
392 		.tag = 0,
393 		.offset = offsetof(DSA, pub_key),
394 		.field_name = "pub_key",
395 		.item = &BIGNUM_it,
396 	},
397 	{
398 		.flags = 0 | ASN1_TFLG_COMBINE,
399 		.tag = 0,
400 		.offset = 0,
401 		.field_name = NULL,
402 		.item = &dsa_pub_internal_it,
403 	},
404 };
405 
406 const ASN1_ITEM DSAPublicKey_it = {
407 	.itype = ASN1_ITYPE_CHOICE,
408 	.utype = offsetof(DSA, write_params),
409 	.templates = DSAPublicKey_ch_tt,
410 	.tcount = sizeof(DSAPublicKey_ch_tt) / sizeof(ASN1_TEMPLATE),
411 	.funcs = &DSAPublicKey_aux,
412 	.size = sizeof(DSA),
413 	.sname = "DSA",
414 };
415 
416 
417 DSA *
418 d2i_DSAPublicKey(DSA **a, const unsigned char **in, long len)
419 {
420 	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
421 	    &DSAPublicKey_it);
422 }
423 
424 int
425 i2d_DSAPublicKey(const DSA *a, unsigned char **out)
426 {
427 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPublicKey_it);
428 }
429 
430 DSA *
431 DSAparams_dup(DSA *dsa)
432 {
433 	return ASN1_item_dup(&DSAparams_it, dsa);
434 }
435 
436 int
437 DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
438     unsigned int *siglen, DSA *dsa)
439 {
440 	DSA_SIG *s;
441 
442 	s = DSA_do_sign(dgst, dlen, dsa);
443 	if (s == NULL) {
444 		*siglen = 0;
445 		return 0;
446 	}
447 	*siglen = i2d_DSA_SIG(s,&sig);
448 	DSA_SIG_free(s);
449 	return 1;
450 }
451 
452 /*
453  * data has already been hashed (probably with SHA or SHA-1).
454  * returns
455  *      1: correct signature
456  *      0: incorrect signature
457  *     -1: error
458  */
459 int
460 DSA_verify(int type, const unsigned char *dgst, int dgst_len,
461     const unsigned char *sigbuf, int siglen, DSA *dsa)
462 {
463 	DSA_SIG *s;
464 	unsigned char *der = NULL;
465 	const unsigned char *p = sigbuf;
466 	int derlen = -1;
467 	int ret = -1;
468 
469 	s = DSA_SIG_new();
470 	if (s == NULL)
471 		return ret;
472 	if (d2i_DSA_SIG(&s, &p, siglen) == NULL)
473 		goto err;
474 	/* Ensure signature uses DER and doesn't have trailing garbage */
475 	derlen = i2d_DSA_SIG(s, &der);
476 	if (derlen != siglen || memcmp(sigbuf, der, derlen))
477 		goto err;
478 	ret = DSA_do_verify(dgst, dgst_len, s, dsa);
479 err:
480 	freezero(der, derlen);
481 	DSA_SIG_free(s);
482 	return ret;
483 }
484