diff --git a/tests/test_map_tpm_manufacturer_id.py b/tests/test_map_tpm_manufacturer_id.py new file mode 100644 index 0000000..12886b7 --- /dev/null +++ b/tests/test_map_tpm_manufacturer_id.py @@ -0,0 +1,15 @@ +from unittest import TestCase + +from webauthn.helpers.tpm import map_tpm_manufacturer_id + + +class TestWebAuthnGenerateUserHandle(TestCase): + def test_handles_recognized_id(self) -> None: + info = map_tpm_manufacturer_id("id:4353434F") + + self.assertEqual(info.name, "Cisco") + self.assertEqual(info.id, "CSCO") + + def test_raises_on_unrecognized_id(self) -> None: + with self.assertRaises(KeyError): + map_tpm_manufacturer_id("id:FFFFFFFF") diff --git a/webauthn/helpers/tpm/__init__.py b/webauthn/helpers/tpm/__init__.py index e8982ad..173ffd5 100644 --- a/webauthn/helpers/tpm/__init__.py +++ b/webauthn/helpers/tpm/__init__.py @@ -1,4 +1,5 @@ +from .map_tpm_manufacturer import map_tpm_manufacturer_id from .parse_cert_info import parse_cert_info from .parse_pub_area import parse_pub_area -__all__ = ["parse_cert_info", "parse_pub_area"] +__all__ = ["map_tpm_manufacturer_id", "parse_cert_info", "parse_pub_area"] diff --git a/webauthn/helpers/tpm/map_tpm_manufacturer.py b/webauthn/helpers/tpm/map_tpm_manufacturer.py new file mode 100644 index 0000000..48c99b5 --- /dev/null +++ b/webauthn/helpers/tpm/map_tpm_manufacturer.py @@ -0,0 +1,18 @@ +from .structs import TPM_MANUFACTURERS, TPMManufacturerInfo + + +def map_tpm_manufacturer_id(id: str) -> TPMManufacturerInfo: + """ + Map a TPM manufacturer's hex ID to a manufacturer's assigned name and ASCII identifier + + Args: + - `id`: A TPM manufacturer ID string like `"id:FFFFFFFF"` + (a.k.a. oid "2.23.133.2.1" in SubjectAlternativeName extension) + + Returns: + An instance of `TPMManufacturerInfo` + + Raises: + `KeyError` on unrecognized TPM manufacturer ID + """ + return TPM_MANUFACTURERS[id] diff --git a/webauthn/helpers/tpm/structs.py b/webauthn/helpers/tpm/structs.py index 4e0e9ba..03d034e 100644 --- a/webauthn/helpers/tpm/structs.py +++ b/webauthn/helpers/tpm/structs.py @@ -381,14 +381,19 @@ class TPMManufacturerInfo: # Sourced from https://trustedcomputinggroup.org/resource/vendor-id-registry/ -# Latest version: https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-Vendor-ID-Registry-Version-1.02-Revision-1.00.pdf +# Latest version: https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-Vendor-ID-Registry-Family-1.2-and-2.0-Version-1.07-Revision-0.02_pub.pdf TPM_MANUFACTURERS: Mapping[str, TPMManufacturerInfo] = { "id:414D4400": TPMManufacturerInfo(name="AMD", id="AMD"), + "id:414E5400": TPMManufacturerInfo(name="Ant Group", id="ANT"), "id:41544D4C": TPMManufacturerInfo(name="Atmel", id="ATML"), "id:4252434D": TPMManufacturerInfo(name="Broadcom", id="BRCM"), "id:4353434F": TPMManufacturerInfo(name="Cisco", id="CSCO"), "id:464C5953": TPMManufacturerInfo(name="Flyslice Technologies", id="FLYS"), + "id:524F4343": TPMManufacturerInfo(name="Fuzhou Rockchip", id="ROCC"), + "id:474F4F47": TPMManufacturerInfo(name="Google", id="GOOG"), + "id:48504900": TPMManufacturerInfo(name="HPI", id="HPI"), "id:48504500": TPMManufacturerInfo(name="HPE", id="HPE"), + "id:48495349": TPMManufacturerInfo(name="Huawei", id="HISI"), "id:49424d00": TPMManufacturerInfo(name="IBM", id="IBM"), "id:49465800": TPMManufacturerInfo(name="Infineon", id="IFX"), "id:494E5443": TPMManufacturerInfo(name="Intel", id="INTC"), @@ -396,14 +401,15 @@ class TPMManufacturerInfo: "id:4D534654": TPMManufacturerInfo(name="Microsoft", id="MSFT"), "id:4E534D20": TPMManufacturerInfo(name="National Semiconductor", id="NSM"), "id:4E545A00": TPMManufacturerInfo(name="Nationz", id="NTZ"), + "id:4E534700": TPMManufacturerInfo(name="NSING", id="NSG"), "id:4E544300": TPMManufacturerInfo(name="Nuvoton Technology", id="NTC"), "id:51434F4D": TPMManufacturerInfo(name="Qualcomm", id="QCOM"), - "id:534D5343": TPMManufacturerInfo(name="SMSC", id="SMSC"), - "id:53544D20": TPMManufacturerInfo(name="ST Microelectronics", id="STM"), "id:534D534E": TPMManufacturerInfo(name="Samsung", id="SMSN"), + "id:53454345": TPMManufacturerInfo(name="SecEdge", id="SECE"), "id:534E5300": TPMManufacturerInfo(name="Sinosun", id="SNS"), + "id:534D5343": TPMManufacturerInfo(name="SMSC", id="SMSC"), + "id:53544D20": TPMManufacturerInfo(name="STMicroelectronics", id="STM"), "id:54584E00": TPMManufacturerInfo(name="Texas Instruments", id="TXN"), "id:57454300": TPMManufacturerInfo(name="Winbond", id="WEC"), - "id:524F4343": TPMManufacturerInfo(name="Fuzhou Rockchip", id="ROCC"), - "id:474F4F47": TPMManufacturerInfo(name="Google", id="GOOG"), + "id:5345414C": TPMManufacturerInfo(name="Wisekey", id="SEAL"), } diff --git a/webauthn/registration/formats/tpm.py b/webauthn/registration/formats/tpm.py index 504242a..a15a629 100644 --- a/webauthn/registration/formats/tpm.py +++ b/webauthn/registration/formats/tpm.py @@ -1,6 +1,5 @@ from typing import List -import cbor2 from cryptography import x509 from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import default_backend @@ -31,11 +30,10 @@ InvalidRegistrationResponse, ) from webauthn.helpers.structs import AttestationStatement -from webauthn.helpers.tpm import parse_cert_info, parse_pub_area +from webauthn.helpers.tpm import map_tpm_manufacturer_id, parse_cert_info, parse_pub_area from webauthn.helpers.tpm.structs import ( TPM_ALG_COSE_ALG_MAP, TPM_ECC_CURVE_COSE_CRV_MAP, - TPM_MANUFACTURERS, TPMPubAreaParametersECC, TPMPubAreaParametersRSA, ) @@ -255,7 +253,8 @@ def verify_tpm( ) try: - TPM_MANUFACTURERS[tcg_at_tpm_manufacturer] + # Naively try to map the manufacturer hex ID to a known manufacturer + map_tpm_manufacturer_id(tcg_at_tpm_manufacturer) except KeyError: raise InvalidRegistrationResponse( f'Unrecognized TPM Manufacturer "{tcg_at_tpm_manufacturer}" (TPM)'