Browse Source

stub out secure as its own feature

zvecr 4 years ago
parent
commit
89fab427c4

+ 1 - 0
builddefs/common_features.mk

@@ -802,6 +802,7 @@ ifeq ($(strip $(XAP_ENABLE)), yes)
 
 
     OPT_DEFS += -DXAP_ENABLE
     OPT_DEFS += -DXAP_ENABLE
     DYNAMIC_KEYMAP_ENABLE := yes
     DYNAMIC_KEYMAP_ENABLE := yes
+    SECURE_ENABLE := yes
     EMBED_INFO_JSON := yes
     EMBED_INFO_JSON := yes
     VPATH += $(QUANTUM_DIR)/xap
     VPATH += $(QUANTUM_DIR)/xap
     SRC += $(QUANTUM_DIR)/xap/xap.c $(QUANTUM_DIR)/xap/xap_handlers.c
     SRC += $(QUANTUM_DIR)/xap/xap.c $(QUANTUM_DIR)/xap/xap_handlers.c

+ 1 - 0
builddefs/generic_features.mk

@@ -32,6 +32,7 @@ GENERIC_FEATURES = \
     KEY_OVERRIDE \
     KEY_OVERRIDE \
     LEADER \
     LEADER \
     PROGRAMMABLE_BUTTON \
     PROGRAMMABLE_BUTTON \
+    SECURE \
     SPACE_CADET \
     SPACE_CADET \
     SWAP_HANDS \
     SWAP_HANDS \
     TAP_DANCE \
     TAP_DANCE \

+ 15 - 1
data/xap/xap_0.1.0.hjson

@@ -172,7 +172,21 @@
                         * any other value should be interpreted as disabled
                         * any other value should be interpreted as disabled
                         '''
                         '''
                     return_type: u8
                     return_type: u8
-                    return_value: secure_status
+                    return_execute: secure_status
+                }
+                0x04: {
+                    type: command
+                    name: Secure Unlock
+                    define: SECURE_UNLOCK
+                    description: Initiate secure route unlock sequence
+                    return_execute: secure_unlock
+                }
+                0x05: {
+                    type: command
+                    name: Secure Lock
+                    define: SECURE_LOCK
+                    description: Disable secure routes
+                    return_execute: secure_lock
                 }
                 }
             }
             }
         },
         },

+ 14 - 1
lib/python/qmk/cli/xap/xap.py

@@ -185,9 +185,14 @@ def xap_broadcast_listen(device):
         cli.log.info("Stopping...")
         cli.log.info("Stopping...")
 
 
 
 
+def xap_unlock(device):
+    _xap_transaction(device, 0x00, 0x04)
+
+
 @cli.argument('-d', '--device', help='device to select - uses format <pid>:<vid>.')
 @cli.argument('-d', '--device', help='device to select - uses format <pid>:<vid>.')
 @cli.argument('-i', '--index', default=0, help='device index to select.')
 @cli.argument('-i', '--index', default=0, help='device index to select.')
 @cli.argument('-l', '--list', arg_only=True, action='store_true', help='List available devices.')
 @cli.argument('-l', '--list', arg_only=True, action='store_true', help='List available devices.')
+@cli.argument('action', nargs='?', arg_only=True)
 @cli.subcommand('Acquire debugging information from usb XAP devices.', hidden=False if cli.config.user.developer else True)
 @cli.subcommand('Acquire debugging information from usb XAP devices.', hidden=False if cli.config.user.developer else True)
 def xap(cli):
 def xap(cli):
     """Acquire debugging information from XAP devices
     """Acquire debugging information from XAP devices
@@ -210,4 +215,12 @@ def xap(cli):
     cli.log.info("Connected to:%04x:%04x %s %s", dev['vendor_id'], dev['product_id'], dev['manufacturer_string'], dev['product_string'])
     cli.log.info("Connected to:%04x:%04x %s %s", dev['vendor_id'], dev['product_id'], dev['manufacturer_string'], dev['product_string'])
 
 
     # xap_doit(device)
     # xap_doit(device)
-    xap_broadcast_listen(device)
+    if cli.args.action == 'unlock':
+        xap_unlock(device)
+        cli.log.info("Done")
+
+    elif cli.args.action == 'listen':
+        xap_broadcast_listen(device)
+
+    elif not cli.args.action:
+        xap_broadcast_listen(device)

+ 8 - 0
quantum/keyboard.c

