o
    l>j5<                     @  sj  d dl mZ d dlZd dlZd dlZd dlZd dlmZmZ ddl	m
Z
mZmZmZ eeZdZdZdZd	Zd
ZdZdZdZdZG dd dejZG dd deZG dd deZG dd deZG dd deZG dd deZ G dd deZ!e"eZ#e"eZ$e"eZ%e"e Z&ej'Z(e"e!Z)ej*Z+ej*Z,ej-Z.ej/Z0ej1Z2ej3Z4dZ5ej6Z7ej6Z8ej6Z9ej6Z:ej6Z;e:Z<e:Z=e"eZ>e"eZ?e@dejAe7ej*e8ej3e"ejBe0ZCe@dejAe7ej*ZDdZEdZFd ZGdZHd ZIdZJdZKd ZLejMNejOPd!pd"ZQejMNejOPd#pd$ZRe$SeRd%ZTdeRjU_Ve#e"ej*geRjU_We$eRjX_Vej*ejYej3geRjX_WejZeRj[_Ve%ejYe0e4geRj[_We.eRj\_Ve%geRj\_We.eRj]_Ve.eRj^_Vej_eRj`_Ve&eRja_Vg eRja_We(eRjb_Ve$e2ejZgeRjb_We7eRjc_Ve%geRjc_We:geQjd_We>eQje_Ve)e9geQje_We#eQjf_Ve>geQjf_WdeQjg_Ve>e%geQjg_We,eQjh_VejigeQjh_We7eQjj_Ve=e"ejigeQjj_We?eQjk_Ve)e<geQjk_We7eQjl_Ve?ej3geQjl_WdeQjm_Ve?e&e$geQjm_WdeQjn_Ve?e&e$geQjn_We%eQjo_Ve?e$geQjo_We7eQjp_Ve?e8e0ej*e0geQjp_We<eQjq_Ve;e+geQjq_Wd&d' ZreCerZsd(d) ZteDetZud*d+ ZvG d,d- d-eZwd.d/ Zxd0d1 Zyd2d3 Zzd4d5 Z{d6d7 Z|d8d9 Z}d:d; Z~d<d= ZdS )>    )annotationsN)EmptyQueue   )
FIDO_USAGEFIDO_USAGE_PAGECtapHidConnectionHidDescriptors   VendorIDs	   ProductIDs   Products   SerialNumbers   PrimaryUsages   PrimaryUsagePages   MaxInputReportSizes   MaxOutputReportSizes   ReportIDc                   @     e Zd ZdS )_CFTypeN__name__
__module____qualname__ r   r   D/home/thesage/.local/lib/python3.10/site-packages/fido2/hid/macos.pyr   ,       r   c                   @  r
   )	_CFStringNr   r   r   r   r   r   0   r   r   c                   @  r
   )_CFSetNr   r   r   r   r   r   4   r   r   c                   @  r
   )_IOHIDManagerNr   r   r   r   r   r   8   r   r   c                   @  r
   )_IOHIDDeviceNr   r   r   r   r   r   <   r   r   c                   @  r
   )
_CFRunLoopNr   r   r   r   r   r   @   r   r   c                   @  r
   )_CFAllocatorNr   r   r   r   r   r   D   r   r   i           IOKitz0/System/Library/Frameworks/IOKit.framework/IOKitCoreFoundationzB/System/Library/Frameworks/CoreFoundation.framework/CoreFoundationkCFRunLoopDefaultModec                 C  s   ~~~~|  t|| dS )z+Handles incoming IN report from HID device.N)putctypes	string_at)
