
    ,                     h    S r SSKrSSKrSSKrSSKrSSKJr  SSKJr  S r\4S jr	 " S S\
5      rg)	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                 *    U S   S:X  a
  U S   S:X  a  gg)N
usage_pagei  usage   TF )devices    %lib/third_party/pyu2f/hidtransport.pyHidUsageSelectorr      s     LV#w4(?	    c              #      #    [         R                  " 5        H9  nU " U5      (       d  M   [         R                  " US   5      n[        U5      v   M;     g ! [         a     MK  f = f7f)Npath)r   	EnumerateOpenUsbHidTransportOSError)selectorddevs      r   DiscoverLocalHIDU2FDevicesr   #   sS     ==?a{{hhqy!c""	 
  s(   $A'&AA'
A$ A'#A$$A'c                       \ rS rSrSrSrSrSrSrSr	Sr
S	rS
r\" / SQ5      r\" S/5      r " S S\5      r " S S\5      rSS jrS rS rS rS rS rS rS rS rS rS rSrg)r   .   aa  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                   4    \ rS rSrSrS rS r\S 5       rSr	g)UsbHidTransport.InitPacketE   aS  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                    Xl         [        U5      S:w  d  US:  d  US:  a  [        R                  " 5       e[        U5      U R                   S-
  :  a  [        R                  " 5       eX l        X0l        X@l        XPl        g )N   r"   i      )packet_sizelenr   InvalidPacketErrorcidcmdsizepayload)selfr*   r-   r.   r/   r0   s         r   __init__#UsbHidTransport.InitPacket.__init__V   sh    $	SQ#)tu}''))	W((1,	,''))hhilr   c                    [        S5      nU R                  USS& U R                  US'   [        R                  " SUSU R
                  5        U R                  USS[        U R                  5      -   & [        [        [        U5      5      $ )Serializes the packet.@   r   r(   >H   r)   )	bytearrayr-   r.   struct	pack_intor/   r0   r+   listmapintr1   rets     r   ToWireFormat'UsbHidTransport.InitPacket.ToWireFormatb   sn    bMcc!Ahxxc!ftS!TYY/%)\\c!ADLL!!"#c3-  r   c                     [        U5      n[        U5      U :w  a  [        R                  " 5       eUSS nUS   n[        R
                  " S[        USS 5      5      S   nUSSU-    n[        R                  XXEU5      $ )a7  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(   r7   r8   r)   )	r9   r+   r   r,   r:   unpackbytesr   
InitPacket)r*   databar-   r.   r/   r0   s          r   FromWireFormat)UsbHidTransport.InitPacket.FromWireFormatk   s      T?b	RK	''))qGcqEc]]4r!Aw03d1QXg''#WMMr   )r-   r.   r*   r0   r/   N
__name__
__module____qualname____firstlineno____doc__r2   rA   staticmethodrI   __static_attributes__r	   r   r   rF   r%   E   s'     
! N Nr   rF   c                   4    \ rS rSrSrS rS r\S 5       rSr	g)UsbHidTransport.ContPacketr   ac  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                     Xl         X l        X0l        X@l        [	        U5      U R                   S-
  :  a  [
        R                  " 5       eUS:  a  [
        R                  " 5       eg )Nr8      )r*   r-   seqr0   r+   r   r,   )r1   r*   r-   rW   r0   s        r   r2   #UsbHidTransport.ContPacket.__init__   sX    $hhl	W((1,	,''))	s'')) 
r   c                     [        U R                  5      nU R                  USS& U R                  US'   U R                  USS[        U R                  5      -   & [        [        [        U5      5      $ )r5   r   r(   r8   )	r9   r*   r-   rW   r0   r+   r<   r=   r>   r?   s     r   rA   'UsbHidTransport.ContPacket.ToWireFormat   s]    d&&'cc!Ahxxc!f%)\\c!ADLL!!"#c3-  r   c                     [        U5      n[        U5      U :w  a  [        R                  " 5       eUSS nUS   nUSS n[        R                  XXE5      $ )a7  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(   r8   N)r9   r+   r   r,   r   
ContPacket)r*   rG   rH   r-   rW   r0   s         r   rI   )UsbHidTransport.ContPacket.FromWireFormat   s\      T?b	RK	''))qGcqEc
 12g''#GGr   )r-   r*   r0   rW   NrK   r	   r   r   r\   rT      s'     *! H Hr   r\   c                 ,   Xl         UR                  5       nUR                  5       nX4:w  a  [        R                  " S5      eUS:X  a  [        R                  " S5      eX0l        X l        [        R                  " S5      U l	        U R                  5         g )Nz6unsupported device with different in/out packet sizes.r   zunable to determine packet sizezpyu2f.hidtransport)
