Implement XAP 'secure' core requirements (#16843)
Co-authored-by: Drashna Jaelre <drashna@live.com> Co-authored-by: Stefan Kerkmann <karlk90@pm.me>miryoku-merge-master
parent
ae4d518352
commit
92a61aa0cd
@ -0,0 +1,39 @@
|
||||
// Copyright 2022 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "secure.h"
|
||||
#include "process_secure.h"
|
||||
#include "quantum_keycodes.h"
|
||||
|
||||
bool preprocess_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;
|
||||
}
|
||||
|
||||
bool process_secure(uint16_t keycode, keyrecord_t *record) {
|
||||
#ifndef SECURE_DISABLE_KEYCODES
|
||||
if (!record->event.pressed) {
|
||||
if (keycode == SECURE_LOCK) {
|
||||
secure_lock();
|
||||
return false;
|
||||
}
|
||||
if (keycode == SECURE_UNLOCK) {
|
||||
secure_unlock();
|
||||
return false;
|
||||
}
|
||||
if (keycode == SECURE_TOGGLE) {
|
||||
secure_is_locked() ? secure_unlock() : secure_lock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
// Copyright 2022 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "action.h"
|
||||
|
||||
/** \brief Intercept keycodes and detect unlock sequences
|
||||
*/
|
||||
bool preprocess_secure(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
/** \brief Handle any secure specific keycodes
|
||||
*/
|
||||
bool process_secure(uint16_t keycode, keyrecord_t *record);
|
||||
@ -0,0 +1,87 @@
|
||||
// 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
|
||||
|
||||
#ifndef SECURE_UNLOCK_SEQUENCE
|
||||
# define SECURE_UNLOCK_SEQUENCE \
|
||||
{ \
|
||||
{ 0, 0 } \
|
||||
}
|
||||
#endif
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
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_activity_event(void) {
|
||||
if (secure_status == SECURE_UNLOCKED) {
|
||||
idle_time = timer_read32();
|
||||
}
|
||||
}
|
||||
|
||||
void secure_keypress_event(uint8_t row, uint8_t col) {
|
||||
static const uint8_t sequence[][2] = SECURE_UNLOCK_SEQUENCE;
|
||||
static const uint8_t sequence_len = sizeof(sequence) / sizeof(sequence[0]);
|
||||
|
||||
static uint8_t offset = 0;
|
||||
if ((sequence[offset][0] == row) && (sequence[offset][1] == col)) {
|
||||
offset++;
|
||||
if (offset == sequence_len) {
|
||||
offset = 0;
|
||||
secure_unlock();
|
||||
}
|
||||
} else {
|
||||
offset = 0;
|
||||
secure_lock();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
// Copyright 2022 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Exposes a set of functionality to act as a virtual padlock for your device
|
||||
* ... As long as that padlock is made of paper and its currently raining.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/** \brief Available secure states
|
||||
*/
|
||||
typedef enum {
|
||||
SECURE_LOCKED,
|
||||
SECURE_PENDING,
|
||||
SECURE_UNLOCKED,
|
||||
} secure_status_t;
|
||||
|
||||
/** \brief Query current secure state
|
||||
*/
|
||||
secure_status_t secure_get_status(void);
|
||||
|
||||
/** \brief Helper to check if unlocking is currently locked
|
||||
*/
|
||||
#define secure_is_locked() (secure_get_status() == SECURE_LOCKED)
|
||||
|
||||
/** \brief Helper to check if unlocking is currently in progress
|
||||
*/
|
||||
#define secure_is_unlocking() (secure_get_status() == SECURE_PENDING)
|
||||
|
||||
/** \brief Helper to check if unlocking is currently unlocked
|
||||
*/
|
||||
#define secure_is_unlocked() (secure_get_status() == SECURE_UNLOCKED)
|
||||
|
||||
/** \brief Lock down the device
|
||||
*/
|
||||
void secure_lock(void);
|
||||
|
||||
/** \brief Force unlock the device
|
||||
*
|
||||
* \warning bypasses user unlock sequence
|
||||
*/
|
||||
void secure_unlock(void);
|
||||
|
||||
/** \brief Begin listening for an unlock sequence
|
||||
*/
|
||||
void secure_request_unlock(void);
|
||||
|
||||
/** \brief Flag to the secure subsystem that user activity has happened
|
||||
*
|
||||
* Call when some user activity has happened and the device should remain unlocked
|
||||
*/
|
||||
void secure_activity_event(void);
|
||||
|
||||
/** \brief Flag to the secure subsystem that user has triggered a keypress
|
||||
*
|
||||
* Call to trigger processing of the unlock sequence
|
||||
*/
|
||||
void secure_keypress_event(uint8_t row, uint8_t col);
|
||||
|
||||
/** \brief Handle various secure subsystem background tasks
|
||||
*/
|
||||
void secure_task(void);
|
||||
Loading…
Reference in New Issue