bitwarden_core/auth/login/
prelogin.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use bitwarden_api_identity::{
    apis::accounts_api::accounts_prelogin_post,
    models::{PreloginRequestModel, PreloginResponseModel},
};
use bitwarden_crypto::Kdf;
use thiserror::Error;

use crate::{require, ApiError, Client, MissingFieldError};

#[derive(Debug, Error)]
pub enum PreloginError {
    #[error(transparent)]
    Api(#[from] ApiError),
    #[error(transparent)]
    MissingField(#[from] MissingFieldError),
}

pub(crate) async fn prelogin(client: &Client, email: String) -> Result<Kdf, PreloginError> {
    let request_model = PreloginRequestModel::new(email);
    let config = client.internal.get_api_configurations().await;
    let result = accounts_prelogin_post(&config.identity, Some(request_model))
        .await
        .map_err(ApiError::from)?;

    Ok(parse_prelogin(result)?)
}

fn parse_prelogin(response: PreloginResponseModel) -> Result<Kdf, MissingFieldError> {
    use std::num::NonZeroU32;

    use bitwarden_api_identity::models::KdfType;
    use bitwarden_crypto::{
        default_argon2_iterations, default_argon2_memory, default_argon2_parallelism,
        default_pbkdf2_iterations,
    };

    let kdf = require!(response.kdf);

    Ok(match kdf {
        KdfType::PBKDF2_SHA256 => Kdf::PBKDF2 {
            iterations: response
                .kdf_iterations
                .and_then(|e| NonZeroU32::new(e as u32))
                .unwrap_or_else(default_pbkdf2_iterations),
        },
        KdfType::Argon2id => Kdf::Argon2id {
            iterations: response
                .kdf_iterations
                .and_then(|e| NonZeroU32::new(e as u32))
                .unwrap_or_else(default_argon2_iterations),
            memory: response
                .kdf_memory
                .and_then(|e| NonZeroU32::new(e as u32))
                .unwrap_or_else(default_argon2_memory),
            parallelism: response
                .kdf_parallelism
                .and_then(|e| NonZeroU32::new(e as u32))
                .unwrap_or_else(default_argon2_parallelism),
        },
    })
}