summaryrefslogtreecommitdiff
path: root/ext/openssl
diff options
context:
space:
mode:
Diffstat (limited to 'ext/openssl')
-rw-r--r--ext/openssl/lib/openssl/pkey.rb57
-rw-r--r--ext/openssl/ossl_pkey_dh.c186
2 files changed, 90 insertions, 153 deletions
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
index be60ac2beb..5a3d0ed1ef 100644
--- a/ext/openssl/lib/openssl/pkey.rb
+++ b/ext/openssl/lib/openssl/pkey.rb
@@ -27,6 +27,63 @@ module OpenSSL::PKey
peer.set_key(pub_bn, nil)
derive(peer)
end
+
+ # :call-seq:
+ # dh.generate_key! -> self
+ #
+ # Generates a private and public key unless a private key already exists.
+ # If this DH instance was generated from public \DH parameters (e.g. by
+ # encoding the result of DH#public_key), then this method needs to be
+ # called first in order to generate the per-session keys before performing
+ # the actual key exchange.
+ #
+ # See also OpenSSL::PKey.generate_key.
+ #
+ # Example:
+ # dh = OpenSSL::PKey::DH.new(2048)
+ # public_key = dh.public_key #contains no private/public key yet
+ # public_key.generate_key!
+ # puts public_key.private? # => true
+ def generate_key!
+ unless priv_key
+ tmp = OpenSSL::PKey.generate_key(self)
+ set_key(tmp.pub_key, tmp.priv_key)
+ end
+ self
+ end
+
+ class << self
+ # :call-seq:
+ # DH.generate(size, generator = 2) -> dh
+ #
+ # Creates a new DH instance from scratch by generating random parameters
+ # and a key pair.
+ #
+ # See also OpenSSL::PKey.generate_parameters and
+ # OpenSSL::PKey.generate_key.
+ #
+ # +size+::
+ # The desired key size in bits.
+ # +generator+::
+ # The generator.
+ def generate(size, generator = 2, &blk)
+ dhparams = OpenSSL::PKey.generate_parameters("DH", {
+ "dh_paramgen_prime_len" => size,
+ "dh_paramgen_generator" => generator,
+ }, &blk)
+ OpenSSL::PKey.generate_key(dhparams)
+ end
+
+ # Handle DH.new(size, generator) form here; new(str) and new() forms
+ # are handled by #initialize
+ def new(*args, &blk) # :nodoc:
+ if args[0].is_a?(Integer)
+ generate(*args, &blk)
+ else
+ super
+ end
+ end
+ end
end
class DSA
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index 5bc1c49ca1..6b477b077c 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -32,147 +32,56 @@ VALUE eDHError;
/*
* Private
*/
-struct dh_blocking_gen_arg {
- DH *dh;
- int size;
- int gen;
- BN_GENCB *cb;
- int result;
-};
-
-static void *
-dh_blocking_gen(void *arg)
-{
- struct dh_blocking_gen_arg *gen = (struct dh_blocking_gen_arg *)arg;
- gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb);
- return 0;
-}
-
-static DH *
-dh_generate(int size, int gen)
-{
- struct ossl_generate_cb_arg cb_arg = { 0 };
- struct dh_blocking_gen_arg gen_arg;
- DH *dh = DH_new();
- BN_GENCB *cb = BN_GENCB_new();
-
- if (!dh || !cb) {
- DH_free(dh);
- BN_GENCB_free(cb);
- ossl_raise(eDHError, "malloc failure");
- }
-
- if (rb_block_given_p())
- cb_arg.yield = 1;
- BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
- gen_arg.dh = dh;
- gen_arg.size = size;
- gen_arg.gen = gen;
- gen_arg.cb = cb;
- if (cb_arg.yield == 1) {
- /* we cannot release GVL when callback proc is supplied */
- dh_blocking_gen(&gen_arg);
- } else {
- /* there's a chance to unblock */
- rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
- }
-
- BN_GENCB_free(cb);
- if (!gen_arg.result) {
- DH_free(dh);
- if (cb_arg.state) {
- /* Clear OpenSSL error queue before re-raising. */
- ossl_clear_error();
- rb_jump_tag(cb_arg.state);
- }
- ossl_raise(eDHError, "DH_generate_parameters_ex");
- }
-
- if (!DH_generate_key(dh)) {
- DH_free(dh);
- ossl_raise(eDHError, "DH_generate_key");
- }
-
- return dh;
-}
-
-/*
- * call-seq:
- * DH.generate(size [, generator]) -> dh
- *
- * Creates a new DH instance from scratch by generating the private and public
- * components alike.
- *
- * === Parameters
- * * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
- * * _generator_ is a small number > 1, typically 2 or 5.
- *
- */
-static VALUE
-ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
-{
- EVP_PKEY *pkey;
- DH *dh ;
- int g = 2;
- VALUE size, gen, obj;
-
- if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
- g = NUM2INT(gen);
- }
- obj = rb_obj_alloc(klass);
- GetPKey(obj, pkey);
-
- dh = dh_generate(NUM2INT(size), g);
- if (!EVP_PKEY_assign_DH(pkey, dh)) {
- DH_free(dh);
- ossl_raise(eDHError, "EVP_PKEY_assign_DH");
- }
- return obj;
-}
-
/*
* call-seq:
* DH.new -> dh
* DH.new(string) -> dh
* DH.new(size [, generator]) -> dh
*
- * Either generates a DH instance from scratch or by reading already existing
- * DH parameters from _string_. Note that when reading a DH instance from
- * data that was encoded from a DH instance by using DH#to_pem or DH#to_der
- * the result will *not* contain a public/private key pair yet. This needs to
- * be generated using DH#generate_key! first.
+ * Creates a new instance of OpenSSL::PKey::DH.
+ *
+ * If called without arguments, an empty instance without any parameter or key
+ * components is created. Use #set_pqg to manually set the parameters afterwards
+ * (and optionally #set_key to set private and public key components).
+ *
+ * If a String is given, tries to parse it as a DER- or PEM- encoded parameters.
+ * See also OpenSSL::PKey.read which can parse keys of any kinds.
+ *
+ * The DH.new(size [, generator]) form is an alias of DH.generate.
*
- * === Parameters
- * * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
- * * _generator_ is a small number > 1, typically 2 or 5.
- * * _string_ contains the DER or PEM encoded key.
+ * +string+::
+ * A String that contains the DER or PEM encoded key.
+ * +size+::
+ * See DH.generate.
+ * +generator+::
+ * See DH.generate.
*
- * === Examples
- * DH.new # -> dh
- * DH.new(1024) # -> dh
- * DH.new(1024, 5) # -> dh
- * #Reading DH parameters
- * dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
- * dh.generate_key! # -> dh with public and private key
+ * Examples:
+ * # Creating an instance from scratch
+ * dh = DH.new
+ * dh.set_pqg(bn_p, nil, bn_g)
+ *
+ * # Generating a parameters and a key pair
+ * dh = DH.new(2048) # An alias of DH.generate(2048)
+ *
+ * # Reading DH parameters
+ * dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
+ * dh.generate_key! # -> dh with public and private key
*/
static VALUE
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
DH *dh;
- int g = 2;
BIO *in;
- VALUE arg, gen;
+ VALUE arg;
GetPKey(self, pkey);
- if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
- dh = DH_new();
- }
- else if (RB_INTEGER_TYPE_P(arg)) {
- if (!NIL_P(gen)) {
- g = NUM2INT(gen);
- }
- dh = dh_generate(NUM2INT(arg), g);
+ /* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */
+ if (rb_scan_args(argc, argv, "01", &arg) == 0) {
+ dh = DH_new();
+ if (!dh)
+ ossl_raise(eDHError, "DH_new");
}
else {
arg = ossl_to_der_if_possible(arg);
@@ -450,33 +359,6 @@ ossl_dh_check_params(VALUE self)
}
/*
- * call-seq:
- * dh.generate_key! -> self
- *
- * Generates a private and public key unless a private key already exists.
- * If this DH instance was generated from public DH parameters (e.g. by
- * encoding the result of DH#public_key), then this method needs to be
- * called first in order to generate the per-session keys before performing
- * the actual key exchange.
- *
- * === Example
- * dh = OpenSSL::PKey::DH.new(2048)
- * public_key = dh.public_key #contains no private/public key yet
- * public_key.generate_key!
- * puts public_key.private? # => true
- */
-static VALUE
-ossl_dh_generate_key(VALUE self)
-{
- DH *dh;
-
- GetDH(self, dh);
- if (!DH_generate_key(dh))
- ossl_raise(eDHError, "Failed to generate key");
- return self;
-}
-
-/*
* Document-method: OpenSSL::PKey::DH#set_pqg
* call-seq:
* dh.set_pqg(p, q, g) -> self
@@ -540,7 +422,6 @@ Init_ossl_dh(void)
* puts symm_key1 == symm_key2 # => true
*/
cDH = rb_define_class_under(mPKey, "DH", cPKey);
- rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1);
rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
@@ -552,7 +433,6 @@ Init_ossl_dh(void)
rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
- rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
DEF_OSSL_PKEY_BN(cDH, dh, p);
DEF_OSSL_PKEY_BN(cDH, dh, q);