@@ -24,6 +24,7 @@ impl Drop for EvpKdfCtx {
24
24
25
25
cfg_if:: cfg_if! {
26
26
if #[ cfg( all( ossl320, not( osslconf = "OPENSSL_NO_ARGON2" ) ) ) ] {
27
+ use std:: cmp;
27
28
use std:: ffi:: { c_char, c_void} ;
28
29
use std:: mem:: MaybeUninit ;
29
30
use std:: ptr;
@@ -34,8 +35,9 @@ cfg_if::cfg_if! {
34
35
35
36
/// Derives a key using the argon2id algorithm.
36
37
///
37
- /// This function currently does not support multi-threaded operation, so
38
- /// lanes greater than 1 will be processed sequentially.
38
+ /// To use multiple cores to process the lanes in parallel you must
39
+ /// set a global max thread count using `OSSL_set_max_threads`. On
40
+ /// builds with no threads all lanes will be processed sequentially.
39
41
///
40
42
/// Requires OpenSSL 3.2.0 or newer.
41
43
#[ allow( clippy:: too_many_arguments) ]
@@ -54,7 +56,14 @@ cfg_if::cfg_if! {
54
56
ffi:: init( ) ;
55
57
let libctx = ctx. map_or( ptr:: null_mut( ) , ForeignTypeRef :: as_ptr) ;
56
58
59
+ let max_threads = ffi:: OSSL_get_max_threads ( libctx) ;
57
60
let mut threads = 1 ;
61
+ // If max_threads is 0, then this isn't a threaded build.
62
+ // If max_threads is > u32::MAX we need to clamp since
63
+ // argon2id's threads parameter is a u32.
64
+ if max_threads > 0 {
65
+ threads = cmp:: min( lanes, cmp:: min( max_threads, u32 :: MAX as u64 ) as u32 ) ;
66
+ }
58
67
let mut params: [ ffi:: OSSL_PARAM ; 10 ] =
59
68
core:: array:: from_fn( |_| MaybeUninit :: <ffi:: OSSL_PARAM >:: zeroed( ) . assume_init( ) ) ;
60
69
let mut idx = 0 ;
0 commit comments