Import LibreSSL v2.4.2 to vendor branch
[dragonfly.git] / crypto / libressl / crypto / dsa / dsa_asn1.c
1 /* $OpenBSD: dsa_asn1.c,v 1.15 2015/02/10 05:12: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 /* 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                         DSAerr(DSA_F_SIG_CB, 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 /* Override the default free and new methods */
137 static int
138 dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
139 {
140         if (operation == ASN1_OP_NEW_PRE) {
141                 *pval = (ASN1_VALUE *)DSA_new();
142                 if (*pval)
143                         return 2;
144                 return 0;
145         } else if (operation == ASN1_OP_FREE_PRE) {
146                 DSA_free((DSA *)*pval);
147                 *pval = NULL;
148                 return 2;
149         }
150         return 1;
151 }
152
153 static const ASN1_AUX DSAPrivateKey_aux = {
154         .app_data = NULL,
155         .flags = 0,
156         .ref_offset = 0,
157         .ref_lock = 0,
158         .asn1_cb = dsa_cb,
159         .enc_offset = 0,
160 };
161 static const ASN1_TEMPLATE DSAPrivateKey_seq_tt[] = {
162         {
163                 .flags = 0,
164                 .tag = 0,
165                 .offset = offsetof(DSA, version),
166                 .field_name = "version",
167                 .item = &LONG_it,
168         },
169         {
170                 .flags = 0,
171                 .tag = 0,
172                 .offset = offsetof(DSA, p),
173                 .field_name = "p",
174                 .item = &BIGNUM_it,
175         },
176         {
177                 .flags = 0,
178                 .tag = 0,
179                 .offset = offsetof(DSA, q),
180                 .field_name = "q",
181                 .item = &BIGNUM_it,
182         },
183         {
184                 .flags = 0,
185                 .tag = 0,
186                 .offset = offsetof(DSA, g),
187                 .field_name = "g",
188                 .item = &BIGNUM_it,
189         },
190         {
191                 .flags = 0,
192                 .tag = 0,
193                 .offset = offsetof(DSA, pub_key),
194                 .field_name = "pub_key",
195                 .item = &BIGNUM_it,
196         },
197         {
198                 .flags = 0,
199                 .tag = 0,
200                 .offset = offsetof(DSA, priv_key),
201                 .field_name = "priv_key",
202                 .item = &BIGNUM_it,
203         },
204 };
205
206 const ASN1_ITEM DSAPrivateKey_it = {
207         .itype = ASN1_ITYPE_SEQUENCE,
208         .utype = V_ASN1_SEQUENCE,
209         .templates = DSAPrivateKey_seq_tt,
210         .tcount = sizeof(DSAPrivateKey_seq_tt) / sizeof(ASN1_TEMPLATE),
211         .funcs = &DSAPrivateKey_aux,
212         .size = sizeof(DSA),
213         .sname = "DSA",
214 };
215
216
217 DSA *
218 d2i_DSAPrivateKey(DSA **a, const unsigned char **in, long len)
219 {
220         return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
221             &DSAPrivateKey_it);
222 }
223
224 int
225 i2d_DSAPrivateKey(const DSA *a, unsigned char **out)
226 {
227         return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPrivateKey_it);
228 }
229
230 static const ASN1_AUX DSAparams_aux = {
231         .app_data = NULL,
232         .flags = 0,
233         .ref_offset = 0,
234         .ref_lock = 0,
235         .asn1_cb = dsa_cb,
236         .enc_offset = 0,
237 };
238 static const ASN1_TEMPLATE DSAparams_seq_tt[] = {
239         {
240                 .flags = 0,
241                 .tag = 0,
242                 .offset = offsetof(DSA, p),
243                 .field_name = "p",
244                 .item = &BIGNUM_it,
245         },
246         {
247                 .flags = 0,
248                 .tag = 0,
249                 .offset = offsetof(DSA, q),
250                 .field_name = "q",
251                 .item = &BIGNUM_it,
252         },
253         {
254                 .flags = 0,
255                 .tag = 0,
256                 .offset = offsetof(DSA, g),
257                 .field_name = "g",
258                 .item = &BIGNUM_it,
259         },
260 };
261
262 const ASN1_ITEM DSAparams_it = {
263         .itype = ASN1_ITYPE_SEQUENCE,
264         .utype = V_ASN1_SEQUENCE,
265         .templates = DSAparams_seq_tt,
266         .tcount = sizeof(DSAparams_seq_tt) / sizeof(ASN1_TEMPLATE),
267         .funcs = &DSAparams_aux,
268         .size = sizeof(DSA),
269         .sname = "DSA",
270 };
271
272
273 DSA *
274 d2i_DSAparams(DSA **a, const unsigned char **in, long len)
275 {
276         return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
277             &DSAparams_it);
278 }
279
280 int
281 i2d_DSAparams(const DSA *a, unsigned char **out)
282 {
283         return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAparams_it);
284 }
285
286 /*
287  * DSA public key is a bit trickier... its effectively a CHOICE type
288  * decided by a field called write_params which can either write out
289  * just the public key as an INTEGER or the parameters and public key
290  * in a SEQUENCE
291  */
292
293 static const ASN1_TEMPLATE dsa_pub_internal_seq_tt[] = {
294         {
295                 .flags = 0,
296                 .tag = 0,
297                 .offset = offsetof(DSA, pub_key),
298                 .field_name = "pub_key",
299                 .item = &BIGNUM_it,
300         },
301         {
302                 .flags = 0,
303                 .tag = 0,
304                 .offset = offsetof(DSA, p),
305                 .field_name = "p",
306                 .item = &BIGNUM_it,
307         },
308         {
309                 .flags = 0,
310                 .tag = 0,
311                 .offset = offsetof(DSA, q),
312                 .field_name = "q",
313                 .item = &BIGNUM_it,
314         },
315         {
316                 .flags = 0,
317                 .tag = 0,
318                 .offset = offsetof(DSA, g),
319                 .field_name = "g",
320                 .item = &BIGNUM_it,
321         },
322 };
323
324 const ASN1_ITEM dsa_pub_internal_it = {
325         .itype = ASN1_ITYPE_SEQUENCE,
326         .utype = V_ASN1_SEQUENCE,
327         .templates = dsa_pub_internal_seq_tt,
328         .tcount = sizeof(dsa_pub_internal_seq_tt) / sizeof(ASN1_TEMPLATE),
329         .funcs = NULL,
330         .size = sizeof(DSA),
331         .sname = "DSA",
332 };
333
334 static const ASN1_AUX DSAPublicKey_aux = {
335         .app_data = NULL,
336         .flags = 0,
337         .ref_offset = 0,
338         .ref_lock = 0,
339         .asn1_cb = dsa_cb,
340         .enc_offset = 0,
341 };
342 static const ASN1_TEMPLATE DSAPublicKey_ch_tt[] = {
343         {
344                 .flags = 0,
345                 .tag = 0,
346                 .offset = offsetof(DSA, pub_key),
347                 .field_name = "pub_key",
348                 .item = &BIGNUM_it,
349         },
350         {
351                 .flags = 0 | ASN1_TFLG_COMBINE,
352                 .tag = 0,
353                 .offset = 0,
354                 .field_name = NULL,
355                 .item = &dsa_pub_internal_it,
356         },
357 };
358
359 const ASN1_ITEM DSAPublicKey_it = {
360         .itype = ASN1_ITYPE_CHOICE,
361         .utype = offsetof(DSA, write_params),
362         .templates = DSAPublicKey_ch_tt,
363         .tcount = sizeof(DSAPublicKey_ch_tt) / sizeof(ASN1_TEMPLATE),
364         .funcs = &DSAPublicKey_aux,
365         .size = sizeof(DSA),
366         .sname = "DSA",
367 };
368
369
370 DSA *
371 d2i_DSAPublicKey(DSA **a, const unsigned char **in, long len)
372 {
373         return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
374             &DSAPublicKey_it);
375 }
376
377 int
378 i2d_DSAPublicKey(const DSA *a, unsigned char **out)
379 {
380         return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPublicKey_it);
381 }
382
383 DSA *
384 DSAparams_dup(DSA *dsa)
385 {
386         return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), dsa);
387 }
388
389 int
390 DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
391     unsigned int *siglen, DSA *dsa)
392 {
393         DSA_SIG *s;
394
395         s = DSA_do_sign(dgst, dlen, dsa);
396         if (s == NULL) {
397                 *siglen = 0;
398                 return 0;
399         }
400         *siglen = i2d_DSA_SIG(s,&sig);
401         DSA_SIG_free(s);
402         return 1;
403 }
404
405 /*
406  * data has already been hashed (probably with SHA or SHA-1).
407  * returns
408  *      1: correct signature
409  *      0: incorrect signature
410  *     -1: error
411  */
412 int
413 DSA_verify(int type, const unsigned char *dgst, int dgst_len,
414     const unsigned char *sigbuf, int siglen, DSA *dsa)
415 {
416         DSA_SIG *s;
417         unsigned char *der = NULL;
418         const unsigned char *p = sigbuf;
419         int derlen = -1;
420         int ret = -1;
421
422         s = DSA_SIG_new();
423         if (s == NULL)
424                 return ret;
425         if (d2i_DSA_SIG(&s, &p, siglen) == NULL)
426                 goto err;
427         /* Ensure signature uses DER and doesn't have trailing garbage */
428         derlen = i2d_DSA_SIG(s, &der);
429         if (derlen != siglen || memcmp(sigbuf, der, derlen))
430                 goto err;
431         ret = DSA_do_verify(dgst, dgst_len, s, dsa);
432 err:
433         if (derlen > 0) {
434                 explicit_bzero(der, derlen);
435                 free(der);
436         }
437         DSA_SIG_free(s);
438         return ret;
439 }