o
    sh<                     @  sN  d dl mZ ddlmZmZ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 d d
lmZmZmZ d dlmZ d dlmZmZmZ d dlmZ d dlmZ d dlm Z m!Z!m"Z"m#Z#m$Z$m%Z% d dl&Z&d dl'Z'd dl(Z(e()e*Z+d!ddZ,G dd de&j-Z.eG dd dZ/G dd de.Z0G dd de0Z1G dd  d Z2dS )"    )annotations   )sha256hmac_sha256	bytes2int	int2bytes)CoseKey   )Ctap2)default_backend)hashes)ec)Cipher
algorithmsmodes)HKDF)IntEnumIntFlagunique)	dataclass)Event)OptionalAnyMappingClassVarTupleCallableNpinstrreturnbytesc                 C  sn   t | tstdt t| dk rtd|  dd}|dt|d  d  7 }t|dkr5td|S )	NzPIN of wrong type, expecting    zPIN must be >= 4 characters@             zPIN must be <= 255 bytes)
isinstancer   
ValueErrorlenencodeljust)r   
pin_padded r,   J/var/www/html/env_mimamsha/lib/python3.10/site-packages/fido2/ctap2/pin.py_pad_pin4   s   
r.   c                   @  sf   e Zd ZU ded< ejdddZejdddZejdddZejdddZ	ejdddZ
dS )PinProtocolzClassVar[int]VERSIONpeer_cose_keyr   r   Tuple[Mapping[int, Any], bytes]c                 C     dS )zuGenerates an encapsulation of the public key.
        Returns the message to transmit and the shared secret.
        Nr,   )selfr1   r,   r,   r-   encapsulateC       zPinProtocol.encapsulatekeyr    	plaintextc                 C  r3   )zEncrypts dataNr,   )r4   r7   r8   r,   r,   r-   encryptI   r6   zPinProtocol.encrypt
ciphertextc                 C  r3   )zDecrypts encrypted dataNr,   )r4   r7   r:   r,   r,   r-   decryptM   r6   zPinProtocol.decryptmessagec                 C  r3   )z$Computes a MAC of the given message.Nr,   r4   r7   r<   r,   r,   r-   authenticateQ   r6   zPinProtocol.authenticatetokenc                 C  r3   )znValidates that a token is well-formed.
        Returns the token, or if invalid, raises a ValueError.
        Nr,   r4   r?   r,   r,   r-   validate_tokenU   r6   zPinProtocol.validate_tokenN)r1   r   r   r2   )r7   r    r8   r    r   r    )r7   r    r:   r    r   r    )r7   r    r<   r    r   r    )r?   r    r   r    )__name__
__module____qualname____annotations__abcabstractmethodr5   r9   r;   r>   rA   r,   r,   r,   r-   r/   @   s   
 r/   c                   @  s   e Zd ZU ded< ded< dS )_PinUvr/   protocolr    r?   N)rB   rC   rD   rE   r,   r,   r,   r-   rH   \   s   
 rH   c                   @  sR   e Zd ZdZdZdZdddZd	d
 Zdd Zdd Z	dd Z
dd Zdd ZdS )PinProtocolV1zImplementation of the CTAP2 PIN/UV protocol v1.

    :param ctap: An instance of a CTAP2 object.
    :cvar VERSION: The version number of the PIV/UV protocol.
    :cvar IV: An all-zero IV used for some cryptographic operations.
    r	   s                   zr    r   c                 C  s   t |S N)r   )r4   rK   r,   r,   r-   kdfm   s   zPinProtocolV1.kdfc           
      C  s   t  }tt |}|  }dddt|jdt|jdd}t	|d }t	|d }t
||t |}| |t |}	||	fS )Nr   ir	       )r	      rQ   rR   )r   r   generate_private_key	SECP256R1
public_keypublic_numbersr   xyr   EllipticCurvePublicNumbersrM   exchangeECDH)
r4   r1   beskpnkey_agreementrW   rX   pkshared_secretr,   r,   r-   r5   p   s   

