What changed, and why it matters
This commit caches the secure chip's serial number in memory during setup so it doesn't have to be read from the chip every time it's needed later. The change also makes a key-authorization function fail if the serial number hasn't been cached yet. This is a hardening improvement rather than a fix for an active vulnerability: it reduces how often the firmware talks to the secure chip for the serial number and ensures the value is available before use.
Review as normal hardening. Verify that atecc_setup() is always called before _authorize_key() in all boot/code paths, and that the cached serial number is not exposed through debug interfaces or untrusted memory reads. No urgent security patch is indicated by the diff alone.
Security signals we found
Reduction in repeated secure-element reads for a static identifier
Addition of an initialization-guard check before cryptographic authorization
No new cryptographic operations or trust model changes
Evidence from the diff
In src/atecc/atecc.c, the patch adds a static buffer _serial_number[ATCA_SERIAL_NUM_SIZE] and a flag _serial_number_cached. During atecc_setup(), after config verification succeeds, atcab_read_serial_number() is called once and the result is stored. The _authorize_key() function no longer reads the serial number directly from the ATECC; instead it uses the cached copy and returns ATCA_NOT_INITIALIZED if the cache isn’t ready. This is a defensive refactor that removes a repeated secure-chip read and adds a precondition check.
Changed components
src/atecc/atecc.cATECC secure chip interface_authorize_key() CHECKMAC authorization flowInspect captured patch +15 / −6
diff --git a/src/atecc/atecc.c b/src/atecc/atecc.c
index 13bfe22..5698198 100644
--- a/src/atecc/atecc.c
+++ b/src/atecc/atecc.c
@@ -86,6 +86,8 @@ typedef union {
#pragma GCC diagnostic pop
static const securechip_interface_functions_t* _interface_functions = NULL;
+static uint8_t _serial_number[ATCA_SERIAL_NUM_SIZE] = {0};
+static bool _serial_number_cached = false;
/** \brief initialize an I2C interface using given config.
* \param[in] hal - opaque ptr to HAL data
@@ -391,7 +393,16 @@ int atecc_setup(const securechip_interface_functions_t* ifs)
}
#endif
- return _verify_config();
+ int verify_config_result = _verify_config();
+ if (verify_config_result != ATCA_SUCCESS) {
+ return verify_config_result;
+ }
+ result = atcab_read_serial_number(_serial_number);
+ if (result != ATCA_SUCCESS) {
+ return result;
+ }
+ _serial_number_cached = true;
+ return ATCA_SUCCESS;
}
/**
@@ -425,10 +436,8 @@ static ATCA_STATUS _authorize_key(void)
uint8_t response[32] = {0};
const uint8_t other_data[13] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- uint8_t sn[9] = {0};
- result = atcab_read_serial_number(sn);
- if (result != ATCA_SUCCESS) {
- return result;
+ if (!_serial_number_cached) {
+ return ATCA_NOT_INITIALIZED;
}
uint8_t auth_key[32] = {0};
@@ -438,7 +447,7 @@ static ATCA_STATUS _authorize_key(void)
// First SHA block from slot key, Second SHA block from TempKey.
.mode = CHECKMAC_MODE_BLOCK2_TEMPKEY,
.key_id = ATECC_SLOT_AUTHKEY,
- .sn = sn,
+ .sn = _serial_number,
.client_chal = NULL, // unused in this mode
.client_resp = response,
.other_data = other_data,
Why this scored 25/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.