New host-side arch working
This commit is contained in:
parent
d2c9b00b36
commit
af15c38a05
8 changed files with 485 additions and 886 deletions
294
adjectives.py
294
adjectives.py
|
|
@ -1,260 +1,34 @@
|
|||
|
||||
ADJECTIVES = [
|
||||
"wrathful", # 0
|
||||
"worthy", # 1
|
||||
"weird", # 2
|
||||
"warm", # 3
|
||||
"volatile", # 4
|
||||
"veiled", # 5
|
||||
"vacuous", # 6
|
||||
"useless", # 7
|
||||
"upset", # 8
|
||||
"unsoiled", # 9
|
||||
"unsightly", # 10
|
||||
"unpronounceable", # 11
|
||||
"unfriendly", # 12
|
||||
"unfree", # 13
|
||||
"unfit", # 14
|
||||
"unfaithful", # 15
|
||||
"unchaste", # 16
|
||||
"unbroken", # 17
|
||||
"unbound", # 18
|
||||
"unblessed", # 19
|
||||
"unbefitting", # 20
|
||||
"unaltered", # 21
|
||||
"unabused", # 22
|
||||
"unable", # 23
|
||||
"ugly", # 24
|
||||
"tongued", # 25
|
||||
"thorny", # 26
|
||||
"thirsty", # 27
|
||||
"thick", # 28
|
||||
"terminal", # 29
|
||||
"ten-sided", # 30
|
||||
"teeming", # 31
|
||||
"tangerine", # 32
|
||||
"taken", # 33
|
||||
"substantial", # 34
|
||||
"stupefying", # 35
|
||||
"stringy", # 36
|
||||
"strange", # 37
|
||||
"stillborn", # 38
|
||||
"sticky", # 39
|
||||
"stagnant", # 40
|
||||
"spongy", # 41
|
||||
"sour", # 42
|
||||
"soul-destroying", # 43
|
||||
"smoldering", # 44
|
||||
"smitten", # 45
|
||||
"slain", # 46
|
||||
"six-sided", # 47
|
||||
"shifting", # 48
|
||||
"shadowy", # 49
|
||||
"severed", # 50
|
||||
"seven-sided", # 51
|
||||
"serene", # 52
|
||||
"salty", # 53
|
||||
"rust-red", # 54
|
||||
"royal", # 55
|
||||
"rotten", # 56
|
||||
"riddled", # 57
|
||||
"resentful", # 58
|
||||
"regrettable", # 59
|
||||
"reeking", # 60
|
||||
"rare", # 61
|
||||
"rank", # 62
|
||||
"rancid", # 63
|
||||
"quiescent", # 64
|
||||
"putrid", # 65
|
||||
"putrid", # 66
|
||||
"putrescent", # 67
|
||||
"prehistoric", # 68
|
||||
"predatory", # 69
|
||||
"predaceous", # 70
|
||||
"porous", # 71
|
||||
"poisonous", # 72
|
||||
"pierced", # 73
|
||||
"phlegmatic", # 74
|
||||
"petrifying", # 75
|
||||
"pessimal", # 76
|
||||
"pathetic", # 77
|
||||
"odorless", # 78
|
||||
"oddish", # 79
|
||||
"obsessed", # 80
|
||||
"obscene", # 81
|
||||
"numb", # 82
|
||||
"nine-sided", # 83
|
||||
"nasty", # 84
|
||||
"mysterious", # 85
|
||||
"mute", # 86
|
||||
"musky", # 87
|
||||
"morose", # 88
|
||||
"moribund", # 89
|
||||
"moldy", # 90
|
||||
"miasmic", # 91
|
||||
"material", # 92
|
||||
"many-lobed", # 93
|
||||
"malodorous", # 94
|
||||
"malign", # 95
|
||||
"maimed", # 96
|
||||
"luminescent", # 97
|
||||
"low-cut", # 98
|
||||
"lousy", # 99
|
||||
"live", # 100
|
||||
"limp", # 101
|
||||
"lifeless", # 102
|
||||
"leering", # 103
|
||||
"leaky", # 104
|
||||
"layered", # 105
|
||||
"latent", # 106
|
||||
"lackluster", # 107
|
||||
"jagged", # 108
|
||||
"irregular", # 109
|
||||
"iridescent", # 110
|
||||
"intangible", # 111
|
||||
"infinite", # 112
|
||||
"inept", # 113
|
||||
"incomprehensible", # 114
|
||||
"in-between", # 115
|
||||
"improper", # 116
|
||||
"idle", # 117
|
||||
"hunted", # 118
|
||||
"hideous", # 119
|
||||
"heavy", # 120
|
||||
"hairy", # 121
|
||||
"guilty", # 122
|
||||
"grotesque", # 123
|
||||
"grey", # 124
|
||||
"greedy", # 125
|
||||
"gory", # 126
|
||||
"gorgeous", # 127
|
||||
"gooey", # 128
|
||||
"golden-brown", # 129
|
||||
"golden", # 130
|
||||
"ghastly", # 131
|
||||
"frostbitten", # 132
|
||||
"fresh-cut", # 133
|
||||
"freakish", # 134
|
||||
"frantic", # 135
|
||||
"fossilized", # 136
|
||||
"formless", # 137
|
||||
"formidable", # 138
|
||||
"floccose", # 139
|
||||
"five-lobed", # 140
|
||||
"firstborn", # 141
|
||||
"filthy", # 142
|
||||
"fickle", # 143
|
||||
"fetid", # 144
|
||||
"fertile", # 145
|
||||
"fearful", # 146
|
||||
"fatal", # 147
|
||||
"familiar", # 148
|
||||
"fallen", # 149
|
||||
"fallacious", # 150
|
||||
"faint", # 151
|
||||
"faceless", # 152
|
||||
"extinct", # 153
|
||||
"esoteric", # 154
|
||||
"errant", # 155
|
||||
"emergent", # 156
|
||||
"elastic", # 157
|
||||
"eight-sided", # 158
|
||||
"eerie", # 159
|
||||
"ebon", # 160
|
||||
"dysphoric", # 161
|
||||
"dying", # 162
|
||||
"dumb", # 163
|
||||
"dull-purple", # 164
|
||||
"dull", # 165
|
||||
"dull", # 166
|
||||
"dull", # 167
|
||||
"dormant", # 168
|
||||
"doomed", # 169
|
||||
"disfigured", # 170
|
||||
"dirty", # 171
|
||||
"defenseless", # 172
|
||||
"deep-pink", # 173
|
||||
"deep", # 174
|
||||
"deconsecrated", # 175
|
||||
"deathlike", # 176
|
||||
"deadly", # 177
|
||||
"dead", # 178
|
||||
"dark-blue", # 179
|
||||
"dark", # 180
|
||||
"curly", # 181
|
||||
"curious", # 182
|
||||
"cured", # 183
|
||||
"cunning", # 184
|
||||
"crystalline", # 185
|
||||
"cryptic", # 186
|
||||
"crying", # 187
|
||||
"crumbly", # 188
|
||||
"crimson", # 189
|
||||
"crested", # 190
|
||||
"creepy", # 191
|
||||
"crazy", # 192
|
||||
"corrupt", # 193
|
||||
"corporeal", # 194
|
||||
"contemptible", # 195
|
||||
"contained", # 196
|
||||
"concrete", # 197
|
||||
"cloudy", # 198
|
||||
"chopped", # 199
|
||||
"chained", # 200
|
||||
"caustic", # 201
|
||||
"catholic", # 202
|
||||
"cathartic", # 203
|
||||
"captive", # 204
|
||||
"cancerous", # 205
|
||||
"cabalistic", # 206
|
||||
"burnt", # 207
|
||||
"buoyant", # 208
|
||||
"bronze-red", # 209
|
||||
"bronze", # 210
|
||||
"broken", # 211
|
||||
"bright-red", # 212
|
||||
"breathless", # 213
|
||||
"bound", # 214
|
||||
"bound", # 215
|
||||
"bottomless", # 216
|
||||
"bony", # 217
|
||||
"bodiless", # 218
|
||||
"blue-lilac", # 219
|
||||
"blue", # 220
|
||||
"bloody", # 221
|
||||
"bloodthirsty", # 222
|
||||
"bloodsucking", # 223
|
||||
"bloodstained", # 224
|
||||
"bloodcurdling", # 225
|
||||
"blonde", # 226
|
||||
"blistered", # 227
|
||||
"blank", # 228
|
||||
"bitter", # 229
|
||||
"bilgy", # 230
|
||||
"bewitched", # 231
|
||||
"befouled", # 232
|
||||
"beardless", # 233
|
||||
"bastardly", # 234
|
||||
"barbed", # 235
|
||||
"baleful", # 236
|
||||
"balding", # 237
|
||||
"awkward", # 238
|
||||
"awful", # 239
|
||||
"atrocious", # 240
|
||||
"arcane", # 241
|
||||
"appalling", # 242
|
||||
"antic", # 243
|
||||
"anonymous", # 244
|
||||
"angry", # 245
|
||||
"ample", # 246
|
||||
"ambiguous", # 247
|
||||
"amber-green", # 248
|
||||
"amber", # 249
|
||||
"aghast", # 250
|
||||
"activated", # 251
|
||||
"acidic", # 252
|
||||
"abused", # 253
|
||||
"abstruse", # 254
|
||||
"abject", # 255
|
||||
]
|
||||
|
||||
ADJECTIVES = '''
|
||||
wrathful worthy weird warm volatile veiled vacuous useless
|
||||
upset unsoiled unsightly unpronounceable unfriendly unfree unfit unfaithful
|
||||
unchaste unbroken unbound unblessed unbefitting unaltered unabused unable
|
||||
ugly tongued thorny thirsty thick terminal ten-sided teeming
|
||||
tangerine taken substantial stupefying stringy strange stillborn sticky
|
||||
stagnant spongy sour soul-destroying smoldering smitten slain six-sided
|
||||
shifting shadowy severed seven-sided serene salty rust-red royal
|
||||
rotten riddled resentful regrettable reeking rare rank rancid
|
||||
quiescent putrid putrid putrescent prehistoric predatory predaceous porous
|
||||
poisonous pierced phlegmatic petrifying pessimal pathetic odorless oddish
|
||||
obsessed obscene numb nine-sided nasty mysterious mute musky
|
||||
morose moribund moldy miasmic material many-lobed malodorous malign
|
||||
maimed luminescent low-cut lousy live limp lifeless leering
|
||||
leaky layered latent lackluster jagged irregular iridescent intangible
|
||||
infinite inept incomprehensible in-between improper idle hunted hideous
|
||||
heavy hairy guilty grotesque grey greedy gory gorgeous
|
||||
gooey golden-brown golden ghastly frostbitten fresh-cut freakish frantic
|
||||
fossilized formless formidable floccose five-lobed firstborn filthy fickle
|
||||
fetid fertile fearful fatal familiar fallen fallacious faint
|
||||
faceless extinct esoteric errant emergent elastic eight-sided eerie
|
||||
ebon dysphoric dying dumb dull-purple dull dull dull
|
||||
dormant doomed disfigured dirty defenseless deep-pink deep deconsecrated
|
||||
deathlike deadly dead dark-blue dark curly curious cured
|
||||
cunning crystalline cryptic crying crumbly crimson crested creepy
|
||||
crazy corrupt corporeal contemptible contained concrete cloudy chopped
|
||||
chained caustic catholic cathartic captive cancerous cabalistic burnt
|
||||
buoyant bronze-red bronze broken bright-red breathless bound bound
|
||||
bottomless bony bodiless blue-lilac blue bloody bloodthirsty bloodsucking
|
||||
bloodstained bloodcurdling blonde blistered blank bitter bilgy bewitched
|
||||
befouled beardless bastardly barbed baleful balding awkward awful
|
||||
atrocious arcane appalling antic anonymous angry ample ambiguous
|
||||
amber-green amber aghast activated acidic abused abstruse abject
|
||||
'''.split()
|
||||
|
|
|
|||
27
hexdump.py
Normal file
27
hexdump.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
import string
|
||||
import time
|
||||
|
||||
startup = time.time()
|
||||
|
||||
def _print_line(write, ts, line, width=16):
|
||||
h,m,s,ms = int(ts//3600), int((ts//60)%60), int(ts%60), int((ts%1.0) * 1000)
|
||||
timestamp = f'{h: 3d}:{m:02d}:{s:02d}:{ms:03d}'
|
||||
line = list(line) + [None]*(width-len(line))
|
||||
hexcol = '\033[0m'
|
||||
col = lambda b, s: s if b != 0 else f'\033[91m{s}{hexcol}'
|
||||
hexfmt = ' '.join(
|
||||
' '.join(col(b, f'{b:02x}') if b is not None else ' ' for b in line[i*8:i*8+8])
|
||||
for i in range(1 + (len(line)-1)//8))
|
||||
asciifmt = ''.join(chr(c) if c is not None and chr(c) in string.printable and c>=0x20 else '.' for c in line)
|
||||
write(f'\033[38;5;244m{timestamp} {hexcol}{hexfmt} \033[38;5;244m|\033[92m{asciifmt}\033[38;5;244m|\033[0m', flush=True, end='')
|
||||
|
||||
def hexdump(write, packet, width=16):
|
||||
ts = time.time()
|
||||
while len(packet) > width:
|
||||
chunk, packet = packet[:width], packet[width:]
|
||||
_print_line(write, ts-startup, chunk, width=width)
|
||||
write()
|
||||
_print_line(write, ts-startup, packet, width=width)
|
||||
write()
|
||||
|
||||
446
hexnoise.py
446
hexnoise.py
|
|
@ -1,33 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import time
|
||||
import string
|
||||
import enum
|
||||
import sys
|
||||
from contextlib import contextmanager, suppress, wraps
|
||||
|
||||
import serial
|
||||
from cobs import cobs
|
||||
import uinput
|
||||
from noise.connection import NoiseConnection, Keypair
|
||||
from noise.exceptions import NoiseInvalidMessage
|
||||
|
||||
def _print_line(write, ts, line, width=16):
|
||||
h,m,s,ms = int(ts//3600), int((ts//60)%60), int(ts%60), int((ts%1.0) * 1000)
|
||||
timestamp = f'{h: 3d}:{m:02d}:{s:02d}:{ms:03d}'
|
||||
line = list(line) + [None]*(width-len(line))
|
||||
hexcol = '\033[0m'
|
||||
col = lambda b, s: s if b != 0 else f'\033[91m{s}{hexcol}'
|
||||
hexfmt = ' '.join(
|
||||
' '.join(col(b, f'{b:02x}') if b is not None else ' ' for b in line[i*8:i*8+8])
|
||||
for i in range(1 + (len(line)-1)//8))
|
||||
asciifmt = ''.join(chr(c) if c is not None and chr(c) in string.printable and c>=0x20 else '.' for c in line)
|
||||
write(f'\033[38;5;244m{timestamp} {hexcol}{hexfmt} \033[38;5;244m|\033[92m{asciifmt}\033[38;5;244m|\033[0m', flush=True, end='')
|
||||
|
||||
startup = time.time()
|
||||
|
||||
def hexdump(write, packet, width=16):
|
||||
ts = time.time()
|
||||
while len(packet) > width:
|
||||
chunk, packet = packet[:width], packet[width:]
|
||||
_print_line(write, ts-startup, chunk, width=width)
|
||||
write()
|
||||
_print_line(write, ts-startup, packet, width=width)
|
||||
write()
|
||||
import keymap
|
||||
from hexdump import hexdump
|
||||
|
||||
class PacketType(enum.Enum):
|
||||
_RESERVED = 0
|
||||
|
|
@ -39,147 +24,308 @@ class ReportType(enum.Enum):
|
|||
_RESERVED = 0
|
||||
KEYBOARD = 1
|
||||
MOUSE = 2
|
||||
PAIRING = 3 # keyboard in disguise
|
||||
PAIRING_INPUT = 3
|
||||
PAIRING_SUCESS = 4
|
||||
PAIRING_ERROR = 5
|
||||
|
||||
def send_packet(ser, pkt_type, data, width=16):
|
||||
print(f'\033[93mSending {len(data)} bytes, packet type {pkt_type.name} ({pkt_type.value})\033[0m')
|
||||
hexdump(print, data, width)
|
||||
data = bytes([pkt_type.value]) + data
|
||||
encoded = cobs.encode(data) + b'\0'
|
||||
ser.write(encoded)
|
||||
ser.flushOutput()
|
||||
class Packetizer:
|
||||
def __init__(self, serial, debug=False, width=16):
|
||||
self.ser, self.debug, self.width = serial, debug, width
|
||||
self.ser.write(b'\0') # COBS synchronization
|
||||
|
||||
def receive_packet(ser, width=16):
|
||||
packet = ser.read_until(b'\0')
|
||||
data = cobs.decode(packet[:-1])
|
||||
#print(f'\033[93mReceived {len(data)} bytes\033[0m')
|
||||
#hexdump(print, data, width)
|
||||
return data[0], data[1:]
|
||||
def send_packet(self, pkt_type, data):
|
||||
if self.debug:
|
||||
print(f'\033[93mSending {len(data)} bytes, packet type {pkt_type.name} ({pkt_type.value})\033[0m')
|
||||
hexdump(print, data, self.width)
|
||||
data = bytes([pkt_type.value]) + data
|
||||
encoded = cobs.encode(data) + b'\0'
|
||||
self.ser.write(encoded)
|
||||
self.ser.flushOutput()
|
||||
|
||||
def receive_packet(self):
|
||||
packet = self.ser.read_until(b'\0')
|
||||
data = cobs.decode(packet[:-1])
|
||||
if self.debug:
|
||||
print(f'\033[93mReceived {len(data)} bytes\033[0m')
|
||||
hexdump(print, data, self.width)
|
||||
return PacketType(data[0]), data[1:]
|
||||
|
||||
class KeyMapper:
|
||||
Keycode = enum.Enum('Keycode', start=0, names='''
|
||||
KEY_NONE _RESERVED_0x01 _RESERVED_0x02 _RESERVED_0x03 KEY_A KEY_B KEY_C KEY_D
|
||||
KEY_E KEY_F KEY_G KEY_H KEY_I KEY_J KEY_K KEY_L
|
||||
KEY_M KEY_N KEY_O KEY_P KEY_Q KEY_R KEY_S KEY_T
|
||||
KEY_U KEY_V KEY_W KEY_X KEY_Y KEY_Z KEY_1 KEY_2
|
||||
KEY_3 KEY_4 KEY_5 KEY_6 KEY_7 KEY_8 KEY_9 KEY_0
|
||||
KEY_ENTER KEY_ESC KEY_BACKSPACE KEY_TAB KEY_SPACE KEY_MINUS KEY_EQUAL KEY_LEFTBRACE
|
||||
KEY_RIGHTBRACE KEY_BACKSLASH KEY_HASH KEY_SEMICOLON KEY_APOSTROPHE KEY_GRAVE KEY_COMMA KEY_DOT
|
||||
KEY_SLASH KEY_CAPSLOCK KEY_F1 KEY_F2 KEY_F3 KEY_F4 KEY_F5 KEY_F6
|
||||
KEY_F7 KEY_F8 KEY_F9 KEY_F10 KEY_F11 KEY_F12 KEY_SYSRQ KEY_SCROLLLOCK
|
||||
KEY_PAUSE KEY_INSERT KEY_HOME KEY_PAGEUP KEY_DELETE KEY_END KEY_PAGEDOWN KEY_RIGHT
|
||||
KEY_LEFT KEY_DOWN KEY_UP KEY_NUMLOCK KEY_KPSLASH KEY_KPASTERISK KEY_KPMINUS KEY_KPPLUS
|
||||
KEY_KPENTER KEY_KP1 KEY_KP2 KEY_KP3 KEY_KP4 KEY_KP5 KEY_KP6 KEY_KP7
|
||||
KEY_KP8 KEY_KP9 KEY_KP0 KEY_KPDOT KEY_102ND KEY_COMPOSE KEY_POWER KEY_KPEQUAL
|
||||
KEY_F13 KEY_F14 KEY_F15 KEY_F16 KEY_F17 KEY_F18 KEY_F19 KEY_F20
|
||||
KEY_F21 KEY_F22 KEY_F23 KEY_F24 KEY_OPEN KEY_HELP KEY_PROPS KEY_FRONT
|
||||
KEY_STOP KEY_AGAIN KEY_UNDO KEY_CUT KEY_COPY KEY_PASTE KEY_FIND KEY_MUTE
|
||||
KEY_VOLUMEUP KEY_VOLUMEDOWN _RESERVED_0x82 _RESERVED_0x83 _RESERVED_0x84 KEY_KPCOMMA _RESERVED_0x86 KEY_RO
|
||||
KEY_KATAKANAHIRAGANA KEY_YEN KEY_HENKAN KEY_MUHENKAN KEY_KPJPCOMMA _RESERVED_0x8D _RESERVED_0x8E _RESERVED_0x8F
|
||||
KEY_HANGEUL KEY_HANJA KEY_KATAKANA KEY_HIRAGANA KEY_ZENKAKUHANKAKU _RESERVED_0x95 _RESERVED_0x96 _RESERVED_0x97
|
||||
_RESERVED_0x98 _RESERVED_0x99 _RESERVED_0x9A _RESERVED_0x9B _RESERVED_0x9C _RESERVED_0x9D _RESERVED_0x9E _RESERVED_0x9F
|
||||
_RESERVED_0xA0 _RESERVED_0xA1 _RESERVED_0xA2 _RESERVED_0xA3 _RESERVED_0xA4 _RESERVED_0xA5 _RESERVED_0xA6 _RESERVED_0xA7
|
||||
_RESERVED_0xA8 _RESERVED_0xA9 _RESERVED_0xAA _RESERVED_0xAB _RESERVED_0xAC _RESERVED_0xAD _RESERVED_0xAE _RESERVED_0xAF
|
||||
_RESERVED_0xB0 _RESERVED_0xB1 _RESERVED_0xB2 _RESERVED_0xB3 _RESERVED_0xB4 _RESERVED_0xB5 KEY_KPLEFTPAREN KEY_KPRIGHTPAREN
|
||||
_RESERVED_0xB8 _RESERVED_0xB9 _RESERVED_0xBA _RESERVED_0xBB _RESERVED_0xBC _RESERVED_0xBD _RESERVED_0xBE _RESERVED_0xBF
|
||||
_RESERVED_0xC0 _RESERVED_0xC1 _RESERVED_0xC2 _RESERVED_0xC3 _RESERVED_0xC4 _RESERVED_0xC5 _RESERVED_0xC6 _RESERVED_0xC7
|
||||
_RESERVED_0xC8 _RESERVED_0xC9 _RESERVED_0xCA _RESERVED_0xCB _RESERVED_0xCC _RESERVED_0xCD _RESERVED_0xCE _RESERVED_0xCF
|
||||
_RESERVED_0xD0 _RESERVED_0xD1 _RESERVED_0xD2 _RESERVED_0xD3 _RESERVED_0xD4 _RESERVED_0xD5 _RESERVED_0xD6 _RESERVED_0xD7
|
||||
_RESERVED_0xD8 _RESERVED_0xD9 _RESERVED_0xDA _RESERVED_0xDB _RESERVED_0xDC _RESERVED_0xDD _RESERVED_0xDE _RESERVED_0xDF
|
||||
_RESERVED_0xE0 _RESERVED_0xE1 _RESERVED_0xE2 _RESERVED_0xE3 _RESERVED_0xE4 _RESERVED_0xE5 _RESERVED_0xE6 _RESERVED_0xE7
|
||||
_RESERVED_0xE8 _RESERVED_0xE9 _RESERVED_0xEA _RESERVED_0xEB _RESERVED_0xEC _RESERVED_0xED _RESERVED_0xEE _RESERVED_0xEF
|
||||
_RESERVED_0xF0 _RESERVED_0xF1 _RESERVED_0xF2 _RESERVED_0xF3 _RESERVED_0xF4 _RESERVED_0xF5 _RESERVED_0xF6 _RESERVED_0xF7
|
||||
_RESERVED_0xF8 _RESERVED_0xF9 _RESERVED_0xFA _RESERVED_0xFB _RESERVED_0xFC _RESERVED_0xFD _RESERVED_0xFE _RESERVED_0xFF
|
||||
''')
|
||||
|
||||
MODIFIERS = [ uinput.ev.KEY_LEFTCTRL, uinput.ev.KEY_LEFTSHIFT, uinput.ev.KEY_LEFTALT, uinput.ev.KEY_LEFTMETA,
|
||||
uinput.ev.KEY_RIGHTCTRL, uinput.ev.KEY_RIGHTSHIFT, uinput.ev.KEY_RIGHTALT, uinput.ev.KEY_RIGHTMETA ]
|
||||
|
||||
ALL_KEYS = [ v for k, v in uinput.ev.__dict__.items() if k.startswith('KEY_') ]
|
||||
REGULAR_MAP = { kc.value: getattr(uinput.ev, kc.name) for kc in Keycode if hasattr(uinput.ev, kc.name) }
|
||||
|
||||
@classmethod
|
||||
def map_modifiers(kls, val):
|
||||
return [ mod for i, mod in enumerate(kls.MODIFIERS) if val & (1<<i) ]
|
||||
|
||||
@classmethod
|
||||
def map_regulars(kls, keycodes):
|
||||
return [ kls.REGULAR_MAP[kc] for kc in keycodes if kc != 0 and kc in kls.REGULAR_MAP ]
|
||||
|
||||
class Magic:
|
||||
@classmethod
|
||||
def map_bytes_to_incantation(kls, data):
|
||||
elems = [ f'{kls.ADJECTIVES[a]} {kls.NOUNS[b]}' for a, b in zip(data[0::2], data[1::2]) ]
|
||||
nfirst = ", ".join(elems[:-1])
|
||||
return f'{nfirst} and {elems[-1]}'
|
||||
|
||||
ADJECTIVES = '''
|
||||
wrathful worthy weird warm volatile veiled vacuous useless
|
||||
upset unsoiled unsightly unpronounceable unfriendly unfree unfit unfaithful
|
||||
unchaste unbroken unbound unblessed unbefitting unaltered unabused unable
|
||||
ugly tongued thorny thirsty thick terminal ten-sided teeming
|
||||
tangerine taken substantial stupefying stringy strange stillborn sticky
|
||||
stagnant spongy sour soul-destroying smoldering smitten slain six-sided
|
||||
shifting shadowy severed seven-sided serene salty rust-red royal
|
||||
rotten riddled resentful regrettable reeking rare rank rancid
|
||||
quiescent putrid putrid putrescent prehistoric predatory predaceous porous
|
||||
poisonous pierced phlegmatic petrifying pessimal pathetic odorless oddish
|
||||
obsessed obscene numb nine-sided nasty mysterious mute musky
|
||||
morose moribund moldy miasmic material many-lobed malodorous malign
|
||||
maimed luminescent low-cut lousy live limp lifeless leering
|
||||
leaky layered latent lackluster jagged irregular iridescent intangible
|
||||
infinite inept incomprehensible in-between improper idle hunted hideous
|
||||
heavy hairy guilty grotesque grey greedy gory gorgeous
|
||||
gooey golden-brown golden ghastly frostbitten fresh-cut freakish frantic
|
||||
fossilized formless formidable floccose five-lobed firstborn filthy fickle
|
||||
fetid fertile fearful fatal familiar fallen fallacious faint
|
||||
faceless extinct esoteric errant emergent elastic eight-sided eerie
|
||||
ebon dysphoric dying dumb dull-purple dull dull dull
|
||||
dormant doomed disfigured dirty defenseless deep-pink deep deconsecrated
|
||||
deathlike deadly dead dark-blue dark curly curious cured
|
||||
cunning crystalline cryptic crying crumbly crimson crested creepy
|
||||
crazy corrupt corporeal contemptible contained concrete cloudy chopped
|
||||
chained caustic catholic cathartic captive cancerous cabalistic burnt
|
||||
buoyant bronze-red bronze broken bright-red breathless bound bound
|
||||
bottomless bony bodiless blue-lilac blue bloody bloodthirsty bloodsucking
|
||||
bloodstained bloodcurdling blonde blistered blank bitter bilgy bewitched
|
||||
befouled beardless bastardly barbed baleful balding awkward awful
|
||||
atrocious arcane appalling antic anonymous angry ample ambiguous
|
||||
amber-green amber aghast activated acidic abused abstruse abject
|
||||
'''.split()
|
||||
|
||||
NOUNS = '''
|
||||
yolk writing wrath wound worm wings whistle watchdog
|
||||
waste vomit vermin variation underachievement tusk troll trick
|
||||
transplant transgression tooth tongue tickle tick thorn thistle
|
||||
thing terror tentacle tease surrender surge sucker substance
|
||||
storm stone stew stalk squid sprout sponge spill
|
||||
spider sphere spectacle speck spawn soul solution snout
|
||||
snake smell sloth slime slice sleeper slave sinew
|
||||
shell shape seizure seed schism scam scale sainthood
|
||||
root robe roach rinse remains relay rejuvenation realization
|
||||
reaction ransom pupa pride prey predator potion pornography
|
||||
polyp plum pleasure pitch pigeon phenomenon pest periwinkle
|
||||
percolation parasite pair oyster orphan orgasm organism orchid
|
||||
object nail mushroom murder mucus movement mother mold
|
||||
mist mildew metal mesh meddling mayhem masterpiece masonry
|
||||
mask manhood maggot lust loop living_thing liquor liquid
|
||||
lining laceration knife kitten kiss jumper jest instrument
|
||||
injustice injury influence indulgence incursion impulse imago hound
|
||||
horn hook hoof heirloom heart hawk hare hair
|
||||
gulp guardian grass goat gnat gluttony glowworm gasp
|
||||
game fusion fungus frustration frog foul foot food
|
||||
fog foal fluke fluff flower flicker flea flattery
|
||||
flask flare firefly finger filtration female feeder feather
|
||||
fart fang failure face fabrication extract exodus evil
|
||||
envy enema embryo egress echo eater ear dwarf
|
||||
dust drop draft domestication distortion dew depravity deity
|
||||
death daughter dash dagger culture crutch crow critter
|
||||
creeper creation crab corruption cocoon claw chip child
|
||||
cell catch carving carrot carnival cancer butterfly burn
|
||||
buildup brush brew bottle boot book bone blunder
|
||||
blot blood blink bite bird benthos beak basket
|
||||
bark ball baby axolotl ashes artifact arson armor
|
||||
apparition antenna alms alienation advent adornment abomination abandonment
|
||||
'''.split()
|
||||
|
||||
class NoiseEngine:
|
||||
def __init__(self, packetizer, debug=False):
|
||||
self.debug = debug
|
||||
self.packetizer = packetizer
|
||||
self.static_local = bytes([ # FIXME
|
||||
0xbb, 0xdb, 0x4c, 0xdb, 0xd3, 0x09, 0xf1, 0xa1, 0xf2, 0xe1, 0x45, 0x69, 0x67, 0xfe, 0x28, 0x8c,
|
||||
0xad, 0xd6, 0xf7, 0x12, 0xd6, 0x5d, 0xc7, 0xb7, 0x79, 0x3d, 0x5e, 0x63, 0xda, 0x6b, 0x37, 0x5b
|
||||
])
|
||||
self.proto = NoiseConnection.from_name(b'Noise_XX_25519_ChaChaPoly_BLAKE2s')
|
||||
self.proto.set_as_initiator()
|
||||
self.proto.set_keypair_from_private_bytes(Keypair.STATIC, self.static_local)
|
||||
self.proto.start_handshake()
|
||||
self.packetizer.send_packet(PacketType.INITIATE_HANDSHAKE, b'')
|
||||
self.debug_print('Handshake started')
|
||||
|
||||
@wraps(print)
|
||||
def debug_print(self, *args, **kwargs):
|
||||
if self.debug:
|
||||
print(*args, **kwargs)
|
||||
|
||||
def perform_handshake(self):
|
||||
while True:
|
||||
if self.proto.handshake_finished:
|
||||
break
|
||||
self.packetizer.send_packet(PacketType.HANDSHAKE, self.proto.write_message())
|
||||
|
||||
if self.proto.handshake_finished:
|
||||
break
|
||||
pkt_type, payload = self.packetizer.receive_packet()
|
||||
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.')
|
||||
if self.debug:
|
||||
print('Handshake finished, handshake hash:')
|
||||
hexdump(print, self.proto.get_handshake_hash(), args.width)
|
||||
|
||||
def channel_binding_incantation(self):
|
||||
hhash = self.proto.get_handshake_hash()
|
||||
return '\n'.join(Magic.map_bytes_to_incantation(hhash[i:i+8]) for i in range(0, 16, 8))
|
||||
|
||||
def receive_loop(self):
|
||||
while True:
|
||||
try:
|
||||
pkt_type, received = self.packetizer.receive_packet()
|
||||
except Exception as e:
|
||||
self.debug_print('Invalid framing:', e)
|
||||
|
||||
if pkt_type is not PacketType.DATA:
|
||||
raise UserWarning(f'Unexpected packet type {pkt_type}. Ignoring.')
|
||||
continue
|
||||
|
||||
rtype, data = self._decrypt(received)
|
||||
if self.debug:
|
||||
print(f'Decrypted packet {rtype} ({rtype.value}):')
|
||||
hexdump(print, data, args.width)
|
||||
yield rtype, data
|
||||
|
||||
def _decrypt(self, received):
|
||||
try:
|
||||
data = self.proto.decrypt(received)
|
||||
return ReportType(data[0]), data[1:]
|
||||
|
||||
except NoiseInvalidMessage as e:
|
||||
self.debug_print('Invalid noise message', e)
|
||||
for i in range(3):
|
||||
with self._nonce_lookahead() as set_nonce:
|
||||
set_nonce(i)
|
||||
data = self.proto.decrypt(received)
|
||||
return ReportType(data[0]), data[1:]
|
||||
else:
|
||||
self.debug_print(' Unrecoverable.')
|
||||
raise e
|
||||
self.debug_print(f' Recovered. n={n}')
|
||||
|
||||
@contextmanager
|
||||
def _nonce_lookahead(self):
|
||||
nold = self.proto.noise_protocol.cipher_state_decrypt.n
|
||||
def setter(n):
|
||||
self.proto.noise_protocol.cipher_state_decrypt.n = nold + n
|
||||
|
||||
with suppress(NoiseInvalMessage):
|
||||
yield setter
|
||||
|
||||
proto.noise_protocol.cipher_state_decrypt.n = nold
|
||||
|
||||
def pairing_messages(self):
|
||||
user_input = ''
|
||||
for msg_type, payload in self.receive_loop():
|
||||
if msg_type == ReportType.PAIRING_INPUT:
|
||||
ch = chr(payload[0])
|
||||
if ch == '\b':
|
||||
user_input = user_input[:-1]
|
||||
else:
|
||||
user_input += ch
|
||||
yield user_input
|
||||
|
||||
elif msg_type == ReportType.PAIRING_SUCESS:
|
||||
break
|
||||
|
||||
elif msg_type == ReportType.PAIRING_ERROR:
|
||||
raise ValueError('Device-side pairing error') # FIXME find better exception subclass here
|
||||
|
||||
else:
|
||||
raise ValueError('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
|
||||
keys = { *KeyMapper.map_modifiers(modbyte), *KeyMapper.map_regulars(keycodes) }
|
||||
if args.debug:
|
||||
print('Emitting:', keys)
|
||||
|
||||
for key in keys - old_kcs:
|
||||
ui.emit(key, 1, syn=False)
|
||||
for key in old_kcs - keys:
|
||||
ui.emit(key, 0, syn=False)
|
||||
ui.syn()
|
||||
old_kcs = keys
|
||||
|
||||
elif msg_type == ReportType.MOUSE:
|
||||
# FIXME unhandled
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
import serial
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('serial')
|
||||
parser.add_argument('baudrate')
|
||||
parser.add_argument('-w', '--width', type=int, default=16, help='Number of bytes to display in one line')
|
||||
parser.add_argument('-d', '--debug', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
ser = serial.Serial(args.serial, args.baudrate)
|
||||
ser.write(b'\0') # COBS synchronization
|
||||
packetizer = Packetizer(ser, debug=args.debug, width=args.width)
|
||||
noise = NoiseEngine(packetizer, debug=args.debug)
|
||||
noise.perform_handshake()
|
||||
|
||||
import uinput
|
||||
ALL_KEYS = [ v for k, v in uinput.ev.__dict__.items() if k.startswith('KEY_') ]
|
||||
MODIFIERS = [
|
||||
uinput.ev.KEY_LEFTCTRL,
|
||||
uinput.ev.KEY_LEFTSHIFT,
|
||||
uinput.ev.KEY_LEFTALT,
|
||||
uinput.ev.KEY_LEFTMETA,
|
||||
uinput.ev.KEY_RIGHTCTRL,
|
||||
uinput.ev.KEY_RIGHTSHIFT,
|
||||
uinput.ev.KEY_RIGHTALT,
|
||||
uinput.ev.KEY_RIGHTMETA,
|
||||
]
|
||||
map_modifiers = lambda x: [ mod for i, mod in enumerate(MODIFIERS) if x & (1<<i) ]
|
||||
import keymap
|
||||
map_regular = { v: getattr(uinput.ev, k) for k, v in keymap.__dict__.items() if k.startswith('KEY_') }
|
||||
map_regulars = lambda keycodes: [ map_regular[kc] for kc in keycodes if kc != 0 and kc in map_regular ]
|
||||
|
||||
from noise.connection import NoiseConnection, Keypair
|
||||
from noise.exceptions import NoiseInvalidMessage
|
||||
|
||||
STATIC_LOCAL = bytes([
|
||||
0xbb, 0xdb, 0x4c, 0xdb, 0xd3, 0x09, 0xf1, 0xa1,
|
||||
0xf2, 0xe1, 0x45, 0x69, 0x67, 0xfe, 0x28, 0x8c,
|
||||
0xad, 0xd6, 0xf7, 0x12, 0xd6, 0x5d, 0xc7, 0xb7,
|
||||
0x79, 0x3d, 0x5e, 0x63, 0xda, 0x6b, 0x37, 0x5b
|
||||
])
|
||||
|
||||
proto = NoiseConnection.from_name(b'Noise_XX_25519_ChaChaPoly_BLAKE2s')
|
||||
proto.set_as_initiator()
|
||||
proto.set_keypair_from_private_bytes(Keypair.STATIC, STATIC_LOCAL)
|
||||
proto.start_handshake()
|
||||
send_packet(ser, PacketType.INITIATE_HANDSHAKE, b'', args.width)
|
||||
print('Handshake started')
|
||||
|
||||
while True:
|
||||
if proto.handshake_finished:
|
||||
break
|
||||
send_packet(ser, PacketType.HANDSHAKE, proto.write_message(), args.width)
|
||||
|
||||
if proto.handshake_finished:
|
||||
break
|
||||
pkt_type, payload = receive_packet(ser, args.width)
|
||||
if pkt_type == PacketType.HANDSHAKE.value:
|
||||
proto.read_message(payload)
|
||||
else:
|
||||
print(f'Incorrect packet type {pkt_type}. Ignoring since this is only test code.')
|
||||
print('Handshake finished, handshake hash:')
|
||||
hexdump(print, proto.get_handshake_hash(), args.width)
|
||||
|
||||
from nouns import NOUNS
|
||||
from adjectives import ADJECTIVES
|
||||
def map_bytes_to_incantation(data):
|
||||
elems = [ f'{ADJECTIVES[a]} {NOUNS[b]}' for a, b in zip(data[0::2], data[1::2]) ]
|
||||
nfirst = ", ".join(elems[:-1])
|
||||
return f'{nfirst} and {elems[-1]}'
|
||||
print('Handshake channel binding incantation:')
|
||||
hhash = proto.get_handshake_hash()
|
||||
print(' ' + map_bytes_to_incantation(hhash[:8 ]))
|
||||
print(' ' + map_bytes_to_incantation(hhash[ 8:16 ]))
|
||||
print(' ' + map_bytes_to_incantation(hhash[ 16:24 ]))
|
||||
print(' ' + map_bytes_to_incantation(hhash[ 24:]))
|
||||
print(noise.channel_binding_incantation())
|
||||
|
||||
old_kcs = set()
|
||||
def noise_rx(received, ui):
|
||||
global old_kcs
|
||||
|
||||
data = proto.decrypt(received)
|
||||
#print('Decrypted data:')
|
||||
#hexdump(print, data, args.width)
|
||||
|
||||
rtype, rlen, *report = data
|
||||
if rtype != 1 or rlen != 8:
|
||||
return
|
||||
|
||||
modbyte, _reserved, *keycodes = report
|
||||
keys = map_modifiers(modbyte) + map_regulars(keycodes)
|
||||
print('Emitting:', keys)
|
||||
keyset = set(keys)
|
||||
|
||||
for key in keyset - old_kcs:
|
||||
ui.emit(key, 1, syn=False)
|
||||
for key in old_kcs - keyset:
|
||||
ui.emit(key, 0, syn=False)
|
||||
ui.syn()
|
||||
|
||||
old_kcs = keyset
|
||||
|
||||
with uinput.Device(ALL_KEYS) as ui:
|
||||
while True:
|
||||
try:
|
||||
pkt_type, received = receive_packet(ser, args.width)
|
||||
if pkt_type != PacketType.DATA.value:
|
||||
print(f'Unexpected packet type {pkt_type}. Ignoring.')
|
||||
continue
|
||||
|
||||
try:
|
||||
noise_rx(received, ui)
|
||||
except NoiseInvalidMessage as e:
|
||||
orig_n = proto.noise_protocol.cipher_state_decrypt.n
|
||||
print('Invalid noise message', e)
|
||||
for n in [orig_n+1, orig_n+2, orig_n+3]:
|
||||
try:
|
||||
proto.noise_protocol.cipher_state_decrypt.n = n
|
||||
noise_rx(received, ui)
|
||||
print(f' Recovered. n={n}')
|
||||
break
|
||||
except NoiseInvalidMessage as e:
|
||||
pass
|
||||
else:
|
||||
print(' Unrecoverable.')
|
||||
proto.noise_protocol.cipher_state_decrypt.n = orig_n
|
||||
except Exception as e:
|
||||
print('Invalid framing:', e)
|
||||
for user_input in noise.pairing_messages():
|
||||
print('\033[2K\r', end='')
|
||||
print('Pairing input:', user_input, end='', flush=True)
|
||||
print()
|
||||
print('Pairing success')
|
||||
|
||||
noise.uinput_passthrough()
|
||||
|
|
|
|||
176
keymap.py
176
keymap.py
|
|
@ -1,176 +0,0 @@
|
|||
KEY_RESERVED = 0x00
|
||||
KEY_A = 0x04
|
||||
KEY_B = 0x05
|
||||
KEY_C = 0x06
|
||||
KEY_D = 0x07
|
||||
KEY_E = 0x08
|
||||
KEY_F = 0x09
|
||||
KEY_G = 0x0a
|
||||
KEY_H = 0x0b
|
||||
KEY_I = 0x0c
|
||||
KEY_J = 0x0d
|
||||
KEY_K = 0x0e
|
||||
KEY_L = 0x0f
|
||||
KEY_M = 0x10
|
||||
KEY_N = 0x11
|
||||
KEY_O = 0x12
|
||||
KEY_P = 0x13
|
||||
KEY_Q = 0x14
|
||||
KEY_R = 0x15
|
||||
KEY_S = 0x16
|
||||
KEY_T = 0x17
|
||||
KEY_U = 0x18
|
||||
KEY_V = 0x19
|
||||
KEY_W = 0x1a
|
||||
KEY_X = 0x1b
|
||||
KEY_Y = 0x1c
|
||||
KEY_Z = 0x1d
|
||||
|
||||
KEY_1 = 0x1e
|
||||
KEY_2 = 0x1f
|
||||
KEY_3 = 0x20
|
||||
KEY_4 = 0x21
|
||||
KEY_5 = 0x22
|
||||
KEY_6 = 0x23
|
||||
KEY_7 = 0x24
|
||||
KEY_8 = 0x25
|
||||
KEY_9 = 0x26
|
||||
KEY_0 = 0x27
|
||||
|
||||
KEY_ENTER = 0x28
|
||||
KEY_ESC = 0x29
|
||||
KEY_BACKSPACE = 0x2a
|
||||
KEY_TAB = 0x2b
|
||||
KEY_SPACE = 0x2c
|
||||
KEY_MINUS = 0x2d
|
||||
KEY_EQUAL = 0x2e
|
||||
KEY_LEFTBRACE = 0x2f
|
||||
KEY_RIGHTBRACE = 0x30
|
||||
KEY_BACKSLASH = 0x31
|
||||
KEY_SEMICOLON = 0x33
|
||||
KEY_APOSTROPHE = 0x34
|
||||
KEY_GRAVE = 0x35
|
||||
KEY_COMMA = 0x36
|
||||
KEY_DOT = 0x37
|
||||
KEY_SLASH = 0x38
|
||||
KEY_CAPSLOCK = 0x39
|
||||
|
||||
KEY_F1 = 0x3a
|
||||
KEY_F2 = 0x3b
|
||||
KEY_F3 = 0x3c
|
||||
KEY_F4 = 0x3d
|
||||
KEY_F5 = 0x3e
|
||||
KEY_F6 = 0x3f
|
||||
KEY_F7 = 0x40
|
||||
KEY_F8 = 0x41
|
||||
KEY_F9 = 0x42
|
||||
KEY_F10 = 0x43
|
||||
KEY_F11 = 0x44
|
||||
KEY_F12 = 0x45
|
||||
|
||||
KEY_SYSRQ = 0x46
|
||||
KEY_SCROLLLOCK = 0x47
|
||||
KEY_PAUSE = 0x48
|
||||
KEY_INSERT = 0x49
|
||||
KEY_HOME = 0x4a
|
||||
KEY_PAGEUP = 0x4b
|
||||
KEY_DELETE = 0x4c
|
||||
KEY_END = 0x4d
|
||||
KEY_PAGEDOWN = 0x4e
|
||||
KEY_RIGHT = 0x4f
|
||||
KEY_LEFT = 0x50
|
||||
KEY_DOWN = 0x51
|
||||
KEY_UP = 0x52
|
||||
|
||||
KEY_NUMLOCK = 0x53
|
||||
KEY_KPSLASH = 0x54
|
||||
KEY_KPASTERISK = 0x55
|
||||
KEY_KPMINUS = 0x56
|
||||
KEY_KPPLUS = 0x57
|
||||
KEY_KPENTER = 0x58
|
||||
KEY_KP1 = 0x59
|
||||
KEY_KP2 = 0x5a
|
||||
KEY_KP3 = 0x5b
|
||||
KEY_KP4 = 0x5c
|
||||
KEY_KP5 = 0x5d
|
||||
KEY_KP6 = 0x5e
|
||||
KEY_KP7 = 0x5f
|
||||
KEY_KP8 = 0x60
|
||||
KEY_KP9 = 0x61
|
||||
KEY_KP0 = 0x62
|
||||
KEY_KPDOT = 0x63
|
||||
|
||||
KEY_102ND = 0x64
|
||||
KEY_COMPOSE = 0x65
|
||||
KEY_POWER = 0x66
|
||||
KEY_KPEQUAL = 0x67
|
||||
|
||||
KEY_F13 = 0x68
|
||||
KEY_F14 = 0x69
|
||||
KEY_F15 = 0x6a
|
||||
KEY_F16 = 0x6b
|
||||
KEY_F17 = 0x6c
|
||||
KEY_F18 = 0x6d
|
||||
KEY_F19 = 0x6e
|
||||
KEY_F20 = 0x6f
|
||||
KEY_F21 = 0x70
|
||||
KEY_F22 = 0x71
|
||||
KEY_F23 = 0x72
|
||||
KEY_F24 = 0x73
|
||||
|
||||
KEY_OPEN = 0x74
|
||||
KEY_HELP = 0x75
|
||||
KEY_PROPS = 0x76
|
||||
KEY_FRONT = 0x77
|
||||
KEY_STOP = 0x78
|
||||
KEY_AGAIN = 0x79
|
||||
KEY_UNDO = 0x7a
|
||||
KEY_CUT = 0x7b
|
||||
KEY_COPY = 0x7c
|
||||
KEY_PASTE = 0x7d
|
||||
KEY_FIND = 0x7e
|
||||
KEY_MUTE = 0x7f
|
||||
KEY_VOLUMEUP = 0x80
|
||||
KEY_VOLUMEDOWN = 0x81
|
||||
KEY_KPCOMMA = 0x85
|
||||
KEY_RO = 0x87
|
||||
KEY_KATAKANAHIRAGANA = 0x88
|
||||
KEY_YEN = 0x89
|
||||
KEY_HENKAN = 0x8a
|
||||
KEY_MUHENKAN = 0x8b
|
||||
KEY_KPJPCOMMA = 0x8c
|
||||
KEY_HANGEUL = 0x90
|
||||
KEY_HANJA = 0x91
|
||||
KEY_KATAKANA = 0x92
|
||||
KEY_HIRAGANA = 0x93
|
||||
KEY_ZENKAKUHANKAKU = 0x94
|
||||
KEY_KPLEFTPAREN = 0xb6
|
||||
KEY_KPRIGHTPAREN = 0xb7
|
||||
KEY_LEFTCTRL = 0xe0
|
||||
KEY_LEFTSHIFT = 0xe1
|
||||
KEY_LEFTALT = 0xe2
|
||||
KEY_LEFTMETA = 0xe3
|
||||
KEY_RIGHTCTRL = 0xe4
|
||||
KEY_RIGHTSHIFT = 0xe5
|
||||
KEY_RIGHTALT = 0xe6
|
||||
KEY_RIGHTMETA = 0xe7
|
||||
KEY_PLAYPAUSE = 0xe8
|
||||
KEY_STOPCD = 0xe9
|
||||
KEY_PREVIOUSSONG = 0xea
|
||||
KEY_NEXTSONG = 0xeb
|
||||
KEY_EJECTCD = 0xec
|
||||
KEY_VOLUMEUP = 0xed
|
||||
KEY_VOLUMEDOWN = 0xee
|
||||
KEY_MUTE = 0xef
|
||||
KEY_WWW = 0xf0
|
||||
KEY_BACK = 0xf1
|
||||
KEY_FORWARD = 0xf2
|
||||
KEY_STOP = 0xf3
|
||||
KEY_FIND = 0xf4
|
||||
KEY_SCROLLUP = 0xf5
|
||||
KEY_SCROLLDOWN = 0xf6
|
||||
KEY_EDIT = 0xf7
|
||||
KEY_SLEEP = 0xf8
|
||||
KEY_COFFEE = 0xf9
|
||||
KEY_REFRESH = 0xfa
|
||||
KEY_CALC = 0xfb
|
||||
294
nouns.py
294
nouns.py
|
|
@ -1,260 +1,34 @@
|
|||
|
||||
NOUNS = [
|
||||
"yolk", # 0
|
||||
"writing", # 1
|
||||
"wrath", # 2
|
||||
"wound", # 3
|
||||
"worm", # 4
|
||||
"wings", # 5
|
||||
"whistle", # 6
|
||||
"watchdog", # 7
|
||||
"waste", # 8
|
||||
"vomit", # 9
|
||||
"vermin", # 10
|
||||
"variation", # 11
|
||||
"underachievement", # 12
|
||||
"tusk", # 13
|
||||
"troll", # 14
|
||||
"trick", # 15
|
||||
"transplant", # 16
|
||||
"transgression", # 17
|
||||
"tooth", # 18
|
||||
"tongue", # 19
|
||||
"tickle", # 20
|
||||
"tick", # 21
|
||||
"thorn", # 22
|
||||
"thistle", # 23
|
||||
"thing", # 24
|
||||
"terror", # 25
|
||||
"tentacle", # 26
|
||||
"tease", # 27
|
||||
"surrender", # 28
|
||||
"surge", # 29
|
||||
"sucker", # 30
|
||||
"substance", # 31
|
||||
"storm", # 32
|
||||
"stone", # 33
|
||||
"stew", # 34
|
||||
"stalk", # 35
|
||||
"squid", # 36
|
||||
"sprout", # 37
|
||||
"sponge", # 38
|
||||
"spill", # 39
|
||||
"spider", # 40
|
||||
"sphere", # 41
|
||||
"spectacle", # 42
|
||||
"speck", # 43
|
||||
"spawn", # 44
|
||||
"soul", # 45
|
||||
"solution", # 46
|
||||
"snout", # 47
|
||||
"snake", # 48
|
||||
"smell", # 49
|
||||
"sloth", # 50
|
||||
"slime", # 51
|
||||
"slice", # 52
|
||||
"sleeper", # 53
|
||||
"slave", # 54
|
||||
"sinew", # 55
|
||||
"shell", # 56
|
||||
"shape", # 57
|
||||
"seizure", # 58
|
||||
"seed", # 59
|
||||
"schism", # 60
|
||||
"scam", # 61
|
||||
"scale", # 62
|
||||
"sainthood", # 63
|
||||
"root", # 64
|
||||
"robe", # 65
|
||||
"roach", # 66
|
||||
"rinse", # 67
|
||||
"remains", # 68
|
||||
"relay", # 69
|
||||
"rejuvenation", # 70
|
||||
"realization", # 71
|
||||
"reaction", # 72
|
||||
"ransom", # 73
|
||||
"pupa", # 74
|
||||
"pride", # 75
|
||||
"prey", # 76
|
||||
"predator", # 77
|
||||
"potion", # 78
|
||||
"pornography", # 79
|
||||
"polyp", # 80
|
||||
"plum", # 81
|
||||
"pleasure", # 82
|
||||
"pitch", # 83
|
||||
"pigeon", # 84
|
||||
"phenomenon", # 85
|
||||
"pest", # 86
|
||||
"periwinkle", # 87
|
||||
"percolation", # 88
|
||||
"parasite", # 89
|
||||
"pair", # 90
|
||||
"oyster", # 91
|
||||
"orphan", # 92
|
||||
"orgasm", # 93
|
||||
"organism", # 94
|
||||
"orchid", # 95
|
||||
"object", # 96
|
||||
"nail", # 97
|
||||
"mushroom", # 98
|
||||
"murder", # 99
|
||||
"mucus", # 100
|
||||
"movement", # 101
|
||||
"mother", # 102
|
||||
"mold", # 103
|
||||
"mist", # 104
|
||||
"mildew", # 105
|
||||
"metal", # 106
|
||||
"mesh", # 107
|
||||
"meddling", # 108
|
||||
"mayhem", # 109
|
||||
"masterpiece", # 110
|
||||
"masonry", # 111
|
||||
"mask", # 112
|
||||
"manhood", # 113
|
||||
"maggot", # 114
|
||||
"lust", # 115
|
||||
"loop", # 116
|
||||
"living_thing", # 117
|
||||
"liquor", # 118
|
||||
"liquid", # 119
|
||||
"lining", # 120
|
||||
"laceration", # 121
|
||||
"knife", # 122
|
||||
"kitten", # 123
|
||||
"kiss", # 124
|
||||
"jumper", # 125
|
||||
"jest", # 126
|
||||
"instrument", # 127
|
||||
"injustice", # 128
|
||||
"injury", # 129
|
||||
"influence", # 130
|
||||
"indulgence", # 131
|
||||
"incursion", # 132
|
||||
"impulse", # 133
|
||||
"imago", # 134
|
||||
"hound", # 135
|
||||
"horn", # 136
|
||||
"hook", # 137
|
||||
"hoof", # 138
|
||||
"heirloom", # 139
|
||||
"heart", # 140
|
||||
"hawk", # 141
|
||||
"hare", # 142
|
||||
"hair", # 143
|
||||
"gulp", # 144
|
||||
"guardian", # 145
|
||||
"grass", # 146
|
||||
"goat", # 147
|
||||
"gnat", # 148
|
||||
"gluttony", # 149
|
||||
"glowworm", # 150
|
||||
"gasp", # 151
|
||||
"game", # 152
|
||||
"fusion", # 153
|
||||
"fungus", # 154
|
||||
"frustration", # 155
|
||||
"frog", # 156
|
||||
"foul", # 157
|
||||
"foot", # 158
|
||||
"food", # 159
|
||||
"fog", # 160
|
||||
"foal", # 161
|
||||
"fluke", # 162
|
||||
"fluff", # 163
|
||||
"flower", # 164
|
||||
"flicker", # 165
|
||||
"flea", # 166
|
||||
"flattery", # 167
|
||||
"flask", # 168
|
||||
"flare", # 169
|
||||
"firefly", # 170
|
||||
"finger", # 171
|
||||
"filtration", # 172
|
||||
"female", # 173
|
||||
"feeder", # 174
|
||||
"feather", # 175
|
||||
"fart", # 176
|
||||
"fang", # 177
|
||||
"failure", # 178
|
||||
"face", # 179
|
||||
"fabrication", # 180
|
||||
"extract", # 181
|
||||
"exodus", # 182
|
||||
"evil", # 183
|
||||
"envy", # 184
|
||||
"enema", # 185
|
||||
"embryo", # 186
|
||||
"egress", # 187
|
||||
"echo", # 188
|
||||
"eater", # 189
|
||||
"ear", # 190
|
||||
"dwarf", # 191
|
||||
"dust", # 192
|
||||
"drop", # 193
|
||||
"draft", # 194
|
||||
"domestication", # 195
|
||||
"distortion", # 196
|
||||
"dew", # 197
|
||||
"depravity", # 198
|
||||
"deity", # 199
|
||||
"death", # 200
|
||||
"daughter", # 201
|
||||
"dash", # 202
|
||||
"dagger", # 203
|
||||
"culture", # 204
|
||||
"crutch", # 205
|
||||
"crow", # 206
|
||||
"critter", # 207
|
||||
"creeper", # 208
|
||||
"creation", # 209
|
||||
"crab", # 210
|
||||
"corruption", # 211
|
||||
"cocoon", # 212
|
||||
"claw", # 213
|
||||
"chip", # 214
|
||||
"child", # 215
|
||||
"cell", # 216
|
||||
"catch", # 217
|
||||
"carving", # 218
|
||||
"carrot", # 219
|
||||
"carnival", # 220
|
||||
"cancer", # 221
|
||||
"butterfly", # 222
|
||||
"burn", # 223
|
||||
"buildup", # 224
|
||||
"brush", # 225
|
||||
"brew", # 226
|
||||
"bottle", # 227
|
||||
"boot", # 228
|
||||
"book", # 229
|
||||
"bone", # 230
|
||||
"blunder", # 231
|
||||
"blot", # 232
|
||||
"blood", # 233
|
||||
"blink", # 234
|
||||
"bite", # 235
|
||||
"bird", # 236
|
||||
"benthos", # 237
|
||||
"beak", # 238
|
||||
"basket", # 239
|
||||
"bark", # 240
|
||||
"ball", # 241
|
||||
"baby", # 242
|
||||
"axolotl", # 243
|
||||
"ashes", # 244
|
||||
"artifact", # 245
|
||||
"arson", # 246
|
||||
"armor", # 247
|
||||
"apparition", # 248
|
||||
"antenna", # 249
|
||||
"alms", # 250
|
||||
"alienation", # 251
|
||||
"advent", # 252
|
||||
"adornment", # 253
|
||||
"abomination", # 254
|
||||
"abandonment", # 255
|
||||
]
|
||||
|
||||
NOUNS = '''
|
||||
yolk writing wrath wound worm wings whistle watchdog
|
||||
waste vomit vermin variation underachievement tusk troll trick
|
||||
transplant transgression tooth tongue tickle tick thorn thistle
|
||||
thing terror tentacle tease surrender surge sucker substance
|
||||
storm stone stew stalk squid sprout sponge spill
|
||||
spider sphere spectacle speck spawn soul solution snout
|
||||
snake smell sloth slime slice sleeper slave sinew
|
||||
shell shape seizure seed schism scam scale sainthood
|
||||
root robe roach rinse remains relay rejuvenation realization
|
||||
reaction ransom pupa pride prey predator potion pornography
|
||||
polyp plum pleasure pitch pigeon phenomenon pest periwinkle
|
||||
percolation parasite pair oyster orphan orgasm organism orchid
|
||||
object nail mushroom murder mucus movement mother mold
|
||||
mist mildew metal mesh meddling mayhem masterpiece masonry
|
||||
mask manhood maggot lust loop living_thing liquor liquid
|
||||
lining laceration knife kitten kiss jumper jest instrument
|
||||
injustice injury influence indulgence incursion impulse imago hound
|
||||
horn hook hoof heirloom heart hawk hare hair
|
||||
gulp guardian grass goat gnat gluttony glowworm gasp
|
||||
game fusion fungus frustration frog foul foot food
|
||||
fog foal fluke fluff flower flicker flea flattery
|
||||
flask flare firefly finger filtration female feeder feather
|
||||
fart fang failure face fabrication extract exodus evil
|
||||
envy enema embryo egress echo eater ear dwarf
|
||||
dust drop draft domestication distortion dew depravity deity
|
||||
death daughter dash dagger culture crutch crow critter
|
||||
creeper creation crab corruption cocoon claw chip child
|
||||
cell catch carving carrot carnival cancer butterfly burn
|
||||
buildup brush brew bottle boot book bone blunder
|
||||
blot blood blink bite bird benthos beak basket
|
||||
bark ball baby axolotl ashes artifact arson armor
|
||||
apparition antenna alms alienation advent adornment abomination abandonment
|
||||
'''.split()
|
||||
|
|
|
|||
27
pairing.py
Executable file
27
pairing.py
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env python3
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
class PairingWindow(Gtk.Window):
|
||||
def __init__(self):
|
||||
Gtk.Window.__init__(self, title='SecureHID pairing')
|
||||
self.set_border_width(10)
|
||||
self.set_default_size(400, 100)
|
||||
|
||||
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||
|
||||
self.label = Gtk.Label()
|
||||
self.label.set_line_wrap(True)
|
||||
self.label.set_justify(Gtk.Justification.CENTER)
|
||||
self.label.set_markup('<b>Step 1</b>\n\nSearching for device')
|
||||
self.vbox.add(self.label)
|
||||
|
||||
self.add(self.vbox)
|
||||
|
||||
if __name__ == '__main__':
|
||||
window = PairingWindow()
|
||||
window.connect('destroy', Gtk.main_quit)
|
||||
window.show_all()
|
||||
Gtk.main()
|
||||
|
||||
85
src/demo.c
85
src/demo.c
|
|
@ -184,6 +184,7 @@ int pairing_check(struct NoiseState *st, const char *buf) {
|
|||
}
|
||||
|
||||
void pairing_input(uint8_t modbyte, uint8_t keycode) {
|
||||
char ch = 0;
|
||||
uint8_t level = modbyte & MOD_XSHIFT ? LEVEL_SHIFT : LEVEL_NONE;
|
||||
switch (keycode) {
|
||||
case KEY_ENTER:
|
||||
|
|
@ -191,8 +192,17 @@ void pairing_input(uint8_t modbyte, uint8_t keycode) {
|
|||
if (!pairing_check(&noise_state, pairing_buf)) {
|
||||
persist_remote_key(&noise_state);
|
||||
/* FIXME write key to backup memory */
|
||||
|
||||
uint8_t response = REPORT_PAIRING_SUCCESS;
|
||||
if (send_encrypted_message(&noise_state, &response, sizeof(response)))
|
||||
LOG_PRINTF("Error sending pairing response packet\n");
|
||||
|
||||
} else {
|
||||
/* FIXME sound alarm */
|
||||
|
||||
uint8_t response = REPORT_PAIRING_ERROR;
|
||||
if (send_encrypted_message(&noise_state, &response, sizeof(response)))
|
||||
LOG_PRINTF("Error sending pairing response packet\n");
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -200,17 +210,18 @@ void pairing_input(uint8_t modbyte, uint8_t keycode) {
|
|||
if (pairing_buf_pos > 0)
|
||||
pairing_buf_pos--;
|
||||
pairing_buf[pairing_buf_pos] = '\0'; /* FIXME debug */
|
||||
ch = '\b';
|
||||
break;
|
||||
|
||||
default:
|
||||
for (size_t i=0; keycode_mapping[i].kc != KEY_NONE; i++) {
|
||||
if (keycode_mapping[i].kc == keycode) {
|
||||
char ch = keycode_mapping[i].ch[level];
|
||||
/* FIXME send decoded char to host here instead of raw hid report to reduce buggability */
|
||||
ch = keycode_mapping[i].ch[level];
|
||||
if (!(('a' <= ch && ch <= 'z') ||
|
||||
('A' <= ch && ch <= 'Z') ||
|
||||
('0' <= ch && ch <= '9') ||
|
||||
(ch == ' ')))
|
||||
(ch == ' ') ||
|
||||
(ch == '-')))
|
||||
break; /* ignore special chars */
|
||||
|
||||
if (pairing_buf_pos < sizeof(pairing_buf)-1) /* allow for terminating null byte */ {
|
||||
|
|
@ -218,14 +229,28 @@ void pairing_input(uint8_t modbyte, uint8_t keycode) {
|
|||
pairing_buf[pairing_buf_pos] = '\0'; /* FIXME debug */
|
||||
} else {
|
||||
LOG_PRINTF("Pairing confirmation user input buffer full\n");
|
||||
/* FIXME return error to host? */
|
||||
|
||||
uint8_t response = REPORT_PAIRING_ERROR;
|
||||
if (send_encrypted_message(&noise_state, &response, sizeof(response)))
|
||||
LOG_PRINTF("Error sending pairing response packet\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
LOG_PRINTF("Input: %s\n", pairing_buf);
|
||||
|
||||
if (ch) {
|
||||
LOG_PRINTF("Input: %s\n", pairing_buf);
|
||||
struct hid_report_packet pkt = {
|
||||
.type = REPORT_PAIRING_INPUT,
|
||||
.pairing_input = { .c = ch }
|
||||
};
|
||||
if (send_encrypted_message(&noise_state, (uint8_t *)&pkt, sizeof(pkt))) {
|
||||
LOG_PRINTF("Error sending pairing input packet\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pairing_parse_report(struct hid_report *buf, uint8_t len) {
|
||||
|
|
@ -249,44 +274,36 @@ void pairing_parse_report(struct hid_report *buf, uint8_t len) {
|
|||
memcpy(old_keycodes, buf->keycodes, 6);
|
||||
}
|
||||
|
||||
static void hid_in_message_handler(uint8_t device_id, const uint8_t *data, uint32_t length)
|
||||
{
|
||||
if (length < 4) {
|
||||
LOG_PRINTF("HID report too short\n");
|
||||
return;
|
||||
}
|
||||
if (length > 8) {
|
||||
LOG_PRINTF("HID report too long\n");
|
||||
static void hid_in_message_handler(uint8_t device_id, const uint8_t *data, uint32_t length) {
|
||||
if (length < 4 || length > 8) {
|
||||
LOG_PRINTF("HID report length must be 4 < len < 8, is %d bytes\n", length);
|
||||
return;
|
||||
}
|
||||
|
||||
//LOG_PRINTF("Sending event %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]);
|
||||
struct hid_report_packet pkt = {
|
||||
.len = length,
|
||||
.report = {0}
|
||||
};
|
||||
memcpy(pkt.report, data, length);
|
||||
|
||||
int type = hid_get_type(device_id);
|
||||
if (type == HID_TYPE_KEYBOARD) {
|
||||
if (noise_state.handshake_state == HANDSHAKE_DONE_UNKNOWN_HOST) {
|
||||
pkt.type = PAIRING;
|
||||
pairing_parse_report((struct hid_report *)data, length);
|
||||
} else {
|
||||
pkt.type = HID_KEYBOARD_REPORT;
|
||||
}
|
||||
} else if (type == HID_TYPE_MOUSE) {
|
||||
if (noise_state.handshake_state == HANDSHAKE_DONE_UNKNOWN_HOST) {
|
||||
LOG_PRINTF("Not sending HID mouse report during pairing\n");
|
||||
return;
|
||||
} else {
|
||||
pkt.type = HID_MOUSE_REPORT;
|
||||
}
|
||||
} else {
|
||||
if (type != HID_TYPE_KEYBOARD && type != HID_TYPE_MOUSE) {
|
||||
LOG_PRINTF("Unsupported HID report type %x\n", type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (noise_state.handshake_state == HANDSHAKE_DONE_UNKNOWN_HOST) {
|
||||
if (type == HID_TYPE_KEYBOARD)
|
||||
pairing_parse_report((struct hid_report *)data, length);
|
||||
else
|
||||
LOG_PRINTF("Not sending HID mouse report during pairing\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct hid_report_packet pkt = {
|
||||
.type = type == HID_TYPE_KEYBOARD ? REPORT_KEYBOARD : REPORT_MOUSE,
|
||||
.report = {
|
||||
.len = length,
|
||||
.report = {0}
|
||||
}
|
||||
};
|
||||
memcpy(pkt.report.report, data, length);
|
||||
|
||||
if (send_encrypted_message(&noise_state, (uint8_t *)&pkt, sizeof(pkt))) {
|
||||
LOG_PRINTF("Error sending HID report packet\n");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -14,18 +14,28 @@ enum control_packet_types {
|
|||
};
|
||||
|
||||
enum packet_types {
|
||||
_PACKET_RESERVED = 0,
|
||||
HID_KEYBOARD_REPORT = 1,
|
||||
HID_MOUSE_REPORT = 2,
|
||||
PAIRING = 3,
|
||||
_REPORT_RESERVED = 0,
|
||||
REPORT_KEYBOARD= 1,
|
||||
REPORT_MOUSE= 2,
|
||||
REPORT_PAIRING_INPUT = 3,
|
||||
REPORT_PAIRING_SUCCESS = 4,
|
||||
REPORT_PAIRING_ERROR = 5,
|
||||
};
|
||||
|
||||
struct hid_report_packet {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
uint8_t report[8];
|
||||
union {
|
||||
struct {
|
||||
uint8_t len;
|
||||
uint8_t report[8];
|
||||
} report;
|
||||
struct {
|
||||
char c;
|
||||
} pairing_input;
|
||||
};
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
struct control_packet {
|
||||
uint8_t type;
|
||||
uint8_t payload[0];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue