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:
Moinak Ghosh 2013-03-04 21:56:07 +05:30
parent e16b408061
commit 20250aa5dc
15 changed files with 5568 additions and 74 deletions

View file

@ -29,15 +29,22 @@ MAINHDRS = allocator.h pcompress.h utils/utils.h utils/xxhash.h utils/heapq.h
utils/cpuid.h utils/xxhash.h utils/cpuid.h utils/xxhash.h
MAINOBJS = $(MAINSRCS:.c=.o) 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_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/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_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/scrypt/sha256.h crypto/scrypt/crypto_aesctr.h crypto/aes/crypto_aes.h \
crypto/sha2_utils.h crypto/sha3_utils.h $(MAINHDRS) crypto/sha2_utils.h crypto/sha3_utils.h crypto/xsalsa20/crypto_core_hsalsa20.h \
CRYPTO_ASM_SRCS = crypto/aes/vpaes-x86_64.s crypto/aes/aesni-x86_64.s crypto/xsalsa20/crypto_stream_salsa20.h crypto/xsalsa20/crypto_xsalsa20.h \
CRYPTO_ASM_OBJS = crypto/aes/vpaes-x86_64.o crypto/aes/aesni-x86_64.o $(MAINHDRS)
CRYPTO_ASM_HDRS = crypto/aes/crypto_aes.h 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_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_COMPAT_HDRS = crypto/old/sha2_utils_old.h crypto/old/sha3_utils_old.h
CRYPTO_OBJS = $(CRYPTO_SRCS:.c=.o) 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 \ -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./lzp @LIBBSCCPPFLAGS@ -I./crypto/skein -I./utils -I./crypto/sha2 \
-I./crypto/scrypt -I./crypto/aes -I./crypto @KEYLEN@ -I./rabin/global \ -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 \ -fno-strict-aliasing -Wno-unused-but-set-variable -Wno-enum-compare \
@COMPAT_CPPFLAGS@ @COMPAT_CPPFLAGS@ @XSALSA20_DEBUG@
COMMON_VEC_FLAGS = -ftree-vectorize COMMON_VEC_FLAGS = -ftree-vectorize
COMMON_LOOP_OPTFLAGS = $(VEC_FLAGS) -floop-interchange -floop-block 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@ \ LDLIBS = -ldl -L./buildtmp -Wl,-R@LIBBZ2_DIR@ -lbz2 -L./buildtmp -Wl,-R@LIBZ_DIR@ -lz -lm @LIBBSCLFLAGS@ \

12
config
View file

@ -63,6 +63,9 @@ sse_detect=1
sse_opt_flags="-msse2" sse_opt_flags="-msse2"
crypto_compat_objs='\$\(CRYPTO_COMPAT_OBJS\)' crypto_compat_objs='\$\(CRYPTO_COMPAT_OBJS\)'
crypto_compat_flags="-D__HASH_COMPATIBILITY_" crypto_compat_flags="-D__HASH_COMPATIBILITY_"
salsa20_stream_c=
salsa20_stream_asm='\$\(XSALSA20_STREAM_ASM\)'
salsa20_debug=
rm -rf ./buildtmp rm -rf ./buildtmp
mkdir ./buildtmp mkdir ./buildtmp
@ -168,6 +171,9 @@ done
if [ $debug -eq 1 ] if [ $debug -eq 1 ]
then then
typ="DEBUG" typ="DEBUG"
salsa20_stream_c='\$\(XSALSA20_STREAM_C\)'
salsa20_stream_asm=
salsa20_debug='\$\(XSALSA20_DEBUG\)'
else else
typ="RELEASE" typ="RELEASE"
fi fi
@ -523,6 +529,9 @@ keccak_srcs_asm_var="KECCAK_SRCS_ASM"
crypto_compat_objs_var="CRYPTO_COMPAT_OBJS" crypto_compat_objs_var="CRYPTO_COMPAT_OBJS"
crypto_compat_flags_var="COMPAT_CPPFLAGS" 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= noslabcppflagsval=
debugstatscppflagsval= debugstatscppflagsval=
@ -567,5 +576,8 @@ s#@${extra_opt_flags_var}@#${extra_opt_flags}#g
s#@${sse_opt_flags_var}@#${sse_opt_flags}#g s#@${sse_opt_flags_var}@#${sse_opt_flags}#g
s#@${crypto_compat_objs_var}@#${crypto_compat_objs}#g s#@${crypto_compat_objs_var}@#${crypto_compat_objs}#g
s#@${crypto_compat_flags_var}@#${crypto_compat_flags}#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 " > Makefile

