summaryrefslogtreecommitdiffstats
path: root/src/crypto/dh/dh.c
diff options
context:
space:
mode:
authorAdam Langley <agl@google.com>2015-11-12 12:15:39 -0800
committerAdam Langley <agl@google.com>2015-11-12 12:16:24 -0800
commitfad6327e4112082b1e77e89a995723f26bd5a9aa (patch)
treea1a6dd4f0310c9a9ce682a0436f80e27c56bf8e4 /src/crypto/dh/dh.c
parente99801b603dea8893dcc61c70b327ef2d00b652c (diff)
downloadexternal_boringssl-fad6327e4112082b1e77e89a995723f26bd5a9aa.zip
external_boringssl-fad6327e4112082b1e77e89a995723f26bd5a9aa.tar.gz
external_boringssl-fad6327e4112082b1e77e89a995723f26bd5a9aa.tar.bz2
external/boringssl: update from upstream
BUG=24082170 7104cc9 Update and fix fuzzing instructions. 9a4beb8 Add four, basic fuzz tests. 4ab2540 Add AArch64 Montgomery assembly. ad38dc7 Enable Montgomery optimisations on ARM. 2e64f1b Check PKCS#8 pkey field is valid before cleansing. f606f98 bssl pkcs12 shouldn't crash on missing key. e348ff4 Fix build. 6e80765 Add SSL_get_server_key_exchange_hash. 788be4a Remove the hard-coded SHA-1 exception for sigalgs. 5d5e39f Remove non-ASM version of |bn_mul_mont| in bn/generic.c. 59b0fcc Define BORINGSSL_201510. e6d1e5a Use typedef names, not struct names. 16285ea Rewrite DTLS handshake message sending logic. c81ee8b Add missing state to DTLS state machine. 2e24b9b Allow SHA-512 unaligned data access in |OPENSSL_NO_ASM| mode. e82e6f6 Constify more BN_MONT_CTX parameters. c7817d8 Add SSL_CIPHER_get_min_version and tidy up SSL_TLSV1_2 logic. 9d94d5e Remove untested, unnecessary big-endian SHA-1/SHA-256 optimizations. 38feb99 Require that EC points are on the curve. ef793f4 Add various functions for SSL_CIPHER. f93995b Test that the client doesn't offer TLS 1.2 ciphers when it shouldn't. 5f88999 Fix up several comments and detect problems in the future. e57a192 Add missing newline in aead.h. c2d3280 Add SSL_get_ivs. a97b737 Separate CCS and handshake writing in DTLS. ac9404c Improve crypto/digest/md32_common.h mechanism. 8fb0f52 Free BN_MONT_CTX in generic code. bb87535 Fix ASan bot. d93831d Make it possible for a static linker to discard unused RSA functions. e8f783a Unwind DH_METHOD and DSA_METHOD. 3fc138e Don't bother sampling __func__. 165248c Fix several MSVC warnings. 8f7ecb8 (Hopefully) fix a warning on Windows. 466b989 Initialise variable before jump. 1895493 Add Intel's P-256 27a0d08 Add ssl_renegotiate_ignore. fa9eb56 Correct the spelling of "primitive". f1c1cf8 Revert "Improve crypto/digest/md32_common.h mechanism." 00461cf Improve crypto/digest/md32_common.h mechanism. ecc2591 Update link to Google style guide. efb42fb Make BN_mod_exp_mont_consttime take a const context. eb8be01 Add ciphers option to bssl. 09d68c9 Expand a comment. 2e0901b Don't use ssl3_write_pending in DTLS. 13e81fc Fix DTLS asynchronous write handling. ebda9b3 Make recordingconn emit more useful things for DTLS. 069bedf Fix documentation typo. ce51469 Fix a missing initializer that only Clang warns about. d9e8173 Fix several warnings that arise in Android. bb85f3d Reorganise |SSL_SESSION| and |SSL| to save a little memory. dff504d Make the instructions for downloading the ARM compiler easier to copy and paste. Change-Id: I5ef2238f77f2bcab239919c8c50c3705b4577f09
Diffstat (limited to 'src/crypto/dh/dh.c')
-rw-r--r--src/crypto/dh/dh.c282
1 files changed, 245 insertions, 37 deletions
diff --git a/src/crypto/dh/dh.c b/src/crypto/dh/dh.c
index ee6c9a0..a88520d 100644
--- a/src/crypto/dh/dh.c
+++ b/src/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 <karn@qualcomm.com> 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 |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 DH_default_method.generate_parameters(dh, prime_bits, generator, cb);
+ 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;
+ }
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
}
- return DH_default_method.compute_key(dh, out, peers_key);
+ 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);
}