xref: /freebsd/crypto/openssl/crypto/dsa/dsa_lib.c (revision 6f9291ce)
174664626SKris Kennaway /* crypto/dsa/dsa_lib.c */
274664626SKris Kennaway /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
374664626SKris Kennaway  * All rights reserved.
474664626SKris Kennaway  *
574664626SKris Kennaway  * This package is an SSL implementation written
674664626SKris Kennaway  * by Eric Young (eay@cryptsoft.com).
774664626SKris Kennaway  * The implementation was written so as to conform with Netscapes SSL.
874664626SKris Kennaway  *
974664626SKris Kennaway  * This library is free for commercial and non-commercial use as long as
1074664626SKris Kennaway  * the following conditions are aheared to.  The following conditions
1174664626SKris Kennaway  * apply to all code found in this distribution, be it the RC4, RSA,
1274664626SKris Kennaway  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1374664626SKris Kennaway  * included with this distribution is covered by the same copyright terms
1474664626SKris Kennaway  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1574664626SKris Kennaway  *
1674664626SKris Kennaway  * Copyright remains Eric Young's, and as such any Copyright notices in
1774664626SKris Kennaway  * the code are not to be removed.
1874664626SKris Kennaway  * If this package is used in a product, Eric Young should be given attribution
1974664626SKris Kennaway  * as the author of the parts of the library used.
2074664626SKris Kennaway  * This can be in the form of a textual message at program startup or
2174664626SKris Kennaway  * in documentation (online or textual) provided with the package.
2274664626SKris Kennaway  *
2374664626SKris Kennaway  * Redistribution and use in source and binary forms, with or without
2474664626SKris Kennaway  * modification, are permitted provided that the following conditions
2574664626SKris Kennaway  * are met:
2674664626SKris Kennaway  * 1. Redistributions of source code must retain the copyright
2774664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer.
2874664626SKris Kennaway  * 2. Redistributions in binary form must reproduce the above copyright
2974664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer in the
3074664626SKris Kennaway  *    documentation and/or other materials provided with the distribution.
3174664626SKris Kennaway  * 3. All advertising materials mentioning features or use of this software
3274664626SKris Kennaway  *    must display the following acknowledgement:
3374664626SKris Kennaway  *    "This product includes cryptographic software written by
3474664626SKris Kennaway  *     Eric Young (eay@cryptsoft.com)"
3574664626SKris Kennaway  *    The word 'cryptographic' can be left out if the rouines from the library
3674664626SKris Kennaway  *    being used are not cryptographic related :-).
3774664626SKris Kennaway  * 4. If you include any Windows specific code (or a derivative thereof) from
3874664626SKris Kennaway  *    the apps directory (application code) you must include an acknowledgement:
3974664626SKris Kennaway  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4074664626SKris Kennaway  *
4174664626SKris Kennaway  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4274664626SKris Kennaway  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4374664626SKris Kennaway  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4474664626SKris Kennaway  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4574664626SKris Kennaway  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4674664626SKris Kennaway  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4774664626SKris Kennaway  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4874664626SKris Kennaway  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4974664626SKris Kennaway  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5074664626SKris Kennaway  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5174664626SKris Kennaway  * SUCH DAMAGE.
5274664626SKris Kennaway  *
5374664626SKris Kennaway  * The licence and distribution terms for any publically available version or
5474664626SKris Kennaway  * derivative of this code cannot be changed.  i.e. this code cannot simply be
5574664626SKris Kennaway  * copied and put under another distribution licence
5674664626SKris Kennaway  * [including the GNU Public Licence.]
5774664626SKris Kennaway  */
5874664626SKris Kennaway 
5974664626SKris Kennaway /* Original version from Steven Schoch <schoch@sheba.arc.nasa.gov> */
6074664626SKris Kennaway 
6174664626SKris Kennaway #include <stdio.h>
6274664626SKris Kennaway #include "cryptlib.h"
6374664626SKris Kennaway #include <openssl/bn.h>
6474664626SKris Kennaway #include <openssl/dsa.h>
6574664626SKris Kennaway #include <openssl/asn1.h>
66fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE
675c87c606SMark Murray # include <openssl/engine.h>
68fceca8a3SJacques Vidrine #endif
693b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_DH
703b4e3dcbSSimon L. B. Nielsen # include <openssl/dh.h>
713b4e3dcbSSimon L. B. Nielsen #endif
7274664626SKris Kennaway 
731f13597dSJung-uk Kim #ifdef OPENSSL_FIPS
741f13597dSJung-uk Kim # include <openssl/fips.h>
751f13597dSJung-uk Kim #endif
761f13597dSJung-uk Kim 
775471f83eSSimon L. B. Nielsen const char DSA_version[] = "DSA" OPENSSL_VERSION_PTEXT;
7874664626SKris Kennaway 
795c87c606SMark Murray static const DSA_METHOD *default_DSA_method = NULL;
80f579bf8eSKris Kennaway 
815c87c606SMark Murray void DSA_set_default_method(const DSA_METHOD *meth)
82f579bf8eSKris Kennaway {
83f579bf8eSKris Kennaway     default_DSA_method = meth;
84f579bf8eSKris Kennaway }
85f579bf8eSKris Kennaway 
865c87c606SMark Murray const DSA_METHOD *DSA_get_default_method(void)
87f579bf8eSKris Kennaway {
886f9291ceSJung-uk Kim     if (!default_DSA_method) {
891f13597dSJung-uk Kim #ifdef OPENSSL_FIPS
901f13597dSJung-uk Kim         if (FIPS_mode())
911f13597dSJung-uk Kim             return FIPS_dsa_openssl();
921f13597dSJung-uk Kim         else
931f13597dSJung-uk Kim             return DSA_OpenSSL();
941f13597dSJung-uk Kim #else
955c87c606SMark Murray         default_DSA_method = DSA_OpenSSL();
961f13597dSJung-uk Kim #endif
971f13597dSJung-uk Kim     }
98f579bf8eSKris Kennaway     return default_DSA_method;
99f579bf8eSKris Kennaway }
100f579bf8eSKris Kennaway 
10174664626SKris Kennaway DSA *DSA_new(void)
10274664626SKris Kennaway {
103f579bf8eSKris Kennaway     return DSA_new_method(NULL);
104f579bf8eSKris Kennaway }
105f579bf8eSKris Kennaway 
1065c87c606SMark Murray int DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
107f579bf8eSKris Kennaway {
1086f9291ceSJung-uk Kim     /*
1096f9291ceSJung-uk Kim      * NB: The caller is specifically setting a method, so it's not up to us
1106f9291ceSJung-uk Kim      * to deal with which ENGINE it comes from.
1116f9291ceSJung-uk Kim      */
1125c87c606SMark Murray     const DSA_METHOD *mtmp;
113f579bf8eSKris Kennaway     mtmp = dsa->meth;
1146f9291ceSJung-uk Kim     if (mtmp->finish)
1156f9291ceSJung-uk Kim         mtmp->finish(dsa);
116fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE
1176f9291ceSJung-uk Kim     if (dsa->engine) {
1185c87c606SMark Murray         ENGINE_finish(dsa->engine);
1195c87c606SMark Murray         dsa->engine = NULL;
1205c87c606SMark Murray     }
121fceca8a3SJacques Vidrine #endif
122f579bf8eSKris Kennaway     dsa->meth = meth;
1236f9291ceSJung-uk Kim     if (meth->init)
1246f9291ceSJung-uk Kim         meth->init(dsa);
1255c87c606SMark Murray     return 1;
126f579bf8eSKris Kennaway }
127f579bf8eSKris Kennaway 
1285c87c606SMark Murray DSA *DSA_new_method(ENGINE *engine)
129f579bf8eSKris Kennaway {
13074664626SKris Kennaway     DSA *ret;
13174664626SKris Kennaway 
132ddd58736SKris Kennaway     ret = (DSA *)OPENSSL_malloc(sizeof(DSA));
1336f9291ceSJung-uk Kim     if (ret == NULL) {
1345c87c606SMark Murray         DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
13574664626SKris Kennaway         return (NULL);
13674664626SKris Kennaway     }
1375c87c606SMark Murray     ret->meth = DSA_get_default_method();
138fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE
1396f9291ceSJung-uk Kim     if (engine) {
1406f9291ceSJung-uk Kim         if (!ENGINE_init(engine)) {
1415c87c606SMark Murray             DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
1425c87c606SMark Murray             OPENSSL_free(ret);
1435c87c606SMark Murray             return NULL;
1445c87c606SMark Murray         }
1455c87c606SMark Murray         ret->engine = engine;
1466f9291ceSJung-uk Kim     } else
1475c87c606SMark Murray         ret->engine = ENGINE_get_default_DSA();
1486f9291ceSJung-uk Kim     if (ret->engine) {
1495c87c606SMark Murray         ret->meth = ENGINE_get_DSA(ret->engine);
1506f9291ceSJung-uk Kim         if (!ret->meth) {
1516f9291ceSJung-uk Kim             DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
1525c87c606SMark Murray             ENGINE_finish(ret->engine);
1535c87c606SMark Murray             OPENSSL_free(ret);
1545c87c606SMark Murray             return NULL;
1555c87c606SMark Murray         }
1565c87c606SMark Murray     }
157fceca8a3SJacques Vidrine #endif
1585c87c606SMark Murray 
15974664626SKris Kennaway     ret->pad = 0;
16074664626SKris Kennaway     ret->version = 0;
16174664626SKris Kennaway     ret->write_params = 1;
16274664626SKris Kennaway     ret->p = NULL;
16374664626SKris Kennaway     ret->q = NULL;
16474664626SKris Kennaway     ret->g = NULL;
16574664626SKris Kennaway 
16674664626SKris Kennaway     ret->pub_key = NULL;
16774664626SKris Kennaway     ret->priv_key = NULL;
16874664626SKris Kennaway 
16974664626SKris Kennaway     ret->kinv = NULL;
17074664626SKris Kennaway     ret->r = NULL;
17174664626SKris Kennaway     ret->method_mont_p = NULL;
17274664626SKris Kennaway 
17374664626SKris Kennaway     ret->references = 1;
1746a599222SSimon L. B. Nielsen     ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
1755c87c606SMark Murray     CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data);
1766f9291ceSJung-uk Kim     if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
177fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE
1785c87c606SMark Murray         if (ret->engine)
1795c87c606SMark Murray             ENGINE_finish(ret->engine);
180fceca8a3SJacques Vidrine #endif
1815c87c606SMark Murray         CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data);
182ddd58736SKris Kennaway         OPENSSL_free(ret);
183f579bf8eSKris Kennaway         ret = NULL;
184f579bf8eSKris Kennaway     }
185f579bf8eSKris Kennaway 
18674664626SKris Kennaway     return (ret);
18774664626SKris Kennaway }
18874664626SKris Kennaway 
18974664626SKris Kennaway void DSA_free(DSA *r)
19074664626SKris Kennaway {
19174664626SKris Kennaway     int i;
19274664626SKris Kennaway 
1936f9291ceSJung-uk Kim     if (r == NULL)
1946f9291ceSJung-uk Kim         return;
19574664626SKris Kennaway 
19674664626SKris Kennaway     i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DSA);
19774664626SKris Kennaway #ifdef REF_PRINT
19874664626SKris Kennaway     REF_PRINT("DSA", r);
19974664626SKris Kennaway #endif
2006f9291ceSJung-uk Kim     if (i > 0)
2016f9291ceSJung-uk Kim         return;
20274664626SKris Kennaway #ifdef REF_CHECK
2036f9291ceSJung-uk Kim     if (i < 0) {
20474664626SKris Kennaway         fprintf(stderr, "DSA_free, bad reference count\n");
20574664626SKris Kennaway         abort();
20674664626SKris Kennaway     }
20774664626SKris Kennaway #endif
20874664626SKris Kennaway 
2095c87c606SMark Murray     if (r->meth->finish)
2105c87c606SMark Murray         r->meth->finish(r);
211fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE
2125c87c606SMark Murray     if (r->engine)
2135c87c606SMark Murray         ENGINE_finish(r->engine);
214fceca8a3SJacques Vidrine #endif
215f579bf8eSKris Kennaway 
2165c87c606SMark Murray     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data);
2175740a5e3SKris Kennaway 
2186f9291ceSJung-uk Kim     if (r->p != NULL)
2196f9291ceSJung-uk Kim         BN_clear_free(r->p);
2206f9291ceSJung-uk Kim     if (r->q != NULL)
2216f9291ceSJung-uk Kim         BN_clear_free(r->q);
2226f9291ceSJung-uk Kim     if (r->g != NULL)
2236f9291ceSJung-uk Kim         BN_clear_free(r->g);
2246f9291ceSJung-uk Kim     if (r->pub_key != NULL)
2256f9291ceSJung-uk Kim         BN_clear_free(r->pub_key);
2266f9291ceSJung-uk Kim     if (r->priv_key != NULL)
2276f9291ceSJung-uk Kim         BN_clear_free(r->priv_key);
2286f9291ceSJung-uk Kim     if (r->kinv != NULL)
2296f9291ceSJung-uk Kim         BN_clear_free(r->kinv);
2306f9291ceSJung-uk Kim     if (r->r != NULL)
2316f9291ceSJung-uk Kim         BN_clear_free(r->r);
232ddd58736SKris Kennaway     OPENSSL_free(r);
23374664626SKris Kennaway }
23474664626SKris Kennaway 
2355c87c606SMark Murray int DSA_up_ref(DSA *r)
2365c87c606SMark Murray {
2375c87c606SMark Murray     int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DSA);
2385c87c606SMark Murray #ifdef REF_PRINT
2395c87c606SMark Murray     REF_PRINT("DSA", r);
2405c87c606SMark Murray #endif
2415c87c606SMark Murray #ifdef REF_CHECK
2426f9291ceSJung-uk Kim     if (i < 2) {
2435c87c606SMark Murray         fprintf(stderr, "DSA_up_ref, bad reference count\n");
2445c87c606SMark Murray         abort();
2455c87c606SMark Murray     }
2465c87c606SMark Murray #endif
2475c87c606SMark Murray     return ((i > 1) ? 1 : 0);
2485c87c606SMark Murray }
2495c87c606SMark Murray 
2501f13597dSJung-uk Kim int DSA_size(const DSA *r)
2511f13597dSJung-uk Kim {
2521f13597dSJung-uk Kim     int ret, i;
2531f13597dSJung-uk Kim     ASN1_INTEGER bs;
2546f9291ceSJung-uk Kim     unsigned char buf[4];       /* 4 bytes looks really small. However,
2556f9291ceSJung-uk Kim                                  * i2d_ASN1_INTEGER() will not look beyond
2566f9291ceSJung-uk Kim                                  * the first byte, as long as the second
2576f9291ceSJung-uk Kim                                  * parameter is NULL. */
2581f13597dSJung-uk Kim 
2591f13597dSJung-uk Kim     i = BN_num_bits(r->q);
2601f13597dSJung-uk Kim     bs.length = (i + 7) / 8;
2611f13597dSJung-uk Kim     bs.data = buf;
2621f13597dSJung-uk Kim     bs.type = V_ASN1_INTEGER;
2631f13597dSJung-uk Kim     /* If the top bit is set the asn1 encoding is 1 larger. */
2641f13597dSJung-uk Kim     buf[0] = 0xff;
2651f13597dSJung-uk Kim 
2661f13597dSJung-uk Kim     i = i2d_ASN1_INTEGER(&bs, NULL);
2671f13597dSJung-uk Kim     i += i;                     /* r and s */
2681f13597dSJung-uk Kim     ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
2691f13597dSJung-uk Kim     return (ret);
2701f13597dSJung-uk Kim }
2711f13597dSJung-uk Kim 
272f579bf8eSKris Kennaway int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
273f579bf8eSKris Kennaway                          CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
274f579bf8eSKris Kennaway {
2755c87c606SMark Murray     return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, argl, argp,
2765c87c606SMark Murray                                    new_func, dup_func, free_func);
277f579bf8eSKris Kennaway }
278f579bf8eSKris Kennaway 
279f579bf8eSKris Kennaway int DSA_set_ex_data(DSA *d, int idx, void *arg)
280f579bf8eSKris Kennaway {
281f579bf8eSKris Kennaway     return (CRYPTO_set_ex_data(&d->ex_data, idx, arg));
282f579bf8eSKris Kennaway }
283f579bf8eSKris Kennaway 
284f579bf8eSKris Kennaway void *DSA_get_ex_data(DSA *d, int idx)
285f579bf8eSKris Kennaway {
286f579bf8eSKris Kennaway     return (CRYPTO_get_ex_data(&d->ex_data, idx));
287f579bf8eSKris Kennaway }
288f579bf8eSKris Kennaway 
2895c87c606SMark Murray #ifndef OPENSSL_NO_DH
2905c87c606SMark Murray DH *DSA_dup_DH(const DSA *r)
29174664626SKris Kennaway {
2926f9291ceSJung-uk Kim     /*
2936f9291ceSJung-uk Kim      * DSA has p, q, g, optional pub_key, optional priv_key. DH has p,
2946f9291ceSJung-uk Kim      * optional length, g, optional pub_key, optional priv_key, optional q.
29574664626SKris Kennaway      */
29674664626SKris Kennaway 
29774664626SKris Kennaway     DH *ret = NULL;
29874664626SKris Kennaway 
29974664626SKris Kennaway     if (r == NULL)
30074664626SKris Kennaway         goto err;
30174664626SKris Kennaway     ret = DH_new();
30274664626SKris Kennaway     if (ret == NULL)
30374664626SKris Kennaway         goto err;
30474664626SKris Kennaway     if (r->p != NULL)
30574664626SKris Kennaway         if ((ret->p = BN_dup(r->p)) == NULL)
30674664626SKris Kennaway             goto err;
3076f9291ceSJung-uk Kim     if (r->q != NULL) {
30874664626SKris Kennaway         ret->length = BN_num_bits(r->q);
3091f13597dSJung-uk Kim         if ((ret->q = BN_dup(r->q)) == NULL)
3101f13597dSJung-uk Kim             goto err;
3111f13597dSJung-uk Kim     }
31274664626SKris Kennaway     if (r->g != NULL)
31374664626SKris Kennaway         if ((ret->g = BN_dup(r->g)) == NULL)
31474664626SKris Kennaway             goto err;
31574664626SKris Kennaway     if (r->pub_key != NULL)
31674664626SKris Kennaway         if ((ret->pub_key = BN_dup(r->pub_key)) == NULL)
31774664626SKris Kennaway             goto err;
31874664626SKris Kennaway     if (r->priv_key != NULL)
31974664626SKris Kennaway         if ((ret->priv_key = BN_dup(r->priv_key)) == NULL)
32074664626SKris Kennaway             goto err;
32174664626SKris Kennaway 
32274664626SKris Kennaway     return ret;
32374664626SKris Kennaway 
32474664626SKris Kennaway  err:
32574664626SKris Kennaway     if (ret != NULL)
32674664626SKris Kennaway         DH_free(ret);
32774664626SKris Kennaway     return NULL;
32874664626SKris Kennaway }
32974664626SKris Kennaway #endif
330