read_queueresultsenderreport_type	report_idreportreport_lengthr   r   r   _hid_read_callback   s   r)   c                 C  s   ~~t | j d S N)cfCFRunLoopStoprun_loop_ref)
hid_devicer#   r$   r   r   r   _hid_removal_callback   s   r/   c                 C  s   t  | _| jstd dS t| j| jt t	| jt
t|  d}d}||k rTt tdd}| j  }|tkrI|r?ntd |d7 }ntd	| n||k s+t| j| jt dS )
zBinds a device to the thread's run loop, then starts the run loop.

    Args:
    hid_device: The MacOsHidDevice object

    The HID manager requires a run loop to handle Report reads. This thread
    function serves that purpose.
    zFailed to get current run loopNr   r   r   Tz6Read queue empty after HANDLE_SOURCE, attempting retryr   z!Unexpected run loop exit code: %d)r+   CFRunLoopGetCurrentr-   loggererroriokitIOHIDDeviceScheduleWithRunLoophandleK_CF_RUNLOOP_DEFAULT_MODE"IOHIDDeviceRegisterRemovalCallbackREMOVAL_CALLBACKr    	py_objectCFRunLoopRunInModer"   empty K_CF_RUN_LOOP_RUN_HANDLED_SOURCEdebug IOHIDDeviceUnscheduleFromRunLoop)r.   max_retriesretriesrun_loop_run_resultreceived_datar   r   r   _dev_read_thread   s<   





rC   c                   @  s,   e Zd Zdd Zdd Zdd Zdd Zd	S )
MacCtapHidConnectionc              	   C  sz   || _ t|j| _t| jd}|tkrtd| t | _	d | _
tj|j  | _t| j| j| j jtt| j	 d S )Nr   z)Failed to open device for communication: )
descriptor_handle_from_pathpathr5   r3   IOHIDDeviceOpenK_IO_RETURN_SUCCESSOSErrorr   r"   r-   r    c_uint8report_size_inin_report_buffer&IOHIDDeviceRegisterInputReportCallbackREGISTERED_READ_CALLBACKr9   )selfrE   r#   r   r   r   __init__  s   
zMacCtapHidConnection.__init__c              	   C  s&   t | j| j| jjtdtd  d S )Nr   )	r3   rN   r5   rM   rE   rL   r    castIO_HID_REPORT_CALLBACK)rP   r   r   r   close8  s   
zMacCtapHidConnection.closec                 C  s2   t | jtd|t|}|tkrtd| d S )Nr   z"Failed to write report to device: )r3   IOHIDDeviceSetReportr5   K_IO_HID_REPORT_TYPE_OUTPUTlenrI   rJ   )rP   datar#   r   r   r   write_packetA  s   	z!MacCtapHidConnection.write_packetc                 C  sh   z| j dW S  ty3   tjt| fd}|  |  z	| j dW  Y S  ty2   tdw w )NF)targetargszFailed reading a response)	r"   getr   	threadingThreadrC   startjoinrJ   )rP   read_threadr   r   r   read_packetN  s   z MacCtapHidConnection.read_packetN)r   r   r   rQ   rT   rY   rb   r   r   r   r   rD     s
    	rD   c                 C  s   t d|d}t| |}t | |std| dt |t  kr/tdt | t	
 }t |tt	|sEtd| d|jS )z'Reads int property from the HID device.Nr   z
Property 'z' not foundzExpected number type, got zFailed to read property '')r+   CFStringCreateWithCStringr3   IOHIDDeviceGetProperty	CFRelease
ValueErrorCFGetTypeIDCFNumberGetTypeIDrJ   r    c_int32CFNumberGetValueK_CF_NUMBER_SINT32_TYPEbyrefvalue)devkeycf_keytype_refoutr   r   r   get_int_property[  s   
rt   c                 C  s   t d|d}t| |}t | |sdS t |t  kr)tdt | t	d}t 
||t|t}|s=dS z	|jdpEdW S  tyP   Y dS w )z*Reads string property from the HID device.Nr   zExpected string type, got    zutf-8)r+   rd   r3   re   rf   rh   CFStringGetTypeIDrJ   r    create_string_bufferCFStringGetCStringsizeof CF_STRING_BUILTIN_ENCODINGS_UTF8rn   decodeUnicodeDecodeError)ro   rp   rq   rr   rs   retr   r   r   get_string_propertym  s$   

r~   c                 C  s@   t | }t }t |t|}|tkrtd| |jS )zObtains the unique IORegistry entry ID for the device.

    Args:
    handle: reference to the device

    Returns:
    A unique ID for the device, obtained from the IO Registry
    z&Failed to obtain IORegistry entry ID: )	r3   IOHIDDeviceGetServicer    c_uint64!IORegistryEntryGetRegistryEntryIDrm   rI   rJ   rn   )r5   io_service_objentry_idr#   r   r   r   get_device_id  s   


