Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TPM Attestation in WebAuthn

This document describes the TPM (Trusted Platform Module) attestation format as implemented in the oauth2-passkey library, following the WebAuthn specification.

Overview

TPM attestation is used by authenticators that use a Trusted Platform Module as their cryptographic engine. The TPM attestation statement format is identified by the string “tpm” and supports the AttCA attestation type.

Attestation Statement Format

The TPM attestation statement follows this structure:

attStmtType = (
    fmt: "tpm",
    attStmt: tpmStmtFormat
)

tpmStmtFormat = {
    ver: "2.0",
    (
        alg: COSEAlgorithmIdentifier,
        x5c: [ aikCert: bytes, * (caCert: bytes) ]
    )
    sig: bytes,
    certInfo: bytes,
    pubArea: bytes
}

Field Descriptions

  • ver: The version of the TPM specification to which the signature conforms.
  • alg: A COSEAlgorithmIdentifier containing the identifier of the algorithm used to generate the attestation signature.
  • x5c: aikCert followed by its certificate chain, in X.509 encoding.
    • aikCert: The AIK certificate used for the attestation, in X.509 encoding.
  • sig: The attestation signature, in the form of a TPMT_SIGNATURE structure.
  • certInfo: The TPMS_ATTEST structure over which the signature was computed.
  • pubArea: The TPMT_PUBLIC structure used by the TPM to represent the credential public key.

Verification Procedure

The verification procedure for TPM attestation statements follows these steps:

  1. Basic Structure Verification:

    • Verify that the attestation statement is valid CBOR with the required fields (ver, alg, x5c, sig, certInfo, pubArea)
    • Check that the version is “2.0”
  2. Public Key Verification:

    • Verify that the public key in pubArea matches the credential public key in authenticatorData
  3. certInfo Validation:

    • Verify that magic is set to TPM_GENERATED_VALUE
    • Verify that type is set to TPM_ST_ATTEST_CERTIFY
    • Verify that extraData is set to the hash of attToBeSigned (authenticatorData + clientDataHash)
    • Verify that attested contains a valid TPMS_CERTIFY_INFO structure with the correct name field
  4. x5c Verification:

    • Verify that x5c is present
    • The qualifiedSigner, clockInfo, and firmwareVersion fields are ignored
  5. Signature Verification:

    • Verify that the signature is valid over certInfo using the attestation public key in aikCert
  6. AIK Certificate Requirements:

    • Verify that the AIK certificate version is 3
    • Verify that the Subject field is empty
    • Verify the Subject Alternative Name extension
    • Verify the Extended Key Usage extension contains the required OID (2.23.133.8.3)
    • Verify the Basic Constraints extension has CA set to false
    • If present, verify the AAGUID extension (OID 1.3.6.1.4.1.45724.1.1.4) matches the AAGUID in authenticatorData

TPM Structures

TPMS_ATTEST Structure

The TPMS_ATTEST structure contains the following fields:

  • magic: Must be set to TPM_GENERATED_VALUE (0xff544347)
  • type: Must be set to TPM_ST_ATTEST_CERTIFY (0x8017)
  • qualifiedSigner: TPM name of the key signing the attestation
  • extraData: The hash of attToBeSigned (authenticatorData + clientDataHash)
  • clockInfo: Information about the TPM’s clock
  • firmwareVersion: The TPM’s firmware version
  • attested: Contains a TPMS_CERTIFY_INFO structure

TPMS_CERTIFY_INFO Structure

The TPMS_CERTIFY_INFO structure contains:

  • name: The TPM name of the certified key (hash of pubArea)
  • qualifiedName: The qualified name of the certified key

Name Verification

The name field in the TPMS_CERTIFY_INFO structure is a hash of the pubArea using the nameAlg algorithm. The verification process includes:

#![allow(unused)]
fn main() {
// Extract the name algorithm from pubArea
let _name_alg = u16::from_be_bytes([pub_area[2], pub_area[3]]);

// Calculate the hash of pubArea using the nameAlg
let pub_area_hash = match _name_alg {
    0x000B => {
        // TPM_ALG_SHA256
        use sha2::{Digest, Sha256};
        let mut hasher = Sha256::new();
        hasher.update(pub_area);
        hasher.finalize().to_vec()
    }
    0x000C => {
        // TPM_ALG_SHA384
        use sha2::{Digest, Sha384};
        let mut hasher = Sha384::new();
        hasher.update(pub_area);
        hasher.finalize().to_vec()
    }
    0x000D => {
        // TPM_ALG_SHA512
        use sha2::{Digest, Sha512};
        let mut hasher = Sha512::new();
        hasher.update(pub_area);
        hasher.finalize().to_vec()
    }
    _ => {
        // Unsupported algorithm
        return Error;
    }
};

// The name field includes a 2-byte algorithm ID followed by the hash
// Verify that the hash part matches our calculated hash
}

AIK Certificate Verification

The AIK certificate must meet specific requirements:

  1. Version: Must be set to 3
  2. Subject: Must be empty
  3. Subject Alternative Name: Must be present as defined in TPMv2-EK-Profile
  4. Extended Key Usage: Must contain the OID 2.23.133.8.3
  5. Basic Constraints: Must have CA set to false
  6. AAGUID Extension: If present (OID 1.3.6.1.4.1.45724.1.1.4), must match the AAGUID in authenticatorData

