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}