RustCrypto / utils

Utility crates used in RustCrypto
432 stars 128 forks source link

Why `DefaultIsZeroes` requires `Copy`? #1062

Closed dima74 closed 5 months ago

dima74 commented 5 months ago

https://github.com/RustCrypto/utils/blob/216d2b82f691487b80e8d94022a1aaf45b2f926f/zeroize/src/lib.rs#L283

What is recommended approach to implement Zeroize for non-copy-types? Consider some library has non-copy type:

// somelib.rs
#[derive(Clone)]
pub struct SecretKey([u8; 32]);

And in user code we have wrapper around that which we would like to zeroize on drop:

// main.rs
#[derive(Clone)]
struct MyKey(SecretKey);

One approach would be to implement Default for MyKey and add impl DefaultIsZeroes for MyKey {} so MyKey will implement Zeroize, but it is not possible because of Copy constraint on DefaultIsZeroes

tarcieri commented 5 months ago

DefaultIsZeroes underlies the core zeroization behavior for integer types, which is performed using core::ptr::write_volatile.

A Copy bound is the simplest way we can avoid making DefaultIsZeroes an unsafe trait:

What is recommended approach to implement Zeroize for non-copy-types?

For your example:

impl Zeroize for SecretKey {
    fn zeroize(&mut self) {
        self.0.zeroize();
    }
}

Though you'd likely be better zeroizing in a drop handler for such a use case, to avoid use-after-zeroize problems:

impl Drop for SecretKey {
    fn drop(&mut self) {
        self.0.zeroize();
    }
}

impl ZeroizeOnDrop for SecretKey {}
dima74 commented 5 months ago

Thanks for the detailed answer!

impl Zeroize for SecretKey {
    fn zeroize(&mut self) {
        self.0.zeroize();
    }
}

If this can't be used because SecretKey is from (external) library which doesn't use zeroize, and SecretKey doesn't implement Copy, are there any possibilities to use zeroize on the wrapper (MyKey), or the only solution would be to approach library author and suggest to use zeroize?

tarcieri commented 5 months ago

There's no safe way to zeroize a foreign type.

1045 added a zeroize_flat_type function which could potentially apply to these cases, although it's a bit dangerous to use on a type you don't control as its internal structure could change.

dima74 commented 5 months ago

Thanks for the explanation 👍