xref: /dragonfly/crypto/libressl/crypto/dsa/dsa_asn1.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
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