@@ -99,6 +99,32 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
9999}
100100
101101#if defined(HAVE_EVP_PBE_SCRYPT )
102+ struct scrypt_args {
103+ char * pass ;
104+ size_t passlen ;
105+ unsigned char * salt ;
106+ size_t saltlen ;
107+ uint64_t N , r , p ;
108+ size_t len ;
109+ unsigned char * out ;
110+ };
111+
112+ static void *
113+ scrypt_nogvl (void * args_ )
114+ {
115+ struct scrypt_args * args = (struct scrypt_args * )args_ ;
116+ /*
117+ * OpenSSL uses 32MB by default (if zero is specified), which is too
118+ * small. Let's not limit memory consumption but just let malloc() fail
119+ * inside OpenSSL. The amount is controllable by other parameters.
120+ */
121+ uint64_t maxmem = UINT64_MAX ;
122+ int ret = EVP_PBE_scrypt (args -> pass , args -> passlen ,
123+ args -> salt , args -> saltlen , args -> N , args -> r ,
124+ args -> p , maxmem , args -> out , args -> len );
125+ return (void * )(uintptr_t )ret ;
126+ }
127+
102128/*
103129 * call-seq:
104130 * KDF.scrypt(pass, salt:, N:, r:, p:, length:) -> aString
@@ -134,10 +160,11 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
134160static VALUE
135161kdf_scrypt (int argc , VALUE * argv , VALUE self )
136162{
137- VALUE pass , salt , opts , kwargs [5 ], str ;
163+ VALUE pass , salt , opts , kwargs [5 ], str , pass_tmp , salt_tmp ;
138164 static ID kwargs_ids [5 ];
139- size_t len ;
140- uint64_t N , r , p , maxmem ;
165+ size_t passlen , saltlen ;
166+ long len ;
167+ uint64_t N , r , p ;
141168
142169 if (!kwargs_ids [0 ]) {
143170 kwargs_ids [0 ] = rb_intern_const ("salt" );
@@ -155,19 +182,27 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
155182 r = NUM2UINT64T (kwargs [2 ]);
156183 p = NUM2UINT64T (kwargs [3 ]);
157184 len = NUM2LONG (kwargs [4 ]);
158- /*
159- * OpenSSL uses 32MB by default (if zero is specified), which is too small.
160- * Let's not limit memory consumption but just let malloc() fail inside
161- * OpenSSL. The amount is controllable by other parameters.
162- */
163- maxmem = SIZE_MAX ;
164-
165- str = rb_str_new (0 , len );
166- if (!EVP_PBE_scrypt (RSTRING_PTR (pass ), RSTRING_LEN (pass ),
167- (unsigned char * )RSTRING_PTR (salt ), RSTRING_LEN (salt ),
168- N , r , p , maxmem , (unsigned char * )RSTRING_PTR (str ), len ))
185+ passlen = RSTRING_LEN (pass );
186+ saltlen = RSTRING_LEN (salt );
187+ str = rb_str_new (NULL , len );
188+ struct scrypt_args args = {
189+ .pass = ALLOCV (pass_tmp , passlen ),
190+ .passlen = passlen ,
191+ .salt = ALLOCV (salt_tmp , saltlen ),
192+ .saltlen = saltlen ,
193+ .N = N ,
194+ .r = r ,
195+ .p = p ,
196+ .len = len ,
197+ .out = (unsigned char * )RSTRING_PTR (str ),
198+ };
199+ memcpy (args .pass , RSTRING_PTR (pass ), passlen );
200+ memcpy (args .salt , RSTRING_PTR (salt ), saltlen );
201+ if (!rb_thread_call_without_gvl (scrypt_nogvl , & args , NULL , NULL ))
169202 ossl_raise (eKDF , "EVP_PBE_scrypt" );
170-
203+ OPENSSL_cleanse (& args .pass , passlen );
204+ ALLOCV_END (pass_tmp );
205+ ALLOCV_END (salt_tmp );
171206 return str ;
172207}
173208#endif
0 commit comments