/* Copyright 2011 Jun Wako This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "wait.h" #include "keycode.h" #include "host.h" #include "keymap.h" #include "print.h" #include "debug.h" #include "util.h" #include "timer.h" #include "keyboard.h" #include "bootloader.h" #include "action_layer.h" #include "action_util.h" #include "eeconfig.h" #include "sleep_led.h" #include "led.h" #include "command.h" #include "backlight.h" #include "quantum.h" #ifdef MOUSEKEY_ENABLE #include "mousekey.h" #endif #ifdef PROTOCOL_PJRC #include "usb_keyboard.h" #ifdef EXTRAKEY_ENABLE #include "usb_extra.h" #endif #endif #ifdef PROTOCOL_VUSB #include "usbdrv.h" #endif #ifdef AUDIO_ENABLE #include "audio.h" #endif /* AUDIO_ENABLE */ static bool command_common(uint8_t code); static void command_common_help(void); static void print_version(void); static void print_status(void); static bool command_console(uint8_t code); static void command_console_help(void); #ifdef MOUSEKEY_ENABLE static bool mousekey_console(uint8_t code); static void mousekey_console_help(void); #endif static void switch_default_layer(uint8_t layer); command_state_t command_state = ONESHOT; bool command_proc(uint8_t code) { switch (command_state) { case ONESHOT: if (!IS_COMMAND()) return false; return (command_extra(code) || command_common(code)); break; case CONSOLE: if (IS_COMMAND()) return (command_extra(code) || command_common(code)); else return (command_console_extra(code) || command_console(code)); break; #ifdef MOUSEKEY_ENABLE case MOUSEKEY: mousekey_console(code); break; #endif default: command_state = ONESHOT; return false; } return true; } /* TODO: Refactoring is needed. */ /* This allows to define extra commands. return false when not processed. */ bool command_extra(uint8_t code) __attribute__ ((weak)); bool command_extra(uint8_t code) { (void)code; return false; } bool command_console_extra(uint8_t code) __attribute__ ((weak)); bool command_console_extra(uint8_t code) { (void)code; return false; } /*********************************************************** * Command common ***********************************************************/ static void command_common_help(void) { print( "\n\t- Magic -\n" STR(MAGIC_KEY_DEBUG ) ": Debug Message Toggle\n" STR(MAGIC_KEY_DEBUG_MATRIX) ": Matrix Debug Mode Toggle - Show keypresses in matrix grid\n" STR(MAGIC_KEY_DEBUG_KBD ) ": Keyboard Debug Toggle - Show keypress report\n" STR(MAGIC_KEY_DEBUG_MOUSE ) ": Debug Mouse Toggle\n" STR(MAGIC_KEY_VERSION ) ": Version\n" STR(MAGIC_KEY_STATUS ) ": Status\n" STR(MAGIC_KEY_CONSOLE ) ": Activate Console Mode\n" #if MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM STR(MAGIC_KEY_LAYER0 ) ": Switch to Layer 0\n" STR(MAGIC_KEY_LAYER1 ) ": Switch to Layer 1\n" STR(MAGIC_KEY_LAYER2 ) ": Switch to Layer 2\n" STR(MAGIC_KEY_LAYER3 ) ": Switch to Layer 3\n" STR(MAGIC_KEY_LAYER4 ) ": Switch to Layer 4\n" STR(MAGIC_KEY_LAYER5 ) ": Switch to Layer 5\n" STR(MAGIC_KEY_LAYER6 ) ": Switch to Layer 6\n" STR(MAGIC_KEY_LAYER7 ) ": Switch to Layer 7\n" STR(MAGIC_KEY_LAYER8 ) ": Switch to Layer 8\n" STR(MAGIC_KEY_LAYER9 ) ": Switch to Layer 9\n" #endif #if MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS "F1-F10: Switch to Layer 0-9 (F10 = L0)\n" #endif #if MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS "0-9: Switch to Layer 0-9\n" #endif STR(MAGIC_KEY_LAYER0_ALT1 ) ": Switch to Layer 0 (alternate key 1)\n" STR(MAGIC_KEY_LAYER0_ALT2 ) ": Switch to Layer 0 (alternate key 2)\n" STR(MAGIC_KEY_BOOTLOADER ) ": Jump to Bootloader (Reset)\n" #ifdef KEYBOARD_LOCK_ENABLE STR(MAGIC_KEY_LOCK ) ": Lock\n" #endif #ifdef BOOTMAGIC_ENABLE STR(MAGIC_KEY_EEPROM ) ": Print EEPROM Settings\n" #endif #ifdef NKRO_ENABLE STR(MAGIC_KEY_NKRO ) ": NKRO Toggle\n" #endif #ifdef SLEEP_LED_ENABLE STR(MAGIC_KEY_SLEEP_LED ) ": Sleep LED Test\n" #endif ); } static void print_version(void) { // print version & information print("\n\t- Version -\n"); print("DESC: " STR(DESCRIPTION) "\n"); print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") " "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") " "VER: " STR(DEVICE_VER) "\n"); print("BUILD: " STR(VERSION) " (" __TIME__ " " __DATE__ ")\n"); /* build options */ print("OPTIONS:" #ifdef PROTOCOL_PJRC " PJRC" #endif #ifdef PROTOCOL_LUFA " LUFA" #endif #ifdef PROTOCOL_VUSB " VUSB" #endif #ifdef BOOTMAGIC_ENABLE " BOOTMAGIC" #endif #ifdef MOUSEKEY_ENABLE " MOUSEKEY" #endif #ifdef EXTRAKEY_ENABLE " EXTRAKEY" #endif #ifdef CONSOLE_ENABLE " CONSOLE" #endif #ifdef COMMAND_ENABLE " COMMAND" #endif #ifdef NKRO_ENABLE " NKRO" #endif #ifdef KEYMAP_SECTION_ENABLE " KEYMAP_SECTION" #endif " " STR(BOOTLOADER_SIZE) "\n"); print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__) #if defined(__AVR__) " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__ " AVR_ARCH: avr" STR(__AVR_ARCH__) #endif "\n"); return; } static void print_status(void) { print("\n\t- Status -\n"); print_val_hex8(host_keyboard_leds()); print_val_hex8(keyboard_protocol); print_val_hex8(keyboard_idle); #ifdef NKRO_ENABLE print_val_hex8(keyboard_nkro); #endif print_val_hex32(timer_read32()); #ifdef PROTOCOL_PJRC print_val_hex8(UDCON); print_val_hex8(UDIEN); print_val_hex8(UDINT); print_val_hex8(usb_keyboard_leds); print_val_hex8(usb_keyboard_idle_count); #endif #ifdef PROTOCOL_PJRC # if USB_COUNT_SOF print_val_hex8(usbSofCount); # endif #endif return; } #ifdef BOOTMAGIC_ENABLE static void print_eeconfig(void) { #ifndef NO_PRINT print("default_layer: "); print_dec(eeconfig_read_default_layer()); print("\n"); debug_config_t dc; dc.raw = eeconfig_read_debug(); print("debug_config.raw: "); print_hex8(dc.raw); print("\n"); print(".enable: "); print_dec(dc.enable); print("\n"); print(".matrix: "); print_dec(dc.matrix); print("\n"); print(".keyboard: "); print_dec(dc.keyboard); print("\n"); print(".mouse: "); print_dec(dc.mouse); print("\n"); keymap_config_t kc; kc.raw = eeconfig_read_keymap(); print("keymap_config.raw: "); print_hex8(kc.raw); print("\n"); print(".swap_control_capslock: "); print_dec(kc.swap_control_capslock); print("\n"); print(".capslock_to_control: "); print_dec(kc.capslock_to_control); print("\n"); print(".swap_lalt_lgui: "); print_dec(kc.swap_lalt_lgui); print("\n"); print(".swap_ralt_rgui: "); print_dec(kc.swap_ralt_rgui); print("\n"); print(".no_gui: "); print_dec(kc.no_gui); print("\n"); print(".swap_grave_esc: "); print_dec(kc.swap_grave_esc); print("\n"); print(".swap_backslash_backspace: "); print_dec(kc.swap_backslash_backspace); print("\n"); print(".nkro: "); print_dec(kc.nkro); print("\n"); #ifdef BACKLIGHT_ENABLE backlight_config_t bc; bc.raw = eeconfig_read_backlight(); print("backlight_config.raw: "); print_hex8(bc.raw); print("\n"); print(".enable: "); print_dec(bc.enable); print("\n"); print(".level: "); print_dec(bc.level); print("\n"); #endif /* BACKLIGHT_ENABLE */ #endif /* !NO_PRINT */ } #endif /* BOOTMAGIC_ENABLE */ static bool command_common(uint8_t code) { #ifdef KEYBOARD_LOCK_ENABLE static host_driver_t *host_driver = 0; #endif switch (code) { #ifdef SLEEP_LED_ENABLE // test breathing sleep LED case MAGIC_KC(MAGIC_KEY_SLEEP_LED): print("Sleep LED Test\n"); sleep_led_toggle(); led_set(host_keyboard_leds()); break; #endif #ifdef BOOTMAGIC_ENABLE // print stored eeprom config case MAGIC_KC(MAGIC_KEY_EEPROM): print("eeconfig:\n"); print_eeconfig(); break; #endif #ifdef KEYBOARD_LOCK_ENABLE // lock/unlock keyboard case MAGIC_KC(MAGIC_KEY_LOCK): if (host_get_driver()) {
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.

