You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1004 lines
32 KiB
1004 lines
32 KiB
From 6bbdaef1a578fdbfc6a5bf82402ba4d3fd733d4a Mon Sep 17 00:00:00 2001 |
|
From: Kazuki Yamaguchi <k@rhe.jp> |
|
Date: Tue, 21 Mar 2017 18:23:53 +0900 |
|
Subject: [PATCH 1/6] pkey: assume generic PKeys contain private components |
|
|
|
The EVP interface cannot tell whether if a pkey contains the private |
|
components or not. Assume it does if it does not respond to #private?. |
|
This fixes the NoMethodError on calling #sign on a generic PKey. |
|
--- |
|
ext/openssl/ossl_pkey.c | 15 +++++++++++---- |
|
1 file changed, 11 insertions(+), 4 deletions(-) |
|
|
|
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c |
|
index 610a83fd2d..8d41623e80 100644 |
|
--- a/ext/openssl/ossl_pkey.c |
|
+++ b/ext/openssl/ossl_pkey.c |
|
@@ -252,12 +252,19 @@ GetPrivPKeyPtr(VALUE obj) |
|
{ |
|
EVP_PKEY *pkey; |
|
|
|
- if (rb_funcallv(obj, id_private_q, 0, NULL) != Qtrue) { |
|
- ossl_raise(rb_eArgError, "Private key is needed."); |
|
- } |
|
GetPKey(obj, pkey); |
|
+ if (OSSL_PKEY_IS_PRIVATE(obj)) |
|
+ return pkey; |
|
+ /* |
|
+ * The EVP API does not provide a way to check if the EVP_PKEY has private |
|
+ * components. Assuming it does... |
|
+ */ |
|
+ if (!rb_respond_to(obj, id_private_q)) |
|
+ return pkey; |
|
+ if (RTEST(rb_funcallv(obj, id_private_q, 0, NULL))) |
|
+ return pkey; |
|
|
|
- return pkey; |
|
+ rb_raise(rb_eArgError, "private key is needed"); |
|
} |
|
|
|
EVP_PKEY * |
|
-- |
|
2.32.0 |
|
|
|
|
|
From 86508f74b3d41166ed6091b7b31f18a26478c347 Mon Sep 17 00:00:00 2001 |
|
From: Kazuki Yamaguchi <k@rhe.jp> |
|
Date: Mon, 20 Mar 2017 23:18:26 +0900 |
|
Subject: [PATCH 2/6] pkey: add PKey.generate_parameters and .generate_key |
|
|
|
Add two methods to create a PKey using the generic EVP interface. This |
|
is useful for the PKey types we don't have a dedicated class. |
|
--- |
|
ext/openssl/ossl_pkey.c | 222 ++++++++++++++++++++++++++++++++++++++ |
|
test/openssl/test_pkey.rb | 43 ++++++++ |
|
2 files changed, 265 insertions(+) |
|
|
|
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c |
|
index 8d41623e80..1f3dd39b9b 100644 |
|
--- a/ext/openssl/ossl_pkey.c |
|
+++ b/ext/openssl/ossl_pkey.c |
|
@@ -197,6 +197,226 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self) |
|
return ossl_pkey_new(pkey); |
|
} |
|
|
|
+static VALUE |
|
+pkey_gen_apply_options_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ctx_v)) |
|
+{ |
|
+ VALUE key = rb_ary_entry(i, 0), value = rb_ary_entry(i, 1); |
|
+ EVP_PKEY_CTX *ctx = (EVP_PKEY_CTX *)ctx_v; |
|
+ |
|
+ if (SYMBOL_P(key)) |
|
+ key = rb_sym2str(key); |
|
+ value = rb_String(value); |
|
+ |
|
+ if (EVP_PKEY_CTX_ctrl_str(ctx, StringValueCStr(key), StringValueCStr(value)) <= 0) |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_ctrl_str(ctx, %+"PRIsVALUE", %+"PRIsVALUE")", |
|
+ key, value); |
|
+ return Qnil; |
|
+} |
|
+ |
|
+static VALUE |
|
+pkey_gen_apply_options0(VALUE args_v) |
|
+{ |
|
+ VALUE *args = (VALUE *)args_v; |
|
+ |
|
+ rb_block_call(args[1], rb_intern("each"), 0, NULL, |
|
+ pkey_gen_apply_options_i, args[0]); |
|
+ return Qnil; |
|
+} |
|
+ |
|
+struct pkey_blocking_generate_arg { |
|
+ EVP_PKEY_CTX *ctx; |
|
+ EVP_PKEY *pkey; |
|
+ int state; |
|
+ int yield: 1; |
|
+ int genparam: 1; |
|
+ int stop: 1; |
|
+}; |
|
+ |
|
+static VALUE |
|
+pkey_gen_cb_yield(VALUE ctx_v) |
|
+{ |
|
+ EVP_PKEY_CTX *ctx = (void *)ctx_v; |
|
+ int i, info_num; |
|
+ VALUE *argv; |
|
+ |
|
+ info_num = EVP_PKEY_CTX_get_keygen_info(ctx, -1); |
|
+ argv = ALLOCA_N(VALUE, info_num); |
|
+ for (i = 0; i < info_num; i++) |
|
+ argv[i] = INT2NUM(EVP_PKEY_CTX_get_keygen_info(ctx, i)); |
|
+ |
|
+ return rb_yield_values2(info_num, argv); |
|
+} |
|
+ |
|
+static int |
|
+pkey_gen_cb(EVP_PKEY_CTX *ctx) |
|
+{ |
|
+ struct pkey_blocking_generate_arg *arg = EVP_PKEY_CTX_get_app_data(ctx); |
|
+ |
|
+ if (arg->yield) { |
|
+ int state; |
|
+ rb_protect(pkey_gen_cb_yield, (VALUE)ctx, &state); |
|
+ if (state) { |
|
+ arg->stop = 1; |
|
+ arg->state = state; |
|
+ } |
|
+ } |
|
+ return !arg->stop; |
|
+} |
|
+ |
|
+static void |
|
+pkey_blocking_gen_stop(void *ptr) |
|
+{ |
|
+ struct pkey_blocking_generate_arg *arg = ptr; |
|
+ arg->stop = 1; |
|
+} |
|
+ |
|
+static void * |
|
+pkey_blocking_gen(void *ptr) |
|
+{ |
|
+ struct pkey_blocking_generate_arg *arg = ptr; |
|
+ |
|
+ if (arg->genparam && EVP_PKEY_paramgen(arg->ctx, &arg->pkey) <= 0) |
|
+ return NULL; |
|
+ if (!arg->genparam && EVP_PKEY_keygen(arg->ctx, &arg->pkey) <= 0) |
|
+ return NULL; |
|
+ return arg->pkey; |
|
+} |
|
+ |
|
+static VALUE |
|
+pkey_generate(int argc, VALUE *argv, VALUE self, int genparam) |
|
+{ |
|
+ EVP_PKEY_CTX *ctx; |
|
+ VALUE alg, options; |
|
+ struct pkey_blocking_generate_arg gen_arg = { 0 }; |
|
+ int state; |
|
+ |
|
+ rb_scan_args(argc, argv, "11", &alg, &options); |
|
+ if (rb_obj_is_kind_of(alg, cPKey)) { |
|
+ EVP_PKEY *base_pkey; |
|
+ |
|
+ GetPKey(alg, base_pkey); |
|
+ ctx = EVP_PKEY_CTX_new(base_pkey, NULL/* engine */); |
|
+ if (!ctx) |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); |
|
+ } |
|
+ else { |
|
+ const EVP_PKEY_ASN1_METHOD *ameth; |
|
+ ENGINE *tmpeng; |
|
+ int pkey_id; |
|
+ |
|
+ StringValue(alg); |
|
+ ameth = EVP_PKEY_asn1_find_str(&tmpeng, RSTRING_PTR(alg), |
|
+ RSTRING_LENINT(alg)); |
|
+ if (!ameth) |
|
+ ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", alg); |
|
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); |
|
+#if !defined(OPENSSL_NO_ENGINE) |
|
+ if (tmpeng) |
|
+ ENGINE_finish(tmpeng); |
|
+#endif |
|
+ |
|
+ ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL/* engine */); |
|
+ if (!ctx) |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_id"); |
|
+ } |
|
+ |
|
+ if (genparam && EVP_PKEY_paramgen_init(ctx) <= 0) { |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_paramgen_init"); |
|
+ } |
|
+ if (!genparam && EVP_PKEY_keygen_init(ctx) <= 0) { |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_keygen_init"); |
|
+ } |
|
+ |
|
+ if (!NIL_P(options)) { |
|
+ VALUE args[2]; |
|
+ |
|
+ args[0] = (VALUE)ctx; |
|
+ args[1] = options; |
|
+ rb_protect(pkey_gen_apply_options0, (VALUE)args, &state); |
|
+ if (state) { |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ rb_jump_tag(state); |
|
+ } |
|
+ } |
|
+ |
|
+ gen_arg.genparam = genparam; |
|
+ gen_arg.ctx = ctx; |
|
+ gen_arg.yield = rb_block_given_p(); |
|
+ EVP_PKEY_CTX_set_app_data(ctx, &gen_arg); |
|
+ EVP_PKEY_CTX_set_cb(ctx, pkey_gen_cb); |
|
+ if (gen_arg.yield) |
|
+ pkey_blocking_gen(&gen_arg); |
|
+ else |
|
+ rb_thread_call_without_gvl(pkey_blocking_gen, &gen_arg, |
|
+ pkey_blocking_gen_stop, &gen_arg); |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ if (!gen_arg.pkey) { |
|
+ if (gen_arg.state) { |
|
+ ossl_clear_error(); |
|
+ rb_jump_tag(gen_arg.state); |
|
+ } |
|
+ else { |
|
+ ossl_raise(ePKeyError, genparam ? "EVP_PKEY_paramgen" : "EVP_PKEY_keygen"); |
|
+ } |
|
+ } |
|
+ |
|
+ return ossl_pkey_new(gen_arg.pkey); |
|
+} |
|
+ |
|
+/* |
|
+ * call-seq: |
|
+ * OpenSSL::PKey.generate_parameters(algo_name [, options]) -> pkey |
|
+ * |
|
+ * Generates new parameters for the algorithm. _algo_name_ is a String that |
|
+ * represents the algorithm. The optional argument _options_ is a Hash that |
|
+ * specifies the options specific to the algorithm. The order of the options |
|
+ * can be important. |
|
+ * |
|
+ * A block can be passed optionally. The meaning of the arguments passed to |
|
+ * the block varies depending on the implementation of the algorithm. The block |
|
+ * may be called once or multiple times, or may not even be called. |
|
+ * |
|
+ * For the supported options, see the documentation for the 'openssl genpkey' |
|
+ * utility command. |
|
+ * |
|
+ * == Example |
|
+ * pkey = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048) |
|
+ * p pkey.p.num_bits #=> 2048 |
|
+ */ |
|
+static VALUE |
|
+ossl_pkey_s_generate_parameters(int argc, VALUE *argv, VALUE self) |
|
+{ |
|
+ return pkey_generate(argc, argv, self, 1); |
|
+} |
|
+ |
|
+/* |
|
+ * call-seq: |
|
+ * OpenSSL::PKey.generate_key(algo_name [, options]) -> pkey |
|
+ * OpenSSL::PKey.generate_key(pkey [, options]) -> pkey |
|
+ * |
|
+ * Generates a new key (pair). |
|
+ * |
|
+ * If a String is given as the first argument, it generates a new random key |
|
+ * for the algorithm specified by the name just as ::generate_parameters does. |
|
+ * If an OpenSSL::PKey::PKey is given instead, it generates a new random key |
|
+ * for the same algorithm as the key, using the parameters the key contains. |
|
+ * |
|
+ * See ::generate_parameters for the details of _options_ and the given block. |
|
+ * |
|
+ * == Example |
|
+ * pkey_params = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048) |
|
+ * pkey_params.priv_key #=> nil |
|
+ * pkey = OpenSSL::PKey.generate_key(pkey_params) |
|
+ * pkey.priv_key #=> #<OpenSSL::BN 6277... |
|
+ */ |
|
+static VALUE |
|
+ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self) |
|
+{ |
|
+ return pkey_generate(argc, argv, self, 0); |
|
+} |
|
+ |
|
void |
|
ossl_pkey_check_public_key(const EVP_PKEY *pkey) |
|
{ |
|
@@ -707,6 +927,8 @@ Init_ossl_pkey(void) |
|
cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject); |
|
|
|
rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1); |
|
+ rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1); |
|
+ rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1); |
|
|
|
rb_define_alloc_func(cPKey, ossl_pkey_alloc); |
|
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0); |
|
diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb |
|
index 0bdc9795cc..a325a1ea2b 100644 |
|
--- a/test/openssl/test_pkey.rb |
|
+++ b/test/openssl/test_pkey.rb |
|
@@ -25,4 +25,47 @@ def test_generic_oid_inspect |
|
assert_equal "X25519", x25519.oid |
|
assert_match %r{oid=X25519}, x25519.inspect |
|
end |
|
+ |
|
+ def test_s_generate_parameters |
|
+ # 512 is non-default; 1024 is used if 'dsa_paramgen_bits' is not specified |
|
+ # with OpenSSL 1.1.0. |
|
+ pkey = OpenSSL::PKey.generate_parameters("DSA", { |
|
+ "dsa_paramgen_bits" => 512, |
|
+ "dsa_paramgen_q_bits" => 256, |
|
+ }) |
|
+ assert_instance_of OpenSSL::PKey::DSA, pkey |
|
+ assert_equal 512, pkey.p.num_bits |
|
+ assert_equal 256, pkey.q.num_bits |
|
+ assert_equal nil, pkey.priv_key |
|
+ |
|
+ # Invalid options are checked |
|
+ assert_raise(OpenSSL::PKey::PKeyError) { |
|
+ OpenSSL::PKey.generate_parameters("DSA", "invalid" => "option") |
|
+ } |
|
+ |
|
+ # Parameter generation callback is called |
|
+ cb_called = [] |
|
+ assert_raise(RuntimeError) { |
|
+ OpenSSL::PKey.generate_parameters("DSA") { |*args| |
|
+ cb_called << args |
|
+ raise "exit!" if cb_called.size == 3 |
|
+ } |
|
+ } |
|
+ assert_not_empty cb_called |
|
+ end |
|
+ |
|
+ def test_s_generate_key |
|
+ assert_raise(OpenSSL::PKey::PKeyError) { |
|
+ # DSA key pair cannot be generated without parameters |
|
+ OpenSSL::PKey.generate_key("DSA") |
|
+ } |
|
+ pkey_params = OpenSSL::PKey.generate_parameters("DSA", { |
|
+ "dsa_paramgen_bits" => 512, |
|
+ "dsa_paramgen_q_bits" => 256, |
|
+ }) |
|
+ pkey = OpenSSL::PKey.generate_key(pkey_params) |
|
+ assert_instance_of OpenSSL::PKey::DSA, pkey |
|
+ assert_equal 512, pkey.p.num_bits |
|
+ assert_not_equal nil, pkey.priv_key |
|
+ end |
|
end |
|
-- |
|
2.32.0 |
|
|
|
|
|
From 5713605e70c96e3215aab0e0341548af29b5088e Mon Sep 17 00:00:00 2001 |
|
From: Kazuki Yamaguchi <k@rhe.jp> |
|
Date: Mon, 15 May 2017 23:47:47 +0900 |
|
Subject: [PATCH 3/6] pkey: port PKey::PKey#sign and #verify to the EVP_Digest* |
|
interface |
|
|
|
Use EVP_DigestSign*() and EVP_DigestVerify*() interface instead of the |
|
old EVP_Sign*() and EVP_Verify*() functions. They were added in OpenSSL |
|
1.0.0. |
|
|
|
Also, allow the digest to be specified as nil, as certain EVP_PKEY types |
|
don't expect a digest algorithm. |
|
--- |
|
ext/openssl/ossl_pkey.c | 90 ++++++++++++++++++++++----------------- |
|
test/openssl/test_pkey.rb | 12 ++++++ |
|
2 files changed, 63 insertions(+), 39 deletions(-) |
|
|
|
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c |
|
index 1f3dd39b9b..a0d73f5821 100644 |
|
--- a/ext/openssl/ossl_pkey.c |
|
+++ b/ext/openssl/ossl_pkey.c |
|
@@ -753,35 +753,47 @@ static VALUE |
|
ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) |
|
{ |
|
EVP_PKEY *pkey; |
|
- const EVP_MD *md; |
|
+ const EVP_MD *md = NULL; |
|
EVP_MD_CTX *ctx; |
|
- unsigned int buf_len; |
|
- VALUE str; |
|
- int result; |
|
+ size_t siglen; |
|
+ int state; |
|
+ VALUE sig; |
|
|
|
pkey = GetPrivPKeyPtr(self); |
|
- md = ossl_evp_get_digestbyname(digest); |
|
+ if (!NIL_P(digest)) |
|
+ md = ossl_evp_get_digestbyname(digest); |
|
StringValue(data); |
|
- str = rb_str_new(0, EVP_PKEY_size(pkey)); |
|
|
|
ctx = EVP_MD_CTX_new(); |
|
if (!ctx) |
|
- ossl_raise(ePKeyError, "EVP_MD_CTX_new"); |
|
- if (!EVP_SignInit_ex(ctx, md, NULL)) { |
|
- EVP_MD_CTX_free(ctx); |
|
- ossl_raise(ePKeyError, "EVP_SignInit_ex"); |
|
+ ossl_raise(ePKeyError, "EVP_MD_CTX_new"); |
|
+ if (EVP_DigestSignInit(ctx, NULL, md, /* engine */NULL, pkey) < 1) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_DigestSignInit"); |
|
+ } |
|
+ if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_DigestSignUpdate"); |
|
+ } |
|
+ if (EVP_DigestSignFinal(ctx, NULL, &siglen) < 1) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_DigestSignFinal"); |
|
} |
|
- if (!EVP_SignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) { |
|
- EVP_MD_CTX_free(ctx); |
|
- ossl_raise(ePKeyError, "EVP_SignUpdate"); |
|
+ if (siglen > LONG_MAX) |
|
+ rb_raise(ePKeyError, "signature would be too large"); |
|
+ sig = ossl_str_new(NULL, (long)siglen, &state); |
|
+ if (state) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ rb_jump_tag(state); |
|
+ } |
|
+ if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(sig), |
|
+ &siglen) < 1) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_DigestSignFinal"); |
|
} |
|
- result = EVP_SignFinal(ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey); |
|
EVP_MD_CTX_free(ctx); |
|
- if (!result) |
|
- ossl_raise(ePKeyError, "EVP_SignFinal"); |
|
- rb_str_set_len(str, buf_len); |
|
- |
|
- return str; |
|
+ rb_str_set_len(sig, siglen); |
|
+ return sig; |
|
} |
|
|
|
/* |
|
@@ -809,38 +821,38 @@ static VALUE |
|
ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data) |
|
{ |
|
EVP_PKEY *pkey; |
|
- const EVP_MD *md; |
|
+ const EVP_MD *md = NULL; |
|
EVP_MD_CTX *ctx; |
|
- int siglen, result; |
|
+ int ret; |
|
|
|
GetPKey(self, pkey); |
|
ossl_pkey_check_public_key(pkey); |
|
- md = ossl_evp_get_digestbyname(digest); |
|
+ if (!NIL_P(digest)) |
|
+ md = ossl_evp_get_digestbyname(digest); |
|
StringValue(sig); |
|
- siglen = RSTRING_LENINT(sig); |
|
StringValue(data); |
|
|
|
ctx = EVP_MD_CTX_new(); |
|
if (!ctx) |
|
- ossl_raise(ePKeyError, "EVP_MD_CTX_new"); |
|
- if (!EVP_VerifyInit_ex(ctx, md, NULL)) { |
|
- EVP_MD_CTX_free(ctx); |
|
- ossl_raise(ePKeyError, "EVP_VerifyInit_ex"); |
|
+ ossl_raise(ePKeyError, "EVP_MD_CTX_new"); |
|
+ if (EVP_DigestVerifyInit(ctx, NULL, md, /* engine */NULL, pkey) < 1) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_DigestVerifyInit"); |
|
} |
|
- if (!EVP_VerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) { |
|
- EVP_MD_CTX_free(ctx); |
|
- ossl_raise(ePKeyError, "EVP_VerifyUpdate"); |
|
+ if (EVP_DigestVerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_DigestVerifyUpdate"); |
|
} |
|
- result = EVP_VerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), siglen, pkey); |
|
+ ret = EVP_DigestVerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), |
|
+ RSTRING_LEN(sig)); |
|
EVP_MD_CTX_free(ctx); |
|
- switch (result) { |
|
- case 0: |
|
- ossl_clear_error(); |
|
- return Qfalse; |
|
- case 1: |
|
- return Qtrue; |
|
- default: |
|
- ossl_raise(ePKeyError, "EVP_VerifyFinal"); |
|
+ if (ret < 0) |
|
+ ossl_raise(ePKeyError, "EVP_DigestVerifyFinal"); |
|
+ if (ret) |
|
+ return Qtrue; |
|
+ else { |
|
+ ossl_clear_error(); |
|
+ return Qfalse; |
|
} |
|
} |
|
|
|
diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb |
|
index a325a1ea2b..247ba84f83 100644 |
|
--- a/test/openssl/test_pkey.rb |
|
+++ b/test/openssl/test_pkey.rb |
|
@@ -68,4 +68,16 @@ def test_s_generate_key |
|
assert_equal 512, pkey.p.num_bits |
|
assert_not_equal nil, pkey.priv_key |
|
end |
|
+ |
|
+ def test_hmac_sign_verify |
|
+ pkey = OpenSSL::PKey.generate_key("HMAC", { "key" => "abcd" }) |
|
+ |
|
+ hmac = OpenSSL::HMAC.new("abcd", "SHA256").update("data").digest |
|
+ assert_equal hmac, pkey.sign("SHA256", "data") |
|
+ |
|
+ # EVP_PKEY_HMAC does not support verify |
|
+ assert_raise(OpenSSL::PKey::PKeyError) { |
|
+ pkey.verify("SHA256", "data", hmac) |
|
+ } |
|
+ end |
|
end |
|
-- |
|
2.32.0 |
|
|
|
|
|
From 76566a2e1bab42a2e1587ecbec23779ee00020fc Mon Sep 17 00:00:00 2001 |
|
From: Kazuki Yamaguchi <k@rhe.jp> |
|
Date: Mon, 15 May 2017 23:47:47 +0900 |
|
Subject: [PATCH 4/6] pkey: support 'one-shot' signing and verification |
|
|
|
OpenSSL 1.1.1 added EVP_DigestSign() and EVP_DigestVerify() functions |
|
to the interface. Some EVP_PKEY methods such as PureEdDSA algorithms |
|
do not support the streaming mechanism and require us to use them. |
|
--- |
|
ext/openssl/ossl_pkey.c | 30 ++++++++++++++++++++++++++ |
|
test/openssl/test_pkey.rb | 45 +++++++++++++++++++++++++++++++++++++++ |
|
2 files changed, 75 insertions(+) |
|
|
|
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c |
|
index a0d73f5821..19544ec7f0 100644 |
|
--- a/ext/openssl/ossl_pkey.c |
|
+++ b/ext/openssl/ossl_pkey.c |
|
@@ -771,6 +771,26 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) |
|
EVP_MD_CTX_free(ctx); |
|
ossl_raise(ePKeyError, "EVP_DigestSignInit"); |
|
} |
|
+#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER) |
|
+ if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data), |
|
+ RSTRING_LEN(data)) < 1) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_DigestSign"); |
|
+ } |
|
+ if (siglen > LONG_MAX) |
|
+ rb_raise(ePKeyError, "signature would be too large"); |
|
+ sig = ossl_str_new(NULL, (long)siglen, &state); |
|
+ if (state) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ rb_jump_tag(state); |
|
+ } |
|
+ if (EVP_DigestSign(ctx, (unsigned char *)RSTRING_PTR(sig), &siglen, |
|
+ (unsigned char *)RSTRING_PTR(data), |
|
+ RSTRING_LEN(data)) < 1) { |
|
+ EVP_MD_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_DigestSign"); |
|
+ } |
|
+#else |
|
if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) { |
|
EVP_MD_CTX_free(ctx); |
|
ossl_raise(ePKeyError, "EVP_DigestSignUpdate"); |
|
@@ -791,6 +811,7 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) |
|
EVP_MD_CTX_free(ctx); |
|
ossl_raise(ePKeyError, "EVP_DigestSignFinal"); |
|
} |
|
+#endif |
|
EVP_MD_CTX_free(ctx); |
|
rb_str_set_len(sig, siglen); |
|
return sig; |
|
@@ -839,6 +860,14 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data) |
|
EVP_MD_CTX_free(ctx); |
|
ossl_raise(ePKeyError, "EVP_DigestVerifyInit"); |
|
} |
|
+#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER) |
|
+ ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig), |
|
+ RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data), |
|
+ RSTRING_LEN(data)); |
|
+ EVP_MD_CTX_free(ctx); |
|
+ if (ret < 0) |
|
+ ossl_raise(ePKeyError, "EVP_DigestVerify"); |
|
+#else |
|
if (EVP_DigestVerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) { |
|
EVP_MD_CTX_free(ctx); |
|
ossl_raise(ePKeyError, "EVP_DigestVerifyUpdate"); |
|
@@ -848,6 +877,7 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data) |
|
EVP_MD_CTX_free(ctx); |
|
if (ret < 0) |
|
ossl_raise(ePKeyError, "EVP_DigestVerifyFinal"); |
|
+#endif |
|
if (ret) |
|
return Qtrue; |
|
else { |
|
diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb |
|
index 247ba84f83..d811b9c75f 100644 |
|
--- a/test/openssl/test_pkey.rb |
|
+++ b/test/openssl/test_pkey.rb |
|
@@ -80,4 +80,49 @@ def test_hmac_sign_verify |
|
pkey.verify("SHA256", "data", hmac) |
|
} |
|
end |
|
+ |
|
+ def test_ed25519 |
|
+ # Test vector from RFC 8032 Section 7.1 TEST 2 |
|
+ priv_pem = <<~EOF |
|
+ -----BEGIN PRIVATE KEY----- |
|
+ MC4CAQAwBQYDK2VwBCIEIEzNCJso/5banbbDRuwRTg9bijGfNaumJNqM9u1PuKb7 |
|
+ -----END PRIVATE KEY----- |
|
+ EOF |
|
+ pub_pem = <<~EOF |
|
+ -----BEGIN PUBLIC KEY----- |
|
+ MCowBQYDK2VwAyEAPUAXw+hDiVqStwqnTRt+vJyYLM8uxJaMwM1V8Sr0Zgw= |
|
+ -----END PUBLIC KEY----- |
|
+ EOF |
|
+ begin |
|
+ priv = OpenSSL::PKey.read(priv_pem) |
|
+ pub = OpenSSL::PKey.read(pub_pem) |
|
+ rescue OpenSSL::PKey::PKeyError |
|
+ # OpenSSL < 1.1.1 |
|
+ pend "Ed25519 is not implemented" |
|
+ end |
|
+ assert_instance_of OpenSSL::PKey::PKey, priv |
|
+ assert_instance_of OpenSSL::PKey::PKey, pub |
|
+ assert_equal priv_pem, priv.private_to_pem |
|
+ assert_equal pub_pem, priv.public_to_pem |
|
+ assert_equal pub_pem, pub.public_to_pem |
|
+ |
|
+ sig = [<<~EOF.gsub(/[^0-9a-f]/, "")].pack("H*") |
|
+ 92a009a9f0d4cab8720e820b5f642540 |
|
+ a2b27b5416503f8fb3762223ebdb69da |
|
+ 085ac1e43e15996e458f3613d0f11d8c |
|
+ 387b2eaeb4302aeeb00d291612bb0c00 |
|
+ EOF |
|
+ data = ["72"].pack("H*") |
|
+ assert_equal sig, priv.sign(nil, data) |
|
+ assert_equal true, priv.verify(nil, sig, data) |
|
+ assert_equal true, pub.verify(nil, sig, data) |
|
+ assert_equal false, pub.verify(nil, sig, data.succ) |
|
+ |
|
+ # PureEdDSA wants nil as the message digest |
|
+ assert_raise(OpenSSL::PKey::PKeyError) { priv.sign("SHA512", data) } |
|
+ assert_raise(OpenSSL::PKey::PKeyError) { pub.verify("SHA512", sig, data) } |
|
+ |
|
+ # Ed25519 pkey type does not support key derivation |
|
+ assert_raise(OpenSSL::PKey::PKeyError) { priv.derive(pub) } |
|
+ end |
|
end |
|
-- |
|
2.32.0 |
|
|
|
|
|
From fabdd22bddc572ba3342ec0b09e3fef8ed6245b8 Mon Sep 17 00:00:00 2001 |
|
From: Kazuki Yamaguchi <k@rhe.jp> |
|
Date: Sat, 18 Mar 2017 21:58:46 +0900 |
|
Subject: [PATCH 5/6] pkey: add PKey::PKey#derive |
|
|
|
Add OpenSSL::PKey::PKey#derive as the wrapper for EVP_PKEY_CTX_derive(). |
|
This is useful for pkey types that we don't have dedicated classes, such |
|
as X25519. |
|
--- |
|
ext/openssl/ossl_pkey.c | 52 ++++++++++++++++++++++++++++++++++++ |
|
test/openssl/test_pkey.rb | 26 ++++++++++++++++++ |
|
test/openssl/test_pkey_dh.rb | 13 +++++++++ |
|
test/openssl/test_pkey_ec.rb | 16 +++++++++++ |
|
4 files changed, 107 insertions(+) |
|
|
|
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c |
|
index 19544ec7f0..df8b425a0f 100644 |
|
--- a/ext/openssl/ossl_pkey.c |
|
+++ b/ext/openssl/ossl_pkey.c |
|
@@ -886,6 +886,57 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data) |
|
} |
|
} |
|
|
|
+/* |
|
+ * call-seq: |
|
+ * pkey.derive(peer_pkey) -> string |
|
+ * |
|
+ * Derives a shared secret from _pkey_ and _peer_pkey_. _pkey_ must contain |
|
+ * the private components, _peer_pkey_ must contain the public components. |
|
+ */ |
|
+static VALUE |
|
+ossl_pkey_derive(int argc, VALUE *argv, VALUE self) |
|
+{ |
|
+ EVP_PKEY *pkey, *peer_pkey; |
|
+ EVP_PKEY_CTX *ctx; |
|
+ VALUE peer_pkey_obj, str; |
|
+ size_t keylen; |
|
+ int state; |
|
+ |
|
+ GetPKey(self, pkey); |
|
+ rb_scan_args(argc, argv, "1", &peer_pkey_obj); |
|
+ GetPKey(peer_pkey_obj, peer_pkey); |
|
+ |
|
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); |
|
+ if (!ctx) |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); |
|
+ if (EVP_PKEY_derive_init(ctx) <= 0) { |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_derive_init"); |
|
+ } |
|
+ if (EVP_PKEY_derive_set_peer(ctx, peer_pkey) <= 0) { |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_derive_set_peer"); |
|
+ } |
|
+ if (EVP_PKEY_derive(ctx, NULL, &keylen) <= 0) { |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_derive"); |
|
+ } |
|
+ if (keylen > LONG_MAX) |
|
+ rb_raise(ePKeyError, "derived key would be too large"); |
|
+ str = ossl_str_new(NULL, (long)keylen, &state); |
|
+ if (state) { |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ rb_jump_tag(state); |
|
+ } |
|
+ if (EVP_PKEY_derive(ctx, (unsigned char *)RSTRING_PTR(str), &keylen) <= 0) { |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ ossl_raise(ePKeyError, "EVP_PKEY_derive"); |
|
+ } |
|
+ EVP_PKEY_CTX_free(ctx); |
|
+ rb_str_set_len(str, keylen); |
|
+ return str; |
|
+} |
|
+ |
|
/* |
|
* INIT |
|
*/ |
|
@@ -983,6 +1034,7 @@ Init_ossl_pkey(void) |
|
|
|
rb_define_method(cPKey, "sign", ossl_pkey_sign, 2); |
|
rb_define_method(cPKey, "verify", ossl_pkey_verify, 3); |
|
+ rb_define_method(cPKey, "derive", ossl_pkey_derive, -1); |
|
|
|
id_private_q = rb_intern("private?"); |
|
|
|
diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb |
|
index d811b9c75f..5307fe5b08 100644 |
|
--- a/test/openssl/test_pkey.rb |
|
+++ b/test/openssl/test_pkey.rb |
|
@@ -125,4 +125,30 @@ def test_ed25519 |
|
# Ed25519 pkey type does not support key derivation |
|
assert_raise(OpenSSL::PKey::PKeyError) { priv.derive(pub) } |
|
end |
|
+ |
|
+ def test_x25519 |
|
+ # Test vector from RFC 7748 Section 6.1 |
|
+ alice_pem = <<~EOF |
|
+ -----BEGIN PRIVATE KEY----- |
|
+ MC4CAQAwBQYDK2VuBCIEIHcHbQpzGKV9PBbBclGyZkXfTC+H68CZKrF3+6UduSwq |
|
+ -----END PRIVATE KEY----- |
|
+ EOF |
|
+ bob_pem = <<~EOF |
|
+ -----BEGIN PUBLIC KEY----- |
|
+ MCowBQYDK2VuAyEA3p7bfXt9wbTTW2HC7OQ1Nz+DQ8hbeGdNrfx+FG+IK08= |
|
+ -----END PUBLIC KEY----- |
|
+ EOF |
|
+ shared_secret = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" |
|
+ begin |
|
+ alice = OpenSSL::PKey.read(alice_pem) |
|
+ bob = OpenSSL::PKey.read(bob_pem) |
|
+ rescue OpenSSL::PKey::PKeyError |
|
+ # OpenSSL < 1.1.0 |
|
+ pend "X25519 is not implemented" |
|
+ end |
|
+ assert_instance_of OpenSSL::PKey::PKey, alice |
|
+ assert_equal alice_pem, alice.private_to_pem |
|
+ assert_equal bob_pem, bob.public_to_pem |
|
+ assert_equal [shared_secret].pack("H*"), alice.derive(bob) |
|
+ end |
|
end |
|
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb |
|
index 4a05626a12..9efc3ba68d 100644 |
|
--- a/test/openssl/test_pkey_dh.rb |
|
+++ b/test/openssl/test_pkey_dh.rb |
|
@@ -18,6 +18,19 @@ def test_new_break |
|
end |
|
end |
|
|
|
+ def test_derive_key |
|
+ dh1 = Fixtures.pkey("dh1024").generate_key! |
|
+ dh2 = Fixtures.pkey("dh1024").generate_key! |
|
+ dh1_pub = OpenSSL::PKey.read(dh1.public_to_der) |
|
+ dh2_pub = OpenSSL::PKey.read(dh2.public_to_der) |
|
+ z = dh1.g.mod_exp(dh1.priv_key, dh1.p).mod_exp(dh2.priv_key, dh1.p).to_s(2) |
|
+ assert_equal z, dh1.derive(dh2_pub) |
|
+ assert_equal z, dh2.derive(dh1_pub) |
|
+ |
|
+ assert_equal z, dh1.compute_key(dh2.pub_key) |
|
+ assert_equal z, dh2.compute_key(dh1.pub_key) |
|
+ end |
|
+ |
|
def test_DHparams |
|
dh1024 = Fixtures.pkey("dh1024") |
|
asn1 = OpenSSL::ASN1::Sequence([ |
|
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb |
|
index a0e6a23ff8..95d4338a51 100644 |
|
--- a/test/openssl/test_pkey_ec.rb |
|
+++ b/test/openssl/test_pkey_ec.rb |
|
@@ -93,6 +93,22 @@ def test_sign_verify |
|
assert_equal false, p256.verify("SHA256", signature1, data) |
|
end |
|
|
|
+ def test_derive_key |
|
+ # NIST CAVP, KAS_ECC_CDH_PrimitiveTest.txt, P-256 COUNT = 0 |
|
+ qCAVSx = "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287" |
|
+ qCAVSy = "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac" |
|
+ dIUT = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534" |
|
+ zIUT = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b" |
|
+ a = OpenSSL::PKey::EC.new("prime256v1") |
|
+ a.private_key = OpenSSL::BN.new(dIUT, 16) |
|
+ b = OpenSSL::PKey::EC.new("prime256v1") |
|
+ uncompressed = OpenSSL::BN.new("04" + qCAVSx + qCAVSy, 16) |
|
+ b.public_key = OpenSSL::PKey::EC::Point.new(b.group, uncompressed) |
|
+ assert_equal [zIUT].pack("H*"), a.derive(b) |
|
+ |
|
+ assert_equal a.derive(b), a.dh_compute_key(b.public_key) |
|
+ end |
|
+ |
|
def test_dsa_sign_verify |
|
data1 = "foo" |
|
data2 = "bar" |
|
-- |
|
2.32.0 |
|
|
|
|
|
From 97078c7fa8a724c7c71f9850d31fc401239da228 Mon Sep 17 00:00:00 2001 |
|
From: Kazuki Yamaguchi <k@rhe.jp> |
|
Date: Sat, 18 Mar 2017 22:34:19 +0900 |
|
Subject: [PATCH 6/6] pkey: reimplement PKey::DH#compute_key and |
|
PKey::EC#dh_compute_key |
|
|
|
Use the new OpenSSL::PKey::PKey#derive instead of the raw |
|
{EC,}DH_compute_key(), mainly to reduce amount of the C code. |
|
--- |
|
ext/openssl/lib/openssl/pkey.rb | 33 +++++++++++++++++++++++++++++++ |
|
ext/openssl/ossl_pkey_dh.c | 35 --------------------------------- |
|
ext/openssl/ossl_pkey_ec.c | 32 ------------------------------ |
|
3 files changed, 33 insertions(+), 67 deletions(-) |
|
|
|
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb |
|
index 9cc3276356..be60ac2beb 100644 |
|
--- a/ext/openssl/lib/openssl/pkey.rb |
|
+++ b/ext/openssl/lib/openssl/pkey.rb |
|
@@ -9,6 +9,24 @@ |
|
module OpenSSL::PKey |
|
class DH |
|
include OpenSSL::Marshal |
|
+ |
|
+ # :call-seq: |
|
+ # dh.compute_key(pub_bn) -> string |
|
+ # |
|
+ # Returns a String containing a shared secret computed from the other |
|
+ # party's public value. |
|
+ # |
|
+ # This method is provided for backwards compatibility, and calls #derive |
|
+ # internally. |
|
+ # |
|
+ # === Parameters |
|
+ # * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by |
|
+ # DH#public_key as that contains the DH parameters only. |
|
+ def compute_key(pub_bn) |
|
+ peer = dup |
|
+ peer.set_key(pub_bn, nil) |
|
+ derive(peer) |
|
+ end |
|
end |
|
|
|
class DSA |
|
@@ -18,7 +36,22 @@ class DSA |
|
if defined?(EC) |
|
class EC |
|
include OpenSSL::Marshal |
|
+ |
|
+ # :call-seq: |
|
+ # ec.dh_compute_key(pubkey) -> string |
|
+ # |
|
+ # Derives a shared secret by ECDH. _pubkey_ must be an instance of |
|
+ # OpenSSL::PKey::EC::Point and must belong to the same group. |
|
+ # |
|
+ # This method is provided for backwards compatibility, and calls #derive |
|
+ # internally. |
|
+ def dh_compute_key(pubkey) |
|
+ peer = OpenSSL::PKey::EC.new(group) |
|
+ peer.public_key = pubkey |
|
+ derive(peer) |
|
+ end |
|
end |
|
+ |
|
class EC::Point |
|
# :call-seq: |
|
# point.to_bn([conversion_form]) -> OpenSSL::BN |
|
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c |
|
index bc50e5566b..5bc1c49ca1 100644 |
|
--- a/ext/openssl/ossl_pkey_dh.c |
|
+++ b/ext/openssl/ossl_pkey_dh.c |
|
@@ -476,40 +476,6 @@ ossl_dh_generate_key(VALUE self) |
|
return self; |
|
} |
|
|
|
-/* |
|
- * call-seq: |
|
- * dh.compute_key(pub_bn) -> aString |
|
- * |
|
- * Returns a String containing a shared secret computed from the other party's public value. |
|
- * See DH_compute_key() for further information. |
|
- * |
|
- * === Parameters |
|
- * * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by |
|
- * DH#public_key as that contains the DH parameters only. |
|
- */ |
|
-static VALUE |
|
-ossl_dh_compute_key(VALUE self, VALUE pub) |
|
-{ |
|
- DH *dh; |
|
- const BIGNUM *pub_key, *dh_p; |
|
- VALUE str; |
|
- int len; |
|
- |
|
- GetDH(self, dh); |
|
- DH_get0_pqg(dh, &dh_p, NULL, NULL); |
|
- if (!dh_p) |
|
- ossl_raise(eDHError, "incomplete DH"); |
|
- pub_key = GetBNPtr(pub); |
|
- len = DH_size(dh); |
|
- str = rb_str_new(0, len); |
|
- if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) { |
|
- ossl_raise(eDHError, NULL); |
|
- } |
|
- rb_str_set_len(str, len); |
|
- |
|
- return str; |
|
-} |
|
- |
|
/* |
|
* Document-method: OpenSSL::PKey::DH#set_pqg |
|
* call-seq: |
|
@@ -587,7 +553,6 @@ Init_ossl_dh(void) |
|
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); |
|
- rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1); |
|
|
|
DEF_OSSL_PKEY_BN(cDH, dh, p); |
|
DEF_OSSL_PKEY_BN(cDH, dh, q); |
|
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c |
|
index 6fe2533e2a..c2534251c3 100644 |
|
--- a/ext/openssl/ossl_pkey_ec.c |
|
+++ b/ext/openssl/ossl_pkey_ec.c |
|
@@ -487,37 +487,6 @@ static VALUE ossl_ec_key_check_key(VALUE self) |
|
return Qtrue; |
|
} |
|
|
|
-/* |
|
- * call-seq: |
|
- * key.dh_compute_key(pubkey) => String |
|
- * |
|
- * See the OpenSSL documentation for ECDH_compute_key() |
|
- */ |
|
-static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey) |
|
-{ |
|
- EC_KEY *ec; |
|
- EC_POINT *point; |
|
- int buf_len; |
|
- VALUE str; |
|
- |
|
- GetEC(self, ec); |
|
- GetECPoint(pubkey, point); |
|
- |
|
-/* BUG: need a way to figure out the maximum string size */ |
|
- buf_len = 1024; |
|
- str = rb_str_new(0, buf_len); |
|
-/* BUG: take KDF as a block */ |
|
- buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL); |
|
- if (buf_len < 0) |
|
- ossl_raise(eECError, "ECDH_compute_key"); |
|
- |
|
- rb_str_resize(str, buf_len); |
|
- |
|
- return str; |
|
-} |
|
- |
|
-/* sign_setup */ |
|
- |
|
/* |
|
* call-seq: |
|
* key.dsa_sign_asn1(data) => String |
|
@@ -1657,7 +1626,6 @@ void Init_ossl_ec(void) |
|
rb_define_alias(cEC, "generate_key", "generate_key!"); |
|
rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0); |
|
|
|
- rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1); |
|
rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1); |
|
rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2); |
|
/* do_sign/do_verify */ |
|
-- |
|
2.32.0 |
|
|
|
|