Skip to content

Commit 5c7e3c2

Browse files
rheniummatzbot
authored andcommitted
[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. ruby/openssl@2a24966414
1 parent ad82b72 commit 5c7e3c2

1 file changed

Lines changed: 42 additions & 9 deletions

File tree

ext/openssl/ossl_kdf.c

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,27 @@
77

88
static VALUE mKDF, eKDF;
99

10+
struct pbkdf2_hmac_args {
11+
char *pass;
12+
int passlen;
13+
unsigned char *salt;
14+
int saltlen;
15+
int iters;
16+
const EVP_MD *md;
17+
int len;
18+
unsigned char *out;
19+
};
20+
21+
static void *
22+
pbkdf2_hmac_nogvl(void *args_)
23+
{
24+
struct pbkdf2_hmac_args *args = (struct pbkdf2_hmac_args *)args_;
25+
int ret = PKCS5_PBKDF2_HMAC(args->pass, args->passlen, args->salt,
26+
args->saltlen, args->iters, args->md,
27+
args->len, args->out);
28+
return (void *)(uintptr_t)ret;
29+
}
30+
1031
/*
1132
* call-seq:
1233
* KDF.pbkdf2_hmac(pass, salt:, iterations:, length:, hash:) -> aString
@@ -35,9 +56,9 @@ static VALUE mKDF, eKDF;
3556
static VALUE
3657
kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
3758
{
38-
VALUE pass, salt, opts, kwargs[4], str, md_holder;
59+
VALUE pass, salt, opts, kwargs[4], str, md_holder, pass_tmp, salt_tmp;
3960
static ID kwargs_ids[4];
40-
int iters, len;
61+
int passlen, saltlen, iters, len;
4162
const EVP_MD *md;
4263

4364
if (!kwargs_ids[0]) {
@@ -54,14 +75,26 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
5475
iters = NUM2INT(kwargs[1]);
5576
len = NUM2INT(kwargs[2]);
5677
md = ossl_evp_md_fetch(kwargs[3], &md_holder);
57-
58-
str = rb_str_new(0, len);
59-
if (!PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass),
60-
(unsigned char *)RSTRING_PTR(salt),
61-
RSTRING_LENINT(salt), iters, md, len,
62-
(unsigned char *)RSTRING_PTR(str)))
78+
passlen = RSTRING_LENINT(pass);
79+
saltlen = RSTRING_LENINT(salt);
80+
str = rb_str_new(NULL, len);
81+
struct pbkdf2_hmac_args args = {
82+
.pass = ALLOCV(pass_tmp, passlen),
83+
.passlen = passlen,
84+
.salt = ALLOCV(salt_tmp, saltlen),
85+
.saltlen = saltlen,
86+
.iters = iters,
87+
.md = md,
88+
.len = len,
89+
.out = (unsigned char *)RSTRING_PTR(str),
90+
};
91+
memcpy(args.pass, RSTRING_PTR(pass), passlen);
92+
memcpy(args.salt, RSTRING_PTR(salt), saltlen);
93+
if (!rb_thread_call_without_gvl(pbkdf2_hmac_nogvl, &args, NULL, NULL))
6394
ossl_raise(eKDF, "PKCS5_PBKDF2_HMAC");
64-
95+
OPENSSL_cleanse(&args.pass, passlen);
96+
ALLOCV_END(pass_tmp);
97+
ALLOCV_END(salt_tmp);
6598
return str;
6699
}
67100

0 commit comments

Comments
 (0)