Conversation
On STM32L0 and STM32L1, `DEVICE_ID3` points at a reserved memory location instead of the third word of the 96-bit unique device ID. The USB serial number string is therefore derived from only 64 bits of the ID plus a constant, and **devices from the same production lot and wafer enumerate with byte-identical USB serial numbers**.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(usb): read UID word 2 at its documented offset on STM32L0/L1
Summary
On STM32L0 and STM32L1,
DEVICE_ID3points at a reserved memory locationinstead of the third word of the 96-bit unique device ID. The USB serial
number string is therefore derived from only 64 bits of the ID plus a
constant, and devices from the same production lot and wafer enumerate with
byte-identical USB serial numbers.
The bug
libraries/USBDevice/inc/usbd_desc.h:+0x8Uis correct for every STM32 family except STM32L0 and STM32L1,where the three UID words are not contiguous. The reference manuals place
bits 95:64 at offset 0x14:
(RM0376 §"Unique device ID registers (96 bits)" for STM32L0x2; likewise
RM0377 L0x1, RM0367 L0x3, RM0451 L011/L021, and RM0038 for STM32L1.)
UID_BASE + 0x8Uon these parts is reserved space. On the STM32L072 I testedit reads a constant
0x00000011.This repository already disagrees with itself
ST's HAL, vendored in this same tree, gets it right:
I scanned
HAL_GetUIDw2()across every HAL driver in the tree. STM32L0xxand STM32L1xx are the only two families using
0x14U; all 22 others use8U. So the conditional below is exactly as narrow as it needs to be.ST has confirmed the offset publicly. Their moderator acknowledged the same
bug in the LL driver and stated the reference-manual values are correct:
https://community.st.com/t5/stm32-mcus-products/how-to-report-issues-on-ll-hal-driver-for-stm32l0-incorrect/td-p/457949
Why it matters in practice
Per RM0451 §25.2 the L0 UID fields are laid out as:
LOT_NUM(ASCII)WAF_NUMLOT_NUMcontinued (ASCII)Words 0 and 1 are therefore lot and wafer identifiers, shared by every die
from the same wafer. The bits that distinguish individual dies live in word
2 — precisely the word
DEVICE_ID3fails to read.Get_SerialNum()computesserial = hex8(ID1 + ID3) + hex4(ID2), so with the wrongID3the serial isa function of lot and wafer only.
ST's moderator makes the same point: "If you want to use the Unique ID, you
would actually have to use the full 96bit", warning that partial fields may
be identical across devices from one batch.
https://community.st.com/stm32-mcus-products-25/stm32l0x0-are-unique-id-bits-95-64-of-unique-device-id-registers-at0x1ff8-0050-uniques-21113
Concretely: I have three physically distinct boards, reel-soldered from one
lot, all running STM32L072KBUx. Before this change all three enumerated as
USB serial
034733453934, which broke udev rules,/dev/serial/by-idpaths, and every attempt to tell one board from another on the same host.
This also produces false counterfeit reports. Users have concluded their
parts were fake after seeing identical "unique" IDs, when the cause was this
offset:
https://community.st.com/t5/stm32-mcus-products/non-unique-unique-device-id-or-counterfeit-parts/td-p/407850
The fix
No change on any other family.
Verification
Hardware: STM32L072KBUx, USB CDC, core 4.21200.0.
Read over SWD, the true UID is:
Get_SerialNum()predictshex8(0x03473334 + 0x002D002D) + hex4(0x39343436)=
03743361+3934.034733453934037433613934037433613934Matches, and the serial now depends on the word that actually varies between
dies.