diff --git a/encrypt.cpp b/encrypt.cpp index c6f80639..de562074 100755 --- a/encrypt.cpp +++ b/encrypt.cpp @@ -1,4 +1,5 @@ #include "lib/aes-common.h" +#include "lib/chacha20.h" #include "lib/md5.h" #include "lib/pbkdf2-sha1.h" #include "lib/pbkdf2-sha256.h" @@ -28,7 +29,7 @@ unsigned char cipher_key_decrypt[cipher_key_len + 100]; //key for aes etc. unordered_map auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"},{auth_hmac_sha1,"hmac_sha1"},}; -unordered_map cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cfb,"aes128cfb"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"},}; +unordered_map cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cfb,"aes128cfb"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"},{cipher_chacha12,"chacha12"},{cipher_chacha20,"chacha20"},}; //TODO aes-gcm auth_mode_t auth_mode=auth_md5; @@ -324,6 +325,20 @@ int cipher_aes128cfb_encrypt(const char *data,char *output,int &len,char * key) AES_CFB_encrypt_buffer((unsigned char *)output,(unsigned char *)buf,len,(unsigned char *)key,(unsigned char *)zero_iv); return 0; } +int cipher_chacha12_encrypt(const char *data,char *output,int &len,char * key) +{ + ChaCha12XOR((uint8_t *) key, 1, (uint8_t *) zero_iv, + (uint8_t *) data, (uint8_t *) output, len); + //AES_CBC_encrypt_buffer((unsigned char *)output,(unsigned char *)buf,len,(unsigned char *)key,(unsigned char *)zero_iv); + return 0; +} +int cipher_chacha20_encrypt(const char *data,char *output,int &len,char * key) +{ + ChaCha20XOR((uint8_t *) key, 1, (uint8_t *) zero_iv, + (uint8_t *) data, (uint8_t *) output, len); + //AES_CBC_encrypt_buffer((unsigned char *)output,(unsigned char *)buf,len,(unsigned char *)key,(unsigned char *)zero_iv); + return 0; +} int auth_crc32_verify(const char *data,int &len) { if(len +#include +#include "chacha20.h" + +static inline void u32t8le(uint32_t v, uint8_t p[4]) { + p[0] = v & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; +} + +static inline uint32_t u8t32le(uint8_t p[4]) { + uint32_t value = p[3]; + + value = (value << 8) | p[2]; + value = (value << 8) | p[1]; + value = (value << 8) | p[0]; + + return value; +} + +static inline uint32_t rotl32(uint32_t x, int n) { + // http://blog.regehr.org/archives/1063 + return x << n | (x >> (-n & 31)); +} + +// https://tools.ietf.org/html/rfc7539#section-2.1 +static void chacha20_quarterround(uint32_t *x, int a, int b, int c, int d) { + x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16); + x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12); + x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8); + x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7); +} + +static void chacha20_serialize(uint32_t in[16], uint8_t output[64]) { + int i; + for (i = 0; i < 16; i++) { + u32t8le(in[i], output + (i << 2)); + } +} + +static void chacha20_block(uint32_t in[16], uint8_t out[64], int num_rounds) { + int i; + uint32_t x[16]; + + memcpy(x, in, sizeof(uint32_t) * 16); + + for (i = num_rounds; i > 0; i -= 2) { + chacha20_quarterround(x, 0, 4, 8, 12); + chacha20_quarterround(x, 1, 5, 9, 13); + chacha20_quarterround(x, 2, 6, 10, 14); + chacha20_quarterround(x, 3, 7, 11, 15); + chacha20_quarterround(x, 0, 5, 10, 15); + chacha20_quarterround(x, 1, 6, 11, 12); + chacha20_quarterround(x, 2, 7, 8, 13); + chacha20_quarterround(x, 3, 4, 9, 14); + } + + for (i = 0; i < 16; i++) { + x[i] += in[i]; + } + + chacha20_serialize(x, out); +} + +// https://tools.ietf.org/html/rfc7539#section-2.3 +static void chacha20_init_state(uint32_t s[16], uint8_t key[32], uint32_t counter, uint8_t nonce[12]) { + int i; + + // refer: https://dxr.mozilla.org/mozilla-beta/source/security/nss/lib/freebl/chacha20.c + // convert magic number to string: "expand 32-byte k" + s[0] = 0x61707865; + s[1] = 0x3320646e; + s[2] = 0x79622d32; + s[3] = 0x6b206574; + + for (i = 0; i < 8; i++) { + s[4 + i] = u8t32le(key + i * 4); + } + + s[12] = counter; + + for (i = 0; i < 3; i++) { + s[13 + i] = u8t32le(nonce + i * 4); + } +} +void ChaCha12XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *in, uint8_t *out, int inlen) { + int i, j; + + uint32_t s[16]; + uint8_t block[64]; + + chacha20_init_state(s, key, counter, nonce); + + for (i = 0; i < inlen; i += 64) { + chacha20_block(s, block, 12); + s[12]++; + + for (j = i; j < i + 64; j++) { + if (j >= inlen) { + break; + } + out[j] = in[j] ^ block[j - i]; + } + } +} + +void ChaCha20XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *in, uint8_t *out, int inlen) { + int i, j; + + uint32_t s[16]; + uint8_t block[64]; + + chacha20_init_state(s, key, counter, nonce); + + for (i = 0; i < inlen; i += 64) { + chacha20_block(s, block, 20); + s[12]++; + + for (j = i; j < i + 64; j++) { + if (j >= inlen) { + break; + } + out[j] = in[j] ^ block[j - i]; + } + } +} diff --git a/lib/chacha20.h b/lib/chacha20.h new file mode 100644 index 00000000..5131d7f5 --- /dev/null +++ b/lib/chacha20.h @@ -0,0 +1,9 @@ +#ifndef __CHACHA20_H +#define __CHACHA20_H +#include + +void ChaCha12XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *input, uint8_t *output, int inputlen); + +void ChaCha20XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *input, uint8_t *output, int inputlen); + +#endif \ No newline at end of file diff --git a/makefile b/makefile index 387d74ef..184a556a 100755 --- a/makefile +++ b/makefile @@ -10,7 +10,7 @@ cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++ #cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers ${OPT} -COMMON=main.cpp lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp fd_manager.cpp client.cpp server.cpp -lpthread my_ev.cpp -isystem libev +COMMON=main.cpp lib/chacha20.c lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp fd_manager.cpp client.cpp server.cpp -lpthread my_ev.cpp -isystem libev SOURCES= $(COMMON) lib/aes_faster_c/aes.cpp lib/aes_faster_c/wrapper.cpp SOURCES_TINY_AES= $(COMMON) lib/aes.c SOURCES_AES_ACC=$(COMMON) $(wildcard lib/aes_acc/aes*.c) diff --git a/misc.cpp b/misc.cpp index 60ea4151..da95528f 100644 --- a/misc.cpp +++ b/misc.cpp @@ -138,7 +138,7 @@ void print_help() printf("common options,these options must be same on both side:\n"); printf(" --raw-mode avaliable values:faketcp(default),udp,icmp\n"); printf(" -k,--key password to gen symetric key,default:\"secret key\"\n"); - printf(" --cipher-mode avaliable values:aes128cfb,aes128cbc(default),xor,none\n"); + printf(" --cipher-mode avaliable values:chacha12,chacha20,aes128cfb,aes128cbc(default),xor,none\n"); printf(" --auth-mode avaliable values:hmac_sha1,md5(default),crc32,simple,none\n"); printf(" -a,--auto-rule auto add (and delete) iptables rule\n"); printf(" -g,--gen-rule generate iptables rule then exit,so that you can copy and\n");