Describe the issue
verifyRegistrationResponse() throws on registrations from devices with a Qualcomm fTPM (Snapdragon-based Windows / Windows-on-ARM machines, e.g. Surface Pro X and Snapdragon Copilot+ PCs):
Could not match TPM manufacturer "id:51434f4d" (TPM)
0x51434f4d decodes to ASCII QCOM (Qualcomm), and Qualcomm is present in TPM_MANUFACTURERS:
https://github.com/MasterKale/SimpleWebAuthn/blob/master/packages/server/src/registration/verifications/tpm/constants.ts#L126
'id:51434F4D': { name: 'Qualcomm', id: 'QCOM' },
The problem is casing. The lookup is case-sensitive, and these TPMs emit the manufacturer attribute in lowercase hex (id:51434f4d), while the map is keyed in uppercase (id:51434F4D):
https://github.com/MasterKale/SimpleWebAuthn/blob/master/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts#L437
tcgAtTpmManufacturer = attr.value.toString(); // raw cert value, e.g. "id:51434f4d"
https://github.com/MasterKale/SimpleWebAuthn/blob/master/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts#L328
if (!TPM_MANUFACTURERS[tcgAtTpmManufacturer]) { // undefined for lowercase key
throw new Error(`Could not match TPM manufacturer "${tcgAtTpmManufacturer}" (TPM)`);
}
I understand this is arguably a firmware defect: per the TCG spec (and as noted in #604), TPMManufacturer MUST use uppercase hex A-F, so Qualcomm's fTPM is technically non-compliant by emitting lowercase. But these are shipping consumer devices we can't fix, and the manufacturer is already in your list so only the casing prevents a match.
Reproduction Steps
- Request a passkey registration (
navigator.credentials.create) on a device backed by a Qualcomm fTPM (Snapdragon-based Windows machine using Windows Hello). The platform returns an attestation object with fmt: "tpm".
- Pass the response to
verifyRegistrationResponse().
- Verification throws
Could not match TPM manufacturer "id:51434f4d" (TPM).
Expected behavior
A manufacturer that is present in TPM_MANUFACTURERS should match regardless of the casing used in the certificate's TPMManufacturer attribute. Suggested fix: normalize the hex portion to uppercase before the lookup, which is the spec-canonical form (per #604):
// after parsing, in getTcgAtTpmValues / before the lookup
const normalized = tcgAtTpmManufacturer.toUpperCase().replace(/^ID:/, 'id:');
if (!TPM_MANUFACTURERS[normalized]) { ... }
Code Samples + WebAuthn Options and Responses
Standard usage:
const verification = await verifyRegistrationResponse({
response,
expectedChallenge,
expectedOrigin,
expectedRPID,
requireUserVerification: true,
});
The attestation statement's fmt is "tpm"; the AIK cert's subjectAltName directoryName carries TPMManufacturer = "id:51434f4d".
Dependencies
- OS: Windows (Snapdragon / Windows-on-ARM)
- Browser: Any (Chromium / Edge)
- Authenticator: Platform authenticator (Windows Hello) backed by a Qualcomm fTPM 2.0
SimpleWebAuthn Libraries
@simplewebauthn/server@13.2.2
(Confirmed still present on master / 13.3.1.)
Additional context
Related precedent: #604 (lowercase d in the IBM identifier) and #665 / #673 (incomplete manufacturer list). This one differs in that the entry already exists and is correctly cased per spec so the gap is that the cert value's casing isn't normalized before lookup.
Describe the issue
verifyRegistrationResponse()throws on registrations from devices with a Qualcomm fTPM (Snapdragon-based Windows / Windows-on-ARM machines, e.g. Surface Pro X and Snapdragon Copilot+ PCs):0x51434f4ddecodes to ASCIIQCOM(Qualcomm), and Qualcomm is present inTPM_MANUFACTURERS:https://github.com/MasterKale/SimpleWebAuthn/blob/master/packages/server/src/registration/verifications/tpm/constants.ts#L126
The problem is casing. The lookup is case-sensitive, and these TPMs emit the manufacturer attribute in lowercase hex (
id:51434f4d), while the map is keyed in uppercase (id:51434F4D):https://github.com/MasterKale/SimpleWebAuthn/blob/master/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts#L437
https://github.com/MasterKale/SimpleWebAuthn/blob/master/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts#L328
I understand this is arguably a firmware defect: per the TCG spec (and as noted in #604),
TPMManufacturerMUST use uppercase hexA-F, so Qualcomm's fTPM is technically non-compliant by emitting lowercase. But these are shipping consumer devices we can't fix, and the manufacturer is already in your list so only the casing prevents a match.Reproduction Steps
navigator.credentials.create) on a device backed by a Qualcomm fTPM (Snapdragon-based Windows machine using Windows Hello). The platform returns an attestation object withfmt: "tpm".verifyRegistrationResponse().Could not match TPM manufacturer "id:51434f4d" (TPM).Expected behavior
A manufacturer that is present in
TPM_MANUFACTURERSshould match regardless of the casing used in the certificate'sTPMManufacturerattribute. Suggested fix: normalize the hex portion to uppercase before the lookup, which is the spec-canonical form (per #604):Code Samples + WebAuthn Options and Responses
Standard usage:
The attestation statement's
fmtis"tpm"; the AIK cert'ssubjectAltNamedirectoryName carriesTPMManufacturer = "id:51434f4d".Dependencies
SimpleWebAuthn Libraries
(Confirmed still present on
master/13.3.1.)Additional context
Related precedent: #604 (lowercase
din the IBM identifier) and #665 / #673 (incomplete manufacturer list). This one differs in that the entry already exists and is correctly cased per spec so the gap is that the cert value's casing isn't normalized before lookup.