GGSheng's picture
feat: deploy Gemma 4 to hf space
08c964e verified
from dataclasses import dataclass
from enum import Enum
from typing import Mapping, Union
from ..cose import COSECRV, COSEAlgorithmIdentifier
from ..exceptions import InvalidTPMPubAreaStructure
################
#
# A whole lotta domain knowledge is captured here, with hazy connections to source
# documents. Good places to start searching for more info on these values are the
# following Trusted Computing Group TPM Library docs linked in the WebAuthn API:
#
# - https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-1-Architecture-01.38.pdf
# - https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
# - https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-3-Commands-01.38.pdf
#
################
class TPM_ST(str, Enum):
RSP_COMMAND = "TPM_ST_RSP_COMMAND"
NULL = "TPM_ST_NULL"
NO_SESSIONS = "TPM_ST_NO_SESSIONS"
SESSIONS = "TPM_ST_SESSIONS"
ATTEST_NV = "TPM_ST_ATTEST_NV"
ATTEST_COMMAND_AUDIT = "TPM_ST_ATTEST_COMMAND_AUDIT"
ATTEST_SESSION_AUDIT = "TPM_ST_ATTEST_SESSION_AUDIT"
ATTEST_CERTIFY = "TPM_ST_ATTEST_CERTIFY"
ATTEST_QUOTE = "TPM_ST_ATTEST_QUOTE"
ATTEST_TIME = "TPM_ST_ATTEST_TIME"
ATTEST_CREATION = "TPM_ST_ATTEST_CREATION"
CREATION = "TPM_ST_CREATION"
VERIFIED = "TPM_ST_VERIFIED"
AUTH_SECRET = "TPM_ST_AUTH_SECRET"
HASHCHECK = "TPM_ST_HASHCHECK"
AUTH_SIGNED = "TPM_ST_AUTH_SIGNED"
FU_MANIFEST = "TPM_ST_FU_MANIFEST"
class TPM_ALG(str, Enum):
ERROR = "TPM_ALG_ERROR"
RSA = "TPM_ALG_RSA"
SHA1 = "TPM_ALG_SHA1"
HMAC = "TPM_ALG_HMAC"
AES = "TPM_ALG_AES"
MGF1 = "TPM_ALG_MGF1"
KEYEDHASH = "TPM_ALG_KEYEDHASH"
XOR = "TPM_ALG_XOR"
SHA256 = "TPM_ALG_SHA256"
SHA384 = "TPM_ALG_SHA384"
SHA512 = "TPM_ALG_SHA512"
NULL = "TPM_ALG_NULL"
SM3_256 = "TPM_ALG_SM3_256"
SM4 = "TPM_ALG_SM4"
RSASSA = "TPM_ALG_RSASSA"
RSAES = "TPM_ALG_RSAES"
RSAPSS = "TPM_ALG_RSAPSS"
OAEP = "TPM_ALG_OAEP"
ECDSA = "TPM_ALG_ECDSA"
ECDH = "TPM_ALG_ECDH"
ECDAA = "TPM_ALG_ECDAA"
SM2 = "TPM_ALG_SM2"
ECSCHNORR = "TPM_ALG_ECSCHNORR"
ECMQV = "TPM_ALG_ECMQV"
KDF1_SP800_56A = "TPM_ALG_KDF1_SP800_56A"
KDF2 = "TPM_ALG_KDF2"
KDF1_SP800_108 = "TPM_ALG_KDF1_SP800_108"
ECC = "TPM_ALG_ECC"
SYMCIPHER = "TPM_ALG_SYMCIPHER"
CAMELLIA = "TPM_ALG_CAMELLIA"
CTR = "TPM_ALG_CTR"
OFB = "TPM_ALG_OFB"
CBC = "TPM_ALG_CBC"
CFB = "TPM_ALG_CFB"
ECB = "TPM_ALG_ECB"
class TPM_ECC_CURVE(str, Enum):
NONE = "NONE"
NIST_P192 = "NIST_P192"
NIST_P224 = "NIST_P224"
NIST_P256 = "NIST_P256"
NIST_P384 = "NIST_P384"
NIST_P521 = "NIST_P521"
BN_P256 = "BN_P256"
BN_P638 = "BN_P638"
SM2_P256 = "SM2_P256"
class TPMCertInfoClockInfo:
"""
10.11.1 TPMS_CLOCK_INFO
"""
clock: bytes
reset_count: int
restart_count: int
safe: bool
def __init__(self, clock_info: bytes):
self.clock = clock_info[0:8]
self.reset_count = int.from_bytes(clock_info[8:12], "big")
self.restart_count = int.from_bytes(clock_info[12:16], "big")
self.safe = bool(clock_info[16])
class TPMCertInfoAttested:
"""
10.12.3 TPMS_CERTIFY_INFO
"""
name_alg: TPM_ALG
name_alg_bytes: bytes
name: bytes
qualified_name: bytes
def __init__(self, attested_name: bytes, qualified_name: bytes):
self.name_alg = TPM_ALG_MAP[attested_name[0:2]]
self.name_alg_bytes = attested_name[0:2]
self.name = attested_name
self.qualified_name = qualified_name
@dataclass
class TPMCertInfo:
"""
10.12.8 TPMS_ATTEST
"""
magic: bytes
type: TPM_ST
qualified_signer: bytes
extra_data: bytes
clock_info: TPMCertInfoClockInfo
firmware_version: bytes
attested: TPMCertInfoAttested
class TPMPubAreaParametersRSA:
"""
12.2.3.5 TPMS_RSA_PARMS
"""
symmetric: TPM_ALG
scheme: TPM_ALG
key_bits: bytes
exponent: bytes
def __init__(self, params: bytes):
self.symmetric = TPM_ALG_MAP[params[0:2]]
self.scheme = TPM_ALG_MAP[params[2:4]]
self.key_bits = params[4:6]
self.exponent = params[6:10]
class TPMPubAreaParametersECC:
"""
12.2.3.6 TPMS_ECC_PARMS
"""
symmetric: TPM_ALG
scheme: TPM_ALG
curve_id: TPM_ECC_CURVE
kdf: TPM_ALG
def __init__(self, params: bytes):
self.symmetric = TPM_ALG_MAP[params[0:2]]
self.scheme = TPM_ALG_MAP[params[2:4]]
self.curve_id = TPM_ECC_CURVE_MAP[params[4:6]]
self.kdf = TPM_ALG_MAP[params[6:8]]
class TPMPubAreaObjectAttributes:
"""
8.3 TPMA_OBJECT (Object Attributes)
"""
fixed_tpm: bool
st_clear: bool
fixed_parent: bool
sensitive_data_origin: bool
user_with_auth: bool
admin_with_policy: bool
no_da: bool
encrypted_duplication: bool
restricted: bool
decrypt: bool
sign_or_encrypt: bool
def __init__(self, object_attributes: bytes):
attrs = int.from_bytes(object_attributes[0:4], "big")
self.fixed_tpm = attrs & (1 << 1) != 0
self.st_clear = attrs & (1 << 2) != 0
self.fixed_parent = attrs & (1 << 4) != 0
self.sensitive_data_origin = attrs & (1 << 5) != 0
self.user_with_auth = attrs & (1 << 6) != 0
self.admin_with_policy = attrs & (1 << 7) != 0
self.no_da = attrs & (1 << 10) != 0
self.encrypted_duplication = attrs & (1 << 11) != 0
self.restricted = attrs & (1 << 16) != 0
self.decrypt = attrs & (1 << 17) != 0
self.sign_or_encrypt = attrs & (1 << 18) != 0
class TPMPubAreaUnique:
"""
12.2.3.2 TPMU_PUBLIC_ID
"""
value: bytes
def __init__(self, unique: bytes, alg_type: TPM_ALG):
if alg_type == TPM_ALG.RSA:
"""
As per 11.2.4.5 TPM2B_PUBLIC_KEY_RSA, extract `unique` of dynamic length
"""
unique_length = int.from_bytes(unique[0:2], "big")
rsa_unique = unique[2 : 2 + unique_length]
self.value = rsa_unique
elif alg_type == TPM_ALG.ECC:
"""
As per 12.2.3.2 TPMU_PUBLIC_ID, `unique` is `TPMS_ECC_POINT` when `type`
indicates ECC.
As per 11.2.5.2 TPMS_ECC_POINT, `x` and `y` within are
`TPM2B_ECC_PARAMETER`, which is a uint16 `size`, followed by bytes of
the indicated length.
`unique`, then, is structured thusly:
[
[x_len, ...x_bytes],
[y_len, ...y_bytes]
]
Get `unique` to this structure for easier comparison with the output from
`decode_credential_public_key`, which will return bytes for its `x` and `y`
and to which this value will be compared:
[
x_bytes,
y_bytes,
]
"""
pointer = 0
unique_x_len = int.from_bytes(unique[0:2], "big")
pointer += 2
unique_x = unique[pointer : pointer + unique_x_len]
pointer += unique_x_len
unique_y_len = int.from_bytes(unique[pointer : pointer + 2], "big")
pointer += 2
unique_y = unique[pointer : pointer + unique_y_len]
self.value = b"".join([unique_x, unique_y])
else:
raise InvalidTPMPubAreaStructure(
f'Pub Area alg type "{alg_type}" was not "{TPM_ALG.RSA}" or "{TPM_ALG.ECC}"'
)
@dataclass
class TPMPubArea:
"""
12.2.4 TPMT_PUBLIC
"""
type: TPM_ALG
name_alg: TPM_ALG
object_attributes: TPMPubAreaObjectAttributes
auth_policy: bytes
parameters: Union[TPMPubAreaParametersRSA, TPMPubAreaParametersECC]
unique: TPMPubAreaUnique
@dataclass
class TPMManufacturerInfo:
name: str
id: str
"""
6.9 TPM_ST (Structure Tags)
"""
TPM_ST_MAP: Mapping[bytes, TPM_ST] = {
b"\x00\xc4": TPM_ST.RSP_COMMAND,
b"\x80\x00": TPM_ST.NULL,
b"\x80\x01": TPM_ST.NO_SESSIONS,
b"\x80\x02": TPM_ST.SESSIONS,
b"\x80\x14": TPM_ST.ATTEST_NV,
b"\x80\x15": TPM_ST.ATTEST_COMMAND_AUDIT,
b"\x80\x16": TPM_ST.ATTEST_SESSION_AUDIT,
b"\x80\x17": TPM_ST.ATTEST_CERTIFY,
b"\x80\x18": TPM_ST.ATTEST_QUOTE,
b"\x80\x19": TPM_ST.ATTEST_TIME,
b"\x80\x1a": TPM_ST.ATTEST_CREATION,
b"\x80\x21": TPM_ST.CREATION,
b"\x80\x22": TPM_ST.VERIFIED,
b"\x80\x23": TPM_ST.AUTH_SECRET,
b"\x80\x24": TPM_ST.HASHCHECK,
b"\x80\x25": TPM_ST.AUTH_SIGNED,
b"\x80\x29": TPM_ST.FU_MANIFEST,
}
"""
6.3 TPM_ALG_ID
"""
TPM_ALG_MAP: Mapping[bytes, TPM_ALG] = {
b"\x00\x00": TPM_ALG.ERROR,
b"\x00\x01": TPM_ALG.RSA,
b"\x00\x04": TPM_ALG.SHA1,
b"\x00\x05": TPM_ALG.HMAC,
b"\x00\x06": TPM_ALG.AES,
b"\x00\x07": TPM_ALG.MGF1,
b"\x00\x08": TPM_ALG.KEYEDHASH,
b"\x00\x0a": TPM_ALG.XOR,
b"\x00\x0b": TPM_ALG.SHA256,
b"\x00\x0c": TPM_ALG.SHA384,
b"\x00\x0d": TPM_ALG.SHA512,
b"\x00\x10": TPM_ALG.NULL,
b"\x00\x12": TPM_ALG.SM3_256,
b"\x00\x13": TPM_ALG.SM4,
b"\x00\x14": TPM_ALG.RSASSA,
b"\x00\x15": TPM_ALG.RSAES,
b"\x00\x16": TPM_ALG.RSAPSS,
b"\x00\x17": TPM_ALG.OAEP,
b"\x00\x18": TPM_ALG.ECDSA,
b"\x00\x19": TPM_ALG.ECDH,
b"\x00\x1a": TPM_ALG.ECDAA,
b"\x00\x1b": TPM_ALG.SM2,
b"\x00\x1c": TPM_ALG.ECSCHNORR,
b"\x00\x1d": TPM_ALG.ECMQV,
b"\x00\x20": TPM_ALG.KDF1_SP800_56A,
b"\x00\x21": TPM_ALG.KDF2,
b"\x00\x22": TPM_ALG.KDF1_SP800_108,
b"\x00\x23": TPM_ALG.ECC,
b"\x00\x25": TPM_ALG.SYMCIPHER,
b"\x00\x26": TPM_ALG.CAMELLIA,
b"\x00\x40": TPM_ALG.CTR,
b"\x00\x41": TPM_ALG.OFB,
b"\x00\x42": TPM_ALG.CBC,
b"\x00\x43": TPM_ALG.CFB,
b"\x00\x44": TPM_ALG.ECB,
}
"""
6.4 TPM_ECC_CURVE
"""
TPM_ECC_CURVE_MAP: Mapping[bytes, TPM_ECC_CURVE] = {
b"\x00\x00": TPM_ECC_CURVE.NONE,
b"\x00\x01": TPM_ECC_CURVE.NIST_P192,
b"\x00\x02": TPM_ECC_CURVE.NIST_P224,
b"\x00\x03": TPM_ECC_CURVE.NIST_P256,
b"\x00\x04": TPM_ECC_CURVE.NIST_P384,
b"\x00\x05": TPM_ECC_CURVE.NIST_P521,
b"\x00\x10": TPM_ECC_CURVE.BN_P256,
b"\x00\x11": TPM_ECC_CURVE.BN_P638,
b"\x00\x20": TPM_ECC_CURVE.SM2_P256,
}
# Intentionally omit curves we can't map so a KeyError gets thrown
TPM_ECC_CURVE_COSE_CRV_MAP: Mapping[TPM_ECC_CURVE, COSECRV] = {
TPM_ECC_CURVE.NIST_P256: COSECRV.P256,
TPM_ECC_CURVE.NIST_P384: COSECRV.P384,
TPM_ECC_CURVE.NIST_P521: COSECRV.P521,
TPM_ECC_CURVE.BN_P256: COSECRV.P256,
TPM_ECC_CURVE.SM2_P256: COSECRV.P256,
}
# Intentionally omit algs we can't map so a KeyError gets thrown
TPM_ALG_COSE_ALG_MAP: Mapping[TPM_ALG, COSEAlgorithmIdentifier] = {
TPM_ALG.SHA256: COSEAlgorithmIdentifier.RSASSA_PSS_SHA_256,
TPM_ALG.SHA384: COSEAlgorithmIdentifier.RSASSA_PKCS1_v1_5_SHA_384,
TPM_ALG.SHA512: COSEAlgorithmIdentifier.RSASSA_PKCS1_v1_5_SHA_512,
TPM_ALG.SHA1: COSEAlgorithmIdentifier.RSASSA_PKCS1_v1_5_SHA_1,
}
# 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
TPM_MANUFACTURERS: Mapping[str, TPMManufacturerInfo] = {
"id:414D4400": TPMManufacturerInfo(name="AMD", id="AMD"),
"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:48504500": TPMManufacturerInfo(name="HPE", id="HPE"),
"id:49424d00": TPMManufacturerInfo(name="IBM", id="IBM"),
"id:49465800": TPMManufacturerInfo(name="Infineon", id="IFX"),
"id:494E5443": TPMManufacturerInfo(name="Intel", id="INTC"),
"id:4C454E00": TPMManufacturerInfo(name="Lenovo", id="LEN"),
"id:4D534654": TPMManufacturerInfo(name="Microsoft", id="MSFT"),
"id:4E534D20": TPMManufacturerInfo(name="National Semiconductor", id="NSM"),
"id:4E545A00": TPMManufacturerInfo(name="Nationz", id="NTZ"),
"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:534E5300": TPMManufacturerInfo(name="Sinosun", id="SNS"),
"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"),
}