From e8f783ac0d7491723dc5f8656a4c9ba9ce830294 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Fri, 30 Oct 2015 16:53:00 -0400 Subject: [PATCH] Unwind DH_METHOD and DSA_METHOD. This will allow a static linker (with -ffunction-sections since things aren't split into files) to drop unused parts of DH and DSA. Notably, the parameter generation bits pull in primality-checking code. Change-Id: I25087e4cb91bc9d0ab43bcb267c2e2c164e56b59 Reviewed-on: https://boringssl-review.googlesource.com/6388 Reviewed-by: Adam Langley --- crypto/dh/CMakeLists.txt | 1 - crypto/dh/dh.c | 282 +++++++++++++-- crypto/dh/dh_impl.c | 326 ----------------- crypto/dh/params.c | 4 +- crypto/dsa/CMakeLists.txt | 1 - crypto/dsa/dsa.c | 653 ++++++++++++++++++++++++++++++--- crypto/dsa/dsa_impl.c | 734 -------------------------------------- crypto/engine/engine.c | 24 -- include/openssl/base.h | 2 - include/openssl/dh.h | 36 +- include/openssl/dsa.h | 31 -- include/openssl/engine.h | 9 - 12 files changed, 856 insertions(+), 1247 deletions(-) delete mode 100644 crypto/dh/dh_impl.c delete mode 100644 crypto/dsa/dsa_impl.c diff --git a/crypto/dh/CMakeLists.txt b/crypto/dh/CMakeLists.txt index 8ddf03da..f1e86162 100644 --- a/crypto/dh/CMakeLists.txt +++ b/crypto/dh/CMakeLists.txt @@ -6,7 +6,6 @@ add_library( OBJECT dh.c - dh_impl.c params.c check.c dh_asn1.c diff --git a/crypto/dh/dh.c b/crypto/dh/dh.c index ee6c9a02..a88520d2 100644 --- a/crypto/dh/dh.c +++ b/crypto/dh/dh.c @@ -69,13 +69,11 @@ #include "../internal.h" -extern const DH_METHOD DH_default_method; +#define OPENSSL_DH_MAX_MODULUS_BITS 10000 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; -DH *DH_new(void) { return DH_new_method(NULL); } - -DH *DH_new_method(const ENGINE *engine) { +DH *DH_new(void) { DH *dh = (DH *)OPENSSL_malloc(sizeof(DH)); if (dh == NULL) { OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE); @@ -84,15 +82,6 @@ DH *DH_new_method(const ENGINE *engine) { memset(dh, 0, sizeof(DH)); - if (engine) { - dh->meth = ENGINE_get_DH_method(engine); - } - - if (dh->meth == NULL) { - dh->meth = (DH_METHOD*) &DH_default_method; - } - METHOD_ref(dh->meth); - CRYPTO_MUTEX_init(&dh->method_mont_p_lock); dh->references = 1; @@ -102,14 +91,6 @@ DH *DH_new_method(const ENGINE *engine) { return NULL; } - if (dh->meth->init && !dh->meth->init(dh)) { - CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data); - CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock); - METHOD_unref(dh->meth); - OPENSSL_free(dh); - return NULL; - } - return dh; } @@ -122,11 +103,6 @@ void DH_free(DH *dh) { return; } - if (dh->meth->finish) { - dh->meth->finish(dh); - } - METHOD_unref(dh->meth); - CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data); BN_MONT_CTX_free(dh->method_mont_p); @@ -144,24 +120,256 @@ void DH_free(DH *dh) { } int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) { - if (dh->meth->generate_parameters) { - return dh->meth->generate_parameters(dh, prime_bits, generator, cb); + /* We generate DH parameters as follows + * find a prime q which is prime_bits/2 bits long. + * p=(2*q)+1 or (p-1)/2 = q + * For this case, g is a generator if + * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1. + * Since the factors of p-1 are q and 2, we just need to check + * g^2 mod p != 1 and g^q mod p != 1. + * + * Having said all that, + * there is another special case method for the generators 2, 3 and 5. + * for 2, p mod 24 == 11 + * for 3, p mod 12 == 5 <<<<< does not work for safe primes. + * for 5, p mod 10 == 3 or 7 + * + * Thanks to Phil Karn for the pointers about the + * special generators and for answering some of my questions. + * + * I've implemented the second simple method :-). + * Since DH should be using a safe prime (both p and q are prime), + * this generator function can take a very very long time to run. + */ + + /* Actually there is no reason to insist that 'generator' be a generator. + * It's just as OK (and in some sense better) to use a generator of the + * order-q subgroup. + */ + + BIGNUM *t1, *t2; + int g, ok = 0; + BN_CTX *ctx = NULL; + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; } - return DH_default_method.generate_parameters(dh, prime_bits, generator, cb); + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t1 == NULL || t2 == NULL) { + goto err; + } + + /* Make sure |dh| has the necessary elements */ + if (dh->p == NULL) { + dh->p = BN_new(); + if (dh->p == NULL) { + goto err; + } + } + if (dh->g == NULL) { + dh->g = BN_new(); + if (dh->g == NULL) { + goto err; + } + } + + if (generator <= 1) { + OPENSSL_PUT_ERROR(DH, DH_R_BAD_GENERATOR); + goto err; + } + if (generator == DH_GENERATOR_2) { + if (!BN_set_word(t1, 24)) { + goto err; + } + if (!BN_set_word(t2, 11)) { + goto err; + } + g = 2; + } else if (generator == DH_GENERATOR_5) { + if (!BN_set_word(t1, 10)) { + goto err; + } + if (!BN_set_word(t2, 3)) { + goto err; + } + /* BN_set_word(t3,7); just have to miss + * out on these ones :-( */ + g = 5; + } else { + /* in the general case, don't worry if 'generator' is a + * generator or not: since we are using safe primes, + * it will generate either an order-q or an order-2q group, + * which both is OK */ + if (!BN_set_word(t1, 2)) { + goto err; + } + if (!BN_set_word(t2, 1)) { + goto err; + } + g = generator; + } + + if (!BN_generate_prime_ex(dh->p, prime_bits, 1, t1, t2, cb)) { + goto err; + } + if (!BN_GENCB_call(cb, 3, 0)) { + goto err; + } + if (!BN_set_word(dh->g, g)) { + goto err; + } + ok = 1; + +err: + if (!ok) { + OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); + } + + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; } int DH_generate_key(DH *dh) { - if (dh->meth->generate_key) { - return dh->meth->generate_key(dh); + int ok = 0; + int generate_new_key = 0; + unsigned l; + BN_CTX *ctx; + BN_MONT_CTX *mont = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; + BIGNUM local_priv; + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; } - return DH_default_method.generate_key(dh); + + if (dh->priv_key == NULL) { + priv_key = BN_new(); + if (priv_key == NULL) { + goto err; + } + generate_new_key = 1; + } else { + priv_key = dh->priv_key; + } + + if (dh->pub_key == NULL) { + pub_key = BN_new(); + if (pub_key == NULL) { + goto err; + } + } else { + pub_key = dh->pub_key; + } + + mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, + dh->p, ctx); + if (!mont) { + goto err; + } + + if (generate_new_key) { + if (dh->q) { + do { + if (!BN_rand_range(priv_key, dh->q)) { + goto err; + } + } while (BN_is_zero(priv_key) || BN_is_one(priv_key)); + } else { + /* secret exponent length */ + DH_check_standard_parameters(dh); + l = dh->priv_length ? dh->priv_length : BN_num_bits(dh->p) - 1; + if (!BN_rand(priv_key, l, 0, 0)) { + goto err; + } + } + } + + BN_with_flags(&local_priv, priv_key, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont(pub_key, dh->g, &local_priv, dh->p, ctx, mont)) { + goto err; + } + + dh->pub_key = pub_key; + dh->priv_key = priv_key; + ok = 1; + +err: + if (ok != 1) { + OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); + } + + if (dh->pub_key == NULL) { + BN_free(pub_key); + } + if (dh->priv_key == NULL) { + BN_free(priv_key); + } + BN_CTX_free(ctx); + return ok; } int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) { - if (dh->meth->compute_key) { - return dh->meth->compute_key(dh, out, peers_key); + BN_CTX *ctx = NULL; + BN_MONT_CTX *mont = NULL; + BIGNUM *shared_key; + int ret = -1; + int check_result; + BIGNUM local_priv; + + if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { + OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE); + goto err; } - return DH_default_method.compute_key(dh, out, peers_key); + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + shared_key = BN_CTX_get(ctx); + if (shared_key == NULL) { + goto err; + } + + if (dh->priv_key == NULL) { + OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE); + goto err; + } + + mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, + dh->p, ctx); + if (!mont) { + goto err; + } + + if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) { + OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY); + goto err; + } + + BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont(shared_key, peers_key, &local_priv, dh->p, ctx, + mont)) { + OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); + goto err; + } + + ret = BN_bn2bin(shared_key, out); + +err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + + return ret; } int DH_size(const DH *dh) { return BN_num_bytes(dh->p); } @@ -246,9 +454,9 @@ int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, } int DH_set_ex_data(DH *d, int idx, void *arg) { - return (CRYPTO_set_ex_data(&d->ex_data, idx, arg)); + return CRYPTO_set_ex_data(&d->ex_data, idx, arg); } void *DH_get_ex_data(DH *d, int idx) { - return (CRYPTO_get_ex_data(&d->ex_data, idx)); + return CRYPTO_get_ex_data(&d->ex_data, idx); } diff --git a/crypto/dh/dh_impl.c b/crypto/dh/dh_impl.c deleted file mode 100644 index 6cf0abb6..00000000 --- a/crypto/dh/dh_impl.c +++ /dev/null @@ -1,326 +0,0 @@ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] */ - -#include - -#include -#include -#include - -#include "internal.h" - - -#define OPENSSL_DH_MAX_MODULUS_BITS 10000 - -static int generate_parameters(DH *ret, int prime_bits, int generator, BN_GENCB *cb) { - /* We generate DH parameters as follows - * find a prime q which is prime_bits/2 bits long. - * p=(2*q)+1 or (p-1)/2 = q - * For this case, g is a generator if - * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1. - * Since the factors of p-1 are q and 2, we just need to check - * g^2 mod p != 1 and g^q mod p != 1. - * - * Having said all that, - * there is another special case method for the generators 2, 3 and 5. - * for 2, p mod 24 == 11 - * for 3, p mod 12 == 5 <<<<< does not work for safe primes. - * for 5, p mod 10 == 3 or 7 - * - * Thanks to Phil Karn for the pointers about the - * special generators and for answering some of my questions. - * - * I've implemented the second simple method :-). - * Since DH should be using a safe prime (both p and q are prime), - * this generator function can take a very very long time to run. - */ - - /* Actually there is no reason to insist that 'generator' be a generator. - * It's just as OK (and in some sense better) to use a generator of the - * order-q subgroup. - */ - - BIGNUM *t1, *t2; - int g, ok = 0; - BN_CTX *ctx = NULL; - - ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } - BN_CTX_start(ctx); - t1 = BN_CTX_get(ctx); - t2 = BN_CTX_get(ctx); - if (t1 == NULL || t2 == NULL) { - goto err; - } - - /* Make sure 'ret' has the necessary elements */ - if (!ret->p && ((ret->p = BN_new()) == NULL)) { - goto err; - } - if (!ret->g && ((ret->g = BN_new()) == NULL)) { - goto err; - } - - if (generator <= 1) { - OPENSSL_PUT_ERROR(DH, DH_R_BAD_GENERATOR); - goto err; - } - if (generator == DH_GENERATOR_2) { - if (!BN_set_word(t1, 24)) { - goto err; - } - if (!BN_set_word(t2, 11)) { - goto err; - } - g = 2; - } else if (generator == DH_GENERATOR_5) { - if (!BN_set_word(t1, 10)) { - goto err; - } - if (!BN_set_word(t2, 3)) { - goto err; - } - /* BN_set_word(t3,7); just have to miss - * out on these ones :-( */ - g = 5; - } else { - /* in the general case, don't worry if 'generator' is a - * generator or not: since we are using safe primes, - * it will generate either an order-q or an order-2q group, - * which both is OK */ - if (!BN_set_word(t1, 2)) { - goto err; - } - if (!BN_set_word(t2, 1)) { - goto err; - } - g = generator; - } - - if (!BN_generate_prime_ex(ret->p, prime_bits, 1, t1, t2, cb)) { - goto err; - } - if (!BN_GENCB_call(cb, 3, 0)) { - goto err; - } - if (!BN_set_word(ret->g, g)) { - goto err; - } - ok = 1; - -err: - if (!ok) { - OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); - } - - if (ctx != NULL) { - BN_CTX_end(ctx); - BN_CTX_free(ctx); - } - return ok; -} - -static int generate_key(DH *dh) { - int ok = 0; - int generate_new_key = 0; - unsigned l; - BN_CTX *ctx; - BN_MONT_CTX *mont = NULL; - BIGNUM *pub_key = NULL, *priv_key = NULL; - BIGNUM local_priv; - - ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } - - if (dh->priv_key == NULL) { - priv_key = BN_new(); - if (priv_key == NULL) { - goto err; - } - generate_new_key = 1; - } else { - priv_key = dh->priv_key; - } - - if (dh->pub_key == NULL) { - pub_key = BN_new(); - if (pub_key == NULL) { - goto err; - } - } else { - pub_key = dh->pub_key; - } - - mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, - dh->p, ctx); - if (!mont) { - goto err; - } - - if (generate_new_key) { - if (dh->q) { - do { - if (!BN_rand_range(priv_key, dh->q)) { - goto err; - } - } while (BN_is_zero(priv_key) || BN_is_one(priv_key)); - } else { - /* secret exponent length */ - DH_check_standard_parameters(dh); - l = dh->priv_length ? dh->priv_length : BN_num_bits(dh->p) - 1; - if (!BN_rand(priv_key, l, 0, 0)) { - goto err; - } - } - } - - BN_with_flags(&local_priv, priv_key, BN_FLG_CONSTTIME); - if (!BN_mod_exp_mont(pub_key, dh->g, &local_priv, dh->p, ctx, mont)) { - goto err; - } - - dh->pub_key = pub_key; - dh->priv_key = priv_key; - ok = 1; - -err: - if (ok != 1) { - OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); - } - - if (dh->pub_key == NULL) { - BN_free(pub_key); - } - if (dh->priv_key == NULL) { - BN_free(priv_key); - } - BN_CTX_free(ctx); - return ok; -} - -static int compute_key(DH *dh, unsigned char *out, const BIGNUM *pub_key) { - BN_CTX *ctx = NULL; - BN_MONT_CTX *mont = NULL; - BIGNUM *shared_key; - int ret = -1; - int check_result; - BIGNUM local_priv; - - if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { - OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE); - goto err; - } - - ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } - BN_CTX_start(ctx); - shared_key = BN_CTX_get(ctx); - if (shared_key == NULL) { - goto err; - } - - if (dh->priv_key == NULL) { - OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE); - goto err; - } - - mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, - dh->p, ctx); - if (!mont) { - goto err; - } - - if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) { - OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY); - goto err; - } - - BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME); - if (!BN_mod_exp_mont(shared_key, pub_key, &local_priv, dh->p, ctx, - mont)) { - OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); - goto err; - } - - ret = BN_bn2bin(shared_key, out); - -err: - if (ctx != NULL) { - BN_CTX_end(ctx); - BN_CTX_free(ctx); - } - - return ret; -} - -const struct dh_method DH_default_method = { - { - 0 /* references */, - 1 /* is_static */, - }, - NULL /* app_data */, - NULL /* init */, - NULL /* finish */, - generate_parameters, - generate_key, - compute_key, -}; diff --git a/crypto/dh/params.c b/crypto/dh/params.c index 2bfccb8d..6b30036e 100644 --- a/crypto/dh/params.c +++ b/crypto/dh/params.c @@ -264,9 +264,7 @@ BIGNUM bn_two = STATIC_BIGNUM(bn_two_data); static DH *get_standard_parameters(const struct standard_parameters *params, const ENGINE *engine) { - DH *dh; - - dh = DH_new_method(engine); + DH *dh = DH_new(); if (!dh) { return NULL; } diff --git a/crypto/dsa/CMakeLists.txt b/crypto/dsa/CMakeLists.txt index 654f18cd..de365656 100644 --- a/crypto/dsa/CMakeLists.txt +++ b/crypto/dsa/CMakeLists.txt @@ -6,7 +6,6 @@ add_library( OBJECT dsa.c - dsa_impl.c dsa_asn1.c ) diff --git a/crypto/dsa/dsa.c b/crypto/dsa/dsa.c index eb8e61f5..ceffd1ad 100644 --- a/crypto/dsa/dsa.c +++ b/crypto/dsa/dsa.c @@ -62,24 +62,30 @@ #include #include +#include #include +#include #include #include #include #include +#include +#include #include #include "internal.h" #include "../internal.h" -extern const DSA_METHOD DSA_default_method; +#define OPENSSL_DSA_MAX_MODULUS_BITS 10000 + +/* Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of + * Rabin-Miller */ +#define DSS_prime_checks 50 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; -DSA *DSA_new(void) { return DSA_new_method(NULL); } - -DSA *DSA_new_method(const ENGINE *engine) { +DSA *DSA_new(void) { DSA *dsa = (DSA *)OPENSSL_malloc(sizeof(DSA)); if (dsa == NULL) { OPENSSL_PUT_ERROR(DSA, ERR_R_MALLOC_FAILURE); @@ -88,15 +94,6 @@ DSA *DSA_new_method(const ENGINE *engine) { memset(dsa, 0, sizeof(DSA)); - if (engine) { - dsa->meth = ENGINE_get_DSA_method(engine); - } - - if (dsa->meth == NULL) { - dsa->meth = (DSA_METHOD*) &DSA_default_method; - } - METHOD_ref(dsa->meth); - dsa->write_params = 1; dsa->references = 1; @@ -104,15 +101,6 @@ DSA *DSA_new_method(const ENGINE *engine) { if (!CRYPTO_new_ex_data(&g_ex_data_class, dsa, &dsa->ex_data)) { CRYPTO_MUTEX_cleanup(&dsa->method_mont_p_lock); - METHOD_unref(dsa->meth); - OPENSSL_free(dsa); - return NULL; - } - - if (dsa->meth->init && !dsa->meth->init(dsa)) { - CRYPTO_free_ex_data(&g_ex_data_class, dsa, &dsa->ex_data); - CRYPTO_MUTEX_cleanup(&dsa->method_mont_p_lock); - METHOD_unref(dsa->meth); OPENSSL_free(dsa); return NULL; } @@ -129,11 +117,6 @@ void DSA_free(DSA *dsa) { return; } - if (dsa->meth->finish) { - dsa->meth->finish(dsa); - } - METHOD_unref(dsa->meth); - CRYPTO_free_ex_data(&g_ex_data_class, dsa, &dsa->ex_data); BN_clear_free(dsa->p); @@ -143,6 +126,7 @@ void DSA_free(DSA *dsa) { BN_clear_free(dsa->priv_key); BN_clear_free(dsa->kinv); BN_clear_free(dsa->r); + BN_MONT_CTX_free(dsa->method_mont_p); CRYPTO_MUTEX_cleanup(&dsa->method_mont_p_lock); OPENSSL_free(dsa); } @@ -155,19 +139,319 @@ int DSA_up_ref(DSA *dsa) { int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in, size_t seed_len, int *out_counter, unsigned long *out_h, BN_GENCB *cb) { - if (dsa->meth->generate_parameters) { - return dsa->meth->generate_parameters(dsa, bits, seed_in, seed_len, - out_counter, out_h, cb); + int ok = 0; + unsigned char seed[SHA256_DIGEST_LENGTH]; + unsigned char md[SHA256_DIGEST_LENGTH]; + unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH]; + BIGNUM *r0, *W, *X, *c, *test; + BIGNUM *g = NULL, *q = NULL, *p = NULL; + BN_MONT_CTX *mont = NULL; + int k, n = 0, m = 0; + unsigned i; + int counter = 0; + int r = 0; + BN_CTX *ctx = NULL; + unsigned int h = 2; + unsigned qsize; + const EVP_MD *evpmd; + + evpmd = (bits >= 2048) ? EVP_sha256() : EVP_sha1(); + qsize = EVP_MD_size(evpmd); + + if (bits < 512) { + bits = 512; } - return DSA_default_method.generate_parameters(dsa, bits, seed_in, seed_len, - out_counter, out_h, cb); + + bits = (bits + 63) / 64 * 64; + + if (seed_in != NULL) { + if (seed_len < (size_t)qsize) { + return 0; + } + if (seed_len > (size_t)qsize) { + /* Only consume as much seed as is expected. */ + seed_len = qsize; + } + memcpy(seed, seed_in, seed_len); + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + + mont = BN_MONT_CTX_new(); + if (mont == NULL) { + goto err; + } + + r0 = BN_CTX_get(ctx); + g = BN_CTX_get(ctx); + W = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + c = BN_CTX_get(ctx); + p = BN_CTX_get(ctx); + test = BN_CTX_get(ctx); + + if (test == NULL || !BN_lshift(test, BN_value_one(), bits - 1)) { + goto err; + } + + for (;;) { + /* Find q. */ + for (;;) { + /* step 1 */ + if (!BN_GENCB_call(cb, 0, m++)) { + goto err; + } + + int use_random_seed = (seed_in == NULL); + if (use_random_seed) { + if (!RAND_bytes(seed, qsize)) { + goto err; + } + } else { + /* If we come back through, use random seed next time. */ + seed_in = NULL; + } + memcpy(buf, seed, qsize); + memcpy(buf2, seed, qsize); + /* precompute "SEED + 1" for step 7: */ + for (i = qsize - 1; i < qsize; i--) { + buf[i]++; + if (buf[i] != 0) { + break; + } + } + + /* step 2 */ + if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL) || + !EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) { + goto err; + } + for (i = 0; i < qsize; i++) { + md[i] ^= buf2[i]; + } + + /* step 3 */ + md[0] |= 0x80; + md[qsize - 1] |= 0x01; + if (!BN_bin2bn(md, qsize, q)) { + goto err; + } + + /* step 4 */ + r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, use_random_seed, cb); + if (r > 0) { + break; + } + if (r != 0) { + goto err; + } + + /* do a callback call */ + /* step 5 */ + } + + if (!BN_GENCB_call(cb, 2, 0) || !BN_GENCB_call(cb, 3, 0)) { + goto err; + } + + /* step 6 */ + counter = 0; + /* "offset = 2" */ + + n = (bits - 1) / 160; + + for (;;) { + if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) { + goto err; + } + + /* step 7 */ + BN_zero(W); + /* now 'buf' contains "SEED + offset - 1" */ + for (k = 0; k <= n; k++) { + /* obtain "SEED + offset + k" by incrementing: */ + for (i = qsize - 1; i < qsize; i--) { + buf[i]++; + if (buf[i] != 0) { + break; + } + } + + if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) { + goto err; + } + + /* step 8 */ + if (!BN_bin2bn(md, qsize, r0) || + !BN_lshift(r0, r0, (qsize << 3) * k) || + !BN_add(W, W, r0)) { + goto err; + } + } + + /* more of step 8 */ + if (!BN_mask_bits(W, bits - 1) || + !BN_copy(X, W) || + !BN_add(X, X, test)) { + goto err; + } + + /* step 9 */ + if (!BN_lshift1(r0, q) || + !BN_mod(c, X, r0, ctx) || + !BN_sub(r0, c, BN_value_one()) || + !BN_sub(p, X, r0)) { + goto err; + } + + /* step 10 */ + if (BN_cmp(p, test) >= 0) { + /* step 11 */ + r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb); + if (r > 0) { + goto end; /* found it */ + } + if (r != 0) { + goto err; + } + } + + /* step 13 */ + counter++; + /* "offset = offset + n + 1" */ + + /* step 14 */ + if (counter >= 4096) { + break; + } + } + } +end: + if (!BN_GENCB_call(cb, 2, 1)) { + goto err; + } + + /* We now need to generate g */ + /* Set r0=(p-1)/q */ + if (!BN_sub(test, p, BN_value_one()) || + !BN_div(r0, NULL, test, q, ctx)) { + goto err; + } + + if (!BN_set_word(test, h) || + !BN_MONT_CTX_set(mont, p, ctx)) { + goto err; + } + + for (;;) { + /* g=test^r0%p */ + if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) { + goto err; + } + if (!BN_is_one(g)) { + break; + } + if (!BN_add(test, test, BN_value_one())) { + goto err; + } + h++; + } + + if (!BN_GENCB_call(cb, 3, 1)) { + goto err; + } + + ok = 1; + +err: + if (ok) { + BN_free(dsa->p); + BN_free(dsa->q); + BN_free(dsa->g); + dsa->p = BN_dup(p); + dsa->q = BN_dup(q); + dsa->g = BN_dup(g); + if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { + ok = 0; + goto err; + } + if (out_counter != NULL) { + *out_counter = counter; + } + if (out_h != NULL) { + *out_h = h; + } + } + + if (ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + + BN_MONT_CTX_free(mont); + + return ok; } int DSA_generate_key(DSA *dsa) { - if (dsa->meth->keygen) { - return dsa->meth->keygen(dsa); + int ok = 0; + BN_CTX *ctx = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; + BIGNUM prk; + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; } - return DSA_default_method.keygen(dsa); + + priv_key = dsa->priv_key; + if (priv_key == NULL) { + priv_key = BN_new(); + if (priv_key == NULL) { + goto err; + } + } + + do { + if (!BN_rand_range(priv_key, dsa->q)) { + goto err; + } + } while (BN_is_zero(priv_key)); + + pub_key = dsa->pub_key; + if (pub_key == NULL) { + pub_key = BN_new(); + if (pub_key == NULL) { + goto err; + } + } + + BN_init(&prk); + BN_with_flags(&prk, priv_key, BN_FLG_CONSTTIME); + + if (!BN_mod_exp(pub_key, dsa->g, &prk, dsa->p, ctx)) { + goto err; + } + + dsa->priv_key = priv_key; + dsa->pub_key = pub_key; + ok = 1; + +err: + if (dsa->pub_key == NULL) { + BN_free(pub_key); + } + if (dsa->priv_key == NULL) { + BN_free(priv_key); + } + BN_CTX_free(ctx); + + return ok; } DSA_SIG *DSA_SIG_new(void) { @@ -192,10 +476,99 @@ void DSA_SIG_free(DSA_SIG *sig) { } DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, DSA *dsa) { - if (dsa->meth->sign) { - return dsa->meth->sign(digest, digest_len, dsa); + BIGNUM *kinv = NULL, *r = NULL, *s = NULL; + BIGNUM m; + BIGNUM xr; + BN_CTX *ctx = NULL; + int reason = ERR_R_BN_LIB; + DSA_SIG *ret = NULL; + int noredo = 0; + + BN_init(&m); + BN_init(&xr); + + if (!dsa->p || !dsa->q || !dsa->g) { + reason = DSA_R_MISSING_PARAMETERS; + goto err; } - return DSA_default_method.sign(digest, digest_len, dsa); + + s = BN_new(); + if (s == NULL) { + goto err; + } + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + +redo: + if (dsa->kinv == NULL || dsa->r == NULL) { + if (!DSA_sign_setup(dsa, ctx, &kinv, &r)) { + goto err; + } + } else { + kinv = dsa->kinv; + dsa->kinv = NULL; + r = dsa->r; + dsa->r = NULL; + noredo = 1; + } + + if (digest_len > BN_num_bytes(dsa->q)) { + /* if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see + * fips 186-3, 4.2 */ + digest_len = BN_num_bytes(dsa->q); + } + + if (BN_bin2bn(digest, digest_len, &m) == NULL) { + goto err; + } + + /* Compute s = inv(k) (m + xr) mod q */ + if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx)) { + goto err; /* s = xr */ + } + if (!BN_add(s, &xr, &m)) { + goto err; /* s = m + xr */ + } + if (BN_cmp(s, dsa->q) > 0) { + if (!BN_sub(s, s, dsa->q)) { + goto err; + } + } + if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) { + goto err; + } + + ret = DSA_SIG_new(); + if (ret == NULL) { + goto err; + } + /* Redo if r or s is zero as required by FIPS 186-3: this is + * very unlikely. */ + if (BN_is_zero(r) || BN_is_zero(s)) { + if (noredo) { + reason = DSA_R_NEED_NEW_SETUP_VALUES; + goto err; + } + goto redo; + } + ret->r = r; + ret->s = s; + +err: + if (!ret) { + OPENSSL_PUT_ERROR(DSA, reason); + BN_free(r); + BN_free(s); + } + BN_CTX_free(ctx); + BN_clear_free(&m); + BN_clear_free(&xr); + BN_clear_free(kinv); + + return ret; } int DSA_do_verify(const uint8_t *digest, size_t digest_len, DSA_SIG *sig, @@ -209,11 +582,112 @@ int DSA_do_verify(const uint8_t *digest, size_t digest_len, DSA_SIG *sig, int DSA_do_check_signature(int *out_valid, const uint8_t *digest, size_t digest_len, DSA_SIG *sig, const DSA *dsa) { - if (dsa->meth->verify) { - return dsa->meth->verify(out_valid, digest, digest_len, sig, dsa); + BN_CTX *ctx; + BIGNUM u1, u2, t1; + BN_MONT_CTX *mont = NULL; + int ret = 0; + unsigned i; + + *out_valid = 0; + + if (!dsa->p || !dsa->q || !dsa->g) { + OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS); + return 0; } - return DSA_default_method.verify(out_valid, digest, digest_len, sig, dsa); + i = BN_num_bits(dsa->q); + /* fips 186-3 allows only different sizes for q */ + if (i != 160 && i != 224 && i != 256) { + OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_Q_VALUE); + return 0; + } + + if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) { + OPENSSL_PUT_ERROR(DSA, DSA_R_MODULUS_TOO_LARGE); + return 0; + } + + BN_init(&u1); + BN_init(&u2); + BN_init(&t1); + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + + if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || + BN_ucmp(sig->r, dsa->q) >= 0) { + ret = 1; + goto err; + } + if (BN_is_zero(sig->s) || BN_is_negative(sig->s) || + BN_ucmp(sig->s, dsa->q) >= 0) { + ret = 1; + goto err; + } + + /* Calculate W = inv(S) mod Q + * save W in u2 */ + if (BN_mod_inverse(&u2, sig->s, dsa->q, ctx) == NULL) { + goto err; + } + + /* save M in u1 */ + if (digest_len > (i >> 3)) { + /* if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see + * fips 186-3, 4.2 */ + digest_len = (i >> 3); + } + + if (BN_bin2bn(digest, digest_len, &u1) == NULL) { + goto err; + } + + /* u1 = M * w mod q */ + if (!BN_mod_mul(&u1, &u1, &u2, dsa->q, ctx)) { + goto err; + } + + /* u2 = r * w mod q */ + if (!BN_mod_mul(&u2, sig->r, &u2, dsa->q, ctx)) { + goto err; + } + + mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, + (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, + dsa->p, ctx); + if (!mont) { + goto err; + } + + if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, + mont)) { + goto err; + } + + /* BN_copy(&u1,&t1); */ + /* let u1 = u1 mod q */ + if (!BN_mod(&u1, &t1, dsa->q, ctx)) { + goto err; + } + + /* V is now in u1. If the signature is correct, it will be + * equal to R. */ + *out_valid = BN_ucmp(&u1, sig->r) == 0; + ret = 1; + +err: + if (ret != 1) { + OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB); + } + BN_CTX_free(ctx); + BN_free(&u1); + BN_free(&u2); + BN_free(&t1); + + return ret; } int DSA_sign(int type, const uint8_t *digest, size_t digest_len, @@ -292,13 +766,102 @@ int DSA_size(const DSA *dsa) { return ret; } -int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx, BIGNUM **out_kinv, +int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv, BIGNUM **out_r) { - if (dsa->meth->sign_setup) { - return dsa->meth->sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0); + BN_CTX *ctx; + BIGNUM k, kq, *K, *kinv = NULL, *r = NULL; + int ret = 0; + + if (!dsa->p || !dsa->q || !dsa->g) { + OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS); + return 0; } - return DSA_default_method.sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0); + BN_init(&k); + BN_init(&kq); + + ctx = ctx_in; + if (ctx == NULL) { + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + } + + r = BN_new(); + if (r == NULL) { + goto err; + } + + /* Get random k */ + do { + if (!BN_rand_range(&k, dsa->q)) { + goto err; + } + } while (BN_is_zero(&k)); + + BN_set_flags(&k, BN_FLG_CONSTTIME); + + if (BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, + (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p, + ctx) == NULL) { + goto err; + } + + /* Compute r = (g^k mod p) mod q */ + if (!BN_copy(&kq, &k)) { + goto err; + } + + /* We do not want timing information to leak the length of k, + * so we compute g^k using an equivalent exponent of fixed length. + * + * (This is a kludge that we need because the BN_mod_exp_mont() + * does not let us specify the desired timing behaviour.) */ + + if (!BN_add(&kq, &kq, dsa->q)) { + goto err; + } + if (BN_num_bits(&kq) <= BN_num_bits(dsa->q) && !BN_add(&kq, &kq, dsa->q)) { + goto err; + } + + K = &kq; + + if (!BN_mod_exp_mont(r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p)) { + goto err; + } + if (!BN_mod(r, r, dsa->q, ctx)) { + goto err; + } + + /* Compute part of 's = inv(k) (m + xr) mod q' */ + kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx); + if (kinv == NULL) { + goto err; + } + + BN_clear_free(*out_kinv); + *out_kinv = kinv; + kinv = NULL; + BN_clear_free(*out_r); + *out_r = r; + ret = 1; + +err: + if (!ret) { + OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB); + if (r != NULL) { + BN_clear_free(r); + } + } + + if (ctx_in == NULL) { + BN_CTX_free(ctx); + } + BN_clear_free(&k); + BN_clear_free(&kq); + return ret; } int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, diff --git a/crypto/dsa/dsa_impl.c b/crypto/dsa/dsa_impl.c deleted file mode 100644 index e046f9c6..00000000 --- a/crypto/dsa/dsa_impl.c +++ /dev/null @@ -1,734 +0,0 @@ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - * - * The DSS routines are based on patches supplied by - * Steven Schoch . */ - -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include "internal.h" - -#define OPENSSL_DSA_MAX_MODULUS_BITS 10000 - -/* Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of - * Rabin-Miller */ -#define DSS_prime_checks 50 - -static int sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, - BIGNUM **rp, const uint8_t *digest, size_t digest_len) { - BN_CTX *ctx; - BIGNUM k, kq, *K, *kinv = NULL, *r = NULL; - int ret = 0; - - if (!dsa->p || !dsa->q || !dsa->g) { - OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS); - return 0; - } - - BN_init(&k); - BN_init(&kq); - - ctx = ctx_in; - if (ctx == NULL) { - ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } - } - - r = BN_new(); - if (r == NULL) { - goto err; - } - - /* Get random k */ - do { - /* If possible, we'll include the private key and message digest in the k - * generation. The |digest| argument is only empty if |DSA_sign_setup| is - * being used. */ - int ok; - - if (digest_len > 0) { - ok = BN_generate_dsa_nonce(&k, dsa->q, dsa->priv_key, digest, digest_len, - ctx); - } else { - ok = BN_rand_range(&k, dsa->q); - } - if (!ok) { - goto err; - } - } while (BN_is_zero(&k)); - - BN_set_flags(&k, BN_FLG_CONSTTIME); - - if (BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, - (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p, - ctx) == NULL) { - goto err; - } - - /* Compute r = (g^k mod p) mod q */ - if (!BN_copy(&kq, &k)) { - goto err; - } - - /* We do not want timing information to leak the length of k, - * so we compute g^k using an equivalent exponent of fixed length. - * - * (This is a kludge that we need because the BN_mod_exp_mont() - * does not let us specify the desired timing behaviour.) */ - - if (!BN_add(&kq, &kq, dsa->q)) { - goto err; - } - if (BN_num_bits(&kq) <= BN_num_bits(dsa->q) && !BN_add(&kq, &kq, dsa->q)) { - goto err; - } - - K = &kq; - - if (!BN_mod_exp_mont(r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p)) { - goto err; - } - if (!BN_mod(r, r, dsa->q, ctx)) { - goto err; - } - - /* Compute part of 's = inv(k) (m + xr) mod q' */ - kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx); - if (kinv == NULL) { - goto err; - } - - BN_clear_free(*kinvp); - *kinvp = kinv; - kinv = NULL; - BN_clear_free(*rp); - *rp = r; - ret = 1; - -err: - if (!ret) { - OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB); - if (r != NULL) { - BN_clear_free(r); - } - } - - if (ctx_in == NULL) { - BN_CTX_free(ctx); - } - BN_clear_free(&k); - BN_clear_free(&kq); - return ret; -} - -static DSA_SIG *sign(const uint8_t *digest, size_t digest_len, DSA *dsa) { - BIGNUM *kinv = NULL, *r = NULL, *s = NULL; - BIGNUM m; - BIGNUM xr; - BN_CTX *ctx = NULL; - int reason = ERR_R_BN_LIB; - DSA_SIG *ret = NULL; - int noredo = 0; - - BN_init(&m); - BN_init(&xr); - - if (!dsa->p || !dsa->q || !dsa->g) { - reason = DSA_R_MISSING_PARAMETERS; - goto err; - } - - s = BN_new(); - if (s == NULL) { - goto err; - } - ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } - -redo: - if (dsa->kinv == NULL || dsa->r == NULL) { - if (!DSA_sign_setup(dsa, ctx, &kinv, &r)) { - goto err; - } - } else { - kinv = dsa->kinv; - dsa->kinv = NULL; - r = dsa->r; - dsa->r = NULL; - noredo = 1; - } - - if (digest_len > BN_num_bytes(dsa->q)) { - /* if the digest length is greater than the size of q use the - * BN_num_bits(dsa->q) leftmost bits of the digest, see - * fips 186-3, 4.2 */ - digest_len = BN_num_bytes(dsa->q); - } - - if (BN_bin2bn(digest, digest_len, &m) == NULL) { - goto err; - } - - /* Compute s = inv(k) (m + xr) mod q */ - if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx)) { - goto err; /* s = xr */ - } - if (!BN_add(s, &xr, &m)) { - goto err; /* s = m + xr */ - } - if (BN_cmp(s, dsa->q) > 0) { - if (!BN_sub(s, s, dsa->q)) { - goto err; - } - } - if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) { - goto err; - } - - ret = DSA_SIG_new(); - if (ret == NULL) { - goto err; - } - /* Redo if r or s is zero as required by FIPS 186-3: this is - * very unlikely. */ - if (BN_is_zero(r) || BN_is_zero(s)) { - if (noredo) { - reason = DSA_R_NEED_NEW_SETUP_VALUES; - goto err; - } - goto redo; - } - ret->r = r; - ret->s = s; - -err: - if (!ret) { - OPENSSL_PUT_ERROR(DSA, reason); - BN_free(r); - BN_free(s); - } - BN_CTX_free(ctx); - BN_clear_free(&m); - BN_clear_free(&xr); - BN_clear_free(kinv); - - return ret; -} - -static int verify(int *out_valid, const uint8_t *dgst, size_t digest_len, - DSA_SIG *sig, const DSA *dsa) { - BN_CTX *ctx; - BIGNUM u1, u2, t1; - BN_MONT_CTX *mont = NULL; - int ret = 0; - unsigned i; - - *out_valid = 0; - - if (!dsa->p || !dsa->q || !dsa->g) { - OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS); - return 0; - } - - i = BN_num_bits(dsa->q); - /* fips 186-3 allows only different sizes for q */ - if (i != 160 && i != 224 && i != 256) { - OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_Q_VALUE); - return 0; - } - - if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) { - OPENSSL_PUT_ERROR(DSA, DSA_R_MODULUS_TOO_LARGE); - return 0; - } - - BN_init(&u1); - BN_init(&u2); - BN_init(&t1); - - ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } - - if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || - BN_ucmp(sig->r, dsa->q) >= 0) { - ret = 1; - goto err; - } - if (BN_is_zero(sig->s) || BN_is_negative(sig->s) || - BN_ucmp(sig->s, dsa->q) >= 0) { - ret = 1; - goto err; - } - - /* Calculate W = inv(S) mod Q - * save W in u2 */ - if (BN_mod_inverse(&u2, sig->s, dsa->q, ctx) == NULL) { - goto err; - } - - /* save M in u1 */ - if (digest_len > (i >> 3)) { - /* if the digest length is greater than the size of q use the - * BN_num_bits(dsa->q) leftmost bits of the digest, see - * fips 186-3, 4.2 */ - digest_len = (i >> 3); - } - - if (BN_bin2bn(dgst, digest_len, &u1) == NULL) { - goto err; - } - - /* u1 = M * w mod q */ - if (!BN_mod_mul(&u1, &u1, &u2, dsa->q, ctx)) { - goto err; - } - - /* u2 = r * w mod q */ - if (!BN_mod_mul(&u2, sig->r, &u2, dsa->q, ctx)) { - goto err; - } - - mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, - (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, - dsa->p, ctx); - if (!mont) { - goto err; - } - - if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, - mont)) { - goto err; - } - - /* BN_copy(&u1,&t1); */ - /* let u1 = u1 mod q */ - if (!BN_mod(&u1, &t1, dsa->q, ctx)) { - goto err; - } - - /* V is now in u1. If the signature is correct, it will be - * equal to R. */ - *out_valid = BN_ucmp(&u1, sig->r) == 0; - ret = 1; - -err: - if (ret != 1) { - OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB); - } - BN_CTX_free(ctx); - BN_free(&u1); - BN_free(&u2); - BN_free(&t1); - - return ret; -} - -static int keygen(DSA *dsa) { - int ok = 0; - BN_CTX *ctx = NULL; - BIGNUM *pub_key = NULL, *priv_key = NULL; - BIGNUM prk; - - ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } - - priv_key = dsa->priv_key; - if (priv_key == NULL) { - priv_key = BN_new(); - if (priv_key == NULL) { - goto err; - } - } - - do { - if (!BN_rand_range(priv_key, dsa->q)) { - goto err; - } - } while (BN_is_zero(priv_key)); - - pub_key = dsa->pub_key; - if (pub_key == NULL) { - pub_key = BN_new(); - if (pub_key == NULL) { - goto err; - } - } - - BN_init(&prk); - BN_with_flags(&prk, priv_key, BN_FLG_CONSTTIME); - - if (!BN_mod_exp(pub_key, dsa->g, &prk, dsa->p, ctx)) { - goto err; - } - - dsa->priv_key = priv_key; - dsa->pub_key = pub_key; - ok = 1; - -err: - if (dsa->pub_key == NULL) { - BN_free(pub_key); - } - if (dsa->priv_key == NULL) { - BN_free(priv_key); - } - BN_CTX_free(ctx); - - return ok; -} - -static int paramgen(DSA *ret, unsigned bits, const uint8_t *seed_in, - size_t seed_len, int *counter_ret, unsigned long *h_ret, - BN_GENCB *cb) { - int ok = 0; - unsigned char seed[SHA256_DIGEST_LENGTH]; - unsigned char md[SHA256_DIGEST_LENGTH]; - unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH]; - BIGNUM *r0, *W, *X, *c, *test; - BIGNUM *g = NULL, *q = NULL, *p = NULL; - BN_MONT_CTX *mont = NULL; - int k, n = 0, m = 0; - unsigned i; - int counter = 0; - int r = 0; - BN_CTX *ctx = NULL; - unsigned int h = 2; - unsigned qsize; - const EVP_MD *evpmd; - - evpmd = (bits >= 2048) ? EVP_sha256() : EVP_sha1(); - qsize = EVP_MD_size(evpmd); - - if (bits < 512) { - bits = 512; - } - - bits = (bits + 63) / 64 * 64; - - if (seed_in != NULL) { - if (seed_len < (size_t)qsize) { - return 0; - } - if (seed_len > (size_t)qsize) { - /* Only consume as much seed as is expected. */ - seed_len = qsize; - } - memcpy(seed, seed_in, seed_len); - } - - ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } - BN_CTX_start(ctx); - - mont = BN_MONT_CTX_new(); - if (mont == NULL) { - goto err; - } - - r0 = BN_CTX_get(ctx); - g = BN_CTX_get(ctx); - W = BN_CTX_get(ctx); - q = BN_CTX_get(ctx); - X = BN_CTX_get(ctx); - c = BN_CTX_get(ctx); - p = BN_CTX_get(ctx); - test = BN_CTX_get(ctx); - - if (test == NULL || !BN_lshift(test, BN_value_one(), bits - 1)) { - goto err; - } - - for (;;) { - /* Find q. */ - for (;;) { - /* step 1 */ - if (!BN_GENCB_call(cb, 0, m++)) { - goto err; - } - - int use_random_seed = (seed_in == NULL); - if (use_random_seed) { - if (!RAND_bytes(seed, qsize)) { - goto err; - } - } else { - /* If we come back through, use random seed next time. */ - seed_in = NULL; - } - memcpy(buf, seed, qsize); - memcpy(buf2, seed, qsize); - /* precompute "SEED + 1" for step 7: */ - for (i = qsize - 1; i < qsize; i--) { - buf[i]++; - if (buf[i] != 0) { - break; - } - } - - /* step 2 */ - if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL) || - !EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) { - goto err; - } - for (i = 0; i < qsize; i++) { - md[i] ^= buf2[i]; - } - - /* step 3 */ - md[0] |= 0x80; - md[qsize - 1] |= 0x01; - if (!BN_bin2bn(md, qsize, q)) { - goto err; - } - - /* step 4 */ - r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, use_random_seed, cb); - if (r > 0) { - break; - } - if (r != 0) { - goto err; - } - - /* do a callback call */ - /* step 5 */ - } - - if (!BN_GENCB_call(cb, 2, 0) || !BN_GENCB_call(cb, 3, 0)) { - goto err; - } - - /* step 6 */ - counter = 0; - /* "offset = 2" */ - - n = (bits - 1) / 160; - - for (;;) { - if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) { - goto err; - } - - /* step 7 */ - BN_zero(W); - /* now 'buf' contains "SEED + offset - 1" */ - for (k = 0; k <= n; k++) { - /* obtain "SEED + offset + k" by incrementing: */ - for (i = qsize - 1; i < qsize; i--) { - buf[i]++; - if (buf[i] != 0) { - break; - } - } - - if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) { - goto err; - } - - /* step 8 */ - if (!BN_bin2bn(md, qsize, r0) || - !BN_lshift(r0, r0, (qsize << 3) * k) || - !BN_add(W, W, r0)) { - goto err; - } - } - - /* more of step 8 */ - if (!BN_mask_bits(W, bits - 1) || - !BN_copy(X, W) || - !BN_add(X, X, test)) { - goto err; - } - - /* step 9 */ - if (!BN_lshift1(r0, q) || - !BN_mod(c, X, r0, ctx) || - !BN_sub(r0, c, BN_value_one()) || - !BN_sub(p, X, r0)) { - goto err; - } - - /* step 10 */ - if (BN_cmp(p, test) >= 0) { - /* step 11 */ - r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb); - if (r > 0) { - goto end; /* found it */ - } - if (r != 0) { - goto err; - } - } - - /* step 13 */ - counter++; - /* "offset = offset + n + 1" */ - - /* step 14 */ - if (counter >= 4096) { - break; - } - } - } -end: - if (!BN_GENCB_call(cb, 2, 1)) { - goto err; - } - - /* We now need to generate g */ - /* Set r0=(p-1)/q */ - if (!BN_sub(test, p, BN_value_one()) || - !BN_div(r0, NULL, test, q, ctx)) { - goto err; - } - - if (!BN_set_word(test, h) || - !BN_MONT_CTX_set(mont, p, ctx)) { - goto err; - } - - for (;;) { - /* g=test^r0%p */ - if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) { - goto err; - } - if (!BN_is_one(g)) { - break; - } - if (!BN_add(test, test, BN_value_one())) { - goto err; - } - h++; - } - - if (!BN_GENCB_call(cb, 3, 1)) { - goto err; - } - - ok = 1; - -err: - if (ok) { - BN_free(ret->p); - BN_free(ret->q); - BN_free(ret->g); - ret->p = BN_dup(p); - ret->q = BN_dup(q); - ret->g = BN_dup(g); - if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { - ok = 0; - goto err; - } - if (counter_ret != NULL) { - *counter_ret = counter; - } - if (h_ret != NULL) { - *h_ret = h; - } - } - - if (ctx) { - BN_CTX_end(ctx); - BN_CTX_free(ctx); - } - - BN_MONT_CTX_free(mont); - - return ok; -} - -static int finish(DSA *dsa) { - BN_MONT_CTX_free(dsa->method_mont_p); - dsa->method_mont_p = NULL; - return 1; -} - -const struct dsa_method DSA_default_method = { - { - 0 /* references */, - 1 /* is_static */, - }, - NULL /* app_data */, - - NULL /* init */, - finish /* finish */, - - sign, - sign_setup, - verify, - - paramgen, - keygen, -}; diff --git a/crypto/engine/engine.c b/crypto/engine/engine.c index 6c3300d3..25ea98de 100644 --- a/crypto/engine/engine.c +++ b/crypto/engine/engine.c @@ -17,8 +17,6 @@ #include #include -#include -#include #include #include #include @@ -27,8 +25,6 @@ struct engine_st { - DH_METHOD *dh_method; - DSA_METHOD *dsa_method; RSA_METHOD *rsa_method; ECDSA_METHOD *ecdsa_method; }; @@ -64,26 +60,6 @@ static int set_method(void **out_member, const void *method, size_t method_size, return 1; } -int ENGINE_set_DH_method(ENGINE *engine, const DH_METHOD *method, - size_t method_size) { - return set_method((void **)&engine->dh_method, method, method_size, - sizeof(DH_METHOD)); -} - -DH_METHOD *ENGINE_get_DH_method(const ENGINE *engine) { - return engine->dh_method; -} - -int ENGINE_set_DSA_method(ENGINE *engine, const DSA_METHOD *method, - size_t method_size) { - return set_method((void **)&engine->dsa_method, method, method_size, - sizeof(DSA_METHOD)); -} - -DSA_METHOD *ENGINE_get_DSA_method(const ENGINE *engine) { - return engine->dsa_method; -} - int ENGINE_set_RSA_method(ENGINE *engine, const RSA_METHOD *method, size_t method_size) { return set_method((void **)&engine->rsa_method, method, method_size, diff --git a/include/openssl/base.h b/include/openssl/base.h index f0aafec4..604bd969 100644 --- a/include/openssl/base.h +++ b/include/openssl/base.h @@ -201,9 +201,7 @@ typedef struct cbs_st CBS; typedef struct cmac_ctx_st CMAC_CTX; typedef struct conf_st CONF; typedef struct conf_value_st CONF_VALUE; -typedef struct dh_method DH_METHOD; typedef struct dh_st DH; -typedef struct dsa_method DSA_METHOD; typedef struct dsa_st DSA; typedef struct ec_key_st EC_KEY; typedef struct ecdsa_method_st ECDSA_METHOD; diff --git a/include/openssl/dh.h b/include/openssl/dh.h index 75df632c..d781789e 100644 --- a/include/openssl/dh.h +++ b/include/openssl/dh.h @@ -77,9 +77,6 @@ extern "C" { /* DH_new returns a new, empty DH object or NULL on error. */ OPENSSL_EXPORT DH *DH_new(void); -/* DH_new_method acts the same as |DH_new| but takes an explicit |ENGINE|. */ -OPENSSL_EXPORT DH *DH_new_method(const ENGINE *engine); - /* DH_free decrements the reference count of |dh| and frees it if the reference * count drops to zero. */ OPENSSL_EXPORT void DH_free(DH *dh); @@ -90,9 +87,8 @@ OPENSSL_EXPORT int DH_up_ref(DH *dh); /* Standard parameters. * - * These functions return new DH objects with standard parameters configured - * that use the given ENGINE, which may be NULL. They return NULL on allocation - * failure. */ + * These functions return new DH objects with standard parameters. They return + * NULL on allocation failure. The |engine| parameter is ignored. */ /* These parameters are taken from RFC 5114. */ @@ -204,35 +200,7 @@ OPENSSL_EXPORT int DH_set_ex_data(DH *d, int idx, void *arg); OPENSSL_EXPORT void *DH_get_ex_data(DH *d, int idx); -/* dh_method contains function pointers to override the implementation of DH. - * See |engine.h| for details. */ -struct dh_method { - struct openssl_method_common_st common; - - /* app_data is an opaque pointer for the method to use. */ - void *app_data; - - /* init is called just before the return of |DH_new_method|. It returns one - * on success or zero on error. */ - int (*init)(DH *dh); - - /* finish is called before |dh| is destructed. */ - void (*finish)(DH *dh); - - /* generate_parameters is called by |DH_generate_parameters_ex|. */ - int (*generate_parameters)(DH *dh, int prime_bits, int generator, - BN_GENCB *cb); - - /* generate_parameters is called by |DH_generate_key|. */ - int (*generate_key)(DH *dh); - - /* compute_key is called by |DH_compute_key|. */ - int (*compute_key)(DH *dh, uint8_t *out, const BIGNUM *pub_key); -}; - struct dh_st { - DH_METHOD *meth; - BIGNUM *p; BIGNUM *g; BIGNUM *pub_key; /* g^x mod p */ diff --git a/include/openssl/dsa.h b/include/openssl/dsa.h index b1e73091..bd163950 100644 --- a/include/openssl/dsa.h +++ b/include/openssl/dsa.h @@ -80,9 +80,6 @@ extern "C" { /* DSA_new returns a new, empty DSA object or NULL on error. */ OPENSSL_EXPORT DSA *DSA_new(void); -/* DSA_new_method acts the same as |DH_new| but takes an explicit |ENGINE|. */ -OPENSSL_EXPORT DSA *DSA_new_method(const ENGINE *engine); - /* DSA_free decrements the reference count of |dsa| and frees it if the * reference count drops to zero. */ OPENSSL_EXPORT void DSA_free(DSA *dsa); @@ -312,31 +309,6 @@ OPENSSL_EXPORT int DSA_set_ex_data(DSA *d, int idx, void *arg); OPENSSL_EXPORT void *DSA_get_ex_data(const DSA *d, int idx); -struct dsa_method { - struct openssl_method_common_st common; - - void *app_data; - - int (*init)(DSA *dsa); - int (*finish)(DSA *dsa); - - DSA_SIG *(*sign)(const uint8_t *digest, size_t digest_len, DSA *dsa); - - int (*sign_setup)(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, - const uint8_t *digest, size_t digest_len); - - int (*verify)(int *out_valid, const uint8_t *digest, size_t digest_len, - DSA_SIG *sig, const DSA *dsa); - - /* generate_parameters, if non-NULL, is used to generate DSA parameters. */ - int (*generate_parameters)(DSA *dsa, unsigned bits, const uint8_t *seed, - size_t seed_len, int *counter_ret, - unsigned long *h_ret, BN_GENCB *cb); - - /* keygen, if non-NULL, is used to generate DSA keys. */ - int (*keygen)(DSA *dsa); -}; - struct dsa_st { long version; int write_params; @@ -356,9 +328,6 @@ struct dsa_st { BN_MONT_CTX *method_mont_p; CRYPTO_refcount_t references; CRYPTO_EX_DATA ex_data; - DSA_METHOD *meth; - /* functional reference if 'meth' is ENGINE-provided */ - ENGINE *engine; }; diff --git a/include/openssl/engine.h b/include/openssl/engine.h index d3d278a6..128a2ae1 100644 --- a/include/openssl/engine.h +++ b/include/openssl/engine.h @@ -53,15 +53,6 @@ OPENSSL_EXPORT void ENGINE_free(ENGINE *engine); * * Set functions return one on success and zero on allocation failure. */ -OPENSSL_EXPORT int ENGINE_set_DH_method(ENGINE *engine, const DH_METHOD *method, - size_t method_size); -OPENSSL_EXPORT DH_METHOD *ENGINE_get_DH_method(const ENGINE *engine); - -OPENSSL_EXPORT int ENGINE_set_DSA_method(ENGINE *engine, - const DSA_METHOD *method, - size_t method_size); -OPENSSL_EXPORT DSA_METHOD *ENGINE_get_DSA_method(const ENGINE *engine); - OPENSSL_EXPORT int ENGINE_set_RSA_method(ENGINE *engine, const RSA_METHOD *method, size_t method_size);