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 <agl@google.com>
diff --git a/crypto/dh/CMakeLists.txt b/crypto/dh/CMakeLists.txt
index 8ddf03d..f1e8616 100644
--- a/crypto/dh/CMakeLists.txt
+++ b/crypto/dh/CMakeLists.txt
@@ -6,7 +6,6 @@
   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 ee6c9a0..a88520d 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 @@
 
   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 @@
     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 @@
     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 @@
 }
 
 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;
   }
-  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_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 6cf0abb..0000000
--- 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 <openssl/dh.h>
-
-#include <openssl/bn.h>
-#include <openssl/err.h>
-#include <openssl/thread.h>
-
-#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 <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 '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 2bfccb8..6b30036 100644
--- a/crypto/dh/params.c
+++ b/crypto/dh/params.c
@@ -264,9 +264,7 @@
 
 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 654f18c..de36565 100644
--- a/crypto/dsa/CMakeLists.txt
+++ b/crypto/dsa/CMakeLists.txt
@@ -6,7 +6,6 @@
   OBJECT
 
   dsa.c
-  dsa_impl.c
   dsa_asn1.c
 )
 
diff --git a/crypto/dsa/dsa.c b/crypto/dsa/dsa.c
index eb8e61f..ceffd1a 100644
--- a/crypto/dsa/dsa.c
+++ b/crypto/dsa/dsa.c
@@ -62,24 +62,30 @@
 #include <string.h>
 
 #include <openssl/asn1.h>
+#include <openssl/bn.h>
 #include <openssl/dh.h>
+#include <openssl/digest.h>
 #include <openssl/engine.h>
 #include <openssl/err.h>
 #include <openssl/ex_data.h>
 #include <openssl/mem.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
 #include <openssl/thread.h>
 
 #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 @@
 
   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 @@
 
   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 @@
     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 @@
   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_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 @@
 }
 
 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_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 @@
   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 e046f9c..0000000
--- 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 <schoch@sheba.arc.nasa.gov>. */
-
-#include <openssl/dsa.h>
-
-#include <string.h>
-
-#include <openssl/bn.h>
-#include <openssl/digest.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
-#include <openssl/sha.h>
-#include <openssl/thread.h>
-
-#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 6c3300d..25ea98d 100644
--- a/crypto/engine/engine.c
+++ b/crypto/engine/engine.c
@@ -17,8 +17,6 @@
 #include <string.h>
 #include <assert.h>
 
-#include <openssl/dh.h>
-#include <openssl/dsa.h>
 #include <openssl/ec_key.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
@@ -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 @@
   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 f0aafec..604bd96 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -201,9 +201,7 @@
 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 75df632..d781789 100644
--- a/include/openssl/dh.h
+++ b/include/openssl/dh.h
@@ -77,9 +77,6 @@
 /* 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 @@
 
 /* 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 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 b1e7309..bd16395 100644
--- a/include/openssl/dsa.h
+++ b/include/openssl/dsa.h
@@ -80,9 +80,6 @@
 /* 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 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 @@
   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 d3d278a..128a2ae 100644
--- a/include/openssl/engine.h
+++ b/include/openssl/engine.h
@@ -53,15 +53,6 @@
  *
  * 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);