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
sig_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)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 *
d2i_DSA_SIG(DSA_SIG ** a,const unsigned char ** in,long len)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
i2d_DSA_SIG(const DSA_SIG * a,unsigned char ** out)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
DSA_SIG_get0(const DSA_SIG * sig,const BIGNUM ** pr,const BIGNUM ** ps)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
DSA_SIG_set0(DSA_SIG * sig,BIGNUM * r,BIGNUM * s)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
dsa_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)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 *
d2i_DSAPrivateKey(DSA ** a,const unsigned char ** in,long len)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
i2d_DSAPrivateKey(const DSA * a,unsigned char ** out)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 *
d2i_DSAparams(DSA ** a,const unsigned char ** in,long len)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
i2d_DSAparams(const DSA * a,unsigned char ** out)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 *
d2i_DSAparams_bio(BIO * bp,DSA ** a)309 d2i_DSAparams_bio(BIO *bp, DSA **a)
310 {
311 return ASN1_item_d2i_bio(&DSAparams_it, bp, a);
312 }
313
314 int
i2d_DSAparams_bio(BIO * bp,DSA * a)315 i2d_DSAparams_bio(BIO *bp, DSA *a)
316 {
317 return ASN1_item_i2d_bio(&DSAparams_it, bp, a);
318 }
319
320 DSA *
d2i_DSAparams_fp(FILE * fp,DSA ** a)321 d2i_DSAparams_fp(FILE *fp, DSA **a)
322 {
323 return ASN1_item_d2i_fp(&DSAparams_it, fp, a);
324 }
325
326 int
i2d_DSAparams_fp(FILE * fp,DSA * a)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 *
d2i_DSAPublicKey(DSA ** a,const unsigned char ** in,long len)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
i2d_DSAPublicKey(const DSA * a,unsigned char ** out)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 *
DSAparams_dup(DSA * dsa)395 DSAparams_dup(DSA *dsa)
396 {
397 return ASN1_item_dup(&DSAparams_it, dsa);
398 }
399
400 int
DSA_sign(int type,const unsigned char * dgst,int dlen,unsigned char * sig,unsigned int * siglen,DSA * dsa)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
DSA_verify(int type,const unsigned char * dgst,int dgst_len,const unsigned char * sigbuf,int siglen,DSA * dsa)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