hid_deviceGetInReportDataLengthGetOutReportDataLengthr   HardwareErrorr*   read_timeout_secslogging	getLoggerloggerInternalInit)r1   r_   rc   in_sizeout_sizes        r   r2   UsbHidTransport.__init__   s     O..0G002H  
BD D!|  !BCC.##$89DKr   c                 F    U R                  [        R                  U5      nU$ N)InternalExchanger   
U2FHID_MSG)r1   msgrs      r   SendMsgBytesUsbHidTransport.SendMsgBytes   s    o88#>AHr   c                 V    U R                  [        R                  [        U/5      5      $ rl   )rm   r   U2FHID_PROMPTr9   )r1   lengths     r   	SendBlinkUsbHidTransport.SendBlink   s'      !>!>!*F8!46 6r   c                 T    U R                  [        R                  [        / 5      5      $ rl   )rm   r   U2FHID_WINKr9   )r1   s    r   SendWinkUsbHidTransport.SendWink   s      !<!<imLLr   c                 B    U R                  [        R                  U5      $ rl   )rm   r   U2FHID_PING)r1   rG   s     r   SendPingUsbHidTransport.SendPing   s      !<!<dCCr   c                 n   [         R                  U l        [        [        R
                  " S5      5      nU R                  [         R                  U5      n[        U5      S:  a  [        R                  " S5      eUSS U:w  a  [        R                  " S5      e[        USS 5      U l        US   U l        g)z.Initializes the device and obtains channel id.      zunexpected init reply lenr   znonce mismatch   N)r   U2FHID_BROADCAST_CIDr-   r9   osurandomrm   U2FHID_INITr+   r   HidErroru2fhid_version)r1   noncerp   s      r   rg   UsbHidTransport.InternalInit   s    33DHbjjm$Eo995AA
1v{OO7881vOO,--1R!DHB%Dr   c                    U R                   R                  S[        [        U5      5      -   5        [	        5       nX#SS& [        S5       H  nU R                  X5        U R                  5       u  pVU[        R                  :X  aQ  U[        R                  :X  a  [        R                  " S5        Mf  [        R                  " S[        US   5      -  5      eXQ:w  a  [        R                  " S5      eUs  $    [        R                  " S5      e)	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)rf   debugstrr<   r9   rangeInternalSendInternalRecvr   U2FHID_ERRORERR_CHANNEL_BUSYtimesleepr   r   r>   )r1   r.   
payload_inr0   _ret_cmdret_payloads          r   rm    UsbHidTransport.InternalExchange   s     	KKkCZ(8$99:kGAJ1X
%!..0g	O00	0/:::
**S/
oo03{1~3FFGG>oo122  //6
77r   c                    [        U5      nU R                  S-
  nUSU n[        R                  U R                  U R                  U[        U5      U5      nUSU2	 U[        U5      -  nU R                  U5        SnUS:  ar  U R                  S-
  nUSU nUSU2	 U[        U5      -  n[        R                  U R                  U R                  UU5      n	U R                  U	5        US-  nUS:  a  Mq  gg)z8Sends a message to the device, including fragmenting it.r)   r   r8   r   N)r+   r*   r   rF   r-   InternalSendPacketr\   )
r1   r.   r0   length_to_sendmax_payloadfirst_framefirst_packetrW   
next_framenext_packets
             r   r   UsbHidTransport.InternalSend  s   \N""Q&K!K(K"--d.>.>#.1'lKIL+c+&&NL)
C
1
$$q(k1[)j
!K-
 J'n#..t/?/?3/9;k
k*	Qhc 1
r   c                     UR                  5       nU R                  R                  S[        U5      -   5        U R                  R                  U5        g )Nzsending packet: )rA   rf   r   r   r_   Write)r1   packetwires      r   r   "UsbHidTransport.InternalSendPacket  s>     DKK(3t945OO$r   c                     U R                   R                  5       nU R                  R                  S[	        U5      -   5        U$ )Nzrecv: )r_   Readrf   r   r   )r1   frames     r   InternalReadFrame!UsbHidTransport.InternalReadFrame   s6    
 OO  "EKKhU+,Lr   c                    U R                  5       n[        R                  R                  U R                  U5      nUR
                  nUR                  [        UR
                  5      -
  nSnUS:  a  U R                  5       n[        R                  R                  U R                  U5      nU R                  UR                  :w  a  M\  XWR                  :w  a  [        R                  " S5      eU[        UR
                  5      -  nUR                  UR
                  5        US-  nUS:  a  M  USUR                   nUR                  U4$ )z?Receives a message from the device, including defragmenting it.r   zPackets received out of orderr   )r   r   rF   rI   r*   r0   r/   r+   r\   r-   rW   r   rb   extendr.   )r1   
first_readr   rG   to_readrW   	next_readr   s           r   r   UsbHidTransport.InternalRecv)  s'   '')J"--<<T=M=M=GIL D#l&:&:";;G
C
A+((*i#..==d>N>N>GIk	[__	$ 			""#BCC [(())g
kk+%%&	Qhc) A+. ,##$Dd##r   )r-   r_   rf   r*   rc   r   N)g      @)rL   rM   rN   rO   rP   r}   rn   ry   rt   r   U2FHID_LOCKr   U2FHID_SYNCr9   r   r   objectrF   r\   r2   rq   rv   rz   r~   rg   rm   r   r   r   r   rR   r	   r   r   r   r   .   s     +*+-++,+"#;<v&=N6 =N~=H6 =H~"6MD 8*. 
"$r   r   )rP   rd   r   r:   r   pyu2fr   r   r   r   r   r   r	   r   r   <module>r      s;   
  	     )9 ]$f ]$r   