Compliance Assessment

The oauth2-passkey library implementation of TPM attestation has been assessed against the WebAuthn specification requirements. Here’s a summary of the compliance status:

RequirementStatusNotes
Basic Structure Verification✅ CompliantVerifies all required fields and format
Public Key Verification✅ CompliantEnsures pubArea matches credentialPublicKey
certInfo Validation✅ CompliantVerifies magic, type, extraData, and attested fields
x5c Verification✅ CompliantChecks presence and properly ignores specified fields
Signature Verification✅ CompliantValidates signature over certInfo using AIK certificate
AIK Certificate Version✅ CompliantVerifies version is 3
AIK Certificate Subject✅ CompliantVerifies subject is empty
Subject Alternative Name✅ CompliantVerifies extension is present
Extended Key Usage✅ CompliantVerifies OID 2.23.133.8.3 is present
Basic Constraints✅ CompliantVerifies CA is false
AAGUID Extension✅ CompliantVerifies match with authenticatorData when present

Areas for Improvement

While the implementation is fully compliant with the WebAuthn specification, there are some areas that could be enhanced:

  1. Fallback Verification Robustness: The fallback verification using x509-parser could benefit from more detailed error messages to help diagnose specific validation failures.

  2. Error Handling: Current error handling could be enhanced with more specific error types for each verification step.

  3. Testing Coverage: Comprehensive tests for various edge cases and failure modes would strengthen the implementation.

  4. Performance Optimization: The current implementation prioritizes correctness and compliance over performance. There may be opportunities to optimize the verification process for high-volume deployments.

Supported Signature Algorithms

The TPM attestation verifier supports the following COSE algorithms for signature verification over certInfo:

COSE Alg IDNameDescriptionVerification Method
-7ES256ECDSA with P-256 and SHA-256webpki
-257RS256RSASSA-PKCS1-v1_5 with SHA-256webpki
-65535RS1RSASSA-PKCS1-v1_5 with SHA-1ring (legacy)

RS1 (SHA-1 RSA) Support

Windows Hello with TPM attestation commonly uses RS1 (-65535) to sign the certInfo structure, even when the credential key itself uses ES256. This is because the TPM’s Attestation Identity Key (AIK) may be an RSA key that signs using SHA-1.

Since the webpki crate does not support SHA-1 RSA signature verification, RS1 signatures are verified directly using the ring crate’s RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY algorithm. The public key is extracted from the AIK certificate using x509-parser.

Why Windows Hello TPM uses RS1

The attestation signature algorithm is determined by the TPM hardware, not the OS. The TPM’s AIK (Attestation Identity Key) is derived from the Endorsement Key (EK), which is burned into the TPM chip at manufacturing time. On many existing TPM chips, the EK is an RSA key that signs using SHA-1, and the AIK inherits this characteristic.

It is important to distinguish between two different keys and algorithms in TPM attestation:

  • Attestation signature (AIK): Signs certInfo to prove the TPM generated the credential. This is where RS1 (-65535) appears. The algorithm is dictated by the TPM hardware.
  • Credential key: Used for ongoing authentication (login). Typically uses ES256 (-7), a modern and secure algorithm. This is unaffected by the AIK’s algorithm.

Why RS1 persists and the outlook

SHA-1 has been considered cryptographically broken since 2017 (SHAttered collision attack), and all major browsers and CAs have stopped accepting SHA-1 certificates. However, RS1 remains in TPM attestation for the following reasons:

  • Hardware constraint: Changing the AIK algorithm requires a new TPM chip, not just a software or firmware update. The EK is immutable, and re-provisioning risks breaking dependent services (e.g., BitLocker relies on the TPM’s key hierarchy).
  • webpki’s design decision: The webpki (rustls-webpki) crate intentionally excludes SHA-1 as a security policy. This is a deliberate choice, not an omission, and future support is unlikely.
  • ring’s pragmatic approach: The ring crate provides RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY explicitly for legacy compatibility scenarios like this one.

Newer TPM chips (especially those shipping in recent PCs) tend to support SHA-256 based attestation. However, the transition is tied to hardware replacement cycles (5-10 years), so RS1 support will remain necessary for the foreseeable future.

Security impact

The use of RS1 for attestation has limited security impact:

  • The SHA-1 signature only proves that the TPM generated the credential at registration time. It does not affect the security of ongoing authentication.
  • An attacker exploiting SHA-1 collisions would need to forge a TPM attestation statement, which would also require compromising the TPM’s private AIK – a much harder attack than finding a hash collision.
  • The credential’s authentication signatures use ES256 (SHA-256), which is not affected.

Implementation Notes

  • The library uses webpki, x509-parser, and ring for certificate and signature verification
  • RS1 (SHA-1 RSA) signatures bypass webpki and are verified directly with ring’s legacy API
  • A fallback verification mechanism is implemented when webpki cannot parse the certificate
  • The implementation follows a modular approach to separate core attestation logic from TPM-specific logic
  • Comprehensive error handling is provided throughout the attestation verification process

References

  1. WebAuthn Specification
  2. TPM 2.0 Library Specification
  3. TPM 2.0 EK Profile