aboutsummaryrefslogtreecommitdiffstats
path: root/tmk_core/common/bootmagic.c
blob: 2c6bcbae56fccafae40a627ce0e47ceb4fcce37c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <stdint.h>
#include <stdbool.h>
#include "wait.h"
#include "matrix.h"
#include "bootloader.h"
#include "debug.h"
#include "keymap.h"
#include "host.h"
#include "action_layer.h"
#include "eeconfig.h"
#include "bootmagic.h"

keymap_config_t keymap_config;

void bootmagic(void)
{
    /* check signature */
    if (!eeconfig_is_enabled()) {
        eeconfig_init();
    }

    /* do scans in case of bounce */
    print("bootmagic scan: ... ");
    uint8_t scan = 100;
    while (scan--) { matrix_scan(); wait_ms(10); }
    print("done.\n");

    /* bootmagic skip */
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SKIP)) {
        return;
    }

    /* eeconfig clear */
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) {
        eeconfig_init();
    }

    /* bootloader */
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_BOOTLOADER)) {
        bootloader_jump();
    }

    /* debug enable */
    debug_config.raw = eeconfig_read_debug();
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) {
        if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) {
            debug_config.matrix = !debug_config.matrix;
        } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) {
            debug_config.keyboard = !debug_config.keyboard;
        } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MOUSE)) {
            debug_config.mouse = !debug_config.mouse;
        } else {
            debug_config.enable = !debug_config.enable;
        }
    }
    eeconfig_update_debug(debug_config.raw);

    /* keymap config */
    keymap_config.raw = eeconfig_read_keymap();
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) {
        keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
    }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) {
        keymap_config.capslock_to_control = !keymap_config.capslock_to_control;
    }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) {
        keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
    }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) {
        keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
    }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_NO_GUI)) {
        keymap_config.no_gui = !keymap_config.no_gui;
    }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) {
        keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc;
    }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) {
        keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace;
    }
    if (bootmagic_scan_keycode(BOOTMAGIC_HOST_NKRO)) {
        keymap_config.nkro = !keymap_config.nkro;
    }
    eeconfig_update_keymap(keymap_config.raw);

    /* default layer */
    uint8_t default_layer = 0;
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { default_layer |= (1<<0); }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { default_layer |= (1<<1); }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { default_layer |= (1<<2); }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { default_layer |= (1<<3); }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { default_layer |= (1<<4); }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { default_layer |= (1<<5); }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { default_layer |= (1<<6); }
    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { default_layer |= (1<<7); }
    if (default_layer) {
        eeconfig_update_default_layer(default_layer);
        default_layer_set((uint32_t)default_layer);
    } else {
        default_layer = eeconfig_read_default_layer();
        default_layer_set((uint32_t)default_layer);
    }
}

static bool scan_keycode(uint8_t keycode)
{
    for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
        matrix_row_t matrix_row = matrix_get_row(r);
        for (uint8_t c = 0; c < MATRIX_COLS; c++) {
            if (matrix_row & ((matrix_row_t)1<<c)) {
                if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) {
                    return true;
                }
            }
        }
    }
    return false;
}

