diff options
author | jaseg <git@jaseg.net> | 2018-11-12 11:59:11 +0900 |
---|---|---|
committer | jaseg <git@jaseg.net> | 2018-11-12 11:59:11 +0900 |
commit | 2f4f3e13aa6a6dbbb5a45e02b792eb935e91c766 (patch) | |
tree | 80a4520254d93523fc75f25624d53b161944013d | |
parent | 42d4bebde7d3cc7f536dec114ca5a54072b9e21b (diff) | |
download | secure-hid-2f4f3e13aa6a6dbbb5a45e02b792eb935e91c766.tar.gz secure-hid-2f4f3e13aa6a6dbbb5a45e02b792eb935e91c766.tar.bz2 secure-hid-2f4f3e13aa6a6dbbb5a45e02b792eb935e91c766.zip |
Handshake working with new abstractions
-rwxr-xr-x | hexnoise.py | 36 | ||||
-rw-r--r-- | src/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/adjectives.c | 262 | ||||
-rw-r--r-- | src/demo.c | 190 | ||||
-rw-r--r-- | src/hid_keycodes.c | 43 | ||||
-rw-r--r-- | src/hid_keycodes.h | 194 | ||||
-rw-r--r-- | src/noise.c | 138 | ||||
-rw-r--r-- | src/noise.h | 35 | ||||
-rw-r--r-- | src/nouns.c | 262 | ||||
-rw-r--r-- | src/packet_interface.h | 27 | ||||
-rw-r--r-- | src/words.h | 7 |
11 files changed, 1119 insertions, 78 deletions
diff --git a/hexnoise.py b/hexnoise.py index df71d93..1f53fcd 100755 --- a/hexnoise.py +++ b/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) + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e5e23ac..9084cbb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,6 +24,9 @@ add_library (usbhost cobs.c noise.c packet_interface.c + adjectives.c + nouns.c + hid_keycodes.c ) add_subdirectory (crypto) diff --git a/src/adjectives.c b/src/adjectives.c new file mode 100644 index 0000000..e3bc3d0 --- /dev/null +++ b/src/adjectives.c @@ -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 */ +}; + @@ -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__));
+
+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;
+ }
-struct hid_report_packet {
- uint8_t type;
- uint8_t len;
- uint8_t report[8];
-};
+ 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() */
}
diff --git a/src/hid_keycodes.c b/src/hid_keycodes.c new file mode 100644 index 0000000..19b6f69 --- /dev/null +++ b/src/hid_keycodes.c @@ -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, ' ' }, +}; + diff --git a/src/hid_keycodes.h b/src/hid_keycodes.h new file mode 100644 index 0000000..a7f590a --- /dev/null +++ b/src/hid_keycodes.h @@ -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 diff --git a/src/noise.c b/src/noise.c index 83f2e4c..09a4c47 100644 --- a/src/noise.c +++ b/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; +} + +int reset_protocol_handshake(struct NoiseState *st) { + uninit_handshake(st, HANDSHAKE_UNINITIALIZED); + return start_protocol_handshake(st); +} -NoiseHandshakeState *start_protocol_handshake() { +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; +} + +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(uint8_t *msg, size_t len) { +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; + } + + 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(tx_cipher, &noise_buf), "encrypting data"); - send_packet(usart2_out, raw_buf, noise_buf.size); + 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: diff --git a/src/noise.h b/src/noise.h index fb1f93d..c777a0b 100644 --- a/src/noise.h +++ b/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; - -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); +enum handshake_state { + HANDSHAKE_UNINITIALIZED, + HANDSHAKE_NOT_STARTED, + HANDSHAKE_IN_PROGRESS, + HANDSHAKE_DONE_UNKNOWN_HOST, + HANDSHAKE_DONE_KNOWN_HOST, +}; + +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 diff --git a/src/nouns.c b/src/nouns.c new file mode 100644 index 0000000..65cae90 --- /dev/null +++ b/src/nouns.c @@ -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 */ +}; + diff --git a/src/packet_interface.h b/src/packet_interface.h index 546918b..9e1327d 100644 --- a/src/packet_interface.h +++ b/src/packet_interface.h @@ -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 diff --git a/src/words.h b/src/words.h new file mode 100644 index 0000000..e8cb628 --- /dev/null +++ b/src/words.h @@ -0,0 +1,7 @@ +#ifndef __ADJECTIVES_H__ +#define __ADJECTIVES_H__ + +extern const char * const adjectives[256]; +extern const char * const nouns[256]; + +#endif |