1#[cfg(test)]
24mod tests;
25
26use log::{debug, trace};
27use openssl::error::ErrorStack;
28use openssl::pkcs5::pbkdf2_hmac;
29use std::fmt;
30use std::num::ParseIntError;
31use std::str::FromStr;
32use thiserror::Error;
33
34use crate::buffer::{Buffer, BufferError, BufferMut};
35use crate::digest::Digest;
36use crate::ossl;
37use crate::svec::SecureVec;
38
39#[derive(Debug, Error)]
41pub enum KdfError {
42 #[error(transparent)]
44 OpenSSL(#[from] ErrorStack),
45}
46
47#[derive(Clone, PartialEq)]
58pub enum Kdf {
59 None,
61
62 Pbkdf2 {
64 digest: Digest,
66
67 iterations: u32,
69
70 salt: Vec<u8>,
72 },
73}
74
75impl Kdf {
76 pub fn is_none(&self) -> bool {
78 match self {
79 Kdf::None => true,
80 Kdf::Pbkdf2 {
81 digest: _,
82 iterations: _,
83 salt: _,
84 } => false,
85 }
86 }
87
88 pub fn is_pbkdf2(&self) -> bool {
90 match self {
91 Kdf::None => false,
92 Kdf::Pbkdf2 {
93 digest: _,
94 iterations: _,
95 salt: _,
96 } => true,
97 }
98 }
99
100 pub fn pbkdf2(digest: Digest, iterations: u32, salt: &[u8]) -> Kdf {
126 Kdf::Pbkdf2 {
127 digest,
128 iterations,
129 salt: salt.to_vec(),
130 }
131 }
132
133 pub fn generate_pbkdf2(
168 digest: Digest,
169 iterations: u32,
170 salt_len: u32,
171 ) -> Result<Kdf, KdfError> {
172 let mut salt = vec![0; salt_len as usize];
173 ossl::rand_bytes(&mut salt)?;
174
175 Ok(Kdf::Pbkdf2 {
176 digest,
177 iterations,
178 salt,
179 })
180 }
181
182 fn create_key_internal(&self, password: &[u8]) -> Result<SecureVec, KdfError> {
183 match self {
184 Kdf::None => Ok(vec![].into()),
185 Kdf::Pbkdf2 {
186 digest,
187 iterations,
188 salt,
189 } => {
190 if password.is_empty() {
191 panic!("invalid password, cannot be empty");
192 }
193
194 if salt.is_empty() {
195 panic!("invalid salt, cannot be empty");
196 }
197
198 let md = digest.as_openssl();
199 let mut key = vec![0; digest.size()];
200
201 pbkdf2_hmac(password, salt, *iterations as usize, md, &mut key)?;
202
203 Ok(key.into())
204 }
205 }
206 }
207
208 pub(crate) fn create_key(
209 &self,
210 password: &[u8],
211 min_len: usize,
212 ) -> Result<SecureVec, KdfError> {
213 let mut key = self.create_key_internal(password)?;
214
215 while !self.is_none() && key.len() < min_len {
217 let xxx = self.create_key_internal(&key)?;
218 key.extend(xxx.as_ref());
219
220 trace!("create_key (step): len = {}", key.len());
221 }
222
223 debug!("create_key: min_len = {}, len = {}", min_len, key.len());
224
225 Ok(key)
226 }
227
228 pub(crate) fn get_from_buffer<T: Buffer>(buf: &mut T) -> Result<Kdf, BufferError> {
229 let b = buf.get_u32()?;
230
231 match b {
232 0 => Ok(Kdf::None),
233 1 => {
234 let digest = Digest::get_from_buffer(buf)?;
235 let iterations = buf.get_u32()?;
236 let salt = buf.get_vec::<8>()?;
237
238 Ok(Kdf::pbkdf2(digest, iterations, &salt))
239 }
240 _ => Err(BufferError::InvalidIndex("Kdf".to_string(), b)),
241 }
242 }
243
244 pub(crate) fn put_into_buffer<T: BufferMut>(&self, buf: &mut T) -> Result<(), BufferError> {
245 match self {
246 Kdf::None => buf.put_u32(0),
247 Kdf::Pbkdf2 {
248 digest,
249 iterations,
250 salt,
251 } => {
252 buf.put_u32(1)?;
253 digest.put_into_buffer(buf)?;
254 buf.put_u32(*iterations)?;
255 buf.put_vec::<8>(salt.as_slice())?;
256
257 Ok(())
258 }
259 }
260 }
261}
262
263impl fmt::Display for Kdf {
264 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
265 match self {
266 Kdf::None => fmt.write_str("none"),
267 Kdf::Pbkdf2 {
268 digest,
269 iterations,
270 salt,
271 } => {
272 write!(fmt, "pbkdf2:{}:{}:{}", digest, iterations, salt.len())
273 }
274 }
275 }
276}
277
278impl fmt::Debug for Kdf {
279 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
280 match self {
281 Kdf::None => fmt.debug_struct("None").finish(),
282 Kdf::Pbkdf2 {
283 digest,
284 iterations,
285 salt,
286 } => {
287 let salt = format!("<{} bytes>", salt.len());
288 fmt.debug_struct("Pbkdf2")
289 .field("digest", &digest)
290 .field("iterations", &iterations)
291 .field("salt", &salt)
292 .finish()
293 }
294 }
295 }
296}
297
298fn parse_none(v: &[&str]) -> Result<Kdf, ParseKdfNoneError> {
299 if v.is_empty() {
300 Ok(Kdf::None)
301 } else {
302 Err(ParseKdfNoneError::InvalidNumberOfArguments(v.len()))
303 }
304}
305
306fn parse_pbkdf2(v: &[&str]) -> Result<Kdf, ParseKdfPbkdf2Error> {
307 const DEFAULT_DIGEST: Digest = Digest::Sha256;
308 const DEFAULT_ITERATIONS: u32 = 65536;
309 const DEFAULT_SALT_LEN: u32 = 16;
310
311 if !v.is_empty() && v.len() != 3 {
312 return Err(ParseKdfPbkdf2Error::InvalidNumberOfArguments(v.len()));
313 }
314
315 let digest = if v.is_empty() || v[0].is_empty() {
316 DEFAULT_DIGEST
317 } else {
318 v[0].parse::<Digest>()
319 .map_err(|()| ParseKdfPbkdf2Error::InvalidDigest(v[0].to_string()))?
320 };
321
322 let iterations = if v.is_empty() || v[1].is_empty() {
323 DEFAULT_ITERATIONS
324 } else {
325 v[1].parse::<u32>()
326 .map_err(ParseKdfPbkdf2Error::InvalidIterations)?
327 };
328
329 let salt_len = if v.is_empty() || v[2].is_empty() {
330 DEFAULT_SALT_LEN
331 } else {
332 v[2].parse::<u32>()
333 .map_err(ParseKdfPbkdf2Error::InvalidSaltLen)?
334 };
335
336 Ok(Kdf::generate_pbkdf2(digest, iterations, salt_len)?)
337}
338
339#[derive(Debug, Error)]
340pub enum ParseKdfNoneError {
341 #[error("invalid number of arguments for the none-kdf, expected none but got {0}")]
342 InvalidNumberOfArguments(usize),
343}
344
345#[derive(Debug, Error)]
346pub enum ParseKdfPbkdf2Error {
347 #[error("invalid number of arguments for PBKDF2, got {0} but none or three are expected")]
348 InvalidNumberOfArguments(usize),
349
350 #[error("invalid digest: {0}")]
351 InvalidDigest(String),
352
353 #[error("invalid iterations: {0}")]
354 InvalidIterations(#[source] ParseIntError),
355
356 #[error("invalid salt length: {0}")]
357 InvalidSaltLen(#[source] ParseIntError),
358
359 #[error(transparent)]
360 Kdf(#[from] KdfError),
361}
362
363#[derive(Debug, Error)]
364pub enum ParseKdfError {
365 #[error(transparent)]
366 None(ParseKdfNoneError),
367
368 #[error(transparent)]
369 Pbkdf2(ParseKdfPbkdf2Error),
370
371 #[error("unknown kdf: {0}")]
372 Unknown(String),
373}
374
375impl FromStr for Kdf {
376 type Err = ParseKdfError;
377
378 fn from_str(s: &str) -> Result<Self, ParseKdfError> {
379 let v: Vec<&str> = s
380 .split(':')
381 .map(|s| s.trim_matches(char::is_whitespace))
382 .collect();
383
384 if v.is_empty() {
385 todo!()
386 }
387
388 match v[0] {
389 "none" => parse_none(&v[1..]).map_err(ParseKdfError::None),
390 "pbkdf2" => parse_pbkdf2(&v[1..]).map_err(ParseKdfError::Pbkdf2),
391 _ => Err(ParseKdfError::Unknown(v[0].to_string())),
392 }
393 }
394}