54 lines
2 KiB
Rust
54 lines
2 KiB
Rust
//! scrypt memory requirements scale linearly with parameters `N` and `r`.
|
|
//! This makes it unsuitable for embedded environments with the parameters
|
|
//! used in Spectre.
|
|
//! Our work-around is to derive the Spectre _user key_ using scrypt on the
|
|
//! host, encrypt it with XOR using a key derived using argon2, which
|
|
//! has parameters for specifying the memory and time requirements separately.
|
|
//! This encrypted key is then stored on the keyboard, to be decrypted again.
|
|
#![cfg_attr(not(feature = "std"), no_std)]
|
|
#![feature(allocator_api)]
|
|
|
|
extern crate alloc;
|
|
|
|
use alloc::alloc::Allocator;
|
|
use argon2::{Algorithm, Argon2, ParamsBuilder, Version};
|
|
|
|
use crate::blocks::Argon2Blocks;
|
|
|
|
pub mod blocks;
|
|
|
|
pub type Key = [u8; 64];
|
|
|
|
/// KiB used by the argon2 algorithm.
|
|
/// Lower than the default, to fit in the constrained memory of embedded devices.
|
|
pub const ARGON2_M_COST: u32 = 1024;
|
|
/// Compensate the difficulty by increasing the iterations proportionally.
|
|
pub const ARGON2_T_COST: u32 =
|
|
argon2::Params::DEFAULT_T_COST * argon2::Params::DEFAULT_M_COST / ARGON2_M_COST;
|
|
pub const ARGON2_P_COST: u32 = argon2::Params::DEFAULT_P_COST;
|
|
pub const ARGON2_SALT_PREFIX: &[u8] = b"acid-firmware\0";
|
|
|
|
pub fn derive_encryption_key(username: &[u8], secret: &[u8], allocator: impl Allocator) -> Key {
|
|
let argon2 = Argon2::new(
|
|
Algorithm::Argon2id,
|
|
Version::default(),
|
|
ParamsBuilder::default()
|
|
.m_cost(ARGON2_M_COST)
|
|
.t_cost(ARGON2_T_COST)
|
|
.p_cost(ARGON2_P_COST)
|
|
.build()
|
|
.unwrap(),
|
|
);
|
|
let mut blocks = Argon2Blocks::new_in(ARGON2_M_COST as usize, &allocator).unwrap();
|
|
let mut key: Key = [0u8; _];
|
|
// Username is prefixed to form a salt that is long enough for Argon2.
|
|
let mut salt = Vec::with_capacity_in(username.len() + ARGON2_SALT_PREFIX.len(), &allocator);
|
|
salt.extend_from_slice(ARGON2_SALT_PREFIX);
|
|
salt.extend_from_slice(username);
|
|
argon2
|
|
.hash_password_into_with_memory(secret, &salt, &mut key, &mut blocks)
|
|
.unwrap();
|
|
|
|
key
|
|
}
|