o
    l>jBL                     @  s  U d dl mZ d dlZd dlmZ d dlmZmZ d dlm	Z	m
Z
 d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZmZ ddlmZ ddlmZmZ ddlmZmZmZm Z mZm!Z!m"Z" dZ#e$dZ%eG dd deZ&eG dd deZ'eG dd deZ(eG dd dZ)dZ*dZ+eG dd dZ,eG dd dZ-G d d! d!e.Z/eG d"d# d#eZ0eG d$d% d%eZ1eG d&d' d'Z2eG d(d) d)Z3eG d*d+ d+eZ4ej5ej6B Z7d,e8d-< e-e2B Z9e/e3B Z:eG d.d/ d/Z;d0d1 Z<G d2d3 d3eZ=dS )4    )annotationsN)	dataclass)IntEnumunique)	TypeAliascast)x509)InvalidSignature)default_backend)hashes)ecrsa   )CoseKey)
ByteBuffer	bytes2int   )AttestationAttestationResultAttestationTypeInvalidDatar	   _validate_cert_commoncatch_builtins   z2.23.133.8.3c                   @  s   e Zd ZdZdZdZdZdS )TpmRsaScheme            N)__name__
__module____qualname__RSASSARSAPSSOAEPRSAES r&   r&   J/home/thesage/.local/lib/python3.10/site-packages/fido2/attestation/tpm.pyr   ;   s
    r   c                   @  s   e Zd ZdZdZdS )
TpmAlgAsymr   #   N)r   r    r!   RSAECCr&   r&   r&   r'   r(   C   s    r(   c                   @  s&   e Zd ZdZdZdZdZd
ddZd	S )
TpmAlgHash            returnhashes.HashAlgorithmc                 C  sV   | t jkr	t S | t jkrt S | t jkrt S | t jkr$t S td| )Nz!_hash_alg is not implemented for )r,   SHA1r   SHA256SHA384SHA512NotImplementedErrorselfr&   r&   r'   	_hash_algP   s   



zTpmAlgHash._hash_algN)r1   r2   )r   r    r!   r3   r4   r5   r6   r:   r&   r&   r&   r'   r,   I   s    r,   c                   @  s   e Zd ZU ded< ded< dS )TpmsCertifyInfobytesnamequalified_nameN)r   r    r!   __annotations__r&   r&   r&   r'   r;   ]   s   
 r;   s   TCGs   c                   @  sH   e Zd ZU dZded< ded< ded< ded< d	ed
< edddZdS )TpmAttestationFormatu  the signature data is defined by [TPMv2-Part2] Section 10.12.8 (TPMS_ATTEST)
    as:
      TPM_GENERATED_VALUE (0xff544347 aka "ÿTCG")
      TPMI_ST_ATTEST - always TPM_ST_ATTEST_CERTIFY (0x8017)
        because signing procedure defines it should call TPM_Certify
        [TPMv2-Part3] Section 18.2
      TPM2B_NAME
        size (uint16)
        name (size long)
      TPM2B_DATA
        size (uint16)
        name (size long)
      TPMS_CLOCK_INFO
        clock (uint64)
        resetCount (uint32)
        restartCount (uint32)
        safe (byte) 1 yes, 0 no
      firmwareVersion uint64
      attested TPMS_CERTIFY_INFO (because TPM_ST_ATTEST_CERTIFY)
        name TPM2B_NAME
        qualified_name TPM2B_NAME
    See:
      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
    r<   r=   dataztuple[int, int, int, bool]
clock_infointfirmware_versionr;   attestedr1   c              
   C  s  t |}|d}|tkrtd|d}|tkrtdzL||d}||d}|d}|d}|d}|d}	|	d	vrPtd
|	dd|	dk}
|d}||d}||d}W n tjy{ } zt|d }~ww | ||||||
f|t||ddS )Nr-   z generated value field is invalidr   ztpmi_st_attest field is invalid!Hz!Q!LB)r   r   zinvalid value 0xxz for booleanr   )r=   r>   )r=   rA   rB   rD   rE   )	r   readTPM_GENERATED_VALUE
ValueErrorTPM_ST_ATTEST_CERTIFYunpackstructerrorr;   )clsrA   readergenerated_valuetpmi_st_attestr=   clockreset_countrestart_count
safe_valuesaferD   attested_nameattested_qualified_nameer&   r&   r'   parse   sB   







zTpmAttestationFormat.parseN)rA   r<   r1   r@   r   r    r!   __doc__r?   classmethodr]   r&   r&   r&   r'   r@   g   s   
 r@   c                   @  s>   e Zd ZU dZded< ded< ded< ded< edd Zd	S )
TpmsRsaParmszParse TPMS_RSA_PARMS struct

    See:
    https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
    section 12.2.3.5
    rC   	symmetricschemekey_bitsexponentc                 C  s  | d}|tjtjB @ }|tjtjB k}|s|tkrtd| d}|tjtjB @ }|tjk}|r@|ttjtj	fvr@td|tjtjB k}	|	rV|tjtj	fvrVtd|tjk}