from __future__ import absolute_import, division, print_function

INCLUDES = """
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <openssl/crypto.h>

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Wincrypt.h>
#include <Winsock2.h>
#else
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#endif
"""

TYPES = """
typedef struct {
    char *password;
    int length;
    int called;
    int error;
    int maxsize;
} CRYPTOGRAPHY_PASSWORD_DATA;
"""

FUNCTIONS = """
int _setup_ssl_threads(void);
int Cryptography_pem_password_cb(char *, int, int, void *);
"""

CUSTOMIZATIONS = """
/* This code is derived from the locking code found in the Python _ssl module's
   locking callback for OpenSSL.

   Copyright 2001-2016 Python Software Foundation; All Rights Reserved.

   It has been subsequently modified to use cross platform locking without
   using CPython APIs by Armin Rigo of the PyPy project.
*/

#ifdef _WIN32
typedef CRITICAL_SECTION Cryptography_mutex;
static __inline void cryptography_mutex_init(Cryptography_mutex *mutex) {
    InitializeCriticalSection(mutex);
}
static __inline void cryptography_mutex_lock(Cryptography_mutex *mutex) {
    EnterCriticalSection(mutex);
}
static __inline void cryptography_mutex_unlock(Cryptography_mutex *mutex) {
    LeaveCriticalSection(mutex);
}
#else
typedef pthread_mutex_t Cryptography_mutex;
#define ASSERT_STATUS(call)                                             \
    if ((call) != 0) {                                                  \
        perror("Fatal error in callback initialization: " #call);       \
        abort();                                                        \
    }
static inline void cryptography_mutex_init(Cryptography_mutex *mutex) {
#if !defined(pthread_mutexattr_default)
#  define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
#endif
    ASSERT_STATUS(pthread_mutex_init(mutex, pthread_mutexattr_default));
}
static inline void cryptography_mutex_lock(Cryptography_mutex *mutex) {
    ASSERT_STATUS(pthread_mutex_lock(mutex));
}
static inline void cryptography_mutex_unlock(Cryptography_mutex *mutex) {
    ASSERT_STATUS(pthread_mutex_unlock(mutex));
}
#endif



static unsigned int _ssl_locks_count = 0;
static Cryptography_mutex *_ssl_locks = NULL;

static void _ssl_thread_locking_function(int mode, int n, const char *file,
                                         int line) {
    /* this function is needed to perform locking on shared data
       structures. (Note that OpenSSL uses a number of global data
       structures that will be implicitly shared whenever multiple
       threads use OpenSSL.) Multi-threaded applications will
       crash at random if it is not set.

       locking_function() must be able to handle up to
       CRYPTO_num_locks() different mutex locks. It sets the n-th
       lock if mode & CRYPTO_LOCK, and releases it otherwise.

       file and line are the file number of the function setting the
       lock. They can be useful for debugging.
    */

    if ((_ssl_locks == NULL) ||
        (n < 0) || ((unsigned)n >= _ssl_locks_count)) {
        return;
    }

    if (mode & CRYPTO_LOCK) {
        cryptography_mutex_lock(_ssl_locks + n);
    } else {
        cryptography_mutex_unlock(_ssl_locks + n);
    }
}

static void init_mutexes(void) {
    int i;
    for (i = 0; i < _ssl_locks_count; i++) {
        cryptography_mutex_init(_ssl_locks + i);
    }
}


int _setup_ssl_threads(void) {
    if (_ssl_locks == NULL) {
        _ssl_locks_count = CRYPTO_num_locks();
        _ssl_locks = calloc(_ssl_locks_count, sizeof(Cryptography_mutex));
        if (_ssl_locks == NULL) {
            return 0;
        }
        init_mutexes();
        CRYPTO_set_locking_callback(_ssl_thread_locking_function);
#ifndef _WIN32
        pthread_atfork(NULL, NULL, &init_mutexes);
#endif
    }
    return 1;
}

typedef struct {
    char *password;
    int length;
    int called;
    int error;
    int maxsize;
} CRYPTOGRAPHY_PASSWORD_DATA;

int Cryptography_pem_password_cb(char *buf, int size,
                                  int rwflag, void *userdata) {
    /* The password cb is only invoked if OpenSSL decides the private
       key is encrypted. So this path only occurs if it needs a password */
    CRYPTOGRAPHY_PASSWORD_DATA *st = (CRYPTOGRAPHY_PASSWORD_DATA *)userdata;
    st->called += 1;
    st->maxsize = size;
    if (st->length == 0) {
        st->error = -1;
        return 0;
    } else if (st->length < size) {
        memcpy(buf, st->password, st->length);
        return st->length;
    } else {
        st->error = -2;
        return 0;
    }
}
"""