diff options
author | Kazuki Yamaguchi <[email protected]> | 2017-03-18 21:58:46 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <[email protected]> | 2021-03-16 19:16:11 +0900 |
commit | fbadb01d6e0881ef6c6e5e105b8ac20fe663c817 (patch) | |
tree | 59b9014cf8bf92e142cf9a29053e2ec10e433958 /ext/openssl/ossl_pkey.c | |
parent | b2dc4880f5d000c3e0117ecf9c57a273cbd713f9 (diff) |
[ruby/openssl] 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.
https://github.com/ruby/openssl/commit/28f0059bea
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4275
Diffstat (limited to 'ext/openssl/ossl_pkey.c')
-rw-r--r-- | ext/openssl/ossl_pkey.c | 52 |
1 files changed, 52 insertions, 0 deletions
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 @@ -887,6 +887,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 */ void @@ -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?"); |