|
rj|tj
tjtfvrjtd|ru|tfvrutd| d}| d}|dkrd	}| ||||S )
NrF    symmetric is expected to be NULLzlkey is an unrestricted signing key, scheme is expected to be TPM_ALG_RSAPSS, TPM_ALG_RSASSA, or TPM_ALG_NULLz[key is a restricted signing key, scheme is expected to be TPM_ALG_RSAPSS, or TPM_ALG_RSASSAzlkey is an unrestricted decryption key, scheme is expected to be TPM_ALG_RSAES, TPM_ALG_OAEP, or TPM_ALG_NULLzJkey is an restricted decryption key, scheme is expected to be TPM_ALG_NULLrG   r   i  )rN   
ATTRIBUTES
RESTRICTEDDECRYPTTPM_ALG_NULLrL   SIGN_ENCRYPTr   r"   r#   r$   r%   )rQ   rR   
attributesrb   restricted_decryptionis_restricted_decryption_keyrc   restricted_signis_unrestricted_signing_keyis_restricted_signing_keyis_unrestricted_decryption_keyrd   re   r&   r&   r'   r]      s`   








zTpmsRsaParms.parseNr^   r&   r&   r&   r'   ra      s   
 ra   c                   @  s   e Zd ZedddZdS )Tpm2bPublicKeyRsarR   r   r1   c                 C  s   | | |dS NrF   rJ   rN   )rQ   rR   r&   r&   r'   r]     s   zTpm2bPublicKeyRsa.parseN)rR   r   r1   rs   )r   r    r!   r`   r]   r&   r&   r&   r'   rs     s    rs   c                   @  s>   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdddZdS )TpmEccCurvezTPM_ECC_CURVE
    https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
    section 6.4
    r   r   r      r-      r          r1   ec.EllipticCurvec                 C  sv   | t jkr	td| t jkrt S | t jkrt S | t jkr$t	 S | t j
kr-t S | t jkr6t S td| )NzNo such curvezcurve is not supported)rv   NONErL   	NIST_P192r   	SECP192R1	NIST_P224	SECP224R1	NIST_P256	SECP256R1	NIST_P384	SECP384R1	NIST_P521	SECP521R1r8   r&   r&   r'   to_curve%  s   






zTpmEccCurve.to_curveN)r1   r{   )r   r    r!   r_   r|   r}   r   r   r   r   BN_P256BN_P638SM2_P256r   r&   r&   r&   r'   rv     s    rv   c                   @  s    e Zd ZdZeZdZdZdZdS )
TpmiAlgKdfzTPMI_ALG_KDF
    https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
    section 9.28
    rz   !   "   N)	r   r    r!   r_   rj   NULLKDF1_SP800_56AKDF2KDF1_SP800_108r&   r&   r&   r'   r   6  s    r   c                   @  s<   e Zd ZU ded< ded< ded< ded< edddZdS )TpmsEccParmsrC   rb   rc   rv   curve_idr   kdfrR   r   r1   c                 C  s^   | d}| d}|tkrtd|tkrtdt| d}t| d}| ||||S )NrF   rf   zscheme is expected to be NULL)rN   rj   rL   rv   r   )rQ   rR   rb   rc   r   
kdf_schemer&   r&   r'   r]   J  s   

