Skip to content

Commit bc030cd

Browse files
committed
kdf: release GVL in OpenSSL::KDF.pbkdf2_hmac
PBKDF2 is a password hashing function that runs single-threaded and is typically configured to take several hundred milliseconds.
1 parent 274a652 commit bc030cd

File tree

1 file changed

+42
-12
lines changed

1 file changed

+42
-12
lines changed

ext/openssl/ossl_kdf.c

Lines changed: 42 additions & 12 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 iter;
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->iter, 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,10 +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;
59+
VALUE pass, salt, opts, kwargs[4], str, pass_tmp, salt_tmp;
3960
static ID kwargs_ids[4];
40-
int iters, len;
41-
const EVP_MD *md;
61+
int passlen, saltlen, len;
4262

4363
if (!kwargs_ids[0]) {
4464
kwargs_ids[0] = rb_intern_const("salt");
@@ -50,18 +70,28 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
5070
rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs);
5171

5272
StringValue(pass);
73+
passlen = RSTRING_LENINT(pass);
5374
salt = StringValue(kwargs[0]);
54-
iters = NUM2INT(kwargs[1]);
75+
saltlen = RSTRING_LENINT(salt);
5576
len = NUM2INT(kwargs[2]);
56-
md = ossl_evp_get_digestbyname(kwargs[3]);
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)))
77+
str = rb_str_new(NULL, len);
78+
struct pbkdf2_hmac_args args = {
79+
.pass = ALLOCV(pass_tmp, passlen),
80+
.passlen = passlen,
81+
.salt = ALLOCV(salt_tmp, saltlen),
82+
.saltlen = saltlen,
83+
.iter = NUM2INT(kwargs[1]),
84+
.md = ossl_evp_get_digestbyname(kwargs[3]),
85+
.len = len,
86+
.out = (unsigned char *)RSTRING_PTR(str),
87+
};
88+
memcpy(args.pass, RSTRING_PTR(pass), passlen);
89+
memcpy(args.salt, RSTRING_PTR(salt), saltlen);
90+
if (!rb_thread_call_without_gvl(pbkdf2_hmac_nogvl, &args, NULL, NULL))
6391
ossl_raise(eKDF, "PKCS5_PBKDF2_HMAC");
64-
92+
OPENSSL_cleanse(&args.pass, passlen);
93+
ALLOCV_END(pass_tmp);
94+
ALLOCV_END(salt_tmp);
6595
return str;
6696
}
6797

0 commit comments

Comments
 (0)