zPinProtocolV1.encapsulatec                 C  s    t  }tt|ttj|S rL   )r   r   r   AESr   CBCrJ   IV)r4   secretr\   r,   r,   r-   _get_cipher_v1   s   zPinProtocolV1._get_cipher_v1c                 C  $   |  |}| }|||  S rL   )rf   	encryptorupdatefinalize)r4   r7   r8   cipherencr,   r,   r-   r9         
zPinProtocolV1.encryptc                 C  rg   rL   )rf   	decryptorri   rj   )r4   r7   r:   rk   decr,   r,   r-   r;      rm   zPinProtocolV1.decryptc                 C  s   t ||d d S )Nr$   r   r=   r,   r,   r-   r>      s   zPinProtocolV1.authenticatec                 C  s   t |dvr
td|S )N)r$   rN   z#PIN/UV token must be 16 or 32 bytesr(   r'   r@   r,   r,   r-   rA         zPinProtocolV1.validate_tokenN)rK   r    r   r    )rB   rC   rD   __doc__r0   rd   rM   r5   rf   r9   r;   r>   rA   r,   r,   r,   r-   rJ   b   s    
rJ   c                   @  sP   e Zd ZdZdZdZdZdZdd Zdd	 Z	d
d Z
dd Zdd Zdd ZdS )PinProtocolV2zImplementation of the CTAP2 PIN/UV protocol v2.

    :param ctap: An instance of a CTAP2 object.
    :cvar VERSION: The version number of the PIV/UV protocol.
    :cvar IV: An all-zero IV used for some cryptographic operations.
    r   s                                    s   CTAP2 HMAC keys   CTAP2 AES keyc                 C  sN   t  }tt dtjtj|d|}tt dtjtj|d|}|| S )NrN   )	algorithmlengthsaltinfobackend)	r   r   r   SHA256rt   	HKDF_SALTHKDF_INFO_HMACderiveHKDF_INFO_AES)r4   rK   r\   hmac_keyaes_keyr,   r,   r-   rM      s(   zPinProtocolV2.kdfc                 C  s   t  }tt|t||S rL   )r   r   r   rb   r   rc   )r4   re   ivr\   r,   r,   r-   _get_cipher_v2   s   zPinProtocolV2._get_cipher_v2c                 C  s@   |dd  }t d}| ||}| }||| |  S NrN   r$   )osurandomr   rh   ri   rj   )r4   r7   r8   r   r   rk   rl   r,   r,   r-   r9      s
   
zPinProtocolV2.encryptc                 C  sL   |dd  }|d d |dd  }}|  ||}| }|||  S r   )r   rn   ri   rj   )r4   r7   r:   r   r   rk   ro   r,   r,   r-   r;      s
   zPinProtocolV2.decryptc                 C  s   |d d }t ||S )NrN   rp   )r4   r7   r<   r   r,   r,   r-   r>      s   
zPinProtocolV2.authenticatec                 C  s   t |dkr
td|S )NrN   zPIN/UV token must be 32 bytesrq   r@   r,   r,   r-   rA      rr   zPinProtocolV2.validate_tokenN)rB   rC   rD   rs   r0   r{   r|   r~   rM   r   r9   r;   r>   rA   r,   r,   r,   r-   rt      s    rt   c                   @  s   e Zd ZdZeegZeG dd deZ	eG dd deZ
eG dd deZedd	 Zed
d Zd2d3ddZdd Z		d4d5ddZ				d6d7d#d$Zd8d&d'Zd9d)d*Zd:d,d-Zd;d0d1ZdS )<	ClientPina!  Implementation of the CTAP2 Client PIN API.

    :param ctap: An instance of a CTAP2 object.
    :param protocol: An optional instance of a PinUvAuthProtocol object. If None is
        provided then the latest protocol supported by both library and Authenticator
        will be used.
    c                   @  s,   e Zd ZdZdZdZdZdZdZdZ	dZ
d	S )
zClientPin.CMDr	   r   rO   r!            	   N)rB   rC   rD   GET_PIN_RETRIESGET_KEY_AGREEMENTSET_PIN
CHANGE_PINGET_TOKEN_USING_PIN_LEGACYGET_TOKEN_USING_UVGET_UV_RETRIESGET_TOKEN_USING_PINr,   r,   r,   r-   CMD   s    r   c                   @  s    e Zd ZdZdZdZdZdZdS )zClientPin.RESULTr	   r   rO   r!   r   N)rB   rC   rD   KEY_AGREEMENTPIN_UV_TOKENPIN_RETRIESPOWER_CYCLE_STATE
UV_RETRIESr,   r,   r,   r-   RESULT   s    r   c                   @  s$   e Zd ZdZdZdZdZdZdZdS )zClientPin.PERMISSIONr	   r   r!      r$   rN   N)	rB   rC   rD   MAKE_CREDENTIALGET_ASSERTIONCREDENTIAL_MGMT
BIO_ENROLLLARGE_BLOB_WRITEAUTHENTICATOR_CFGr,   r,   r,   r-   
PERMISSION   s    r   c                 C  s
   d| j v S )zChecks if ClientPin functionality is supported.

        Note that the ClientPin function is still usable without support for client
        PIN functionality, as UV token may still be supported.
        	clientPin)optionsrx   r,   r,   r-   is_supported   s   
zClientPin.is_supportedc                 C  s   | j ddu S )z&Checks if pinUvAuthToken is supported.pinUvAuthTokenT)r   getr   r,   r,   r-   is_token_supported  s   zClientPin.is_token_supportedNctapr
   rI   Optional[PinProtocol]c                 C  sH   || _ |d u rtjD ]}|j|jjv r| | _ d S q
td|| _d S )Nz)No compatible PIN/UV protocols supported!)r   r   	PROTOCOLSr0   rx   pin_uv_protocolsrI   r'   )r4   r   rI   protor,   r,   r-   __init__
  s   

