Skip to main content

config_generator/
crc.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//! CRC-16 implementation used to compute the lock-confirmation hash of
17//! the writable portion of the configuration zone.
18//!
19//! This is a deliberate duplicate of the same algorithm used in the
20//! firmware (`crates/atecc608b/src/crc.rs`). The duplication keeps the
21//! generator self-contained: it does not pull the embedded driver crate
22//! and its no_std machinery into a host build. Both implementations are
23//! tested against the same set of reference vectors taken from the
24//! Microchip CryptoAuthLib C source.
25//!
26//! Parameters:
27//! - Polynomial:    0x8005
28//! - Initial value: 0x0000
29//! - Reflect in:    false (MSB first)
30//! - Reflect out:   false
31//! - XOR out:       0x0000
32
33/// Compute the CRC-16 over `data`.
34#[must_use]
35pub(crate) fn crc16(data: &[u8]) -> u16
36{
37    const POLY: u16 = 0x8005;
38    let mut crc: u16 = 0x0000;
39    for byte in data
40    {
41        for bit_index in 0..8u8
42        {
43            let data_bit = (byte >> bit_index) & 0x01;
44            let crc_bit  = ((crc >> 15) & 0x0001) as u8;
45            crc <<= 1;
46            if data_bit != crc_bit
47            {
48                crc ^= POLY;
49            }
50        }
51    }
52    crc
53}
54
55#[cfg(test)]
56mod tests
57{
58    use super::*;
59
60    /// Reference vectors taken from `crates/atecc608b/src/crc.rs` tests.
61    /// Both implementations must agree on these.
62
63    #[test]
64    fn empty_input_is_zero()
65    {
66        assert_eq!(crc16(&[]), 0x0000);
67    }
68
69    #[test]
70    fn info_command_frame()
71    {
72        // Frame { count=0x07, opcode=Info=0x30, p1=0, p2=0,0 }
73        let frame = [0x07, 0x30, 0x00, 0x00, 0x00];
74        assert_eq!(crc16(&frame), 0x5D03);
75    }
76
77    #[test]
78    fn random_command_frame()
79    {
80        let frame = [0x07, 0x1B, 0x00, 0x00, 0x00];
81        assert_eq!(crc16(&frame), 0xCD24);
82    }
83
84    #[test]
85    fn wake_response_prefix()
86    {
87        let prefix = [0x04, 0x11];
88        assert_eq!(crc16(&prefix), 0x4333);
89    }
90}