Compare commits

...

49 Commits

Author SHA1 Message Date
Matthias Fulz 19d14d4ef7 Merge branch 'keyboards/trenctyl_manuform' into enc_master 2022-08-23 10:08:56 +02:00
Matthias Fulz 764bcd12c5 Merge branch 'features/encryption' into enc_master 2022-08-23 10:08:47 +02:00
Matthias Fulz fc450f4de0 Merge branch 'master' into keyboards/trenctyl_manuform 2022-08-23 10:08:27 +02:00
Matthias Fulz c644facdac Merge branch 'master' into features/encryption 2022-08-23 10:08:04 +02:00
Matthias Fulz df13bc34bf Fixed OLED block count 2022-08-23 10:07:57 +02:00
Matthias Fulz 143a1afccb Merge branch 'features/encryption' into enc_master 2022-07-26 12:50:58 +02:00
Matthias Fulz f6d7770a85 key oled feedback 2022-07-26 12:49:54 +02:00
Matthias Fulz f5d4b4f86f Merge branch 'features/encryption' into enc_master 2022-07-26 09:40:09 +02:00
Matthias Fulz 89de0b3091 bugfixes 2022-07-26 09:39:56 +02:00
Matthias Fulz 539f96a2c6 Merge branch 'features/encryption' into enc_master 2022-07-26 09:22:17 +02:00
Matthias Fulz 3a52e1819e added backspace for keys 2022-07-26 09:22:03 +02:00
Matthias Fulz f68a65d766 added backspace for keys 2022-07-26 09:17:19 +02:00
Matthias Fulz c7d78a05f3 fixed key loading 2022-07-26 09:04:00 +02:00
Matthias Fulz c501395cc1 Merge branch 'keyboards/trenctyl_manuform' into enc_master 2022-07-26 01:46:52 +02:00
Matthias Fulz 4c4bc524c2 Merge branch 'features/encryption' into enc_master 2022-07-26 01:46:47 +02:00
Matthias Fulz 8161c72c75 added keycode 2022-07-26 01:46:33 +02:00
Matthias Fulz d7f74c7a6f set key via keyboard 2022-07-26 01:43:43 +02:00
Matthias Fulz c54765e246 set key via keyboard 2022-07-26 01:42:24 +02:00
Matthias Fulz 8523ffd758 Merge branch 'keyboards/trenctyl_manuform' into enc_master 2022-07-25 22:21:51 +02:00
Matthias Fulz 7145871ccf Merge branch 'features/encryption' into enc_master 2022-07-25 22:21:45 +02:00
Matthias Fulz 3019b56aac Merge branch 'master' into keyboards/trenctyl_manuform 2022-07-25 22:21:26 +02:00
Matthias Fulz ba36d2204b Merge branch 'master' into features/encryption 2022-07-25 22:21:02 +02:00
Matthias Fulz f197e476df Merge branch 'keyboards/trenctyl_manuform' into enc_master 2022-07-19 10:51:40 +02:00
Matthias Fulz 4d3adb0437 Merge branch 'features/encryption' into enc_master 2022-07-19 10:51:34 +02:00
Matthias Fulz e4ff1fdf80 Merge branch 'master' into keyboards/trenctyl_manuform 2022-07-19 10:51:20 +02:00
Matthias Fulz 562df82b85 Merge branch 'master' into features/encryption 2022-07-19 10:51:03 +02:00
Matthias Fulz f7bfe769b8 Merge branch 'keyboards/trenctyl_manuform' into enc_master 2022-07-11 00:37:57 +02:00
Matthias Fulz 914cc32ec0 Merge branch 'features/encryption' into enc_master 2022-07-11 00:37:48 +02:00
Matthias Fulz fc9eb9dd06 Merge branch 'master' into keyboards/trenctyl_manuform 2022-07-11 00:37:31 +02:00
Matthias Fulz 62e448747e Merge branch 'master' into features/encryption 2022-07-11 00:36:57 +02:00
Matthias Fulz 868b416f77 Merge branch 'keyboards/trenctyl_manuform' into enc_master 2022-07-04 00:29:22 +02:00
Matthias Fulz f8a382de40 Merge branch 'features/encryption' into enc_master 2022-07-04 00:29:10 +02:00
Matthias Fulz 8d90fc1474 Added close keyboard handle 2022-07-04 00:27:55 +02:00
Matthias Fulz c473110c89 Merge branch 'master' into keyboards/trenctyl_manuform 2022-07-04 00:26:18 +02:00
Matthias Fulz 4a28710f4b Merge branch 'master' into features/encryption 2022-07-04 00:25:46 +02:00
Matthias Fulz af291b0990 Merge branch 'features/encryption' into enc_master 2022-07-02 14:12:31 +02:00
Matthias Fulz 5acc167a3f Merge branch 'keyboards/trenctyl_manuform' into enc_master 2022-07-02 14:12:22 +02:00
Matthias Fulz 9bda2904f3 Mouse speed adjustments 2022-07-02 14:11:47 +02:00
Matthias Fulz 969c680721 Merge branch 'master' into features/encryption 2022-06-28 10:55:31 +02:00
Matthias Fulz 365709dc15 Merge branch 'features/encryption' into enc_master 2022-06-28 10:51:18 +02:00
Matthias Fulz 1e145e0fed Merge branch 'keyboards/trenctyl_manuform' into enc_master 2022-06-28 10:51:12 +02:00
Matthias Fulz d7bdb943f0 Merge branch 'master' into keyboards/trenctyl_manuform 2022-06-28 10:50:51 +02:00
Matthias Fulz 2350ecd5b7 Merge branch 'master' into features/encryption 2022-06-28 10:50:25 +02:00
Matthias Fulz 30a7fa7cd1 Merge branch 'keyboards/trenctyl_manuform' into enc_master 2022-06-27 00:37:07 +02:00
Matthias Fulz dc5cb40c72 Fixed renaming 2022-06-26 22:03:17 +02:00
Matthias Fulz b0ff58a23a Fixed renaming 2022-06-26 22:02:01 +02:00
Matthias Fulz eb60e9230a Fixed transactions 2022-06-26 21:59:21 +02:00
Matthias Fulz 27801eefc8 New master broke compilation 2022-06-26 21:41:19 +02:00
Matthias Fulz 43ef5cedf0 Updated encryption feature to new master -> something totally broke... 2022-06-26 21:36:17 +02:00
35 changed files with 4582 additions and 2 deletions

View File

@ -556,6 +556,17 @@ ifeq ($(strip $(VIA_ENABLE)), yes)
OPT_DEFS += -DVIA_ENABLE
endif
ifeq ($(strip $(ENC_ENABLE)), yes)
RAW_ENABLE := yes
COMMON_VPATH += $(QUANTUM_DIR)/enc
COMMON_VPATH += $(QUANTUM_DIR)/enc/enc_boards
include $(QUANTUM_DIR)/enc/enc_boards/enc_boards.mk
OPT_DEFS += -DENC_ENABLE
SRC += aes.c
SRC += pkcs7_padding.c
SRC += enc.c
endif
VALID_MAGIC_TYPES := yes
BOOTMAGIC_ENABLE ?= no
ifneq ($(strip $(BOOTMAGIC_ENABLE)), no)

View File

@ -11,7 +11,8 @@ BUILD_OPTION_NAMES = \
SPLIT_KEYBOARD \
DYNAMIC_KEYMAP_ENABLE \
USB_HID_ENABLE \
VIA_ENABLE
VIA_ENABLE \
ENC_ENABLE
HARDWARE_OPTION_NAMES = \
SLEEP_LED_ENABLE \

View File

@ -0,0 +1 @@
#include "6x6.h"

View File

@ -0,0 +1,40 @@
#pragma once
#include "trenctyl_manuform.h"
#if defined(KEYBOARD_handwired_trenctyl_manuform_6x6_f401)
# include "f401.h"
#elif defined(KEYBOARD_handwired_trenctyl_manuform_6x6_f411)
# include "f411.h"
#endif
#define XXX KC_NO
#define LAYOUT_6x6( \
L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
L30, L31, L32, L33, L34, L35, R30, R31, R32, R33, R34, R35, \
L40, L41, L42, L43, L44, L45, R40, R41, R42, R43, R44, R45, \
L51, L52, L53, R52, R53, \
L54, L55, R50, R51, \
L64, L65, R60, R61, \
L62, L63 \
) { \
{ L00, L01, L02, L03, L04, L05 }, \
{ L10, L11, L12, L13, L14, L15 }, \
{ L20, L21, L22, L23, L24, L25 }, \
{ L30, L31, L32, L33, L34, L35 }, \
{ L40, L41, L42, L43, L44, L45 }, \
{ XXX, L51, L52, L53, L54, L55 }, \
{ XXX, XXX, L62, L63, L64, L65 }, \
\
{ R00, R01, R02, R03, R04, R05 }, \
{ R10, R11, R12, R13, R14, R15 }, \
{ R20, R21, R22, R23, R24, R25 }, \
{ R30, R31, R32, R33, R34, R35 }, \
{ R40, R41, R42, R43, R44, R45 }, \
{ R50, R51, R52, R53, XXX, XXX }, \
{ R60, R61, XXX, XXX, XXX, XXX } \
}

View File

