Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e338e2a092 | ||
|
|
1bec7c0a51 | ||
|
|
3c86e0aca4 | ||
|
|
0226bd664b | ||
|
|
c2ebaab825 | ||
|
|
be92c14ee6 | ||
|
|
14fb36819f | ||
|
|
8082991993 | ||
|
|
9ec31d0b52 | ||
|
|
c8fe3ff597 | ||
|
|
731d890cc9 | ||
|
|
c1bf11fea6 | ||
|
|
d1cb628eec | ||
|
|
350e2833f2 | ||
|
|
a12f7243c9 | ||
|
|
847923b74b | ||
|
|
4a6afc4d11 | ||
|
|
103bed5f4d | ||
|
|
b28c3c2c1d |
No files matched your search
@@ -1,13 +1,23 @@
|
||||
# RED_CRYPTO ver 0.5.0
|
||||
# RED_CRYPTO ver 0.7.3-full
|
||||
|
||||
## Description
|
||||
|
||||
Password manager for (almost) any QMK-compatible keyboards.
|
||||
It is lightweight version of `RED_CRYPTO` lib.
|
||||
Password manager for (almost) any QMK-compatible keyboards. It is full version of `RED_CRYPTO` lib.
|
||||
|
||||
There are two versions:
|
||||
- hard-coded passwords in `keymap.c`, change branch to [`hard_coded_storage`](https://github.com/redlineo/red_crypto/tree/hard_coded_storage) or releases (YOU ARE HERE)
|
||||
- storing passwords in EEPROM with adding and editing via `RED_MENU`, change branch to [`eeprom_storage`](https://github.com/redlineo/red_crypto/tree/eeprom_storage) or releases
|
||||
- hard-coded passwords in `keymap.c`, change branch to [`hard_coded_storage`](https://github.com/redlineo/red_crypto/tree/hard_coded_storage) or releases
|
||||
- storing passwords in EEPROM with adding and editing via `RED_MENU`, change branch to [`eeprom_storage`](https://github.com/redlineo/red_crypto/tree/eeprom_storage) or releases (YOU ARE HERE)
|
||||
|
||||
## Alert
|
||||
|
||||
> Now red_crypto supports STM32 EEPROM.
|
||||
>
|
||||
> Tested on Keychron K9 Pro with STM32L432xx with virtual EEPROM
|
||||
|
||||
See chapter about [Memory issue](#memory-issue) and [Memory usage](#memory-usage).
|
||||
I recommend using at the beginning internal FLASH or EEPROM, because you have some resources not to need external memory. Or you can do not change your passwords, if there are very strong one's.
|
||||
|
||||
> Red_crypto will remind you constanly about using internal memory.
|
||||
|
||||
### Supports cryptographic algorithms
|
||||
|
||||
@@ -23,7 +33,20 @@ There are two versions:
|
||||
- [x] use SHA256 for hashing key to set key length to 32 bytes
|
||||
- [x] expand stored passwords length from 16 byte to 64
|
||||
- [x] expand number of stored passwords (manual adding new keys)
|
||||
- [x] add menu to managing stored passwords
|
||||
- [x] adding new passwords via menu to EEPROM without flashing firmware
|
||||
- [x] add feature to edit passwords in EEPROM
|
||||
- [ ] add feature to backspacing while adding password
|
||||
- [ ] add feature to name passwords in EEPROM
|
||||
- [ ] add feature to update master password in EEPROM
|
||||
- [ ] add feature to count memory usage
|
||||
- [ ] add feature to see how many passwords you can store
|
||||
- [ ] add feature to interactive choosing passwords with arrows
|
||||
- [ ] add support Streebog
|
||||
- [ ] add CBC mode for Kuznechik, it will increase security
|
||||
- [ ] add addition procedures for Kuznechik (is it really need?)
|
||||
- [ ] add support AES256
|
||||
- [ ] reseach and add KDF algorithm instead of SHA256
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -47,78 +70,121 @@ include keyboards/<your keyboard>/<path to your keymap folder>/red_crypto/red_cr
|
||||
#define USE_KUZNECHIK_8
|
||||
```
|
||||
|
||||
If you want use SHA256 of your key to encrypt passwords, define this in `config.h`.
|
||||
If you want (and if you can) use SHA256 of your key to encrypt passwords, define this in `config.h`.
|
||||
|
||||
```c
|
||||
#define USE_SHA256_KEY
|
||||
```
|
||||
|
||||
Change storage size (default `4`) and maximum password length (default `64`).
|
||||
Change storage size (default `5`) and maximum password length (default `64`).
|
||||
|
||||
```c
|
||||
#define STORAGE_SIZE 4
|
||||
#define STORAGE_PASS_LEN 64 // use a multiple of 16, e.g. 16, 32, 64... but don't forget about available memory!
|
||||
#define INIT_STORAGE_SIZE 5
|
||||
#define INIT_STORAGE_PASS_LEN 64 // use a multiple of 16, e.g. 16, 32, 64... but don't forget about available memory!
|
||||
```
|
||||
|
||||
5. Encrypt your passwords with chosen algorithm (AES, Kuznechik). Now available only Kuznechik. You can use `CyberChef`.
|
||||
5. Adding passwords now in menu. Look [Usage](#usage).
|
||||
|
||||
> Don't use web version! We are here for security, right?
|
||||
6. Add new layer or set new keys everywhere you want.
|
||||
|
||||
If you've enabled SHA256 for key, choose `SHA2`, then `SHA256` mode and `64` rounds. Hash your key, then copy it to next step.
|
||||
|
||||
Choose `GOST Encrypt`, then choose type `GOST R 34.12 (Kuznechik, 2015)`, not `Magma`. Choose mode `ECB`. Now there is no other modes for `Kuznechik`.
|
||||
|
||||
> Don't forget IV for GOST
|
||||
```
|
||||
94208510C2C001FB01C0C21085209401
|
||||
```
|
||||
|
||||
6. Add your encrypted passwords in **keymap.c**. Now you can encrypt 4 passwords with any length (16, 32, 64, more not tested).
|
||||
|
||||
> Keep this information in secret. Even if there are no plaintext.
|
||||
|
||||
Chosen parameter `STORAGE_PASS_LEN` must be the same as the number of zeros in this array.
|
||||
|
||||
Chosen parameter `STORAGE_SIZE` must be the same as the number of passwords in this array.
|
||||
|
||||
```c
|
||||
const uint8_t encrypted_passwords[STORAGE_SIZE][STORAGE_PASS_LEN] = {
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
};
|
||||
```
|
||||
|
||||
If you want more passwords in storage, you should:
|
||||
- add keys `RED_PASSX` into `enum red_crypto_keys` in `red_crypto.h`
|
||||
- add into `crypto_proccess_record_user` handling new keys
|
||||
|
||||
7. Add new layer or set new keyes everywhere you want.
|
||||
|
||||
- `RED_TEST` - execute test functions of every algorithm with. Available only with `#define TEST_FUNCTIONS_ENABLED` and `COMMAND_ENABLE=yes`. You can see output via `hid_listen`.
|
||||
- `RED_CRY_M` - execute reading password for encrypted passwords. After entering password, tap this key again. Now, you can use `RED_PASSX` keys.
|
||||
- `RED_PASSX` - where `X` is number of your password in database. After tapping, keyboard send decrypted password.
|
||||
- `RED_MENU` - exec menu to change passwords, show them, etc.
|
||||
- `RED_RNG` - use 32 times function named `tap_random_base64` from QMK. It's for generating random strings. But now random seed is not unique for every keyboard's power on.
|
||||
- `RED_TEST` - execute test functions of every algorithm with. Available only with `#define TEST_FUNCTIONS_ENABLED` and `COMMAND_ENABLE=yes`. You can see output via `hid_listen`.
|
||||
|
||||
8. Copy this string to function **process_record_user** in **keymap.c** before all your code. It uses "switch case" construction inside.
|
||||
7. Add some code to **keymap.c**.
|
||||
|
||||
Copy this function above **process_record_user**. It is initializing EEPROM of STM32.
|
||||
|
||||
```c
|
||||
uint8_t crypto_return = crypto_process_record_user(keycode, event, encrypted_passwords);
|
||||
if (crypto_return == 1){
|
||||
uint16_t density=0; // for test
|
||||
void keyboard_post_init_user(void) {
|
||||
density=EEPROM_Init();
|
||||
}
|
||||
```
|
||||
|
||||
Copy this string to at the beginning of function **process_record_user** in **keymap.c**. It uses "switch case" construction inside.
|
||||
|
||||
```c
|
||||
uint8_t crypto_return = crypto_process_record_user(keycode, record);
|
||||
if (crypto_return == RED_KEY_READ){
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
9. Compile and flash your keyboard.
|
||||
8. Compile and flash your keyboard.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Tap `RED_CRY_M`. Enter password. Tap `RED_CRY_M` again to confirm.
|
||||
Now you can use `RED_PASSX` to send decrypted passwords.
|
||||
Tap `RED_CRY_M`. Enter master key. Tap `RED_CRY_M` again to confirm.
|
||||
Now you can use `RED_PASSX` to send decrypted passwords. And you can use menu via `RED_MENU`.
|
||||
|
||||
If you have missed while entering password, just tap `RED_CRY_M` and tap `RED_CRY_M`.
|
||||
> If you have missed while entering password, just tap `RED_CRY_M` and tap `RED_CRY_M`.
|
||||
|
||||
### Adding passwords
|
||||
|
||||
You must firstly enter master key to enter in **crypto mode**.
|
||||
|
||||
You should open any program with text box (notepad, telegram, html text box). Then tap `RED_MENU` and you will see menu.
|
||||
|
||||
Choose `6-Add password` with entering `6`. Enter password, tap `Enter` and `Enter`.
|
||||
|
||||
### Changing passwords
|
||||
|
||||
Open menu with `RED_MENU`, choose `4-Change password in storage` with entering `4`.
|
||||
Choose **index** in hex from 0 to F. Now you can change first 16 password.
|
||||
Enter new password, tap `Enter` and `Enter`.
|
||||
|
||||
## Memory usage
|
||||
|
||||
To represent the resources that will be spent on the password storage. It is just example calculate.
|
||||
|
||||
If you have 10 different password, set 64 byte size for encrypted password, 16 byte size for ecrypted name for each password, you will store:
|
||||
|
||||
$10*(64+16)=800b$
|
||||
|
||||
i.e. even if you have arduino with 1kb EEPROM, you can store enough passwords.
|
||||
|
||||
If you have up to 100.000 rewrite cycles, and if you will change you passwords every month, you will use up the entire resource of memory in:
|
||||
|
||||
$\frac{100.000}{10*(64+16)}=\frac{125}{12}=10.4167$
|
||||
|
||||
i.e. you can rewrite you passwords for 10 years. But in my calculations not consider the probability of forgetting passwords.
|
||||
|
||||
## Memory issue
|
||||
|
||||
You have two ways to store passwords:
|
||||
|
||||
### FLASH or internal EEPROM
|
||||
|
||||
You can use FLASH or internal EEPROM memory to store passwords near with your keymap.
|
||||
|
||||
#### Advantages:
|
||||
- You can use red_crypto without any upgrading of keyboard.
|
||||
|
||||
#### Disadvantages:
|
||||
- You have memory limit. E.g. Arduino ProMicro have 1024 byte EEPROM.
|
||||
- On STM32 MCUs in most cases you don't have true EEPROM, because it's emulated in FLASH.
|
||||
- You have limit of re-flashing your firmware. Most likely about 100.000 times, but this number may vary depending on the temperature, manufacturer, and revision. Remember this.
|
||||
- You don't have access to rewrite passwords without re-flashing firmware. May be you can, but with hard way.
|
||||
|
||||
### External EEPROM (or FRAM)
|
||||
|
||||
You can use external EEPROM (FRAM) memory with access to rewrite on-the-fly and add new passwords, etc.
|
||||
|
||||
#### Advantages:
|
||||
|
||||
- You can add new passwords, update old one's, renew master password, etc.
|
||||
- Up to 1.000.000 rewrite cycles (or up to $10^{14}$ with FRAM).
|
||||
- Faster access to data (more fast with FRAM).
|
||||
- CAT24C512 EEPROM has built-in ECC module (Error Correction Code). Don't know how it works, but sounds good.
|
||||
- You can upgrade memory with adding chips on I2C or SPI bus. Look at docs on your memory chip to know about maximum quantity.
|
||||
|
||||
#### Disadvantages:
|
||||
|
||||
- You will have to buy a chip and solder it to your MCU's pins. Your MCU must have 2 free pins for I2C support or 4 pins for SPI. Look [QMK docs](https://docs.qmk.fm/drivers/eeprom) to choose EEPROM(FRAM) chip.
|
||||
|
||||
|
||||
## Related projects
|
||||
|
||||
@@ -1097,7 +1097,7 @@ void print_rnd_key(WORD key[])
|
||||
|
||||
/*********************** TEST FUNCTION DEFINITIONS ***********************/
|
||||
#ifdef TEST_FUNCTIONS_ENABLED
|
||||
void print_hex(BYTE str[], int len)
|
||||
void red_print_hex(BYTE str[], int len)
|
||||
{
|
||||
int idx;
|
||||
|
||||
@@ -1126,21 +1126,21 @@ int aes_ecb_test(void)
|
||||
//printf("* ECB mode:\n");
|
||||
aes_key_setup(key[0], key_schedule, 256);
|
||||
//printf( "Key : ");
|
||||
//print_hex(key[0], 32);
|
||||
//red_print_hex(key[0], 32);
|
||||
|
||||
for(idx = 0; idx < 2; idx++) {
|
||||
aes_encrypt(plaintext[idx], enc_buf, key_schedule, 256);
|
||||
//printf("\nPlaintext : ");
|
||||
//print_hex(plaintext[idx], 16);
|
||||
//red_print_hex(plaintext[idx], 16);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, 16);
|
||||
//red_print_hex(enc_buf, 16);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[idx], 16);
|
||||
|
||||
aes_decrypt(ciphertext[idx], enc_buf, key_schedule, 256);
|
||||
//printf("\nCiphertext : ");
|
||||
//print_hex(ciphertext[idx], 16);
|
||||
//red_print_hex(ciphertext[idx], 16);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, 16);
|
||||
//red_print_hex(enc_buf, 16);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[idx], 16);
|
||||
|
||||
//printf("\n\n");
|
||||
@@ -1171,26 +1171,26 @@ int aes_cbc_test(void)
|
||||
aes_key_setup(key[0], key_schedule, 256);
|
||||
|
||||
//printf( "Key : ");
|
||||
//print_hex(key[0], 32);
|
||||
//red_print_hex(key[0], 32);
|
||||
//printf("\nIV : ");
|
||||
//print_hex(iv[0], 16);
|
||||
//red_print_hex(iv[0], 16);
|
||||
|
||||
aes_encrypt_cbc(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]);
|
||||
//printf("\nPlaintext : ");
|
||||
//print_hex(plaintext[0], 32);
|
||||
//red_print_hex(plaintext[0], 32);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, 32);
|
||||
//red_print_hex(enc_buf, 32);
|
||||
//printf("\nCiphertext : ");
|
||||
//print_hex(ciphertext[0], 32);
|
||||
//red_print_hex(ciphertext[0], 32);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[0], 32);
|
||||
|
||||
aes_decrypt_cbc(ciphertext[0], 32, enc_buf, key_schedule, 256, iv[0]);
|
||||
//printf("\nCiphertext : ");
|
||||
//print_hex(ciphertext[0], 32);
|
||||
//red_print_hex(ciphertext[0], 32);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, 32);
|
||||
//red_print_hex(enc_buf, 32);
|
||||
//printf("\nPlaintext : ");
|
||||
//print_hex(plaintext[0], 32);
|
||||
//red_print_hex(plaintext[0], 32);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[0], 32);
|
||||
|
||||
//printf("\n\n");
|
||||
@@ -1219,22 +1219,22 @@ int aes_ctr_test(void)
|
||||
aes_key_setup(key[0], key_schedule, 256);
|
||||
|
||||
//printf( "Key : ");
|
||||
//print_hex(key[0], 32);
|
||||
//red_print_hex(key[0], 32);
|
||||
//printf("\nIV : ");
|
||||
//print_hex(iv[0], 16);
|
||||
//red_print_hex(iv[0], 16);
|
||||
|
||||
aes_encrypt_ctr(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]);
|
||||
//printf("\nPlaintext : ");
|
||||
//print_hex(plaintext[0], 32);
|
||||
//red_print_hex(plaintext[0], 32);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, 32);
|
||||
//red_print_hex(enc_buf, 32);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[0], 32);
|
||||
|
||||
aes_decrypt_ctr(ciphertext[0], 32, enc_buf, key_schedule, 256, iv[0]);
|
||||
//printf("\nCiphertext : ");
|
||||
//print_hex(ciphertext[0], 32);
|
||||
//red_print_hex(ciphertext[0], 32);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, 32);
|
||||
//red_print_hex(enc_buf, 32);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[0], 32);
|
||||
|
||||
//printf("\n\n");
|
||||
@@ -1273,70 +1273,70 @@ int aes_ccm_test(void)
|
||||
|
||||
//printf("* CCM mode:\n");
|
||||
//printf("Key : ");
|
||||
//print_hex(key[0], 16);
|
||||
//red_print_hex(key[0], 16);
|
||||
|
||||
//print_hex(plaintext[0], 4);
|
||||
//print_hex(assoc[0], 8);
|
||||
//print_hex(ciphertext[0], 8);
|
||||
//print_hex(iv[0], 7);
|
||||
//print_hex(key[0], 16);
|
||||
//red_print_hex(plaintext[0], 4);
|
||||
//red_print_hex(assoc[0], 8);
|
||||
//red_print_hex(ciphertext[0], 8);
|
||||
//red_print_hex(iv[0], 7);
|
||||
//red_print_hex(key[0], 16);
|
||||
|
||||
aes_encrypt_ccm(plaintext[0], 4, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, key[0], 128);
|
||||
//printf("\nNONCE : ");
|
||||
//print_hex(iv[0], 7);
|
||||
//red_print_hex(iv[0], 7);
|
||||
//printf("\nAssoc. Data : ");
|
||||
//print_hex(assoc[0], 8);
|
||||
//red_print_hex(assoc[0], 8);
|
||||
//printf("\nPayload : ");
|
||||
//print_hex(plaintext[0], 4);
|
||||
//red_print_hex(plaintext[0], 4);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
//red_print_hex(enc_buf, enc_buf_len);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[0], enc_buf_len);
|
||||
|
||||
aes_decrypt_ccm(ciphertext[0], 8, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, &mac_auth, key[0], 128);
|
||||
//printf("\n-Ciphertext : ");
|
||||
//print_hex(ciphertext[0], 8);
|
||||
//red_print_hex(ciphertext[0], 8);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
//red_print_hex(enc_buf, enc_buf_len);
|
||||
//printf("\nAuthenticated: %d ", mac_auth);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[0], enc_buf_len) && mac_auth;
|
||||
|
||||
|
||||
aes_encrypt_ccm(plaintext[1], 16, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, key[0], 128);
|
||||
//printf("\n\nNONCE : ");
|
||||
//print_hex(iv[1], 8);
|
||||
//red_print_hex(iv[1], 8);
|
||||
//printf("\nAssoc. Data : ");
|
||||
//print_hex(assoc[1], 16);
|
||||
//red_print_hex(assoc[1], 16);
|
||||
//printf("\nPayload : ");
|
||||
//print_hex(plaintext[1], 16);
|
||||
//red_print_hex(plaintext[1], 16);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
//red_print_hex(enc_buf, enc_buf_len);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[1], enc_buf_len);
|
||||
|
||||
aes_decrypt_ccm(ciphertext[1], 22, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, &mac_auth, key[0], 128);
|
||||
//printf("\n-Ciphertext : ");
|
||||
//print_hex(ciphertext[1], 22);
|
||||
//red_print_hex(ciphertext[1], 22);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
//red_print_hex(enc_buf, enc_buf_len);
|
||||
//printf("\nAuthenticated: %d ", mac_auth);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[1], enc_buf_len) && mac_auth;
|
||||
|
||||
|
||||
aes_encrypt_ccm(plaintext[2], 24, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, key[0], 128);
|
||||
//printf("\n\nNONCE : ");
|
||||
//print_hex(iv[2], 12);
|
||||
//red_print_hex(iv[2], 12);
|
||||
//printf("\nAssoc. Data : ");
|
||||
//print_hex(assoc[2], 20);
|
||||
//red_print_hex(assoc[2], 20);
|
||||
//printf("\nPayload : ");
|
||||
//print_hex(plaintext[2], 24);
|
||||
//red_print_hex(plaintext[2], 24);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
//red_print_hex(enc_buf, enc_buf_len);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[2], enc_buf_len);
|
||||
|
||||
aes_decrypt_ccm(ciphertext[2], 32, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, &mac_auth, key[0], 128);
|
||||
//printf("\n-Ciphertext : ");
|
||||
//print_hex(ciphertext[2], 32);
|
||||
//red_print_hex(ciphertext[2], 32);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
//red_print_hex(enc_buf, enc_buf_len);
|
||||
//printf("\nAuthenticated: %d ", mac_auth);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[2], enc_buf_len) && mac_auth;
|
||||
|
||||
|
||||
+55
-102
@@ -4,7 +4,7 @@
|
||||
|
||||
uint8_t shift_tracker = 0;
|
||||
|
||||
void write_keycode(uint8_t up_key, uint8_t low_key, keyrecord_t *record, uint8_t readed_key[], uint8_t *count_char_key) {
|
||||
uint8_t write_keycode(uint8_t up_key, uint8_t low_key, keyrecord_t *record, uint8_t readed_key[], uint8_t *count_char_key) {
|
||||
if (record->event.pressed) {
|
||||
if (shift_tracker == 1) {
|
||||
// shift_tracker = 0;
|
||||
@@ -17,6 +17,7 @@ void write_keycode(uint8_t up_key, uint8_t low_key, keyrecord_t *record, uint8_t
|
||||
#endif
|
||||
*count_char_key = *count_char_key + 1;
|
||||
}
|
||||
return RED_KEY_READ;
|
||||
};
|
||||
|
||||
uint8_t kc_to_ascii(uint16_t keycode, keyrecord_t *record, uint8_t readed_key[], uint8_t *count_char_key) {
|
||||
@@ -24,211 +25,163 @@ uint8_t kc_to_ascii(uint16_t keycode, keyrecord_t *record, uint8_t readed_key[],
|
||||
case KC_LEFT_SHIFT:
|
||||
if (record->event.pressed) {
|
||||
shift_tracker = 1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
shift_tracker = 0;
|
||||
}
|
||||
return 1;
|
||||
return RED_KEY_READ;
|
||||
break;
|
||||
case KC_A:
|
||||
write_keycode(ASCII_UP_A, ASCII_LOW_A, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_A, ASCII_LOW_A, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_B:
|
||||
write_keycode(ASCII_UP_B, ASCII_LOW_B, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_B, ASCII_LOW_B, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_C:
|
||||
write_keycode(ASCII_UP_C, ASCII_LOW_C, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_C, ASCII_LOW_C, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_D:
|
||||
write_keycode(ASCII_UP_D, ASCII_LOW_D, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_D, ASCII_LOW_D, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_E:
|
||||
write_keycode(ASCII_UP_E, ASCII_LOW_E, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_E, ASCII_LOW_E, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_F:
|
||||
write_keycode(ASCII_UP_F, ASCII_LOW_F, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_F, ASCII_LOW_F, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_G:
|
||||
write_keycode(ASCII_UP_G, ASCII_LOW_G, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_G, ASCII_LOW_G, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_H:
|
||||
write_keycode(ASCII_UP_H, ASCII_LOW_H, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_H, ASCII_LOW_H, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_I:
|
||||
write_keycode(ASCII_UP_I, ASCII_LOW_I, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_I, ASCII_LOW_I, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_J:
|
||||
write_keycode(ASCII_UP_J, ASCII_LOW_J, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_J, ASCII_LOW_J, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_K:
|
||||
write_keycode(ASCII_UP_K, ASCII_LOW_K, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_K, ASCII_LOW_K, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_L:
|
||||
write_keycode(ASCII_UP_L, ASCII_LOW_L, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_L, ASCII_LOW_L, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_M:
|
||||
write_keycode(ASCII_UP_M, ASCII_LOW_M, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_M, ASCII_LOW_M, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_N:
|
||||
write_keycode(ASCII_UP_N, ASCII_LOW_N, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_N, ASCII_LOW_N, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_O:
|
||||
write_keycode(ASCII_UP_O, ASCII_LOW_O, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_O, ASCII_LOW_O, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_P:
|
||||
write_keycode(ASCII_UP_P, ASCII_LOW_P, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_P, ASCII_LOW_P, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_Q:
|
||||
write_keycode(ASCII_UP_Q, ASCII_LOW_Q, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_Q, ASCII_LOW_Q, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_R:
|
||||
write_keycode(ASCII_UP_R, ASCII_LOW_R, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_R, ASCII_LOW_R, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_S:
|
||||
write_keycode(ASCII_UP_S, ASCII_LOW_S, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_S, ASCII_LOW_S, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_T:
|
||||
write_keycode(ASCII_UP_T, ASCII_LOW_T, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_T, ASCII_LOW_T, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_U:
|
||||
write_keycode(ASCII_UP_U, ASCII_LOW_U, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_U, ASCII_LOW_U, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_V:
|
||||
write_keycode(ASCII_UP_V, ASCII_LOW_V, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_V, ASCII_LOW_V, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_W:
|
||||
write_keycode(ASCII_UP_W, ASCII_LOW_W, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_W, ASCII_LOW_W, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_X:
|
||||
write_keycode(ASCII_UP_X, ASCII_LOW_X, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_X, ASCII_LOW_X, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_Y:
|
||||
write_keycode(ASCII_UP_Y, ASCII_LOW_Y, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_Y, ASCII_LOW_Y, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_Z:
|
||||
write_keycode(ASCII_UP_Z, ASCII_LOW_Z, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_Z, ASCII_LOW_Z, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_1:
|
||||
write_keycode(ASCII_UP_1, ASCII_LOW_1, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_1, ASCII_LOW_1, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_2:
|
||||
write_keycode(ASCII_UP_2, ASCII_LOW_2, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_2, ASCII_LOW_2, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_3:
|
||||
write_keycode(ASCII_UP_3, ASCII_LOW_3, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_3, ASCII_LOW_3, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_4:
|
||||
write_keycode(ASCII_UP_4, ASCII_LOW_4, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_4, ASCII_LOW_4, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_5:
|
||||
write_keycode(ASCII_UP_5, ASCII_LOW_5, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_5, ASCII_LOW_5, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_6:
|
||||
write_keycode(ASCII_UP_6, ASCII_LOW_6, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_6, ASCII_LOW_6, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_7:
|
||||
write_keycode(ASCII_UP_7, ASCII_LOW_7, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_7, ASCII_LOW_7, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_8:
|
||||
write_keycode(ASCII_UP_8, ASCII_LOW_8, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_8, ASCII_LOW_8, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_9:
|
||||
write_keycode(ASCII_UP_9, ASCII_LOW_9, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_9, ASCII_LOW_9, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_0:
|
||||
write_keycode(ASCII_UP_0, ASCII_LOW_0, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_0, ASCII_LOW_0, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_SPACE:
|
||||
write_keycode(ASCII_SPACE, ASCII_SPACE, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_SPACE, ASCII_SPACE, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_MINUS:
|
||||
write_keycode(ASCII_UP_MINUS, ASCII_LOW_MINUS, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_MINUS, ASCII_LOW_MINUS, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_EQUAL:
|
||||
write_keycode(ASCII_UP_EQUAL, ASCII_LOW_EQUAL, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_EQUAL, ASCII_LOW_EQUAL, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_LEFT_BRACKET:
|
||||
write_keycode(ASCII_UP_LEFT_BR, ASCII_LOW_LEFT_BR, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_LEFT_BR, ASCII_LOW_LEFT_BR, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_RIGHT_BRACKET:
|
||||
write_keycode(ASCII_UP_RIGHT_BR, ASCII_LOW_RIGHT_BR, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_RIGHT_BR, ASCII_LOW_RIGHT_BR, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_BACKSLASH:
|
||||
write_keycode(ASCII_UP_BACKSLASH, ASCII_LOW_BACKSLASH, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_BACKSLASH, ASCII_LOW_BACKSLASH, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_NONUS_HASH:
|
||||
write_keycode(ASCII_UP_HASH, ASCII_GRAVE, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_HASH, ASCII_GRAVE, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_SEMICOLON:
|
||||
write_keycode(ASCII_UP_SEMICOLON, ASCII_LOW_SEMICOLON, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_SEMICOLON, ASCII_LOW_SEMICOLON, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_QUOTE:
|
||||
write_keycode(ASCII_UP_QUOTE, ASCII_LOW_QUOTE, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_QUOTE, ASCII_LOW_QUOTE, record, readed_key, count_char_key);
|
||||
break;
|
||||
// i am not sure about KC_GRAVE and KC_NONUS_HASH
|
||||
// need to test
|
||||
case KC_GRAVE:
|
||||
write_keycode(ASCII_NON_PRINTABLE, ASCII_GRAVE, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_NON_PRINTABLE, ASCII_GRAVE, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_COMMA:
|
||||
write_keycode(ASCII_UP_COMMA, ASCII_LOW_COMMA, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_COMMA, ASCII_LOW_COMMA, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_DOT:
|
||||
write_keycode(ASCII_UP_DOT, ASCII_LOW_DOT, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_DOT, ASCII_LOW_DOT, record, readed_key, count_char_key);
|
||||
break;
|
||||
case KC_SLASH:
|
||||
write_keycode(ASCII_UP_SLASH, ASCII_LOW_SLASH, record, readed_key, count_char_key);
|
||||
return 1;
|
||||
return write_keycode(ASCII_UP_SLASH, ASCII_LOW_SLASH, record, readed_key, count_char_key);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
return RED_IDLE;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
#include "quantum.h"
|
||||
#include "red_crypto.h"
|
||||
|
||||
#ifndef KC_TO_ASCII_H
|
||||
# define KC_TO_ASCII_H
|
||||
|
||||
@@ -0,0 +1,416 @@
|
||||
// kuznechik_128bit.c
|
||||
// 04-Jan-15 Markku-Juhani O. Saarinen <mjos@iki.fi>
|
||||
|
||||
// Basic 128-bit version without platform - specific optimizations
|
||||
|
||||
// Conforms to included doc/GOSTR-bsh.pdf file, which has an internal
|
||||
// date of September 2, 2014.
|
||||
|
||||
#include "kuznechik_128bit.h"
|
||||
|
||||
#ifndef __SSE4_1__
|
||||
#error "This version requires __SSE4_1__"
|
||||
#endif
|
||||
|
||||
#include <mmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#include <smmintrin.h>
|
||||
|
||||
// The S-Box from section 5.1.1
|
||||
|
||||
static const uint8_t kuz_pi[0x100] = {
|
||||
0xFC, 0xEE, 0xDD, 0x11, 0xCF, 0x6E, 0x31, 0x16, // 00..07
|
||||
0xFB, 0xC4, 0xFA, 0xDA, 0x23, 0xC5, 0x04, 0x4D, // 08..0F
|
||||
0xE9, 0x77, 0xF0, 0xDB, 0x93, 0x2E, 0x99, 0xBA, // 10..17
|
||||
0x17, 0x36, 0xF1, 0xBB, 0x14, 0xCD, 0x5F, 0xC1, // 18..1F
|
||||
0xF9, 0x18, 0x65, 0x5A, 0xE2, 0x5C, 0xEF, 0x21, // 20..27
|
||||
0x81, 0x1C, 0x3C, 0x42, 0x8B, 0x01, 0x8E, 0x4F, // 28..2F
|
||||
0x05, 0x84, 0x02, 0xAE, 0xE3, 0x6A, 0x8F, 0xA0, // 30..37
|
||||
0x06, 0x0B, 0xED, 0x98, 0x7F, 0xD4, 0xD3, 0x1F, // 38..3F
|
||||
0xEB, 0x34, 0x2C, 0x51, 0xEA, 0xC8, 0x48, 0xAB, // 40..47
|
||||
0xF2, 0x2A, 0x68, 0xA2, 0xFD, 0x3A, 0xCE, 0xCC, // 48..4F
|
||||
0xB5, 0x70, 0x0E, 0x56, 0x08, 0x0C, 0x76, 0x12, // 50..57
|
||||
0xBF, 0x72, 0x13, 0x47, 0x9C, 0xB7, 0x5D, 0x87, // 58..5F
|
||||
0x15, 0xA1, 0x96, 0x29, 0x10, 0x7B, 0x9A, 0xC7, // 60..67
|
||||
0xF3, 0x91, 0x78, 0x6F, 0x9D, 0x9E, 0xB2, 0xB1, // 68..6F
|
||||
0x32, 0x75, 0x19, 0x3D, 0xFF, 0x35, 0x8A, 0x7E, // 70..77
|
||||
0x6D, 0x54, 0xC6, 0x80, 0xC3, 0xBD, 0x0D, 0x57, // 78..7F
|
||||
0xDF, 0xF5, 0x24, 0xA9, 0x3E, 0xA8, 0x43, 0xC9, // 80..87
|
||||
0xD7, 0x79, 0xD6, 0xF6, 0x7C, 0x22, 0xB9, 0x03, // 88..8F
|
||||
0xE0, 0x0F, 0xEC, 0xDE, 0x7A, 0x94, 0xB0, 0xBC, // 90..97
|
||||
0xDC, 0xE8, 0x28, 0x50, 0x4E, 0x33, 0x0A, 0x4A, // 98..9F
|
||||
0xA7, 0x97, 0x60, 0x73, 0x1E, 0x00, 0x62, 0x44, // A0..A7
|
||||
0x1A, 0xB8, 0x38, 0x82, 0x64, 0x9F, 0x26, 0x41, // A8..AF
|
||||
0xAD, 0x45, 0x46, 0x92, 0x27, 0x5E, 0x55, 0x2F, // B0..B7
|
||||
0x8C, 0xA3, 0xA5, 0x7D, 0x69, 0xD5, 0x95, 0x3B, // B8..BF
|
||||
0x07, 0x58, 0xB3, 0x40, 0x86, 0xAC, 0x1D, 0xF7, // C0..C7
|
||||
0x30, 0x37, 0x6B, 0xE4, 0x88, 0xD9, 0xE7, 0x89, // C8..CF
|
||||
0xE1, 0x1B, 0x83, 0x49, 0x4C, 0x3F, 0xF8, 0xFE, // D0..D7
|
||||
0x8D, 0x53, 0xAA, 0x90, 0xCA, 0xD8, 0x85, 0x61, // D8..DF
|
||||
0x20, 0x71, 0x67, 0xA4, 0x2D, 0x2B, 0x09, 0x5B, // E0..E7
|
||||
0xCB, 0x9B, 0x25, 0xD0, 0xBE, 0xE5, 0x6C, 0x52, // E8..EF
|
||||
0x59, 0xA6, 0x74, 0xD2, 0xE6, 0xF4, 0xB4, 0xC0, // F0..F7
|
||||
0xD1, 0x66, 0xAF, 0xC2, 0x39, 0x4B, 0x63, 0xB6, // F8..FF
|
||||
};
|
||||
|
||||
// Inverse S-Box
|
||||
|
||||
static const uint8_t kuz_pi_inv[0x100] = {
|
||||
0xA5, 0x2D, 0x32, 0x8F, 0x0E, 0x30, 0x38, 0xC0, // 00..07
|
||||
0x54, 0xE6, 0x9E, 0x39, 0x55, 0x7E, 0x52, 0x91, // 08..0F
|
||||
0x64, 0x03, 0x57, 0x5A, 0x1C, 0x60, 0x07, 0x18, // 10..17
|
||||
0x21, 0x72, 0xA8, 0xD1, 0x29, 0xC6, 0xA4, 0x3F, // 18..1F
|
||||
0xE0, 0x27, 0x8D, 0x0C, 0x82, 0xEA, 0xAE, 0xB4, // 20..27
|
||||
0x9A, 0x63, 0x49, 0xE5, 0x42, 0xE4, 0x15, 0xB7, // 28..2F
|
||||
0xC8, 0x06, 0x70, 0x9D, 0x41, 0x75, 0x19, 0xC9, // 30..37
|
||||
0xAA, 0xFC, 0x4D, 0xBF, 0x2A, 0x73, 0x84, 0xD5, // 38..3F
|
||||
0xC3, 0xAF, 0x2B, 0x86, 0xA7, 0xB1, 0xB2, 0x5B, // 40..47
|
||||
0x46, 0xD3, 0x9F, 0xFD, 0xD4, 0x0F, 0x9C, 0x2F, // 48..4F
|
||||
0x9B, 0x43, 0xEF, 0xD9, 0x79, 0xB6, 0x53, 0x7F, // 50..57
|
||||
0xC1, 0xF0, 0x23, 0xE7, 0x25, 0x5E, 0xB5, 0x1E, // 58..5F
|
||||
0xA2, 0xDF, 0xA6, 0xFE, 0xAC, 0x22, 0xF9, 0xE2, // 60..67
|
||||
0x4A, 0xBC, 0x35, 0xCA, 0xEE, 0x78, 0x05, 0x6B, // 68..6F
|
||||
0x51, 0xE1, 0x59, 0xA3, 0xF2, 0x71, 0x56, 0x11, // 70..77
|
||||
0x6A, 0x89, 0x94, 0x65, 0x8C, 0xBB, 0x77, 0x3C, // 78..7F
|
||||
0x7B, 0x28, 0xAB, 0xD2, 0x31, 0xDE, 0xC4, 0x5F, // 80..87
|
||||
0xCC, 0xCF, 0x76, 0x2C, 0xB8, 0xD8, 0x2E, 0x36, // 88..8F
|
||||
0xDB, 0x69, 0xB3, 0x14, 0x95, 0xBE, 0x62, 0xA1, // 90..97
|
||||
0x3B, 0x16, 0x66, 0xE9, 0x5C, 0x6C, 0x6D, 0xAD, // 98..9F
|
||||
0x37, 0x61, 0x4B, 0xB9, 0xE3, 0xBA, 0xF1, 0xA0, // A0..A7
|
||||
0x85, 0x83, 0xDA, 0x47, 0xC5, 0xB0, 0x33, 0xFA, // A8..AF
|
||||
0x96, 0x6F, 0x6E, 0xC2, 0xF6, 0x50, 0xFF, 0x5D, // B0..B7
|
||||
0xA9, 0x8E, 0x17, 0x1B, 0x97, 0x7D, 0xEC, 0x58, // B8..BF
|
||||
0xF7, 0x1F, 0xFB, 0x7C, 0x09, 0x0D, 0x7A, 0x67, // C0..C7
|
||||
0x45, 0x87, 0xDC, 0xE8, 0x4F, 0x1D, 0x4E, 0x04, // C8..CF
|
||||
0xEB, 0xF8, 0xF3, 0x3E, 0x3D, 0xBD, 0x8A, 0x88, // D0..D7
|
||||
0xDD, 0xCD, 0x0B, 0x13, 0x98, 0x02, 0x93, 0x80, // D8..DF
|
||||
0x90, 0xD0, 0x24, 0x34, 0xCB, 0xED, 0xF4, 0xCE, // E0..E7
|
||||
0x99, 0x10, 0x44, 0x40, 0x92, 0x3A, 0x01, 0x26, // E8..EF
|
||||
0x12, 0x1A, 0x48, 0x68, 0xF5, 0x81, 0x8B, 0xC7, // F0..F7
|
||||
0xD6, 0x20, 0x0A, 0x08, 0x00, 0x4C, 0xD7, 0x74 // F8..FF
|
||||
};
|
||||
|
||||
// Linear vector from sect 5.1.2
|
||||
|
||||
static const uint8_t kuz_lvec[16] = {
|
||||
0x94, 0x20, 0x85, 0x10, 0xC2, 0xC0, 0x01, 0xFB,
|
||||
0x01, 0xC0, 0xC2, 0x10, 0x85, 0x20, 0x94, 0x01
|
||||
};
|
||||
|
||||
// lookup tables initialized by kuz_init()
|
||||
|
||||
static int kuz_initialized = 0;
|
||||
static __m128i kuz_pil_enc128[16][256];
|
||||
static __m128i kuz_l_dec128[16][256];
|
||||
static __m128i kuz_pil_dec128[16][256];
|
||||
|
||||
// poly multiplication mod p(x) = x^8 + x^7 + x^6 + x + 1
|
||||
|
||||
static uint8_t kuz_mul_gf256(uint8_t x, uint8_t y)
|
||||
{
|
||||
uint8_t z;
|
||||
|
||||
z = 0;
|
||||
while (y) {
|
||||
if (y & 1)
|
||||
z ^= x;
|
||||
x = (x << 1) ^ (x & 0x80 ? 0xC3 : 0x00);
|
||||
y >>= 1;
|
||||
}
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
// (slow) linear operation l
|
||||
|
||||
static void kuz_l(w128_t *w)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t x;
|
||||
|
||||
// 16 rounds
|
||||
for (j = 0; j < 16; j++) {
|
||||
|
||||
// An LFSR with 16 elements from GF(2^8)
|
||||
x = w->b[15]; // since lvec[15] = 1
|
||||
|
||||
for (i = 14; i >= 0; i--) {
|
||||
w->b[i + 1] = w->b[i];
|
||||
x ^= kuz_mul_gf256(w->b[i], kuz_lvec[i]);
|
||||
}
|
||||
w->b[0] = x;
|
||||
}
|
||||
}
|
||||
|
||||
// inverse of linear operation l
|
||||
|
||||
static void kuz_l_inv(w128_t *w)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t x;
|
||||
|
||||
// 16 rounds
|
||||
for (j = 0; j < 16; j++) {
|
||||
|
||||
x = w->b[0];
|
||||
for (i = 0; i < 15; i++) {
|
||||
w->b[i] = w->b[i + 1];
|
||||
x ^= kuz_mul_gf256(w->b[i], kuz_lvec[i]);
|
||||
}
|
||||
w->b[15] = x;
|
||||
}
|
||||
}
|
||||
|
||||
// key setup
|
||||
|
||||
void kuz_set_encrypt_key(kuz_key_t *kuz, const uint8_t key[32])
|
||||
{
|
||||
int i, j;
|
||||
w128_t c, x, y, z;
|
||||
|
||||
if (!kuz_initialized)
|
||||
kuz_init();
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
// this will be have to changed for little-endian systems
|
||||
x.b[i] = key[i];
|
||||
y.b[i] = key[i + 16];
|
||||
}
|
||||
|
||||
kuz->k[0].q[0] = x.q[0];
|
||||
kuz->k[0].q[1] = x.q[1];
|
||||
kuz->k[1].q[0] = y.q[0];
|
||||
kuz->k[1].q[1] = y.q[1];
|
||||
|
||||
for (i = 1; i <= 32; i++) {
|
||||
|
||||
// C Value
|
||||
c.q[0] = 0;
|
||||
c.q[1] = 0;
|
||||
c.b[15] = i; // load round in lsb
|
||||
kuz_l(&c);
|
||||
|
||||
z.q[0] = x.q[0] ^ c.q[0];
|
||||
z.q[1] = x.q[1] ^ c.q[1];
|
||||
for (j = 0; j < 16; j++)
|
||||
z.b[j] = kuz_pi[z.b[j]];
|
||||
kuz_l(&z);
|
||||
z.q[0] ^= y.q[0];
|
||||
z.q[1] ^= y.q[1];
|
||||
|
||||
y.q[0] = x.q[0];
|
||||
y.q[1] = x.q[1];
|
||||
|
||||
x.q[0] = z.q[0];
|
||||
x.q[1] = z.q[1];
|
||||
|
||||
if ((i & 7) == 0) {
|
||||
kuz->k[(i >> 2)].q[0] = x.q[0];
|
||||
kuz->k[(i >> 2)].q[1] = x.q[1];
|
||||
kuz->k[(i >> 2) + 1].q[0] = y.q[0];
|
||||
kuz->k[(i >> 2) + 1].q[1] = y.q[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// these two funcs are identical in the simple implementation
|
||||
|
||||
void kuz_set_decrypt_key(kuz_key_t *kuz, const uint8_t key[32])
|
||||
{
|
||||
int i;
|
||||
|
||||
kuz_set_encrypt_key(kuz, key);
|
||||
|
||||
for (i = 1; i < 10; i++)
|
||||
kuz_l_inv(&kuz->k[i]);
|
||||
}
|
||||
|
||||
// encrypt a block - 128 bit way
|
||||
|
||||
void kuz_encrypt_block(kuz_key_t *key, void *blk)
|
||||
{
|
||||
int i;
|
||||
__m128i x;
|
||||
|
||||
x = *((__m128i *) blk);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
x ^= *((__m128i *) &key->k[i]);
|
||||
x = kuz_pil_enc128[ 0][((uint8_t *) &x)[ 0]] ^
|
||||
kuz_pil_enc128[ 1][((uint8_t *) &x)[ 1]] ^
|
||||
kuz_pil_enc128[ 2][((uint8_t *) &x)[ 2]] ^
|
||||
kuz_pil_enc128[ 3][((uint8_t *) &x)[ 3]] ^
|
||||
kuz_pil_enc128[ 4][((uint8_t *) &x)[ 4]] ^
|
||||
kuz_pil_enc128[ 5][((uint8_t *) &x)[ 5]] ^
|
||||
kuz_pil_enc128[ 6][((uint8_t *) &x)[ 6]] ^
|
||||
kuz_pil_enc128[ 7][((uint8_t *) &x)[ 7]] ^
|
||||
kuz_pil_enc128[ 8][((uint8_t *) &x)[ 8]] ^
|
||||
kuz_pil_enc128[ 9][((uint8_t *) &x)[ 9]] ^
|
||||
kuz_pil_enc128[10][((uint8_t *) &x)[10]] ^
|
||||
kuz_pil_enc128[11][((uint8_t *) &x)[11]] ^
|
||||
kuz_pil_enc128[12][((uint8_t *) &x)[12]] ^
|
||||
kuz_pil_enc128[13][((uint8_t *) &x)[13]] ^
|
||||
kuz_pil_enc128[14][((uint8_t *) &x)[14]] ^
|
||||
kuz_pil_enc128[15][((uint8_t *) &x)[15]];
|
||||
|
||||
}
|
||||
x ^= *((__m128i *) &key->k[9]);
|
||||
|
||||
*((__m128i *) blk) = x;
|
||||
}
|
||||
|
||||
// decrypt a block - 128 bit way
|
||||
|
||||
void kuz_decrypt_block(kuz_key_t *key, void *blk)
|
||||
{
|
||||
int i, j;
|
||||
__m128i x;
|
||||
|
||||
x = *((__m128i *) blk);
|
||||
|
||||
x = kuz_l_dec128[ 0][((uint8_t *) &x)[ 0]] ^
|
||||
kuz_l_dec128[ 1][((uint8_t *) &x)[ 1]] ^
|
||||
kuz_l_dec128[ 2][((uint8_t *) &x)[ 2]] ^
|
||||
kuz_l_dec128[ 3][((uint8_t *) &x)[ 3]] ^
|
||||
kuz_l_dec128[ 4][((uint8_t *) &x)[ 4]] ^
|
||||
kuz_l_dec128[ 5][((uint8_t *) &x)[ 5]] ^
|
||||
kuz_l_dec128[ 6][((uint8_t *) &x)[ 6]] ^
|
||||
kuz_l_dec128[ 7][((uint8_t *) &x)[ 7]] ^
|
||||
kuz_l_dec128[ 8][((uint8_t *) &x)[ 8]] ^
|
||||
kuz_l_dec128[ 9][((uint8_t *) &x)[ 9]] ^
|
||||
kuz_l_dec128[10][((uint8_t *) &x)[10]] ^
|
||||
kuz_l_dec128[11][((uint8_t *) &x)[11]] ^
|
||||
kuz_l_dec128[12][((uint8_t *) &x)[12]] ^
|
||||
kuz_l_dec128[13][((uint8_t *) &x)[13]] ^
|
||||
kuz_l_dec128[14][((uint8_t *) &x)[14]] ^
|
||||
kuz_l_dec128[15][((uint8_t *) &x)[15]];
|
||||
|
||||
for (i = 9; i > 1; i--) {
|
||||
x ^= *((__m128i *) &key->k[i]);
|
||||
x = kuz_pil_dec128[ 0][((uint8_t *) &x)[ 0]] ^
|
||||
kuz_pil_dec128[ 1][((uint8_t *) &x)[ 1]] ^
|
||||
kuz_pil_dec128[ 2][((uint8_t *) &x)[ 2]] ^
|
||||
kuz_pil_dec128[ 3][((uint8_t *) &x)[ 3]] ^
|
||||
kuz_pil_dec128[ 4][((uint8_t *) &x)[ 4]] ^
|
||||
kuz_pil_dec128[ 5][((uint8_t *) &x)[ 5]] ^
|
||||
kuz_pil_dec128[ 6][((uint8_t *) &x)[ 6]] ^
|
||||
kuz_pil_dec128[ 7][((uint8_t *) &x)[ 7]] ^
|
||||
kuz_pil_dec128[ 8][((uint8_t *) &x)[ 8]] ^
|
||||
kuz_pil_dec128[ 9][((uint8_t *) &x)[ 9]] ^
|
||||
kuz_pil_dec128[10][((uint8_t *) &x)[10]] ^
|
||||
kuz_pil_dec128[11][((uint8_t *) &x)[11]] ^
|
||||
kuz_pil_dec128[12][((uint8_t *) &x)[12]] ^
|
||||
kuz_pil_dec128[13][((uint8_t *) &x)[13]] ^
|
||||
kuz_pil_dec128[14][((uint8_t *) &x)[14]] ^
|
||||
kuz_pil_dec128[15][((uint8_t *) &x)[15]];
|
||||
}
|
||||
x ^= *((__m128i *) &key->k[1]);
|
||||
for (j = 0; j < 16; j++)
|
||||
((uint8_t *) &x)[j] = kuz_pi_inv[((uint8_t *) &x)[j]];
|
||||
x ^= *((__m128i *) &key->k[0]);
|
||||
|
||||
*((__m128i *) blk) = x;
|
||||
}
|
||||
|
||||
// initalize lookup tables
|
||||
|
||||
void kuz_init()
|
||||
{
|
||||
int i, j;
|
||||
w128_t x;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (j = 0; j < 256; j++) {
|
||||
x.q[0] = 0;
|
||||
x.q[1] = 0;
|
||||
x.b[i] = kuz_pi[j];
|
||||
kuz_l(&x);
|
||||
kuz_pil_enc128[i][j] = *((__m128i *) &x);
|
||||
|
||||
x.q[0] = 0;
|
||||
x.q[1] = 0;
|
||||
x.b[i] = j; // kuz_pi[j];
|
||||
kuz_l_inv(&x);
|
||||
kuz_l_dec128[i][j] = *((__m128i *) &x);
|
||||
|
||||
x.q[0] = 0;
|
||||
x.q[1] = 0;
|
||||
x.b[i] = kuz_pi_inv[j];
|
||||
kuz_l_inv(&x);
|
||||
kuz_pil_dec128[i][j] = *((__m128i *) &x);
|
||||
}
|
||||
}
|
||||
kuz_initialized = 1;
|
||||
}
|
||||
|
||||
|
||||
/*********************** TEST FUNCTION DEFINITIONS ***********************/
|
||||
#ifdef TEST_FUNCTIONS_ENABLED
|
||||
|
||||
void exec_kuznechik_test(void) {
|
||||
// These are here in Big Endian format, as that seems to be the favored
|
||||
// way of representing things. However, it is open if we will have to
|
||||
// flip byte order for the final version or not.
|
||||
|
||||
const uint8_t testvec_key[32] = {
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
|
||||
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
|
||||
};
|
||||
const uint8_t testvec_pt[16] = {
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00,
|
||||
0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88
|
||||
};
|
||||
const uint8_t testvec_ct[16] = {
|
||||
0x7F, 0x67, 0x9D, 0x90, 0xBE, 0xBC, 0x24, 0x30,
|
||||
0x5A, 0x46, 0x8D, 0x42, 0xB9, 0xD4, 0xED, 0xCD
|
||||
};
|
||||
|
||||
int i;
|
||||
kuz_key_t key;
|
||||
w128_t x;
|
||||
|
||||
printf("Self-test:\n");
|
||||
kuz_init();
|
||||
|
||||
kuz_set_encrypt_key(&key, testvec_key);
|
||||
for (i = 0; i < 10; i++) {
|
||||
printf("K_%d\t=", i + 1);
|
||||
print_w128(&key.k[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
x.b[i] = testvec_pt[i];
|
||||
printf("PT\t=");
|
||||
print_w128(&x);
|
||||
|
||||
kuz_encrypt_block(&key, &x);
|
||||
|
||||
printf("CT\t=");
|
||||
print_w128(&x);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (testvec_ct[i] != x.b[i]) {
|
||||
fprintf(stderr, "Encryption self-test failure.\n");
|
||||
// return -1;
|
||||
}
|
||||
}
|
||||
|
||||
kuz_set_decrypt_key(&key, testvec_key);
|
||||
kuz_decrypt_block(&key, &x);
|
||||
|
||||
printf("PT\t=");
|
||||
print_w128(&x);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (testvec_pt[i] != x.b[i]) {
|
||||
fprintf(stderr, "Decryption self-test failure.\n");
|
||||
// return -2;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Self-test OK!\n");
|
||||
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
// kuznechik.h
|
||||
// 04-Jan-15 Markku-Juhani O. Saarinen <mjos@iki.fi>
|
||||
|
||||
#ifndef KUZNECHIK_H
|
||||
#define KUZNECHIK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// my 128-bit datatype
|
||||
typedef union {
|
||||
uint64_t q[2];
|
||||
uint8_t b[16];
|
||||
} w128_t;
|
||||
|
||||
// cipher context
|
||||
typedef struct {
|
||||
w128_t k[10]; // round keys
|
||||
} kuz_key_t;
|
||||
|
||||
// init lookup tables
|
||||
void kuz_init(void);
|
||||
|
||||
// key setup
|
||||
void kuz_set_encrypt_key(kuz_key_t *subkeys, const uint8_t key[32]);
|
||||
void kuz_set_decrypt_key(kuz_key_t *subkeys, const uint8_t key[32]);
|
||||
|
||||
// single-block ecp ops
|
||||
void kuz_encrypt_block(kuz_key_t *subkeys, void *x);
|
||||
void kuz_decrypt_block(kuz_key_t *subkeys, void *x);
|
||||
|
||||
// utils
|
||||
void print_w128(w128_t *x);
|
||||
|
||||
// tests
|
||||
#ifdef TEST_FUNCTIONS_ENABLED
|
||||
void exec_kuznechik_test(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+9
-1
@@ -258,12 +258,20 @@ void kuz_decrypt_block(kuz_key_t *key, void *blk)
|
||||
void print_w128(w128_t *x)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("\n");
|
||||
for (i = 0; i < 16; i++)
|
||||
printf(" %02X", x->b[i]);
|
||||
printf("\n");
|
||||
};
|
||||
|
||||
void print_chars_w128(w128_t *x) {
|
||||
printf("\n");
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if (x->b[i] == 0x00) break;
|
||||
printf("%c", x->b[i]);
|
||||
}
|
||||
printf("\n");
|
||||
};
|
||||
|
||||
/*********************** TEST FUNCTION DEFINITIONS ***********************/
|
||||
#ifdef TEST_FUNCTIONS_ENABLED
|
||||
|
||||
@@ -32,6 +32,7 @@ void kuz_decrypt_block(kuz_key_t *subkeys, void *x);
|
||||
|
||||
// utils
|
||||
void print_w128(w128_t *x);
|
||||
void print_chars_w128(w128_t *x);
|
||||
|
||||
// tests
|
||||
#ifdef TEST_FUNCTIONS_ENABLED
|
||||
|
||||
+215
-120
@@ -2,116 +2,155 @@
|
||||
|
||||
#include "red_crypto.h"
|
||||
|
||||
uint8_t dec_pass[STORAGE_SIZE][STORAGE_PASS_LEN];
|
||||
|
||||
void init_dec_pass(void) {
|
||||
for (uint8_t i = 0; i < STORAGE_SIZE; i++) {
|
||||
for (uint8_t j = 0; j < STORAGE_PASS_LEN; j++) {
|
||||
dec_pass[i][j] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// you can use key any length with SHA256, kuznechik use only 32byte
|
||||
uint8_t eeprom_inited = 0;
|
||||
uint8_t *master_key; // you can use key any length with SHA256 by defining MASTER_KEY_LEN, kuznechik use only 32byte
|
||||
uint8_t **decrypted_passwords;
|
||||
uint8_t *new_pass_enc;
|
||||
#ifdef USE_SHA256_KEY
|
||||
uint8_t readed_key[128] = {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, 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, 0, 0};
|
||||
uint8_t master_key_hash[32];
|
||||
#endif
|
||||
#ifndef USE_SHA256_KEY
|
||||
uint8_t readed_key[32] = {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};
|
||||
#endif
|
||||
|
||||
uint8_t count_char_key = 0;
|
||||
|
||||
uint8_t crypto_mode = 0;
|
||||
uint8_t decrypted_mode = 0;
|
||||
uint8_t red_menu_mode = 0;
|
||||
|
||||
void print_chars_w128(w128_t *x) {
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if (x->b[i] == 0x00) break;
|
||||
dprintf("%c", x->b[i]);
|
||||
void crypto_eeprom_init() {
|
||||
uint8_t red_var[3] = {'R', 'E', 'D'};
|
||||
// TODO: don't work with this var,copy it to global var in RAM
|
||||
// TODO: write code for not emulated EEPROM
|
||||
// eeconfig_read_user_datablock(enc_pass.raw);
|
||||
// for (uint8_t i = 0; i < EECONFIG_USER_DATA_SIZE; i++) {
|
||||
// dprintf("%x ", enc_pass.raw[i]);
|
||||
// }
|
||||
|
||||
red_read_from_storage();
|
||||
|
||||
if (enc_pass.init_var[0] == red_var[0] && enc_pass.init_var[1] == red_var[1] && enc_pass.init_var[2] == red_var[2]) { // not empty eeprom
|
||||
dprintf("Not empty EEPROM\n");
|
||||
eeprom_inited = 1;
|
||||
// #undef INIT_STORAGE_SIZE
|
||||
// #define INIT_STORAGE_SIZE enc_pass.storage_size
|
||||
// #undef INIT_STORAGE_PASS_LEN
|
||||
// #define INIT_STORAGE_PASS_LEN enc_pass.storage_pass_len
|
||||
} else { // empty eeprom
|
||||
dprintf("Empty EEPROM\n");
|
||||
eeprom_inited = 0;
|
||||
enc_pass.init_var[0] = 'R';
|
||||
enc_pass.init_var[1] = 'E';
|
||||
enc_pass.init_var[2] = 'D';
|
||||
enc_pass.version[0] = '0';
|
||||
enc_pass.version[1] = '7';
|
||||
enc_pass.version[2] = '3';
|
||||
enc_pass.memory_usage = 0;
|
||||
enc_pass.password_count = 0;
|
||||
enc_pass.storage_size = INIT_STORAGE_SIZE;
|
||||
enc_pass.storage_pass_len = INIT_STORAGE_PASS_LEN;
|
||||
for (uint8_t password_index = 0; password_index < enc_pass.storage_size; password_index++) { // must zero bytes in memory
|
||||
for (uint8_t password_byte = 0; password_byte < enc_pass.storage_pass_len; password_byte++) {
|
||||
enc_pass.passwords[password_index * enc_pass.storage_pass_len + password_byte] = 0x00;
|
||||
}
|
||||
dprintf("\n");
|
||||
};
|
||||
|
||||
void print_chars(uint8_t *c) {
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
if (c[i] == 0x00) break;
|
||||
dprintf("%c", c[i]);
|
||||
}
|
||||
dprintf("\n");
|
||||
};
|
||||
|
||||
void print_int(uint8_t *c) {
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
dprintf("%d", c[i]);
|
||||
// eeconfig_update_user_datablock(enc_pass.raw);
|
||||
red_write_to_storage();
|
||||
}
|
||||
dprintf("\n");
|
||||
};
|
||||
|
||||
void print_hex(uint8_t *h) {
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
dprintf("%x ", h[i]);
|
||||
}
|
||||
dprintf("\n");
|
||||
};
|
||||
|
||||
size_t min_len(size_t a, size_t b) {
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
uint8_t red_strlen_printable(uint8_t *str_printable, uint8_t max_len) {
|
||||
uint8_t result = 0;
|
||||
while (result < max_len && *str_printable != '\0') {
|
||||
result++;
|
||||
str_printable++;
|
||||
// encrypt new password
|
||||
uint8_t *encrypt_pass_kuzn(const uint8_t *new_pass, const uint8_t new_pass_length, const uint8_t password_index) {
|
||||
kuz_key_t key;
|
||||
w128_t x;
|
||||
new_pass_enc = red_init_array(enc_pass.storage_pass_len, 0x00); // assign zeros to encrypted new password var
|
||||
// copy new password in decrypted_passwords
|
||||
if (password_index == 255) {
|
||||
for (uint8_t byte_index = 0; byte_index < new_pass_length; byte_index++) {
|
||||
decrypted_passwords[enc_pass.password_count][byte_index] = new_pass[byte_index];
|
||||
}
|
||||
} else {
|
||||
decrypted_passwords[password_index] = red_init_array(enc_pass.storage_pass_len, 0x00);
|
||||
for (uint8_t byte_index = 0; byte_index < new_pass_length; byte_index++) {
|
||||
decrypted_passwords[password_index][byte_index] = new_pass[byte_index];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void decrypt_pass_kuzn(const uint8_t encrypted_passwords[STORAGE_SIZE][STORAGE_PASS_LEN]) {
|
||||
kuz_init();
|
||||
|
||||
// using master_key for encrypting
|
||||
#ifdef USE_SHA256_KEY
|
||||
kuz_set_encrypt_key(&key, hashing_string(master_key));
|
||||
#endif
|
||||
// if you don't have enough FLASH in MCU
|
||||
#ifndef USE_SHA256_KEY
|
||||
kuz_set_encrypt_key(&key, master_key);
|
||||
#endif
|
||||
|
||||
#ifdef USE_RED_CRY_DEBUG
|
||||
print_w128(&x);
|
||||
#endif
|
||||
// encrypting one password
|
||||
// it will read only blocks with password, empty blocks will not be encrypted!
|
||||
for (uint8_t block_index = 0; block_index < CEILING(new_pass_length, BLOCK_SIZE); block_index++) {
|
||||
// reading password's block for encrypting
|
||||
for (uint8_t byte_index = 0 + block_index * BLOCK_SIZE; byte_index < BLOCK_SIZE + block_index * BLOCK_SIZE; byte_index++) {
|
||||
x.b[byte_index % BLOCK_SIZE] = new_pass[byte_index];
|
||||
}
|
||||
kuz_encrypt_block(&key, &x);
|
||||
// reading encrypted block to return variable
|
||||
for (uint8_t byte_index = 0 + block_index * BLOCK_SIZE; byte_index < BLOCK_SIZE + block_index * BLOCK_SIZE; byte_index++) {
|
||||
new_pass_enc[byte_index + block_index * BLOCK_SIZE] = x.b[byte_index % BLOCK_SIZE];
|
||||
}
|
||||
#ifdef USE_RED_CRY_DEBUG
|
||||
print_w128(&x);
|
||||
print_chars_w128(&x);
|
||||
#endif
|
||||
}
|
||||
return new_pass_enc;
|
||||
}
|
||||
|
||||
// decrypting passwords
|
||||
void decrypt_pass_kuzn(void) {
|
||||
kuz_key_t key;
|
||||
w128_t x;
|
||||
|
||||
init_dec_pass();
|
||||
decrypted_passwords = red_init_array_2d(enc_pass.storage_size, enc_pass.storage_pass_len, 0x00); // clear decrypted passwords
|
||||
kuz_init();
|
||||
|
||||
// for hashing key, like a KDF algorithm
|
||||
#ifdef USE_SHA256_KEY
|
||||
SHA256_CTX ctx;
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, readed_key, red_strlen_printable(readed_key, MAX_KEY_LEN));
|
||||
BYTE result_key[SHA256_BLOCK_SIZE];
|
||||
sha256_final(&ctx, result_key);
|
||||
print_hex(result_key);
|
||||
kuz_set_decrypt_key(&key, result_key);
|
||||
kuz_set_decrypt_key(&key, hashing_string(master_key));
|
||||
#endif
|
||||
// if you don't have enough FLASH in MCU
|
||||
#ifndef USE_SHA256_KEY
|
||||
kuz_set_decrypt_key(&key, readed_key);
|
||||
kuz_set_decrypt_key(&key, master_key);
|
||||
#endif
|
||||
for (uint8_t j = 0; j < STORAGE_SIZE; j++) {
|
||||
|
||||
// decrypting all passwords in storage
|
||||
for (uint8_t password_index = 0; password_index < enc_pass.storage_size; password_index++) {
|
||||
#ifdef USE_RED_CRY_DEBUG
|
||||
dprintf("decrypted\t=");
|
||||
#endif
|
||||
for (uint8_t k = 0; k < STORAGE_PASS_LEN / 16; k++) {
|
||||
for (uint8_t block_index = 0; block_index < enc_pass.storage_pass_len / BLOCK_SIZE; block_index++) {
|
||||
uint8_t cnt_zeros = 0;
|
||||
for (uint8_t z = 0 + k * 16; z < 16 + k * 16; z++) {
|
||||
if (encrypted_passwords[j][z] == 0x00) {
|
||||
// checking is this empty block or not
|
||||
for (uint8_t byte_index = 0 + block_index * BLOCK_SIZE; byte_index < BLOCK_SIZE + block_index * BLOCK_SIZE; byte_index++) {
|
||||
// if (encrypted_passwords[password_index][byte_index] == 0x00) {
|
||||
if (enc_pass.passwords[password_index * enc_pass.storage_pass_len + byte_index] == 0x00) {
|
||||
cnt_zeros++;
|
||||
} else {
|
||||
cnt_zeros = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cnt_zeros != 0) break; // if there is zero 8 byte block in password, e.g. password length <32 or <64
|
||||
if (cnt_zeros == BLOCK_SIZE) break; // if there are BLOCK_SIZE byte zeros block in password, e.g. password length <32 or <64
|
||||
|
||||
for (uint8_t i = 0 + k * 16; i < 16 + k * 16; i++) {
|
||||
x.b[i % 16] = encrypted_passwords[j][i];
|
||||
// reading password's block for decrypting
|
||||
for (uint8_t byte_index = 0 + block_index * BLOCK_SIZE; byte_index < BLOCK_SIZE + block_index * BLOCK_SIZE; byte_index++) {
|
||||
// x.b[byte_index % BLOCK_SIZE] = encrypted_passwords[password_index][byte_index];
|
||||
x.b[byte_index % BLOCK_SIZE] = enc_pass.passwords[password_index * enc_pass.storage_pass_len + byte_index];
|
||||
}
|
||||
|
||||
// decrypting via Kuznechik
|
||||
kuz_decrypt_block(&key, &x);
|
||||
|
||||
for (uint8_t i = 0 + k * 16; i < 16 + k * 16; i++) {
|
||||
dec_pass[j][i] = x.b[i % 16];
|
||||
// writing decrypted password's block
|
||||
for (uint8_t byte_index = 0 + block_index * BLOCK_SIZE; byte_index < BLOCK_SIZE + block_index * BLOCK_SIZE; byte_index++) {
|
||||
decrypted_passwords[password_index][byte_index] = x.b[byte_index % BLOCK_SIZE];
|
||||
}
|
||||
|
||||
#ifdef USE_RED_CRY_DEBUG
|
||||
@@ -122,63 +161,46 @@ void decrypt_pass_kuzn(const uint8_t encrypted_passwords[STORAGE_SIZE][STORAGE_P
|
||||
}
|
||||
};
|
||||
|
||||
void send_chars_pass(uint8_t *out) {
|
||||
for (uint8_t i = 0; i < STORAGE_PASS_LEN && out[i] != 0; i++) {
|
||||
send_char((char)out[i]);
|
||||
}
|
||||
};
|
||||
|
||||
uint8_t crypto_process_record_user(uint16_t keycode, keyrecord_t *record, const uint8_t encrypted_passwords[STORAGE_SIZE][STORAGE_PASS_LEN]) {
|
||||
// function for embedding to "proccess_record_user" for adding crypto features
|
||||
uint8_t crypto_process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
if (crypto_mode) {
|
||||
switch (keycode) {
|
||||
case RED_CRY_M:
|
||||
if (record->event.pressed) {
|
||||
#ifdef USE_RED_CRY_DEBUG
|
||||
print_int(readed_key);
|
||||
red_print_int(master_key, MASTER_KEY_LEN);
|
||||
#endif
|
||||
crypto_mode = 0;
|
||||
count_char_key = 0;
|
||||
decrypt_pass_kuzn(encrypted_passwords);
|
||||
if (eeprom_inited == 1) decrypt_pass_kuzn();
|
||||
decrypted_mode = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// reading key
|
||||
return kc_to_ascii(keycode, record, readed_key, &count_char_key);
|
||||
return kc_to_ascii(keycode, record, master_key, &count_char_key);
|
||||
break;
|
||||
}
|
||||
} else if (decrypted_mode && red_menu_mode) {
|
||||
uint8_t key_return = draw_red_menu(keycode, record);
|
||||
if (key_return == RED_MENU_EXIT) {
|
||||
red_menu_mode = 0;
|
||||
} else {
|
||||
return key_return;
|
||||
}
|
||||
} else if (decrypted_mode) {
|
||||
switch (keycode) {
|
||||
case RED_PASS1:
|
||||
case RED_RST_EE:
|
||||
if (record->event.pressed) {
|
||||
send_chars_pass(dec_pass[0]);
|
||||
enc_pass.init_var[0] = 0x00;
|
||||
crypto_eeprom_init();
|
||||
}
|
||||
break;
|
||||
case RED_PASS2:
|
||||
case RED_CRY_M:
|
||||
if (record->event.pressed) {
|
||||
send_chars_pass(dec_pass[1]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS3:
|
||||
if (record->event.pressed) {
|
||||
send_chars_pass(dec_pass[2]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS4:
|
||||
if (record->event.pressed) {
|
||||
send_chars_pass(dec_pass[3]);
|
||||
}
|
||||
break;
|
||||
// if you want to add more keys for passwords, copy this `case`
|
||||
// case RED_PASSX: //change X here
|
||||
// if (record->event.pressed) {
|
||||
// send_chars_pass(dec_pass[X]); //change X here
|
||||
// }
|
||||
// break;
|
||||
case RED_RNG:
|
||||
if (record->event.pressed) {
|
||||
// TODO: change seed
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
tap_random_base64();
|
||||
}
|
||||
decrypted_mode = 0;
|
||||
decrypted_passwords = red_init_array_2d(enc_pass.storage_size, enc_pass.storage_pass_len, 0x00); // clear decrypted passwords
|
||||
master_key = red_init_array(MASTER_KEY_LEN, 0);
|
||||
}
|
||||
break;
|
||||
case RED_TEST:
|
||||
@@ -190,16 +212,89 @@ uint8_t crypto_process_record_user(uint16_t keycode, keyrecord_t *record, const
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case RED_RNG:
|
||||
if (record->event.pressed) {
|
||||
// TODO: change seed
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
tap_random_base64();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RED_MENU:
|
||||
if (record->event.pressed) {
|
||||
red_menu_mode = 1; // to enter in menu mode block code above
|
||||
}
|
||||
break;
|
||||
case RED_PASS1:
|
||||
if (record->event.pressed && enc_pass.password_count >= 1) {
|
||||
red_send_chars_pass(decrypted_passwords[0]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS2:
|
||||
if (record->event.pressed && enc_pass.password_count >= 2) {
|
||||
red_send_chars_pass(decrypted_passwords[1]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS3:
|
||||
if (record->event.pressed && enc_pass.password_count >= 3) {
|
||||
red_send_chars_pass(decrypted_passwords[2]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS4:
|
||||
if (record->event.pressed && enc_pass.password_count >= 4) {
|
||||
red_send_chars_pass(decrypted_passwords[3]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS5:
|
||||
if (record->event.pressed && enc_pass.password_count >= 5) {
|
||||
red_send_chars_pass(decrypted_passwords[4]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS6:
|
||||
if (record->event.pressed && enc_pass.password_count >= 6) {
|
||||
red_send_chars_pass(decrypted_passwords[5]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS7:
|
||||
if (record->event.pressed && enc_pass.password_count >= 7) {
|
||||
red_send_chars_pass(decrypted_passwords[6]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS8:
|
||||
if (record->event.pressed && enc_pass.password_count >= 8) {
|
||||
red_send_chars_pass(decrypted_passwords[7]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS9:
|
||||
if (record->event.pressed && enc_pass.password_count >= 9) {
|
||||
red_send_chars_pass(decrypted_passwords[8]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS10:
|
||||
if (record->event.pressed && enc_pass.password_count >= 10) {
|
||||
red_send_chars_pass(decrypted_passwords[9]);
|
||||
}
|
||||
break;
|
||||
// if you want to add more keys for passwords, copy this `case` and add new keys in red_crypto.h
|
||||
// case RED_PASSX: //change X here
|
||||
// if (record->event.pressed) {
|
||||
// red_send_chars_pass(decrypted_passwords[X]); //change X here
|
||||
// }
|
||||
// break;
|
||||
}
|
||||
} else {
|
||||
// by default
|
||||
switch (keycode) {
|
||||
case RED_CRY_M:
|
||||
if (record->event.pressed) {
|
||||
crypto_mode = 1;
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
readed_key[i] = 0;
|
||||
}
|
||||
crypto_eeprom_init();
|
||||
crypto_mode = 1; // to enter in crypto mode and unlock other keys
|
||||
// clearing readed key
|
||||
master_key = red_init_array(MASTER_KEY_LEN, 0);
|
||||
// dprintf("%d", keycode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return RED_IDLE;
|
||||
}
|
||||
+72
-14
@@ -1,16 +1,34 @@
|
||||
// Author: redlineo, romanov.pd@gmail.com
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
#include "quantum.h"
|
||||
|
||||
#ifndef RED_CRYPTO_H
|
||||
#define RED_CRYPTO_H
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
#include "quantum.h"
|
||||
|
||||
// includes of red_crypto
|
||||
#include "kc_to_ascii.h"
|
||||
#include "utils.h"
|
||||
#include "red_menu.h"
|
||||
// includes for EEPROM, tested on STM32L432xx
|
||||
#ifdef STM32L432xx
|
||||
# include "eeprom.h"
|
||||
# include "eeprom_stm32_defs.h"
|
||||
# include "eeprom_stm32_l4.h"
|
||||
#endif
|
||||
|
||||
// not tested!!!
|
||||
// #ifdef USE_RED_KUZNECHIK_128
|
||||
// #include "kuznechik_128bit.h"
|
||||
// #endif
|
||||
|
||||
#define MASTER_KEY_LEN 32
|
||||
|
||||
#ifdef USE_RED_KUZNECHIK_8
|
||||
# include "kuznechik_8bit.h"
|
||||
# ifdef USE_SHA256_KEY
|
||||
# undef MASTER_KEY_LEN
|
||||
# define MASTER_KEY_LEN 128
|
||||
# include "sha256.h"
|
||||
# endif
|
||||
#endif
|
||||
@@ -20,21 +38,21 @@
|
||||
#endif
|
||||
|
||||
#define MAX_KEY_LEN 128
|
||||
#define BLOCK_SIZE 16
|
||||
|
||||
# ifndef STORAGE_SIZE
|
||||
# define STORAGE_SIZE 4
|
||||
#ifndef INIT_STORAGE_SIZE
|
||||
# define INIT_STORAGE_SIZE 5
|
||||
#endif
|
||||
|
||||
# ifdef STORAGE_PASS_LEN
|
||||
# if STORAGE_PASS_LEN % 16 != 0
|
||||
# error Storage password length must be a multiple of 16
|
||||
# endif
|
||||
#ifndef INIT_STORAGE_PASS_LEN
|
||||
# define INIT_STORAGE_PASS_LEN 64
|
||||
#endif
|
||||
|
||||
# ifndef STORAGE_PASS_LEN
|
||||
# define STORAGE_PASS_LEN 64
|
||||
#ifdef INIT_STORAGE_PASS_LEN
|
||||
# if (INIT_STORAGE_PASS_LEN % 16 != 0)
|
||||
# error "Password length must be multiply of 16 (16,32,64...)"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// example for encrypted 64 byte password
|
||||
// const uint8_t red_enc_pass[STORAGE_SIZE][STORAGE_PASS_LEN] = {
|
||||
@@ -46,11 +64,51 @@
|
||||
|
||||
enum red_crypto_keys {
|
||||
RED_CRY_M = SAFE_RANGE + 0x80, // added safe range offset
|
||||
RED_MENU,
|
||||
RED_RNG,
|
||||
RED_TEST,
|
||||
RED_PASS1, RED_PASS2, RED_PASS3, RED_PASS4, RED_PASS5, RED_PASS6, RED_PASS7, RED_PASS8, RED_PASS9, RED_PASS10, RED_PASS11, RED_PASS12
|
||||
RED_LOCK, // TODO: add autolock feature
|
||||
RED_RST_EE, // resetting EEPROM by clearing RED bytes
|
||||
RED_PASS1,
|
||||
RED_PASS2,
|
||||
RED_PASS3,
|
||||
RED_PASS4,
|
||||
RED_PASS5,
|
||||
RED_PASS6,
|
||||
RED_PASS7,
|
||||
RED_PASS8,
|
||||
RED_PASS9,
|
||||
RED_PASS10,
|
||||
};
|
||||
|
||||
uint8_t crypto_process_record_user(uint16_t keycode, keyrecord_t *record, const uint8_t encrypted_passwords[STORAGE_SIZE][STORAGE_PASS_LEN]);
|
||||
enum red_crypto_states {
|
||||
RED_IDLE = 0,
|
||||
RED_KEY_READ,
|
||||
RED_MENU_EXIT,
|
||||
};
|
||||
|
||||
// uint8_t storage_size = INIT_STORAGE_SIZE;
|
||||
// uint8_t storage_pass_len = INIT_STORAGE_PASS_LEN;
|
||||
#define EEPROM_PASS_OFFSET 3 + 3 + 1 + 1 + 4 + 1
|
||||
#define STORAGE_SIZE (EEPROM_PASS_OFFSET + INIT_STORAGE_SIZE * INIT_STORAGE_PASS_LEN)
|
||||
|
||||
typedef union {
|
||||
uint8_t raw[STORAGE_SIZE];
|
||||
struct {
|
||||
uint8_t init_var[3]; // if in eeprom is bytes "RED", then it's not first flash or first power-on, or in eeprom is old red_crypto
|
||||
uint8_t version[3]; // red_crypto library version
|
||||
uint8_t storage_size;
|
||||
uint8_t storage_pass_len;
|
||||
uint32_t memory_usage;
|
||||
uint8_t password_count;
|
||||
uint8_t passwords[INIT_STORAGE_SIZE * INIT_STORAGE_PASS_LEN];
|
||||
};
|
||||
} red_crypto_storage_eeprom;
|
||||
|
||||
red_crypto_storage_eeprom enc_pass;
|
||||
|
||||
uint8_t crypto_process_record_user(uint16_t keycode, keyrecord_t *record);
|
||||
uint8_t *encrypt_pass_kuzn(const uint8_t *new_pass, const uint8_t new_pass_length, const uint8_t password_index);
|
||||
void crypto_eeprom_init(void);
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,9 @@ SRC += red_crypto/sha256.c
|
||||
SRC += red_crypto/aes.c
|
||||
SRC += red_crypto/kuznechik_8bit.c
|
||||
SRC += red_crypto/kc_to_ascii.c
|
||||
SRC += red_crypto/utils.c
|
||||
SRC += red_crypto/red_menu.c
|
||||
|
||||
# SRC += red_crypto/kuznechik_128bit.c # you can't include this, because you may not have ARMv8 and upper, check this
|
||||
# TODO: do something like this:
|
||||
# ifneq ($(findstring HAL_USE_CRY TRUE,$(HALCONF)),)
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
#include "red_menu.h"
|
||||
|
||||
// clang-format off
|
||||
enum menu_options {
|
||||
EXIT,
|
||||
SHOW_PASS_NAMES,
|
||||
SHOW_MEMORY_USAGE,
|
||||
CHANGE_MASTER_KEY,
|
||||
CHANGE_PASS_IN_STORAGE,
|
||||
CHANGE_PASS_NAME,
|
||||
ADD_NEW_PASS,
|
||||
SAVE_NEW_PASS,
|
||||
READING_PASS,
|
||||
READ_USER_CHOICE,
|
||||
SHOW_MAIN_MENU,
|
||||
WAIT_PASS_INDEX
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
uint8_t readed_option[1] = {SHOW_MAIN_MENU};
|
||||
uint8_t count_readed = 0;
|
||||
uint8_t return_key = 0;
|
||||
uint8_t password_index = 255;
|
||||
uint8_t *enc_pass_new;
|
||||
|
||||
uint8_t *readed_key_new;
|
||||
uint8_t count_char_key_new = 0;
|
||||
|
||||
// read new key
|
||||
uint8_t read_new_key(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case KC_ENTER:
|
||||
readed_option[0] = SAVE_NEW_PASS;
|
||||
return RED_KEY_READ;
|
||||
break;
|
||||
default:
|
||||
if (count_char_key_new + 1 == enc_pass.storage_pass_len) {
|
||||
readed_option[0] = SAVE_NEW_PASS;
|
||||
send_string("Length limit!\n");
|
||||
// TODO: done this feature
|
||||
}
|
||||
return kc_to_ascii(keycode, record, readed_key_new, &count_char_key_new);
|
||||
break;
|
||||
}
|
||||
return RED_IDLE;
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
// return values
|
||||
// 0 idle
|
||||
// 1 get key input
|
||||
// 2 exit menu
|
||||
uint8_t draw_red_menu(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (readed_option[0]) {
|
||||
case EXIT:
|
||||
readed_option[0] = SHOW_MAIN_MENU;
|
||||
return RED_MENU_EXIT;
|
||||
break;
|
||||
case READ_USER_CHOICE: {
|
||||
return_key = kc_to_ascii(keycode, record, readed_option, &count_readed);
|
||||
count_readed = 0;
|
||||
if (readed_option[0] == ASCII_LOW_0) {
|
||||
readed_option[0] = EXIT;
|
||||
}
|
||||
if (readed_option[0] == ASCII_LOW_1) {
|
||||
readed_option[0] = SHOW_PASS_NAMES;
|
||||
}
|
||||
if (readed_option[0] == ASCII_LOW_2) {
|
||||
readed_option[0] = SHOW_MEMORY_USAGE;
|
||||
}
|
||||
if (readed_option[0] == ASCII_LOW_3) {
|
||||
readed_option[0] = CHANGE_MASTER_KEY;
|
||||
}
|
||||
if (readed_option[0] == ASCII_LOW_4) {
|
||||
readed_option[0] = CHANGE_PASS_IN_STORAGE;
|
||||
}
|
||||
if (readed_option[0] == ASCII_LOW_5) {
|
||||
readed_option[0] = CHANGE_PASS_NAME;
|
||||
}
|
||||
if (readed_option[0] == ASCII_LOW_6) {
|
||||
readed_option[0] = ADD_NEW_PASS;
|
||||
}
|
||||
if (return_key == RED_KEY_READ) {
|
||||
readed_key_new = red_init_array(MAX_KEY_LEN, 0x00); // init or reinit readed keys
|
||||
count_char_key_new = 0; // init or reinit counted keys
|
||||
CLEAR_MENU_MACROS;
|
||||
return RED_KEY_READ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SHOW_PASS_NAMES: // TODO
|
||||
break;
|
||||
case SHOW_MEMORY_USAGE: // TODO
|
||||
break;
|
||||
case CHANGE_MASTER_KEY: // TODO
|
||||
break;
|
||||
case CHANGE_PASS_IN_STORAGE:
|
||||
send_string("Which one? Write index in hex [0-9a-f]: "); // now you can change first 16 passwords on the fly
|
||||
// to read more, I need read keys as integers, or bytes
|
||||
readed_option[0] = WAIT_PASS_INDEX;
|
||||
// send_string("Which one? [1-");
|
||||
// send_byte(enc_pass.password_count);
|
||||
// send_string("]: ");
|
||||
break;
|
||||
case WAIT_PASS_INDEX:
|
||||
return_key = kc_to_ascii(keycode, record, readed_option, &count_readed);
|
||||
count_readed = 0;
|
||||
uint8_t pass_ind_upd = 0; // for checking right translation from keycode to num
|
||||
if (return_key == RED_KEY_READ) {
|
||||
if (readed_option[0] >= ASCII_LOW_0 && readed_option[0] <= ASCII_LOW_9) {
|
||||
password_index = readed_option[0] - 0x30;
|
||||
pass_ind_upd++;
|
||||
} else if (readed_option[0] >= ASCII_LOW_A && readed_option[0] <= ASCII_LOW_F) {
|
||||
password_index = readed_option[0] - 0x61 + 10;
|
||||
pass_ind_upd++;
|
||||
}
|
||||
if (pass_ind_upd == 0 || password_index >= enc_pass.password_count) {
|
||||
send_string("\nWrong index! Try again!\n");
|
||||
readed_option[0] = CHANGE_PASS_IN_STORAGE;
|
||||
} else {
|
||||
readed_option[0] = READING_PASS;
|
||||
send_string("\nWrite new password. Tap `Enter` for confirm\n");
|
||||
}
|
||||
return RED_KEY_READ;
|
||||
}
|
||||
break;
|
||||
case CHANGE_PASS_NAME: // TODO
|
||||
break;
|
||||
case SAVE_NEW_PASS:
|
||||
enc_pass_new = (uint8_t *)malloc(sizeof(uint8_t) * enc_pass.storage_pass_len);
|
||||
enc_pass_new = encrypt_pass_kuzn(readed_key_new, count_char_key_new, password_index);
|
||||
count_char_key_new = 0;
|
||||
if (password_index == 255) {
|
||||
for (uint8_t new_pass_index = 0; new_pass_index < enc_pass.storage_pass_len; new_pass_index++) {
|
||||
enc_pass.passwords[enc_pass.password_count * enc_pass.storage_pass_len + new_pass_index] = enc_pass_new[new_pass_index];
|
||||
}
|
||||
enc_pass.password_count++;
|
||||
} else {
|
||||
for (uint8_t new_pass_index = 0; new_pass_index < enc_pass.storage_pass_len; new_pass_index++) {
|
||||
enc_pass.passwords[password_index * enc_pass.storage_pass_len + new_pass_index] = enc_pass_new[new_pass_index];
|
||||
}
|
||||
}
|
||||
// eeconfig_update_user_datablock(enc_pass.raw);
|
||||
red_write_to_storage();
|
||||
send_string("Successful adding new key on keycode RED_PASS");
|
||||
if (password_index == 255) {
|
||||
send_byte(enc_pass.password_count);
|
||||
} else {
|
||||
send_byte(password_index);
|
||||
password_index = 255;
|
||||
}
|
||||
send_string("\n");
|
||||
send_string(SS_DELAY(1000));
|
||||
CLEAR_MENU_MACROS;
|
||||
send_string("Press `Enter` ");
|
||||
readed_option[0] = SHOW_MAIN_MENU;
|
||||
break;
|
||||
case READING_PASS:
|
||||
return read_new_key(keycode, record);
|
||||
break;
|
||||
case ADD_NEW_PASS:
|
||||
if (enc_pass.password_count == enc_pass.storage_size) {
|
||||
send_string("Limit error\n");
|
||||
readed_option[0] = SHOW_MAIN_MENU;
|
||||
} else {
|
||||
send_string("Write new password. Tap `Enter` for confirm\n");
|
||||
readed_option[0] = READING_PASS;
|
||||
}
|
||||
break;
|
||||
default: // SHOW_MAIN_MENU
|
||||
CLEAR_MENU_MACROS;
|
||||
send_string("RED_CRYPTO MENU:\n0-EXIT\nX-Show password's names\nX-Show memory usage\nX-Change master key\n4-Change password in storage\nX-Change password's name\n6-Add new password\n");
|
||||
send_string("Choose option(0-6): ");
|
||||
readed_option[0] = READ_USER_CHOICE;
|
||||
break;
|
||||
}
|
||||
return RED_IDLE;
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
#include "quantum.h"
|
||||
|
||||
#ifndef RED_MENU_H
|
||||
# define RED_MENU_H
|
||||
|
||||
# include "kc_to_ascii.h"
|
||||
# include "red_crypto.h"
|
||||
|
||||
#define CLEAR_MENU_MACROS send_string(SS_DOWN(X_LCTL) SS_DOWN(X_A) SS_UP(X_LCTL) SS_UP(X_A) SS_TAP(X_BACKSPACE))
|
||||
|
||||
uint8_t draw_red_menu(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "utils.h"
|
||||
|
||||
void red_print_chars(uint8_t *c) {
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
if (c[i] == 0x00) break;
|
||||
dprintf("%c", c[i]);
|
||||
}
|
||||
dprintf("\n");
|
||||
};
|
||||
|
||||
void red_print_int(uint8_t *c, uint8_t len) {
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
dprintf("%d", c[i]);
|
||||
}
|
||||
dprintf("\n");
|
||||
};
|
||||
|
||||
void red_print_hex(uint8_t *h) {
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
dprintf("%x ", h[i]);
|
||||
}
|
||||
dprintf("\n");
|
||||
};
|
||||
|
||||
size_t red_min_len(size_t a, size_t b) {
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
void red_send_chars_pass(uint8_t *out) {
|
||||
for (uint8_t i = 0; i < INIT_STORAGE_PASS_LEN && out[i] != 0; i++) {
|
||||
send_char((char)out[i]);
|
||||
}
|
||||
};
|
||||
|
||||
uint8_t *red_init_array(uint8_t len, uint8_t val) {
|
||||
uint8_t *arr = (uint8_t *)malloc(sizeof(uint8_t) * len);
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
arr[i] = val;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
uint8_t **red_init_array_2d(uint8_t len_row, uint8_t len_col, uint8_t val) {
|
||||
uint8_t **arr = (uint8_t **)malloc(sizeof(uint8_t *) * len_row);
|
||||
for (uint8_t i = 0; i < len_row; i++) {
|
||||
arr[i] = (uint8_t *)malloc(sizeof(uint8_t) * len_col);
|
||||
for (uint8_t j = 0; j < len_col; j++) {
|
||||
arr[i][j] = val;
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
// count printable symbols of ASCII in string with safety check of max length
|
||||
uint8_t red_strlen_printable(uint8_t *str_printable, uint8_t max_len) {
|
||||
uint8_t result = 0;
|
||||
while (result < max_len && *str_printable != '\0') {
|
||||
result++;
|
||||
str_printable++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef USE_SHA256_KEY
|
||||
// hashing string to 32byte with sha256
|
||||
uint8_t *hashing_string(uint8_t *str_to_hash) {
|
||||
SHA256_CTX ctx;
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, str_to_hash, red_strlen_printable(str_to_hash, MAX_KEY_LEN));
|
||||
// BYTE result_key[SHA256_BLOCK_SIZE];
|
||||
BYTE *result_key = red_init_array(SHA256_BLOCK_SIZE, 0x00);
|
||||
sha256_final(&ctx, result_key);
|
||||
# ifdef USE_RED_CRY_DEBUG
|
||||
red_print_hex(result_key);
|
||||
# endif
|
||||
return result_key;
|
||||
}
|
||||
#endif
|
||||
|
||||
// EEPROM utils
|
||||
|
||||
void red_write_to_storage(void) {
|
||||
// uint8_t res = 0;
|
||||
for (uint16_t raw_index = 0; raw_index < STORAGE_SIZE; raw_index++) {
|
||||
// res = EEPROM_WriteDataByte(0x0000 + raw_index, enc_pass.raw[raw_index]);
|
||||
EEPROM_WriteDataByte(0x0040 + raw_index, enc_pass.raw[raw_index]);
|
||||
}
|
||||
// return res;
|
||||
}
|
||||
|
||||
void red_read_from_storage(void) {
|
||||
for (uint16_t raw_index = 0; raw_index < STORAGE_SIZE; raw_index++) {
|
||||
enc_pass.raw[raw_index] = EEPROM_ReadDataByte(0x0040 + raw_index);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef RED_UTILS_H
|
||||
#define RED_UTILS_H
|
||||
#include QMK_KEYBOARD_H
|
||||
#include "quantum.h"
|
||||
#include "red_crypto.h"
|
||||
|
||||
void red_print_chars(uint8_t *c);
|
||||
|
||||
void red_print_int(uint8_t *c, uint8_t len);
|
||||
|
||||
void red_print_hex(uint8_t *h);
|
||||
|
||||
size_t red_min_len(size_t a, size_t b);
|
||||
|
||||
void red_send_chars_pass(uint8_t *out);
|
||||
|
||||
uint8_t *hashing_string(uint8_t *str_to_hash);
|
||||
|
||||
uint8_t *red_init_array(uint8_t len, uint8_t val);
|
||||
|
||||
uint8_t **red_init_array_2d(uint8_t len_row, uint8_t len_col, uint8_t val);
|
||||
|
||||
void red_write_to_storage(void);
|
||||
|
||||
void red_read_from_storage(void);
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user