From c304e13550f0ffadcf9f861f98f963bd00159c26 Mon Sep 17 00:00:00 2001 From: "ivan.fedorov" <ivan.fedorov@demlabs.net> Date: Thu, 30 Apr 2020 22:30:18 +0300 Subject: [PATCH] salsa implemented --- CMakeLists.txt | 2 + include/dap_enc_key.h | 2 +- include/dap_enc_salsa2012.h | 34 +++ src/dap_enc_key.c | 22 +- src/dap_enc_salsa2012.c | 131 ++++++++++++ src/ringct20/ringct20_params.c | 2 +- src/salsa2012/common_salsa.h | 263 ++++++++++++++++++++++++ src/salsa2012/core_salsa_ref.c | 116 +++++++++++ src/salsa2012/crypto_core_salsa2012.h | 35 ++++ src/salsa2012/crypto_stream_salsa2012.h | 50 +++++ src/salsa2012/stream_salsa2012.c | 26 +++ src/salsa2012/stream_salsa2012_ref.c | 124 +++++++++++ src/salsa2012/utils.h | 9 + test/crypto/main.c | 6 +- 14 files changed, 815 insertions(+), 7 deletions(-) create mode 100644 include/dap_enc_salsa2012.h create mode 100644 src/dap_enc_salsa2012.c create mode 100644 src/salsa2012/common_salsa.h create mode 100644 src/salsa2012/core_salsa_ref.c create mode 100644 src/salsa2012/crypto_core_salsa2012.h create mode 100644 src/salsa2012/crypto_stream_salsa2012.h create mode 100644 src/salsa2012/stream_salsa2012.c create mode 100644 src/salsa2012/stream_salsa2012_ref.c create mode 100644 src/salsa2012/utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index adf7711..9b83fb9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ file( GLOB CRYPTO_SRCS src/oaes/*.c src/blowfish/*.c src/GOST/*.c + src/salsa2012/*.c src/sha3/*.c src/msrln/*.c src/defeo_scheme/*.c @@ -49,6 +50,7 @@ file( GLOB CRYPTO_HEADERS src/oaes/*.h src/blowfish/*.h src/GOST/*.h + src/salsa2012/*.h src/sha3/*.h src/msrln/*.h src/defeo_scheme/*.h diff --git a/include/dap_enc_key.h b/include/dap_enc_key.h index 145fb27..8f05eff 100755 --- a/include/dap_enc_key.h +++ b/include/dap_enc_key.h @@ -241,7 +241,7 @@ extern "C" { int dap_enc_key_init(void); void dap_enc_key_deinit(void); -char *dap_enc_get_type_name(dap_enc_key_type_t key_type); +const char *dap_enc_get_type_name(dap_enc_key_type_t a_key_type); size_t dap_enc_key_get_enc_size(dap_enc_key_t * a_key, const size_t buf_in_size); size_t dap_enc_key_get_dec_size(dap_enc_key_t * a_key, const size_t buf_in_size); diff --git a/include/dap_enc_salsa2012.h b/include/dap_enc_salsa2012.h new file mode 100644 index 0000000..de2e7de --- /dev/null +++ b/include/dap_enc_salsa2012.h @@ -0,0 +1,34 @@ +#ifndef _DAP_ENC_SALSA2012_H_ +#define _DAP_ENC_SALSA2012_H_ + +#include <stddef.h> +#include "dap_enc_key.h" +#include "salsa2012/crypto_stream_salsa2012.h" + +#ifdef __cplusplus +extern "C" { +#endif +void dap_enc_salsa2012_key_delete(struct dap_enc_key *a_key); +void dap_enc_salsa2012_key_generate(struct dap_enc_key * a_key, const void *kex_buf, + size_t kex_size, const void * seed, size_t seed_size, size_t key_size); +//------salsa2012--------- +void dap_enc_salsa2012_key_new(struct dap_enc_key * a_key); + +size_t dap_enc_salsa2012_calc_decode_size(const size_t size_in); +size_t dap_enc_salsa2012_calc_encode_size(const size_t size_in); + +size_t dap_enc_salsa2012_decrypt(struct dap_enc_key * a_key, const void * a_in, size_t a_in_size, void ** a_out); +size_t dap_enc_salsa2012_encrypt(struct dap_enc_key * a_key, const void * a_in, size_t a_in_size, void ** a_out); + +// Writes result ( out ) in already allocated buffer +size_t dap_enc_salsa2012_decrypt_fast(struct dap_enc_key * a_key, const void * a_in, + size_t a_in_size, void * buf_out, size_t buf_out_size); +// Writes result ( out ) in already allocated buffer +size_t dap_enc_salsa2012_encrypt_fast(struct dap_enc_key * a_key, const void * a_in, + size_t a_in_size, void * buf_out, size_t buf_out_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/dap_enc_key.c b/src/dap_enc_key.c index 55258d7..4d0812b 100755 --- a/src/dap_enc_key.c +++ b/src/dap_enc_key.c @@ -166,6 +166,22 @@ struct dap_enc_key_callbacks{ .sign_get = NULL, .sign_verify = NULL }, + [DAP_ENC_KEY_TYPE_SALSA2012]={ + .name = "SALSA2012", + .enc = dap_enc_salsa2012_encrypt, + .enc_na = dap_enc_salsa2012_encrypt_fast , + .dec = dap_enc_salsa2012_decrypt, + .dec_na = dap_enc_salsa2012_decrypt_fast , + .new_callback = dap_enc_salsa2012_key_new, + .delete_callback = dap_enc_salsa2012_key_delete, + .new_generate_callback = dap_enc_salsa2012_key_generate, + .gen_key_public = NULL, + .gen_key_public_size = NULL, + .enc_out_size = dap_enc_salsa2012_calc_encode_size, + .dec_out_size = dap_enc_salsa2012_calc_decode_size, + .sign_get = NULL, + .sign_verify = NULL + }, [DAP_ENC_KEY_TYPE_MSRLN] = { .name = "MSRLN", @@ -750,10 +766,10 @@ size_t dap_enc_key_get_dec_size(dap_enc_key_t * a_key, const size_t buf_in_size) return 0; } -char *dap_enc_get_type_name(dap_enc_key_type_t key_type) +const char *dap_enc_get_type_name(dap_enc_key_type_t a_key_type) { - if(s_callbacks[key_type].name) { - return s_callbacks[key_type].name; + if(s_callbacks[a_key_type].name) { + return s_callbacks[a_key_type].name; } log_it(L_ERROR, "name not realize for current key type"); return 0; diff --git a/src/dap_enc_salsa2012.c b/src/dap_enc_salsa2012.c new file mode 100644 index 0000000..767f9fb --- /dev/null +++ b/src/dap_enc_salsa2012.c @@ -0,0 +1,131 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stddef.h> +#include <string.h> + +#include "dap_enc_salsa2012.h" +#include "dap_common.h" +#include "rand/dap_rand.h" +#include "sha3/KeccakHash.h" + +#define LOG_TAG "dap_enc_salsa2012" +#define SALSA20_KEY_SIZE 32 +#define SALSA20_NONCE_SIZE 8 + +void dap_enc_salsa2012_key_generate(struct dap_enc_key * a_key, const void *kex_buf, + size_t kex_size, const void * seed, size_t seed_size, size_t key_size) +{ + if(key_size < SALSA20_KEY_SIZE) + { + log_it(L_ERROR, "SALSA20 key cannot be less than 32 bytes."); + } + a_key->last_used_timestamp = time(NULL); + + + a_key->priv_key_data_size = SALSA20_KEY_SIZE; + a_key->priv_key_data = DAP_NEW_SIZE(uint8_t, key_size); + + Keccak_HashInstance Keccak_ctx; + Keccak_HashInitialize(&Keccak_ctx, 1088, 512, SALSA20_KEY_SIZE*8, 0x06); + Keccak_HashUpdate(&Keccak_ctx, kex_buf, kex_size*8); + if(seed_size) + Keccak_HashUpdate(&Keccak_ctx, seed, seed_size*8); + Keccak_HashFinal(&Keccak_ctx, a_key->priv_key_data); +} + +void dap_enc_salsa2012_key_delete(struct dap_enc_key *a_key) +{ + if(a_key->priv_key_data != NULL) + { + randombytes(a_key->priv_key_data,a_key->priv_key_data_size); + DAP_DELETE(a_key->priv_key_data); + } + a_key->priv_key_data_size = 0; +} +//------SALSA2012----------- +void dap_enc_salsa2012_key_new(struct dap_enc_key * a_key) +{ + a_key->_inheritor = NULL; + a_key->_inheritor_size = 0; + a_key->type = DAP_ENC_KEY_TYPE_SALSA2012; + a_key->enc = dap_enc_salsa2012_encrypt; + a_key->dec = dap_enc_salsa2012_decrypt; + a_key->enc_na = dap_enc_salsa2012_encrypt_fast; + a_key->dec_na = dap_enc_salsa2012_decrypt_fast; +} + + +size_t dap_enc_salsa2012_decrypt(struct dap_enc_key *a_key, const void * a_in, size_t a_in_size, void ** a_out) +{ + size_t a_out_size = a_in_size - SALSA20_NONCE_SIZE; + if(a_out_size <= 0) { + log_it(L_ERROR, "salsa2012 decryption ct with iv must be more than kBlockLen89 bytes"); + return 0; + } + *a_out = DAP_NEW_SIZE(uint8_t, a_in_size - SALSA20_NONCE_SIZE); + a_out_size = dap_enc_salsa2012_decrypt_fast(a_key, a_in, a_in_size, *a_out, a_out_size); + if(a_out_size == 0) + DAP_DEL_Z(*a_out); + return a_out_size; +} + +size_t dap_enc_salsa2012_encrypt(struct dap_enc_key * a_key, const void * a_in, size_t a_in_size, void ** a_out) +{ + if(a_in_size <= 0) { + log_it(L_ERROR, "gost ofb encryption pt cannot be 0 bytes"); + return 0; + } + size_t a_out_size = a_in_size + SALSA20_NONCE_SIZE; + *a_out = DAP_NEW_SIZE(uint8_t, a_out_size); + a_out_size = dap_enc_salsa2012_encrypt_fast(a_key, a_in, a_in_size, *a_out, a_out_size); + if(a_out_size == 0) + DAP_DEL_Z(*a_out); + return a_out_size; +} + +size_t dap_enc_salsa2012_calc_encode_size(const size_t size_in) +{ + return size_in + SALSA20_NONCE_SIZE; +} + +size_t dap_enc_salsa2012_calc_decode_size(const size_t size_in) +{ + if(size_in <= SALSA20_NONCE_SIZE) { + log_it(L_ERROR, "salsa2012 decryption size_in ct with iv must be more than kBlockLen89 bytes"); + return 0; + } + return size_in - SALSA20_NONCE_SIZE; +} + +size_t dap_enc_salsa2012_decrypt_fast(struct dap_enc_key *a_key, const void * a_in, + size_t a_in_size, void * a_out, size_t buf_out_size) { + size_t a_out_size = a_in_size - SALSA20_NONCE_SIZE; + if(a_out_size > buf_out_size) { + log_it(L_ERROR, "salsa2012 fast_decryption too small buf_out_size"); + return 0; + } + + //memcpy(nonce, a_in, SALSA20_NONCE_SIZE); + crypto_stream_salsa2012_xor(a_out, a_in + SALSA20_NONCE_SIZE, a_in_size - SALSA20_NONCE_SIZE, a_in, a_key->priv_key_data); + return a_out_size; +} + +size_t dap_enc_salsa2012_encrypt_fast(struct dap_enc_key * a_key, const void * a_in, size_t a_in_size, void * a_out,size_t buf_out_size) +{ + size_t a_out_size = a_in_size + SALSA20_NONCE_SIZE; + if(a_out_size > buf_out_size) { + log_it(L_ERROR, "salsa2012 fast_encryption too small buf_out_size"); + return 0; + } + + if(randombytes(a_out, SALSA20_NONCE_SIZE) == 1) + { + log_it(L_ERROR, "failed to get SALSA20_NONCE_SIZE bytes nonce"); + return 0; + } + + crypto_stream_salsa2012_xor(a_out + SALSA20_NONCE_SIZE, a_in, a_in_size, a_out, a_key->priv_key_data); + return a_out_size; + } + diff --git a/src/ringct20/ringct20_params.c b/src/ringct20/ringct20_params.c index c55598f..077221e 100644 --- a/src/ringct20/ringct20_params.c +++ b/src/ringct20/ringct20_params.c @@ -74,7 +74,7 @@ uint8_t H_bpoly_MAXSEC[14][NEWHOPE_POLYBYTES] = { #elif (NEWHOPE_N == 1024) #error "NEWHOPE_N must be either 512 or 1024.. NEWHOPE_N == 1024 not implemented yet" #elif -#error "NEWHOPE_N must be either 512 or 1024.. +#error "NEWHOPE_N must be either 512 or 1024.." #endif bool ringct20_params_init(ringct20_param_t *ringct20_p, DAP_RINGCT20_SIGN_SECURITY kind)//, const int wLen) diff --git a/src/salsa2012/common_salsa.h b/src/salsa2012/common_salsa.h new file mode 100644 index 0000000..5f45c9a --- /dev/null +++ b/src/salsa2012/common_salsa.h @@ -0,0 +1,263 @@ +#ifndef common_SALSA_H +#define common_SALSA_H 1 + +#if !defined(_MSC_VER) && !defined(DEV_MODE) && 1 +# warning *** This is unstable, untested, development code. +# warning It might not compile. It might not work as expected. +# warning It might be totally insecure. +# warning Do not use this except if you are planning to contribute code. +# warning Use releases available at https://download.libsodium.org/libsodium/releases/ instead. +# warning Alternatively, use the "stable" branch in the git repository. +#endif + +#if !defined(_MSC_VER) && (!defined(CONFIGURED) || CONFIGURED != 1) +# warning *** The library is being compiled using an undocumented method. +# warning This is not supported. It has not been tested, it might not +# warning work as expected, and performance is likely to be suboptimal. +#endif + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +//#include "private/quirks.h" + +#define COMPILER_ASSERT(X) (void) sizeof(char[(X) ? 1 : -1]) + +#ifdef HAVE_TI_MODE +# if defined(__SIZEOF_INT128__) +typedef unsigned __int128 uint128_t; +# else +typedef unsigned uint128_t __attribute__((mode(TI))); +# endif +#endif + +#define ROTL32(X, B) rotl32((X), (B)) +static inline uint32_t +rotl32(const uint32_t x, const int b) +{ + return (x << b) | (x >> (32 - b)); +} + +#define ROTL64(X, B) rotl64((X), (B)) +static inline uint64_t +rotl64(const uint64_t x, const int b) +{ + return (x << b) | (x >> (64 - b)); +} + +#define ROTR32(X, B) rotr32((X), (B)) +static inline uint32_t +rotr32(const uint32_t x, const int b) +{ + return (x >> b) | (x << (32 - b)); +} + +#define ROTR64(X, B) rotr64((X), (B)) +static inline uint64_t +rotr64(const uint64_t x, const int b) +{ + return (x >> b) | (x << (64 - b)); +} + +#define LOAD64_LE(SRC) load64_le(SRC) +static inline uint64_t +load64_le(const uint8_t src[8]) +{ +#ifdef NATIVE_LITTLE_ENDIAN + uint64_t w; + memcpy(&w, src, sizeof w); + return w; +#else + uint64_t w = (uint64_t) src[0]; + w |= (uint64_t) src[1] << 8; + w |= (uint64_t) src[2] << 16; + w |= (uint64_t) src[3] << 24; + w |= (uint64_t) src[4] << 32; + w |= (uint64_t) src[5] << 40; + w |= (uint64_t) src[6] << 48; + w |= (uint64_t) src[7] << 56; + return w; +#endif +} + +#define STORE64_LE(DST, W) store64_le((DST), (W)) +static inline void +store64_le(uint8_t dst[8], uint64_t w) +{ +#ifdef NATIVE_LITTLE_ENDIAN + memcpy(dst, &w, sizeof w); +#else + dst[0] = (uint8_t) w; w >>= 8; + dst[1] = (uint8_t) w; w >>= 8; + dst[2] = (uint8_t) w; w >>= 8; + dst[3] = (uint8_t) w; w >>= 8; + dst[4] = (uint8_t) w; w >>= 8; + dst[5] = (uint8_t) w; w >>= 8; + dst[6] = (uint8_t) w; w >>= 8; + dst[7] = (uint8_t) w; +#endif +} + +#define LOAD32_LE(SRC) load32_le(SRC) +static inline uint32_t +load32_le(const uint8_t src[4]) +{ +#ifdef NATIVE_LITTLE_ENDIAN + uint32_t w; + memcpy(&w, src, sizeof w); + return w; +#else + uint32_t w = (uint32_t) src[0]; + w |= (uint32_t) src[1] << 8; + w |= (uint32_t) src[2] << 16; + w |= (uint32_t) src[3] << 24; + return w; +#endif +} + +#define STORE32_LE(DST, W) store32_le((DST), (W)) +static inline void +store32_le(uint8_t dst[4], uint32_t w) +{ +#ifdef NATIVE_LITTLE_ENDIAN + memcpy(dst, &w, sizeof w); +#else + dst[0] = (uint8_t) w; w >>= 8; + dst[1] = (uint8_t) w; w >>= 8; + dst[2] = (uint8_t) w; w >>= 8; + dst[3] = (uint8_t) w; +#endif +} + +/* ----- */ + +#define LOAD64_BE(SRC) load64_be(SRC) +static inline uint64_t +load64_be(const uint8_t src[8]) +{ +#ifdef NATIVE_BIG_ENDIAN + uint64_t w; + memcpy(&w, src, sizeof w); + return w; +#else + uint64_t w = (uint64_t) src[7]; + w |= (uint64_t) src[6] << 8; + w |= (uint64_t) src[5] << 16; + w |= (uint64_t) src[4] << 24; + w |= (uint64_t) src[3] << 32; + w |= (uint64_t) src[2] << 40; + w |= (uint64_t) src[1] << 48; + w |= (uint64_t) src[0] << 56; + return w; +#endif +} + +#define STORE64_BE(DST, W) store64_be((DST), (W)) +static inline void +store64_be(uint8_t dst[8], uint64_t w) +{ +#ifdef NATIVE_BIG_ENDIAN + memcpy(dst, &w, sizeof w); +#else + dst[7] = (uint8_t) w; w >>= 8; + dst[6] = (uint8_t) w; w >>= 8; + dst[5] = (uint8_t) w; w >>= 8; + dst[4] = (uint8_t) w; w >>= 8; + dst[3] = (uint8_t) w; w >>= 8; + dst[2] = (uint8_t) w; w >>= 8; + dst[1] = (uint8_t) w; w >>= 8; + dst[0] = (uint8_t) w; +#endif +} + +#define LOAD32_BE(SRC) load32_be(SRC) +static inline uint32_t +load32_be(const uint8_t src[4]) +{ +#ifdef NATIVE_BIG_ENDIAN + uint32_t w; + memcpy(&w, src, sizeof w); + return w; +#else + uint32_t w = (uint32_t) src[3]; + w |= (uint32_t) src[2] << 8; + w |= (uint32_t) src[1] << 16; + w |= (uint32_t) src[0] << 24; + return w; +#endif +} + +#define STORE32_BE(DST, W) store32_be((DST), (W)) +static inline void +store32_be(uint8_t dst[4], uint32_t w) +{ +#ifdef NATIVE_BIG_ENDIAN + memcpy(dst, &w, sizeof w); +#else + dst[3] = (uint8_t) w; w >>= 8; + dst[2] = (uint8_t) w; w >>= 8; + dst[1] = (uint8_t) w; w >>= 8; + dst[0] = (uint8_t) w; +#endif +} + +#define XOR_BUF(OUT, IN, N) xor_buf((OUT), (IN), (N)) +static inline void +xor_buf(unsigned char *out, const unsigned char *in, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) { + out[i] ^= in[i]; + } +} + +#if !defined(__clang__) && !defined(__GNUC__) +# ifdef __attribute__ +# undef __attribute__ +# endif +# define __attribute__(a) +#endif + +#ifndef CRYPTO_ALIGN +# if defined(__INTEL_COMPILER) || defined(_MSC_VER) +# define CRYPTO_ALIGN(x) __declspec(align(x)) +# else +# define CRYPTO_ALIGN(x) __attribute__ ((aligned(x))) +# endif +#endif + +#if defined(_MSC_VER) && \ + (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)) + +# include <intrin.h> + +# define HAVE_INTRIN_H 1 +# define HAVE_MMINTRIN_H 1 +# define HAVE_EMMINTRIN_H 1 +# define HAVE_PMMINTRIN_H 1 +# define HAVE_TMMINTRIN_H 1 +# define HAVE_SMMINTRIN_H 1 +# define HAVE_AVXINTRIN_H 1 +# if _MSC_VER >= 1600 +# define HAVE_WMMINTRIN_H 1 +# endif +# if _MSC_VER >= 1700 && defined(_M_X64) +# define HAVE_AVX2INTRIN_H 1 +# endif +#elif defined(HAVE_INTRIN_H) +# include <intrin.h> +#endif + +#ifdef HAVE_LIBCTGRIND +extern void ct_poison (const void *, size_t); +extern void ct_unpoison(const void *, size_t); +# define POISON(X, L) ct_poison((X), (L)) +# define UNPOISON(X, L) ct_unpoison((X), (L)) +#else +# define POISON(X, L) (void) 0 +# define UNPOISON(X, L) (void) 0 +#endif + +#endif diff --git a/src/salsa2012/core_salsa_ref.c b/src/salsa2012/core_salsa_ref.c new file mode 100644 index 0000000..0caccc3 --- /dev/null +++ b/src/salsa2012/core_salsa_ref.c @@ -0,0 +1,116 @@ + +#include <stdint.h> +#include <stdlib.h> + +#include "crypto_core_salsa2012.h" +#include "common_salsa.h" + +/** @brief main salsa code + * @param[out] out -- + * @param[in] rounds main rounds number + * @param[in] c constants for x0,5,10,15 refer to NULL, than uses fixed const + * @param[in] k 32 bytes key + * @param[in] in 16 bytes input generated from nonce and counts + */ +static void +crypto_core_salsa(unsigned char *out, const unsigned char *in, + const unsigned char *k, const unsigned char *c, + const int rounds) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, + x15; + uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, + j15; + int i; + + j0 = x0 = 0x61707865; + j5 = x5 = 0x3320646e; + j10 = x10 = 0x79622d32; + j15 = x15 = 0x6b206574; + if (c != NULL) { + j0 = x0 = LOAD32_LE(c + 0); + j5 = x5 = LOAD32_LE(c + 4); + j10 = x10 = LOAD32_LE(c + 8); + j15 = x15 = LOAD32_LE(c + 12); + } + j1 = x1 = LOAD32_LE(k + 0); + j2 = x2 = LOAD32_LE(k + 4); + j3 = x3 = LOAD32_LE(k + 8); + j4 = x4 = LOAD32_LE(k + 12); + j11 = x11 = LOAD32_LE(k + 16); + j12 = x12 = LOAD32_LE(k + 20); + j13 = x13 = LOAD32_LE(k + 24); + j14 = x14 = LOAD32_LE(k + 28); + + j6 = x6 = LOAD32_LE(in + 0); + j7 = x7 = LOAD32_LE(in + 4); + j8 = x8 = LOAD32_LE(in + 8); + j9 = x9 = LOAD32_LE(in + 12); + + for (i = 0; i < rounds; i += 2) { + x4 ^= ROTL32(x0 + x12, 7); + x8 ^= ROTL32(x4 + x0, 9); + x12 ^= ROTL32(x8 + x4, 13); + x0 ^= ROTL32(x12 + x8, 18); + x9 ^= ROTL32(x5 + x1, 7); + x13 ^= ROTL32(x9 + x5, 9); + x1 ^= ROTL32(x13 + x9, 13); + x5 ^= ROTL32(x1 + x13, 18); + x14 ^= ROTL32(x10 + x6, 7); + x2 ^= ROTL32(x14 + x10, 9); + x6 ^= ROTL32(x2 + x14, 13); + x10 ^= ROTL32(x6 + x2, 18); + x3 ^= ROTL32(x15 + x11, 7); + x7 ^= ROTL32(x3 + x15, 9); + x11 ^= ROTL32(x7 + x3, 13); + x15 ^= ROTL32(x11 + x7, 18); + x1 ^= ROTL32(x0 + x3, 7); + x2 ^= ROTL32(x1 + x0, 9); + x3 ^= ROTL32(x2 + x1, 13); + x0 ^= ROTL32(x3 + x2, 18); + x6 ^= ROTL32(x5 + x4, 7); + x7 ^= ROTL32(x6 + x5, 9); + x4 ^= ROTL32(x7 + x6, 13); + x5 ^= ROTL32(x4 + x7, 18); + x11 ^= ROTL32(x10 + x9, 7); + x8 ^= ROTL32(x11 + x10, 9); + x9 ^= ROTL32(x8 + x11, 13); + x10 ^= ROTL32(x9 + x8, 18); + x12 ^= ROTL32(x15 + x14, 7); + x13 ^= ROTL32(x12 + x15, 9); + x14 ^= ROTL32(x13 + x12, 13); + x15 ^= ROTL32(x14 + x13, 18); + } + STORE32_LE(out + 0, x0 + j0); + STORE32_LE(out + 4, x1 + j1); + STORE32_LE(out + 8, x2 + j2); + STORE32_LE(out + 12, x3 + j3); + STORE32_LE(out + 16, x4 + j4); + STORE32_LE(out + 20, x5 + j5); + STORE32_LE(out + 24, x6 + j6); + STORE32_LE(out + 28, x7 + j7); + STORE32_LE(out + 32, x8 + j8); + STORE32_LE(out + 36, x9 + j9); + STORE32_LE(out + 40, x10 + j10); + STORE32_LE(out + 44, x11 + j11); + STORE32_LE(out + 48, x12 + j12); + STORE32_LE(out + 52, x13 + j13); + STORE32_LE(out + 56, x14 + j14); + STORE32_LE(out + 60, x15 + j15); +} + +int +crypto_core_salsa20(unsigned char *out, const unsigned char *in, + const unsigned char *k, const unsigned char *c) +{ + crypto_core_salsa(out, in, k, c, 20); + return 0; +} +int +crypto_core_salsa2012(unsigned char *out, const unsigned char *in, + const unsigned char *k, const unsigned char *c) +{ + crypto_core_salsa(out, in, k, c, 12); + return 0; +} + diff --git a/src/salsa2012/crypto_core_salsa2012.h b/src/salsa2012/crypto_core_salsa2012.h new file mode 100644 index 0000000..956024f --- /dev/null +++ b/src/salsa2012/crypto_core_salsa2012.h @@ -0,0 +1,35 @@ +#ifndef crypto_core_salsa2012_H +#define crypto_core_salsa2012_H + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define crypto_core_salsa2012_OUTPUTBYTES 64U + +size_t crypto_core_salsa2012_outputbytes(void); + +#define crypto_core_salsa2012_INPUTBYTES 16U + +size_t crypto_core_salsa2012_inputbytes(void); + +#define crypto_core_salsa2012_KEYBYTES 32U + +size_t crypto_core_salsa2012_keybytes(void); + +#define crypto_core_salsa2012_CONSTBYTES 16U + +size_t crypto_core_salsa2012_constbytes(void); + + +int crypto_core_salsa2012(unsigned char *out, const unsigned char *in, + const unsigned char *k, const unsigned char *c) + __attribute__ ((nonnull(1, 2, 3))); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/salsa2012/crypto_stream_salsa2012.h b/src/salsa2012/crypto_stream_salsa2012.h new file mode 100644 index 0000000..d6cc6e2 --- /dev/null +++ b/src/salsa2012/crypto_stream_salsa2012.h @@ -0,0 +1,50 @@ +#ifndef crypto_stream_salsa2012_H +#define crypto_stream_salsa2012_H + +/* + * WARNING: This is just a stream cipher. It is NOT authenticated encryption. + * While it provides some protection against eavesdropping, it does NOT + * provide any security against active attacks. + * Unless you know what you're doing, what you are looking for is probably + * the crypto_box functions. + */ + +#include <stddef.h> +#include "utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define crypto_stream_salsa2012_KEYBYTES 32U + +size_t crypto_stream_salsa2012_keybytes(void); + +#define crypto_stream_salsa2012_NONCEBYTES 8U + +size_t crypto_stream_salsa2012_noncebytes(void); + +#define crypto_stream_salsa2012_MESSAGEBYTES_MAX SODIUM_SIZE_MAX + +size_t crypto_stream_salsa2012_messagebytes_max(void); + + +int crypto_stream_salsa2012(unsigned char *c, unsigned long long clen, + const unsigned char *n, const unsigned char *k) + __attribute__ ((nonnull)); + + +int crypto_stream_salsa2012_xor(unsigned char *c, const unsigned char *m, + unsigned long long mlen, const unsigned char *n, + const unsigned char *k) + __attribute__ ((nonnull)); + + +void crypto_stream_salsa2012_keygen(unsigned char k[crypto_stream_salsa2012_KEYBYTES]) + __attribute__ ((nonnull)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/salsa2012/stream_salsa2012.c b/src/salsa2012/stream_salsa2012.c new file mode 100644 index 0000000..be62fe4 --- /dev/null +++ b/src/salsa2012/stream_salsa2012.c @@ -0,0 +1,26 @@ +#include "crypto_stream_salsa2012.h" +#include "rand/dap_rand.h" + +size_t +crypto_stream_salsa2012_keybytes(void) +{ + return crypto_stream_salsa2012_KEYBYTES; +} + +size_t +crypto_stream_salsa2012_noncebytes(void) +{ + return crypto_stream_salsa2012_NONCEBYTES; +} + +size_t +crypto_stream_salsa2012_messagebytes_max(void) +{ + return crypto_stream_salsa2012_MESSAGEBYTES_MAX; +} + +void +crypto_stream_salsa2012_keygen(unsigned char k[crypto_stream_salsa2012_KEYBYTES]) +{ + randombytes(k, crypto_stream_salsa2012_KEYBYTES); +} diff --git a/src/salsa2012/stream_salsa2012_ref.c b/src/salsa2012/stream_salsa2012_ref.c new file mode 100644 index 0000000..5937c63 --- /dev/null +++ b/src/salsa2012/stream_salsa2012_ref.c @@ -0,0 +1,124 @@ +/* +version 20140420 +D. J. Bernstein +Public domain. +*/ + +#include <stdint.h> + +#include "crypto_core_salsa2012.h" +#include "crypto_stream_salsa2012.h" +#include "utils.h" + + +/** + * @brief generate gamma bytes + * @param gamma bytes array + * @param gamma_len + * @param n nonce + * @param k key + * @return + */ + +int +crypto_stream_salsa2012(unsigned char *gamma, unsigned long long gamma_len, + const unsigned char *n, const unsigned char *k) +{ + unsigned char in[16]; + unsigned char block[64]; + unsigned char kcopy[32]; + unsigned int i; + unsigned int u; + + if (!gamma_len) { + return 0; + } + for (i = 0; i < 32; ++i) { + kcopy[i] = k[i]; + } + for (i = 0; i < 8; ++i) { + in[i] = n[i]; + } + for (i = 8; i < 16; ++i) { + in[i] = 0; + } + while (gamma_len >= 64) { + crypto_core_salsa2012(gamma, in, kcopy, NULL); + u = 1; + for (i = 8; i < 16; ++i) { + u += (unsigned int)in[i]; + in[i] = u; + u >>= 8; + } + gamma_len -= 64; + gamma += 64; + } + if (gamma_len) { + crypto_core_salsa2012(block, in, kcopy, NULL); + for (i = 0; i < (unsigned int)gamma_len; ++i) { + gamma[i] = block[i]; + } + } +// sodium_memzero(block, sizeof block);//TODO +// sodium_memzero(kcopy, sizeof kcopy); + + return 0; +} +/** + * @brief c = m ^ gamma + * @param c + * @param m + * @param mlen + * @param n nonce 8 bytes + * @param k + * @return + */ +int +crypto_stream_salsa2012_xor(unsigned char *c, const unsigned char *m, + unsigned long long mlen, const unsigned char *n, + const unsigned char *k) +{ + unsigned char in[16]; + unsigned char block[64]; + unsigned char kcopy[32]; + unsigned int i; + unsigned int u; + + if (!mlen) { + return 0; + } + for (i = 0; i < 32; ++i) { + kcopy[i] = k[i]; + } + for (i = 0; i < 8; ++i) { + in[i] = n[i]; + } + for (i = 8; i < 16; ++i) { + in[i] = 0; + } + while (mlen >= 64) { + crypto_core_salsa2012(block, in, kcopy, NULL); + for (i = 0; i < 64; ++i) { + c[i] = m[i] ^ block[i]; + } + u = 1; + for (i = 8; i < 16; ++i) { + u += (unsigned int)in[i]; + in[i] = u; + u >>= 8; + } + mlen -= 64; + c += 64; + m += 64; + } + if (mlen) { + crypto_core_salsa2012(block, in, kcopy, NULL); + for (i = 0; i < (unsigned int)mlen; ++i) { + c[i] = m[i] ^ block[i]; + } + } +// sodium_memzero(block, sizeof block);//TODO +// sodium_memzero(kcopy, sizeof kcopy); + + return 0; +} diff --git a/src/salsa2012/utils.h b/src/salsa2012/utils.h new file mode 100644 index 0000000..d7ce028 --- /dev/null +++ b/src/salsa2012/utils.h @@ -0,0 +1,9 @@ +#ifndef sodium_utils_H +#define sodium_utils_H + +#include <stddef.h> + + +#define SODIUM_MIN(A, B) ((A) < (B) ? (A) : (B)) +#define SODIUM_SIZE_MAX SODIUM_MIN(UINT64_MAX, SIZE_MAX) +#endif diff --git a/test/crypto/main.c b/test/crypto/main.c index dc0d542..075dc0a 100755 --- a/test/crypto/main.c +++ b/test/crypto/main.c @@ -18,8 +18,10 @@ int main(void) // switch off debug info from library dap_log_level_set(L_CRITICAL); - test_encypt_decrypt (1000, DAP_ENC_KEY_TYPE_GOST_OFB, 32); - test_encypt_decrypt_fast (1000, DAP_ENC_KEY_TYPE_GOST_OFB, 32); + test_encypt_decrypt (1000, DAP_ENC_KEY_TYPE_SALSA2012, 32); + test_encypt_decrypt_fast (1000, DAP_ENC_KEY_TYPE_SALSA2012, 32); + test_encypt_decrypt (1000, DAP_ENC_KEY_TYPE_GOST_OFB, 32); + test_encypt_decrypt_fast (1000, DAP_ENC_KEY_TYPE_GOST_OFB, 32); test_encypt_decrypt (1000, DAP_ENC_KEY_TYPE_KUZN_OFB, 32); test_encypt_decrypt_fast (1000, DAP_ENC_KEY_TYPE_KUZN_OFB, 32); return 0; -- GitLab