@@ -562,6 +562,14 @@ void quantum_task(void) {
 #ifdef AUTO_SHIFT_ENABLE
 #ifdef AUTO_SHIFT_ENABLE
     autoshift_matrix_scan();
     autoshift_matrix_scan();
 #endif
 #endif
+
+#ifdef SECURE_ENABLE
+    secure_task();
+#endif
+
+#ifdef XAP_ENABLE
+    xap_event_task();
+#endif
 }
 }
 
 
 /** \brief Keyboard task: Do keyboard routine jobs
 /** \brief Keyboard task: Do keyboard routine jobs

+ 18 - 0
quantum/process_keycode/process_secure.c

@@ -0,0 +1,18 @@
+// Copyright 2022 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "secure.h"
+#include "process_secure.h"
+
+bool process_secure(uint16_t keycode, keyrecord_t *record) {
+    if (secure_is_unlocking()) {
+        if (!record->event.pressed) {
+            secure_keypress_event(record->event.key.row, record->event.key.col);
+        }
+
+        // Normal keypresses should be disabled until the sequence is completed
+        return false;
+    }
+
+    return true;
+}

+ 9 - 0
quantum/process_keycode/process_secure.h

@@ -0,0 +1,9 @@
+// Copyright 2022 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <stdbool.h>
+#include "action.h"
+
+bool process_secure(uint16_t keycode, keyrecord_t *record);

+ 3 - 0
quantum/quantum.c

@@ -245,6 +245,9 @@ bool process_record_quantum(keyrecord_t *record) {
 #endif
 #endif
 #if defined(VIA_ENABLE)
 #if defined(VIA_ENABLE)
             process_record_via(keycode, record) &&
             process_record_via(keycode, record) &&
+#endif
+#if defined(SECURE_ENABLE)
+            process_secure(keycode, record) &&
 #endif
 #endif
             process_record_kb(keycode, record) &&
             process_record_kb(keycode, record) &&
 #if defined(SEQUENCER_ENABLE)
 #if defined(SEQUENCER_ENABLE)

+ 5 - 0
quantum/quantum.h

@@ -196,6 +196,11 @@ extern layer_state_t layer_state;
 #    include "process_dynamic_macro.h"
 #    include "process_dynamic_macro.h"
 #endif
 #endif
 
 
+#ifdef SECURE_ENABLE
+#    include "secure.h"
+#    include "process_secure.h"
+#endif
+
 #ifdef DYNAMIC_KEYMAP_ENABLE
 #ifdef DYNAMIC_KEYMAP_ENABLE
 #    include "dynamic_keymap.h"
 #    include "dynamic_keymap.h"
 #endif
 #endif

+ 66 - 0
quantum/secure.c

@@ -0,0 +1,66 @@
+// Copyright 2022 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "secure.h"
+#include "timer.h"
+
+#ifndef SECURE_UNLOCK_TIMEOUT
+#    define SECURE_UNLOCK_TIMEOUT 5000
+#endif
+
+#ifndef SECURE_IDLE_TIMEOUT
+#    define SECURE_IDLE_TIMEOUT 60000
+#endif
+
+secure_status_t secure_status = SECURE_LOCKED;
+static uint32_t unlock_time   = 0;
+static uint32_t idle_time     = 0;
+
+secure_status_t secure_get_status(void) {
+    return secure_status;
+}
+
+bool secure_is_unlocking(void) {
+    return secure_status == SECURE_PENDING;
+}
+
+void secure_lock(void) {
+    secure_status = SECURE_LOCKED;
+}
+
+void secure_unlock(void) {
+    secure_status = SECURE_UNLOCKED;
+    idle_time     = timer_read32();
+}
+
+void secure_request_unlock(void) {
+    if (secure_status == SECURE_LOCKED) {
+        secure_status = SECURE_PENDING;
+        unlock_time   = timer_read32();
+    }
+}
+
+void secure_keypress_event(uint8_t row, uint8_t col) {
+    // TODO: check keypress is actually part of unlock sequence
+    secure_unlock();
+}
+
+void secure_task(void) {
+#if SECURE_UNLOCK_TIMEOUT != 0
+    // handle unlock timeout
+    if (secure_status == SECURE_PENDING) {
+        if (timer_elapsed32(unlock_time) >= SECURE_UNLOCK_TIMEOUT) {
+            secure_lock();
+        }
+    }
+#endif
+
+#if SECURE_IDLE_TIMEOUT != 0
+    // handle idle timeout
+    if (secure_status == SECURE_UNLOCKED) {
+        if (timer_elapsed32(idle_time) >= SECURE_IDLE_TIMEOUT) {
+            secure_lock();
+        }
+    }
+#endif
+}

+ 27 - 0
quantum/secure.h

@@ -0,0 +1,27 @@
+// Copyright 2022 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef enum {
+    SECURE_LOCKED,
+    SECURE_PENDING,
+    SECURE_UNLOCKED,
+} secure_status_t;
+
+secure_status_t secure_get_status(void);
+
+bool secure_is_unlocking(void);
+
+void secure_lock(void);
+
+void secure_unlock(void);
+
+void secure_request_unlock(void);
+
+void secure_keypress_event(uint8_t row, uint8_t col);
+
+void secure_task(void);

+ 19 - 3
quantum/xap/xap.c

@@ -16,6 +16,7 @@
 
 
 #include <quantum.h>
 #include <quantum.h>
 #include <xap.h>
 #include <xap.h>
+#include "secure.h"
 
 
 #include "info_json_gz.h"
 #include "info_json_gz.h"
 bool get_info_json_chunk(uint16_t offset, uint8_t *data, uint8_t data_len) {
 bool get_info_json_chunk(uint16_t offset, uint8_t *data, uint8_t data_len) {
@@ -27,8 +28,6 @@ bool get_info_json_chunk(uint16_t offset, uint8_t *data, uint8_t data_len) {
     return true;
     return true;
 }
 }
 
 
-uint8_t secure_status = 2;
-
 #define QSTR2(z) #z
 #define QSTR2(z) #z
 #define QSTR(z) QSTR2(z)
 #define QSTR(z) QSTR2(z)
 
 
@@ -86,11 +85,18 @@ void xap_execute_route(xap_token_t token, const xap_route_t *routes, size_t max_
         xap_route_t route;
         xap_route_t route;
         memcpy_P(&route, &routes[id], sizeof(xap_route_t));
         memcpy_P(&route, &routes[id], sizeof(xap_route_t));
 
 
-        if (route.flags.is_secure && secure_status != 2) {
+        if (route.flags.is_secure && secure_get_status() != SECURE_UNLOCKED) {
             xap_respond_failure(token, XAP_RESPONSE_FLAG_SECURE_FAILURE);
             xap_respond_failure(token, XAP_RESPONSE_FLAG_SECURE_FAILURE);
             return;
             return;
         }
         }
 
 
+        // TODO: All other subsystems are disabled during unlock.
+        //       how to flag status route as still allowed?
+        // if (!route.flags.is_secure && secure_get_status() == SECURE_PENDING) {
+        //     xap_respond_failure(token, XAP_RESPONSE_FLAG_UNLOCK_IN_PROGRESS);
+        //     return;
+        // }
+
         switch (route.flags.type) {
         switch (route.flags.type) {
             case XAP_ROUTE:
             case XAP_ROUTE:
                 if (route.child_routes != NULL && route.child_routes_len > 0 && data_len > 0) {
                 if (route.child_routes != NULL && route.child_routes_len > 0 && data_len > 0) {
@@ -134,3 +140,13 @@ void xap_execute_route(xap_token_t token, const xap_route_t *routes, size_t max_
 void xap_receive(xap_token_t token, const uint8_t *data, size_t length) {
 void xap_receive(xap_token_t token, const uint8_t *data, size_t length) {
     xap_execute_route(token, xap_route_table, sizeof(xap_route_table) / sizeof(xap_route_t), data, length);
     xap_execute_route(token, xap_route_table, sizeof(xap_route_table) / sizeof(xap_route_t), data, length);
 }
 }
+
+void xap_event_task(void) {
+    static secure_status_t last_status = -1;
+
+    secure_status_t status = secure_get_status();
+    if (last_status != status) {
+        last_status = status;
+        xap_broadcast_secure_status(status);
+    }
+}

+ 2 - 0
quantum/xap/xap.h

@@ -36,3 +36,5 @@ bool xap_respond_data_P(xap_token_t token, const void *data, size_t length);
 
 
 void xap_send(xap_token_t token, xap_response_flags_t response_flags, const void *data, size_t length);
 void xap_send(xap_token_t token, xap_response_flags_t response_flags, const void *data, size_t length);
 void xap_broadcast(uint8_t type, const void *data, size_t length);
 void xap_broadcast(uint8_t type, const void *data, size_t length);
+
+void xap_event_task(void);

+ 16 - 0
quantum/xap/xap_handlers.c

@@ -16,6 +16,7 @@
 
 
 #include <quantum.h>
 #include <quantum.h>
 #include <xap.h>
 #include <xap.h>
+#include "secure.h"
 
 
 void xap_respond_success(xap_token_t token) {
 void xap_respond_success(xap_token_t token) {
     xap_send(token, XAP_RESPONSE_FLAG_SUCCESS, NULL, 0);
     xap_send(token, XAP_RESPONSE_FLAG_SUCCESS, NULL, 0);
@@ -59,6 +60,21 @@ bool xap_respond_get_info_json_chunk(xap_token_t token, const void *data, size_t
     return xap_respond_data(token, &ret, sizeof(ret));
     return xap_respond_data(token, &ret, sizeof(ret));
 }
 }
 
 
+bool xap_respond_secure_status(xap_token_t token, const void *data, size_t length) {
+    uint8_t ret = secure_get_status();
+    return xap_respond_data(token, &ret, sizeof(ret));
+}
+
+bool xap_respond_secure_unlock(xap_token_t token, const void *data, size_t length) {
+    secure_request_unlock();
+    return xap_respond_data(token, NULL, 0);
+}
+
+bool xap_respond_secure_lock(xap_token_t token, const void *data, size_t length) {
+    secure_lock();
+    return xap_respond_data(token, NULL, 0);
+}
+
 // TODO: how to set this if "custom" is just an empty stub
 // TODO: how to set this if "custom" is just an empty stub
 #ifndef BOOTLOADER_JUMP_SUPPORTED
 #ifndef BOOTLOADER_JUMP_SUPPORTED
 #    define BOOTLOADER_JUMP_SUPPORTED
 #    define BOOTLOADER_JUMP_SUPPORTED