ed25519_compact/
common.rs

1use core::ops::{Deref, DerefMut};
2use core::ptr;
3use core::sync::atomic;
4
5use super::error::Error;
6
7/// A seed, which a key pair can be derived from.
8#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
9pub struct Seed([u8; Seed::BYTES]);
10
11impl From<[u8; 32]> for Seed {
12    fn from(seed: [u8; 32]) -> Self {
13        Seed(seed)
14    }
15}
16
17impl Seed {
18    /// Number of raw bytes in a seed.
19    pub const BYTES: usize = 32;
20
21    /// Creates a seed from raw bytes.
22    pub fn new(seed: [u8; Seed::BYTES]) -> Self {
23        Seed(seed)
24    }
25
26    /// Creates a seed from a slice.
27    pub fn from_slice(seed: &[u8]) -> Result<Self, Error> {
28        let mut seed_ = [0u8; Seed::BYTES];
29        if seed.len() != seed_.len() {
30            return Err(Error::InvalidSeed);
31        }
32        seed_.copy_from_slice(seed);
33        Ok(Seed::new(seed_))
34    }
35
36    /// Tentatively overwrite the content of the seed with zeros.
37    pub fn wipe(self) {
38        Mem::wipe(self.0)
39    }
40}
41
42#[cfg(feature = "random")]
43impl Default for Seed {
44    /// Generates a random seed.
45    fn default() -> Self {
46        let mut seed = [0u8; Seed::BYTES];
47        getrandom::getrandom(&mut seed).expect("RNG failure");
48        Seed(seed)
49    }
50}
51
52#[cfg(feature = "random")]
53impl Seed {
54    /// Generates a random seed.
55    pub fn generate() -> Self {
56        Seed::default()
57    }
58}
59
60impl Deref for Seed {
61    type Target = [u8; Seed::BYTES];
62
63    /// Returns a seed as raw bytes.
64    fn deref(&self) -> &Self::Target {
65        &self.0
66    }
67}
68
69impl DerefMut for Seed {
70    /// Returns a seed as mutable raw bytes.
71    fn deref_mut(&mut self) -> &mut Self::Target {
72        &mut self.0
73    }
74}
75
76pub(crate) struct Mem;
77
78impl Mem {
79    #[inline]
80    pub fn wipe<T: Default>(mut x: impl AsMut<[T]>) {
81        let x = x.as_mut();
82        for i in 0..x.len() {
83            unsafe {
84                ptr::write_volatile(x.as_mut_ptr().add(i), T::default());
85            }
86        }
87        atomic::compiler_fence(atomic::Ordering::SeqCst);
88        atomic::fence(atomic::Ordering::SeqCst);
89    }
90}