Handshake working with new abstractions

This commit is contained in:
jaseg 2018-11-12 11:59:11 +09:00
parent 42d4bebde7
commit 2f4f3e13aa
11 changed files with 1118 additions and 77 deletions

View file

@ -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)

View file

@ -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
View 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 */
};

View file

@ -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
View 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
View 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

View file

@ -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:

View file

@ -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
View 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 */
};

View file

@ -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
View file

@ -0,0 +1,7 @@
#ifndef __ADJECTIVES_H__
#define __ADJECTIVES_H__
extern const char * const adjectives[256];
extern const char * const nouns[256];
#endif