@ -0,0 +1,91 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "config_common.h"
/* key matrix size */
// Rows are doubled-up
#define MATRIX_ROWS 14
#define MATRIX_COLS 6
#define RGB_MATRIX_KEYPRESSES
//#define RGB_MATRIX_KEYRELEASES
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
#define SPLIT_TRANSPORT_MIRROR
#define SPLIT_LAYER_STATE_ENABLE
#define SPLIT_ENC_MODE_ENABLE
#define SPLIT_ENC_FLAGS_ENABLE
#define SPLIT_OLED_ENABLE
#define POINTING_DEVICE_INVERT_Y TRUE
#define PMW3360_LIFTOFF_DISTANCE 0x03
#define ONESHOT_TAP_TOGGLE 3
#define OLED_TIMEOUT 0
#define ENABLE_RGB_MATRIX_NONE
#define ENABLE_RGB_MATRIX_SOLID_COLOR // Static single hue, no speed support
#define ENABLE_RGB_MATRIX_ALPHAS_MODS // Static dual hue, speed is hue for secondary hue
#define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN // Static gradient top to bottom, speed controls how much gradient changes
#define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT // Static gradient left to right, speed controls how much gradient changes
#define ENABLE_RGB_MATRIX_BREATHING // Single hue brightness cycling animation
#define ENABLE_RGB_MATRIX_BAND_SAT // Single hue band fading saturation scrolling left to right
#define ENABLE_RGB_MATRIX_BAND_VAL // Single hue band fading brightness scrolling left to right
#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT // Single hue 3 blade spinning pinwheel fades saturation
#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL // Single hue 3 blade spinning pinwheel fades brightness
#define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT // Single hue spinning spiral fades saturation
#define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL // Single hue spinning spiral fades brightness
#define ENABLE_RGB_MATRIX_CYCLE_ALL // Full keyboard solid hue cycling through full gradient
#define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT // Full gradient scrolling left to right
#define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN // Full gradient scrolling top to bottom
#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN // Full gradient scrolling out to in
#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL // Full dual gradients scrolling out to in
#define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON // Full gradent Chevron shapped scrolling left to right
#define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL // Full gradient spinning pinwheel around center of keyboard
#define ENABLE_RGB_MATRIX_CYCLE_SPIRAL // Full gradient spinning spiral around center of keyboard
#define ENABLE_RGB_MATRIX_DUAL_BEACON // Full gradient spinning around center of keyboard
#define ENABLE_RGB_MATRIX_RAINBOW_BEACON // Full tighter gradient spinning around center of keyboard
#define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS // Full dual gradients spinning two halfs of keyboard
#define ENABLE_RGB_MATRIX_RAINDROPS // Randomly changes a single key's hue
#define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS // Randomly changes a single key's hue and saturation
#define ENABLE_RGB_MATRIX_HUE_BREATHING // Hue shifts up a slight ammount at the same time then shifts back
#define ENABLE_RGB_MATRIX_HUE_PENDULUM // Hue shifts up a slight ammount in a wave to the right then back to the left
#define ENABLE_RGB_MATRIX_HUE_WAVE // Hue shifts up a slight ammount and then back down in a wave to the right
#define ENABLE_RGB_MATRIX_PIXEL_FRACTAL // Single hue fractal filled keys pulsing horizontally out to edges
#define ENABLE_RGB_MATRIX_PIXEL_RAIN // Randomly light keys with random hues
#define ENABLE_RGB_MATRIX_TYPING_HEATMAP // How hot is your WPM!
#define ENABLE_RGB_MATRIX_DIGITAL_RAIN // That famous computer simulation
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE // Pulses keys hit to hue & value then fades value out
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE // Static single hue pulses keys hit to shifted hue then fades to current hue
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE // Hue & value pulse near a single key hit then fades value out
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE // Hue & value pulse near multiple key hits then fades value out
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS // Hue & value pulse the same column and row of a single key hit then fades value out
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS // Hue & value pulse the same column and row of multiple key hits then fades value out
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS // Hue & value pulse away on the same column and row of a single key hit then fades value out
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS // Hue & value pulse away on the same column and row of multiple key hits then fades value out
#define ENABLE_RGB_MATRIX_SPLASH // Full gradient & value pulse away from a single key hit then fades value out
#define ENABLE_RGB_MATRIX_MULTISPLASH // Full gradient & value pulse away from multiple key hits then fades value out
#define ENABLE_RGB_MATRIX_SOLID_SPLASH // Hue & value pulse away from a single key hit then fades value out
#define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH // Hue & value pulse away from multiple key hits then fades value out
#define ENABLE_RGB_MATRIX_EFFECT_MAX
#define SPLIT_TRANSACTION_IDS_USER USER_SYNC_VIS_STATUS

View File

@ -0,0 +1,76 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "config_common.h"
#define PRODUCT_ID 0x3836
#define DEVICE_VER 0x0001
#define PRODUCT Trenctyl Manuform (6x6) BlackPill F01
#define MATRIX_ROW_PINS { A15, B13, B14, B15, A8, B6, B7 }
#define MATRIX_COL_PINS { B10, B0, A1, A0, B4, C14 }
#define MATRIX_ROW_PINS_RIGHT { A15, B13, B14, B15, A8, B6, B7 }
#define MATRIX_COL_PINS_RIGHT { B10, B0, A1, A0, B4, C14 }
#define DIODE_DIRECTION ROW2COL
#define RGB_DI_PIN B3
#define RGBLED_NUM 74
#define DRIVER_LED_TOTAL 74
#define RGBLIGHT_SPLIT
#define RGBLED_SPLIT { 38, 36 }
#define RGBLIGHT_LIMIT_VAL 200
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS RGBLIGHT_LIMIT_VAL
#define RGB_MATRIX_SPLIT RGBLED_SPLIT
#define RGB_MATRIX_CENTER { 110, 19 }
#define SERIAL_USART_RX_PIN A2
#define SELECT_SOFT_SERIAL_SPEED 1
#define FORCED_SYNC_THROTTLE_MS 200
#define SERIAL_USART_DRIVER SD2
#define SERIAL_USART_TX_PAL_MODE 7
#define SERIAL_USART_RX_PAL_MODE 7
#define SERIAL_USART_TIMEOUT 10
#define I2C1_SCL_PIN B8
#define I2C1_SDA_PIN B9
#define PMW3360_CS_PIN A4
#define SPI_DRIVER SPID1
#define SPI_SCK_PIN A5
#define SPI_SCK_PAL_MODE 5
#define SPI_MOSI_PIN A7
#define SPI_MOSI_PAL_MODE 5
#define SPI_MISO_PIN A6
#define SPI_MISO_PAL_MODE 5
#define ENCODERS_PAD_A { C13 }
#define ENCODERS_PAD_B { C15 }
#define WS2812_PWM_DRIVER PWMD2
#define WS2812_PWM_CHANNEL 2
#define WS2812_DMA_STREAM STM32_DMA1_STREAM7
#define WS2812_DMA_CHANNEL 3
#define WS2812_PWM_PAL_MODE 1
// hw rnd generator
//#define ENC_HW_RND_STM32F4

View File

@ -0,0 +1,19 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "6x6.h"

View File

@ -0,0 +1,8 @@
#pragma once
#define HAL_USE_SERIAL TRUE
#define HAL_USE_I2C TRUE
#define HAL_USE_SPI TRUE
#define HAL_USE_PWM TRUE
#include_next <halconf.h>

View File

@ -0,0 +1,33 @@
#pragma once
#include_next "mcuconf.h"
#undef STM32_SERIAL_USE_USART2
#define STM32_SERIAL_USE_USART2 TRUE
#undef STM32_UART_USART2_RX_DMA_STREAM
#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
#undef STM32_UART_USART2_TX_DMA_STREAM
#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#undef STM32_PWM_USE_TIM2
#define STM32_PWM_USE_TIM2 TRUE
#undef STM32_ST_USE_TIMER
#define STM32_ST_USE_TIMER 5
#undef STM32_SPI_USE_SPI1
#define STM32_SPI_USE_SPI1 TRUE
#undef STM32_SPI_SPI1_RX_DMA_STREAM
#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0)
#undef STM32_SPI_SPI1_TX_DMA_STREAM
#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
#undef STM32_I2C_USE_I2C1
#define STM32_I2C_USE_I2C1 TRUE
#undef STM32_ADC_USE_ADC0
#define STM32_ADC_USE_ADC0 TRUE
#undef STM32_ADC_USE_ADC1
#define STM32_ADC_USE_ADC1 TRUE

View File

@ -0,0 +1,6 @@
MCU = STM32F401
BOOTLOADER = stm32-dfu
LTO_ENABLE = no
SERIAL_DRIVER = usart

View File

@ -0,0 +1,102 @@
{
"keyboard_name": "Dactyl Manuform 6x6",
"url": "",
"maintainer": "qmk",
"layouts": {
"LAYOUT_6x6": {
"layout": [
{"x": 0, "y": 0},
{"x": 1, "y": 0},
{"x": 2, "y": 0},
{"x": 3, "y": 0},
{"x": 4, "y": 0},
{"x": 5, "y": 0},
{"x": 11, "y": 0},
{"x": 12, "y": 0},
{"x": 13, "y": 0},
{"x": 14, "y": 0},
{"x": 15, "y": 0},
{"x": 16, "y": 0},
{"x": 0, "y": 1},
{"x": 1, "y": 1},
{"x": 2, "y": 1},
{"x": 3, "y": 1},
{"x": 4, "y": 1},
{"x": 5, "y": 1},
{"x": 11, "y": 1},
{"x": 12, "y": 1},
{"x": 13, "y": 1},
{"x": 14, "y": 1},
{"x": 15, "y": 1},
{"x": 16, "y": 1},
{"x": 0, "y": 2},
{"x": 1, "y": 2},
{"x": 2, "y": 2},
{"x": 3, "y": 2},
{"x": 4, "y": 2},
{"x": 5, "y": 2},
{"x": 11, "y": 2},
{"x": 12, "y": 2},
{"x": 13, "y": 2},
{"x": 14, "y": 2},
{"x": 15, "y": 2},
{"x": 16, "y": 2},
{"x": 0, "y": 3},
{"x": 1, "y": 3},
{"x": 2, "y": 3},
{"x": 3, "y": 3},
{"x": 4, "y": 3},
{"x": 5, "y": 3},
{"x": 11, "y": 3},
{"x": 12, "y": 3},
{"x": 13, "y": 3},
{"x": 14, "y": 3},
{"x": 15, "y": 3},
{"x": 16, "y": 3},
{"x": 0, "y": 4},
{"x": 1, "y": 4},
{"x": 2, "y": 4},
{"x": 3, "y": 4},
{"x": 4, "y": 4},
{"x": 5, "y": 4},
{"x": 11, "y": 4},
{"x": 12, "y": 4},
{"x": 13, "y": 4},
{"x": 14, "y": 4},
{"x": 15, "y": 4},
{"x": 16, "y": 4},
{"x": 1, "y": 5},
{"x": 2, "y": 5},
{"x": 3, "y": 5},
{"x": 13, "y": 5},
{"x": 14, "y": 5},
{"x": 4, "y": 6},
{"x": 5, "y": 6},
{"x": 11, "y": 6},
{"x": 12, "y": 6},
{"x": 6, "y": 7},
{"x": 7, "y": 7},
{"x": 9, "y": 7},
{"x": 10, "y": 7},
{"x": 6, "y": 8},
{"x": 7, "y": 8}
]
}
}
}

View File

@ -0,0 +1,25 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#define SERIAL_USART_FULL_DUPLEX
//#define MASTER_LEFT
#define MASTER_RIGHT
//#define EE_HANDS

View File

