
    Dj<                       d dl mZ d dlZd dlZd dl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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 ddl m!Z!m"Z"m#Z#m$Z$ ddl%m&Z&  ej'        e(          Z)d dZ* G d dej+                  Z,e G d d                      Z- G d de,          Z. G d de.          Z/ G d d          Z0dS )!    )annotationsN)	dataclass)IntEnumIntFlagunique)Event)AnyCallableClassVarMapping)default_backend)hashes)ec)Cipher
algorithmsmodes)HKDF   )CoseKey)	bytes2inthmac_sha256	int2bytessha256   )Ctap2pinstrreturnbytesc                n   t          | t                    st          dt                     t          |           dk     rt          d          |                                                     dd          }|dt          |          dz
   dz  z  z  }t          |          dk    rt          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_paddeds     J/home/thesage/.hermes/venv/lib/python3.11/site-packages/fido2/ctap2/pin.py_pad_pinr-   3   s    c3 @>>>???
3xx!||6777##B..J%S__r12R788J
:3444    c                      e Zd ZU ded<   ej        dd            Zej        dd            Zej        dd            Zej        dd            Z	ej        dd            Z
dS )PinProtocolzClassVar[int]VERSIONpeer_cose_keyr   r   tuple[Mapping[int, Any], bytes]c                    dS )zuGenerates an encapsulation of the public key.
        Returns the message to transmit and the shared secret.
        N )selfr2   s     r,   encapsulatezPinProtocol.encapsulateB         r.   keyr   	plaintextc                    dS )zEncrypts dataNr5   )r6   r9   r:   s      r,   encryptzPinProtocol.encryptH   r8   r.   
ciphertextc                    dS )zDecrypts encrypted dataNr5   )r6   r9   r=   s      r,   decryptzPinProtocol.decryptL   r8   r.   messagec                    dS )z$Computes a MAC of the given message.Nr5   r6   r9   r@   s      r,   authenticatezPinProtocol.authenticateP   r8   r.   tokenc                    dS )znValidates that a token is well-formed.
        Returns the token, or if invalid, raises a ValueError.
        Nr5   r6   rD   s     r,   validate_tokenzPinProtocol.validate_tokenT   r8   r.   N)r2   r   r   r3   )r9   r   r:   r   r   r   )r9   r   r=   r   r   r   )r9   r   r@   r   r   r   )rD   r   r   r   )__name__
__module____qualname____annotations__abcabstractmethodr7   r<   r?   rC   rG   r5   r.   r,   r0   r0   ?   s            
 	    	& & & & 	3 3 3 3 	     r.   r0   c                  $    e Zd ZU ded<   ded<   dS )_PinUvr0   protocolr   rD   N)rH   rI   rJ   rK   r5   r.   r,   rO   rO   [   s%         LLLLLr.   rO   c                  F    e Zd ZdZdZdZddZd Zd	 Zd
 Z	d Z
d Z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                     t          |          S N)r   )r6   rS   s     r,   kdfzPinProtocolV1.kdfl   s    ayyr.   c                V   t                      }t          j        t          j                    |          }|                                                                }dddt          |j        d          t          |j        d          d}t          |d                   }t          |d                   }t          j
        ||t          j                                                  |          }|                     |                    t          j                    |                    }	||	fS )Nr   ir       )r      r[   r\   )r   r   generate_private_key	SECP256R1