View file

@ -58,12 +58,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <openssl/rand.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <crypto_scrypt.h> #include <crypto_scrypt.h>
#include <crypto_aesctr.h> #include <crypto_aesctr.h>
#include <utils.h> #include <utils.h>
#include "crypto_aes.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 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 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); 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) { if (enc) {
enc_setkey(key, (ctx->keylen << 3), &(ctx->key)); enc_setkey(key, (ctx->keylen << 3), &(ctx->key));
// Derive nonce from salt // Derive 64-bit nonce
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) { if (RAND_status() != 1 || RAND_bytes((uchar_t *)&(ctx->nonce), 8) != 1) {
time((time_t *)&tv); if (geturandom_bytes((uchar_t *)&(ctx->nonce), 8) != 0) {
} else { if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
tv = tp.tv_sec * 1000UL + tp.tv_nsec; 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 // Nullify stack components
memset(num, 0, 25); memset(num, 0, 25);
memset(IV, 0, 32); 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); return (0);
} }
uint64_t uchar_t *
aes_nonce(aes_ctx_t *ctx) aes_nonce(aes_ctx_t *ctx)
{ {
return (ctx->nonce); return ((uchar_t *)&(ctx->nonce));
} }
void void

View file

@ -36,8 +36,6 @@
extern "C" { extern "C" {
#endif #endif
#define PBE_ROUNDS 1000
typedef struct { typedef struct {
uint64_t nonce; uint64_t nonce;
AES_KEY key; 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); 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_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); 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_clean_pkey(aes_ctx_t *ctx);
void aes_cleanup(aes_ctx_t *ctx); void aes_cleanup(aes_ctx_t *ctx);
void aes_module_init(processor_info_t *pc); void aes_module_init(processor_info_t *pc);

View file

@ -41,6 +41,7 @@
#include <crypto_aes.h> #include <crypto_aes.h>
#include <KeccakNISTInterface.h> #include <KeccakNISTInterface.h>
#include <utils.h> #include <utils.h>
#include <crypto_xsalsa20.h>
#include "crypto_utils.h" #include "crypto_utils.h"
#include "sha2_utils.h" #include "sha2_utils.h"
@ -56,7 +57,6 @@
static void init_sha512(void); static void init_sha512(void);
static void init_blake2(void); static void init_blake2(void);
static int geturandom_bytes(uchar_t rbytes[32]);
static struct blake2_dispatch bdsp; static struct blake2_dispatch bdsp;
/* /*
@ -173,6 +173,25 @@ PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
} }
#endif #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 * 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 * 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 int
hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx) 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; mctx->mac_cksum = cksum;
if (cksum == CKSUM_BLAKE256) { if (cksum == CKSUM_BLAKE256) {
blake2b_state *ctx = (blake2b_state *)malloc(sizeof (blake2b_state)); blake2b_state *ctx = (blake2b_state *)malloc(sizeof (blake2b_state));
if (!ctx) return (-1); 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); return (-1);
mctx->mac_ctx = ctx; mctx->mac_ctx = ctx;
ctx = (blake2b_state *)malloc(sizeof (blake2b_state)); 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) { } else if (cksum == CKSUM_BLAKE512) {
blake2b_state *ctx = (blake2b_state *)malloc(sizeof (blake2b_state)); blake2b_state *ctx = (blake2b_state *)malloc(sizeof (blake2b_state));
if (!ctx) return (-1); 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); return (-1);
mctx->mac_ctx = ctx; mctx->mac_ctx = ctx;
ctx = (blake2b_state *)malloc(sizeof (blake2b_state)); 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)); Skein_512_Ctxt_t *ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
if (!ctx) return (-1); if (!ctx) return (-1);
Skein_512_InitExt(ctx, 256, SKEIN_CFG_TREE_INFO_SEQUENTIAL, Skein_512_InitExt(ctx, 256, SKEIN_CFG_TREE_INFO_SEQUENTIAL,
actx->pkey, cctx->keylen); cctx->pkey, cctx->keylen);
mctx->mac_ctx = ctx; mctx->mac_ctx = ctx;
ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t)); ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
if (!ctx) { 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)); Skein_512_Ctxt_t *ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
if (!ctx) return (-1); if (!ctx) return (-1);
Skein_512_InitExt(ctx, 512, SKEIN_CFG_TREE_INFO_SEQUENTIAL, Skein_512_InitExt(ctx, 512, SKEIN_CFG_TREE_INFO_SEQUENTIAL,
actx->pkey, cctx->keylen); cctx->pkey, cctx->keylen);
mctx->mac_ctx = ctx; mctx->mac_ctx = ctx;
ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t)); ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
if (!ctx) { 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)); HMAC_CTX *ctx = (HMAC_CTX *)malloc(sizeof (HMAC_CTX));
if (!ctx) return (-1); if (!ctx) return (-1);
HMAC_CTX_init(ctx); 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; mctx->mac_ctx = ctx;
ctx = (HMAC_CTX *)malloc(sizeof (HMAC_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 { } else {
HMAC_SHA512_Context *ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context)); HMAC_SHA512_Context *ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context));
if (!ctx) return (-1); 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; mctx->mac_ctx = ctx;
ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context)); 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)); HMAC_CTX *ctx = (HMAC_CTX *)malloc(sizeof (HMAC_CTX));
if (!ctx) return (-1); if (!ctx) return (-1);
HMAC_CTX_init(ctx); 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; mctx->mac_ctx = ctx;
ctx = (HMAC_CTX *)malloc(sizeof (HMAC_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 { } else {
HMAC_SHA512_Context *ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context)); HMAC_SHA512_Context *ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context));
if (!ctx) return (-1); 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; mctx->mac_ctx = ctx;
ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context)); 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) if (Keccak_Init(ctx, 512) != 0)
return (-1); return (-1);
} }
if (Keccak_Update(ctx, actx->pkey, cctx->keylen << 3) != 0) if (Keccak_Update(ctx, cctx->pkey, cctx->keylen << 3) != 0)
return (-1); return (-1);
mctx->mac_ctx = ctx; mctx->mac_ctx = ctx;
@ -719,13 +737,27 @@ hmac_cleanup(mac_ctx_t *mctx)
*/ */
int int
init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg, 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) { if (crypto_alg == CRYPTO_ALG_AES || crypto_alg == CRYPTO_ALG_SALSA20) {
aes_ctx_t *actx = (aes_ctx_t *)malloc(sizeof (aes_ctx_t)); aes_ctx_t *actx;
aes_module_init(&proc_info); 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; cctx->keylen = keylen;
actx->keylen = keylen;
if (enc_dec) { 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; salt = cctx->salt;
cctx->saltlen = 32; cctx->saltlen = 32;
if (RAND_status() != 1 || RAND_bytes(salt, 32) != 1) { if (RAND_status() != 1 || RAND_bytes(salt, 32) != 1) {
if (geturandom_bytes(salt) != 0) { if (geturandom_bytes(salt, 32) != 0) {
uchar_t sb[64]; uchar_t sb[64];
int b; int b;
struct timespec tp; 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. * Zero nonce (arg #6) since it will be generated.
*/ */
if (aes_init(actx, salt, 32, pwd, pwd_len, 0, enc_dec) != 0) { if (crypto_alg == CRYPTO_ALG_AES) {
fprintf(stderr, "Failed to initialize AES context\n"); if (aes_init(actx, salt, 32, pwd, pwd_len, 0, enc_dec) != 0) {
return (-1); 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 { } 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); cctx->salt = (uchar_t *)malloc(saltlen);
memcpy(cctx->salt, salt, saltlen); memcpy(cctx->salt, salt, saltlen);
if (aes_init(actx, cctx->salt, saltlen, pwd, pwd_len, nonce, if (crypto_alg == CRYPTO_ALG_AES) {
enc_dec) != 0) { if (aes_init(actx, cctx->salt, saltlen, pwd, pwd_len, *((uint64_t *)nonce),
fprintf(stderr, "Failed to initialize AES context\n"); enc_dec) != 0) {
return (-1); 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->crypto_alg = crypto_alg;
cctx->enc_dec = enc_dec; cctx->enc_dec = enc_dec;
} else { } else {
@ -808,6 +858,12 @@ crypto_buf(crypto_ctx_t *cctx, uchar_t *from, uchar_t *to, uint64_t bytes, uint6
} else { } else {
return (aes_decrypt((aes_ctx_t *)(cctx->crypto_ctx), from, to, bytes, id)); 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 { } else {
fprintf(stderr, "Unrecognized algorithm code: %d\n", cctx->crypto_alg); fprintf(stderr, "Unrecognized algorithm code: %d\n", cctx->crypto_alg);
return (-1); return (-1);
@ -815,37 +871,56 @@ crypto_buf(crypto_ctx_t *cctx, uchar_t *from, uchar_t *to, uint64_t bytes, uint6
return (0); return (0);
} }
uint64_t uchar_t *
crypto_nonce(crypto_ctx_t *cctx) 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 void
crypto_clean_pkey(crypto_ctx_t *cctx) 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 void
cleanup_crypto(crypto_ctx_t *cctx) 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); memset(cctx->salt, 0, 32);
free(cctx->salt); free(cctx->salt);
free(cctx); free(cctx);
} }
static int int
geturandom_bytes(uchar_t rbytes[32]) geturandom_bytes(uchar_t *rbytes, int buflen)
{ {
int fd; int fd;
int64_t lenread; int64_t lenread;
uchar_t * buf = rbytes; uchar_t * buf = rbytes;
uint64_t buflen = 32;
/* Open /dev/urandom. */ /* Open /dev/urandom. Upto 10 retries. */
if ((fd = open("/dev/urandom", O_RDONLY)) == -1) 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; goto err0;
/* Read bytes until we have filled the buffer. */ /* Read bytes until we have filled the buffer. */

View file

@ -47,10 +47,12 @@ extern "C" {
#define MAX_KEYLEN DEFAULT_KEYLEN #define MAX_KEYLEN DEFAULT_KEYLEN
#endif #endif
#define ENCRYPT_FLAG 1 #define ENCRYPT_FLAG 1
#define DECRYPT_FLAG 0 #define DECRYPT_FLAG 0
#define CRYPTO_ALG_AES 0x10 #define CRYPTO_ALG_AES 0x10
#define MAX_SALTLEN 64 #define CRYPTO_ALG_SALSA20 0x20
#define MAX_SALTLEN 64
#define MAX_NONCE 32
#define KECCAK_MAX_SEG (2305843009213693950ULL) #define KECCAK_MAX_SEG (2305843009213693950ULL)
/* /*
@ -80,6 +82,7 @@ typedef struct {
int crypto_alg; int crypto_alg;
int enc_dec; int enc_dec;
uchar_t *salt; uchar_t *salt;
uchar_t *pkey;
int saltlen; int saltlen;
int keylen; int keylen;
} crypto_ctx_t; } crypto_ctx_t;
@ -104,12 +107,14 @@ void deserialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes);
* Encryption related functions. * Encryption related functions.
*/ */
int init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg, 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); 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 crypto_clean_pkey(crypto_ctx_t *cctx);
void cleanup_crypto(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_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. * HMAC functions.

View file

@ -32,6 +32,8 @@
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#define PBE_ROUNDS 50000
/** /**
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,

View 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

View 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

View 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

View 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
View 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

File diff suppressed because it is too large Load diff

View 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
View file

@ -50,6 +50,7 @@
#include <transpose.h> #include <transpose.h>
#include <delta2/delta2.h> #include <delta2/delta2.h>
#include <crypto/crypto_utils.h> #include <crypto/crypto_utils.h>
#include <crypto_xsalsa20.h>
#include <ctype.h> #include <ctype.h>
/* /*
@ -797,9 +798,9 @@ start_decompress(const char *filename, const char *to_filename)
* If encryption is enabled initialize crypto. * If encryption is enabled initialize crypto.
*/ */
if (flags & MASK_CRYPTO_ALG) { if (flags & MASK_CRYPTO_ALG) {
int saltlen; int saltlen, noncelen;
uchar_t *salt1, *salt2; uchar_t *salt1, *salt2;
uint64_t nonce, d3; uchar_t nonce[MAX_NONCE], n1[MAX_NONCE];
uchar_t pw[MAX_PW_LEN]; uchar_t pw[MAX_PW_LEN];
int pw_len; int pw_len;
mac_ctx_t hdr_mac; mac_ctx_t hdr_mac;
@ -807,6 +808,7 @@ start_decompress(const char *filename, const char *to_filename)
unsigned int hlen; unsigned int hlen;
unsigned short d1; unsigned short d1;
unsigned int d2; unsigned int d2;
uint64_t d3;
/* /*
* In encrypted files we do not have a normal digest. The HMAC * 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; pw_len = -1;
compressed_chunksize += mac_bytes; compressed_chunksize += mac_bytes;
encrypt_type = flags & MASK_CRYPTO_ALG; 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)) { if (Read(compfd, &saltlen, sizeof (saltlen)) < sizeof (saltlen)) {
perror("Read: "); perror("Read: ");
UNCOMP_BAIL; UNCOMP_BAIL;
@ -830,7 +841,7 @@ start_decompress(const char *filename, const char *to_filename)
} }
deserialize_checksum(salt2, salt1, saltlen); deserialize_checksum(salt2, salt1, saltlen);
if (Read(compfd, &nonce, sizeof (nonce)) < sizeof (nonce)) { if (Read(compfd, n1, noncelen) < noncelen) {
memset(salt2, 0, saltlen); memset(salt2, 0, saltlen);
free(salt2); free(salt2);
memset(salt1, 0, saltlen); memset(salt1, 0, saltlen);
@ -838,7 +849,13 @@ start_decompress(const char *filename, const char *to_filename)
perror("Read: "); perror("Read: ");
UNCOMP_BAIL; 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 (version > 6) {
if (Read(compfd, &keylen, sizeof (keylen)) < sizeof (keylen)) { 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); memset(salt2, 0, saltlen);
free(salt2); free(salt2);
memset(pw, 0, MAX_PW_LEN); memset(pw, 0, MAX_PW_LEN);
memset(nonce, 0, noncelen);
/* /*
* Verify file header HMAC. * Verify file header HMAC.
@ -937,15 +955,14 @@ start_decompress(const char *filename, const char *to_filename)
d1 = htons(flags); d1 = htons(flags);
hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (flags)); hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (flags));
d3 = htonll(chunksize); d3 = htonll(chunksize);
hmac_update(&hdr_mac, (uchar_t *)&d3, sizeof (nonce)); hmac_update(&hdr_mac, (uchar_t *)&d3, sizeof (chunksize));
d2 = htonl(level); d2 = htonl(level);
hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (level)); hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (level));
if (version > 6) { if (version > 6) {
d2 = htonl(saltlen); d2 = htonl(saltlen);
hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (saltlen)); hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (saltlen));
hmac_update(&hdr_mac, salt1, saltlen); hmac_update(&hdr_mac, salt1, saltlen);
nonce = htonll(nonce); hmac_update(&hdr_mac, n1, noncelen);
hmac_update(&hdr_mac, (uchar_t *)&nonce, sizeof (nonce));
d2 = htonl(keylen); d2 = htonl(keylen);
hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (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); hmac_cleanup(&hdr_mac);
memset(salt1, 0, saltlen); memset(salt1, 0, saltlen);
free(salt1); free(salt1);
nonce = 0; memset(n1, 0, noncelen);
if (memcmp(hdr_hash2, hdr_hash1, mac_bytes) != 0) { if (memcmp(hdr_hash2, hdr_hash1, mac_bytes) != 0) {
close(uncompfd); unlink(to_filename); close(uncompfd); unlink(to_filename);
err_exit(0, "Header verification failed! File tampered or wrong password.\n"); 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); pos += sizeof (int);
serialize_checksum(crypto_ctx.salt, pos, crypto_ctx.saltlen); serialize_checksum(crypto_ctx.salt, pos, crypto_ctx.saltlen);
pos += crypto_ctx.saltlen; pos += crypto_ctx.saltlen;
*((uint64_t *)pos) = htonll(crypto_nonce(&crypto_ctx)); if (encrypt_type == CRYPTO_ALG_AES) {
pos += 8; *((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); *((int *)pos) = htonl(keylen);
pos += sizeof (int); pos += sizeof (int);
} }
@ -2251,7 +2274,7 @@ main(int argc, char *argv[])
slab_init(); slab_init();
init_pcompress(); 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; int ovr;
switch (opt) { switch (opt) {
@ -2325,7 +2348,10 @@ main(int argc, char *argv[])
break; break;
case 'e': 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; break;
case 'w': case 'w':