r   c                 C  sD   t t| }t|}tt|}|std|  dtt	|S )Nz
Device ID z, does not match any HID device on the system)
r    r   intr3   IORegistryEntryIDMatchingIOServiceGetMatchingServiceK_IO_MASTER_PORT_DEFAULTrJ   IOHIDDeviceCreateK_CF_ALLOCATOR_DEFAULT)rG   r   matching_dictdevice_entryr   r   r   rF     s   
rF   c                 C  s   t | S r*   )rD   )rE   r   r   r   open_connection  s   r   c           
      C  s   t | t}t | t}|tkr@|tkr@t| }t | t}t | t}t| t	}t| t
}t | t}t | t}	tt|||||	||S td)NzNot a CTAP device)rt   &HID_DEVICE_PROPERTY_PRIMARY_USAGE_PAGE!HID_DEVICE_PROPERTY_PRIMARY_USAGEr   r   r   HID_DEVICE_PROPERTY_VENDOR_IDHID_DEVICE_PROPERTY_PRODUCT_IDr~   HID_DEVICE_PROPERTY_PRODUCT!HID_DEVICE_PROPERTY_SERIAL_NUMBER)HID_DEVICE_PROPERTY_MAX_INPUT_REPORT_SIZE*HID_DEVICE_PROPERTY_MAX_OUTPUT_REPORT_SIZEr	   strrg   )
r5   
usage_pageusage	device_idvidpidproductserialsize_insize_outr   r   r   _get_descriptor_from_handle  s   







r   c                 C  s   t t| S r*   )r   rF   )rG   r   r   r   get_descriptor  s   r   c               	   C  s   t d d} | stdzQt | d  t | }|stdz9t |}t|  }t || g }|D ]}zt|}|	| W q3 t
yI   Y q3w |W t| W t|  S t| w t|  w )Nr   z&Unable to obtain HID manager referencez)Failed to obtain devices from HID manager)r3   IOHIDManagerCreaterJ   IOHIDManagerSetDeviceMatchingIOHIDManagerCopyDevicesCFSetGetCountIO_HID_DEVICE_REFCFSetGetValuesr   appendrg   r+   rf   )hid_mgrdevice_set_refnumdevicesdescriptorsr5   rE   r   r   r   list_descriptors  s2   


r   )
__future__r   r    ctypes.utilloggingr]   queuer   r   baser   r   r   r	   	getLoggerr   r1   r   r   r   r   r   r   r   r   HID_DEVICE_PROPERTY_REPORT_ID	Structurer   r   r   r   r   r   r   POINTER
CF_SET_REFCF_STRING_REFCF_TYPE_REFCF_RUN_LOOP_REFrj   CF_RUN_LOOP_RUN_RESULTCF_ALLOCATOR_REFc_void_pCF_DICTIONARY_REFCF_MUTABLE_DICTIONARY_REFc_ulong
CF_TYPE_IDc_longCF_INDEXc_doubleCF_TIME_INTERVALc_uint32CF_STRING_ENCODINGrz   c_uint	IO_RETURNIO_HID_REPORT_TYPEIO_OPTION_BITSIO_OBJECT_TMACH_PORT_TIO_SERVICE_TIO_REGISTRY_ENTRY_TIO_HID_MANAGER_REFr   	CFUNCTYPEr9   rK   rS   IO_HID_CALLBACKrl   r   r   rV   rI   K_CF_RUN_LOOP_RUN_STOPPEDK_CF_RUN_LOOP_RUN_TIMED_OUTr<   cdllLoadLibraryutilfind_libraryr3   r+   in_dllr6   r   restypeargtypesrd   c_char_pc_boolrx   rh   ri   rv   c_intrk   r0   r:   rf   IOObjectReleaser   r   r   r   r   r   r   IOHIDDeviceCloser4   r>   re   rU   r   r)   rO   r/   r8   rC   rD   rt   r~   r   rF   r   r   r   r   r   r   r   r   <module>   s,  
















7=