zTpmsEccParms.parseN)rR   r   r1   r   )r   r    r!   r?   r`   r]   r&   r&   r&   r'   r   C  s   
 r   c                   @  s0   e Zd ZU dZded< ded< eddd	Zd
S )TpmsEccPointzTPMS_ECC_POINT
    https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
    Section 11.2.5.2
    r<   rI   yrR   r   r1   c                 C  s*   | |d}| |d}| ||S rt   ru   )rQ   rR   rI   r   r&   r&   r'   r]   c  s   
zTpmsEccPoint.parseN)rR   r   r1   r   r^   r&   r&   r&   r'   r   Y  s   
 r   c                   @  s@   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdS )rg   zObject attributes
    see section 8.3
      https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
    r   r-   r   rz   @      i   i   i   i   i   l   	s N)r   r    r!   r_   	FIXED_TPMST_CLEARFIXED_PARENTSENSITIVE_DATA_ORIGINUSER_WITH_AUTHADMIN_WITH_POLICYNO_DAENCRYPTED_DUPLICATIONrh   ri   rk   SHALL_BE_ZEROr&   r&   r&   r'   rg   k  s    rg   r   
_PublicKeyc                   @  sl   e Zd ZU dZded< ded< ded< ded	< d
ed< ded< ded< edddZdddZdddZdS )TpmPublicFormata  the public area structure is defined by [TPMv2-Part2] Section 12.2.4
    (TPMT_PUBLIC)
    as:
      TPMI_ALG_PUBLIC - type
      TPMI_ALG_HASH - nameAlg
        or + to indicate TPM_ALG_NULL
      TPMA_OBJECT - objectAttributes
      TPM2B_DIGEST - authPolicy
      TPMU_PUBLIC_PARMS - type parameters
      TPMU_PUBLIC_ID - uniq
    See:
      https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
    r(   sign_algr,   name_algrC   rl   r<   auth_policy_Parameters
parameters_Uniquer   rA   r1   c           
      C  s   t |}t|d}t|d}|d}|tj@ dkr&td|d||d}|tjkr?t	
||}t
|}n|tjkrOt
|}t
|}n	td|dd| }	t|	dkrftd| |||||||S )	NrF   rG   r   z(attributes is not formated correctly: 0xrI   z	sign alg z is not supportedz+there should not be any data left in buffer)r   r(   rN   r,   rg   r   rL   rJ   r*   ra   r]   rs   r+   r   r   r7   len)
rQ   rA   rR   r   r   rl   r   r   r   restr&   r&   r'   r]     s(   



zTpmPublicFormat.parser   c                 C  s   | j tjkrtt| jj}ttt| j	}t
||t S | j tjkrCtt| j	}tt|jt|jtt| jj t S td| j )Nzpublic_key not implemented for )r   r(   r*   r   ra   r   re   r   rs   r   r   RSAPublicNumbers
public_keyr
   r+   r   r   EllipticCurvePublicNumbersrI   r   r   r   r   r7   )r9   re   modulusr   r&   r&   r'   r     s   zTpmPublicFormat.public_keyc                 C  s@   t d| j}tj| j t d}|| j ||	 7 }|S )u  
        Computing Entity Names

        see:
          https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-1-Architecture-01.38.pdf
        section 16 Names

        Name ≔ nameAlg || HnameAlg (handle→nvPublicArea)
          where
            nameAlg algorithm used to compute Name
            HnameAlg hash using the nameAlg parameter in the NV Index location
                     associated with handle
            nvPublicArea contents of the TPMS_NV_PUBLIC associated with handle
        rF   backend)
rO   packr   r   Hashr:   r
   updaterA   finalize)r9   outputdigestr&   r&   r'   r=     s
   zTpmPublicFormat.nameN)rA   r<   r1   r   )r1   r   )r1   r<   )	r   r    r!   r_   r?   r`   r]   r   r=   r&   r&   r&   r'   r     s   
 
r   c                 C  sj   t |  t| jdkrtd| jtj}|std| jtj}dd |j	D }d|vr3tdd S )Nr   z#Certificate should not have Subjectz.Certificate should have SubjectAlternativeNamec                 S  s   g | ]}|t kqS r&   )OID_AIK_CERTIFICATE).0rI   r&   r&   r'   
<listcomp>  s    z&_validate_tpm_cert.<locals>.<listcomp>TzExtended key usage MUST contain the "joint-iso-itu-t(2) internationalorganizations(23) 133 tcg-kp(8) tcg-kp-AIKCertificate(3)" OID.)
r   r   subjectr   
extensionsget_extension_for_classr   SubjectAlternativeNameExtendedKeyUsagevalue)certsexthas_aikr&   r&   r'   _validate_tpm_cert  s   r   c                   @  s   e Zd ZdZedd ZdS )TpmAttestationtpmc              
   C  sV  d|v rt d|d }|d }|d }t|d t }t| t|| }z	t	
|d }	W n tyE }
 ztd|
d }
~
ww |jd usMJ |jj|	 |jjkr^td	zAt
|}|| }|j}tj|t d
}|| | }|j|krtd|jj|	 krtd|||d  ttj|W S  ty   tdw )N
ecdaaKeyIdzECDAA not implementedalgx5ccertInfor   pubAreazunable to parse pubAreaz9attestation pubArea does not match attestedCredentialDatar   z5attestation does not sign for authData and ClientDataz;TPMS_CERTIFY_INFO does not include a valid name for pubAreasigz$signature of certInfo does not match)r7   r   load_der_x509_certificater
   r   r   for_algfrom_cryptography_keyr   r   r]   	Exceptionr   credential_datar	   r@   	_HASH_ALGr   r   r   r   rA   rE   r=   verifyr   r   ATT_CA_InvalidSignature)r9   	statement	auth_dataclient_data_hashr   r   	cert_infor   pub_keypub_arear\   r   att_to_be_signedhash_algr   rA   r&   r&   r'   r     sV   



zTpmAttestation.verifyN)r   r    r!   FORMATr   r   r&   r&   r&   r'   r     s    r   )>
__future__r   rO   dataclassesr   enumr   r   typingr   r   cryptographyr   cryptography.exceptionsr	   r   cryptography.hazmat.backendsr
   cryptography.hazmat.primitivesr   )cryptography.hazmat.primitives.asymmetricr   r   coser   utilsr   r   baser   r   r   r   r   r   rj   ObjectIdentifierr   r   r(   r,   r;   rK   rM   r@   ra   r<   rs   rv   r   r   r   rg   RSAPublicKeyEllipticCurvePublicKeyr   r?   r   r   r   r   r   r&   r&   r&   r'   <module>   s^   $

QT![