@ -0,0 +1,462 @@
#include QMK_KEYBOARD_H
#include "pointing_device.h"
#include "quantum_keycodes.h"
#include "transactions.h"
/*#include "enc.h"*/
#define _QWERTZ 0
#define _CONTROL 1
#define _I3WM 2
#define _MOUSE 3
#define QWERTZ TO(_QWERTZ)
#define CONTROL TT(_CONTROL)
#define I3WM TT(_I3WM)
#define MOUSE TG(_MOUSE)
#ifdef RGB_MATRIX_ENABLE
// clang-format off
led_config_t g_led_config = {{
{ 0, 5, 10, 16, 22, 30, },
{ 1, 6, 11, 17, 23, 31, },
{ 2, 7, 12, 18, 24, 32, },
{ 3, 8, 13, 19, 25, 33, },
{ 4, 9, 14, 20, 26, 34, },
{ NO_LED, NO_LED, 15, 21, 27, 35, },
{ NO_LED, NO_LED, 29, 37, 28, 36, },
// RIGHT HALF
{ 38, 45, 52, 58, 64, 69 },
{ 39, 46, 53, 59, 65, 70 },
{ 40, 47, 54, 60, 66, 71 },
{ 41, 48, 55, 61, 67, 72 },
{ 42, 49, 56, 62, 68, 73 },
{ 43, 50, 57, 63, NO_LED, NO_LED },
{ 44, 51, NO_LED, NO_LED, NO_LED, NO_LED },
}, {
{ 0, 0 }, { 0, 8 }, { 0, 19 }, { 0, 30 }, { 0, 41 },
{ 20, 0 }, { 20, 8 }, { 20, 19 }, { 20, 30 }, { 20, 41 },
{ 40, 0 }, { 40, 8 }, { 40, 19 }, { 40, 30 }, { 40, 41 }, { 40, 52 },
{ 60, 0 }, { 60, 8 }, { 60, 19 }, { 60, 30 }, { 60, 41 }, { 60, 52 },
{ 80, 0 }, { 80, 8 }, { 80, 19 }, { 80, 30 }, { 80, 41 }, { 80, 52 }, { 80, 64 },
{ 40, 64 },
{ 100, 0 }, { 100, 8 }, { 100, 19 }, { 100, 30 }, { 100, 41 }, { 100, 52 }, { 100, 64 },
{ 60, 64 },
// RIGHT HALF
{ 120, 0 }, { 120, 8 }, { 120, 19 }, { 120, 30 }, { 120, 41 }, { 120, 52 }, { 120, 64 },
{ 140, 0 }, { 140, 8 }, { 140, 19 }, { 140, 30 }, { 140, 41 }, { 140, 52 }, { 140, 64 },
{ 160, 0 }, { 160, 8 }, { 160, 19 }, { 160, 30 }, { 160, 41 }, { 160, 52 },
{ 180, 0 }, { 180, 8 }, { 180, 19 }, { 180, 30 }, { 180, 41 }, { 180, 52 },
{ 200, 0 }, { 200, 8 }, { 200, 19 }, { 200, 30 }, { 200, 41 },
{ 224, 0 }, { 224, 8 }, { 224, 19 }, { 224, 30 }, { 224, 41 }
}, {
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4,
4, 4,
4, 4,
4, 4,
/*4, 4, 4, 4, 4, 4,*/
// RIGHT HALF
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4,
4, 4,
4, 4,
/*4, 4, 4, 4, 4, 4,*/
}};
#endif
enum my_keycodes {
CPI_NEXT = SAFE_RANGE,
CPI_PREV,
VIS_VAD,
VIS_VAI
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTZ] = LAYOUT_6x6(
KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 ,KC_F10 ,KC_F11 ,KC_F12 ,
KC_GRV , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 ,KC_BSPC,
KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P ,KC_LBRC,
KC_LCTL, KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L ,KC_SCLN,KC_QUOT,
OSM(MOD_LSFT), KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M ,KC_DOT,KC_COMM ,KC_SLSH,KC_BSLASH,
KC_MUTE,KC_RBRC,KC_MINS, KC_NUBS, KC_EQL,
KC_LALT,KC_ENT, KC_SPC, KC_RALT,
KC_ESC,I3WM, KC_LGUI,MOUSE,
MOUSE,CONTROL
),
[_CONTROL] = LAYOUT_6x6(
ENC_INIT,ENC_LOAD,ENC_CLOSE,ENC_KEY,_______,_______, ENC_REQ_ALLOW,ENC_REQ_DENY,_______,_______,_______,EEP_RST,
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,_______,KC_DEL,
_______,_______,KC_PGDN,KC_UP,KC_PGUP,_______, _______,KC_7,KC_8,KC_9,_______,_______,
_______,_______,KC_LEFT,KC_DOWN,KC_RGHT,_______, KC_HOME,KC_4,KC_5,KC_6,KC_END,_______,
_______,_______,_______,_______,_______,_______, _______,KC_1,KC_2,KC_3,VIS_VAD,_______,
_______,VIS_VAI,_______, KC_0,_______,
RGB_MOD,RGB_RMOD, KC_ENT,RGB_VAI,
RGB_SPD,RGB_SPI, RGB_VAD,RGB_TOG,
QWERTZ,_______
),
[_I3WM] = LAYOUT_6x6(
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,_______,_______,
_______,LGUI(KC_1),LGUI(KC_2),LGUI(KC_3),LGUI(KC_4),LGUI(KC_5), LGUI(KC_6),LGUI(KC_7),LGUI(KC_8),LGUI(KC_9),LGUI(KC_0),_______,
_______,SGUI(KC_C),LGUI(KC_W),LGUI(KC_E),_______,_______, LGUI(KC_Y),_______,LGUI(KC_I),_______,LGUI(KC_P),_______,
_______,LGUI(KC_ENT),LGUI(KC_S),LGUI(KC_D),_______,_______, LGUI(KC_H),LGUI(KC_J),LGUI(KC_K),LGUI(KC_L),_______,_______,
_______,_______,_______,LGUI(KC_C),_______,_______, LAG(KC_N),_______,_______,_______,_______,_______,
_______,_______,_______, _______,_______,
_______,_______, LGUI(KC_ENT),_______,
_______,_______, _______,_______,
QWERTZ,_______
),
[_MOUSE] = LAYOUT_6x6(
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,_______,_______,
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,_______,_______,
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,_______,_______,
_______,_______,KC_MS_BTN2,KC_MS_BTN3,KC_MS_BTN1,_______, _______,_______,_______,_______,_______,_______,
_______,_______,_______,_______,_______,_______, _______,KC_MS_BTN1,KC_MS_BTN3,KC_MS_BTN2,_______,_______,
_______,_______,_______, KC_MS_WH_DOWN,KC_MS_WH_UP,
_______,_______, KC_SPC,CPI_NEXT,
_______,_______, CPI_PREV,QWERTZ,
_______,QWERTZ
),
};
#ifdef OLED_ENABLE
#include <stdio.h>
int get_val_percent(void) {
#ifdef RGB_MATRIX_MAXIMUM_BRIGHTNESS
uint8_t maxVal = RGB_MATRIX_MAXIMUM_BRIGHTNESS;
#else
uint8_t maxVal = 255;
#endif
uint8_t actVal = rgb_matrix_get_val();
float ret = ((float) 100)/((float) maxVal)*((float)actVal);
return ((int) ret);
}
int get_speed_percent(void) {
uint8_t maxVal = 255;
uint8_t actVal = rgb_matrix_get_speed();
float ret = ((float) 100)/((float) maxVal)*((float)actVal);
return ((int) ret);
}
#ifdef POINTING_DEVICE_ENABLE
static uint16_t _cpi;
#endif
static uint8_t _vis_timeout_sec;
static uint32_t _vis_timer;
static bool _vis_status;
bool oled_task_user(void) {
// Host Keyboard Layer Status
if(is_keyboard_master()) {
uint32_t _oled_timeout = ((_vis_timeout_sec * 1000) - timer_elapsed32(_vis_timer)) / 1000;
if (!_vis_status) {
// turn displays off
oled_off();
return true;
}
oled_write_P(PSTR("L: "), false);
switch (get_highest_layer(layer_state)) {
case _QWERTZ:
oled_write_P(PSTR("Quertz\n"), false);
break;
case _CONTROL:
oled_write_P(PSTR("Control\n"), false);
break;
case _I3WM:
oled_write_P(PSTR("I3WM\n"), false);
break;
case _MOUSE:
oled_write_P(PSTR("MOUSE\n"), false);
break;
default:
oled_write_P(PSTR("Undefined\n"), false);
}
char brightness[100];
memset(brightness, 0x00, 100);
if (rgb_matrix_is_enabled()) {
snprintf(brightness, 100, "B: %d%% S: %d%%\n", get_val_percent(), get_speed_percent());
} else {
snprintf(brightness, 100, "B: OFF\n");
}
oled_write_P(PSTR(brightness), false);
#ifdef POINTING_DEVICE_ENABLE
switch(_cpi) {
case 100:
oled_write_P(PSTR("M: >\n"), false);
break;
case 200:
oled_write_P(PSTR("M: >>\n"), false);
break;
case 400:
oled_write_P(PSTR("M: >>>\n"), false);
break;
case 500:
oled_write_P(PSTR("M: >>>>\n"), false);
break;
case 600:
oled_write_P(PSTR("M: >>>>>\n"), false);
break;
}
#endif
oled_write_P(PSTR("V: "), false);
oled_write_P(get_u8_str(_oled_timeout, ' '), false);
oled_write_P(PSTR("s\n"), false);
} else {
#ifdef ENC_ENABLE
enc_write_oled(false);
#endif
oled_write_P(PSTR("L: "), false);
switch (get_highest_layer(layer_state)) {
case _QWERTZ:
oled_write_P(PSTR("Quertz\n"), false);
break;
case _CONTROL:
oled_write_P(PSTR("Control\n"), false);
break;
case _I3WM:
oled_write_P(PSTR("I3WM\n"), false);
break;
case _MOUSE:
oled_write_P(PSTR("MOUSE\n"), false);
break;
default:
oled_write_P(PSTR("Undefined\n"), false);
}
}
return true;
}
#endif
#ifdef POINTING_DEVICE_ENABLE
void pointing_device_init_user(void) {
_cpi = 400;
pointing_device_set_cpi(_cpi);
}
void _cpi_next(void) {
switch(_cpi) {
case 100:
_cpi = 200;
break;
case 200:
_cpi = 400;
break;
case 400:
_cpi = 500;
break;
case 500:
_cpi = 600;
break;
case 600:
_cpi = 100;
break;
}
pointing_device_set_cpi(_cpi);
}
void _cpi_prev(void) {
switch(_cpi) {
case 100:
_cpi = 600;
break;
case 200:
_cpi = 100;
break;
case 400:
_cpi = 200;
break;
case 500:
_cpi = 400;
break;
case 600:
_cpi = 500;
break;
}
pointing_device_set_cpi(_cpi);
}
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
if (!layer_state_is(_MOUSE)) {
mouse_report.h = 0;
mouse_report.v = 0;
mouse_report.x = 0;
mouse_report.y = 0;
}
return mouse_report;
}
#endif
void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
if (!_vis_status) {
return;
}
HSV hsv = (HSV){0, 0, 0};
HSV hsv_alt = (HSV){0, 0, 0};
bool led_off = false;
bool led_alt = false;
switch(get_highest_layer(layer_state)) { // special handling per layer
case _CONTROL:
hsv = (HSV){0, 255, 255};
break;
case _I3WM:
hsv = (HSV){85, 255, 255};
break;
case _MOUSE:
hsv = (HSV){170, 255, 255};
led_off = true;
break;
default:
return;
}
hsv.v = rgb_matrix_get_val();
RGB rgb = hsv_to_rgb(hsv);
hsv_alt.v = rgb_matrix_get_val();
RGB rgb_alt = hsv_to_rgb(hsv_alt);
for (uint8_t row=0; row<MATRIX_ROWS; ++row) {
for (uint8_t col=0; col<MATRIX_COLS; ++col) {
uint8_t index = g_led_config.matrix_co[row][col];
if (index >= led_min && index <= led_max && index != NO_LED) {
if (keymap_key_to_keycode(get_highest_layer(layer_state), (keypos_t){col, row}) > KC_TRNS) {
rgb_matrix_set_color(index, rgb.r, rgb.g, rgb.b);
} else {
if (led_alt) {
rgb_matrix_set_color(index, rgb_alt.r, rgb_alt.g, rgb_alt.b);
continue;
}
if (led_off) {
rgb_matrix_set_color(index, 0, 0, 0);
}
}
}
}
}
}
typedef struct _vis_status {
bool m2s_data;
} vis_status_t;
void user_sync_vis_status_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) {
const vis_status_t *m2s = (const vis_status_t*)in_data;
_vis_status = m2s->m2s_data;
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (is_keyboard_master()) {
_vis_timer = timer_read32();
}
switch (keycode) {
#ifdef POINTING_DEVICE_ENABLE
case CPI_PREV:
if (record->event.pressed) {
_cpi_prev();
}
return false;
case CPI_NEXT:
if (record->event.pressed) {
_cpi_next();
}
return false;
#endif
case VIS_VAD:
if (record->event.pressed) {
_vis_timeout_sec -= 10;
}
return false;
case VIS_VAI:
if (record->event.pressed) {
_vis_timeout_sec += 10;
}
return false;
default:
return true;
}
}
bool encoder_update_user(uint8_t index, bool clockwise) {
switch(index) {
case 0:
if(clockwise) {
tap_code_delay(KC_VOLU, 10);
} else {
tap_code_delay(KC_VOLD, 10);
}
break;
}
return false;
}
void keyboard_pre_init_user(void) {
_vis_status = true;
_vis_timeout_sec = 120;
_vis_timer = timer_read32();
pre_init_enc();
}
void eeconfig_init_user(void) {
eeconfig_init_enc();
}
void keyboard_post_init_user(void) {
transaction_register_rpc(USER_SYNC_VIS_STATUS, user_sync_vis_status_slave_handler);
}
void housekeeping_task_user(void) {
if (is_keyboard_master()) {
if (timer_elapsed32(_vis_timer) >= (_vis_timeout_sec * 1000)) {
_vis_status = false;
} else {
_vis_status = true;
}
static uint32_t last_sync = 0;
if (timer_elapsed32(last_sync) > 500) {
vis_status_t m2s = {_vis_status};
if (transaction_rpc_send(USER_SYNC_VIS_STATUS, sizeof(m2s), &m2s)) {
last_sync = timer_read32();
}
}
}
if (!_vis_status) {
rgb_matrix_set_color_all(0, 0, 0);
}
}