public_keypublic_numbersr   xyr   EllipticCurvePublicNumbersrV   exchangeECDH)
r6   r2   beskpnkey_agreementra   rb   pkshared_secrets
             r,   r7   zPinProtocolV1.encapsulateo   s    $R\^^R88]]__++--"$##"$##
 
 mB'((mB'((*1a@@KKBOORWYY!;!;<<m++r.   c                    t                      }t          t          j        |          t	          j        t          j                  |          S rU   )r   r   r   AESr   CBCrR   IV)r6   secretrf   s      r,   _get_cipher_v1zPinProtocolV1._get_cipher_v1   s6    jnV,,ei8H.I.I2NNNr.   c                    |                      |          }|                                }|                    |          |                                z   S rU   )rq   	encryptorupdatefinalize)r6   r9   r:   cipherencs        r,   r<   zPinProtocolV1.encrypt   sE    $$S))  zz)$$s||~~55r.   c                    |                      |          }|                                }|                    |          |                                z   S rU   )rq   	decryptorrt   ru   )r6   r9   r=   rv   decs        r,   r?   zPinProtocolV1.decrypt   sE    $$S))  zz*%%66r.   c                2    t          ||          d d         S )Nr$   r   rB   s      r,   rC   zPinProtocolV1.authenticate   s    3(("--r.   c                F    t          |          dvrt          d          |S )N)r$   rX   z#PIN/UV token must be 16 or 32 bytesr(   r'   rF   s     r,   rG   zPinProtocolV1.validate_token   s'    u::X%%BCCCr.   N)rS   r   r   r   )rH   rI   rJ   __doc__r1   ro   rV   r7   rq   r<   r?   rC   rG   r5   r.   r,   rR   rR   a   s          G	B   , , ,$O O O6 6 6
7 7 7
. . .    r.   rR   c                  F    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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                X   t                      }t          t          j                    dt          j        t          j        |                              |          }t          t          j                    dt          j        t          j        |                              |          }||z   S )NrX   )	algorithmlengthsaltinfobackend)	r   r   r   SHA256r   	HKDF_SALTHKDF_INFO_HMACderiveHKDF_INFO_AES)r6   rS   rf   hmac_keyaes_keys        r,   rV   zPinProtocolV2.kdf   s    moo(-
 
 
 &)) 	 moo(,
 
 
 &)) 	 '!!r.   c                    t                      }t          t          j        |          t	          j        |          |          S rU   )r   r   r   rm   r   rn   )r6   rp   ivrf   s       r,   _get_cipher_v2zPinProtocolV2._get_cipher_v2   s1    jnV,,eimmR@@@r.   c                    |dd          }t          j        d          }|                     ||          }|                                }||                    |          z   |                                z   S NrX   r$   )osurandomr   rs   rt   ru   )r6   r9   r:   r   r   rv   rw   s          r,   r<   zPinProtocolV2.encrypt   sf    bcc(Z^^$$Wb11  CJJy)))CLLNN::r.   c                    |dd          }|d d         |dd          }}|                      ||          }|                                }|                    |          |                                z   S r   )r   ry   rt   ru   )r6   r9   r=   r   r   rv   rz   s          r,   r?   zPinProtocolV2.decrypt   sm    bcc(#CRC*RSS/J$$Wb11  zz*%%66r.   c                6    |d d         }t          ||          S )NrX   r|   )r6   r9   r@   r   s       r,   rC   zPinProtocolV2.authenticate   s    ss88W---r.   c                J    t          |          dk    rt          d          |S )NrX   zPIN/UV token must be 32 bytesr~   rF   s     r,   rG   zPinProtocolV2.validate_token   s'    u::<===r.   N)rH   rI   rJ   r   r1   r   r   r   rV   r   r<   r?   rC   rG   r5   r.   r,   r   r      s          GI&N$M" " "$A A A; ; ;7 7 7. . .    r.   r   c                     e Zd ZdZeegZe G d de                      Z	e G d de                      Z
