init commit of lib
This commit is contained in:
1 parent
bc3358be39
commit
bae7d1ced4
13 files changed
+2787
No files matched your search
@@ -0,0 +1,5 @@
|
||||
# RED_CRYPTO
|
||||
|
||||
## Description
|
||||
|
||||
Password manager for (almost) any QMK keyboards with AES256, Kuznechik (Russian GOST cipher), SHA256.
|
||||
@@ -0,0 +1,125 @@
|
||||
/*********************************************************************
|
||||
* Filename: aes.h
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Defines the API for the corresponding AES implementation.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef AES_H
|
||||
#define AES_H
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stddef.h>
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
#define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time
|
||||
|
||||
/**************************** DATA TYPES ****************************/
|
||||
typedef unsigned char BYTE; // 8-bit byte
|
||||
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
|
||||
|
||||
/*********************** FUNCTION DECLARATIONS **********************/
|
||||
///////////////////
|
||||
// AES
|
||||
///////////////////
|
||||
// Key setup must be done before any AES en/de-cryption functions can be used.
|
||||
void aes_key_setup(const BYTE key[], // The key, must be 128, 192, or 256 bits
|
||||
WORD w[], // Output key schedule to be used later
|
||||
int keysize); // Bit length of the key, 128, 192, or 256
|
||||
|
||||
void aes_encrypt(const BYTE in[], // 16 bytes of plaintext
|
||||
BYTE out[], // 16 bytes of ciphertext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize); // Bit length of the key, 128, 192, or 256
|
||||
|
||||
void aes_decrypt(const BYTE in[], // 16 bytes of ciphertext
|
||||
BYTE out[], // 16 bytes of plaintext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize); // Bit length of the key, 128, 192, or 256
|
||||
|
||||
///////////////////
|
||||
// AES - CBC
|
||||
///////////////////
|
||||
int aes_encrypt_cbc(const BYTE in[], // Plaintext
|
||||
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
||||
BYTE out[], // Ciphertext, same length as plaintext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
// Only output the CBC-MAC of the input.
|
||||
int aes_encrypt_cbc_mac(const BYTE in[], // plaintext
|
||||
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
||||
BYTE out[], // Output MAC
|
||||
const WORD key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
///////////////////
|
||||
// AES - CTR
|
||||
///////////////////
|
||||
void increment_iv(BYTE iv[], // Must be a multiple of AES_BLOCK_SIZE
|
||||
int counter_size); // Bytes of the IV used for counting (low end)
|
||||
|
||||
void aes_encrypt_ctr(const BYTE in[], // Plaintext
|
||||
size_t in_len, // Any byte length
|
||||
BYTE out[], // Ciphertext, same length as plaintext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
void aes_decrypt_ctr(const BYTE in[], // Ciphertext
|
||||
size_t in_len, // Any byte length
|
||||
BYTE out[], // Plaintext, same length as ciphertext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
///////////////////
|
||||
// AES - CCM
|
||||
///////////////////
|
||||
// Returns True if the input parameters do not violate any constraint.
|
||||
int aes_encrypt_ccm(const BYTE plaintext[], // IN - Plaintext.
|
||||
WORD plaintext_len, // IN - Plaintext length.
|
||||
const BYTE associated_data[], // IN - Associated Data included in authentication, but not encryption.
|
||||
unsigned short associated_data_len, // IN - Associated Data length in bytes.
|
||||
const BYTE nonce[], // IN - The Nonce to be used for encryption.
|
||||
unsigned short nonce_len, // IN - Nonce length in bytes.
|
||||
BYTE ciphertext[], // OUT - Ciphertext, a concatination of the plaintext and the MAC.
|
||||
WORD *ciphertext_len, // OUT - The length of the ciphertext, always plaintext_len + mac_len.
|
||||
WORD mac_len, // IN - The desired length of the MAC, must be 4, 6, 8, 10, 12, 14, or 16.
|
||||
const BYTE key[], // IN - The AES key for encryption.
|
||||
int keysize); // IN - The length of the key in bits. Valid values are 128, 192, 256.
|
||||
|
||||
// Returns True if the input parameters do not violate any constraint.
|
||||
// Use mac_auth to ensure decryption/validation was preformed correctly.
|
||||
// If authentication does not succeed, the plaintext is zeroed out. To overwride
|
||||
// this, call with mac_auth = NULL. The proper proceedure is to decrypt with
|
||||
// authentication enabled (mac_auth != NULL) and make a second call to that
|
||||
// ignores authentication explicitly if the first call failes.
|
||||
int aes_decrypt_ccm(const BYTE ciphertext[], // IN - Ciphertext, the concatination of encrypted plaintext and MAC.
|
||||
WORD ciphertext_len, // IN - Ciphertext length in bytes.
|
||||
const BYTE assoc[], // IN - The Associated Data, required for authentication.
|
||||
unsigned short assoc_len, // IN - Associated Data length in bytes.
|
||||
const BYTE nonce[], // IN - The Nonce to use for decryption, same one as for encryption.
|
||||
unsigned short nonce_len, // IN - Nonce length in bytes.
|
||||
BYTE plaintext[], // OUT - The plaintext that was decrypted. Will need to be large enough to hold ciphertext_len - mac_len.
|
||||
WORD *plaintext_len, // OUT - Length in bytes of the output plaintext, always ciphertext_len - mac_len .
|
||||
WORD mac_len, // IN - The length of the MAC that was calculated.
|
||||
int *mac_auth, // OUT - TRUE if authentication succeeded, FALSE if it did not. NULL pointer will ignore the authentication.
|
||||
const BYTE key[], // IN - The AES key for decryption.
|
||||
int keysize); // IN - The length of the key in BITS. Valid values are 128, 192, 256.
|
||||
|
||||
///////////////////
|
||||
// Test functions
|
||||
///////////////////
|
||||
#ifdef TEST_FUNCTIONS_ENABLED
|
||||
void exec_aes_test(void);
|
||||
int aes_ecb_test(void);
|
||||
int aes_cbc_test(void);
|
||||
int aes_ctr_test(void);
|
||||
int aes_ccm_test(void);
|
||||
#endif
|
||||
|
||||
#endif // AES_H
|
||||
@@ -0,0 +1,44 @@
|
||||
/****************************** ASCII TABLE ******************************/
|
||||
|
||||
#define ASCII_NON_PRINTABLE 0x00
|
||||
#define DDD 0x00
|
||||
#define ASCII_SPACE 0x20 // ' '
|
||||
#define ASCII_UP_1 0x21 // !
|
||||
#define ASCII_UP_QUOTE 0x22 // "
|
||||
#define ASCII_UP_3 0x23 // #
|
||||
#define ASCII_UP_4 0x24 // $
|
||||
#define ASCII_UP_5 0x25 // %
|
||||
#define ASCII_UP_7 0x26 // &
|
||||
#define ASCII_LOW_QUOTE 0x27 // '
|
||||
#define ASCII_LEFT_BRACKET 0x28 // (
|
||||
#define ASCII_RIGHT_BRACKET 0x29 // )
|
||||
#define ASCII_UP_8 0x2A // *
|
||||
#define ASCII_UP_EQUAL 0x2B // +
|
||||
#define ASCII_LOW_COMMA 0x2C // ,
|
||||
#define ASCII_LOW_MINUS 0x2D // -
|
||||
#define ASCII_LOW_DOT 0x2E // .
|
||||
#define ASCII_LOW_SLASH 0x2F // /
|
||||
#define ASCII_LOW_0 0x30 // 0
|
||||
#define ASCII_LOW_1 0x31 // 1
|
||||
#define ASCII_LOW_2 0x32 // 2
|
||||
#define ASCII_LOW_3 0x33 // 3
|
||||
#define ASCII_LOW_4 0x34 // 4
|
||||
#define ASCII_LOW_5 0x35 // 5
|
||||
#define ASCII_LOW_6 0x36 // 6
|
||||
#define ASCII_LOW_7 0x37 // 7
|
||||
#define ASCII_LOW_8 0x38 // 8
|
||||
#define ASCII_LOW_9 0x39 // 9
|
||||
#define ASCII_UP_SEMICOLON 0x3A // :
|
||||
#define ASCII_LOW_SEMICOLON 0x3B // ;
|
||||
|
||||
|
||||
|
||||
|
||||
#define ASCII_LOW_EQUAL 0x3D // =
|
||||
|
||||
|
||||
#define ASCII_UP_2 0x40 // @
|
||||
|
||||
|
||||
#define ASCII_UP_6 0x5E // ^
|
||||
#define ASCII_UP_MINUS 0x5F // _
|
||||
@@ -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
|
||||
@@ -0,0 +1,337 @@
|
||||
// kuznechik.c
|
||||
// 04-Jan-15 Markku-Juhani O. Saarinen <mjos@iki.fi>
|
||||
|
||||
// This is the basic non-optimized 8-bit "readble" version of the cipher.
|
||||
// Conforms to included doc/GOSTR-bsh.pdf file, which has an internal
|
||||
// date of September 2, 2014.
|
||||
|
||||
#include "kuznechik_8bit.h"
|
||||
|
||||
// The S-Box from section 5.1.1
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
// poly multiplication mod p(x) = x^8 + x^7 + x^6 + x + 1
|
||||
// totally not constant time
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// a no-op
|
||||
|
||||
void kuz_init()
|
||||
{
|
||||
;
|
||||
}
|
||||
// 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;
|
||||
|
||||
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])
|
||||
{
|
||||
kuz_set_encrypt_key(kuz, key);
|
||||
}
|
||||
|
||||
// encrypt a block - 8 bit way
|
||||
|
||||
void kuz_encrypt_block(kuz_key_t *key, void *blk)
|
||||
{
|
||||
int i, j;
|
||||
w128_t x;
|
||||
|
||||
x.q[0] = ((uint64_t *) blk)[0];
|
||||
x.q[1] = ((uint64_t *) blk)[1];
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
|
||||
x.q[0] ^= key->k[i].q[0];
|
||||
x.q[1] ^= key->k[i].q[1];
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
x.b[j] = kuz_pi[x.b[j]];
|
||||
kuz_l(&x);
|
||||
}
|
||||
((uint64_t *) blk)[0] = x.q[0] ^ key->k[9].q[0];
|
||||
((uint64_t *) blk)[1] = x.q[1] ^ key->k[9].q[1];
|
||||
}
|
||||
|
||||
// decrypt a block - 8 bit way
|
||||
|
||||
void kuz_decrypt_block(kuz_key_t *key, void *blk)
|
||||
{
|
||||
int i, j;
|
||||
w128_t x;
|
||||
|
||||
x.q[0] = ((uint64_t *) blk)[0] ^ key->k[9].q[0];
|
||||
x.q[1] = ((uint64_t *) blk)[1] ^ key->k[9].q[1];
|
||||
|
||||
for (i = 8; i >= 0; i--) {
|
||||
|
||||
kuz_l_inv(&x);
|
||||
for (j = 0; j < 16; j++)
|
||||
x.b[j] = kuz_pi_inv[x.b[j]];
|
||||
|
||||
x.q[0] ^= key->k[i].q[0];
|
||||
x.q[1] ^= key->k[i].q[1];
|
||||
}
|
||||
((uint64_t *) blk)[0] = x.q[0];
|
||||
((uint64_t *) blk)[1] = x.q[1];
|
||||
}
|
||||
|
||||
// print w128
|
||||
void print_w128(w128_t *x)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
printf(" %02X", x->b[i]);
|
||||
printf("\n");
|
||||
};
|
||||
|
||||
|
||||
/*********************** 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
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
#include "red_crypto.h"
|
||||
|
||||
|
||||
|
||||
uint8_t dec_pass[2][16] = {{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 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};
|
||||
|
||||
uint8_t count_char_key = 0;
|
||||
|
||||
uint8_t crypto_mode = 0;
|
||||
|
||||
void print_chars_w128(w128_t *x) {
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if (x->b[i] == 0x00) break;
|
||||
printf("%c", x->b[i]);
|
||||
}
|
||||
dprintf("\n");
|
||||
};
|
||||
|
||||
void print_chars(uint8_t *c) {
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
if (c[i] == 0x00) break;
|
||||
printf("%c", c[i]);
|
||||
}
|
||||
dprintf("\n");
|
||||
};
|
||||
|
||||
void decrypt_pass_kuzn(const uint8_t encrypted_passwords[2][16]) {
|
||||
kuz_key_t key;
|
||||
w128_t x;
|
||||
|
||||
kuz_set_decrypt_key(&key, readed_key);
|
||||
for (uint8_t j = 0; j < 2; j++) {
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
x.b[i] = encrypted_passwords[j][i];
|
||||
}
|
||||
kuz_decrypt_block(&key, &x);
|
||||
|
||||
dprintf("decrypted\t=");
|
||||
print_w128(&x);
|
||||
print_chars_w128(&x);
|
||||
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
dec_pass[j][i] = x.b[i];
|
||||
}
|
||||
}
|
||||
|
||||
// kuz_set_encrypt_key(&key,readed_key);
|
||||
// for (uint8_t i=0; i<16; i++) {
|
||||
// x.b[i] = pass[i];
|
||||
// }
|
||||
// kuz_encrypt_block(&key,&x);
|
||||
// printf("encrypted\t="); print_w128(&x);
|
||||
// print_chars_w128(&x);
|
||||
};
|
||||
|
||||
void send_chars_pass(uint8_t *out) {
|
||||
for (uint8_t i = 0; i < 16 && out[i] != 0; i++) {
|
||||
send_char((char)out[i]);
|
||||
}
|
||||
};
|
||||
|
||||
void crypto_process_record_user(uint16_t keycode, keyrecord_t *record, const uint8_t encrypted_passwords[2][16]) {
|
||||
if (crypto_mode) {
|
||||
switch (keycode) {
|
||||
// TODO: write all ASCII printable keys
|
||||
// may be not printable, because we can use any byte of ASCII with QMK, HA-HA
|
||||
// transcode_keycode_to_ascii();
|
||||
case KC_1:
|
||||
if (record->event.pressed) {
|
||||
readed_key[count_char_key] = ASCII_LOW_1;
|
||||
count_char_key++;
|
||||
}
|
||||
break;
|
||||
case GET_PASS:
|
||||
if (record->event.pressed) {
|
||||
crypto_mode = 0;
|
||||
count_char_key = 0;
|
||||
decrypt_pass_kuzn(encrypted_passwords);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (keycode) {
|
||||
case RED_PASS1:
|
||||
if (record->event.pressed) {
|
||||
send_chars_pass(dec_pass[0]);
|
||||
// SEND_STRING(dec_pass[0]);
|
||||
}
|
||||
break;
|
||||
case RED_PASS2:
|
||||
if (record->event.pressed) {
|
||||
send_chars_pass(dec_pass[1]);
|
||||
// SEND_STRING(dec_pass[1]);
|
||||
}
|
||||
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_TEST:
|
||||
#ifdef TEST_FUNCTIONS_ENABLED
|
||||
if (record->event.pressed) {
|
||||
exec_sha256_test();
|
||||
exec_kuznechik_test();
|
||||
exec_aes_test();
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case GET_PASS:
|
||||
if (record->event.pressed) {
|
||||
crypto_mode = 1;
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
readed_key[i] = 0;
|
||||
}
|
||||
dprintf("%d", keycode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
#include "quantum.h"
|
||||
|
||||
|
||||
#ifndef RED_CRYPTO_H
|
||||
#define RED_CRYPTO_H
|
||||
|
||||
#include "ascii_table.c"
|
||||
|
||||
// #ifdef USE_RED_KUZNECHIK_128
|
||||
// #include "kuznechik_128bit.h"
|
||||
// #endif
|
||||
#ifdef USE_RED_KUZNECHIK_8
|
||||
#include "kuznechik_8bit.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_RED_AES_256
|
||||
#include "aes.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_RED_SHA_256
|
||||
#include "sha256.h"
|
||||
#endif
|
||||
|
||||
|
||||
enum red_crypto_keys {
|
||||
GET_PASS = SAFE_RANGE,
|
||||
RED_PASS1,
|
||||
RED_PASS2,
|
||||
RED_RNG,
|
||||
RED_TEST
|
||||
};
|
||||
|
||||
void crypto_process_record_user(uint16_t keycode, keyrecord_t *record, const uint8_t encrypted_passwords[2][16]);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# make config rules for red_crypto
|
||||
SRC += red_crypto/red_crypto.c
|
||||
|
||||
SRC += red_crypto/sha256.c
|
||||
SRC += red_crypto/aes.c
|
||||
SRC += red_crypto/kuznechik_8bit.c
|
||||
SRC += red_crypto/ascii_table.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)),)
|
||||
@@ -0,0 +1,202 @@
|
||||
/*********************************************************************
|
||||
* Filename: sha256.c
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Implementation of the SHA-256 hashing algorithm.
|
||||
SHA-256 is one of the three algorithms in the SHA2
|
||||
specification. The others, SHA-384 and SHA-512, are not
|
||||
offered in this implementation.
|
||||
Algorithm specification can be found here:
|
||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
|
||||
This implementation uses little endian byte order.
|
||||
*********************************************************************/
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include "sha256.h"
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
|
||||
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
|
||||
|
||||
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
|
||||
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
|
||||
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
|
||||
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
|
||||
|
||||
/**************************** VARIABLES *****************************/
|
||||
static const WORD k[64] = {
|
||||
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
|
||||
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
|
||||
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
|
||||
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
|
||||
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
|
||||
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
|
||||
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
|
||||
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||
};
|
||||
|
||||
/*********************** FUNCTION DEFINITIONS ***********************/
|
||||
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
|
||||
{
|
||||
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
|
||||
|
||||
for (i = 0, j = 0; i < 16; ++i, j += 4)
|
||||
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
|
||||
for ( ; i < 64; ++i)
|
||||
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
|
||||
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];
|
||||
|
||||
for (i = 0; i < 64; ++i) {
|
||||
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
|
||||
t2 = EP0(a) + MAJ(a,b,c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void sha256_init(SHA256_CTX *ctx)
|
||||
{
|
||||
ctx->datalen = 0;
|
||||
ctx->bitlen = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
|
||||
{
|
||||
WORD i;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
ctx->data[ctx->datalen] = data[i];
|
||||
ctx->datalen++;
|
||||
if (ctx->datalen == 64) {
|
||||
sha256_transform(ctx, ctx->data);
|
||||
ctx->bitlen += 512;
|
||||
ctx->datalen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_final(SHA256_CTX *ctx, BYTE hash[])
|
||||
{
|
||||
WORD i;
|
||||
|
||||
i = ctx->datalen;
|
||||
|
||||
// Pad whatever data is left in the buffer.
|
||||
if (ctx->datalen < 56) {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 56)
|
||||
ctx->data[i++] = 0x00;
|
||||
}
|
||||
else {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 64)
|
||||
ctx->data[i++] = 0x00;
|
||||
sha256_transform(ctx, ctx->data);
|
||||
memset(ctx->data, 0, 56);
|
||||
}
|
||||
|
||||
// Append to the padding the total message's length in bits and transform.
|
||||
ctx->bitlen += ctx->datalen * 8;
|
||||
ctx->data[63] = ctx->bitlen;
|
||||
ctx->data[62] = ctx->bitlen >> 8;
|
||||
ctx->data[61] = ctx->bitlen >> 16;
|
||||
ctx->data[60] = ctx->bitlen >> 24;
|
||||
ctx->data[59] = ctx->bitlen >> 32;
|
||||
ctx->data[58] = ctx->bitlen >> 40;
|
||||
ctx->data[57] = ctx->bitlen >> 48;
|
||||
ctx->data[56] = ctx->bitlen >> 56;
|
||||
sha256_transform(ctx, ctx->data);
|
||||
|
||||
// Since this implementation uses little endian byte ordering and SHA uses big endian,
|
||||
// reverse all the bytes when copying the final state to the output hash.
|
||||
for (i = 0; i < 4; ++i) {
|
||||
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************** TEST FUNCTION DEFINITIONS ***********************/
|
||||
#ifdef TEST_FUNCTIONS_ENABLED
|
||||
inline size_t u_strlen(const unsigned char * array)
|
||||
{
|
||||
return strlen((const char*)array);
|
||||
}
|
||||
|
||||
void exec_sha256_test(void)
|
||||
{
|
||||
BYTE text1[] = {"abc"};
|
||||
BYTE text2[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
|
||||
BYTE text3[] = {"aaaaaaaaaa"};
|
||||
BYTE hash1[SHA256_BLOCK_SIZE] = {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};
|
||||
BYTE hash2[SHA256_BLOCK_SIZE] = {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};
|
||||
BYTE hash3[SHA256_BLOCK_SIZE] = {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};
|
||||
BYTE buf[SHA256_BLOCK_SIZE];
|
||||
SHA256_CTX ctx;
|
||||
int idx;
|
||||
int pass = 1;
|
||||
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, text1, u_strlen(text1));
|
||||
sha256_final(&ctx, buf);
|
||||
pass = pass && !memcmp(hash1, buf, SHA256_BLOCK_SIZE);
|
||||
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, text2, u_strlen(text2));
|
||||
sha256_final(&ctx, buf);
|
||||
pass = pass && !memcmp(hash2, buf, SHA256_BLOCK_SIZE);
|
||||
|
||||
sha256_init(&ctx);
|
||||
for (idx = 0; idx < 100000; ++idx)
|
||||
sha256_update(&ctx, text3, u_strlen(text3));
|
||||
sha256_final(&ctx, buf);
|
||||
pass = pass && !memcmp(hash3, buf, SHA256_BLOCK_SIZE);
|
||||
|
||||
printf("SHA-256 tests: %s\n", pass ? "SUCCEEDED" : "FAILED");
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/*********************************************************************
|
||||
* Filename: sha256.h
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Defines the API for the corresponding SHA1 implementation.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef SHA256_H
|
||||
#define SHA256_H
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
|
||||
|
||||
/**************************** DATA TYPES ****************************/
|
||||
typedef unsigned char BYTE; // 8-bit byte
|
||||
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
|
||||
|
||||
typedef struct {
|
||||
BYTE data[64];
|
||||
WORD datalen;
|
||||
unsigned long long bitlen;
|
||||
WORD state[8];
|
||||
} SHA256_CTX;
|
||||
|
||||
/*********************** FUNCTION DECLARATIONS **********************/
|
||||
void sha256_init(SHA256_CTX *ctx);
|
||||
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);
|
||||
void sha256_final(SHA256_CTX *ctx, BYTE hash[]);
|
||||
|
||||
// test
|
||||
#ifdef TEST_FUNCTIONS_ENABLED
|
||||
void exec_sha256_test(void);
|
||||
#endif
|
||||
|
||||
#endif // SHA256_H
|
||||
Reference in new issue
Block a user