View File

@ -0,0 +1,26 @@
# Build Options
# change yes to no to disable
#
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = yes # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
AUDIO_ENABLE = no # Audio output
SPLIT_KEYBOARD = yes
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = WS2812
WS2812_DRIVER = pwm
VIA_ENABLE = yes
RAW_ENABLE = yes
OLED_ENABLE = yes
ENC_ENABLE = yes
POINTING_DEVICE_ENABLE = yes
POINTING_DEVICE_DRIVER = pmw3360
#DIP_SWITCH_ENABLE = yes
ENCODER_ENABLE = yes

View File

@ -0,0 +1,46 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "config_common.h"
/* USB Device descriptor parameter */
#define VENDOR_ID 0x44FD
#define MANUFACTURER mfulz
/* mouse config */
//#define MOUSEKEY_INTERVAL 20
//#define MOUSEKEY_DELAY 0
//#define MOUSEKEY_TIME_TO_MAX 60
//#define MOUSEKEY_MAX_SPEED 7
//#define MOUSEKEY_WHEEL_DELAY 0
/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5
/* serial.c configuration for split keyboard */
#define SOFT_SERIAL_PIN A3
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE
/* Enables This makes it easier for fast typists to use dual-function keys */
#define PERMISSIVE_HOLD

View File

@ -0,0 +1,159 @@
Dactyl Manuform (4x5, 5x6, 5x7, 6x6)
======
the [Dactyl-Manuform](https://github.com/tshort/dactyl-keyboard) is a split curved keyboard based on the design of [adereth dactyl](https://github.com/adereth/dactyl-keyboard) and thumb cluster design of the [manuform](https://geekhack.org/index.php?topic=46015.0) keyboard, the hardware is similar to the let's split keyboard. all information needed for making one is in the first link.
![Imgur](https://i.imgur.com/7y0Vbyd.jpg)
## First Time Setup
Download or clone the `qmk_firmware` repo and navigate to its top level directory. Once your build environment is setup, you'll be able to generate the default .hex using:
Depending on your Layout chose one of the follwing commands:
```
$ make handwired/dactyl_manuform/YOUR_LAYOUT:YOUR_KEYMAP_NAME
```
example:
```
$ make handwired/dactyl_manuform/4x5:default
```
If everything worked correctly you will see a file:
```
dactyl_manuform_YOUR_LAYOUT_YOUR_KEYMAP_NAME.hex
```
For more information on customizing keymaps, take a look at the primary documentation for [Customizing Your Keymap](/docs/faq_keymap.md) in the main readme.md.
## Keymaps
### [Keymaps 4x5](/keyboards/handwired/dactyl_manuform/4x5/keymaps/)
#### Default
Simple QWERTY layout with 3 Layers.
#### Dvorak
### [Keymaps 5x6](/keyboards/handwired/dactyl_manuform/5x6/keymaps/)
#### Default
Just a copy of the Impstyle keymap. Feel free to adjust it.
#### Impstyle
A simple QWERTY keymap with 3 Layers. Both sides are connected via serial and the Left ist the master.
### [Keymaps 5x7 aka almost Ergodox](/keyboards/handwired/dactyl_manuform/5x7/keymaps/)
#### Default
Keymap of Loligagger from geekhack.
### [Keymaps 6x6](/keyboards/handwired/dactyl_manuform/6x6/keymaps/)
#### Default
Simple QWERTY layout with 3 Layers.
## Required Hardware
Apart from diodes and key switches for the keyboard matrix in each half, you
will need:
* 2 Arduino Pro Micros. You can find these on AliExpress for ≈3.50USD each.
* 2 TRRS sockets and 1 TRRS cable, or 2 TRS sockets and 1 TRS cable
Alternatively, you can use any sort of cable and socket that has at least 3
wires. If you want to use I2C to communicate between halves, you will need a
cable with at least 4 wires and 2x 4.7kΩ pull-up resistors
## Optional Hardware
A speaker can be hooked-up to either side to the `5` (`C6`) pin and `GND`, and turned on via `AUDIO_ENABLE`.
## Wiring
The 3 wires of the TRS/TRRS cable need to connect GND, VCC, and digital pin 3 (i.e.
PD0 on the ATmega32u4) between the two Pro Micros.
Next, wire your key matrix to any of the remaining 17 IO pins of the pro micro
and modify the `matrix.c` accordingly.
The wiring for serial:
![serial wiring](https://i.imgur.com/C3D1GAQ.png)
The wiring for i2c:
![i2c wiring](https://i.imgur.com/Hbzhc6E.png)
The pull-up resistors may be placed on either half. It is also possible
to use 4 resistors and have the pull-ups in both halves, but this is
unnecessary in simple use cases.
You can change your configuration between serial and i2c by modifying your `config.h` file.
## Notes on Software Configuration
the keymaps in here are for the 4x5 layout of the keyboard only.
## Flashing
To flash your firmware take a look at: [Flashing Instructions and Bootloader Information](https://docs.qmk.fm/#/flashing)
## Choosing which board to plug the USB cable into (choosing Master)
Because the two boards are identical, the firmware has logic to differentiate the left and right board.
It uses two strategies to figure things out: looking at the EEPROM (memory on the chip) or looking if the current board has the usb cable.
The EEPROM approach requires additional setup (flashing the eeprom) but allows you to swap the usb cable to either side.
The USB cable approach is easier to setup and if you just want the usb cable on the left board, you do not need to do anything extra.
### Setting the left hand as master
If you always plug the usb cable into the left board, nothing extra is needed as this is the default. Comment out `EE_HANDS` and comment out `I2C_MASTER_RIGHT` or `MASTER_RIGHT` if for some reason it was set.
### Setting the right hand as master
If you always plug the usb cable into the right board, add an extra flag to your `config.h`
```
#define MASTER_RIGHT
```
### Setting EE_hands to use either hands as master
If you define `EE_HANDS` in your `config.h`, you will need to set the
EEPROM for the left and right halves.
The EEPROM is used to store whether the
half is left handed or right handed. This makes it so that the same firmware
file will run on both hands instead of having to flash left and right handed
versions of the firmware to each half. To flash the EEPROM file for the left
half run:
```
make handwired/dactyl_promicro:default:dfu-split-left
make handwired/dactyl_promicro:default:dfu-split-right
```
After you have flashed the EEPROM, you then need to set `EE_HANDS` in your config.h, rebuild the hex files and reflash.
Note that you need to program both halves, but you have the option of using
different keymaps for each half. You could program the left half with a QWERTY
layout and the right half with a Colemak layout using bootmagic's default layout option.
Then if you connect the left half to a computer by USB the keyboard will use QWERTY and Colemak when the
right half is connected.
Notes on Using Pro Micro 3.3V
-----------------------------
Do update the `F_CPU` parameter in `rules.mk` to `8000000` which reflects
the frequency on the 3.3V board.
Also, if the slave board is producing weird characters in certain columns,
update the following line in `matrix.c` to the following:
```
// wait_us(30); // without this wait read unstable value.
wait_us(300); // without this wait read unstable value.
```

View File

@ -0,0 +1 @@
#include "trenctyl_manuform.h"

View File

@ -0,0 +1,7 @@
#pragma once
#if defined(KEYBOARD_handwired_trenctyl_manuform_6x6)
# include "6x6.h"
#endif
#include "quantum.h"

572
quantum/enc/aes.c Normal file
View File

@ -0,0 +1,572 @@
/*
This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode.
Block size can be chosen in aes.h - available choices are AES128, AES192, AES256.
The implementation is verified against the test vectors in:
National Institute of Standards and Technology Special Publication 800-38A 2001 ED
ECB-AES128
----------
plain-text:
6bc1bee22e409f96e93d7e117393172a
ae2d8a571e03ac9c9eb76fac45af8e51
30c81c46a35ce411e5fbc1191a0a52ef
f69f2445df4f9b17ad2b417be66c3710
key:
2b7e151628aed2a6abf7158809cf4f3c
resulting cipher
3ad77bb40d7a3660a89ecaf32466ef97
f5d3d58503b9699de785895a96fdbaaf
43b1cd7f598ece23881b00e3ed030688
7b0c785e27e8ad3f8223207104725dd4
NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
You should pad the end of the string with zeros if this is not the case.
For AES192/256 the key size is proportionally larger.
*/
/*****************************************************************************/
/* Includes: */
/*****************************************************************************/
#include <string.h> // CBC mode, for memset
#include "aes.h"
/*****************************************************************************/
/* Defines: */
/*****************************************************************************/
// The number of columns comprising a state in AES. This is a constant in AES. Value=4
#define Nb 4
#if defined(AES256) && (AES256 == 1)
#define Nk 8
#define Nr 14
#elif defined(AES192) && (AES192 == 1)
#define Nk 6
#define Nr 12
#else
#define Nk 4 // The number of 32 bit words in a key.
#define Nr 10 // The number of rounds in AES Cipher.
#endif
// jcallan@github points out that declaring Multiply as a function
// reduces code size considerably with the Keil ARM compiler.
// See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3
#ifndef MULTIPLY_AS_A_FUNCTION
#define MULTIPLY_AS_A_FUNCTION 0
#endif
/*****************************************************************************/
/* Private variables: */
/*****************************************************************************/
// state - array holding the intermediate results during decryption.
typedef uint8_t state_t[4][4];
// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
// The numbers below can be computed dynamically trading ROM for RAM -
// This can be useful in (embedded) bootloader applications, where ROM is often limited.
static const uint8_t sbox[256] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
static const uint8_t rsbox[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
#endif
// The round constant word array, Rcon[i], contains the values given by
// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
static const uint8_t Rcon[11] = {
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
/*
* Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12),
* that you can remove most of the elements in the Rcon array, because they are unused.
*
* From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
*
* "Only the first some of these constants are actually used up to rcon[10] for AES-128 (as 11 round keys are needed),
* up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm."
*/
/*****************************************************************************/
/* Private functions: */
/*****************************************************************************/
/*
static uint8_t getSBoxValue(uint8_t num)
{
return sbox[num];
}
*/
#define getSBoxValue(num) (sbox[(num)])
// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key)
{
unsigned i, j, k;
uint8_t tempa[4]; // Used for the column/row operations
// The first round key is the key itself.
for (i = 0; i < Nk; ++i)
{
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
}
// All other round keys are found from the previous round keys.
for (i = Nk; i < Nb * (Nr + 1); ++i)
{
{
k = (i - 1) * 4;
tempa[0]=RoundKey[k + 0];
tempa[1]=RoundKey[k + 1];
tempa[2]=RoundKey[k + 2];
tempa[3]=RoundKey[k + 3];
}
if (i % Nk == 0)
{
// This function shifts the 4 bytes in a word to the left once.
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
// Function RotWord()
{
const uint8_t u8tmp = tempa[0];
tempa[0] = tempa[1];
tempa[1] = tempa[2];
tempa[2] = tempa[3];
tempa[3] = u8tmp;
}
// SubWord() is a function that takes a four-byte input word and
// applies the S-box to each of the four bytes to produce an output word.
// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}
tempa[0] = tempa[0] ^ Rcon[i/Nk];
}
#if defined(AES256) && (AES256 == 1)
if (i % Nk == 4)
{
// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}
}
#endif
j = i * 4; k=(i - Nk) * 4;
RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
}
}
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key)
{
KeyExpansion(ctx->RoundKey, key);
}
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv)
{
KeyExpansion(ctx->RoundKey, key);
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
}
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv)
{
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
}
#endif
// This function adds the round key to state.
// The round key is added to the state by an XOR function.
static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey)
{
uint8_t i,j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];
}
}
}
// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void SubBytes(state_t* state)
{
uint8_t i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxValue((*state)[j][i]);
}
}
}
// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
static void ShiftRows(state_t* state)
{
uint8_t temp;
// Rotate first row 1 columns to left
temp = (*state)[0][1];
(*state)[0][1] = (*state)[1][1];
(*state)[1][1] = (*state)[2][1];
(*state)[2][1] = (*state)[3][1];
(*state)[3][1] = temp;
// Rotate second row 2 columns to left
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to left
temp = (*state)[0][3];
(*state)[0][3] = (*state)[3][3];
(*state)[3][3] = (*state)[2][3];
(*state)[2][3] = (*state)[1][3];
(*state)[1][3] = temp;
}
static uint8_t xtime(uint8_t x)
{
return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
}
// MixColumns function mixes the columns of the state matrix
static void MixColumns(state_t* state)
{
uint8_t i;
uint8_t Tmp, Tm, t;
for (i = 0; i < 4; ++i)
{
t = (*state)[i][0];
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ;
Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ;
Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ;
Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ;
}
}
// Multiply is used to multiply numbers in the field GF(2^8)
// Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary
// The compiler seems to be able to vectorize the operation better this way.
// See https://github.com/kokke/tiny-AES-c/pull/34
#if MULTIPLY_AS_A_FUNCTION
static uint8_t Multiply(uint8_t x, uint8_t y)
{
return (((y & 1) * x) ^
((y>>1 & 1) * xtime(x)) ^
((y>>2 & 1) * xtime(xtime(x))) ^
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */
}
#else
#define Multiply(x, y) \
( ((y & 1) * x) ^ \
((y>>1 & 1) * xtime(x)) ^ \
((y>>2 & 1) * xtime(xtime(x))) ^ \
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
#endif
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
/*
static uint8_t getSBoxInvert(uint8_t num)
{
return rsbox[num];
}
*/
#define getSBoxInvert(num) (rsbox[(num)])
// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
static void InvMixColumns(state_t* state)
{
int i;
uint8_t a, b, c, d;
for (i = 0; i < 4; ++i)
{
a = (*state)[i][0];
b = (*state)[i][1];
c = (*state)[i][2];
d = (*state)[i][3];
(*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
(*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
(*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
(*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
}
}
// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void InvSubBytes(state_t* state)
{
uint8_t i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxInvert((*state)[j][i]);
}
}
}
static void InvShiftRows(state_t* state)
{
uint8_t temp;
// Rotate first row 1 columns to right
temp = (*state)[3][1];
(*state)[3][1] = (*state)[2][1];
(*state)[2][1] = (*state)[1][1];
(*state)[1][1] = (*state)[0][1];
(*state)[0][1] = temp;
// Rotate second row 2 columns to right
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to right
temp = (*state)[0][3];
(*state)[0][3] = (*state)[1][3];
(*state)[1][3] = (*state)[2][3];
(*state)[2][3] = (*state)[3][3];
(*state)[3][3] = temp;
}
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
// Cipher is the main function that encrypts the PlainText.
static void Cipher(state_t* state, const uint8_t* RoundKey)
{
uint8_t round = 0;
// Add the First round key to the state before starting the rounds.
AddRoundKey(0, state, RoundKey);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr rounds are executed in the loop below.
// Last one without MixColumns()
for (round = 1; ; ++round)
{
SubBytes(state);
ShiftRows(state);
if (round == Nr) {
break;
}
MixColumns(state);
AddRoundKey(round, state, RoundKey);
}
// Add round key to last round
AddRoundKey(Nr, state, RoundKey);
}
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
static void InvCipher(state_t* state, const uint8_t* RoundKey)
{
uint8_t round = 0;
// Add the First round key to the state before starting the rounds.
AddRoundKey(Nr, state, RoundKey);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr rounds are executed in the loop below.
// Last one without InvMixColumn()
for (round = (Nr - 1); ; --round)
{
InvShiftRows(state);
InvSubBytes(state);
AddRoundKey(round, state, RoundKey);
if (round == 0) {
break;
}
InvMixColumns(state);
}
}
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
/*****************************************************************************/
/* Public functions: */
/*****************************************************************************/
#if defined(ECB) && (ECB == 1)
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf)
{
// The next function call encrypts the PlainText with the Key using AES algorithm.
Cipher((state_t*)buf, ctx->RoundKey);
}
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf)
{
// The next function call decrypts the PlainText with the Key using AES algorithm.
InvCipher((state_t*)buf, ctx->RoundKey);
}
#endif // #if defined(ECB) && (ECB == 1)
#if defined(CBC) && (CBC == 1)
static void XorWithIv(uint8_t* buf, const uint8_t* Iv)
{
uint8_t i;
for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size
{
buf[i] ^= Iv[i];
}
}
void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, size_t length)
{
size_t i;
uint8_t *Iv = ctx->Iv;
for (i = 0; i < length; i += AES_BLOCKLEN)
{
XorWithIv(buf, Iv);
Cipher((state_t*)buf, ctx->RoundKey);
Iv = buf;
buf += AES_BLOCKLEN;
}
/* store Iv in ctx for next call */
memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
}
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length)
{
size_t i;
uint8_t storeNextIv[AES_BLOCKLEN];
for (i = 0; i < length; i += AES_BLOCKLEN)
{
memcpy(storeNextIv, buf, AES_BLOCKLEN);
InvCipher((state_t*)buf, ctx->RoundKey);
XorWithIv(buf, ctx->Iv);
memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);
buf += AES_BLOCKLEN;
}
}
#endif // #if defined(CBC) && (CBC == 1)
#if defined(CTR) && (CTR == 1)
/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length)
{
uint8_t buffer[AES_BLOCKLEN];
size_t i;
int bi;
for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
{
if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */
{
memcpy(buffer, ctx->Iv, AES_BLOCKLEN);
Cipher((state_t*)buffer,ctx->RoundKey);
/* Increment Iv and handle overflow */
for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
{
/* inc will overflow */
if (ctx->Iv[bi] == 255)
{
ctx->Iv[bi] = 0;
continue;
}
ctx->Iv[bi] += 1;
break;
}
bi = 0;
}
buf[i] = (buf[i] ^ buffer[bi]);
}
}
#endif // #if defined(CTR) && (CTR == 1)

