Add XSalsa20 encryption algorithm from the NaCL library.
Include 128-bit key support based on the Salsa20 eSTREAM submission. Allow variable-length nonces. Use random bytes for initial nonce value. Increase PBE hash rounds to 50000.
This commit is contained in:
parent
e16b408061
commit
20250aa5dc
15 changed files with 5568 additions and 74 deletions
22
Makefile.in
22
Makefile.in
|
@ -29,15 +29,22 @@ MAINHDRS = allocator.h pcompress.h utils/utils.h utils/xxhash.h utils/heapq.h
|
|||
utils/cpuid.h utils/xxhash.h
|
||||
MAINOBJS = $(MAINSRCS:.c=.o)
|
||||
|
||||
XSALSA20_STREAM_C = crypto/xsalsa20/stream.c
|
||||
XSALSA20_STREAM_ASM = crypto/xsalsa20/stream.s
|
||||
XSALSA20_DEBUG = -DSALSA20_DEBUG
|
||||
|
||||
CRYPTO_SRCS = crypto/aes/crypto_aes.c crypto/scrypt/crypto_scrypt-nosse.c \
|
||||
crypto/scrypt/sha256.c crypto/scrypt/crypto_aesctr.c crypto/crypto_utils.c \
|
||||
crypto/sha2_utils.c crypto/sha3_utils.c
|
||||
crypto/sha2_utils.c crypto/sha3_utils.c crypto/xsalsa20/xsalsa20_xor.c \
|
||||
crypto/xsalsa20/hsalsa_core.c @XSALSA20_STREAM_C@
|
||||
CRYPTO_HDRS = crypto/crypto_utils.h crypto/scrypt/crypto_scrypt.h \
|
||||
crypto/scrypt/sha256.h crypto/scrypt/crypto_aesctr.h crypto/aes/crypto_aes.h \
|
||||
crypto/sha2_utils.h crypto/sha3_utils.h $(MAINHDRS)
|
||||
CRYPTO_ASM_SRCS = crypto/aes/vpaes-x86_64.s crypto/aes/aesni-x86_64.s
|
||||
CRYPTO_ASM_OBJS = crypto/aes/vpaes-x86_64.o crypto/aes/aesni-x86_64.o
|
||||
CRYPTO_ASM_HDRS = crypto/aes/crypto_aes.h
|
||||
crypto/sha2_utils.h crypto/sha3_utils.h crypto/xsalsa20/crypto_core_hsalsa20.h \
|
||||
crypto/xsalsa20/crypto_stream_salsa20.h crypto/xsalsa20/crypto_xsalsa20.h \
|
||||
$(MAINHDRS)
|
||||
CRYPTO_ASM_SRCS = crypto/aes/vpaes-x86_64.s crypto/aes/aesni-x86_64.s @XSALSA20_STREAM_ASM@
|
||||
CRYPTO_ASM_OBJS = $(CRYPTO_ASM_SRCS:.s=.o)
|
||||
CRYPTO_ASM_HDRS = crypto/aes/crypto_aes.h crypto/xsalsa20/crypto_stream_salsa20.h
|
||||
CRYPTO_COMPAT_SRCS = crypto/old/sha2_utils_old.c crypto/old/sha3_utils_old.c
|
||||
CRYPTO_COMPAT_HDRS = crypto/old/sha2_utils_old.h crypto/old/sha3_utils_old.h
|
||||
CRYPTO_OBJS = $(CRYPTO_SRCS:.c=.o)
|
||||
|
@ -175,9 +182,10 @@ COMMON_CPPFLAGS = -I. -I./lzma -I./lzfx -I./lz4 -I./rabin -I./bsdiff -DNODEFAULT
|
|||
-DFILE_OFFSET_BITS=64 -D_REENTRANT -D__USE_SSE_INTRIN__ -D_LZMA_PROB32 \
|
||||
-I./lzp @LIBBSCCPPFLAGS@ -I./crypto/skein -I./utils -I./crypto/sha2 \
|
||||
-I./crypto/scrypt -I./crypto/aes -I./crypto @KEYLEN@ -I./rabin/global \
|
||||
-I./crypto/keccak -I./transpose -I./crypto/blake2 $(EXTRA_CPPFLAGS) -pedantic -Wall -std=gnu99 \
|
||||
-I./crypto/keccak -I./transpose -I./crypto/blake2 $(EXTRA_CPPFLAGS) \
|
||||
-I./crypto/xsalsa20 -pedantic -Wall -std=gnu99 \
|
||||
-fno-strict-aliasing -Wno-unused-but-set-variable -Wno-enum-compare \
|
||||
@COMPAT_CPPFLAGS@
|
||||
@COMPAT_CPPFLAGS@ @XSALSA20_DEBUG@
|
||||
COMMON_VEC_FLAGS = -ftree-vectorize
|
||||
COMMON_LOOP_OPTFLAGS = $(VEC_FLAGS) -floop-interchange -floop-block
|
||||
LDLIBS = -ldl -L./buildtmp -Wl,-R@LIBBZ2_DIR@ -lbz2 -L./buildtmp -Wl,-R@LIBZ_DIR@ -lz -lm @LIBBSCLFLAGS@ \
|
||||
|
|
12
config
12
config
|
@ -63,6 +63,9 @@ sse_detect=1
|
|||
sse_opt_flags="-msse2"
|
||||
crypto_compat_objs='\$\(CRYPTO_COMPAT_OBJS\)'
|
||||
crypto_compat_flags="-D__HASH_COMPATIBILITY_"
|
||||
salsa20_stream_c=
|
||||
salsa20_stream_asm='\$\(XSALSA20_STREAM_ASM\)'
|
||||
salsa20_debug=
|
||||
|
||||
rm -rf ./buildtmp
|
||||
mkdir ./buildtmp
|
||||
|
@ -168,6 +171,9 @@ done
|
|||
if [ $debug -eq 1 ]
|
||||
then
|
||||
typ="DEBUG"
|
||||
salsa20_stream_c='\$\(XSALSA20_STREAM_C\)'
|
||||
salsa20_stream_asm=
|
||||
salsa20_debug='\$\(XSALSA20_DEBUG\)'
|
||||
else
|
||||
typ="RELEASE"
|
||||
fi
|
||||
|
@ -523,6 +529,9 @@ keccak_srcs_asm_var="KECCAK_SRCS_ASM"
|
|||
|
||||
crypto_compat_objs_var="CRYPTO_COMPAT_OBJS"
|
||||
crypto_compat_flags_var="COMPAT_CPPFLAGS"
|
||||
salsa20_stream_c_var="XSALSA20_STREAM_C"
|
||||
salsa20_stream_asm_var="XSALSA20_STREAM_ASM"
|
||||
salsa20_debug_var="XSALSA20_DEBUG"
|
||||
|
||||
noslabcppflagsval=
|
||||
debugstatscppflagsval=
|
||||
|
@ -567,5 +576,8 @@ s#@${extra_opt_flags_var}@#${extra_opt_flags}#g
|
|||
s#@${sse_opt_flags_var}@#${sse_opt_flags}#g
|
||||
s#@${crypto_compat_objs_var}@#${crypto_compat_objs}#g
|
||||
s#@${crypto_compat_flags_var}@#${crypto_compat_flags}#g
|
||||
s#@${salsa20_stream_c_var}@#${salsa20_stream_c}#g
|
||||
s#@${salsa20_stream_asm_var}@#${salsa20_stream_asm}#g
|
||||
s#@${salsa20_debug_var}@#${salsa20_debug}#g
|
||||
" > Makefile
|
||||
|
||||
|
|
|
@ -58,12 +58,14 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <crypto_scrypt.h>
|
||||
#include <crypto_aesctr.h>
|
||||
#include <utils.h>
|
||||
#include "crypto_aes.h"
|
||||
|
||||
extern int geturandom_bytes(uchar_t *rbytes, int nbytes);
|
||||
extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
|
||||
extern int vpaes_set_encrypt_key(const unsigned char *userKey, int bits, AES_KEY *key);
|
||||
extern void vpaes_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);
|
||||
|
@ -123,16 +125,20 @@ aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
|
|||
|
||||
if (enc) {
|
||||
enc_setkey(key, (ctx->keylen << 3), &(ctx->key));
|
||||
// Derive nonce from salt
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
|
||||
time((time_t *)&tv);
|
||||
} else {
|
||||
tv = tp.tv_sec * 1000UL + tp.tv_nsec;
|
||||
// Derive 64-bit nonce
|
||||
if (RAND_status() != 1 || RAND_bytes((uchar_t *)&(ctx->nonce), 8) != 1) {
|
||||
if (geturandom_bytes((uchar_t *)&(ctx->nonce), 8) != 0) {
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
|
||||
time((time_t *)&tv);
|
||||
} else {
|
||||
tv = tp.tv_sec * 1000UL + tp.tv_nsec;
|
||||
}
|
||||
sprintf((char *)num, "%" PRIu64, tv);
|
||||
PKCS5_PBKDF2_HMAC((const char *)num, strlen((char *)num), salt,
|
||||
saltlen, PBE_ROUNDS, EVP_sha256(), 32, IV);
|
||||
ctx->nonce = lzma_crc64(IV, 32, 0);
|
||||
}
|
||||
}
|
||||
sprintf((char *)num, "%" PRIu64, tv);
|
||||
PKCS5_PBKDF2_HMAC((const char *)num, strlen((char *)num), salt,
|
||||
saltlen, PBE_ROUNDS, EVP_sha256(), 32, IV);
|
||||
ctx->nonce = lzma_crc64(IV, 32, 0) & 0xffffffff00000000ULL;
|
||||
// Nullify stack components
|
||||
memset(num, 0, 25);
|
||||
memset(IV, 0, 32);
|
||||
|
@ -193,10 +199,10 @@ aes_decrypt(aes_ctx_t *ctx, uchar_t *ciphertext, uchar_t *plaintext, uint64_t le
|
|||
return (0);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
uchar_t *
|
||||
aes_nonce(aes_ctx_t *ctx)
|
||||
{
|
||||
return (ctx->nonce);
|
||||
return ((uchar_t *)&(ctx->nonce));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PBE_ROUNDS 1000
|
||||
|
||||
typedef struct {
|
||||
uint64_t nonce;
|
||||
AES_KEY key;
|
||||
|
@ -49,7 +47,7 @@ int aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_l
|
|||
uint64_t nonce, int enc);
|
||||
int aes_encrypt(aes_ctx_t *ctx, uchar_t *plaintext, uchar_t *ciphertext, uint64_t len, uint64_t id);
|
||||
int aes_decrypt(aes_ctx_t *ctx, uchar_t *ciphertext, uchar_t *plaintext, uint64_t len, uint64_t id);
|
||||
uint64_t aes_nonce(aes_ctx_t *ctx);
|
||||
uchar_t *aes_nonce(aes_ctx_t *ctx);
|
||||
void aes_clean_pkey(aes_ctx_t *ctx);
|
||||
void aes_cleanup(aes_ctx_t *ctx);
|
||||
void aes_module_init(processor_info_t *pc);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <crypto_aes.h>
|
||||
#include <KeccakNISTInterface.h>
|
||||
#include <utils.h>
|
||||
#include <crypto_xsalsa20.h>
|
||||
|
||||
#include "crypto_utils.h"
|
||||
#include "sha2_utils.h"
|
||||
|
@ -56,7 +57,6 @@
|
|||
|
||||
static void init_sha512(void);
|
||||
static void init_blake2(void);
|
||||
static int geturandom_bytes(uchar_t rbytes[32]);
|
||||
static struct blake2_dispatch bdsp;
|
||||
|
||||
/*
|
||||
|
@ -173,6 +173,25 @@ PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
|
|||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
get_crypto_alg(char *name)
|
||||
{
|
||||
if (name[0] == 0 || name[1] == 0 || name[2] == 0) {
|
||||
return (0);
|
||||
}
|
||||
if (strncmp(name, "AES", 3) == 0) {
|
||||
return (CRYPTO_ALG_AES);
|
||||
} else {
|
||||
if (name[3] == 0 || name[4] == 0 || name[5] == 0 || name[6] == 0) {
|
||||
return (0);
|
||||
}
|
||||
if (strncmp(name, "SALSA20", 3) == 0) {
|
||||
return (CRYPTO_ALG_SALSA20);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute a digest of the given data segment. The parameter mt indicates whether
|
||||
* to use the parallel(OpenMP) versions. Parallel versions are only used when
|
||||
|
@ -401,13 +420,12 @@ deserialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes)
|
|||
int
|
||||
hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
||||
{
|
||||
aes_ctx_t *actx = (aes_ctx_t *)(cctx->crypto_ctx);
|
||||
mctx->mac_cksum = cksum;
|
||||
|
||||
if (cksum == CKSUM_BLAKE256) {
|
||||
blake2b_state *ctx = (blake2b_state *)malloc(sizeof (blake2b_state));
|
||||
if (!ctx) return (-1);
|
||||
if (bdsp.blake2b_init_key(ctx, 32, actx->pkey, cctx->keylen) != 0)
|
||||
if (bdsp.blake2b_init_key(ctx, 32, cctx->pkey, cctx->keylen) != 0)
|
||||
return (-1);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = (blake2b_state *)malloc(sizeof (blake2b_state));
|
||||
|
@ -421,7 +439,7 @@ hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
|||
} else if (cksum == CKSUM_BLAKE512) {
|
||||
blake2b_state *ctx = (blake2b_state *)malloc(sizeof (blake2b_state));
|
||||
if (!ctx) return (-1);
|
||||
if (bdsp.blake2b_init_key(ctx, 64, actx->pkey, cctx->keylen) != 0)
|
||||
if (bdsp.blake2b_init_key(ctx, 64, cctx->pkey, cctx->keylen) != 0)
|
||||
return (-1);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = (blake2b_state *)malloc(sizeof (blake2b_state));
|
||||
|
@ -436,7 +454,7 @@ hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
|||
Skein_512_Ctxt_t *ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) return (-1);
|
||||
Skein_512_InitExt(ctx, 256, SKEIN_CFG_TREE_INFO_SEQUENTIAL,
|
||||
actx->pkey, cctx->keylen);
|
||||
cctx->pkey, cctx->keylen);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) {
|
||||
|
@ -450,7 +468,7 @@ hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
|||
Skein_512_Ctxt_t *ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) return (-1);
|
||||
Skein_512_InitExt(ctx, 512, SKEIN_CFG_TREE_INFO_SEQUENTIAL,
|
||||
actx->pkey, cctx->keylen);
|
||||
cctx->pkey, cctx->keylen);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) {
|
||||
|
@ -465,7 +483,7 @@ hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
|||
HMAC_CTX *ctx = (HMAC_CTX *)malloc(sizeof (HMAC_CTX));
|
||||
if (!ctx) return (-1);
|
||||
HMAC_CTX_init(ctx);
|
||||
HMAC_Init_ex(ctx, actx->pkey, cctx->keylen, EVP_sha256(), NULL);
|
||||
HMAC_Init_ex(ctx, cctx->pkey, cctx->keylen, EVP_sha256(), NULL);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = (HMAC_CTX *)malloc(sizeof (HMAC_CTX));
|
||||
|
@ -482,7 +500,7 @@ hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
|||
} else {
|
||||
HMAC_SHA512_Context *ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context));
|
||||
if (!ctx) return (-1);
|
||||
opt_HMAC_SHA512t256_Init(ctx, actx->pkey, cctx->keylen);
|
||||
opt_HMAC_SHA512t256_Init(ctx, cctx->pkey, cctx->keylen);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context));
|
||||
|
@ -498,7 +516,7 @@ hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
|||
HMAC_CTX *ctx = (HMAC_CTX *)malloc(sizeof (HMAC_CTX));
|
||||
if (!ctx) return (-1);
|
||||
HMAC_CTX_init(ctx);
|
||||
HMAC_Init_ex(ctx, actx->pkey, cctx->keylen, EVP_sha512(), NULL);
|
||||
HMAC_Init_ex(ctx, cctx->pkey, cctx->keylen, EVP_sha512(), NULL);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = (HMAC_CTX *)malloc(sizeof (HMAC_CTX));
|
||||
|
@ -515,7 +533,7 @@ hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
|||
} else {
|
||||
HMAC_SHA512_Context *ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context));
|
||||
if (!ctx) return (-1);
|
||||
opt_HMAC_SHA512_Init(ctx, actx->pkey, cctx->keylen);
|
||||
opt_HMAC_SHA512_Init(ctx, cctx->pkey, cctx->keylen);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context));
|
||||
|
@ -538,7 +556,7 @@ hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
|||
if (Keccak_Init(ctx, 512) != 0)
|
||||
return (-1);
|
||||
}
|
||||
if (Keccak_Update(ctx, actx->pkey, cctx->keylen << 3) != 0)
|
||||
if (Keccak_Update(ctx, cctx->pkey, cctx->keylen << 3) != 0)
|
||||
return (-1);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
|
@ -719,13 +737,27 @@ hmac_cleanup(mac_ctx_t *mctx)
|
|||
*/
|
||||
int
|
||||
init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg,
|
||||
uchar_t *salt, int saltlen, int keylen, uint64_t nonce, int enc_dec)
|
||||
uchar_t *salt, int saltlen, int keylen, uchar_t *nonce, int enc_dec)
|
||||
{
|
||||
if (crypto_alg == CRYPTO_ALG_AES) {
|
||||
aes_ctx_t *actx = (aes_ctx_t *)malloc(sizeof (aes_ctx_t));
|
||||
aes_module_init(&proc_info);
|
||||
if (crypto_alg == CRYPTO_ALG_AES || crypto_alg == CRYPTO_ALG_SALSA20) {
|
||||
aes_ctx_t *actx;
|
||||
salsa20_ctx_t *sctx;
|
||||
|
||||
/* Silence compiler warnings */
|
||||
actx = NULL;
|
||||
sctx = NULL;
|
||||
|
||||
if (crypto_alg == CRYPTO_ALG_AES) {
|
||||
actx = (aes_ctx_t *)malloc(sizeof (aes_ctx_t));
|
||||
actx->keylen = keylen;
|
||||
cctx->pkey = actx->pkey;
|
||||
aes_module_init(&proc_info);
|
||||
} else {
|
||||
sctx = (salsa20_ctx_t *)malloc(sizeof (salsa20_ctx_t));
|
||||
sctx->keylen = keylen;
|
||||
cctx->pkey = sctx->pkey;
|
||||
}
|
||||
cctx->keylen = keylen;
|
||||
actx->keylen = keylen;
|
||||
|
||||
if (enc_dec) {
|
||||
/*
|
||||
|
@ -735,7 +767,7 @@ init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg,
|
|||
salt = cctx->salt;
|
||||
cctx->saltlen = 32;
|
||||
if (RAND_status() != 1 || RAND_bytes(salt, 32) != 1) {
|
||||
if (geturandom_bytes(salt) != 0) {
|
||||
if (geturandom_bytes(salt, 32) != 0) {
|
||||
uchar_t sb[64];
|
||||
int b;
|
||||
struct timespec tp;
|
||||
|
@ -765,9 +797,16 @@ init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg,
|
|||
/*
|
||||
* Zero nonce (arg #6) since it will be generated.
|
||||
*/
|
||||
if (aes_init(actx, salt, 32, pwd, pwd_len, 0, enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize AES context\n");
|
||||
return (-1);
|
||||
if (crypto_alg == CRYPTO_ALG_AES) {
|
||||
if (aes_init(actx, salt, 32, pwd, pwd_len, 0, enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize AES context\n");
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
if (salsa20_init(sctx, salt, 32, pwd, pwd_len, 0, enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize SALSA20 context\n");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -783,13 +822,24 @@ init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg,
|
|||
cctx->salt = (uchar_t *)malloc(saltlen);
|
||||
memcpy(cctx->salt, salt, saltlen);
|
||||
|
||||
if (aes_init(actx, cctx->salt, saltlen, pwd, pwd_len, nonce,
|
||||
enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize AES context\n");
|
||||
return (-1);
|
||||
if (crypto_alg == CRYPTO_ALG_AES) {
|
||||
if (aes_init(actx, cctx->salt, saltlen, pwd, pwd_len, *((uint64_t *)nonce),
|
||||
enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize AES context\n");
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
if (salsa20_init(sctx, salt, 32, pwd, pwd_len, nonce, enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize SALSA20 context\n");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
cctx->crypto_ctx = actx;
|
||||
if (crypto_alg == CRYPTO_ALG_AES) {
|
||||
cctx->crypto_ctx = actx;
|
||||
} else {
|
||||
cctx->crypto_ctx = sctx;
|
||||
}
|
||||
cctx->crypto_alg = crypto_alg;
|
||||
cctx->enc_dec = enc_dec;
|
||||
} else {
|
||||
|
@ -808,6 +858,12 @@ crypto_buf(crypto_ctx_t *cctx, uchar_t *from, uchar_t *to, uint64_t bytes, uint6
|
|||
} else {
|
||||
return (aes_decrypt((aes_ctx_t *)(cctx->crypto_ctx), from, to, bytes, id));
|
||||
}
|
||||
} else if (cctx->crypto_alg == CRYPTO_ALG_SALSA20) {
|
||||
if (cctx->enc_dec == ENCRYPT_FLAG) {
|
||||
return (salsa20_encrypt((salsa20_ctx_t *)(cctx->crypto_ctx), from, to, bytes, id));
|
||||
} else {
|
||||
return (salsa20_decrypt((salsa20_ctx_t *)(cctx->crypto_ctx), from, to, bytes, id));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized algorithm code: %d\n", cctx->crypto_alg);
|
||||
return (-1);
|
||||
|
@ -815,37 +871,56 @@ crypto_buf(crypto_ctx_t *cctx, uchar_t *from, uchar_t *to, uint64_t bytes, uint6
|
|||
return (0);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
uchar_t *
|
||||
crypto_nonce(crypto_ctx_t *cctx)
|
||||
{
|
||||
return (aes_nonce((aes_ctx_t *)(cctx->crypto_ctx)));
|
||||
if (cctx->crypto_alg == CRYPTO_ALG_AES) {
|
||||
return (aes_nonce((aes_ctx_t *)(cctx->crypto_ctx)));
|
||||
}
|
||||
return (salsa20_nonce((salsa20_ctx_t *)(cctx->crypto_ctx)));
|
||||
}
|
||||
|
||||
void
|
||||
crypto_clean_pkey(crypto_ctx_t *cctx)
|
||||
{
|
||||
aes_clean_pkey((aes_ctx_t *)(cctx->crypto_ctx));
|
||||
if (cctx->crypto_alg == CRYPTO_ALG_AES) {
|
||||
aes_clean_pkey((aes_ctx_t *)(cctx->crypto_ctx));
|
||||
} else {
|
||||
salsa20_clean_pkey((salsa20_ctx_t *)(cctx->crypto_ctx));
|
||||
}
|
||||
cctx->pkey = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_crypto(crypto_ctx_t *cctx)
|
||||
{
|
||||
aes_cleanup((aes_ctx_t *)(cctx->crypto_ctx));
|
||||
if (cctx->crypto_alg == CRYPTO_ALG_AES) {
|
||||
aes_cleanup((aes_ctx_t *)(cctx->crypto_ctx));
|
||||
} else {
|
||||
salsa20_cleanup((salsa20_ctx_t *)(cctx->crypto_ctx));
|
||||
}
|
||||
memset(cctx->salt, 0, 32);
|
||||
free(cctx->salt);
|
||||
free(cctx);
|
||||
}
|
||||
|
||||
static int
|
||||
geturandom_bytes(uchar_t rbytes[32])
|
||||
int
|
||||
geturandom_bytes(uchar_t *rbytes, int buflen)
|
||||
{
|
||||
int fd;
|
||||
int64_t lenread;
|
||||
uchar_t * buf = rbytes;
|
||||
uint64_t buflen = 32;
|
||||
|
||||
/* Open /dev/urandom. */
|
||||
if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
|
||||
/* Open /dev/urandom. Upto 10 retries. */
|
||||
fd = -1;
|
||||
lenread = 1;
|
||||
while (fd == -1 && lenread < 10) {
|
||||
if ((fd = open("/dev/urandom", O_RDONLY)) != -1)
|
||||
break;
|
||||
lenread++;
|
||||
sleep(1);
|
||||
}
|
||||
if (fd == -1)
|
||||
goto err0;
|
||||
|
||||
/* Read bytes until we have filled the buffer. */
|
||||
|
|
|
@ -47,10 +47,12 @@ extern "C" {
|
|||
#define MAX_KEYLEN DEFAULT_KEYLEN
|
||||
#endif
|
||||
|
||||
#define ENCRYPT_FLAG 1
|
||||
#define DECRYPT_FLAG 0
|
||||
#define CRYPTO_ALG_AES 0x10
|
||||
#define MAX_SALTLEN 64
|
||||
#define ENCRYPT_FLAG 1
|
||||
#define DECRYPT_FLAG 0
|
||||
#define CRYPTO_ALG_AES 0x10
|
||||
#define CRYPTO_ALG_SALSA20 0x20
|
||||
#define MAX_SALTLEN 64
|
||||
#define MAX_NONCE 32
|
||||
|
||||
#define KECCAK_MAX_SEG (2305843009213693950ULL)
|
||||
/*
|
||||
|
@ -80,6 +82,7 @@ typedef struct {
|
|||
int crypto_alg;
|
||||
int enc_dec;
|
||||
uchar_t *salt;
|
||||
uchar_t *pkey;
|
||||
int saltlen;
|
||||
int keylen;
|
||||
} crypto_ctx_t;
|
||||
|
@ -104,12 +107,14 @@ void deserialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes);
|
|||
* Encryption related functions.
|
||||
*/
|
||||
int init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg,
|
||||
uchar_t *salt, int saltlen, int keylen, uint64_t nonce, int enc_dec);
|
||||
uchar_t *salt, int saltlen, int keylen, uchar_t *nonce, int enc_dec);
|
||||
int crypto_buf(crypto_ctx_t *cctx, uchar_t *from, uchar_t *to, uint64_t bytes, uint64_t id);
|
||||
uint64_t crypto_nonce(crypto_ctx_t *cctx);
|
||||
uchar_t *crypto_nonce(crypto_ctx_t *cctx);
|
||||
void crypto_clean_pkey(crypto_ctx_t *cctx);
|
||||
void cleanup_crypto(crypto_ctx_t *cctx);
|
||||
int get_pw_string(uchar_t pw[MAX_PW_LEN], const char *prompt, int twice);
|
||||
int get_crypto_alg(char *name);
|
||||
int geturandom_bytes(uchar_t *rbytes, int nbytes);
|
||||
|
||||
/*
|
||||
* HMAC functions.
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define PBE_ROUNDS 50000
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
|
|
16
crypto/xsalsa20/crypto_core_hsalsa20.h
Normal file
16
crypto/xsalsa20/crypto_core_hsalsa20.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef crypto_core_hsalsa20_H
|
||||
#define crypto_core_hsalsa20_H
|
||||
|
||||
#define HSALSA_CRYPTO_OUTPUTBYTES 32
|
||||
#define HSALSA_CRYPTO_INPUTBYTES 16
|
||||
#define HSALSA_CRYPTO_CONSTBYTES 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int crypto_core_hsalsa20(unsigned char *out, const unsigned char *in, const unsigned char *k, const unsigned char *c);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
27
crypto/xsalsa20/crypto_stream_salsa20.h
Normal file
27
crypto/xsalsa20/crypto_stream_salsa20.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef crypto_stream_salsa20_H
|
||||
#define crypto_stream_salsa20_H
|
||||
|
||||
#define crypto_stream_salsa20_amd64_xmm6_KEYBYTES 32
|
||||
#define crypto_stream_salsa20_amd64_xmm6_NONCEBYTES 8
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern int crypto_stream_salsa20_amd64_xmm6(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
|
||||
extern int crypto_stream_salsa20_amd64_xmm6_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
|
||||
extern int crypto_stream_salsa20_ref(unsigned char *c,unsigned long long clen, const unsigned char *n, const unsigned char *k);
|
||||
extern int crypto_stream_salsa20_ref_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SALSA20_DEBUG
|
||||
#define crypto_stream_salsa20 crypto_stream_salsa20_amd64_xmm6
|
||||
#define crypto_stream_salsa20_xor crypto_stream_salsa20_amd64_xmm6_xor
|
||||
#else
|
||||
#define crypto_stream_salsa20 crypto_stream_salsa20_ref
|
||||
#define crypto_stream_salsa20_xor crypto_stream_salsa20_ref_xor
|
||||
#endif
|
||||
#define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_amd64_xmm6_KEYBYTES
|
||||
#define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_amd64_xmm6_NONCEBYTES
|
||||
|
||||
#endif
|
32
crypto/xsalsa20/crypto_xsalsa20.h
Normal file
32
crypto/xsalsa20/crypto_xsalsa20.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef crypto_xsalsa20_H
|
||||
#define crypto_xsalsa20_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <utils.h>
|
||||
|
||||
#define XSALSA20_CRYPTO_KEYBYTES 32
|
||||
#define XSALSA20_CRYPTO_NONCEBYTES 24
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned char nonce[XSALSA20_CRYPTO_NONCEBYTES];
|
||||
uchar_t key[XSALSA20_CRYPTO_KEYBYTES];
|
||||
int keylen;
|
||||
uchar_t pkey[XSALSA20_CRYPTO_KEYBYTES];
|
||||
} salsa20_ctx_t;
|
||||
|
||||
int salsa20_init(salsa20_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len, uchar_t *nonce, int enc);
|
||||
int salsa20_encrypt(salsa20_ctx_t *ctx, uchar_t *plaintext, uchar_t *ciphertext, uint64_t len, uint64_t id);
|
||||
int salsa20_decrypt(salsa20_ctx_t *ctx, uchar_t *ciphertext, uchar_t *plaintext, uint64_t len, uint64_t id);
|
||||
uchar_t *salsa20_nonce(salsa20_ctx_t *ctx);
|
||||
void salsa20_clean_pkey(salsa20_ctx_t *ctx);
|
||||
void salsa20_cleanup(salsa20_ctx_t *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
108
crypto/xsalsa20/hsalsa_core.c
Normal file
108
crypto/xsalsa20/hsalsa_core.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
version 20080912
|
||||
D. J. Bernstein
|
||||
Public domain.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <utils.h>
|
||||
|
||||
#define ROUNDS 20
|
||||
|
||||
static uint32_t
|
||||
rotate(uint32_t u,int c)
|
||||
{
|
||||
return (u << c) | (u >> (32 - c));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
load_littleendian(const unsigned char *x)
|
||||
{
|
||||
return
|
||||
(uint32_t) (x[0]) \
|
||||
| (((uint32_t) (x[1])) << 8) \
|
||||
| (((uint32_t) (x[2])) << 16) \
|
||||
| (((uint32_t) (x[3])) << 24)
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
store_littleendian(unsigned char *x, uint32_t u)
|
||||
{
|
||||
x[0] = u; u >>= 8;
|
||||
x[1] = u; u >>= 8;
|
||||
x[2] = u; u >>= 8;
|
||||
x[3] = u;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_core_hsalsa20(unsigned char *out,
|
||||
const unsigned char *in,
|
||||
const unsigned char *k,
|
||||
const unsigned char *c)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
|
||||
int i;
|
||||
|
||||
x0 = load_littleendian(c + 0);
|
||||
x1 = load_littleendian(k + 0);
|
||||
x2 = load_littleendian(k + 4);
|
||||
x3 = load_littleendian(k + 8);
|
||||
x4 = load_littleendian(k + 12);
|
||||
x5 = load_littleendian(c + 4);
|
||||
x6 = load_littleendian(in + 0);
|
||||
x7 = load_littleendian(in + 4);
|
||||
x8 = load_littleendian(in + 8);
|
||||
x9 = load_littleendian(in + 12);
|
||||
x10 = load_littleendian(c + 8);
|
||||
x11 = load_littleendian(k + 16);
|
||||
x12 = load_littleendian(k + 20);
|
||||
x13 = load_littleendian(k + 24);
|
||||
x14 = load_littleendian(k + 28);
|
||||
x15 = load_littleendian(c + 12);
|
||||
|
||||
for (i = ROUNDS;i > 0;i -= 2) {
|
||||
x4 ^= rotate( x0+x12, 7);
|
||||
x8 ^= rotate( x4+ x0, 9);
|
||||
x12 ^= rotate( x8+ x4,13);
|
||||
x0 ^= rotate(x12+ x8,18);
|
||||
x9 ^= rotate( x5+ x1, 7);
|
||||
x13 ^= rotate( x9+ x5, 9);
|
||||
x1 ^= rotate(x13+ x9,13);
|
||||
x5 ^= rotate( x1+x13,18);
|
||||
x14 ^= rotate(x10+ x6, 7);
|
||||
x2 ^= rotate(x14+x10, 9);
|
||||
x6 ^= rotate( x2+x14,13);
|
||||
x10 ^= rotate( x6+ x2,18);
|
||||
x3 ^= rotate(x15+x11, 7);
|
||||
x7 ^= rotate( x3+x15, 9);
|
||||
x11 ^= rotate( x7+ x3,13);
|
||||
x15 ^= rotate(x11+ x7,18);
|
||||
x1 ^= rotate( x0+ x3, 7);
|
||||
x2 ^= rotate( x1+ x0, 9);
|
||||
x3 ^= rotate( x2+ x1,13);
|
||||
x0 ^= rotate( x3+ x2,18);
|
||||
x6 ^= rotate( x5+ x4, 7);
|
||||
x7 ^= rotate( x6+ x5, 9);
|
||||
x4 ^= rotate( x7+ x6,13);
|
||||
x5 ^= rotate( x4+ x7,18);
|
||||
x11 ^= rotate(x10+ x9, 7);
|
||||
x8 ^= rotate(x11+x10, 9);
|
||||
x9 ^= rotate( x8+x11,13);
|
||||
x10 ^= rotate( x9+ x8,18);
|
||||
x12 ^= rotate(x15+x14, 7);
|
||||
x13 ^= rotate(x12+x15, 9);
|
||||
x14 ^= rotate(x13+x12,13);
|
||||
x15 ^= rotate(x14+x13,18);
|
||||
}
|
||||
|
||||
store_littleendian(out + 0,x0);
|
||||
store_littleendian(out + 4,x5);
|
||||
store_littleendian(out + 8,x10);
|
||||
store_littleendian(out + 12,x15);
|
||||
store_littleendian(out + 16,x6);
|
||||
store_littleendian(out + 20,x7);
|
||||
store_littleendian(out + 24,x8);
|
||||
store_littleendian(out + 28,x9);
|
||||
|
||||
return 0;
|
||||
}
|
216
crypto/xsalsa20/stream.c
Normal file
216
crypto/xsalsa20/stream.c
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
version 20080912
|
||||
D. J. Bernstein
|
||||
Public domain.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <utils.h>
|
||||
|
||||
#define ROUNDS 20
|
||||
static const unsigned char sigma[16] = "expand 32-byte k";
|
||||
|
||||
static uint32_t
|
||||
rotate(uint32_t u,int c)
|
||||
{
|
||||
return (u << c) | (u >> (32 - c));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
load_littleendian(const unsigned char *x)
|
||||
{
|
||||
return
|
||||
(uint32_t) (x[0]) \
|
||||
| (((uint32_t) (x[1])) << 8) \
|
||||
| (((uint32_t) (x[2])) << 16) \
|
||||
| (((uint32_t) (x[3])) << 24)
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
store_littleendian(unsigned char *x, uint32_t u)
|
||||
{
|
||||
x[0] = u; u >>= 8;
|
||||
x[1] = u; u >>= 8;
|
||||
x[2] = u; u >>= 8;
|
||||
x[3] = u;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_core(
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
const unsigned char *k,
|
||||
const unsigned char *c
|
||||
)
|
||||
{
|
||||
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 = load_littleendian(c + 0);
|
||||
j1 = x1 = load_littleendian(k + 0);
|
||||
j2 = x2 = load_littleendian(k + 4);
|
||||
j3 = x3 = load_littleendian(k + 8);
|
||||
j4 = x4 = load_littleendian(k + 12);
|
||||
j5 = x5 = load_littleendian(c + 4);
|
||||
j6 = x6 = load_littleendian(in + 0);
|
||||
j7 = x7 = load_littleendian(in + 4);
|
||||
j8 = x8 = load_littleendian(in + 8);
|
||||
j9 = x9 = load_littleendian(in + 12);
|
||||
j10 = x10 = load_littleendian(c + 8);
|
||||
j11 = x11 = load_littleendian(k + 16);
|
||||
j12 = x12 = load_littleendian(k + 20);
|
||||
j13 = x13 = load_littleendian(k + 24);
|
||||
j14 = x14 = load_littleendian(k + 28);
|
||||
j15 = x15 = load_littleendian(c + 12);
|
||||
|
||||
for (i = ROUNDS;i > 0;i -= 2) {
|
||||
x4 ^= rotate( x0+x12, 7);
|
||||
x8 ^= rotate( x4+ x0, 9);
|
||||
x12 ^= rotate( x8+ x4,13);
|
||||
x0 ^= rotate(x12+ x8,18);
|
||||
x9 ^= rotate( x5+ x1, 7);
|
||||
x13 ^= rotate( x9+ x5, 9);
|
||||
x1 ^= rotate(x13+ x9,13);
|
||||
x5 ^= rotate( x1+x13,18);
|
||||
x14 ^= rotate(x10+ x6, 7);
|
||||
x2 ^= rotate(x14+x10, 9);
|
||||
x6 ^= rotate( x2+x14,13);
|
||||
x10 ^= rotate( x6+ x2,18);
|
||||
x3 ^= rotate(x15+x11, 7);
|
||||
x7 ^= rotate( x3+x15, 9);
|
||||
x11 ^= rotate( x7+ x3,13);
|
||||
x15 ^= rotate(x11+ x7,18);
|
||||
x1 ^= rotate( x0+ x3, 7);
|
||||
x2 ^= rotate( x1+ x0, 9);
|
||||
x3 ^= rotate( x2+ x1,13);
|
||||
x0 ^= rotate( x3+ x2,18);
|
||||
x6 ^= rotate( x5+ x4, 7);
|
||||
x7 ^= rotate( x6+ x5, 9);
|
||||
x4 ^= rotate( x7+ x6,13);
|
||||
x5 ^= rotate( x4+ x7,18);
|
||||
x11 ^= rotate(x10+ x9, 7);
|
||||
x8 ^= rotate(x11+x10, 9);
|
||||
x9 ^= rotate( x8+x11,13);
|
||||
x10 ^= rotate( x9+ x8,18);
|
||||
x12 ^= rotate(x15+x14, 7);
|
||||
x13 ^= rotate(x12+x15, 9);
|
||||
x14 ^= rotate(x13+x12,13);
|
||||
x15 ^= rotate(x14+x13,18);
|
||||
}
|
||||
|
||||
x0 += j0;
|
||||
x1 += j1;
|
||||
x2 += j2;
|
||||
x3 += j3;
|
||||
x4 += j4;
|
||||
x5 += j5;
|
||||
x6 += j6;
|
||||
x7 += j7;
|
||||
x8 += j8;
|
||||
x9 += j9;
|
||||
x10 += j10;
|
||||
x11 += j11;
|
||||
x12 += j12;
|
||||
x13 += j13;
|
||||
x14 += j14;
|
||||
x15 += j15;
|
||||
|
||||
store_littleendian(out + 0,x0);
|
||||
store_littleendian(out + 4,x1);
|
||||
store_littleendian(out + 8,x2);
|
||||
store_littleendian(out + 12,x3);
|
||||
store_littleendian(out + 16,x4);
|
||||
store_littleendian(out + 20,x5);
|
||||
store_littleendian(out + 24,x6);
|
||||
store_littleendian(out + 28,x7);
|
||||
store_littleendian(out + 32,x8);
|
||||
store_littleendian(out + 36,x9);
|
||||
store_littleendian(out + 40,x10);
|
||||
store_littleendian(out + 44,x11);
|
||||
store_littleendian(out + 48,x12);
|
||||
store_littleendian(out + 52,x13);
|
||||
store_littleendian(out + 56,x14);
|
||||
store_littleendian(out + 60,x15);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_stream_salsa20_ref_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];
|
||||
int i;
|
||||
unsigned int u;
|
||||
|
||||
if (!mlen) return 0;
|
||||
|
||||
for (i = 0;i < 8;++i) in[i] = n[i];
|
||||
for (i = 8;i < 16;++i) in[i] = 0;
|
||||
|
||||
while (mlen >= 64) {
|
||||
crypto_core(block,in,k,sigma);
|
||||
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(block,in,k,sigma);
|
||||
for (i = 0;i < mlen;++i) c[i] = m[i] ^ block[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_stream_salsa20_ref(
|
||||
unsigned char *c,unsigned long long clen,
|
||||
const unsigned char *n,
|
||||
const unsigned char *k
|
||||
)
|
||||
{
|
||||
unsigned char in[16];
|
||||
unsigned char block[64];
|
||||
int i;
|
||||
unsigned int u;
|
||||
|
||||
if (!clen) return 0;
|
||||
|
||||
for (i = 0;i < 8;++i) in[i] = n[i];
|
||||
for (i = 8;i < 16;++i) in[i] = 0;
|
||||
|
||||
while (clen >= 64) {
|
||||
crypto_core(c,in,k,sigma);
|
||||
|
||||
u = 1;
|
||||
for (i = 8;i < 16;++i) {
|
||||
u += (unsigned int) in[i];
|
||||
in[i] = u;
|
||||
u >>= 8;
|
||||
}
|
||||
|
||||
clen -= 64;
|
||||
c += 64;
|
||||
}
|
||||
|
||||
if (clen) {
|
||||
crypto_core(block,in,k,sigma);
|
||||
for (i = 0;i < clen;++i) c[i] = block[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
4823
crypto/xsalsa20/stream.s
Normal file
4823
crypto/xsalsa20/stream.s
Normal file
File diff suppressed because it is too large
Load diff
140
crypto/xsalsa20/xsalsa20_xor.c
Normal file
140
crypto/xsalsa20/xsalsa20_xor.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
version 20080913
|
||||
D. J. Bernstein
|
||||
Public domain.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <crypto_scrypt.h>
|
||||
#include "crypto_core_hsalsa20.h"
|
||||
#include "crypto_stream_salsa20.h"
|
||||
#include "crypto_xsalsa20.h"
|
||||
|
||||
extern int geturandom_bytes(uchar_t *rbytes, int nbytes);
|
||||
|
||||
static const unsigned char sigma[16] = "expand 32-byte k";
|
||||
static const unsigned char tau[16] = "expand 16-byte k";
|
||||
|
||||
static int
|
||||
crypto_salsa20(unsigned char *c, const unsigned char *m, unsigned long long mlen,
|
||||
const unsigned char *n, const unsigned char *k, int klen)
|
||||
{
|
||||
unsigned char subkey[32];
|
||||
if (klen < XSALSA20_CRYPTO_KEYBYTES)
|
||||
crypto_core_hsalsa20(subkey,n,k,tau);
|
||||
else
|
||||
crypto_core_hsalsa20(subkey,n,k,sigma);
|
||||
return crypto_stream_salsa20_xor(c,m,mlen,n + 16,subkey);
|
||||
}
|
||||
|
||||
int
|
||||
salsa20_init(salsa20_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
|
||||
uchar_t *nonce, int enc)
|
||||
{
|
||||
struct timespec tp;
|
||||
uint64_t tv;
|
||||
uchar_t num[25];
|
||||
uchar_t IV[32];
|
||||
uchar_t *key = ctx->pkey;
|
||||
|
||||
#ifndef _USE_PBK
|
||||
int logN;
|
||||
uint32_t r, p;
|
||||
uint64_t N;
|
||||
|
||||
pickparams(&logN, &r, &p);
|
||||
N = (uint64_t)(1) << logN;
|
||||
if (crypto_scrypt(pwd, pwd_len, salt, saltlen, N, r, p, key, ctx->keylen)) {
|
||||
fprintf(stderr, "Scrypt failed\n");
|
||||
return (-1);
|
||||
}
|
||||
#else
|
||||
rv = PKCS5_PBKDF2_HMAC(pwd, pwd_len, salt, saltlen, PBE_ROUNDS, EVP_sha256(),
|
||||
ctx->keylen, key);
|
||||
if (rv != ctx->keylen) {
|
||||
fprintf(stderr, "Key size is %d bytes - should be %d bits\n", i, ctx->keylen);
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copy the key. XSalsa20 core cipher always uses a 256-bit key. If we are using a
|
||||
* 128-bit key then the key value is repeated twice to form a 256-bit value.
|
||||
* This approach is based on the Salsa20 code submitted to eSTREAM. See the function
|
||||
* ECRYPT_keysetup() in the Salsa20 submission:
|
||||
* http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/ref/salsa20.c?rev=161&view=auto
|
||||
*
|
||||
* The input values corresponding to a 256-bit key contain repeated values if key
|
||||
* length is 128-bit.
|
||||
*/
|
||||
memcpy(ctx->key, key, ctx->keylen);
|
||||
if (ctx->keylen < XSALSA20_CRYPTO_KEYBYTES) {
|
||||
uchar_t *k;
|
||||
k = ctx->key + ctx->keylen;
|
||||
memcpy(k, key, XSALSA20_CRYPTO_KEYBYTES - ctx->keylen);
|
||||
}
|
||||
if (enc) {
|
||||
|
||||
// Derive 192-bit nonce
|
||||
if (RAND_status() != 1 || RAND_bytes(IV, XSALSA20_CRYPTO_NONCEBYTES) != 1) {
|
||||
if (geturandom_bytes(IV, XSALSA20_CRYPTO_NONCEBYTES) != 0) {
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
|
||||
time((time_t *)&tv);
|
||||
} else {
|
||||
tv = tp.tv_sec * 1000UL + tp.tv_nsec;
|
||||
}
|
||||
sprintf((char *)num, "%" PRIu64, tv);
|
||||
PKCS5_PBKDF2_HMAC((const char *)num, strlen((char *)num), salt,
|
||||
saltlen, PBE_ROUNDS, EVP_sha256(), 32, IV);
|
||||
}
|
||||
}
|
||||
memcpy(ctx->nonce, IV, XSALSA20_CRYPTO_NONCEBYTES);
|
||||
|
||||
// Nullify stack components
|
||||
memset(num, 0, 25);
|
||||
memset(IV, 0, 32);
|
||||
memset(&tp, 0, sizeof (tp));
|
||||
tv = 0;
|
||||
} else {
|
||||
memcpy(ctx->nonce, nonce, XSALSA20_CRYPTO_NONCEBYTES);
|
||||
memset(nonce, 0, XSALSA20_CRYPTO_NONCEBYTES);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
salsa20_encrypt(salsa20_ctx_t *ctx, uchar_t *plaintext, uchar_t *ciphertext, uint64_t len, uint64_t id)
|
||||
{
|
||||
return (crypto_salsa20(ciphertext, plaintext, len, ctx->nonce + id, ctx->key, ctx->keylen));
|
||||
}
|
||||
|
||||
int
|
||||
salsa20_decrypt(salsa20_ctx_t *ctx, uchar_t *ciphertext, uchar_t *plaintext, uint64_t len, uint64_t id)
|
||||
{
|
||||
return (crypto_salsa20(plaintext, ciphertext, len, ctx->nonce + id, ctx->key, ctx->keylen));
|
||||
}
|
||||
|
||||
uchar_t *
|
||||
salsa20_nonce(salsa20_ctx_t *ctx)
|
||||
{
|
||||
return (ctx->nonce);
|
||||
}
|
||||
|
||||
void
|
||||
salsa20_clean_pkey(salsa20_ctx_t *ctx)
|
||||
{
|
||||
memset(ctx->pkey, 0, ctx->keylen);
|
||||
}
|
||||
|
||||
void
|
||||
salsa20_cleanup(salsa20_ctx_t *ctx)
|
||||
{
|
||||
memset((void *)(&ctx->key), 0, sizeof (ctx->key));
|
||||
memset(ctx->nonce, 0, XSALSA20_CRYPTO_NONCEBYTES);
|
||||
free(ctx);
|
||||
}
|
50
main.c
50
main.c
|
@ -50,6 +50,7 @@
|
|||
#include <transpose.h>
|
||||
#include <delta2/delta2.h>
|
||||
#include <crypto/crypto_utils.h>
|
||||
#include <crypto_xsalsa20.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
|
@ -797,9 +798,9 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
* If encryption is enabled initialize crypto.
|
||||
*/
|
||||
if (flags & MASK_CRYPTO_ALG) {
|
||||
int saltlen;
|
||||
int saltlen, noncelen;
|
||||
uchar_t *salt1, *salt2;
|
||||
uint64_t nonce, d3;
|
||||
uchar_t nonce[MAX_NONCE], n1[MAX_NONCE];
|
||||
uchar_t pw[MAX_PW_LEN];
|
||||
int pw_len;
|
||||
mac_ctx_t hdr_mac;
|
||||
|
@ -807,6 +808,7 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
unsigned int hlen;
|
||||
unsigned short d1;
|
||||
unsigned int d2;
|
||||
uint64_t d3;
|
||||
|
||||
/*
|
||||
* In encrypted files we do not have a normal digest. The HMAC
|
||||
|
@ -816,6 +818,15 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
pw_len = -1;
|
||||
compressed_chunksize += mac_bytes;
|
||||
encrypt_type = flags & MASK_CRYPTO_ALG;
|
||||
|
||||
if (encrypt_type == CRYPTO_ALG_AES) {
|
||||
noncelen = 8;
|
||||
} else if (encrypt_type == CRYPTO_ALG_SALSA20) {
|
||||
noncelen = XSALSA20_CRYPTO_NONCEBYTES;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid Encryption algorithm code: %d. File corrupt ?\n", encrypt_type);
|
||||
UNCOMP_BAIL;
|
||||
}
|
||||
if (Read(compfd, &saltlen, sizeof (saltlen)) < sizeof (saltlen)) {
|
||||
perror("Read: ");
|
||||
UNCOMP_BAIL;
|
||||
|
@ -830,7 +841,7 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
}
|
||||
deserialize_checksum(salt2, salt1, saltlen);
|
||||
|
||||
if (Read(compfd, &nonce, sizeof (nonce)) < sizeof (nonce)) {
|
||||
if (Read(compfd, n1, noncelen) < noncelen) {
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
memset(salt1, 0, saltlen);
|
||||
|
@ -838,7 +849,13 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
perror("Read: ");
|
||||
UNCOMP_BAIL;
|
||||
}
|
||||
nonce = ntohll(nonce);
|
||||
|
||||
if (encrypt_type == CRYPTO_ALG_AES) {
|
||||
*((uint64_t *)nonce) = ntohll(*((uint64_t *)n1));
|
||||
|
||||
} else if (encrypt_type == CRYPTO_ALG_SALSA20) {
|
||||
deserialize_checksum(nonce, n1, noncelen);
|
||||
}
|
||||
|
||||
if (version > 6) {
|
||||
if (Read(compfd, &keylen, sizeof (keylen)) < sizeof (keylen)) {
|
||||
|
@ -923,6 +940,7 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
memset(pw, 0, MAX_PW_LEN);
|
||||
memset(nonce, 0, noncelen);
|
||||
|
||||
/*
|
||||
* Verify file header HMAC.
|
||||
|
@ -937,15 +955,14 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
d1 = htons(flags);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (flags));
|
||||
d3 = htonll(chunksize);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d3, sizeof (nonce));
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d3, sizeof (chunksize));
|
||||
d2 = htonl(level);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (level));
|
||||
if (version > 6) {
|
||||
d2 = htonl(saltlen);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (saltlen));
|
||||
hmac_update(&hdr_mac, salt1, saltlen);
|
||||
nonce = htonll(nonce);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&nonce, sizeof (nonce));
|
||||
hmac_update(&hdr_mac, n1, noncelen);
|
||||
d2 = htonl(keylen);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (keylen));
|
||||
}
|
||||
|
@ -953,7 +970,7 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
hmac_cleanup(&hdr_mac);
|
||||
memset(salt1, 0, saltlen);
|
||||
free(salt1);
|
||||
nonce = 0;
|
||||
memset(n1, 0, noncelen);
|
||||
if (memcmp(hdr_hash2, hdr_hash1, mac_bytes) != 0) {
|
||||
close(uncompfd); unlink(to_filename);
|
||||
err_exit(0, "Header verification failed! File tampered or wrong password.\n");
|
||||
|
@ -1844,8 +1861,14 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
|||
pos += sizeof (int);
|
||||
serialize_checksum(crypto_ctx.salt, pos, crypto_ctx.saltlen);
|
||||
pos += crypto_ctx.saltlen;
|
||||
*((uint64_t *)pos) = htonll(crypto_nonce(&crypto_ctx));
|
||||
pos += 8;
|
||||
if (encrypt_type == CRYPTO_ALG_AES) {
|
||||
*((uint64_t *)pos) = htonll(*((uint64_t *)crypto_nonce(&crypto_ctx)));
|
||||
pos += 8;
|
||||
|
||||
} else if (encrypt_type == CRYPTO_ALG_SALSA20) {
|
||||
serialize_checksum(crypto_nonce(&crypto_ctx), pos, XSALSA20_CRYPTO_NONCEBYTES);
|
||||
pos += XSALSA20_CRYPTO_NONCEBYTES;
|
||||
}
|
||||
*((int *)pos) = htonl(keylen);
|
||||
pos += sizeof (int);
|
||||
}
|
||||
|
@ -2251,7 +2274,7 @@ main(int argc, char *argv[])
|
|||
slab_init();
|
||||
init_pcompress();
|
||||
|
||||
while ((opt = getopt(argc, argv, "dc:s:l:pt:MCDEew:rLPS:B:Fk:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "dc:s:l:pt:MCDEe:w:rLPS:B:Fk:")) != -1) {
|
||||
int ovr;
|
||||
|
||||
switch (opt) {
|
||||
|
@ -2325,7 +2348,10 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
|
||||
case 'e':
|
||||
encrypt_type = CRYPTO_ALG_AES;
|
||||
encrypt_type = get_crypto_alg(optarg);
|
||||
if (encrypt_type == 0) {
|
||||
err_exit(0, "Invalid encryption algorithm. Should be AES or SALSA20.\n", optarg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
|
|
Loading…
Reference in a new issue