c90d09b0f06f9a4ca2fc58af85872ca4a875a919
[openssl.git] / crypto / dsa / dsa_lib.c
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 /* Original version from Steven Schoch <schoch@sheba.arc.nasa.gov> */
11
12 #include <stdio.h>
13 #include "internal/cryptlib.h"
14 #include <openssl/bn.h>
15 #include "dsa_locl.h"
16 #include <openssl/asn1.h>
17 #include <openssl/engine.h>
18 #include <openssl/dh.h>
19
20 DSA *DSA_new(void)
21 {
22     return DSA_new_method(NULL);
23 }
24
25 int DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
26 {
27     /*
28      * NB: The caller is specifically setting a method, so it's not up to us
29      * to deal with which ENGINE it comes from.
30      */
31     const DSA_METHOD *mtmp;
32     mtmp = dsa->meth;
33     if (mtmp->finish)
34         mtmp->finish(dsa);
35 #ifndef OPENSSL_NO_ENGINE
36     ENGINE_finish(dsa->engine);
37     dsa->engine = NULL;
38 #endif
39     dsa->meth = meth;
40     if (meth->init)
41         meth->init(dsa);
42     return 1;
43 }
44
45 const DSA_METHOD *DSA_get_method(DSA *d)
46 {
47     return d->meth;
48 }
49
50 DSA *DSA_new_method(ENGINE *engine)
51 {
52     DSA *ret = OPENSSL_zalloc(sizeof(*ret));
53
54     if (ret == NULL) {
55         DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
56         return NULL;
57     }
58
59     ret->references = 1;
60     ret->lock = CRYPTO_THREAD_lock_new();
61     if (ret->lock == NULL) {
62         DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
63         OPENSSL_free(ret);
64         return NULL;
65     }
66
67     ret->meth = DSA_get_default_method();
68 #ifndef OPENSSL_NO_ENGINE
69     ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; /* early default init */
70     if (engine) {
71         if (!ENGINE_init(engine)) {
72             DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
73             goto err;
74         }
75         ret->engine = engine;
76     } else
77         ret->engine = ENGINE_get_default_DSA();
78     if (ret->engine) {
79         ret->meth = ENGINE_get_DSA(ret->engine);
80         if (ret->meth == NULL) {
81             DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
82             goto err;
83         }
84     }
85 #endif
86
87     ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
88
89     if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data))
90         goto err;
91
92     if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
93         DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_INIT_FAIL);
94 err:
95         DSA_free(ret);
96         ret = NULL;
97     }
98
99     return ret;
100 }
101
102 void DSA_free(DSA *r)
103 {
104     int i;
105
106     if (r == NULL)
107         return;
108
109     CRYPTO_DOWN_REF(&r->references, &i, r->lock);
110     REF_PRINT_COUNT("DSA", r);
111     if (i > 0)
112         return;
113     REF_ASSERT_ISNT(i < 0);
114
115     if (r->meth->finish)
116         r->meth->finish(r);
117 #ifndef OPENSSL_NO_ENGINE
118     ENGINE_finish(r->engine);
119 #endif
120
121     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data);
122
123     CRYPTO_THREAD_lock_free(r->lock);
124
125     BN_clear_free(r->p);
126     BN_clear_free(r->q);
127     BN_clear_free(r->g);
128     BN_clear_free(r->pub_key);
129     BN_clear_free(r->priv_key);
130     OPENSSL_free(r);
131 }
132
133 int DSA_up_ref(DSA *r)
134 {
135     int i;
136
137     if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0)
138         return 0;
139
140     REF_PRINT_COUNT("DSA", r);
141     REF_ASSERT_ISNT(i < 2);
142     return ((i > 1) ? 1 : 0);
143 }
144
145 int DSA_size(const DSA *r)
146 {
147     int ret, i;
148     ASN1_INTEGER bs;
149     unsigned char buf[4];       /* 4 bytes looks really small. However,
150                                  * i2d_ASN1_INTEGER() will not look beyond
151                                  * the first byte, as long as the second
152                                  * parameter is NULL. */
153
154     i = BN_num_bits(r->q);
155     bs.length = (i + 7) / 8;
156     bs.data = buf;
157     bs.type = V_ASN1_INTEGER;
158     /* If the top bit is set the asn1 encoding is 1 larger. */
159     buf[0] = 0xff;
160
161     i = i2d_ASN1_INTEGER(&bs, NULL);
162     i += i;                     /* r and s */
163     ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
164     return (ret);
165 }
166
167 int DSA_set_ex_data(DSA *d, int idx, void *arg)
168 {
169     return (CRYPTO_set_ex_data(&d->ex_data, idx, arg));
170 }
171
172 void *DSA_get_ex_data(DSA *d, int idx)
173 {
174     return (CRYPTO_get_ex_data(&d->ex_data, idx));
175 }
176
177 int DSA_security_bits(const DSA *d)
178 {
179     if (d->p && d->q)
180         return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q));
181     return -1;
182 }
183
184 #ifndef OPENSSL_NO_DH
185 DH *DSA_dup_DH(const DSA *r)
186 {
187     /*
188      * DSA has p, q, g, optional pub_key, optional priv_key. DH has p,
189      * optional length, g, optional pub_key, optional priv_key, optional q.
190      */
191
192     DH *ret = NULL;
193     BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;
194
195     if (r == NULL)
196         goto err;
197     ret = DH_new();
198     if (ret == NULL)
199         goto err;
200     if (r->p != NULL || r->g != NULL || r->q != NULL) {
201         if (r->p == NULL || r->g == NULL || r->q == NULL) {
202             /* Shouldn't happen */
203             goto err;
204         }
205         p = BN_dup(r->p);
206         g = BN_dup(r->g);
207         q = BN_dup(r->q);
208         if (p == NULL || g == NULL || q == NULL || !DH_set0_pqg(ret, p, q, g))
209             goto err;
210         p = g = q = NULL;
211     }
212
213     if (r->pub_key != NULL) {
214         pub_key = BN_dup(r->pub_key);
215         if (pub_key == NULL)
216             goto err;
217         if (r->priv_key != NULL) {
218             priv_key = BN_dup(r->priv_key);
219             if (priv_key == NULL)
220                 goto err;
221         }
222         if (!DH_set0_key(ret, pub_key, priv_key))
223             goto err;
224     } else if (r->priv_key != NULL) {
225         /* Shouldn't happen */
226         goto err;
227     }
228
229     return ret;
230
231  err:
232     BN_free(p);
233     BN_free(g);
234     BN_free(q);
235     BN_free(pub_key);
236     BN_free(priv_key);
237     DH_free(ret);
238     return NULL;
239 }
240 #endif
241
242 void DSA_get0_pqg(const DSA *d,
243                   const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
244 {
245     if (p != NULL)
246         *p = d->p;
247     if (q != NULL)
248         *q = d->q;
249     if (g != NULL)
250         *g = d->g;
251 }
252
253 int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
254 {
255     /* If the fields p, q and g in d are NULL, the corresponding input
256      * parameters MUST be non-NULL.
257      */
258     if ((d->p == NULL && p == NULL)
259         || (d->q == NULL && q == NULL)
260         || (d->g == NULL && g == NULL))
261         return 0;
262
263     if (p != NULL) {
264         BN_free(d->p);
265         d->p = p;
266     }
267     if (q != NULL) {
268         BN_free(d->q);
269         d->q = q;
270     }
271     if (g != NULL) {
272         BN_free(d->g);
273         d->g = g;
274     }
275
276     return 1;
277 }
278
279 void DSA_get0_key(const DSA *d,
280                   const BIGNUM **pub_key, const BIGNUM **priv_key)
281 {
282     if (pub_key != NULL)
283         *pub_key = d->pub_key;
284     if (priv_key != NULL)
285         *priv_key = d->priv_key;
286 }
287
288 int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
289 {
290     /* If the field pub_key in d is NULL, the corresponding input
291      * parameters MUST be non-NULL.  The priv_key field may
292      * be left NULL.
293      */
294     if (d->pub_key == NULL && pub_key == NULL)
295         return 0;
296
297     if (pub_key != NULL) {
298         BN_free(d->pub_key);
299         d->pub_key = pub_key;
300     }
301     if (priv_key != NULL) {
302         BN_free(d->priv_key);
303         d->priv_key = priv_key;
304     }
305
306     return 1;
307 }
308
309 void DSA_clear_flags(DSA *d, int flags)
310 {
311     d->flags &= ~flags;
312 }
313
314 int DSA_test_flags(const DSA *d, int flags)
315 {
316     return d->flags & flags;
317 }
318
319 void DSA_set_flags(DSA *d, int flags)
320 {
321     d->flags |= flags;
322 }
323
324 ENGINE *DSA_get0_engine(DSA *d)
325 {
326     return d->engine;
327 }
328
329 int DSA_bits(const DSA *dsa)
330 {
331     return BN_num_bits(dsa->p);
332 }