summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjaseg <git@jaseg.net>2018-11-13 21:45:24 +0900
committerjaseg <git@jaseg.net>2018-11-13 21:45:24 +0900
commite16515bb643b9329318809ecc134f74c22a86382 (patch)
tree30efc4ce885ced6edae4299c3453fa2f28c20926
parent6af635bd41b48da04edd1f70a6851cb3f811cea3 (diff)
downloadsecure-hid-e16515bb643b9329318809ecc134f74c22a86382.tar.gz
secure-hid-e16515bb643b9329318809ecc134f74c22a86382.tar.bz2
secure-hid-e16515bb643b9329318809ecc134f74c22a86382.zip
Pairing and passthrough mostly working, except it's too slow
-rwxr-xr-xhexnoise.py32
-rwxr-xr-xpairing.py65
-rw-r--r--src/demo.c34
-rw-r--r--src/packet_interface.c3
4 files changed, 78 insertions, 56 deletions
diff --git a/hexnoise.py b/hexnoise.py
index 8529787..8a8dae5 100755
--- a/hexnoise.py
+++ b/hexnoise.py
@@ -31,6 +31,9 @@ class ReportType(enum.Enum):
PAIRING_SUCESS = 4
PAIRING_ERROR = 5
+class ProtocolError(Exception):
+ pass
+
class Packetizer:
def __init__(self, serial, debug=False, width=16):
self.ser, self.debug, self.width = serial, debug, width
@@ -55,11 +58,11 @@ class Packetizer:
pkt_type, data = PacketType(data[0]), data[1:]
if pkt_type is PacketType.COMM_ERROR:
- raise ValueError('Device-side serial communication error')
+ raise ProtocolError('Device-side serial communication error')
elif pkt_type is PacketType.CRYPTO_ERROR:
- raise ValueError('Device-side cryptographic error')
+ raise ProtocolError('Device-side cryptographic error')
elif pkt_type is PacketType.TOO_MANY_FAILS:
- raise ValueError('Device reports too many failed handshake attempts')
+ raise ProtocolError('Device reports too many failed handshake attempts')
else:
return pkt_type, data
@@ -222,7 +225,7 @@ class NoiseEngine:
if pkt_type is PacketType.HANDSHAKE:
self.proto.read_message(payload)
else:
- raise ValueError(f'Incorrect packet type {pkt_type}. Ignoring since this is only test code.')
+ raise ProtocolError(f'Incorrect packet type {pkt_type}. Ignoring since this is only test code.')
if self.debug:
print('Handshake finished, handshake hash:')
hexdump(print, self.proto.get_handshake_hash())
@@ -291,19 +294,26 @@ class NoiseEngine:
break
elif msg_type == ReportType.PAIRING_ERROR:
- raise ValueError('Device-side pairing error') # FIXME find better exception subclass here
+ raise ProtocolError('Device-side pairing error') # FIXME find better exception subclass here
else:
- raise ValueError('Invalid report type')
+ raise ProtocolError('Invalid report type')
def uinput_passthrough(self):
with uinput.Device(KeyMapper.ALL_KEYS) as ui:
old_kcs = set()
- for msg_type, payload in noise.receive_loop():
- if msg_type == ReportType.KEYBOARD:
- modbyte, _reserved, *keycodes = payload
+ for msg_type, payload in self.receive_loop():
+ report_len, *report = payload
+ if report_len != 8:
+ raise ValueError('Unsupported report length', report_len)
+
+ if msg_type is ReportType.KEYBOARD:
+ modbyte, _reserved, *keycodes = report
+ print(' payload:', payload)
+ print(' modifier:', list(KeyMapper.map_modifiers(modbyte)))
+ print(' regular:', list(KeyMapper.map_regulars(keycodes)))
keys = { *KeyMapper.map_modifiers(modbyte), *KeyMapper.map_regulars(keycodes) }
- if args.debug:
+ if self.debug:
print('Emitting:', keys)
for key in keys - old_kcs:
@@ -313,7 +323,7 @@ class NoiseEngine:
ui.syn()
old_kcs = keys
- elif msg_type == ReportType.MOUSE:
+ elif msg_type is ReportType.MOUSE:
# FIXME unhandled
pass
diff --git a/pairing.py b/pairing.py
index fccc554..605b002 100755
--- a/pairing.py
+++ b/pairing.py
@@ -5,8 +5,7 @@ import re
import serial
import gi
gi.require_version('Gtk', '3.0')
-gi.require_version('Pango', '1.0')
-from gi.repository import Gtk, Pango
+from gi.repository import Gtk, Gdk, Pango, GLib
import hexnoise
@@ -27,39 +26,27 @@ class PairingWindow(Gtk.Window):
self.label.set_markup('<b>Step 1</b>\n\nContacting device...')
self.vbox.pack_start(self.label, True, True, 0)
- self.textview = Gtk.TextView()
- self.textview.set_editable(False)
- self.textbuffer = self.textview.get_buffer()
- self.tag_nomatch = self.textbuffer.create_tag("nomatch", weight=Pango.Weight.BOLD)
- self.tag_match = self.textbuffer.create_tag("match", background='#AAFFAA', weight=Pango.Weight.BOLD)
-
- self.vbox.pack_start(self.textview, True, True, 0)
+ self.entry = Gtk.Entry()
+ self.entry.set_editable(False)
+ self.vbox.pack_start(self.entry, True, True, 0)
self.add(self.vbox)
- self.handshaker = threading.Thread(target=self.run_handshake, daemon=True)
+ self.handshaker = threading.Thread(target=self.pair, daemon=True)
self.handshaker.start()
- @classmethod
- def matchlen(self, ref, text):
- words = ref.split()
- parts = text.split()
- clean = lambda b: re.sub('^[^a-zA-Z0-9-]*', '', re.sub('[^a-zA-Z0-9-]*$', '', b)).lower()
-
- good = ''
- for a, b in zip(words[:-1], parts[:-1]):
- if a == clean(b):
- good = f'{good}b '
-
- rest = clean(parts[-1])
- if words[-1].startswith(rest):
- good = f'{good} {rest}'
- return len(good)
-
- def run_handshake(self):
+ def pair(self):
self.packetizer = hexnoise.Packetizer(self.serial, debug=self.debug)
self.noise = hexnoise.NoiseEngine(self.packetizer, debug=self.debug)
+ for i in range(10):
+ try:
+ self.run_handshake()
+ break
+ except hexnoise.ProtocolError as e:
+ print(e)
+
+ def run_handshake(self):
self.noise.perform_handshake()
binding_incantation = self.noise.channel_binding_incantation()
@@ -67,19 +54,25 @@ class PairingWindow(Gtk.Window):
f'Enter the following incantation, then press enter.\n'
f'<b>{binding_incantation}</b>')
- for user_input in self.noise.pairing_messages():
- print('got:', user_input)
- self.textbuffer.set_text(user_input)
- #i1, i2 = self.textbuffer.get_start_iter(), self.textbuffer.get_end_iter()
- #self.textbuffer.apply_tag(self.tag_nomatch, i1, i2)
+ def update_text(text):
+ self.entry.set_text(text)
+ self.entry.set_position(len(text))
- #i1, i2 = self.textbuffer.get_start_iter(), self.textbuffer.get_start_iter()
- #i2.forward_chars(self.matchlen(binding_incantation, user_input))
- #self.textbuffer.apply_tag(self.tag_match, i1, i2)
+ clean = lambda s: re.sub('[^a-z0-9-]', '', s.lower())
+ if clean(binding_incantation).startswith(clean(text)):
+ color = 0.9, 1.0, 0.9 # light red
+ else:
+ color = 1.0, 0.9, 0.9 # light green
+ self.entry.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(*color, 1.0))
+
+ for user_input in self.noise.pairing_messages():
+ print(f'User input: "{user_input}"')
+ GLib.idle_add(update_text, user_input)
self.label.set_markup(f'<b>Done!</b>')
- #noise.uinput_passthrough()
+ # FIXME demo
+ self.noise.uinput_passthrough()
if __name__ == '__main__':
import argparse
diff --git a/src/demo.c b/src/demo.c
index 49157e9..c176f25 100644
--- a/src/demo.c
+++ b/src/demo.c
@@ -144,14 +144,36 @@ int pairing_check(struct NoiseState *st, const char *buf) {
const char *p = buf;
int idx = 0;
do {
+ /* Skip over most special chars */
+ while (*p) {
+ char c = *p;
+ if ('0' <= c && c <= '9') break;
+ if ('a' <= c && c <= 'z') break;
+ if ('A' <= c && c <= 'Z') break;
+ if (c == '-') break;
+ p++;
+ }
+
const char *found = strchr(p, ' ');
size_t plen = found ? (size_t)(found - p) : strlen(p); /* p >= found */
+ while (plen > 0) {
+ char c = p[plen];
+ if ('0' <= c && c <= '9') break;
+ if ('a' <= c && c <= 'z') break;
+ if ('A' <= c && c <= 'Z') break;
+ if (c == '-') break;
+ plen--;
+ }
+ plen++;
+ //LOG_PRINTF("matching: \"%s\" - \"%s\" %d\n", p, p+plen, plen);
+
if (strncasecmp(p, "and", plen)) { /* ignore "and" */
int num = -1;
/* FIXME ignore "and", ignore commata and dots */
for (int i=0; i<256; i++) {
- if ((!strncasecmp(p, adjectives[i], plen)) || (!strncasecmp(p, nouns[i], plen))) {
+ if ((!strncasecmp(p, adjectives[i], plen) && plen == strlen(adjectives[i]))
+ || (!strncasecmp(p, nouns[i], plen) && plen == strlen(nouns[i] ))) {
//LOG_PRINTF(" idx=%02d h=%02x i=%02x adj=%s n=%s plen=%d s=%s\n", idx, st->handshake_hash[idx], i, adjectives[i], nouns[i], plen, p);
num = i;
break;
@@ -218,12 +240,8 @@ void pairing_input(uint8_t modbyte, uint8_t keycode) {
for (size_t i=0; keycode_mapping[i].kc != KEY_NONE; i++) {
if (keycode_mapping[i].kc == keycode) {
ch = keycode_mapping[i].ch[level];
- if (!(('a' <= ch && ch <= 'z') ||
- ('A' <= ch && ch <= 'Z') ||
- ('0' <= ch && ch <= '9') ||
- (ch == ' ') ||
- (ch == '-')))
- break; /* ignore special chars */
+ if (!ch)
+ break;
if (pairing_buf_pos < sizeof(pairing_buf)-1) /* allow for terminating null byte */ {
pairing_buf[pairing_buf_pos++] = ch;
@@ -242,7 +260,7 @@ void pairing_input(uint8_t modbyte, uint8_t keycode) {
}
if (ch) {
- LOG_PRINTF("Input: %s\n", pairing_buf);
+ //LOG_PRINTF("Input: %s\n", pairing_buf);
struct hid_report_packet pkt = {
.type = REPORT_PAIRING_INPUT,
.pairing_input = { .c = ch }
diff --git a/src/packet_interface.c b/src/packet_interface.c
index 9c0ea5c..319ddd1 100644
--- a/src/packet_interface.c
+++ b/src/packet_interface.c
@@ -25,10 +25,11 @@ struct dma_usart_file usart2_out_s = {
struct dma_usart_file *usart2_out = &usart2_out_s;
void dma1_stream6_isr(void) {
+ static unsigned int fifo_errors = 0; /* debug */
if (dma_get_interrupt_flag(usart2_out->dma, usart2_out->stream, DMA_FEIF)) {
/* Ignore FIFO errors as they're 100% non-critical for UART applications */
dma_clear_interrupt_flags(usart2_out->dma, usart2_out->stream, DMA_FEIF);
- LOG_PRINTF("USART2 DMA FIFO error\n");
+ fifo_errors++;
return;
}