91
quantum/enc/aes.h Normal file
View File

@ -0,0 +1,91 @@
#ifndef _AES_H_
#define _AES_H_
#include <stdint.h>
#include <stddef.h>
// #define the macros below to 1/0 to enable/disable the mode of operation.
//
// CBC enables AES encryption in CBC-mode of operation.
// CTR enables encryption in counter-mode.
// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously.
// The #ifndef-guard allows it to be configured before #include'ing or at compile time.
#ifndef CBC
#define CBC 1
#endif
#ifndef ECB
#define ECB 1
#endif
#ifndef CTR
#define CTR 1
#endif
//#define AES128 1
//#define AES192 1
#define AES256 1
#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only
#if defined(AES256) && (AES256 == 1)
#define AES_KEYLEN 32
#define AES_keyExpSize 240
#elif defined(AES192) && (AES192 == 1)
#define AES_KEYLEN 24
#define AES_keyExpSize 208
#else
#define AES_KEYLEN 16 // Key length in bytes
#define AES_keyExpSize 176
#endif
struct AES_ctx
{
uint8_t RoundKey[AES_keyExpSize];
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
uint8_t Iv[AES_BLOCKLEN];
#endif
};
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
#endif
#if defined(ECB) && (ECB == 1)
// buffer size is exactly AES_BLOCKLEN bytes;
// you need only AES_init_ctx as IV is not used in ECB
// NB: ECB is considered insecure for most uses
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf);
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf);
#endif // #if defined(ECB) && (ECB == !)
#if defined(CBC) && (CBC == 1)
// buffer size MUST be mutile of AES_BLOCKLEN;
// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
#endif // #if defined(CBC) && (CBC == 1)
#if defined(CTR) && (CTR == 1)
// Same function for encrypting as for decrypting.
// IV is incremented for every block, and used after encryption as XOR-compliment for output
// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
#endif // #if defined(CTR) && (CTR == 1)
#endif // _AES_H_