bool bootmagic_scan_keycode(uint8_t keycode)
{
    if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false;

    return scan_keycode(keycode);
}
raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_CIPHER) @utils.register_interface(HashBackend) class DummyHashBackend(object): def __init__(self, supported_algorithms): self._algorithms = supported_algorithms def hash_supported(self, algorithm): return type(algorithm) in self._algorithms def create_hash_ctx(self, algorithm): if not self.hash_supported(algorithm): raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_HASH) @utils.register_interface(HMACBackend) class DummyHMACBackend(object): def __init__(self, supported_algorithms): self._algorithms = supported_algorithms def hmac_supported(self, algorithm): return type(algorithm) in self._algorithms def create_hmac_ctx(self, key, algorithm): if not self.hmac_supported(algorithm): raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_HASH) @utils.register_interface(PBKDF2HMACBackend) class DummyPBKDF2HMACBackend(object): def __init__(self, supported_algorithms): self._algorithms = supported_algorithms def pbkdf2_hmac_supported(self, algorithm): return type(algorithm) in self._algorithms def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations, key_material): if not self.pbkdf2_hmac_supported(algorithm): raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_HASH) @utils.register_interface(RSABackend) class DummyRSABackend(object): def generate_rsa_private_key(self, public_exponent, key_size): pass def rsa_padding_supported(self, padding): pass def generate_rsa_parameters_supported(self, public_exponent, key_size): pass def load_rsa_private_numbers(self, numbers): pass def load_rsa_public_numbers(self, numbers): pass @utils.register_interface(DSABackend) class DummyDSABackend(object): def generate_dsa_parameters(self, key_size): pass def generate_dsa_private_key(self, parameters): pass def generate_dsa_private_key_and_parameters(self, key_size): pass def dsa_hash_supported(self, algorithm): pass def dsa_parameters_supported(self, p, q, g): pass def load_dsa_private_numbers(self, numbers): pass def load_dsa_public_numbers(self, numbers): pass def load_dsa_parameter_numbers(self, numbers): pass @utils.register_interface(CMACBackend) class DummyCMACBackend(object): def __init__(self, supported_algorithms): self._algorithms = supported_algorithms def cmac_algorithm_supported(self, algorithm): return type(algorithm) in self._algorithms def create_cmac_ctx(self, algorithm): if not self.cmac_algorithm_supported(algorithm): raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_CIPHER) @utils.register_interface(EllipticCurveBackend) class DummyEllipticCurveBackend(object): def __init__(self, supported_curves): self._curves = supported_curves def elliptic_curve_supported(self, curve): return any( isinstance(curve, curve_type) for curve_type in self._curves ) def elliptic_curve_signature_algorithm_supported( self, signature_algorithm, curve ): return ( isinstance(signature_algorithm, ec.ECDSA) and any( isinstance(curve, curve_type) for curve_type in self._curves ) ) def generate_elliptic_curve_private_key(self, curve): if not self.elliptic_curve_supported(curve): raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE) def load_elliptic_curve_private_numbers(self, numbers): if not self.elliptic_curve_supported(numbers.public_numbers.curve): raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE) def load_elliptic_curve_public_numbers(self, numbers): if not self.elliptic_curve_supported(numbers.curve): raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE) @utils.register_interface(PEMSerializationBackend) class DummyPEMSerializationBackend(object): def load_pem_private_key(self, data, password): pass def load_pem_public_key(self, data): pass @utils.register_interface(DERSerializationBackend) class DummyDERSerializationBackend(object): def load_der_private_key(self, data, password): pass def load_der_public_key(self, data): pass @utils.register_interface(X509Backend) class DummyX509Backend(object): def load_pem_x509_certificate(self, data): pass def load_der_x509_certificate(self, data): pass def load_pem_x509_csr(self, data): pass def load_der_x509_csr(self, data): pass def create_x509_csr(self, builder, private_key, algorithm): pass def create_x509_certificate(self, builder, private_key, algorithm): pass class TestMultiBackend(object): def test_ciphers(self): backend = MultiBackend([ DummyHashBackend([]), DummyCipherBackend([ (algorithms.AES, modes.CBC), ]) ]) assert backend.cipher_supported( algorithms.AES(b"\x00" * 16), modes.CBC(b"\x00" * 16) ) assert not backend.cipher_supported( algorithms.TripleDES(b"\x00" * 16), modes.CBC(b"\x00" * 16) ) cipher = Cipher( algorithms.AES(b"\x00" * 16), modes.CBC(b"\x00" * 16), backend=backend ) cipher.encryptor() cipher.decryptor() cipher = Cipher( algorithms.Camellia(b"\x00" * 16), modes.CBC(b"\x00" * 16), backend=backend ) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): cipher.encryptor() with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): cipher.decryptor() def test_hashes(self): backend = MultiBackend([ DummyHashBackend([hashes.MD5]) ]) assert backend.hash_supported(hashes.MD5()) assert not backend.hash_supported(hashes.SHA256()) hashes.Hash(hashes.MD5(), backend=backend) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH): hashes.Hash(hashes.SHA1(), backend=backend) def test_hmac(self): backend = MultiBackend([ DummyHMACBackend([hashes.MD5]) ]) assert backend.hmac_supported(hashes.MD5()) assert not backend.hmac_supported(hashes.SHA256()) hmac.HMAC(b"", hashes.MD5(), backend=backend) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH): hmac.HMAC(b"", hashes.SHA1(), backend=backend) def test_pbkdf2(self): backend = MultiBackend([ DummyPBKDF2HMACBackend([hashes.MD5]) ]) assert backend.pbkdf2_hmac_supported(hashes.MD5()) backend.derive_pbkdf2_hmac(hashes.MD5(), 10, b"", 10, b"") with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH): backend.derive_pbkdf2_hmac(hashes.SHA1(), 10, b"", 10, b"") def test_rsa(self): backend = MultiBackend([ DummyRSABackend() ]) backend.generate_rsa_private_key( key_size=1024, public_exponent=65537 ) backend.rsa_padding_supported(padding.PKCS1v15()) backend.generate_rsa_parameters_supported(65537, 1024) backend.load_rsa_private_numbers("private_numbers") backend.load_rsa_public_numbers("public_numbers") backend = MultiBackend([]) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.generate_rsa_private_key(key_size=1024, public_exponent=3) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.rsa_padding_supported(padding.PKCS1v15()) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.generate_rsa_parameters_supported(65537, 1024) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.load_rsa_private_numbers("private_numbers") with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.load_rsa_public_numbers("public_numbers") def test_dsa(self): backend = MultiBackend([ DummyDSABackend() ]) backend.generate_dsa_parameters(key_size=1024) parameters = object() backend.generate_dsa_private_key(parameters) backend.generate_dsa_private_key_and_parameters(key_size=1024) backend.dsa_hash_supported(hashes.SHA1()) backend.dsa_parameters_supported(1, 2, 3) backend.load_dsa_private_numbers("numbers") backend.load_dsa_public_numbers("numbers") backend.load_dsa_parameter_numbers("numbers") backend = MultiBackend([]) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.generate_dsa_parameters(key_size=1024) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.generate_dsa_private_key(parameters) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.generate_dsa_private_key_and_parameters(key_size=1024) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.dsa_hash_supported(hashes.SHA1()) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.dsa_parameters_supported('p', 'q', 'g') with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.load_dsa_private_numbers("numbers") with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.load_dsa_public_numbers("numbers") with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.load_dsa_parameter_numbers("numbers") def test_cmac(self): backend = MultiBackend([ DummyCMACBackend([algorithms.AES]) ]) fake_key = b"\x00" * 16 assert backend.cmac_algorithm_supported(algorithms.AES(fake_key)) assert not backend.cmac_algorithm_supported( algorithms.TripleDES(fake_key) ) cmac.CMAC(algorithms.AES(fake_key), backend) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): cmac.CMAC(algorithms.TripleDES(fake_key), backend) def test_elliptic_curve(self): backend = MultiBackend([ DummyEllipticCurveBackend([ ec.SECT283K1 ]) ]) assert backend.elliptic_curve_supported(ec.SECT283K1()) is True assert backend.elliptic_curve_signature_algorithm_supported( ec.ECDSA(hashes.SHA256()), ec.SECT283K1() ) is True backend.generate_elliptic_curve_private_key(ec.SECT283K1()) backend.load_elliptic_curve_private_numbers( ec.EllipticCurvePrivateNumbers( 1, ec.EllipticCurvePublicNumbers( 2, 3, ec.SECT283K1() ) ) ) backend.load_elliptic_curve_public_numbers( ec.EllipticCurvePublicNumbers( 2, 3, ec.SECT283K1() ) ) assert backend.elliptic_curve_supported(ec.SECT163K1()) is False assert backend.elliptic_curve_signature_algorithm_supported( ec.ECDSA(hashes.SHA256()), ec.SECT163K1() ) is False with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE): backend.generate_elliptic_curve_private_key(ec.SECT163K1()) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE): backend.load_elliptic_curve_private_numbers( ec.EllipticCurvePrivateNumbers( 1, ec.EllipticCurvePublicNumbers( 2, 3, ec.SECT163K1() ) ) ) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE): backend.load_elliptic_curve_public_numbers( ec.EllipticCurvePublicNumbers( 2, 3, ec.SECT163K1() ) ) def test_pem_serialization_backend(self): backend = MultiBackend([DummyPEMSerializationBackend()]) backend.load_pem_private_key(b"keydata", None) backend.load_pem_public_key(b"keydata") backend = MultiBackend([]) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION): backend.load_pem_private_key(b"keydata", None) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION): backend.load_pem_public_key(b"keydata") def test_der_serialization_backend(self): backend = MultiBackend([DummyDERSerializationBackend()]) backend.load_der_private_key(b"keydata", None) backend.load_der_public_key(b"keydata") backend = MultiBackend([]) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION): backend.load_der_private_key(b"keydata", None) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION): backend.load_der_public_key(b"keydata") def test_x509_backend(self): backend = MultiBackend([DummyX509Backend()]) backend.load_pem_x509_certificate(b"certdata") backend.load_der_x509_certificate(b"certdata") backend.load_pem_x509_csr(b"reqdata") backend.load_der_x509_csr(b"reqdata") backend.create_x509_csr(object(), b"privatekey", hashes.SHA1()) backend.create_x509_certificate(object(), b"privatekey", hashes.SHA1()) backend = MultiBackend([]) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509): backend.load_pem_x509_certificate(b"certdata") with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509): backend.load_der_x509_certificate(b"certdata") with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509): backend.load_pem_x509_csr(b"reqdata") with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509): backend.load_der_x509_csr(b"reqdata") with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509): backend.create_x509_csr(object(), b"privatekey", hashes.SHA1()) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509): backend.create_x509_certificate( object(), b"privatekey", hashes.SHA1() )