@@ -96,6 +96,32 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
9696}
9797
9898#if defined(HAVE_EVP_PBE_SCRYPT )
99+ struct scrypt_args {
100+ char * pass ;
101+ size_t passlen ;
102+ unsigned char * salt ;
103+ size_t saltlen ;
104+ uint64_t N , r , p ;
105+ size_t len ;
106+ unsigned char * out ;
107+ };
108+
109+ static void *
110+ scrypt_nogvl (void * args_ )
111+ {
112+ struct scrypt_args * args = (struct scrypt_args * )args_ ;
113+ /*
114+ * OpenSSL uses 32MB by default (if zero is specified), which is too
115+ * small. Let's not limit memory consumption but just let malloc() fail
116+ * inside OpenSSL. The amount is controllable by other parameters.
117+ */
118+ uint64_t maxmem = UINT64_MAX ;
119+ int ret = EVP_PBE_scrypt (args -> pass , args -> passlen ,
120+ args -> salt , args -> saltlen , args -> N , args -> r ,
121+ args -> p , maxmem , args -> out , args -> len );
122+ return (void * )(uintptr_t )ret ;
123+ }
124+
99125/*
100126 * call-seq:
101127 * KDF.scrypt(pass, salt:, N:, r:, p:, length:) -> aString
@@ -131,10 +157,10 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
131157static VALUE
132158kdf_scrypt (int argc , VALUE * argv , VALUE self )
133159{
134- VALUE pass , salt , opts , kwargs [5 ], str ;
160+ VALUE pass , salt , opts , kwargs [5 ], str , pass_tmp , salt_tmp ;
135161 static ID kwargs_ids [5 ];
136- size_t len ;
137- uint64_t N , r , p , maxmem ;
162+ size_t passlen , saltlen ;
163+ long len ;
138164
139165 if (!kwargs_ids [0 ]) {
140166 kwargs_ids [0 ] = rb_intern_const ("salt" );
@@ -147,24 +173,29 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
147173 rb_get_kwargs (opts , kwargs_ids , 5 , 0 , kwargs );
148174
149175 StringValue (pass );
176+ passlen = RSTRING_LEN (pass );
150177 salt = StringValue (kwargs [0 ]);
151- N = NUM2UINT64T (kwargs [1 ]);
152- r = NUM2UINT64T (kwargs [2 ]);
153- p = NUM2UINT64T (kwargs [3 ]);
178+ saltlen = RSTRING_LEN (salt );
154179 len = NUM2LONG (kwargs [4 ]);
155- /*
156- * OpenSSL uses 32MB by default (if zero is specified), which is too small.
157- * Let's not limit memory consumption but just let malloc() fail inside
158- * OpenSSL. The amount is controllable by other parameters.
159- */
160- maxmem = SIZE_MAX ;
161-
162- str = rb_str_new (0 , len );
163- if (!EVP_PBE_scrypt (RSTRING_PTR (pass ), RSTRING_LEN (pass ),
164- (unsigned char * )RSTRING_PTR (salt ), RSTRING_LEN (salt ),
165- N , r , p , maxmem , (unsigned char * )RSTRING_PTR (str ), len ))
180+ str = rb_str_new (NULL , len );
181+ struct scrypt_args args = {
182+ .pass = ALLOCV (pass_tmp , passlen ),
183+ .passlen = passlen ,
184+ .salt = ALLOCV (salt_tmp , saltlen ),
185+ .saltlen = saltlen ,
186+ .N = NUM2UINT64T (kwargs [1 ]),
187+ .r = NUM2UINT64T (kwargs [2 ]),
188+ .p = NUM2UINT64T (kwargs [3 ]),
189+ .len = len ,
190+ .out = (unsigned char * )RSTRING_PTR (str ),
191+ };
192+ memcpy (args .pass , RSTRING_PTR (pass ), passlen );
193+ memcpy (args .salt , RSTRING_PTR (salt ), saltlen );
194+ if (!rb_thread_call_without_gvl (scrypt_nogvl , & args , NULL , NULL ))
166195 ossl_raise (eKDF , "EVP_PBE_scrypt" );
167-
196+ OPENSSL_cleanse (& args .pass , passlen );
197+ ALLOCV_END (pass_tmp );
198+ ALLOCV_END (salt_tmp );
168199 return str ;
169200}
170201#endif
0 commit comments