155714Skris/* crypto/dh/dh_lib.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280304Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280304Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280304Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280304Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280304Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include "cryptlib.h"
6155714Skris#include <openssl/bn.h>
6255714Skris#include <openssl/dh.h>
63111147Snectar#ifndef OPENSSL_NO_ENGINE
64280304Sjkim# include <openssl/engine.h>
65111147Snectar#endif
6655714Skris
67238405Sjkim#ifdef OPENSSL_FIPS
68280304Sjkim# include <openssl/fips.h>
69238405Sjkim#endif
70238405Sjkim
71280304Sjkimconst char DH_version[] = "Diffie-Hellman" OPENSSL_VERSION_PTEXT;
7255714Skris
73109998Smarkmstatic const DH_METHOD *default_DH_method = NULL;
7459191Skris
75109998Smarkmvoid DH_set_default_method(const DH_METHOD *meth)
76280304Sjkim{
77280304Sjkim    default_DH_method = meth;
78280304Sjkim}
7959191Skris
80109998Smarkmconst DH_METHOD *DH_get_default_method(void)
81280304Sjkim{
82280304Sjkim    if (!default_DH_method) {
83238405Sjkim#ifdef OPENSSL_FIPS
84280304Sjkim        if (FIPS_mode())
85280304Sjkim            return FIPS_dh_openssl();
86280304Sjkim        else
87280304Sjkim            return DH_OpenSSL();
88238405Sjkim#else
89280304Sjkim        default_DH_method = DH_OpenSSL();
90238405Sjkim#endif
91280304Sjkim    }
92280304Sjkim    return default_DH_method;
93280304Sjkim}
9459191Skris
95109998Smarkmint DH_set_method(DH *dh, const DH_METHOD *meth)
96280304Sjkim{
97280304Sjkim    /*
98280304Sjkim     * NB: The caller is specifically setting a method, so it's not up to us
99280304Sjkim     * to deal with which ENGINE it comes from.
100280304Sjkim     */
101280304Sjkim    const DH_METHOD *mtmp;
102280304Sjkim    mtmp = dh->meth;
103280304Sjkim    if (mtmp->finish)
104280304Sjkim        mtmp->finish(dh);
105111147Snectar#ifndef OPENSSL_NO_ENGINE
106280304Sjkim    if (dh->engine) {
107280304Sjkim        ENGINE_finish(dh->engine);
108280304Sjkim        dh->engine = NULL;
109280304Sjkim    }
110111147Snectar#endif
111280304Sjkim    dh->meth = meth;
112280304Sjkim    if (meth->init)
113280304Sjkim        meth->init(dh);
114280304Sjkim    return 1;
115280304Sjkim}
11659191Skris
11755714SkrisDH *DH_new(void)
118280304Sjkim{
119280304Sjkim    return DH_new_method(NULL);
120280304Sjkim}
12159191Skris
122109998SmarkmDH *DH_new_method(ENGINE *engine)
123280304Sjkim{
124280304Sjkim    DH *ret;
125109998Smarkm
126280304Sjkim    ret = (DH *)OPENSSL_malloc(sizeof(DH));
127280304Sjkim    if (ret == NULL) {
128280304Sjkim        DHerr(DH_F_DH_NEW_METHOD, ERR_R_MALLOC_FAILURE);
129280304Sjkim        return (NULL);
130280304Sjkim    }
131109998Smarkm
132280304Sjkim    ret->meth = DH_get_default_method();
133111147Snectar#ifndef OPENSSL_NO_ENGINE
134280304Sjkim    if (engine) {
135280304Sjkim        if (!ENGINE_init(engine)) {
136280304Sjkim            DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB);
137280304Sjkim            OPENSSL_free(ret);
138280304Sjkim            return NULL;
139280304Sjkim        }
140280304Sjkim        ret->engine = engine;
141280304Sjkim    } else
142280304Sjkim        ret->engine = ENGINE_get_default_DH();
143280304Sjkim    if (ret->engine) {
144280304Sjkim        ret->meth = ENGINE_get_DH(ret->engine);
145280304Sjkim        if (!ret->meth) {
146280304Sjkim            DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB);
147280304Sjkim            ENGINE_finish(ret->engine);
148280304Sjkim            OPENSSL_free(ret);
149280304Sjkim            return NULL;
150280304Sjkim        }
151280304Sjkim    }
152111147Snectar#endif
153109998Smarkm
154280304Sjkim    ret->pad = 0;
155280304Sjkim    ret->version = 0;
156280304Sjkim    ret->p = NULL;
157280304Sjkim    ret->g = NULL;
158280304Sjkim    ret->length = 0;
159280304Sjkim    ret->pub_key = NULL;
160280304Sjkim    ret->priv_key = NULL;
161280304Sjkim    ret->q = NULL;
162280304Sjkim    ret->j = NULL;
163280304Sjkim    ret->seed = NULL;
164280304Sjkim    ret->seedlen = 0;
165280304Sjkim    ret->counter = NULL;
166280304Sjkim    ret->method_mont_p = NULL;
167280304Sjkim    ret->references = 1;
168280304Sjkim    ret->flags = ret->meth->flags & ~DH_FLAG_NON_FIPS_ALLOW;
169280304Sjkim    CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
170280304Sjkim    if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
171111147Snectar#ifndef OPENSSL_NO_ENGINE
172280304Sjkim        if (ret->engine)
173280304Sjkim            ENGINE_finish(ret->engine);
174111147Snectar#endif
175280304Sjkim        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
176280304Sjkim        OPENSSL_free(ret);
177280304Sjkim        ret = NULL;
178280304Sjkim    }
179280304Sjkim    return (ret);
180280304Sjkim}
18155714Skris
18255714Skrisvoid DH_free(DH *r)
183280304Sjkim{
184280304Sjkim    int i;
185280304Sjkim    if (r == NULL)
186280304Sjkim        return;
187280304Sjkim    i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DH);
18859191Skris#ifdef REF_PRINT
189280304Sjkim    REF_PRINT("DH", r);
19059191Skris#endif
191280304Sjkim    if (i > 0)
192280304Sjkim        return;
19359191Skris#ifdef REF_CHECK
194280304Sjkim    if (i < 0) {
195280304Sjkim        fprintf(stderr, "DH_free, bad reference count\n");
196280304Sjkim        abort();
197280304Sjkim    }
19859191Skris#endif
19959191Skris
200280304Sjkim    if (r->meth->finish)
201280304Sjkim        r->meth->finish(r);
202111147Snectar#ifndef OPENSSL_NO_ENGINE
203280304Sjkim    if (r->engine)
204280304Sjkim        ENGINE_finish(r->engine);
205111147Snectar#endif
20676866Skris
207280304Sjkim    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
20859191Skris
209280304Sjkim    if (r->p != NULL)
210280304Sjkim        BN_clear_free(r->p);
211280304Sjkim    if (r->g != NULL)
212280304Sjkim        BN_clear_free(r->g);
213280304Sjkim    if (r->q != NULL)
214280304Sjkim        BN_clear_free(r->q);
215280304Sjkim    if (r->j != NULL)
216280304Sjkim        BN_clear_free(r->j);
217280304Sjkim    if (r->seed)
218280304Sjkim        OPENSSL_free(r->seed);
219280304Sjkim    if (r->counter != NULL)
220280304Sjkim        BN_clear_free(r->counter);
221280304Sjkim    if (r->pub_key != NULL)
222280304Sjkim        BN_clear_free(r->pub_key);
223280304Sjkim    if (r->priv_key != NULL)
224280304Sjkim        BN_clear_free(r->priv_key);
225280304Sjkim    OPENSSL_free(r);
226280304Sjkim}
22755714Skris
228109998Smarkmint DH_up_ref(DH *r)
229280304Sjkim{
230280304Sjkim    int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DH);
231109998Smarkm#ifdef REF_PRINT
232280304Sjkim    REF_PRINT("DH", r);
233109998Smarkm#endif
234109998Smarkm#ifdef REF_CHECK
235280304Sjkim    if (i < 2) {
236280304Sjkim        fprintf(stderr, "DH_up, bad reference count\n");
237280304Sjkim        abort();
238280304Sjkim    }
239109998Smarkm#endif
240280304Sjkim    return ((i > 1) ? 1 : 0);
241280304Sjkim}
242109998Smarkm
24359191Skrisint DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
244280304Sjkim                        CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
245280304Sjkim{
246280304Sjkim    return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, argl, argp,
247280304Sjkim                                   new_func, dup_func, free_func);
248280304Sjkim}
24959191Skris
25059191Skrisint DH_set_ex_data(DH *d, int idx, void *arg)
251280304Sjkim{
252280304Sjkim    return (CRYPTO_set_ex_data(&d->ex_data, idx, arg));
253280304Sjkim}
25459191Skris
25559191Skrisvoid *DH_get_ex_data(DH *d, int idx)
256280304Sjkim{
257280304Sjkim    return (CRYPTO_get_ex_data(&d->ex_data, idx));
258280304Sjkim}
25959191Skris
260109998Smarkmint DH_size(const DH *dh)
261280304Sjkim{
262280304Sjkim    return (BN_num_bytes(dh->p));
263280304Sjkim}
264