zClientPin.__init__c                 C  s.   | j | jjtjj}|tjj }| j	|S rL   )
r   
client_pinrI   r0   r   r   r   r   r   r5   )r4   respr`   r,   r,   r-   _get_shared_secret  s
   zClientPin._get_shared_secretr   r   permissionsOptional[ClientPin.PERMISSION]permissions_rpidOptional[str]r   r    c                 C  s   t | jjstd|  \}}t| dd }| j	||}t 
| jjr0|r0t jj}nt jj}d}d}| jj| jj|||||d}	|	t jj }
td|  | j| j||
S )a-  Get a PIN/UV token from the authenticator using PIN.

        :param pin: The PIN of the authenticator.
        :param permissions: The permissions to associate with the token.
        :param permissions_rpid: The permissions RPID to associate with the token.
        :return: A PIN/UV token.
        z,Authenticator does not support get_pin_tokenNr$   )r_   pin_hash_encr   r   zGot PIN token for permissions: )r   r   r   rx   r'   r   r   r)   rI   r9   r   r   r   r   r   r0   r   r   loggerdebugrA   r;   )r4   r   r   r   r_   ra   pin_hashr   cmdr   pin_token_encr,   r,   r-   get_pin_token  s.   
zClientPin.get_pin_tokeneventOptional[Event]on_keepaliveOptional[Callable[[int], None]]c           	   	   C  sv   t | jjstd|  \}}| jj| jjt j	j
|||||d}|t jj }td|  | j| j||S )aH  Get a PIN/UV token from the authenticator using built-in UV.

        :param permissions: The permissions to associate with the token.
        :param permissions_rpid: The permissions RPID to associate with the token.
        :param event: An optional threading.Event which can be used to cancel
            the invocation.
        :param on_keepalive: An optional callback to handle keep-alive messages
            from the authenticator. The function is only called once for
            consecutive keep-alive messages with the same status.
        :return: A PIN/UV token.
        z+Authenticator does not support get_uv_token)r_   r   r   r   r   zGot UV token for permissions: )r   r   r   rx   r'   r   r   rI   r0   r   r   r   r   r   r   rA   r;   )	r4   r   r   r   r   r_   ra   r   r   r,   r,   r-   get_uv_tokenI  s"   
zClientPin.get_uv_tokenTuple[int, Optional[int]]c                 C  s0   | j | jjtjj}|tjj |	tjj
fS )zGet the number of PIN retries remaining.

        :return: A tuple of the number of PIN attempts remaining until the
        authenticator is locked, and the power cycle state, if available.
        )r   r   rI   r0   r   r   r   r   r   r   r   r4   r   r,   r,   r-   get_pin_retriesp  s   
zClientPin.get_pin_retriesintc                 C  s"   | j | jjtjj}|tjj S )zGet the number of UV retries remaining.

        :return: A tuple of the number of UV attempts remaining until the
        authenticator is locked, and the power cycle state, if available.
        )	r   r   rI   r0   r   r   r   r   r   r   r,   r,   r-   get_uv_retries~  s   zClientPin.get_uv_retriesNonec                 C  sn   t | jjstd|  \}}| j|t|}| j	||}| jj
| jjt jj|||d td dS )zSet the PIN of the autenticator.

        This only works when no PIN is set. To change the PIN when set, use
        change_pin.

        :param pin: A PIN to set.
        (Authenticator does not support ClientPin)r_   new_pin_encpin_uv_paramzPIN has been setN)r   r   r   rx   r'   r   rI   r9   r.   r>   r   r0   r   r   r   )r4   r   r_   ra   pin_encr   r,   r,   r-   set_pin  s   zClientPin.set_pinold_pinnew_pinc           	      C  s   t | jjstd|  \}}t| dd }| j	||}| j	|t
|}| j||| }| jj| jjt jj||||d td dS )zChange the PIN of the authenticator.

        This only works when a PIN is already set. If no PIN is set, use
        set_pin.

        :param old_pin: The currently set PIN.
        :param new_pin: The new PIN to set.
        r   Nr$   )r_   r   r   r   zPIN has been changed)r   r   r   rx   r'   r   r   r)   rI   r9   r.   r>   r   r0   r   r   r   )	r4   r   r   r_   ra   r   r   r   r   r,   r,   r-   
change_pin  s$   	zClientPin.change_pinrL   )r   r
   rI   r   )NN)r   r   r   r   r   r   r   r    )NNNN)
r   r   r   r   r   r   r   r   r   r    )r   r   )r   r   )r   r   r   r   )r   r   r   r   r   r   )rB   rC   rD   rs   rt   rJ   r   r   r   r   r   r   r   staticmethodr   r   r   r   r   r   r   r   r   r   r,   r,   r,   r-   r      s6    


-
'

	r   )r   r   r   r    )3
__future__r   utilsr   r   r   r   coser   baser
   cryptography.hazmat.backendsr   cryptography.hazmat.primitivesr   )cryptography.hazmat.primitives.asymmetricr   &cryptography.hazmat.primitives.ciphersr   r   r   'cryptography.hazmat.primitives.kdf.hkdfr   enumr   r   r   dataclassesr   	threadingr   typingr   r   r   r   r   r   rF   r   logging	getLoggerrB   r   r.   ABCr/   rH   rJ   rt   r   r,   r,   r,   r-   <module>   s0    

7<