1525
quantum/enc/enc.c Normal file

File diff suppressed because it is too large Load Diff

174
quantum/enc/enc.h Normal file
View File

@ -0,0 +1,174 @@
#pragma once
#include "quantum.h"
#include <stdint.h>
#define CBC 1
#define ENC_ERR_OK 0x00
#define ENC_ERR_EMPTY_BUF 0x01
#define ENC_ERR_NO_CTX 0x02
#define ENC_ERR_NOT_ALLOWED 0x03
#define ENC_ERR_INVALID 0x04
#define ENC_ERR_RETRY 0x05
#define ENC_ERR_HW_SUPPORT 0x06
#define ENC_ERR_MORE_DATA 0x07
#define ENC_CMD_RESET 0x00
#define ENC_CMD_ENCRYPT 0x01
#define ENC_CMD_DECRYPT 0x02
#define ENC_CMD_MORE_DATA 0x03
#define ENC_CMD_UNLOCK 0x04
#define ENC_CMD_LOCK 0x05
#define ENC_CMD_SET_CFG 0x06
#define ENC_CMD_GET_MODE 0x07
#define ENC_CMD_GET_BUFFER 0x08
#define ENC_CMD_GET_KEYS 0x09
#define ENC_CMD_GET_BUFSIZE 0x0A
#define ENC_CMD_SET_KEYS 0x0B
#define ENC_CMD_GET_CFG 0x0C
#define ENC_CMD_INITIALIZE 0x0D
#define ENC_CMD_NONE 0x0E
#define ENC_CMD_SET_BUFFER 0x0F
#define ENC_MODE_CLOSED 0x00
#define ENC_MODE_OPEN 0x01
#define ENC_MODE_LOAD 0x02
#define ENC_MODE_INIT 0x03
#define ENC_MODE_KEY 0x04
#define ENC_SUB_MODE_NONE 0x00
#define ENC_SUB_MODE_SEED 0x01
#define ENC_SUB_MODE_PASSWORD 0x02
#define ENC_SUB_MODE_VERIFY_PASSWORD 0x03
#define ENC_SUB_MODE_REQUEST 0x04
#define ENC_SUB_MODE_REQUEST_ALLOW 0x05
#define ENC_SUB_MODE_REQUEST_DENY 0x06
#define ENC_SUB_MODE_KEY 0x07
#define ENC_CFG_PARANOIA 0x00
#define ENC_CFG_SECURE 0x01
#define ENC_CFG_MAX_ERROR 0x02
#define ENC_CFG_TIMEOUT 0x03
#define ENC_FALSE 0x00
#define ENC_TRUE 0x01
#define ENC_EEPROM_SIZE 123
#ifdef VIA_ENABLE
# include "via.h"
# define ENC_EEPROM_ADDR (VIA_EEPROM_CUSTOM_CONFIG_ADDR - ENC_EEPROM_SIZE)
#else
# include "eeconfig.h"
# define ENC_EEPROM_ADDR (EECONFIG_SIZE)
#endif
typedef struct __attribute__((packed)) {
unsigned int max_error:4;
unsigned int error_count:4;
unsigned int paranoia_mode:1;
unsigned int secure_mode:1;
unsigned int timeout:6;
unsigned int initialized:1;
unsigned int reserved:7;
} enc_config_flags_t;
typedef struct __attribute__((packed)) {
enc_config_flags_t flags;
uint8_t identifier[8];
uint8_t salt[16];
uint8_t validate[32];
uint8_t key_store[64];
} enc_config_t;
typedef struct __attribute__((packed)) {
uint32_t seed;
uint8_t key[32];
} enc_keys_t;
typedef struct {
uint8_t mode;
uint8_t sub_mode;
uint32_t pw_timeout;
bool pw_timeout_enabled;
uint8_t req_cmd;
uint32_t req_timeout;
bool req_timeout_enabled;
// key just temporary
uint8_t key[64];
uint16_t key_size;
} enc_mode_t;
typedef struct {
uint16_t pw[32];
uint16_t pw_check[32];
uint16_t pw_size;
uint16_t pw_check_size;
bool pw_ready;
bool pw_check_ready;
uint8_t key[64];
uint16_t key_size;
bool key_ready;
uint32_t seed;
bool seed_ready;
uint32_t pw_timer;
uint32_t req_timer;
bool cfg_ready;
} enc_state_t;
typedef struct {
enc_mode_t mode;
enc_config_t cnf;
enc_keys_t keys;
enc_state_t state;
} ENC_CTX;
#define ENC_REQUEST_HEADER_LEN 9
#define ENC_RESPONSE_HEADER_POS_SIZE 1
#define ENC_RESPONSE_HEADER_LEN 3
typedef struct __attribute__((packed)) {
uint8_t magic[2];
uint8_t cmd;
uint16_t size;
uint32_t id;
} enc_request_header_t;
typedef struct {
uint8_t *data;
uint16_t dsize;
uint16_t dpos;
} enc_data_buffer_t;
typedef struct {
enc_request_header_t req_header;
enc_data_buffer_t data;
uint8_t req_cmd;
uint32_t req_id;
uint8_t state_cmd;
uint8_t state_cmd_old;
uint8_t *res_data;
uint32_t req_timer;
} enc_request_state_t;
#define ENC_HID_REQUEST_TIMEOUT 30
// Called by QMK core to process ENC-specific keycodes.
bool process_record_enc(uint16_t keycode, keyrecord_t *record);
// called to allow having config ready instantly
void pre_init_enc(void);
void eeconfig_init_enc(void);
enc_config_flags_t enc_get_config_flags(void);
void enc_set_config_flags(enc_config_flags_t);
enc_mode_t enc_get_mode(void);
void enc_set_mode(enc_mode_t);
const char* enc_mode_to_str(uint8_t mode);
const char* enc_sub_mode_to_str(uint8_t mode);
const char* enc_cmd_to_str(uint8_t cmd);
void enc_write_oled(bool invert);

View File

@ -0,0 +1,14 @@
#pragma once
#ifdef ENC_OPTLOCK
# undef ENC_OPTLOCK
#endif
#if defined(STM32F401xx) || defined(STMF411xx)
# define ENC_OPTLOCK
#endif
#ifdef ENC_OPTLOCK
void enc_flash_lock(void);
int enc_is_flash_locked(void);
#endif

View File

@ -0,0 +1,3 @@
ifneq ($(filter %_STM32F401xC %_STM32F401xE %_STM32F405xG %_STM32F411xE, %_STM32F412xB, $(MCU_SERIES)_$(MCU_LDSCRIPT)),)
SRC += enc_stm32f40xx_stm32f41xx.c
endif

View File

@ -0,0 +1,51 @@
#include "hal.h"
#include "enc.h"
#define FLASH_OPTKEY1 0x08192A3B
#define FLASH_OPTKEY2 0x4C5D6E7F
static inline void OPT_WaitNotBusy(void) {
uint32_t sr = 0;
for (sr = FLASH->SR; sr & FLASH_SR_BSY; sr = FLASH->SR) {
__WFI();
}
}
static inline void OPT_Unlock(void) {
OPT_WaitNotBusy();
if (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) {
FLASH->OPTKEYR = FLASH_OPTKEY1;
FLASH->OPTKEYR = FLASH_OPTKEY2;
}
}
static inline void OPT_Lock(void) {
OPT_WaitNotBusy();
FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
}
static inline void OPT_Set(uint32_t OptionBytes) {
__IO uint32_t *optionBytes = &(FLASH->OPTCR);
if (*optionBytes != OptionBytes) {
OPT_Unlock();
*optionBytes = OptionBytes;
FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;
OPT_Lock();
/*NVIC_SystemReset();*/
}
}
bool enc_is_flash_locked(void) {
if (FLASH->OPTCR & FLASH_OPTCR_RDP) {
return ENC_TRUE;
}
return ENC_FALSE;
}
void enc_flash_lock(void) {
OPT_Unlock();
FLASH->OPTCR |= FLASH_OPTCR_RDP;
FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;
OPT_Lock();
/*NVIC_SystemReset();*/
}

855
quantum/enc/pbkdf2-sha256.h Normal file
View File

