# python-validity Validity fingerprint sensor library. Originally designed to capture some of my findings for 138a:0097, but if you manage to get it working for some other Validity sensor - pull requests are welcome. ## Setting up To install Python dependencies run ``` $ pip3 install -r requirements.txt ``` ## Getting the firmware It's possible to just extract [official Lenovo device driver for vfs0097](https://support.lenovo.com/us/en/downloads/DS121407) or [driver for vfs0090](https://support.lenovo.com/us/en/downloads/DS120491) (also [part of the SCCM package](https://support.lenovo.com/ec/th/downloads/DS112113) using [innoextract](https://constexpr.org/innoextract/) (available for all the distros), or `wine`. The only reason you need to do this is to find `6_07f_lenovo_mis.xpfwext` (for vfs0097) or `6_07f_Lenovo.xpfwext` (for vfs0090) and copy it to this project location. innoextract n1mgf03w.exe -e -I 6_07f_lenovo_mis.xpfwext # vfs0097 innoextract n1cgn08w.exe -e -I 6_07f_Lenovo.xpfwext # vfs0090 ## Factory reset If your device was previously paired with another OS or computer, you need to do a factory reset. This will erase all fingers from the internal database and make the device ready for pairing. ``` $ python3 factory-reset.py $ ``` ## Pairing After performing a factory reset you need to pair your device with a host computer. This must be done only once, before you can enroll/identify/verify fingers. ``` $ python3 pair.py Initializing flash... Detected Flash IC: W25Q80B, 1048576 bytes Clean slate Uploading firmware... Sensor: VSI 55E FM209-001 Loaded FWExt version 1.1 (Sat Feb 3 05:07:30 2018), 8 modules Calibrating... Sensor: VSI 55E FM209-001 FWExt version 1.1 (Sat Feb 3 05:07:30 2018), 8 modules Calibration data loaded from the file. Init database... Creating a new user storage object Creating a host machine GUID record That's it, pairing's finished $ ``` ## Examples Here is a couple of examples of how you can use this library. All examples assume that your device is already paired. ### Initialize a session Before talking to a device you will need to open it and start a new TLS session ``` $ python3 Python 3.6.7 (default, Oct 22 2018, 11:32:17) [GCC 8.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from prototype import * >>> open97() >>> ``` Or load previosly saved TLS session (see comments in [holdthedoor.py](holdthedoor.py)) ``` $ python3 Python 3.6.7 (default, Oct 22 2018, 11:32:17) [GCC 8.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from prototype import * >>> load97() >>> ``` ### Enroll a new user Note: 0xf5 == WINBIO_FINGER_UNSPECIFIED_POS_01 (see [ms docs](https://docs.microsoft.com/en-us/windows/desktop/SecBioMet/winbio-ansi-381-pos-fingerprint-constants)) ``` >>> db.dump_all() 8: User S-1-5-21-111111111-1111111111-1111111111-1000 with 1 fingers: 9: f5 (WINBIO_FINGER_UNSPECIFIED_POS_01) >>> enroll(sid_from_string('S-1-5-21-394619333-3876782012-1672975908-3333'), 0xf5) Waiting for a finger... Progress: 14 % done Progress: 28 % done Progress: 42 % done Progress: 57 % done Progress: 71 % done Progress: 85 % done Progress: 100 % done All done 11 >>> db.dump_all() 8: User S-1-5-21-111111111-1111111111-1111111111-1000 with 1 fingers: 9: f5 (WINBIO_FINGER_UNSPECIFIED_POS_01) 10: User S-1-5-21-394619333-3876782012-1672975908-3333 with 1 fingers: 11: f5 (WINBIO_FINGER_UNSPECIFIED_POS_01) >>> ``` ### Delete database record (user/finger/whatever) ``` >>> db.dump_all() 8: User S-1-5-21-111111111-1111111111-1111111111-1000 with 1 fingers: 9: f5 (WINBIO_FINGER_UNSPECIFIED_POS_01) 10: User S-1-5-21-394619333-3876782012-1672975908-3333 with 1 fingers: 11: f5 (WINBIO_FINGER_UNSPECIFIED_POS_01) >>> db.del_record(11) >>> db.dump_all() 8: User S-1-5-21-111111111-1111111111-1111111111-1000 with 1 fingers: 9: f5 (WINBIO_FINGER_UNSPECIFIED_POS_01) 10: User S-1-5-21-394619333-3876782012-1672975908-3333 with 0 fingers: >>> ``` ### Identify a finger (scan) ``` >>> identify() Recognised finger f5 (WINBIO_FINGER_UNSPECIFIED_POS_01) from user S-1-5-21-111111111-1111111111-1111111111-1000 Template hash: 36bc1fe077e59a3090c816fcf2798c30a85d8a8fbe000ead5c6a946c3bacef7b ``` ## DBus service Sources contain a simple DBus service which can impersonate [fprint](https://www.freedesktop.org/wiki/Software/fprint/) daemon. Install fprint, edit /usr/share/dbus-1/system-services/net.reactivated.Fprint.service by commenting out activation info: ``` #Exec=/usr/lib/fprintd/fprintd #User=root #SystemdService=fprintd.service ``` start a fake service with something like this: ``` while sleep 1; do python3 dbus-service.py echo "====restart===" done ``` ## Debugging If you are curious you can enable tracing to see what flows in and out of device before and after encryption ``` >>> tls.trace_enabled=True >>> usb.trace_enabled=True >>> db.dump_all() >tls> 17: 4b00000b0053746757696e64736f7200 >cmd> 1703030050c00a7ff1cf76e90f168141b4bc519ca9598eacb575ff01b7552a3707be8506b246d5272cb119e7b8b3eccd991cb7d8387245953ff1da62cebfb07fae7e47b9b536fb1a82185cc9399d30625ee3c1451f tls> 17: 4a080000000000 >cmd> 1703030040ef982e5d6c403ff636c44cd53e7d0f98c21f67ff3b5b80f53555e4547028bd4d17cf5b0539ac0489238f1f066b8ba849120380cf979088d6c63249c873868c95 tls> 17: 4a0a0000000000 >cmd> 1703030040b522c55b73480e0d71a322abf8b65d97c9b55e9930206c463f998886cda4410d1b00ab41ec5b213d2ac18bf3bf61ce817446f27d643f99aba5a1d4cb80d18461 >> ```