o
    _,                     @   sd   d Z ddlZddlZddlZddlZddlmZ ddlmZ dd ZefddZ	G d	d
 d
e
ZdS )zHID Transport for U2F.

This module imports the U2F HID Transport protocol as well as methods
for discovering devices implementing this protocol.
    N)errors)hidc                 C   s    | d dkr| d dkrdS dS )NZ
usage_pagei  usage   TF )Zdevicer   r   2lib/python3.10/site-packages/pyu2f/hidtransport.pyHidUsageSelector   s   r   c              	   c   sL    t  D ]}| |r#zt |d }t|V  W q ty"   Y qw qd S )Npath)r   Z	EnumerateZOpenUsbHidTransportOSError)selectorddevr   r   r   DiscoverLocalHIDU2FDevices#   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eg d
ZedgZG dd deZG dd deZd(ddZdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'S ))r
   am  Implements the U2FHID transport protocol.

  This class implements the U2FHID transport protocol from the
  FIDO U2F specs.  This protocol manages fragmenting longer messages
  over a short hid frame (usually 64 bytes).  It exposes an APDU
  channel through the MSG command as well as a series of other commands
  for configuring and interacting with the device.
                          )   r   r   r      c                   @   ,   e Zd ZdZdd Zdd Zedd ZdS )	zUsbHidTransport.InitPacketa  Represent an initial U2FHID packet.

    Represent an initial U2FHID packet.  This packet contains
    metadata necessary to interpret the entire packet stream associated
    with a particular exchange (read or write).

    Attributes:
      packet_size: The size of the hid report (packet) used.  Usually 64.
      cid: The channel id for the connection to the device.
      size: The size of the entire message to be sent (including
          all continuation packets)
      payload: The portion of the message to put into the init packet.
          This must be smaller than packet_size - 7 (the overhead for
          an init packet).
    c                 C   s`   || _ t|dks|dks|dkrt t|| j d kr"t || _|| _|| _|| _d S )N   r   i      )packet_sizelenr   InvalidPacketErrorcidcmdsizepayload)selfr   r    r!   r"   r#   r   r   r   __init__V   s   
z#UsbHidTransport.InitPacket.__init__c                 C   sX   t d}| j|dd< | j|d< td|d| j | j|ddt| j < tt	t
|S )Serializes the packet.@   r   r   >H   r   )	bytearrayr    r!   struct	pack_intor"   r#   r   listmapintr$   retr   r   r   ToWireFormatb   s   
z'UsbHidTransport.InitPacket.ToWireFormatc                 C   sn   t |}t|| krt |dd }|d }tdt|dd d }|dd|  }t| ||||S )am  Derializes the packet.

      Deserializes the packet from wire format.

      Args:
        packet_size: The size of all packets (usually 64)
        data: List of ints or bytearray containing the data from the wire.

      Returns:
        InitPacket object for specified data

      Raises:
        InvalidPacketError: if the data isn't a valid InitPacket
      r   r   r(   r)   r   )	r*   r   r   r   r+   unpackbytesr
   
InitPacket)r   databar    r!   r"   r#   r   r   r   FromWireFormatk   s   z)UsbHidTransport.InitPacket.FromWireFormatN__name__
__module____qualname____doc__r%   r2   staticmethodr8   r   r   r   r   r5   E   s    	r5   c                   @   r   )	zUsbHidTransport.ContPacketa  Represents a continutation U2FHID packet.

    Represents a continutation U2FHID packet.  These packets follow
    the intial packet and contains the remaining data in a particular
    message.

    Attributes:
      packet_size: The size of the hid report (packet) used.  Usually 64.
      cid: The channel id for the connection to the device.
      seq: The sequence number for this continuation packet.  The first
          continuation packet is 0 and it increases from there.
      payload:  The payload to put into this continuation packet.  This
          must be less than packet_size - 5 (the overhead of the
          continuation packet is 5).
    c                 C   sF   || _ || _|| _|| _t|| j d krt |dkr!t d S )Nr)      )r   r    seqr#   r   r   r   )r$   r   r    r@   r#   r   r   r   r%      s   z#UsbHidTransport.ContPacket.__init__c                 C   sH   t | j}| j|dd< | j|d< | j|ddt| j < ttt|S )r&   r   r   r)   )	r*   r   r    r@   r#   r   r-   r.   r/   r0   r   r   r   r2      s
   

z'UsbHidTransport.ContPacket.ToWireFormatc                 C   sL   t |}t|| krt |dd }|d }|dd }t| |||S )am  Derializes the packet.

      Deserializes the packet from wire format.

      Args:
        packet_size: The size of all packets (usually 64)
        data: List of ints or bytearray containing the data from the wire.

      Returns:
        InitPacket object for specified data

      Raises:
        InvalidPacketError: if the data isn't a valid ContPacket
      r   r   r)   N)r*   r   r   r   r
   
ContPacket)r   r6   r7   r    r@   r#   r   r   r   r8      s   z)UsbHidTransport.ContPacket.FromWireFormatNr9   r   r   r   r   rA      s    
rA         @c                 C   s^   || _ | }| }||krtd|dkrtd|| _|| _td| _	| 
  d S )Nz6unsupported device with different in/out packet sizes.r   zunable to determine packet sizezpyu2f.hidtransport)
hid_deviceZGetInReportDataLengthZGetOutReportDataLengthr   HardwareErrorr   read_timeout_secsloggingZ	getLoggerloggerInternalInit)r$   rC   rE   Zin_sizeZout_sizer   r   r   r%      s   
zUsbHidTransport.__init__c                 C   s   |  tj|}|S N)InternalExchanger
   
U2FHID_MSG)r$   msgrr   r   r   SendMsgBytes   s   zUsbHidTransport.SendMsgBytesc                 C   s   |  tjt|gS rI   )rJ   r
   U2FHID_PROMPTr*   )r$   lengthr   r   r   	SendBlink   s   zUsbHidTransport.SendBlinkc                 C   s   |  tjtg S rI   )rJ   r
   U2FHID_WINKr*   )r$   r   r   r   SendWink   s   zUsbHidTransport.SendWinkc                 C   s   |  tj|S rI   )rJ   r
   U2FHID_PING)r$   r6   r   r   r   SendPing   s   zUsbHidTransport.SendPingc                 C   st   t j| _ttd}| t j|}t|dk rt	
d|dd |kr*t	
dt|dd | _|d | _dS )z.Initializes the device and obtains channel id.      zunexpected init reply lenr   znonce mismatch   N)r
   U2FHID_BROADCAST_CIDr    r*   osurandomrJ   U2FHID_INITr   r   HidErrorZu2fhid_version)r$   ZnoncerM   r   r   r   rH      s   

zUsbHidTransport.InternalInitc                 C   s   | j dtt|  t }||dd< tdD ]5}| || |  \}}|tj	krB|tj
kr7td qtdt|d  ||krKtd|  S td)	z-Sends and receives a message from the device.z	payload: N   g      ?zDevice error: %dr   zCommand mismatch!zDevice Busy.  Please retry)rG   debugstrr-   r*   rangeInternalSendInternalRecvr
   U2FHID_ERRORERR_CHANNEL_BUSYtimesleepr   r]   r/   )r$   r!   Z
payload_inr#   _Zret_cmdZret_payloadr   r   r   rJ      s   




z UsbHidTransport.InternalExchangec           
      C   s   t |}| jd }|d| }t| j| j|t ||}|d|= |t |8 }| | d}|dkra| jd }|d| }|d|= |t |8 }t| j| j||}	| |	 |d7 }|dks2dS dS )z8Sends a message to the device, including fragmenting it.r   r   r)   r   N)r   r   r
   r5   r    InternalSendPacketrA   )
r$   r!   r#   Zlength_to_sendZmax_payloadZfirst_framefirst_packetr@   Z
next_framenext_packetr   r   r   rb     s*   





zUsbHidTransport.InternalSendc                 C   s,   |  }| jdt|  | j| d S )Nzsending packet: )r2   rG   r_   r`   rC   ZWrite)r$   ZpacketZwirer   r   r   ri     s   z"UsbHidTransport.InternalSendPacketc                 C   s"   | j  }| jdt|  |S )Nzrecv: )rC   ZReadrG   r_   r`   )r$   framer   r   r   InternalReadFrame   s   
z!UsbHidTransport.InternalReadFramec                 C   s   |   }tj| j|}|j}|jt|j }d}|dkrO|   }tj| j|}| j	|j	kr0q||j
kr:td|t|j8 }||j |d7 }|dks|d|j }|j|fS )z?Receives a message from the device, including defragmenting it.r   zPackets received out of orderr   )rm   r
   r5   r8   r   r#   r"   r   rA   r    r@   r   rD   extendr!   )r$   Z
first_readrj   r6   Zto_readr@   Z	next_readrk   r   r   r   rc   )  s,   




zUsbHidTransport.InternalRecvN)rB   )r:   r;   r<   r=   rT   rK   rR   rO   r\   ZU2FHID_LOCKrd   ZU2FHID_SYNCr*   rY   re   objectr5   rA   r%   rN   rQ   rS   rU   rH   rJ   rb   ri   rm   rc   r   r   r   r   r
   .   s2    	
?
?	r
   )r=   rF   rZ   r+   rf   Zpyu2fr   r   r   r   ro   r
   r   r   r   r   <module>   s   