e G d de                      Zed             Zed	             Zd(d)dZd Z	 	 d*d+dZ	 	 	 	 d,d-dZd.d Zd/d"Zd0d$Zd1d'Zd
S )2	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                  .    e Zd ZdZdZdZdZdZdZdZ	dZ
d	S )
ClientPin.CMDr   r   rY   r!            	   N)rH   rI   rJ   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_PINr5   r.   r,   CMDr      s<         
%)"!"r.   r   c                  "    e Zd ZdZdZdZdZdZdS )ClientPin.RESULTr   r   rY   r!   r   N)rH   rI   rJ   KEY_AGREEMENTPIN_UV_TOKENPIN_RETRIESPOWER_CYCLE_STATE
UV_RETRIESr5   r.   r,   RESULTr      s(         


r.   r   c                  *    e Zd ZdZdZdZdZdZdZdZ	dS )	ClientPin.PERMISSIONr   r   r!      r$   rX   r"   N)
rH   rI   rJ   MAKE_CREDENTIALGET_ASSERTIONCREDENTIAL_MGMT
BIO_ENROLLLARGE_BLOB_WRITEAUTHENTICATOR_CFGPERSISTENT_CREDENTIAL_MGMTr5   r.   r,   
PERMISSIONr      s6        
 %)"""r.   r   c                    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r   s    r,   is_supportedzClientPin.is_supported   s     dl**r.   c                :    | j                             d          du S )z&Checks if pinUvAuthToken is supported.pinUvAuthTokenT)r   getr   s    r,   is_token_supportedzClientPin.is_token_supported  s      | 011T99r.   Nctapr   rP   PinProtocol | Nonec                    || _         |Ct          j        D ]'}|j        |j        j        v r |            | _         d S (t          d          || _        d S )Nz)No compatible PIN/UV protocols supported!)r   r   	PROTOCOLSr1   r   pin_uv_protocolsrP   r'   )r6   r   rP   protos       r,   __init__zClientPin.__init__
  sj    	", N N=DI$>>>16DMEE ? !!LMMM$DMMMr.   c                    | j                             | j        j        t          j        j                  }|t          j        j                 }| j        	                    |          S rU   )
r   
client_pinrP   r1   r   r   r   r   r   r7   )r6   resprj   s      r,   _get_shared_secretzClientPin._get_shared_secret  sP    y##M!9=#B
 
 )"01}((,,,r.   r   r   permissionsClientPin.PERMISSION | Nonepermissions_rpid
str | Noner   r   c                   t                               | j        j                  st	          d          |                                 \  }}t          |                                          dd         }| j        	                    ||          }t           
                    | j        j                  r|t           j        j        }nt           j        j        }d}d}| j                            | j        j        |||||          }	|	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$   )ri   pin_hash_encr   r   zGot PIN token for permissions: )r   r   r   r   r'   r   r   r)   rP   r<   r   r   r   r   r   r1   r   r   loggerdebugrG   r?   )r6   r   r   r   ri   rk   pin_hashr   cmdr   pin_token_encs              r,   get_pin_tokenzClientPin.get_pin_token  sH    %%din55 	MKLLL'+'>'>'@'@$}#**,,'',},,]HEE''	77 	$K<S-3CC-:CK#y##M!'%#- $ 
 
 Y-:;D{DDEEE}++M!!-??
 
 	
r.   eventEvent | Noneon_keepaliveCallable[[int], None] | Nonec           	        t                               | j        j                  st	          d          |                                 \  }}| j                            | j        j        t           j	        j
        |||||          }|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)ri   r   r   r   r   zGot UV token for permissions: )r   r   r   r   r'   r   r   rP   r1   r   r   r   r   r   r   rG   r?   )	r6   r   r   r   r   ri   rk   r   r   s	            r,   get_uv_tokenzClientPin.get_uv_tokenI  s    $ ++DIN;; 	LJKKK'+'>'>'@'@$}y##M!M,'#-% $ 
 
 Y-:;CkCCDDD}++M!!-??
 
 	
r.   tuple[int, int | None]c                    | 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   rP   r1   r   r   r   r   r   r   r   r6   r   s     r,   get_pin_retrieszClientPin.get_pin_retriesp  sY     y##M!9=#@
 
 !-.HHY%788
 	
r.   intc                    | 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   rP   r1   r   r   r   r   r   r   s     r,   get_uv_retrieszClientPin.get_uv_retries~  s6     y##DM$99=;WXXI$/00r.   Nonec                   t                               | j        j                  st	          d          |                                 \  }}| j                            |t          |                    }| j        	                    ||          }| j        
                    | j        j        t           j        j        |||           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)ri   new_pin_encpin_uv_paramzPIN has been setN)r   r   r   r   r'   r   rP   r<   r-   rC   r   r1   r   r   r   )r6   r   ri   rk   pin_encr   s         r,   set_pinzClientPin.set_pin  s     %%din55 	IGHHH'+'>'>'@'@$}-''x}}EE}11-II	M!M!'% 	 	
 	
 	
 	&'''''r.   old_pinnew_pinc                T   t                               | j        j                  st	          d          |                                 \  }}t          |                                          dd         }| j        	                    ||          }| j        	                    |t          |                    }| j                            |||z             }| j                            | j        j        t           j        j        ||||           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$   )ri   r   r   r   zPIN has been changed)r   r   r   r   r'   r   r   r)   rP   r<   r-   rC   r   r1   r   r   r   )	r6   r   r   ri   rk   r   r   r   r   s	            r,   
change_pinzClientPin.change_pin  s    %%din55 	IGHHH'+'>'>'@'@$}'..**++CRC0},,]HEEm++M8G;L;LMM}11;5
 
 		M!M$'%#% 	 	
 	
 	
 	*+++++r.   rU   )r   r   rP   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   )rH   rI   rJ   r   r   rR   r   r   r   r   r   r   r   staticmethodr   r   r   r   r   r   r   r   r   r   r5   r.   r,   r   r      s         .I# # # # #g # # V#        V * * * * *W * * V* + + \+ : : \:
% 
% 
% 
% 
%- - - 48'+	)
 )
 )
 )
 )
Z 48'+"59%
 %
 %
 %
 %
N
 
 
 
1 1 1 1( ( ( (0, , , , , ,r.   r   )r   r   r   r   )1
__future__r   rL   loggingr   dataclassesr   enumr   r   r   	threadingr   typingr	   r
   r   r   cryptography.hazmat.backendsr   cryptography.hazmat.primitivesr   )cryptography.hazmat.primitives.asymmetricr   &cryptography.hazmat.primitives.ciphersr   r   r   'cryptography.hazmat.primitives.kdf.hkdfr   coser   utilsr   r   r   r   baser   	getLoggerrH   r   r-   ABCr0   rO   rR   r   r   r5   r.   r,   <module>r     s`  8 # " " " " " 



  				 ! ! ! ! ! ! ) ) ) ) ) ) ) ) ) )       3 3 3 3 3 3 3 3 3 3 3 3 8 8 8 8 8 8 1 1 1 1 1 1 8 8 8 8 8 8 L L L L L L L L L L 8 8 8 8 8 8       = = = = = = = = = = = =      		8	$	$	 	 	 	    #'   8        
4 4 4 4 4K 4 4 4n9 9 9 9 9M 9 9 9xg, g, g, g, g, g, g, g, g, g,r.   