Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Secrets

The Secret struct is a container for sensitive data that needs to be sustained in memory for an extended period. It tries to provide an additional layer of protection against speculative execution or cache attacks.

  • Linux: Uses memfd_secret, which practically does not impact performance.
  • Non-Linux: Holds encrypted heap-allocated bytes that are decrypted on demand. Adds some runtime overhead.

Please keep in mind that this is not a silver bullet, but rather an additional layer of protection. In an ideal world confidential data should be processed in dedicated hardware.

Another thing worth mentioning about non-linux users is that hibernation or swapping to disk can expose plaintext secrets. For example, while the peek method is active sensitive data will exist transiently in CPU registers and caches, which is unavoidable.

Example

//! Long lived secret

extern crate wtx;

use crate::wtx::rng::CryptoSeedableRng;
use std::{env, sync::OnceLock};
use wtx::{
  collections::Vector,
  misc::{Secret, SecretContext},
  rng::ChaCha20,
};

static SECRET: OnceLock<Secret> = OnceLock::new();

fn main() -> wtx::Result<()> {
  let data = env::args()
    .nth(1)
    .ok_or_else(|| wtx::Error::GenericStatic("No data".try_into().unwrap_or_default()))?;
  let mut rng = ChaCha20::from_std_random()?;
  let secret_context = SecretContext::new(&mut rng)?;
  let secret = Secret::new(data.into_bytes().as_mut(), &mut rng, secret_context)?;
  let _rslt = SECRET.set(secret);
  std::thread::spawn(|| {
    let mut buffer = Vector::new();
    let _sp = SECRET.wait().peek(&mut buffer)?;
    // Make API requests, decrypt AES, sign documents, do a flip, etc...
    wtx::Result::Ok(())
  })
  .join()??;
  Ok(())
}