Sweet, this’ll come in handy. Thanks!
I was going to see if I can find or make something to decrypt my LUKS partition during boot. Have a yubi key + a password combo right now.
Not terribly difficult to do, unless your LUKS partition is your boot partition, in which case you’ll probably have to make an initrd image that loads the appropriate drivers, handles reading your implant and recovers the LUKS key before doing the chroot. If your LUKS partition is something else, like /home, you can do all that in the regular system, which is easier.
It’s my boot partition. So yeah what you said.
Maybe I might get cracking on something like that, if I have some time
GnuPG i believe has a solid foundation for this to work. I’ve been swamped (and the Rona’s impacted my work - busy!) but this is next on the list.
If you do I’d definitely be interested. I was going to wait for the Apex line because it’s an actual secure element
Bleh… Why wait for the Apex line when we already have s00per secure Mifare Classics eh?
More seriously, what I was thinking of is a generic mechanism to wait for input from a contactless smartcard / implant at boot time to decrypt the root partition. Once that’s done, you could plug in a shite UID-based authentication, or a more advance challenge-response thing, whatever you fancy. Maybe it even already exists, I haven’t checked.
Oh well then, have at it. I don’t have time either
I have a challenge response slot on my yubi key yeah.
This is already implemented, interestingly enough. YubiKey login has a PAM and i think a similar mechanism can be used to decrypt the root partition with LUKS.
Yes, I use yubikey-luks which adds a 2nd factor using a challenge response in slot 2 of the YubiKey.
I’ve added provisions in SiRFIDaL to read a UID and pass it to cryptsetup. So you would do something like this to set it up (as root):
- Get the UID you want to use as a crypto key for the volume with
sirfidal_getuids.py
- Do
cryptsetup luksAddKey /dev/<your encrypted volume>
and paste the UID when it prompts for a key - Then to open it at boot time with your implant:
sirfidal_getuids.py -q -s '' | cryptsetup -d- luksOpen /dev/<your encrypted volume> <mapper>
You would just have to setup your source of UIDs (pcscd, serial port, keyboard wedge or cellphone) and start sirfidal_server at boot time before opening the LUKS volume.
The script I had posted above works, but it didn’t always work reliably. As I was trying to figure out why, I realized something: Rohos Logon Key really expects UIDs to come in specific data formats from the serial readers it supports nominally. The script however simply passes it raw LF-terminated ASCII UIDs.
So I modified it a bit: now it simulates an Easyident FS-2044 RFID reader (one of the readers Rohos Logon Key explicitely supports). With that new version, Rohos unlocks each and every time without fail.
Here it is:
#!/usr/bin/python3
# This program emulates an Easyident FS-2044 RFID reader with UIDs read from a
# generic, 10-digit UID, 9600 baud serial RFID reader, for use as an input
# device by Rohos Logon Key.
#
# This program requires a virtual null modem cable such as com0com, with
# Rohos Logon Key listening to one end of the null modem cable, and this
# program outputting fake Easyident frames to the other end.
#
# Additionally, this program can kill a running Windows screensaver whenever a
# UID is read, so that the Windows logon screen is automatically brought up
# before passing the UID to Rohos Logon Key, thereby alleviating the need to
# press a key to activate the logon screen.
# Parameters
incomport="COM2" # Input COM port for the generic serial reader
outcomport="COM4" # Output COM port for the virtual null modem
# Rohos Logon Key is connected to the
# other end of
screensaver="ribbons.scr" # Set to None to bypass killing the screensaver
# Modules
import os
import time
import serial
# Main program
incomport_fd=None
outcomport_fd=None
hexdigits = "0123456789ABCDEF"
while True:
uid=None
if not incomport_fd:
try:
incomport_fd = serial.Serial(incomport)
except:
print("Error opening input COM port {}".format(incomport))
incomport_fd = None
time.sleep(0.2)
continue
# Read a UID from the serial RFID reader
try:
uid=incomport_fd.readline().strip().decode("ascii")
except:
print("Read error")
incomport_fd = None
time.sleep(0.2)
continue
if not outcomport_fd:
try:
outcomport_fd = serial.Serial(outcomport)
except:
print("Error opening output COM port {}".format(outcomport))
outcomport_fd = None
time.sleep(0.2)
continue
uid = "".join([c for c in uid.upper() if c in hexdigits])
print("UID read in:", uid)
if len(uid) != 10:
print(" Incompatible UID (not 10 digits) - giving up")
continue
# Kill the screensaver
if screensaver:
try:
os.system("taskkill /f /t /im {}".format(screensaver))
except:
pass
# Create a simulated Easyident data frame
csum = sum([ord(c) - ord("0" if c.isdigit() else "7") for c in uid]) & 0xf
easyident_frame = b"\x8a" + (uid + hexdigits[csum]).encode("ascii") + b"\r\n"
# Pass on the fake Easyident frame to Rohos Logon Key
try:
outcomport_fd.write(easyident_frame)
outcomport_fd.flush()
print(" UID sent out")
except:
print(" Write error")
incomport_fd = None
time.sleep(0.2)
Microsoft pushed a Windows update on Friday that breaks Rohos in serial mode.
My foot reader is now dead.
Fuck Microsoft…
Dicks!
Any legitimate reason for it?
Have you “raised a ticket”?
How long did it take you to work out the cause?
Well I suppose the legitimate reason is that my company’s IT guy is anal about keeping up with updates. I suppose he’s right too. He would be righter if he ditched Windows but this is a Microsoft shop, so…
But he retires in 1 1/2 year and I’m next in line. And I’m already installing Linux right and left and proving by example that it’s nicer when done right, so there is hope
Yeah I reported it to the dev. We’ll see what he says. I’m not too hopeful though: he seems to frown upon what I’m doing with his baby - i.e. using it for insecure applications. I have a feeling he’s not too keen on supporting serial readers, from what he told me in the past. We’ll see.
It took me forever to find out the cause. The clincher was when I uninstalled everything - com2com, my Python script, Rohos, cleaned the registry squeaky clean - then reinstalled Rohos vanilla and simply configured it to listen to a real serial port to which nothing was connected, and seeing card IDs being read. That’s a dead giveaway.
I managed to get Rohos to cooperate with my RFID serial reader again. Most of the time anyway.
Rohos has a really weird way of handling the serial port. I think it’s using a custom reader protocol that I don’t understand. But no matter how hard I try to reverse engineer it, I’m not really able to find out exactly what it needs to work well. Nor can I find the specs of the serial readers it’s supposed to support anywhere online. Not that it would be terribly useful: Rohos simply links to third party libraries to support those readers as far as I can tell, and those manufacturer-provided libraries are rarely fully documented.
Anyway, here’s a new script that manages to pass UIDs from a generic serial reader to Rohos. It’s seriously dirty and hacky but it seems to work more or less reliably:
#!/usr/bin/python3
# This program sends UIDs read from a generic 9600 8N1 serial RFID reader to
# Rohos Logon Key, configured to use the authentication device type
# "RFID Easyident/Addimat/KCY/pcProx/Stahl", using the weird serial protocol
# it seems to be using in that mode.
#
# It requires a virtual null modem provided by com0com, with RTS/CTS "cabled"
# in the com0com setup utility (default), "emulate baud rate" enabled",
# "enable buffer overrun" enabled and Rohos Logon Key configured to be
# listening to one end of the null modem cable.
#
# Additionally, this program can kill a running Windows screensaver whenever a
# UID is read, so that the Windows logon screen is automatically brought up
# before passing the UID to Rohos Logon Key, thereby alleviating the need to
# press a key to activate the logon screen.
#
# Please note that the way Rohos Logon Key is listening to the serial port in
# "RFID Easyident/Addimat/KCY/pcProx/Stahl" mode is totally unclear. The way
# this program sends UIDs to it is highly unusual, but it seems to be the only
# way to get Rohos Logon Key to accept UIDs somewhat reliably. This is probably
# not correct, and probably abuses the program's normal operation.
# Parameters
incomport = "COM2" # Input COM port for the generic serial reader
outcomport = "COM4" # Output COM port for the virtual null modem
# Rohos Logon Key is connected to the
# other end of
screensaver = "ribbons.scr" # Set to None to bypass killing the screensaver
# Modules
import os
import time
import serial
from datetime import datetime
# Main program
incomport_fd = None
outcomport_fd = None
recbuf = b""
while True:
uid = None
if incomport_fd is None:
try:
incomport_fd = serial.Serial(incomport, timeout = .5)
except:
print("Error opening input COM port {}".format(incomport))
incomport_fd = None
time.sleep(0.2)
continue
# Read a UID from the serial RFID reader
uid = b""
b = b""
while True:
try:
b = incomport_fd.read(1)
except:
print("Read error")
incomport_fd = None
time.sleep(0.2)
break
if b:
if b in b"0123456789abcdefABCDEF":
recbuf += b.upper()
elif b == b"\n":
uid = recbuf
recbuf = b""
else:
if uid:
break
if incomport_fd is None:
continue
if outcomport_fd is None:
try:
outcomport_fd = serial.Serial(outcomport)
cts = outcomport_fd.cts
except:
print("Error opening output COM port {}".format(outcomport))
outcomport_fd = None
time.sleep(0.2)
continue
print("UID read in:", uid.decode("ascii"))
# Kill the screensaver
if screensaver is not None:
print(" Killing the screensaver")
try:
os.system("taskkill /f /t /im {}".format(screensaver))
except:
pass
# Pass on the UID to Rohos Logon key twice, it case it misses the first time
for i in range(2):
# First wait for a falling edge on CTS
now = datetime.now().timestamp()
cts_wait_timeout = now + 2
prev_cts = cts
cts = outcomport_fd.cts
while not (cts and not prev_cts) and now < cts_wait_timeout:
prev_cts = cts
cts = outcomport_fd.cts
now = datetime.now().timestamp()
# If we can send the UID, do so. Otherwise give up
if cts and not prev_cts:
try:
outcomport_fd.write(uid)
outcomport_fd.flush()
print(" UID sent out {}".format("once" if i == 0 else "twice"))
except:
print(" Write error")
outcomport_fd = None
# If the CTS thing fails, make sure we don't end up in a tight loop
time.sleep(.5)
EDIT:
Oh and yeah, another thing: if you have a pcProx Sonar connected to your computer, you’ll have to delete or rename C:\Windows\system32\pcProxAPI.dll
and C:\Windows\SysWOW64\pcProxAPI.dll
to disable the pcProx API: it turns out that library (or Rohos) only checks the VID (vendor ID) of the various USB devices listed in the system to determine the presence of a pcProx reader. Of course, the Sonar being made by the same manufacturer, it has the same VID. But it’s not a reader, so it messes everything up.
Took me forever to find that one…
When I select the RFID reader in options and click ok. I get a message saying “Authentication key is not installed. Failed to load Rohos_ed-fs_2044.dll”
I can’t move to set up authorization because for some reason the ACR122 is not being recognized.
Any suggestions?