o
    €ÏC  ã                   @   s8   d Z ddlZddlmZ ddlmZ G dd„ deƒZdS )z”This module implements the low level device API.

This module exposes a low level SecurityKey class,
representing the physical security key device.
é    N)Úapdu)Úerrorsc                   @   sT   e Zd ZdZdd„ Zdd„ Z	ddd„Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ ZdS )ÚSecurityKeyz‘Low level api for talking to a security key.

  This class implements the low level api specified in FIDO
  U2F for talking to a security key.
  c                 C   s   || _ d| _t d¡| _d S )NFzpyu2f.hardware)Ú	transportÚuse_legacy_formatÚloggingÚ	getLoggerÚlogger)Úselfr   © r   ú7/tmp/google-cloud-sdk/lib/third_party/pyu2f/hardware.pyÚ__init__!   s   zSecurityKey.__init__c              	   C   s`   | j  d¡ t|ƒdkst|ƒdkrt ¡ ‚t|| ƒ}|  t dtj	dd|¡¡}| 
¡  |jS )a2  Register security key.

    Ask the security key to register with a particular origin & client.

    Args:
      challenge_param: Arbitrary 32 byte challenge string.
      app_param: Arbitrary 32 byte applciation parameter.

    Returns:
      A binary structure containing the key handle, attestation, and a
      signature over that by the attestation key.  The precise format
      is dictated by the FIDO U2F specs.

    Raises:
      TUPRequiredError: A Test of User Precense is required to proceed.
      ApduError: Something went wrong on the device.
    ÚCmdRegisteré    r   é   )r	   ÚdebugÚlenr   ÚInvalidRequestErrorÚ	bytearrayÚInternalSendApdur   ÚCommandApduÚCMD_REGISTERÚCheckSuccessOrRaiseÚbody)r
   Úchallenge_paramÚ	app_paramr   Úresponser   r   r   r   &   s   ûzSecurityKey.CmdRegisterFc              	   C   s~   | j  d¡ t|ƒdkst|ƒdkrt ¡ ‚|rdnd}t|| tt|ƒgƒ | ƒ}|  t dtj	|d|¡¡}| 
¡  |jS )aä  Attempt to obtain an authentication signature.

    Ask the security key to sign a challenge for a particular key handle
    in order to authenticate the user.

    Args:
      challenge_param: SHA-256 hash of client_data object as a bytes
          object.
      app_param: SHA-256 hash of the app id as a bytes object.
      key_handle: The key handle to use to issue the signature as a bytes
          object.
      check_only: If true, only check if key_handle is valid.

    Returns:
      A binary structure containing the key handle, attestation, and a
      signature over that by the attestation key.  The precise format
      is dictated by the FIDO U2F specs.

    Raises:
      TUPRequiredError: If check_only is False, a Test of User Precense
          is required to proceed.  If check_only is True, this means
          the key_handle is valid.
      InvalidKeyHandleError: The key_handle is not valid for this device.
      ApduError: Something else went wrong on the device.
    ÚCmdAuthenticater   é   r   r   )r	   r   r   r   r   r   r   r   r   ÚCMD_AUTHr   r   )r
   r   r   Ú
key_handleÚ
check_onlyÚcontrolr   r   r   r   r   r   G   s   ÿÿÿzSecurityKey.CmdAuthenticatec                 C   sB   | j  d¡ |  t dtjdd¡¡}| ¡ st |j	|j
¡‚|jS )a†  Obtain the version of the device and test transport format.

    Obtains the version of the device and determines whether to use ISO
    7816-4 or the U2f variant.  This function should be called at least once
    before CmdAuthenticate or CmdRegister to make sure the object is using the
    proper transport for the device.

    Returns:
      The version of the U2F protocol in use.
    Ú
CmdVersionr   )r	   r   r   r   r   ÚCMD_VERSIONÚ	IsSuccessr   Ú	ApduErrorÚsw1Úsw2r   )r
   r   r   r   r   r#   r   s   
ÿzSecurityKey.CmdVersionc                 C   s   | j  d¡ | j |¡ d S )NÚCmdBlink)r	   r   r   Ú	SendBlink)r
   Útimer   r   r   r)   †   s   zSecurityKey.CmdBlinkc                 C   s   | j  d¡ | j ¡  d S )NÚCmdWink)r	   r   r   ÚSendWink)r
   r   r   r   r,   Š   s   zSecurityKey.CmdWinkc                 C   s   | j  d¡ | j |¡S )NÚCmdPing)r	   r   r   ÚSendPing)r
   Údatar   r   r   r.   Ž   s   zSecurityKey.CmdPingc                 C   sb   d}| j s$t | j | ¡ ¡¡}|jdkr"|jdkr"d| _ |  |¡S |S t | j | 	¡ ¡¡}|S )a,  Send an APDU to the device.

    Sends an APDU to the device, possibly falling back to the legacy
    encoding format that is not ISO7816-4 compatible.

    Args:
      apdu_to_send: The CommandApdu object to send

    Returns:
      The ResponseApdu object constructed out of the devices reply.
    Nég   r   T)
r   r   ÚResponseApdur   ÚSendMsgBytesÚToByteArrayr'   r(   r   ÚToLegacyU2FByteArray)r
   Úapdu_to_sendr   r   r   r   r   ’   s   
ÿ

þÿzSecurityKey.InternalSendApduN)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r#   r)   r,   r.   r   r   r   r   r   r      s    %
ü+r   )r:   r   Úpyu2fr   r   Úobjectr   r   r   r   r   Ú<module>   s
   