Memory zeroing advice?

Hi,
Please see the snippet bellow (playground).
I have function with a parameter as data_reader: Box<dyn Read> that make parameter static and I have another function with a password parameter.
As lifetime of static is during all the program run, I would try to zeroing password. I am not sure of memory management of rust. I need advice(s)

I imaged three approaches:

  1. Use mut &str. clear it after using. But in some step it become static :thinking:
  2. Use mut &'static str. According my understanding because of static it will keep it in the same address in memory so if I zeroing the variable it's maybe better.
  3. I use explicit drop but. I can print it after. Due to the reference :roll_eyes:

Question:

  • Do I really erase the memory with these approaches?

Thanks for advices

#![allow(unused)]
use std::io::{Read, BufReader};

fn main() {
    // Question is: Do I really zeroing my memory ?
    
    // Scenario 1,
    let mut pwd:&str = "My secret password";
    do_with_password(pwd);
    pwd = "______________________________________";
    println!("Scenario 1: {}",pwd);

    // Scenario 2,
    let mut pwd_x:&'static str = "My secret password";
    do_with_password(pwd_x);
    pwd_x = "______________________________________";
    println!("Scenario 2: {}",pwd_x);

    // Scenario 3,
    let mut pwd_y:&str = "My secret password";
    do_with_password(pwd_y);
    pwd_y = "______________________________________";
    drop(pwd_y);
    println!("Scenario 3: {}",pwd_y);
}

// function doing a task using data reader as Box<dyn Read> 
// so data_reader is implicit static
fn do_from_reader(data_reader: Box<dyn Read>) {
    let mut buffered = BufReader::new(data_reader);
    let mut dummy : Vec<u8> = Vec::new();
    buffered.read_to_end(dummy.as_mut()).unwrap();
}

// function doing a task using a password and previous function so
// so password parameter should be static (explicit)
fn do_with_password(password : &'static str) {
    let pwd = BufReader::new(password.as_bytes());
    do_from_reader(Box::new(pwd));
}

(Playground)

Output:

Scenario 1: ______________________________________
Scenario 2: ______________________________________
Scenario 3: ______________________________________

Firstly, your three approaches are equivalent. The second one just adds an explicit annotation of the lifetime that is implicitly there in the first one. The third one adds a call to drop() that does nothing, since &str is Copy so the reference is copied rather than moved and you can use it again.

None of these approaches actually erase the memory, they just swap out pointers to different parts of the memory.

String literals in Rust are baked into the executable and are always 'static and immutable. This means that putting passwords in them is a bad idea. You probably want to allocate memory on the heap using a String and reading in the password from a secure source (depending on what you are doing with it, you may want to just operate on a hash of the password).

To fix your original problem (that Box<dyn Read> is implicitly Box<dyn Read + 'static>), you probably want to have the function take a Box<dyn Read + ' a> (or Box<dyn Read + '_> to avoid the explicit lifetime parameter) allowing a reader that borrows from a String. If that doesn't work in your case, then you'll need to give more information why you need it to be 'static.

2 Likes

You may want to consider secrets or zeroize.

Additionally, you probably don't want to bake your secrets into your binary. (Or if you do, zeroing them isn't going to do anything anyway, even if successful.) Instead, you'll want to read them in from some source (such as stdin, environment variables, or a file) or only store a hash (if verifying the password is all that is required).

4 Likes

Thank you ! for your proposals and explanations.
The password in the binary was just for the example, it came from the command line at the start of the application.
You confirmed my intuition about an example I read.

Thanks to the syntax of '_ for lifetime

3 hours later, I got solutions and I learned a new syntax! Fantastic :smiley: