Skip to main content

atecc608b/command/
random.rs

1// Copyright (c) 2026 Tuloup Simon
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program. If not, see <https://www.gnu.org/licenses/>.
15
16//! `Random` command.
17//!
18//! Returns 32 cryptographically random bytes from the chip's hardware RNG.
19//! The default mode `0x00` updates the chip's internal seed before
20//! generating the output, which is what we always want for production use.
21//! Mode `0x01` skips the seed update and exists only for development.
22//!
23//! Reference: `CryptoAuthLib` `lib/calib/calib_random.c`.
24
25use crate::driver::AteccChannel;
26use crate::error::AteccError;
27use crate::hal::AteccHal;
28use crate::opcodes::{EXEC_TIME_RANDOM_MS, OP_RANDOM};
29
30/// Number of random bytes returned by the chip in one Random command.
31pub(crate) const RANDOM_OUTPUT_LEN: usize = 32;
32
33impl<H> AteccChannel<'_, H>
34where
35    H: AteccHal,
36{
37    /// Request 32 random bytes from the chip.
38    ///
39    /// The chip reseeds its internal RNG before producing the output.
40    ///
41    /// # Errors
42    /// See [`AteccChannel::execute_command`].
43    pub async fn random(&mut self) -> Result<[u8; RANDOM_OUTPUT_LEN], AteccError<H::Error>>
44    {
45        // Response: count(1) + 32 data + crc(2) = 35 bytes.
46        let mut response_buf = [0u8; 35];
47        let payload = self
48            .execute_command
49            (
50                OP_RANDOM,
51                0x00,
52                0x0000,
53                &[],
54                EXEC_TIME_RANDOM_MS,
55                &mut response_buf,
56            )
57            .await?;
58
59        if payload.len() != RANDOM_OUTPUT_LEN
60        {
61            return Err(AteccError::MalformedResponse);
62        }
63
64        let mut out = [0u8; RANDOM_OUTPUT_LEN];
65        out.copy_from_slice(payload);
66        Ok(out)
67    }
68}