diff options
| author | Kazuki Yamaguchi <k@rhe.jp> | 2025-08-05 17:36:05 +0900 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2026-04-08 11:08:25 +0000 |
| commit | 5c7e3c202a74f7e39fa8f0d9cb66055ba7d57d43 (patch) | |
| tree | 41a67330db32357d8d33aa072da032de346786d1 | |
| parent | ad82b7274a3efd2ad76e2c73a7474f9a74539e32 (diff) | |
[ruby/openssl] kdf: release GVL in OpenSSL::KDF.pbkdf2_hmac
Since PBKDF2 runs single-threaded and is typically configured to take
several hundred milliseconds or longer, it is a perfect candidate to be
run without the GVL.
https://github.com/ruby/openssl/commit/2a24966414
| -rw-r--r-- | ext/openssl/ossl_kdf.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c index 1f28016440..7fb0540206 100644 --- a/ext/openssl/ossl_kdf.c +++ b/ext/openssl/ossl_kdf.c @@ -7,6 +7,27 @@ static VALUE mKDF, eKDF; +struct pbkdf2_hmac_args { + char *pass; + int passlen; + unsigned char *salt; + int saltlen; + int iters; + const EVP_MD *md; + int len; + unsigned char *out; +}; + +static void * +pbkdf2_hmac_nogvl(void *args_) +{ + struct pbkdf2_hmac_args *args = (struct pbkdf2_hmac_args *)args_; + int ret = PKCS5_PBKDF2_HMAC(args->pass, args->passlen, args->salt, + args->saltlen, args->iters, args->md, + args->len, args->out); + return (void *)(uintptr_t)ret; +} + /* * call-seq: * KDF.pbkdf2_hmac(pass, salt:, iterations:, length:, hash:) -> aString @@ -35,9 +56,9 @@ static VALUE mKDF, eKDF; static VALUE kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self) { - VALUE pass, salt, opts, kwargs[4], str, md_holder; + VALUE pass, salt, opts, kwargs[4], str, md_holder, pass_tmp, salt_tmp; static ID kwargs_ids[4]; - int iters, len; + int passlen, saltlen, iters, len; const EVP_MD *md; if (!kwargs_ids[0]) { @@ -54,14 +75,26 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self) iters = NUM2INT(kwargs[1]); len = NUM2INT(kwargs[2]); md = ossl_evp_md_fetch(kwargs[3], &md_holder); - - str = rb_str_new(0, len); - if (!PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass), - (unsigned char *)RSTRING_PTR(salt), - RSTRING_LENINT(salt), iters, md, len, - (unsigned char *)RSTRING_PTR(str))) + passlen = RSTRING_LENINT(pass); + saltlen = RSTRING_LENINT(salt); + str = rb_str_new(NULL, len); + struct pbkdf2_hmac_args args = { + .pass = ALLOCV(pass_tmp, passlen), + .passlen = passlen, + .salt = ALLOCV(salt_tmp, saltlen), + .saltlen = saltlen, + .iters = iters, + .md = md, + .len = len, + .out = (unsigned char *)RSTRING_PTR(str), + }; + memcpy(args.pass, RSTRING_PTR(pass), passlen); + memcpy(args.salt, RSTRING_PTR(salt), saltlen); + if (!rb_thread_call_without_gvl(pbkdf2_hmac_nogvl, &args, NULL, NULL)) ossl_raise(eKDF, "PKCS5_PBKDF2_HMAC"); - + OPENSSL_cleanse(&args.pass, passlen); + ALLOCV_END(pass_tmp); + ALLOCV_END(salt_tmp); return str; } |
