Skip to content

Commit cddeee0

Browse files
committed
kdf: use ParamBuilder
Increases the safety of the code and, imho, increases the readability. Additionally, removes the need for iter, lanes & memcost to be mutable.
1 parent 4a7529e commit cddeee0

File tree

1 file changed

+43
-80
lines changed

1 file changed

+43
-80
lines changed

openssl/src/kdf.rs

Lines changed: 43 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,14 @@ impl Drop for EvpKdfCtx {
2424

2525
cfg_if::cfg_if! {
2626
if #[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))] {
27+
use crate::error::ErrorStack;
28+
use crate::lib_ctx::LibCtxRef;
29+
use crate::params::ParamBuilder;
30+
use crate::util::c_str;
31+
use crate::{cvt, cvt_p};
32+
use foreign_types::ForeignTypeRef;
2733
use std::cmp;
28-
use std::ffi::c_void;
29-
use std::mem::MaybeUninit;
3034
use std::ptr;
31-
use foreign_types::ForeignTypeRef;
32-
use libc::c_char;
33-
use crate::{cvt, cvt_p};
34-
use crate::lib_ctx::LibCtxRef;
35-
use crate::error::ErrorStack;
3635

3736
/// Derives a key using the argon2id algorithm.
3837
///
@@ -48,86 +47,50 @@ cfg_if::cfg_if! {
4847
salt: &[u8],
4948
ad: Option<&[u8]>,
5049
secret: Option<&[u8]>,
51-
mut iter: u32,
52-
mut lanes: u32,
53-
mut memcost: u32,
50+
iter: u32,
51+
lanes: u32,
52+
memcost: u32,
5453
out: &mut [u8],
5554
) -> Result<(), ErrorStack> {
56-
unsafe {
57-
ffi::init();
58-
let libctx = ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr);
55+
ffi::init();
56+
let libctx = ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr);
5957

60-
let max_threads = ffi::OSSL_get_max_threads(libctx);
61-
let mut threads = 1;
62-
// If max_threads is 0, then this isn't a threaded build.
63-
// If max_threads is > u32::MAX we need to clamp since
64-
// argon2id's threads parameter is a u32.
65-
if max_threads > 0 {
66-
threads = cmp::min(lanes, cmp::min(max_threads, u32::MAX as u64) as u32);
67-
}
68-
let mut params: [ffi::OSSL_PARAM; 10] =
69-
core::array::from_fn(|_| MaybeUninit::<ffi::OSSL_PARAM>::zeroed().assume_init());
70-
let mut idx = 0;
71-
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
72-
b"pass\0".as_ptr() as *const c_char,
73-
pass.as_ptr() as *mut c_void,
74-
pass.len(),
75-
);
76-
idx += 1;
77-
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
78-
b"salt\0".as_ptr() as *const c_char,
79-
salt.as_ptr() as *mut c_void,
80-
salt.len(),
81-
);
82-
idx += 1;
83-
params[idx] =
84-
ffi::OSSL_PARAM_construct_uint(b"threads\0".as_ptr() as *const c_char, &mut threads);
85-
idx += 1;
86-
params[idx] =
87-
ffi::OSSL_PARAM_construct_uint(b"lanes\0".as_ptr() as *const c_char, &mut lanes);
88-
idx += 1;
89-
params[idx] =
90-
ffi::OSSL_PARAM_construct_uint(b"memcost\0".as_ptr() as *const c_char, &mut memcost);
91-
idx += 1;
92-
params[idx] =
93-
ffi::OSSL_PARAM_construct_uint(b"iter\0".as_ptr() as *const c_char, &mut iter);
94-
idx += 1;
95-
let mut size = out.len() as u32;
96-
params[idx] =
97-
ffi::OSSL_PARAM_construct_uint(b"size\0".as_ptr() as *const c_char, &mut size);
98-
idx += 1;
99-
if let Some(ad) = ad {
100-
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
101-
b"ad\0".as_ptr() as *const c_char,
102-
ad.as_ptr() as *mut c_void,
103-
ad.len(),
104-
);
105-
idx += 1;
106-
}
107-
if let Some(secret) = secret {
108-
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
109-
b"secret\0".as_ptr() as *const c_char,
110-
secret.as_ptr() as *mut c_void,
111-
secret.len(),
112-
);
113-
idx += 1;
114-
}
115-
params[idx] = ffi::OSSL_PARAM_construct_end();
58+
let max_threads = unsafe { ffi::OSSL_get_max_threads(libctx) };
59+
let mut threads = 1;
60+
// If max_threads is 0, then this isn't a threaded build.
61+
// If max_threads is > u32::MAX we need to clamp since
62+
// argon2id's threads parameter is a u32.
63+
if max_threads > 0 {
64+
threads = cmp::min(lanes, cmp::min(max_threads, u32::MAX as u64) as u32);
65+
}
66+
let mut param_builder = ParamBuilder::new()
67+
.push_byte_string(c_str(b"pass\0"), pass)?
68+
.push_byte_string(c_str(b"salt\0"), salt)?
69+
.push_uint(c_str(b"threads\0"), threads)?
70+
.push_uint(c_str(b"lanes\0"), lanes)?
71+
.push_uint(c_str(b"memcost\0"), memcost)?
72+
.push_uint(c_str(b"iter\0"), iter)?
73+
.push_size_t(c_str(b"size\0"), out.len())?;
74+
if let Some(ad) = ad {
75+
param_builder = param_builder.push_byte_string(c_str(b"ad\0"), ad)?;
76+
}
77+
if let Some(secret) = secret {
78+
param_builder = param_builder.push_byte_string(c_str(b"secret\0"), secret)?;
79+
}
11680

117-
let argon2 = EvpKdf(cvt_p(ffi::EVP_KDF_fetch(
118-
libctx,
119-
b"ARGON2ID\0".as_ptr() as *const c_char,
120-
ptr::null(),
121-
))?);
122-
let ctx = EvpKdfCtx(cvt_p(ffi::EVP_KDF_CTX_new(argon2.0))?);
123-
cvt(ffi::EVP_KDF_derive(
81+
let argon2 = EvpKdf(cvt_p(unsafe {
82+
ffi::EVP_KDF_fetch(libctx, c_str(b"ARGON2ID\0").as_ptr(), ptr::null())
83+
})?);
84+
let ctx = EvpKdfCtx(cvt_p(unsafe { ffi::EVP_KDF_CTX_new(argon2.0) })?);
85+
cvt(unsafe {
86+
ffi::EVP_KDF_derive(
12487
ctx.0,
12588
out.as_mut_ptr(),
12689
out.len(),
127-
params.as_ptr(),
128-
))
129-
.map(|_| ())
130-
}
90+
param_builder.build()?.as_ptr(),
91+
)
92+
})
93+
.map(|_| ())
13194
}
13295
}
13396
}

0 commit comments

Comments
 (0)