@ -0,0 +1,855 @@
/*
* FIPS-180-2 compliant SHA-256 implementation
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
unsigned long total[2]; /*!< number of bytes processed */
unsigned long state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
int is224; /*!< 0 => SHA-256, else SHA-224 */
} sha2_context;
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
| ( (unsigned long) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* SHA-256 context setup
*/
void sha2_starts( sha2_context *ctx, int is224 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is224 == 0 )
{
/* SHA-256 */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
else
{
/* SHA-224 */
ctx->state[0] = 0xC1059ED8;
ctx->state[1] = 0x367CD507;
ctx->state[2] = 0x3070DD17;
ctx->state[3] = 0xF70E5939;
ctx->state[4] = 0xFFC00B31;
ctx->state[5] = 0x68581511;
ctx->state[6] = 0x64F98FA7;
ctx->state[7] = 0xBEFA4FA4;
}
ctx->is224 = is224;
}
static void sha2_process( sha2_context *ctx, const unsigned char data[64] )
{
unsigned long temp1, temp2, W[64];
unsigned long A, B, C, D, E, F, G, H;
GET_ULONG_BE( W[ 0], data, 0 );
GET_ULONG_BE( W[ 1], data, 4 );
GET_ULONG_BE( W[ 2], data, 8 );
GET_ULONG_BE( W[ 3], data, 12 );
GET_ULONG_BE( W[ 4], data, 16 );
GET_ULONG_BE( W[ 5], data, 20 );
GET_ULONG_BE( W[ 6], data, 24 );
GET_ULONG_BE( W[ 7], data, 28 );
GET_ULONG_BE( W[ 8], data, 32 );
GET_ULONG_BE( W[ 9], data, 36 );
GET_ULONG_BE( W[10], data, 40 );
GET_ULONG_BE( W[11], data, 44 );
GET_ULONG_BE( W[12], data, 48 );
GET_ULONG_BE( W[13], data, 52 );
GET_ULONG_BE( W[14], data, 56 );
GET_ULONG_BE( W[15], data, 60 );
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define XF0(x,y,z) ((x & y) | (z & (x | y)))
#define XF1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + XF1(e,f,g) + K + x; \
temp2 = S2(a) + XF0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
/*
* SHA-256 process buffer
*/
void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
unsigned long left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (unsigned long) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (unsigned long) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sha2_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sha2_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char sha2_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-256 final digest
*/
void sha2_finish( sha2_context *ctx, unsigned char output[32] )
{
unsigned long last, padn;
unsigned long high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_ULONG_BE( high, msglen, 0 );
PUT_ULONG_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha2_update( ctx, (unsigned char *) sha2_padding, padn );
sha2_update( ctx, msglen, 8 );
PUT_ULONG_BE( ctx->state[0], output, 0 );
PUT_ULONG_BE( ctx->state[1], output, 4 );
PUT_ULONG_BE( ctx->state[2], output, 8 );
PUT_ULONG_BE( ctx->state[3], output, 12 );
PUT_ULONG_BE( ctx->state[4], output, 16 );
PUT_ULONG_BE( ctx->state[5], output, 20 );
PUT_ULONG_BE( ctx->state[6], output, 24 );
if( ctx->is224 == 0 )
PUT_ULONG_BE( ctx->state[7], output, 28 );
}
/*
* output = SHA-256( input buffer )
*/
void sha2( const unsigned char *input, size_t ilen,
unsigned char output[32], int is224 )
{
sha2_context ctx;
sha2_starts( &ctx, is224 );
sha2_update( &ctx, input, ilen );
sha2_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha2_context ) );
}
/*
* SHA-256 HMAC context setup
*/
void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
int is224 )
{
size_t i;
unsigned char sum[32];
if( keylen > 64 )
{
sha2( key, keylen, sum, is224 );
keylen = ( is224 ) ? 28 : 32;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha2_starts( ctx, is224 );
sha2_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-256 HMAC process buffer
*/
void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
{
sha2_update( ctx, input, ilen );
}
/*
* SHA-256 HMAC final digest
*/
void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )
{
int is224, hlen;
unsigned char tmpbuf[32];
is224 = ctx->is224;
hlen = ( is224 == 0 ) ? 32 : 28;
sha2_finish( ctx, tmpbuf );
sha2_starts( ctx, is224 );
sha2_update( ctx, ctx->opad, 64 );
sha2_update( ctx, tmpbuf, hlen );
sha2_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* SHA-256 HMAC context reset
*/
void sha2_hmac_reset( sha2_context *ctx )
{
sha2_starts( ctx, ctx->is224 );
sha2_update( ctx, ctx->ipad, 64 );
}
/*
* output = HMAC-SHA-256( hmac key, input buffer )
*/
void sha2_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[32], int is224 )
{
sha2_context ctx;
sha2_hmac_starts( &ctx, key, keylen, is224 );
sha2_hmac_update( &ctx, input, ilen );
sha2_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha2_context ) );
}
#ifndef min
#define min( a, b ) ( ((a) < (b)) ? (a) : (b) )
#endif
void PKCS5_PBKDF2_HMAC(unsigned char *password, size_t plen,
unsigned char *salt, size_t slen,
const unsigned long iteration_count, const unsigned long key_length,
unsigned char *output)
{
sha2_context ctx;
sha2_starts(&ctx, 0);
// Size of the generated digest
unsigned char md_size = 32;
unsigned char md1[32];
unsigned char work[32];
unsigned long counter = 1;
unsigned long generated_key_length = 0;
while (generated_key_length < key_length) {
// U1 ends up in md1 and work
unsigned char c[4];
c[0] = (counter >> 24) & 0xff;
c[1] = (counter >> 16) & 0xff;
c[2] = (counter >> 8) & 0xff;
c[3] = (counter >> 0) & 0xff;
sha2_hmac_starts(&ctx, password, plen, 0);
sha2_hmac_update(&ctx, salt, slen);
sha2_hmac_update(&ctx, c, 4);
sha2_hmac_finish(&ctx, md1);
memcpy(work, md1, md_size);
unsigned long ic = 1;
for (ic = 1; ic < iteration_count; ic++) {
// U2 ends up in md1
sha2_hmac_starts(&ctx, password, plen, 0);
sha2_hmac_update(&ctx, md1, md_size);
sha2_hmac_finish(&ctx, md1);
// U1 xor U2
unsigned long i = 0;
for (i = 0; i < md_size; i++) {
work[i] ^= md1[i];
}
// and so on until iteration_count
}
// Copy the generated bytes to the key
unsigned long bytes_to_write =
min((key_length - generated_key_length), md_size);
memcpy(output + generated_key_length, work, bytes_to_write);
generated_key_length += bytes_to_write;
++counter;
}
}
#ifdef TEST
/*
* FIPS-180-2 test vectors
*/
static unsigned char sha2_test_buf[3][57] =
{
{ "abc" },
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
{ "" }
};
static const int sha2_test_buflen[3] =
{
3, 56, 1000
};
static const unsigned char sha2_test_sum[6][32] =
{
/*
* SHA-224 test vectors
*/
{ 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
0xE3, 0x6C, 0x9D, 0xA7 },
{ 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
0x52, 0x52, 0x25, 0x25 },
{ 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
0x4E, 0xE7, 0xAD, 0x67 },
/*
* SHA-256 test vectors
*/
{ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
{ 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
};
/*
* RFC 4231 test vectors
*/
static unsigned char sha2_hmac_test_key[7][26] = {
{"\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
"\x0B\x0B\x0B\x0B"},
{"Jefe"},
{"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
"\xAA\xAA\xAA\xAA"},
{"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19"},
{"\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
"\x0C\x0C\x0C\x0C"},
{""}, /* 0xAA 131 times */
{""}
};
static const int sha2_hmac_test_keylen[7] = {
20, 4, 20, 25, 20, 131, 131
};
static unsigned char sha2_hmac_test_buf[7][153] =
{
{ "Hi There" },
{ "what do ya want for nothing?" },
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
{ "Test With Truncation" },
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
{ "This is a test using a larger than block-size key "
"and a larger than block-size data. The key needs to "
"be hashed before being used by the HMAC algorithm." }
};
static const int sha2_hmac_test_buflen[7] =
{
8, 28, 50, 50, 20, 54, 152
};
static const unsigned char sha2_hmac_test_sum[14][32] =
{
/*
* HMAC-SHA-224 test vectors
*/
{ 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
0x53, 0x68, 0x4B, 0x22 },
{ 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
0x8F, 0xD0, 0x5E, 0x44 },
{ 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
0xEC, 0x83, 0x33, 0xEA },
{ 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
0xE7, 0xAF, 0xEC, 0x5A },
{ 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
{ 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
0x3F, 0xA6, 0x87, 0x0E },
{ 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
0xF6, 0xF5, 0x65, 0xD1 },
/*
* HMAC-SHA-256 test vectors
*/
{ 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
{ 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
{ 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
{ 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
{ 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
{ 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
{ 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
};
typedef struct {
char *t;
char *p;
int plen;
char *s;
int slen;
int c;
int dkLen;
char dk[1024]; // Remember to set this to max dkLen
} testvector;
int do_test(testvector * tv)
{
printf("Started %s\n", tv->t);
fflush(stdout);
char *key = malloc(tv->dkLen);
if (key == 0) {
return -1;
}
PKCS5_PBKDF2_HMAC((unsigned char*)tv->p, tv->plen,
(unsigned char*)tv->s, tv->slen, tv->c,
tv->dkLen, (unsigned char*)key);
if (memcmp(tv->dk, key, tv->dkLen) != 0) {
// Failed
return -1;
}
return 0;
}
/*
* Checkup routine
*/
int main()
{
int verbose = 1;
int i, j, k, buflen;
unsigned char buf[1024];
unsigned char sha2sum[32];
sha2_context ctx;
for (i = 0; i < 6; i++) {
j = i % 3;
k = i < 3;
if (verbose != 0)
printf(" SHA-%d test #%d: ", 256 - k * 32, j + 1);
sha2_starts(&ctx, k);
if (j == 2) {
memset(buf, 'a', buflen = 1000);
for (j = 0; j < 1000; j++)
sha2_update(&ctx, buf, buflen);
} else
sha2_update(&ctx, sha2_test_buf[j],
sha2_test_buflen[j]);
sha2_finish(&ctx, sha2sum);
if (memcmp(sha2sum, sha2_test_sum[i], 32 - k * 4) != 0) {
if (verbose != 0)
printf("failed\n");
return (1);
}
if (verbose != 0)
printf("passed\n");
}
if (verbose != 0)
printf("\n");
for (i = 0; i < 14; i++) {
j = i % 7;
k = i < 7;
if (verbose != 0)
printf(" HMAC-SHA-%d test #%d: ", 256 - k * 32,
j + 1);
if (j == 5 || j == 6) {
memset(buf, '\xAA', buflen = 131);
sha2_hmac_starts(&ctx, buf, buflen, k);
} else
sha2_hmac_starts(&ctx, sha2_hmac_test_key[j],
sha2_hmac_test_keylen[j], k);
sha2_hmac_update(&ctx, sha2_hmac_test_buf[j],
sha2_hmac_test_buflen[j]);
sha2_hmac_finish(&ctx, sha2sum);
buflen = (j == 4) ? 16 : 32 - k * 4;
if (memcmp(sha2sum, sha2_hmac_test_sum[i], buflen) != 0) {
if (verbose != 0)
printf("failed\n");
return (1);
}
if (verbose != 0)
printf("passed\n");
}
if (verbose != 0)
printf("\n");
testvector *tv = 0;
int res = 0;
testvector t1 = {
"Test 1",
"password", 8, "salt", 4, 1, 32,
.dk = { 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c,
0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37,
0xa8, 0x65, 0x48, 0xc9, 0x2c, 0xcc, 0x35, 0x48,
0x08, 0x05, 0x98, 0x7c, 0xb7, 0x0b, 0xe1, 0x7b }
};
tv = &t1;
res = do_test(tv);
if (res != 0) {
printf("%s failed\n", tv->t);
return res;
}
testvector t2 = {
"Test 2",
"password", 8, "salt", 4, 2, 32, {
0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf,
0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43 }
};
tv = &t2;
res = do_test(tv);
if (res != 0) {
printf("%s failed\n", tv->t);
return res;
}
testvector t3 = {
"Test 3",
"password", 8, "salt", 4, 4096, 32, {
0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41,
0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d,
0x96, 0x28, 0x93, 0xa0, 0x01, 0xce, 0x4e, 0x11,
0xa4, 0x96, 0x38, 0x73, 0xaa, 0x98, 0x13, 0x4a }
};
tv = &t3;
res = do_test(tv);
if (res != 0) {
printf("%s failed\n", tv->t);
return res;
}
testvector t4 = {
"Test 4",
"password", 8, "salt", 4, 16777216, 32, {
0xcf, 0x81, 0xc6, 0x6f, 0xe8, 0xcf, 0xc0, 0x4d,
0x1f, 0x31, 0xec, 0xb6, 0x5d, 0xab, 0x40, 0x89,
0xf7, 0xf1, 0x79, 0xe8, 0x9b, 0x3b, 0x0b, 0xcb,
0x17, 0xad, 0x10, 0xe3, 0xac, 0x6e, 0xba, 0x46 }
};
tv = &t4;
// res = do_test(tv);
if (res != 0) {
printf("%s failed\n", tv->t);
return res;
}
testvector t5 = {
"Test 5",
"passwordPASSWORDpassword", 24,
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096, 40, {
0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f,
0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf,
0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18,
0x1c, 0x4e, 0x2a, 0x1f, 0xb8, 0xdd, 0x53, 0xe1,
0xc6, 0x35, 0x51, 0x8c, 0x7d, 0xac, 0x47, 0xe9 }
};
tv = &t5;
res = do_test(tv);
if (res != 0) {
printf("%s failed\n", tv->t);
return res;
}
testvector t6 = {
"Test 6",
"pass\0word", 9, "sa\0lt", 5, 4096, 16, {
0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89,
0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87 }
};
tv = &t6;
res = do_test(tv);
if (res != 0) {
printf("%s failed\n", tv->t);
return res;
}
return (0);
}
#endif

View File

@ -0,0 +1,56 @@
#include "pkcs7_padding.h"
int pkcs7_padding_pad_buffer( uint8_t *buffer, size_t data_length, size_t buffer_size, uint8_t modulus ){
uint8_t pad_byte = modulus - ( data_length % modulus ) ;
if( data_length + pad_byte > buffer_size ){
return -pad_byte;
}
int i = 0;
while( i < pad_byte){
buffer[data_length+i] = pad_byte;
i++;
}
return pad_byte;
}
int pkcs7_padding_valid( uint8_t *buffer, size_t data_length, size_t buffer_size, uint8_t modulus ){
uint8_t expected_pad_byte = modulus - ( data_length % modulus ) ;
if( data_length + expected_pad_byte > buffer_size ){
return 0;
}
int i = 0;
while( i < expected_pad_byte ){
if( buffer[data_length + i] != expected_pad_byte){
return 0;
}
i++;
}
return 1;
}
size_t pkcs7_padding_data_length( uint8_t * buffer, size_t buffer_size, uint8_t modulus ){
/* test for valid buffer size */
if( buffer_size % modulus != 0 ||
buffer_size < modulus ){
return 0;
}
uint8_t padding_value;
padding_value = buffer[buffer_size-1];
/* test for valid padding value */
if( padding_value < 1 || padding_value > modulus ){
return 0;
}
/* buffer must be at least padding_value + 1 in size */
if( buffer_size < padding_value + 1 ){
return 0;
}
uint8_t count = 1;
buffer_size --;
for( ; count < padding_value ; count++){
buffer_size --;
if( buffer[buffer_size] != padding_value ){
return 0;
}
}
return buffer_size;
}

View File

@ -0,0 +1,24 @@
#ifndef _PKCS7_PADDING_H_
#define _PKCS7_PADDING_H_
#include <stdint.h>
#include <stddef.h>
/* Pad a buffer with bytes as defined in PKCS#7
* Returns the number of pad bytes added, or zero if
* the buffer size is not large enough to hold the correctly padded data
*/
int pkcs7_padding_pad_buffer( uint8_t *buffer, size_t data_length, size_t buffer_size, uint8_t modulus );
int pkcs7_padding_valid( uint8_t *buffer, size_t data_length, size_t buffer_size, uint8_t modulus );
/* Given a block of pkcs7 padded data, return the actual data length in the block based on the padding applied.
* buffer_size must be a multiple of modulus
* last byte 'x' in buffer must be between 1 and modulus
* buffer_size must be at least x + 1 in size
* last 'x' bytes in buffer must be same as 'x'
* returned size will be buffer_size - 'x'
*/
size_t pkcs7_padding_data_length( uint8_t * buffer, size_t buffer_size, uint8_t modulus );
#endif

View File

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

View File

@ -217,6 +217,10 @@ extern layer_state_t layer_state;
# include "via.h"
#endif
#ifdef ENC_ENABLE
# include "enc.h"
#endif
#ifdef WPM_ENABLE
# include "wpm.h"
#endif

View File

@ -605,6 +605,18 @@ enum quantum_keycodes {
CAPS_WORD,
#ifdef ENC_ENABLE
ENC_INIT,
ENC_LOAD,
ENC_CLOSE,
ENC_PASTE,
ENC_KEYSPASTE,
ENC_RESET,
ENC_REQ_ALLOW,
ENC_REQ_DENY,
ENC_KEY,
#endif
// Start of custom keycode range for keyboards and keymaps - always leave at the end
SAFE_RANGE
};

View File

@ -84,6 +84,14 @@ enum serial_transaction_id {
PUT_POINTING_CPI,
#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
#if defined(ENC_ENABLE) && defined(SPLIT_ENC_MODE_ENABLE)
PUT_ENC_MODE,
#endif // defined(ENC_ENABLE) && defined(SPLIT_ENC_MODE_ENABLE)
#if defined(ENC_ENABLE) && defined(SPLIT_ENC_FLAGS_ENABLE)
PUT_ENC_FLAGS,
#endif // defined(ENC_ENABLE) && defined(SPLIT_ENC_FLAGS_ENABLE)
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
PUT_RPC_INFO,
PUT_RPC_REQ_DATA,

View File

@ -663,6 +663,59 @@ static void pointing_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s
#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
////////////////////////////////////////////////////
// ENC
#if defined(ENC_ENABLE) && defined(SPLIT_ENC_MODE_ENABLE)
static bool enc_mode_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
static uint32_t last_update = 0;
enc_mode_t enc_mode_sync;
enc_mode_sync = enc_get_mode();
return send_if_data_mismatch(PUT_ENC_MODE, &last_update, &enc_mode_sync, &split_shmem->enc_mode_sync, sizeof(enc_mode_sync));
}
static void enc_mode_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
enc_set_mode(split_shmem->enc_mode_sync);
}
# define TRANSACTIONS_ENC_MODE_MASTER() TRANSACTION_HANDLER_MASTER(enc_mode)
# define TRANSACTIONS_ENC_MODE_SLAVE() TRANSACTION_HANDLER_SLAVE(enc_mode)
# define TRANSACTIONS_ENC_MODE_REGISTRATIONS [PUT_ENC_MODE] = trans_initiator2target_initializer(enc_mode_sync),
#else // defined(ENC_ENABLE) && defined(SPLIT_ENC_MODE_ENABLE)
# define TRANSACTIONS_ENC_MODE_MASTER()
# define TRANSACTIONS_ENC_MODE_SLAVE()
# define TRANSACTIONS_ENC_MODE_REGISTRATIONS
#endif // defined(ENC_ENABLE) && defined(SPLIT_ENC_MODE_ENABLE)
#if defined(ENC_ENABLE) && defined(SPLIT_ENC_FLAGS_ENABLE)
static bool enc_flags_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
static uint32_t last_update = 0;
enc_config_flags_t enc_flags_sync;
enc_flags_sync = enc_get_config_flags();
return send_if_data_mismatch(PUT_ENC_FLAGS, &last_update, &enc_flags_sync, &split_shmem->enc_flags_sync, sizeof(enc_flags_sync));
}
static void enc_flags_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
enc_set_config_flags(split_shmem->enc_flags_sync);
}
# define TRANSACTIONS_ENC_FLAGS_MASTER() TRANSACTION_HANDLER_MASTER(enc_flags)
# define TRANSACTIONS_ENC_FLAGS_SLAVE() TRANSACTION_HANDLER_SLAVE(enc_flags)
# define TRANSACTIONS_ENC_FLAGS_REGISTRATIONS [PUT_ENC_FLAGS] = trans_initiator2target_initializer(enc_flags_sync),
#else // defined(ENC_ENABLE) && defined(SPLIT_ENC_FLAGS_ENABLE)
# define TRANSACTIONS_ENC_FLAGS_MASTER()
# define TRANSACTIONS_ENC_FLAGS_SLAVE()
# define TRANSACTIONS_ENC_FLAGS_REGISTRATIONS
#endif // defined(ENC_ENABLE) && defined(SPLIT_ENC_FLAGS_ENABLE)
////////////////////////////////////////////////////
split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
@ -689,6 +742,8 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
TRANSACTIONS_OLED_REGISTRATIONS
TRANSACTIONS_ST7565_REGISTRATIONS
TRANSACTIONS_POINTING_REGISTRATIONS
TRANSACTIONS_ENC_MODE_REGISTRATIONS
TRANSACTIONS_ENC_FLAGS_REGISTRATIONS
// clang-format on
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
@ -715,6 +770,8 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix
TRANSACTIONS_OLED_MASTER();
TRANSACTIONS_ST7565_MASTER();
TRANSACTIONS_POINTING_MASTER();
TRANSACTIONS_ENC_MODE_MASTER();
TRANSACTIONS_ENC_FLAGS_MASTER();
return true;
}
@ -734,6 +791,8 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[
TRANSACTIONS_OLED_SLAVE();
TRANSACTIONS_ST7565_SLAVE();
TRANSACTIONS_POINTING_SLAVE();
TRANSACTIONS_ENC_MODE_SLAVE();
TRANSACTIONS_ENC_FLAGS_SLAVE();
}
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)

View File

@ -185,6 +185,14 @@ typedef struct _split_shared_memory_t {
split_slave_pointing_sync_t pointing;
#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
#if defined(ENC_ENABLE) && defined(SPLIT_ENC_MODE_ENABLE)
enc_mode_t enc_mode_sync;
#endif // defined(ENC_ENABLE) && defined(SPLIT_ENC_MODE_ENABLE)
#if defined(ENC_ENABLE) && defined(SPLIT_ENC_FLAGS_ENABLE)
enc_config_flags_t enc_flags_sync;
#endif // defined(ENC_ENABLE) && defined(SPLIT_ENC_FLAGS_ENABLE)
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
rpc_sync_info_t rpc_info;
uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];

View File

@ -45,10 +45,17 @@
# define VIA_EEPROM_LAYOUT_OPTIONS_DEFAULT 0x00000000
#endif
// If ENC_ENABLE the layout has to be adjusted
// for storing the needed crypto stuff inside the EEPROM
#ifdef ENC_ENABLE
# include "enc.h"
# define VIA_EEPROM_CUSTOM_CONFIG_ADDR (VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE + ENC_EEPROM_SIZE)
#else
// The end of the EEPROM memory used by VIA
// By default, dynamic keymaps will start at this if there is no
// custom config
#define VIA_EEPROM_CUSTOM_CONFIG_ADDR (VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE)
# define VIA_EEPROM_CUSTOM_CONFIG_ADDR (VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE)
#endif
#ifndef VIA_EEPROM_CUSTOM_CONFIG_SIZE
# define VIA_EEPROM_CUSTOM_CONFIG_SIZE 0