Handshake working with new abstractions
This commit is contained in:
parent
42d4bebde7
commit
2f4f3e13aa
11 changed files with 1118 additions and 77 deletions
36
hexnoise.py
36
hexnoise.py
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import time
|
||||
import string
|
||||
import enum
|
||||
|
||||
from cobs import cobs
|
||||
|
||||
|
|
@ -28,9 +29,22 @@ def hexdump(write, packet, width=16):
|
|||
_print_line(write, ts-startup, packet, width=width)
|
||||
write()
|
||||
|
||||
def send_packet(ser, data, width=16):
|
||||
print(f'\033[93mSending {len(data)} bytes\033[0m')
|
||||
class PacketType(enum.Enum):
|
||||
_RESERVED = 0
|
||||
INITIATE_HANDSHAKE = 1
|
||||
HANDSHAKE = 2
|
||||
DATA = 3
|
||||
|
||||
class ReportType(enum.Enum):
|
||||
_RESERVED = 0
|
||||
KEYBOARD = 1
|
||||
MOUSE = 2
|
||||
PAIRING = 3 # keyboard in disguise
|
||||
|
||||
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()
|
||||
|
|
@ -40,7 +54,7 @@ def receive_packet(ser, width=16):
|
|||
data = cobs.decode(packet[:-1])
|
||||
print(f'\033[93mReceived {len(data)} bytes\033[0m')
|
||||
hexdump(print, data, width)
|
||||
return data
|
||||
return data[0], data[1:]
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
|
|
@ -85,16 +99,21 @@ if __name__ == '__main__':
|
|||
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, proto.write_message(), args.width)
|
||||
send_packet(ser, PacketType.HANDSHAKE, proto.write_message(), args.width)
|
||||
|
||||
if proto.handshake_finished:
|
||||
break
|
||||
proto.read_message(receive_packet(ser, args.width))
|
||||
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)
|
||||
|
||||
|
|
@ -126,7 +145,11 @@ if __name__ == '__main__':
|
|||
with uinput.Device(ALL_KEYS) as ui:
|
||||
while True:
|
||||
try:
|
||||
received = receive_packet(ser, args.width)
|
||||
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:
|
||||
|
|
@ -145,3 +168,4 @@ if __name__ == '__main__':
|
|||
proto.noise_protocol.cipher_state_decrypt.n = orig_n
|
||||
except Exception as e:
|
||||
print('Invalid framing:', e)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ add_library (usbhost
|
|||
cobs.c
|
||||
noise.c
|
||||
packet_interface.c
|
||||
adjectives.c
|
||||
nouns.c
|
||||
hid_keycodes.c
|
||||
)
|
||||
|
||||
add_subdirectory (crypto)
|
||||
|
|
|
|||
262
src/adjectives.c
Normal file
262
src/adjectives.c
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
|
||||
#include "words.h"
|
||||
|
||||
const char * const adjectives[256] = {
|
||||
"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 */
|
||||
};
|
||||
|
||||
190
src/demo.c
190
src/demo.c
|
|
@ -28,6 +28,8 @@
|
|||
#include "rand_stm32.h"
|
||||
#include "packet_interface.h"
|
||||
#include "noise.h"
|
||||
#include "hid_keycodes.h"
|
||||
#include "words.h"
|
||||
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
|
|
@ -40,13 +42,21 @@
|
|||
#include <libopencmsis/core_cm3.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef USE_STM32F4_USBH_DRIVER_FS
|
||||
#error The full-speed USB driver must be enabled with USE_STM32F4_USBH_DRIVER_FS in usbh_config.h!
|
||||
#endif
|
||||
|
||||
#ifndef MAX_FAILED_HANDSHAKES
|
||||
#define MAX_FAILED_HANDSHAKES 3
|
||||
#endif
|
||||
|
||||
|
||||
static struct NoiseState noise_state;
|
||||
static uint8_t remote_key_reference[CURVE25519_KEY_LEN];
|
||||
|
||||
|
||||
void _fini(void);
|
||||
|
||||
|
|
@ -113,17 +123,99 @@ static void gpio_setup(void)
|
|||
gpio_mode_setup(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO3 | GPIO4);
|
||||
}
|
||||
|
||||
enum packet_types {
|
||||
_RESERVED = 0,
|
||||
HID_KEYBOARD_REPORT = 1,
|
||||
HID_MOUSE_REPORT = 2
|
||||
};
|
||||
struct hid_report {
|
||||
uint8_t modifiers;
|
||||
uint8_t _reserved;
|
||||
uint8_t keycodes[6];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct hid_report_packet {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
uint8_t report[8];
|
||||
};
|
||||
static char pairing_buf[512];
|
||||
static size_t pairing_buf_pos = 0;
|
||||
|
||||
int pairing_check(struct NoiseState *st, const char *buf);
|
||||
void pairing_input(uint8_t keycode);
|
||||
void pairing_parse_report(struct hid_report *buf, uint8_t len);
|
||||
|
||||
int pairing_check(struct NoiseState *st, const char *buf) {
|
||||
const char *p = buf;
|
||||
int idx = 0;
|
||||
do {
|
||||
const char *found = strchr(p, ' ');
|
||||
size_t plen = found ? (size_t)(found - p) : strlen(p); /* p >= found */
|
||||
int num = -1;
|
||||
for (int i=0; i<256; i++) {
|
||||
if (!strncmp(p, adjectives[i], plen) || !strncmp(p, nouns[i], plen)) {
|
||||
num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num == -1) {
|
||||
LOG_PRINTF("Pairing word not found in dictionary\n");
|
||||
return -1;
|
||||
}
|
||||
if (st->handshake_hash[idx] != num) {
|
||||
LOG_PRINTF("Pairing data does not match hash\n");
|
||||
return -1;
|
||||
}
|
||||
idx++;
|
||||
p = strchr(p, ' ');
|
||||
} while (p != NULL && idx < BLAKE2S_HASH_SIZE);
|
||||
|
||||
if (idx < 8) {
|
||||
LOG_PRINTF("Pairing sequence too short, only %d bytes of hash checked\n", idx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pairing_input(uint8_t keycode) {
|
||||
switch (keycode) {
|
||||
case KEY_ENTER:
|
||||
pairing_buf[pairing_buf_pos++] = '\0';
|
||||
if (!pairing_check(&noise_state, pairing_buf)) {
|
||||
persist_remote_key(&noise_state);
|
||||
/* FIXME write key to backup memory */
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_BACKSPACE:
|
||||
if (pairing_buf_pos > 0)
|
||||
pairing_buf_pos--;
|
||||
break;
|
||||
|
||||
default:
|
||||
for (size_t i=0; i<sizeof(keycode_mapping)/sizeof(keycode_mapping[0]); i++) {
|
||||
if (keycode_mapping[i].kc == keycode) {
|
||||
if (pairing_buf_pos < sizeof(pairing_buf)-1) /* allow for terminating null byte */
|
||||
pairing_buf[pairing_buf_pos++] = keycode_mapping[i].ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void pairing_parse_report(struct hid_report *buf, uint8_t len) {
|
||||
static uint8_t old_keycodes[6] = {0};
|
||||
|
||||
for (int i=0; i<len-2; i++) {
|
||||
if (!buf->keycodes[i])
|
||||
break; /* keycodes are always populated from low to high */
|
||||
|
||||
int found = 0;
|
||||
for (int j=0; j<6; j++) {
|
||||
if (old_keycodes[j] == buf->keycodes[i]) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) /* key pressed */
|
||||
pairing_input(buf->keycodes[i]);
|
||||
}
|
||||
|
||||
memcpy(old_keycodes, buf->keycodes, 6);
|
||||
}
|
||||
|
||||
static void hid_in_message_handler(uint8_t device_id, const uint8_t *data, uint32_t length)
|
||||
{
|
||||
|
|
@ -136,21 +228,34 @@ static void hid_in_message_handler(uint8_t device_id, const uint8_t *data, uint3
|
|||
return;
|
||||
}
|
||||
|
||||
int type = hid_get_type(device_id);
|
||||
if (type != HID_TYPE_KEYBOARD && type != HID_TYPE_MOUSE) {
|
||||
LOG_PRINTF("Unsupported HID report type %x\n", type);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_PRINTF("Sending event %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]);
|
||||
struct hid_report_packet pkt = {
|
||||
.type = type == HID_TYPE_KEYBOARD ? HID_KEYBOARD_REPORT : HID_MOUSE_REPORT,
|
||||
.len = length,
|
||||
.report = {0}
|
||||
};
|
||||
memcpy(pkt.report, data, length);
|
||||
|
||||
if (send_encrypted_message((uint8_t *)&pkt, sizeof(pkt))) {
|
||||
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 {
|
||||
LOG_PRINTF("Unsupported HID report type %x\n", type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (send_encrypted_message(&noise_state, (uint8_t *)&pkt, sizeof(pkt))) {
|
||||
LOG_PRINTF("Error sending HID report packet\n");
|
||||
return;
|
||||
}
|
||||
|
|
@ -213,21 +318,52 @@ int main(void)
|
|||
LOG_PRINTF("Initializing RNG...\n");
|
||||
rand_init();
|
||||
|
||||
noise_state_init(&noise_state, remote_key_reference);
|
||||
/* FIXME load remote key from backup memory */
|
||||
/* FIXME only run this on first boot and persist key in backup sram. Allow reset via jumper-triggered factory reset function. */
|
||||
LOG_PRINTF("Generating identity key...\n");
|
||||
if (generate_identity_key())
|
||||
if (generate_identity_key(&noise_state))
|
||||
LOG_PRINTF("Error generating identiy key\n");
|
||||
|
||||
LOG_PRINTF("Starting noise protocol handshake...\n");
|
||||
NoiseHandshakeState *handshake = start_protocol_handshake();
|
||||
if (!handshake)
|
||||
LOG_PRINTF("Error starting protocol handshake.\n");
|
||||
|
||||
while (23) {
|
||||
usbh_poll(tim6_get_time_us());
|
||||
|
||||
if (handshake)
|
||||
handshake = try_continue_noise_handshake(handshake);
|
||||
if (host_packet_length > 0) {
|
||||
struct control_packet *pkt = (struct control_packet *)host_packet_buf;
|
||||
size_t payload_length = host_packet_length - 1;
|
||||
|
||||
if (pkt->type == HOST_INITIATE_HANDSHAKE) {
|
||||
/* It is important that we acknowledge this command right away. Starting the handshake involves key
|
||||
* generation which takes a few milliseconds. If we'd acknowledge this later, we might run into an
|
||||
* overrun here since we would be blocking the buffer during key generation. */
|
||||
host_packet_length = 0; /* Acknowledge to USART ISR the buffer has been handled */
|
||||
|
||||
if (payload_length > 0) {
|
||||
LOG_PRINTF("Extraneous data in INITIATE_HANDSHAKE message\n");
|
||||
} else if (noise_state.failed_handshakes < MAX_FAILED_HANDSHAKES) {
|
||||
LOG_PRINTF("Starting noise protocol handshake...\n");
|
||||
if (reset_protocol_handshake(&noise_state))
|
||||
LOG_PRINTF("Error starting protocol handshake.\n");
|
||||
pairing_buf_pos = 0; /* Reset channel binding keyboard input buffer */
|
||||
} else {
|
||||
LOG_PRINTF("Too many failed handshake attempts, not starting another one\n");
|
||||
}
|
||||
} else if (pkt->type == HOST_HANDSHAKE) {
|
||||
LOG_PRINTF("Handling handshake packet of length %d\n", payload_length);
|
||||
int consumed = 0;
|
||||
try_continue_noise_handshake(&noise_state, pkt->payload, payload_length, &consumed);
|
||||
if (consumed)
|
||||
host_packet_length = 0; /* Acknowledge to USART ISR the buffer has been handled */
|
||||
else /* Otherwise this gets called again in the next iteration of the main loop. Usually that should not happen. */
|
||||
LOG_PRINTF("Handshake buffer unhandled. Waiting for next iteration.\n");
|
||||
|
||||
} else {
|
||||
host_packet_length = 0; /* Acknowledge to USART ISR the buffer has been handled */
|
||||
}
|
||||
}
|
||||
|
||||
if (noise_state.handshake_state == HANDSHAKE_IN_PROGRESS)
|
||||
try_continue_noise_handshake(&noise_state, NULL, 0, NULL); /* handle outgoing messages */
|
||||
|
||||
delay_ms_busy_loop(1); /* approx 1ms interval between usbh_poll() */
|
||||
}
|
||||
|
|
|
|||
43
src/hid_keycodes.c
Normal file
43
src/hid_keycodes.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
#include "hid_keycodes.h"
|
||||
|
||||
struct keymap_entry keycode_mapping[37] = {
|
||||
{ KEY_A, 'A' },
|
||||
{ KEY_B, 'B' },
|
||||
{ KEY_C, 'C' },
|
||||
{ KEY_D, 'D' },
|
||||
{ KEY_E, 'E' },
|
||||
{ KEY_F, 'F' },
|
||||
{ KEY_G, 'G' },
|
||||
{ KEY_H, 'H' },
|
||||
{ KEY_I, 'I' },
|
||||
{ KEY_J, 'J' },
|
||||
{ KEY_K, 'K' },
|
||||
{ KEY_L, 'L' },
|
||||
{ KEY_M, 'M' },
|
||||
{ KEY_N, 'N' },
|
||||
{ KEY_O, 'O' },
|
||||
{ KEY_P, 'P' },
|
||||
{ KEY_Q, 'Q' },
|
||||
{ KEY_R, 'R' },
|
||||
{ KEY_S, 'S' },
|
||||
{ KEY_T, 'T' },
|
||||
{ KEY_U, 'U' },
|
||||
{ KEY_V, 'V' },
|
||||
{ KEY_W, 'W' },
|
||||
{ KEY_X, 'X' },
|
||||
{ KEY_Y, 'Y' },
|
||||
{ KEY_Z, 'Z' },
|
||||
{ KEY_1, '1' },
|
||||
{ KEY_2, '2' },
|
||||
{ KEY_3, '3' },
|
||||
{ KEY_4, '4' },
|
||||
{ KEY_5, '5' },
|
||||
{ KEY_6, '6' },
|
||||
{ KEY_7, '7' },
|
||||
{ KEY_8, '8' },
|
||||
{ KEY_9, '9' },
|
||||
{ KEY_0, '0' },
|
||||
{ KEY_SPACE, ' ' },
|
||||
};
|
||||
|
||||
194
src/hid_keycodes.h
Normal file
194
src/hid_keycodes.h
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
#ifndef __HID_KEYCODES_H__
|
||||
#define __HID_KEYCODES_H__
|
||||
|
||||
struct keymap_entry {
|
||||
unsigned char kc;
|
||||
char ch;
|
||||
};
|
||||
|
||||
extern struct keymap_entry keycode_mapping[37];
|
||||
|
||||
enum hid_keycode {
|
||||
KEY_NONE = 0x00, // No key pressed
|
||||
KEY_ERR_OVF = 0x01, // Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key")
|
||||
KEY_A = 0x04, // Keyboard a and A
|
||||
KEY_B = 0x05, // Keyboard b and B
|
||||
KEY_C = 0x06, // Keyboard c and C
|
||||
KEY_D = 0x07, // Keyboard d and D
|
||||
KEY_E = 0x08, // Keyboard e and E
|
||||
KEY_F = 0x09, // Keyboard f and F
|
||||
KEY_G = 0x0a, // Keyboard g and G
|
||||
KEY_H = 0x0b, // Keyboard h and H
|
||||
KEY_I = 0x0c, // Keyboard i and I
|
||||
KEY_J = 0x0d, // Keyboard j and J
|
||||
KEY_K = 0x0e, // Keyboard k and K
|
||||
KEY_L = 0x0f, // Keyboard l and L
|
||||
KEY_M = 0x10, // Keyboard m and M
|
||||
KEY_N = 0x11, // Keyboard n and N
|
||||
KEY_O = 0x12, // Keyboard o and O
|
||||
KEY_P = 0x13, // Keyboard p and P
|
||||
KEY_Q = 0x14, // Keyboard q and Q
|
||||
KEY_R = 0x15, // Keyboard r and R
|
||||
KEY_S = 0x16, // Keyboard s and S
|
||||
KEY_T = 0x17, // Keyboard t and T
|
||||
KEY_U = 0x18, // Keyboard u and U
|
||||
KEY_V = 0x19, // Keyboard v and V
|
||||
KEY_W = 0x1a, // Keyboard w and W
|
||||
KEY_X = 0x1b, // Keyboard x and X
|
||||
KEY_Y = 0x1c, // Keyboard y and Y
|
||||
KEY_Z = 0x1d, // Keyboard z and Z
|
||||
|
||||
KEY_1 = 0x1e, // Keyboard 1 and !
|
||||
KEY_2 = 0x1f, // Keyboard 2 and @
|
||||
KEY_3 = 0x20, // Keyboard 3 and #
|
||||
KEY_4 = 0x21, // Keyboard 4 and $
|
||||
KEY_5 = 0x22, // Keyboard 5 and %
|
||||
KEY_6 = 0x23, // Keyboard 6 and ^
|
||||
KEY_7 = 0x24, // Keyboard 7 and &
|
||||
KEY_8 = 0x25, // Keyboard 8 and *
|
||||
KEY_9 = 0x26, // Keyboard 9 and (
|
||||
KEY_0 = 0x27, // Keyboard 0 and )
|
||||
|
||||
KEY_ENTER = 0x28, // Keyboard Return (ENTER)
|
||||
KEY_ESC = 0x29, // Keyboard ESCAPE
|
||||
KEY_BACKSPACE = 0x2a, // Keyboard DELETE (Backspace)
|
||||
KEY_TAB = 0x2b, // Keyboard Tab
|
||||
KEY_SPACE = 0x2c, // Keyboard Spacebar
|
||||
KEY_MINUS = 0x2d, // Keyboard - and _
|
||||
KEY_EQUAL = 0x2e, // Keyboard = and +
|
||||
KEY_LEFTBRACE = 0x2f, // Keyboard [ and {
|
||||
KEY_RIGHTBRACE = 0x30, // Keyboard ] and }
|
||||
KEY_BACKSLASH = 0x31, // Keyboard \ and |
|
||||
KEY_HASHTILDE = 0x32, // Keyboard Non-US # and ~
|
||||
KEY_SEMICOLON = 0x33, // Keyboard ; and :
|
||||
KEY_APOSTROPHE = 0x34, // Keyboard ' and "
|
||||
KEY_GRAVE = 0x35, // Keyboard ` and ~
|
||||
KEY_COMMA = 0x36, // Keyboard , and <
|
||||
KEY_DOT = 0x37, // Keyboard . and >
|
||||
KEY_SLASH = 0x38, // Keyboard / and ?
|
||||
KEY_CAPSLOCK = 0x39, // Keyboard Caps Lock
|
||||
|
||||
KEY_F1 = 0x3a, // Keyboard F1
|
||||
KEY_F2 = 0x3b, // Keyboard F2
|
||||
KEY_F3 = 0x3c, // Keyboard F3
|
||||
KEY_F4 = 0x3d, // Keyboard F4
|
||||
KEY_F5 = 0x3e, // Keyboard F5
|
||||
KEY_F6 = 0x3f, // Keyboard F6
|
||||
KEY_F7 = 0x40, // Keyboard F7
|
||||
KEY_F8 = 0x41, // Keyboard F8
|
||||
KEY_F9 = 0x42, // Keyboard F9
|
||||
KEY_F10 = 0x43, // Keyboard F10
|
||||
KEY_F11 = 0x44, // Keyboard F11
|
||||
KEY_F12 = 0x45, // Keyboard F12
|
||||
|
||||
KEY_SYSRQ = 0x46, // Keyboard Print Screen
|
||||
KEY_SCROLLLOCK = 0x47, // Keyboard Scroll Lock
|
||||
KEY_PAUSE = 0x48, // Keyboard Pause
|
||||
KEY_INSERT = 0x49, // Keyboard Insert
|
||||
KEY_HOME = 0x4a, // Keyboard Home
|
||||
KEY_PAGEUP = 0x4b, // Keyboard Page Up
|
||||
KEY_DELETE = 0x4c, // Keyboard Delete Forward
|
||||
KEY_END = 0x4d, // Keyboard End
|
||||
KEY_PAGEDOWN = 0x4e, // Keyboard Page Down
|
||||
KEY_RIGHT = 0x4f, // Keyboard Right Arrow
|
||||
KEY_LEFT = 0x50, // Keyboard Left Arrow
|
||||
KEY_DOWN = 0x51, // Keyboard Down Arrow
|
||||
KEY_UP = 0x52, // Keyboard Up Arrow
|
||||
|
||||
KEY_NUMLOCK = 0x53, // Keyboard Num Lock and Clear
|
||||
KEY_KPSLASH = 0x54, // Keypad /
|
||||
KEY_KPASTERISK = 0x55, // Keypad *
|
||||
KEY_KPMINUS = 0x56, // Keypad -
|
||||
KEY_KPPLUS = 0x57, // Keypad +
|
||||
KEY_KPENTER = 0x58, // Keypad ENTER
|
||||
KEY_KP1 = 0x59, // Keypad 1 and End
|
||||
KEY_KP2 = 0x5a, // Keypad 2 and Down Arrow
|
||||
KEY_KP3 = 0x5b, // Keypad 3 and PageDn
|
||||
KEY_KP4 = 0x5c, // Keypad 4 and Left Arrow
|
||||
KEY_KP5 = 0x5d, // Keypad 5
|
||||
KEY_KP6 = 0x5e, // Keypad 6 and Right Arrow
|
||||
KEY_KP7 = 0x5f, // Keypad 7 and Home
|
||||
KEY_KP8 = 0x60, // Keypad 8 and Up Arrow
|
||||
KEY_KP9 = 0x61, // Keypad 9 and Page Up
|
||||
KEY_KP0 = 0x62, // Keypad 0 and Insert
|
||||
KEY_KPDOT = 0x63, // Keypad . and Delete
|
||||
|
||||
KEY_102ND = 0x64, // Keyboard Non-US \ and |
|
||||
KEY_COMPOSE = 0x65, // Keyboard Application
|
||||
KEY_POWER = 0x66, // Keyboard Power
|
||||
KEY_KPEQUAL = 0x67, // Keypad =
|
||||
|
||||
KEY_F13 = 0x68, // Keyboard F13
|
||||
KEY_F14 = 0x69, // Keyboard F14
|
||||
KEY_F15 = 0x6a, // Keyboard F15
|
||||
KEY_F16 = 0x6b, // Keyboard F16
|
||||
KEY_F17 = 0x6c, // Keyboard F17
|
||||
KEY_F18 = 0x6d, // Keyboard F18
|
||||
KEY_F19 = 0x6e, // Keyboard F19
|
||||
KEY_F20 = 0x6f, // Keyboard F20
|
||||
KEY_F21 = 0x70, // Keyboard F21
|
||||
KEY_F22 = 0x71, // Keyboard F22
|
||||
KEY_F23 = 0x72, // Keyboard F23
|
||||
KEY_F24 = 0x73, // Keyboard F24
|
||||
|
||||
KEY_OPEN = 0x74, // Keyboard Execute
|
||||
KEY_HELP = 0x75, // Keyboard Help
|
||||
KEY_PROPS = 0x76, // Keyboard Menu
|
||||
KEY_FRONT = 0x77, // Keyboard Select
|
||||
KEY_STOP = 0x78, // Keyboard Stop
|
||||
KEY_AGAIN = 0x79, // Keyboard Again
|
||||
KEY_UNDO = 0x7a, // Keyboard Undo
|
||||
KEY_CUT = 0x7b, // Keyboard Cut
|
||||
KEY_COPY = 0x7c, // Keyboard Copy
|
||||
KEY_PASTE = 0x7d, // Keyboard Paste
|
||||
KEY_FIND = 0x7e, // Keyboard Find
|
||||
KEY_MUTE = 0x7f, // Keyboard Mute
|
||||
KEY_VOLUMEUP = 0x80, // Keyboard Volume Up
|
||||
KEY_VOLUMEDOWN = 0x81, // Keyboard Volume Down
|
||||
KEY_KPCOMMA = 0x85, // Keypad Comma
|
||||
KEY_RO = 0x87, // Keyboard International1
|
||||
KEY_KATAKANAHIRAGANA = 0x88, // Keyboard International2
|
||||
KEY_YEN = 0x89, // Keyboard International3
|
||||
KEY_HENKAN = 0x8a, // Keyboard International4
|
||||
KEY_MUHENKAN = 0x8b, // Keyboard International5
|
||||
KEY_KPJPCOMMA = 0x8c, // Keyboard International6
|
||||
KEY_HANGEUL = 0x90, // Keyboard LANG1
|
||||
KEY_HANJA = 0x91, // Keyboard LANG2
|
||||
KEY_KATAKANA = 0x92, // Keyboard LANG3
|
||||
KEY_HIRAGANA = 0x93, // Keyboard LANG4
|
||||
KEY_ZENKAKUHANKAKU = 0x94, // Keyboard LANG5
|
||||
KEY_KPLEFTPAREN = 0xb6, // Keypad (
|
||||
KEY_KPRIGHTPAREN = 0xb7, // Keypad )
|
||||
|
||||
KEY_LEFTCTRL = 0xe0, // Keyboard Left Control
|
||||
KEY_LEFTSHIFT = 0xe1, // Keyboard Left Shift
|
||||
KEY_LEFTALT = 0xe2, // Keyboard Left Alt
|
||||
KEY_LEFTMETA = 0xe3, // Keyboard Left GUI
|
||||
KEY_RIGHTCTRL = 0xe4, // Keyboard Right Control
|
||||
KEY_RIGHTSHIFT = 0xe5, // Keyboard Right Shift
|
||||
KEY_RIGHTALT = 0xe6, // Keyboard Right Alt
|
||||
KEY_RIGHTMETA = 0xe7, // Keyboard Right GUI
|
||||
|
||||
KEY_MEDIA_PLAYPAUSE = 0xe8,
|
||||
KEY_MEDIA_STOPCD = 0xe9,
|
||||
KEY_MEDIA_PREVIOUSSONG = 0xea,
|
||||
KEY_MEDIA_NEXTSONG = 0xeb,
|
||||
KEY_MEDIA_EJECTCD = 0xec,
|
||||
KEY_MEDIA_VOLUMEUP = 0xed,
|
||||
KEY_MEDIA_VOLUMEDOWN = 0xee,
|
||||
KEY_MEDIA_MUTE = 0xef,
|
||||
KEY_MEDIA_WWW = 0xf0,
|
||||
KEY_MEDIA_BACK = 0xf1,
|
||||
KEY_MEDIA_FORWARD = 0xf2,
|
||||
KEY_MEDIA_STOP = 0xf3,
|
||||
KEY_MEDIA_FIND = 0xf4,
|
||||
KEY_MEDIA_SCROLLUP = 0xf5,
|
||||
KEY_MEDIA_SCROLLDOWN = 0xf6,
|
||||
KEY_MEDIA_EDIT = 0xf7,
|
||||
KEY_MEDIA_SLEEP = 0xf8,
|
||||
KEY_MEDIA_COFFEE = 0xf9,
|
||||
KEY_MEDIA_REFRESH = 0xfa,
|
||||
KEY_MEDIA_CALC = 0xfb,
|
||||
};
|
||||
|
||||
#endif
|
||||
138
src/noise.c
138
src/noise.c
|
|
@ -19,11 +19,22 @@
|
|||
volatile uint8_t host_packet_buf[MAX_HOST_PACKET_SIZE];
|
||||
volatile uint8_t host_packet_length = 0;
|
||||
|
||||
static uint8_t local_key[CURVE25519_KEY_LEN];
|
||||
static NoiseCipherState *tx_cipher = NULL, *rx_cipher = NULL;
|
||||
|
||||
void noise_state_init(struct NoiseState *st, uint8_t *remote_key_reference) {
|
||||
st->handshake_state = HANDSHAKE_UNINITIALIZED;
|
||||
st->handshake = NULL;
|
||||
st->tx_cipher = NULL;
|
||||
st->rx_cipher = NULL;
|
||||
st->remote_key_reference = remote_key_reference;
|
||||
st->failed_handshakes = 0;
|
||||
}
|
||||
|
||||
NoiseHandshakeState *start_protocol_handshake() {
|
||||
int reset_protocol_handshake(struct NoiseState *st) {
|
||||
uninit_handshake(st, HANDSHAKE_UNINITIALIZED);
|
||||
return start_protocol_handshake(st);
|
||||
}
|
||||
|
||||
int start_protocol_handshake(struct NoiseState *st) {
|
||||
/* TODO Noise-C is nice for prototyping, but we should really get rid of it for mostly three reasons:
|
||||
* * We don't need cipher/protocol agility, and by baking the final protocol into the firmware we can save a lot
|
||||
* of flash space by not including all the primitives we don't need as well as noise's dynamic protocol
|
||||
|
|
@ -40,18 +51,20 @@ NoiseHandshakeState *start_protocol_handshake() {
|
|||
HANDLE_NOISE_ERROR(noise_handshakestate_new_by_name(&handshake, "Noise_XX_25519_ChaChaPoly_BLAKE2s", NOISE_ROLE_RESPONDER), "instantiating handshake pattern");
|
||||
|
||||
NoiseDHState *dh = noise_handshakestate_get_local_keypair_dh(handshake);
|
||||
HANDLE_NOISE_ERROR(noise_dhstate_set_keypair_private(dh, local_key, sizeof(local_key)), "loading local private keys");
|
||||
HANDLE_NOISE_ERROR(noise_dhstate_set_keypair_private(dh, st->local_key, sizeof(st->local_key)), "loading local private keys");
|
||||
|
||||
HANDLE_NOISE_ERROR(noise_handshakestate_start(handshake), "starting handshake");
|
||||
|
||||
return handshake;
|
||||
st->handshake = handshake;
|
||||
st->handshake_state = HANDSHAKE_IN_PROGRESS;
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
noise_handshakestate_free(handshake);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int generate_identity_key() {
|
||||
int generate_identity_key(struct NoiseState *st) {
|
||||
NoiseDHState *dh;
|
||||
int err;
|
||||
|
||||
|
|
@ -59,84 +72,129 @@ int generate_identity_key() {
|
|||
HANDLE_NOISE_ERROR(noise_dhstate_generate_keypair(dh), "generating key pair");
|
||||
|
||||
uint8_t unused[CURVE25519_KEY_LEN]; /* the noise api is a bit bad here. */
|
||||
memset(local_key, 0, sizeof(local_key));
|
||||
memset(st->local_key, 0, sizeof(st->local_key));
|
||||
|
||||
HANDLE_NOISE_ERROR(noise_dhstate_get_keypair(dh, local_key, sizeof(local_key), unused, sizeof(unused)), "saving key pair");
|
||||
HANDLE_NOISE_ERROR(noise_dhstate_get_keypair(dh, st->local_key, sizeof(st->local_key), unused, sizeof(unused)), "saving key pair");
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
if (dh)
|
||||
noise_dhstate_free(dh);
|
||||
return -1;
|
||||
}
|
||||
|
||||
NoiseHandshakeState *try_continue_noise_handshake(NoiseHandshakeState *handshake) {
|
||||
void uninit_handshake(struct NoiseState *st, enum handshake_state new_state) {
|
||||
if (st->handshake)
|
||||
noise_handshakestate_free(st->handshake);
|
||||
st->handshake_state = new_state;
|
||||
st->handshake = NULL;
|
||||
}
|
||||
|
||||
enum handshake_state try_continue_noise_handshake(struct NoiseState *st, uint8_t *buf, size_t len, int *buf_consumed) {
|
||||
int err;
|
||||
uint8_t message[MAX_HOST_PACKET_SIZE];
|
||||
struct {
|
||||
struct control_packet header;
|
||||
uint8_t payload[MAX_HOST_PACKET_SIZE];
|
||||
} pkt;
|
||||
NoiseBuffer noise_msg;
|
||||
|
||||
if (!st->handshake || st->handshake_state != HANDSHAKE_IN_PROGRESS) {
|
||||
LOG_PRINTF("Error: Invalid handshake state\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Run the protocol handshake */
|
||||
switch (noise_handshakestate_get_action(handshake)) {
|
||||
switch (noise_handshakestate_get_action(st->handshake)) {
|
||||
case NOISE_ACTION_WRITE_MESSAGE:
|
||||
/* Write the next handshake message with a zero-length payload */
|
||||
noise_buffer_set_output(noise_msg, message, sizeof(message));
|
||||
HANDLE_NOISE_ERROR(noise_handshakestate_write_message(handshake, &noise_msg, NULL), "writing handshake message");
|
||||
send_packet(usart2_out, message, noise_msg.size);
|
||||
/* Write the next handshake message with a zero-length noise payload */
|
||||
pkt.header.type = HOST_HANDSHAKE;
|
||||
noise_buffer_set_output(noise_msg, &pkt.payload, sizeof(pkt.payload));
|
||||
HANDLE_NOISE_ERROR(noise_handshakestate_write_message(st->handshake, &noise_msg, NULL), "writing handshake message");
|
||||
send_packet(usart2_out, (uint8_t *)&pkt, noise_msg.size + sizeof(pkt.header));
|
||||
break;
|
||||
|
||||
case NOISE_ACTION_READ_MESSAGE:
|
||||
if (host_packet_length > 0) {
|
||||
if (buf) {
|
||||
/* Read the next handshake message and discard the payload */
|
||||
noise_buffer_set_input(noise_msg, (uint8_t *)host_packet_buf, host_packet_length);
|
||||
HANDLE_NOISE_ERROR(noise_handshakestate_read_message(handshake, &noise_msg, NULL), "reading handshake message");
|
||||
host_packet_length = 0; /* Acknowledge to USART ISR the buffer has been handled */
|
||||
*buf_consumed = 1;
|
||||
noise_buffer_set_input(noise_msg, buf, len);
|
||||
HANDLE_NOISE_ERROR(noise_handshakestate_read_message(st->handshake, &noise_msg, NULL), "reading handshake message");
|
||||
}
|
||||
break;
|
||||
|
||||
case NOISE_ACTION_SPLIT:
|
||||
HANDLE_NOISE_ERROR(noise_handshakestate_split(handshake, &tx_cipher, &rx_cipher), "splitting handshake state");
|
||||
HANDLE_NOISE_ERROR(noise_handshakestate_split(st->handshake, &st->tx_cipher, &st->rx_cipher), "splitting handshake state");
|
||||
LOG_PRINTF("Noise protocol handshake completed successfully, handshake hash:\n");
|
||||
|
||||
uint8_t buf[BLAKE2S_HASH_SIZE];
|
||||
if (noise_handshakestate_get_handshake_hash(handshake, buf, sizeof(buf)) != NOISE_ERROR_NONE) {
|
||||
if (noise_handshakestate_get_handshake_hash(st->handshake, st->handshake_hash, sizeof(st->handshake_hash)) != NOISE_ERROR_NONE) {
|
||||
LOG_PRINTF("Error fetching noise handshake state\n");
|
||||
} else {
|
||||
LOG_PRINTF(" ");
|
||||
for (size_t i=0; i<sizeof(buf); i++)
|
||||
LOG_PRINTF("%02x ", buf[i]);
|
||||
for (size_t i=0; i<sizeof(st->handshake_hash); i++)
|
||||
LOG_PRINTF("%02x ", st->handshake_hash[i]);
|
||||
LOG_PRINTF("\n");
|
||||
}
|
||||
|
||||
noise_handshakestate_free(handshake);
|
||||
return NULL;
|
||||
|
||||
NoiseDHState *remote_dh = noise_handshakestate_get_remote_public_key_dh(st->handshake);
|
||||
if (!remote_dh) {
|
||||
LOG_PRINTF("Error: Host has not identified itself\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
|
||||
HANDLE_NOISE_ERROR(noise_dhstate_get_public_key(remote_dh, st->remote_key, sizeof(st->remote_key)), "getting remote pubkey");
|
||||
|
||||
if (!memcmp(st->remote_key, st->remote_key_reference, sizeof(st->remote_key))) { /* keys match */
|
||||
uninit_handshake(st, HANDSHAKE_DONE_KNOWN_HOST);
|
||||
st->failed_handshakes = 0;
|
||||
} else { /* keys don't match */
|
||||
uninit_handshake(st, HANDSHAKE_DONE_UNKNOWN_HOST);
|
||||
st->failed_handshakes++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_PRINTF("Noise protocol handshake failed\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return handshake;
|
||||
|
||||
return st->handshake_state;
|
||||
errout:
|
||||
noise_handshakestate_free(handshake);
|
||||
return NULL;
|
||||
uninit_handshake(st, HANDSHAKE_UNINITIALIZED);
|
||||
st->failed_handshakes++;
|
||||
LOG_PRINTF("Noise protocol handshake failed, %d failed attempts\n", st->failed_handshakes);
|
||||
return st->handshake_state;
|
||||
}
|
||||
|
||||
int send_encrypted_message(uint8_t *msg, size_t len) {
|
||||
void persist_remote_key(struct NoiseState *st) {
|
||||
memcpy(st->remote_key_reference, st->remote_key, sizeof(st->remote_key));
|
||||
st->handshake_state = HANDSHAKE_DONE_KNOWN_HOST;
|
||||
}
|
||||
|
||||
int send_encrypted_message(struct NoiseState *st, uint8_t *msg, size_t len) {
|
||||
int err;
|
||||
NoiseBuffer noise_buf;
|
||||
uint8_t raw_buf[MAX_HOST_PACKET_SIZE];
|
||||
struct {
|
||||
struct control_packet header;
|
||||
uint8_t payload[MAX_HOST_PACKET_SIZE];
|
||||
} pkt;
|
||||
|
||||
if (!tx_cipher) {
|
||||
if (!st->tx_cipher) {
|
||||
LOG_PRINTF("Cannot send encrypted packet: Data ciphers not yet initialized\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(raw_buf, msg, len); /* This is necessary because noises API doesn't support separate in and out buffers. D'oh! */
|
||||
noise_buffer_set_inout(noise_buf, raw_buf, len, sizeof(raw_buf));
|
||||
if (len > sizeof(pkt.payload)) {
|
||||
LOG_PRINTF("Packet too long\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
HANDLE_NOISE_ERROR(noise_cipherstate_encrypt(tx_cipher, &noise_buf), "encrypting data");
|
||||
send_packet(usart2_out, raw_buf, noise_buf.size);
|
||||
pkt.header.type = HOST_DATA;
|
||||
memcpy(pkt.payload, msg, len); /* This is necessary because noises API doesn't support separate in and out buffers. D'oh! */
|
||||
noise_buffer_set_inout(noise_buf, pkt.payload, len, sizeof(pkt.payload));
|
||||
|
||||
HANDLE_NOISE_ERROR(noise_cipherstate_encrypt(st->tx_cipher, &noise_buf), "encrypting data");
|
||||
send_packet(usart2_out, (uint8_t *)&pkt, noise_buf.size + sizeof(pkt.header));
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
|
|
|
|||
33
src/noise.h
33
src/noise.h
|
|
@ -16,10 +16,35 @@
|
|||
extern volatile uint8_t host_packet_buf[MAX_HOST_PACKET_SIZE];
|
||||
extern volatile uint8_t host_packet_length;
|
||||
|
||||
enum handshake_state {
|
||||
HANDSHAKE_UNINITIALIZED,
|
||||
HANDSHAKE_NOT_STARTED,
|
||||
HANDSHAKE_IN_PROGRESS,
|
||||
HANDSHAKE_DONE_UNKNOWN_HOST,
|
||||
HANDSHAKE_DONE_KNOWN_HOST,
|
||||
};
|
||||
|
||||
NoiseHandshakeState *start_protocol_handshake(void);
|
||||
int generate_identity_key(void);
|
||||
NoiseHandshakeState *try_continue_noise_handshake(NoiseHandshakeState *handshake);
|
||||
int send_encrypted_message(uint8_t *msg, size_t len);
|
||||
extern volatile enum handshake_state handshake_state;
|
||||
|
||||
struct NoiseState {
|
||||
NoiseHandshakeState *handshake;
|
||||
enum handshake_state handshake_state;
|
||||
NoiseCipherState *tx_cipher, *rx_cipher;
|
||||
uint8_t local_key[CURVE25519_KEY_LEN];
|
||||
uint8_t remote_key[CURVE25519_KEY_LEN];
|
||||
uint8_t *remote_key_reference;
|
||||
uint8_t handshake_hash[BLAKE2S_HASH_SIZE];
|
||||
int failed_handshakes;
|
||||
};
|
||||
|
||||
|
||||
void uninit_handshake(struct NoiseState *st, enum handshake_state new_state);
|
||||
void noise_state_init(struct NoiseState *st, uint8_t *remote_key_reference);
|
||||
void persist_remote_key(struct NoiseState *st);
|
||||
int start_protocol_handshake(struct NoiseState *st);
|
||||
int reset_protocol_handshake(struct NoiseState *st);
|
||||
int generate_identity_key(struct NoiseState *st);
|
||||
enum handshake_state try_continue_noise_handshake(struct NoiseState *st, uint8_t *buf, size_t len, int *buf_consumed);
|
||||
int send_encrypted_message(struct NoiseState *st, uint8_t *msg, size_t len);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
262
src/nouns.c
Normal file
262
src/nouns.c
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
|
||||
#include "words.h"
|
||||
|
||||
const char * const nouns[256] = {
|
||||
"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 */
|
||||
};
|
||||
|
||||
|
|
@ -3,8 +3,35 @@
|
|||
|
||||
#include "usart_helpers.h"
|
||||
|
||||
|
||||
extern struct dma_usart_file *usart2_out;
|
||||
|
||||
enum control_packet_types {
|
||||
_HOST_RESERVED = 0,
|
||||
HOST_INITIATE_HANDSHAKE = 1,
|
||||
HOST_HANDSHAKE = 2,
|
||||
HOST_DATA = 3,
|
||||
};
|
||||
|
||||
enum packet_types {
|
||||
_PACKET_RESERVED = 0,
|
||||
HID_KEYBOARD_REPORT = 1,
|
||||
HID_MOUSE_REPORT = 2,
|
||||
PAIRING = 3,
|
||||
};
|
||||
|
||||
struct hid_report_packet {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
uint8_t report[8];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct control_packet {
|
||||
uint8_t type;
|
||||
uint8_t payload[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
void send_packet(struct dma_usart_file *f, const uint8_t *data, size_t len);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
7
src/words.h
Normal file
7
src/words.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef __ADJECTIVES_H__
|
||||
#define __ADJECTIVES_H__
|
||||
|
||||
extern const char * const adjectives[256];
|
||||
extern const char * const nouns[256];
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue