dsa_lib.c revision 296341
1132718Skan/* crypto/dsa/dsa_lib.c */
2189824Sdas/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3189824Sdas * All rights reserved.
4132718Skan *
5132718Skan * This package is an SSL implementation written
6132718Skan * by Eric Young (eay@cryptsoft.com).
7132718Skan * The implementation was written so as to conform with Netscapes SSL.
8132718Skan *
9132718Skan * This library is free for commercial and non-commercial use as long as
10132718Skan * the following conditions are aheared to.  The following conditions
11132718Skan * apply to all code found in this distribution, be it the RC4, RSA,
12132718Skan * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13132718Skan * included with this distribution is covered by the same copyright terms
14132718Skan * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15132718Skan *
16132718Skan * Copyright remains Eric Young's, and as such any Copyright notices in
17132718Skan * the code are not to be removed.
18132718Skan * If this package is used in a product, Eric Young should be given attribution
19169689Skan * as the author of the parts of the library used.
20169689Skan * This can be in the form of a textual message at program startup or
21132718Skan * in documentation (online or textual) provided with the package.
22132718Skan *
23132718Skan * Redistribution and use in source and binary forms, with or without
24132718Skan * modification, are permitted provided that the following conditions
25132718Skan * are met:
26132718Skan * 1. Redistributions of source code must retain the copyright
27169689Skan *    notice, this list of conditions and the following disclaimer.
28132718Skan * 2. Redistributions in binary form must reproduce the above copyright
29132718Skan *    notice, this list of conditions and the following disclaimer in the
30132718Skan *    documentation and/or other materials provided with the distribution.
31132718Skan * 3. All advertising materials mentioning features or use of this software
32132718Skan *    must display the following acknowledgement:
33132718Skan *    "This product includes cryptographic software written by
34132718Skan *     Eric Young (eay@cryptsoft.com)"
35132718Skan *    The word 'cryptographic' can be left out if the rouines from the library
36169689Skan *    being used are not cryptographic related :-).
37132718Skan * 4. If you include any Windows specific code (or a derivative thereof) from
38132718Skan *    the apps directory (application code) you must include an acknowledgement:
39132718Skan *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40132718Skan *
41132718Skan * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43132718Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44132718Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45132718Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46132718Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47132718Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48132718Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49132718Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50132718Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51132718Skan * SUCH DAMAGE.
52132718Skan *
53132718Skan * The licence and distribution terms for any publically available version or
54132718Skan * derivative of this code cannot be changed.  i.e. this code cannot simply be
55132718Skan * copied and put under another distribution licence
56132718Skan * [including the GNU Public Licence.]
57169689Skan */
58132718Skan
59169689Skan/* Original version from Steven Schoch <schoch@sheba.arc.nasa.gov> */
60132718Skan
61132718Skan#include <stdio.h>
62169689Skan#include "cryptlib.h"
63169689Skan#include <openssl/bn.h>
64169689Skan#include <openssl/dsa.h>
65132718Skan#include <openssl/asn1.h>
66132718Skan#ifndef OPENSSL_NO_ENGINE
67132718Skan# include <openssl/engine.h>
68132718Skan#endif
69132718Skan#ifndef OPENSSL_NO_DH
70132718Skan# include <openssl/dh.h>
71132718Skan#endif
72132718Skan
73132718Skan#ifdef OPENSSL_FIPS
74132718Skan# include <openssl/fips.h>
75169689Skan#endif
76169689Skan
77132718Skanconst char DSA_version[] = "DSA" OPENSSL_VERSION_PTEXT;
78169689Skan
79169689Skanstatic const DSA_METHOD *default_DSA_method = NULL;
80169689Skan
81169689Skanvoid DSA_set_default_method(const DSA_METHOD *meth)
82132718Skan{
83132718Skan    default_DSA_method = meth;
84132718Skan}
85132718Skan
86132718Skanconst DSA_METHOD *DSA_get_default_method(void)
87132718Skan{
88132718Skan    if (!default_DSA_method) {
89132718Skan#ifdef OPENSSL_FIPS
90132718Skan        if (FIPS_mode())
91132718Skan            return FIPS_dsa_openssl();
92132718Skan        else
93132718Skan            return DSA_OpenSSL();
94132718Skan#else
95132718Skan        default_DSA_method = DSA_OpenSSL();
96132718Skan#endif
97132718Skan    }
98132718Skan    return default_DSA_method;
99132718Skan}
100169689Skan
101132718SkanDSA *DSA_new(void)
102132718Skan{
103132718Skan    return DSA_new_method(NULL);
104132718Skan}
105132718Skan
106132718Skanint DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
107132718Skan{
108132718Skan    /*
109132718Skan     * NB: The caller is specifically setting a method, so it's not up to us
110132718Skan     * to deal with which ENGINE it comes from.
111132718Skan     */
112132718Skan    const DSA_METHOD *mtmp;
113132718Skan    mtmp = dsa->meth;
114132718Skan    if (mtmp->finish)
115132718Skan        mtmp->finish(dsa);
116132718Skan#ifndef OPENSSL_NO_ENGINE
117132718Skan    if (dsa->engine) {
118132718Skan        ENGINE_finish(dsa->engine);
119132718Skan        dsa->engine = NULL;
120132718Skan    }
121132718Skan#endif
122132718Skan    dsa->meth = meth;
123132718Skan    if (meth->init)
124132718Skan        meth->init(dsa);
125132718Skan    return 1;
126132718Skan}
127132718Skan
128132718SkanDSA *DSA_new_method(ENGINE *engine)
129132718Skan{
130132718Skan    DSA *ret;
131132718Skan
132132718Skan    ret = (DSA *)OPENSSL_malloc(sizeof(DSA));
133132718Skan    if (ret == NULL) {
134132718Skan        DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
135132718Skan        return (NULL);
136132718Skan    }
137132718Skan    ret->meth = DSA_get_default_method();
138132718Skan#ifndef OPENSSL_NO_ENGINE
139132718Skan    if (engine) {
140132718Skan        if (!ENGINE_init(engine)) {
141132718Skan            DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
142132718Skan            OPENSSL_free(ret);
143132718Skan            return NULL;
144132718Skan        }
145132718Skan        ret->engine = engine;
146132718Skan    } else
147132718Skan        ret->engine = ENGINE_get_default_DSA();
148132718Skan    if (ret->engine) {
149132718Skan        ret->meth = ENGINE_get_DSA(ret->engine);
150132718Skan        if (!ret->meth) {
151132718Skan            DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
152132718Skan            ENGINE_finish(ret->engine);
153132718Skan            OPENSSL_free(ret);
154132718Skan            return NULL;
155132718Skan        }
156132718Skan    }
157132718Skan#endif
158132718Skan
159132718Skan    ret->pad = 0;
160132718Skan    ret->version = 0;
161132718Skan    ret->write_params = 1;
162132718Skan    ret->p = NULL;
163132718Skan    ret->q = NULL;
164132718Skan    ret->g = NULL;
165132718Skan
166132718Skan    ret->pub_key = NULL;
167132718Skan    ret->priv_key = NULL;
168132718Skan
169132718Skan    ret->kinv = NULL;
170132718Skan    ret->r = NULL;
171132718Skan    ret->method_mont_p = NULL;
172132718Skan
173132718Skan    ret->references = 1;
174132718Skan    ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
175132718Skan    CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data);
176132718Skan    if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
177132718Skan#ifndef OPENSSL_NO_ENGINE
178132718Skan        if (ret->engine)
179132718Skan            ENGINE_finish(ret->engine);
180132718Skan#endif
181132718Skan        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data);
182132718Skan        OPENSSL_free(ret);
183132718Skan        ret = NULL;
184132718Skan    }
185132718Skan
186132718Skan    return (ret);
187132718Skan}
188132718Skan
189132718Skanvoid DSA_free(DSA *r)
190132718Skan{
191132718Skan    int i;
192132718Skan
193132718Skan    if (r == NULL)
194132718Skan        return;
195132718Skan
196132718Skan    i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DSA);
197132718Skan#ifdef REF_PRINT
198132718Skan    REF_PRINT("DSA", r);
199132718Skan#endif
200132718Skan    if (i > 0)
201132718Skan        return;
202132718Skan#ifdef REF_CHECK
203132718Skan    if (i < 0) {
204132718Skan        fprintf(stderr, "DSA_free, bad reference count\n");
205132718Skan        abort();
206132718Skan    }
207132718Skan#endif
208132718Skan
209132718Skan    if (r->meth->finish)
210132718Skan        r->meth->finish(r);
211132718Skan#ifndef OPENSSL_NO_ENGINE
212132718Skan    if (r->engine)
213132718Skan        ENGINE_finish(r->engine);
214132718Skan#endif
215132718Skan
216132718Skan    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data);
217132718Skan
218132718Skan    if (r->p != NULL)
219132718Skan        BN_clear_free(r->p);
220169689Skan    if (r->q != NULL)
221132718Skan        BN_clear_free(r->q);
222132718Skan    if (r->g != NULL)
223132718Skan        BN_clear_free(r->g);
224132718Skan    if (r->pub_key != NULL)
225132718Skan        BN_clear_free(r->pub_key);
226169689Skan    if (r->priv_key != NULL)
227132718Skan        BN_clear_free(r->priv_key);
228132718Skan    if (r->kinv != NULL)
229132718Skan        BN_clear_free(r->kinv);
230132718Skan    if (r->r != NULL)
231169689Skan        BN_clear_free(r->r);
232169689Skan    OPENSSL_free(r);
233169689Skan}
234169689Skan
235169689Skanint DSA_up_ref(DSA *r)
236169689Skan{
237169689Skan    int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DSA);
238132718Skan#ifdef REF_PRINT
239132718Skan    REF_PRINT("DSA", r);
240132718Skan#endif
241132718Skan#ifdef REF_CHECK
242132718Skan    if (i < 2) {
243132718Skan        fprintf(stderr, "DSA_up_ref, bad reference count\n");
244132718Skan        abort();
245132718Skan    }
246132718Skan#endif
247169689Skan    return ((i > 1) ? 1 : 0);
248132718Skan}
249132718Skan
250132718Skanint DSA_size(const DSA *r)
251132718Skan{
252132718Skan    int ret, i;
253132718Skan    ASN1_INTEGER bs;
254132718Skan    unsigned char buf[4];       /* 4 bytes looks really small. However,
255169689Skan                                 * i2d_ASN1_INTEGER() will not look beyond
256169689Skan                                 * the first byte, as long as the second
257169689Skan                                 * parameter is NULL. */
258132718Skan
259132718Skan    i = BN_num_bits(r->q);
260132718Skan    bs.length = (i + 7) / 8;
261132718Skan    bs.data = buf;
262132718Skan    bs.type = V_ASN1_INTEGER;
263132718Skan    /* If the top bit is set the asn1 encoding is 1 larger. */
264132718Skan    buf[0] = 0xff;
265132718Skan
266132718Skan    i = i2d_ASN1_INTEGER(&bs, NULL);
267132718Skan    i += i;                     /* r and s */
268132718Skan    ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
269132718Skan    return (ret);
270132718Skan}
271169689Skan
272169689Skanint DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
273169689Skan                         CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
274169689Skan{
275169689Skan    return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, argl, argp,
276169689Skan                                   new_func, dup_func, free_func);
277169689Skan}
278169689Skan
279169689Skanint DSA_set_ex_data(DSA *d, int idx, void *arg)
280169689Skan{
281169689Skan    return (CRYPTO_set_ex_data(&d->ex_data, idx, arg));
282169689Skan}
283169689Skan
284169689Skanvoid *DSA_get_ex_data(DSA *d, int idx)
285169689Skan{
286169689Skan    return (CRYPTO_get_ex_data(&d->ex_data, idx));
287169689Skan}
288169689Skan
289169689Skan#ifndef OPENSSL_NO_DH
290169689SkanDH *DSA_dup_DH(const DSA *r)
291169689Skan{
292169689Skan    /*
293169689Skan     * DSA has p, q, g, optional pub_key, optional priv_key. DH has p,
294169689Skan     * optional length, g, optional pub_key, optional priv_key, optional q.
295169689Skan     */
296169689Skan
297169689Skan    DH *ret = NULL;
298169689Skan
299169689Skan    if (r == NULL)
300169689Skan        goto err;
301169689Skan    ret = DH_new();
302169689Skan    if (ret == NULL)
303169689Skan        goto err;
304169689Skan    if (r->p != NULL)
305169689Skan        if ((ret->p = BN_dup(r->p)) == NULL)
306169689Skan            goto err;
307169689Skan    if (r->q != NULL) {
308169689Skan        ret->length = BN_num_bits(r->q);
309169689Skan        if ((ret->q = BN_dup(r->q)) == NULL)
310169689Skan            goto err;
311169689Skan    }
312169689Skan    if (r->g != NULL)
313169689Skan        if ((ret->g = BN_dup(r->g)) == NULL)
314169689Skan            goto err;
315169689Skan    if (r->pub_key != NULL)
316169689Skan        if ((ret->pub_key = BN_dup(r->pub_key)) == NULL)
317169689Skan            goto err;
318169689Skan    if (r->priv_key != NULL)
319169689Skan        if ((ret->priv_key = BN_dup(r->priv_key)) == NULL)
320169689Skan            goto err;
321169689Skan
322169689Skan    return ret;
323169689Skan
324169689Skan err:
325169689Skan    if (ret != NULL)
326169689Skan        DH_free(ret);
327169689Skan    return NULL;
328169689Skan}
329169689Skan#endif
330169689Skan