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