Skip to main content

rs_matter/crypto/
rand.rs

1/*
2 *
3 *    Copyright (c) 2026 Project CHIP Authors
4 *
5 *    Licensed under the Apache License, Version 2.0 (the "License");
6 *    you may not use this file except in compliance with the License.
7 *    You may obtain a copy of the License at
8 *
9 *        http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *    Unless required by applicable law or agreed to in writing, software
12 *    distributed under the License is distributed on an "AS IS" BASIS,
13 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *    See the License for the specific language governing permissions and
15 *    limitations under the License.
16 */
17
18//! Random number generation utilities.
19
20use rand_core::{CryptoRng, RngCore};
21
22use crate::utils::cell::RefCell;
23use crate::utils::init::{init, Init};
24use crate::utils::sync::blocking::Mutex;
25
26/// A utility wrapping a random number generator in a mutex for shared access.
27///
28/// Implements the `RngCore` and `CryptoRng` traits for `&SharedRand<M, T>`, where `T` is the
29/// underlying RNG type and `M` is the mutex type.
30pub struct SharedRand<T> {
31    shared: Mutex<RefCell<T>>,
32}
33
34impl<T> SharedRand<T> {
35    /// Creates a new `SharedRand` instance wrapping the provided RNG.
36    pub const fn new(rand: T) -> Self {
37        Self {
38            shared: Mutex::new(RefCell::new(rand)),
39        }
40    }
41
42    /// Initializes a new `SharedRand` instance using the provided RNG initializer.
43    pub fn init(rand: impl Init<T>) -> impl Init<Self> {
44        init!(Self {
45            shared <- Mutex::init(RefCell::init(rand)),
46        })
47    }
48}
49
50impl<T> rand_core::RngCore for &SharedRand<T>
51where
52    T: rand_core::RngCore,
53{
54    fn next_u32(&mut self) -> u32 {
55        self.shared.lock(|rand| rand.borrow_mut().next_u32())
56    }
57
58    fn next_u64(&mut self) -> u64 {
59        self.shared.lock(|rand| rand.borrow_mut().next_u64())
60    }
61
62    fn fill_bytes(&mut self, dest: &mut [u8]) {
63        self.shared.lock(|rand| rand.borrow_mut().fill_bytes(dest))
64    }
65
66    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
67        self.shared
68            .lock(|rand| rand.borrow_mut().try_fill_bytes(dest))
69    }
70}
71
72impl<T> CryptoRng for &SharedRand<T> where T: CryptoRng {}
73
74/// A weak random number generator intended for use in tests only.
75///
76/// DO NOT USE IN PRODUCTION!
77pub struct WeakTestOnlyRand(u32);
78
79impl WeakTestOnlyRand {
80    /// A fixed seed for the default constructor.
81    const SEED: u32 = 2463534242;
82
83    /// Create a new `WeakTestOnlyRand` instance with a default seed.
84    pub const fn new_default() -> Self {
85        Self(Self::SEED)
86    }
87
88    /// Create a new `WeakTestOnlyRand` instance with the specified seed.
89    pub const fn new(seed: u32) -> Self {
90        Self(seed)
91    }
92}
93
94impl RngCore for WeakTestOnlyRand {
95    fn next_u32(&mut self) -> u32 {
96        self.0 = self.0 ^ (self.0 << 13);
97        self.0 = self.0 ^ (self.0 >> 17);
98        self.0 = self.0 ^ (self.0 << 5);
99
100        self.0
101    }
102
103    fn next_u64(&mut self) -> u64 {
104        rand_core::impls::next_u64_via_u32(self)
105    }
106
107    fn fill_bytes(&mut self, dest: &mut [u8]) {
108        rand_core::impls::fill_bytes_via_next(self, dest)
109    }
110
111    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
112        rand_core::impls::fill_bytes_via_next(self, dest);
113
114        Ok(())
115    }
116}
117
118impl CryptoRng for WeakTestOnlyRand {}