Skip to content

TPM attestation fails for Qualcomm fTPMs: manufacturer ID lookup is case-sensitive #769

@cbachmeier

Description

@cbachmeier

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

  1. 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".
  2. Pass the response to verifyRegistrationResponse().
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions