Change default encryption key length to 256 bits.
Add optional ability to change key length at runtime via cli option. Include key length property in archive header. Fix header HMAC to include salt, nonce and key length properties. Retain backward compatibility to handle older format archives. Fix compilation of AES ASM code.
This commit is contained in:
parent
72b23dac1a
commit
7a29c7be1e
8 changed files with 132 additions and 58 deletions
|
@ -287,7 +287,7 @@ $(CRYPTO_OBJS): $(CRYPTO_SRCS) $(CRYPTO_HDRS) $(CRYPTO_ASM_OBJS)
|
|||
$(COMPILE) $(GEN_OPT) $(CRYPTO_CPPFLAGS) $(CPPFLAGS) $(@:.o=.c) -o $@
|
||||
|
||||
$(CRYPTO_ASM_OBJS): $(CRYPTO_ASM_SRCS) $(CRYPTO_ASM_HDRS)
|
||||
$(YASM) -o $@ $(@:.o=.s)
|
||||
$(COMPILE) $(GEN_OPT) $(CRYPTO_CPPFLAGS) $(CPPFLAGS) -o $@ $(@:.o=.s)
|
||||
|
||||
$(CRYPTO_COMPAT_OBJS): $(CRYPTO_COMPAT_SRCS) $(CRYPTO_COMPAT_HDRS)
|
||||
$(COMPILE) $(GEN_OPT) $(CRYPTO_CPPFLAGS) $(CPPFLAGS) $(@:.o=.c) -o $@
|
||||
|
|
16
README.md
16
README.md
|
@ -131,13 +131,11 @@ NOTE: The option "libbsc" uses Ilya Grebnov's block sorting compression library
|
|||
'-C' - Display compression statistics
|
||||
|
||||
Encryption flags:
|
||||
'-e' Encrypt chunks with AES. The password can be prompted from the user
|
||||
or read from a file. Whether 128-Bit or 256-Bit keys are used depends
|
||||
on how the pcompress binary was built. Default build uses 128-Bit keys.
|
||||
Unique keys are generated every time pcompress is run even when giving
|
||||
the same password. Of course enough info is stored in the compressed
|
||||
file so that the key used for the file can be re-created given the
|
||||
correct password.
|
||||
'-e' Encrypt chunks with AES-CTR. The password can be prompted from the user
|
||||
or read from a file. Unique keys are generated every time pcompress is
|
||||
run even when giving the same password. Of course enough info is stored\
|
||||
in the compresse file so that the key used for the file can be
|
||||
re-created given the correct password.
|
||||
|
||||
The Scrypt algorithm from Tarsnap is used
|
||||
(See: http://www.tarsnap.com/scrypt.html) for generating keys from
|
||||
|
@ -148,6 +146,10 @@ NOTE: The option "libbsc" uses Ilya Grebnov's block sorting compression library
|
|||
be readable and writable since it is zeroed out after the password is
|
||||
read.
|
||||
|
||||
'-k <key length>'
|
||||
Specify the key length. Can be 16 for 128 bit keys or 32 for 256 bit
|
||||
keys. Default value is 23 for 256 bit keys.
|
||||
|
||||
NOTE: When using pipe-mode via -p the only way to provide a password is to use '-w'.
|
||||
|
||||
Environment Variables
|
||||
|
|
21
config
21
config
|
@ -13,20 +13,21 @@ ${prog} [<options>]
|
|||
--enable-debug-stats Enable printing of some verbose debug info (default: disabled).
|
||||
--with-libbsc=<path to libbsc source>
|
||||
Enable support for libbsc (See: libbsc.com). Full path to the libbsc
|
||||
source tree must be provided. It links the library statically.
|
||||
source tree must be provided. It links the library statically.
|
||||
--with-openssl=<path to OpenSSL installation tree> (Default: System)
|
||||
This defaults to the system's OpenSSL library. You can use this option
|
||||
if you want to use an alternate OpenSSL installation.
|
||||
This defaults to the system's OpenSSL library. You can use this option
|
||||
if you want to use an alternate OpenSSL installation.
|
||||
--with-zlib=<path to zlib installation tree> (Default: System)
|
||||
Enable building against an alternate Zlib installation.
|
||||
Enable building against an alternate Zlib installation.
|
||||
--with-bzlib=<path to Bzip2 library installation tree> (Default: System)
|
||||
Enable building against an alternate Bzip2 and library installation.
|
||||
Enable building against an alternate Bzip2 and library installation.
|
||||
--no-sse-detect Do NOT attempt to probe the system's SSE/AVX capability for build flags.
|
||||
--no-1.3-archive-compat Disable compatibility with compressed archives created with Pcompress
|
||||
version 1.3 (default: retain compatibility). Hash formats changed from
|
||||
version 1.3 to 1.4 so this option is required if files created using
|
||||
1.3 need to be decompressed by version 1.4 onwards.
|
||||
--use-key256 Use 256-bit encryption keys. Default key length is 128-bit.
|
||||
version 1.3 (default: retain compatibility). Hash formats changed from
|
||||
version 1.3 to 1.4 so this option is required if files created using
|
||||
1.3 need to be decompressed by version 1.4 onwards.
|
||||
--limit-key128 Limit key length to 128-bit encryption keys. Otherwise the default is to
|
||||
use 256-bit keys changeable at runtime via the '-k <keylen>' option.
|
||||
--help Display this help message.
|
||||
|
||||
_EOF
|
||||
|
@ -145,7 +146,7 @@ do
|
|||
bzlib_prefix=`echo ${arg1} | cut -f2 -d"="`
|
||||
;;
|
||||
--use-key256)
|
||||
keylen='-DKEYLEN=32'
|
||||
keylen='-DDEFAULT_KEYLEN=16'
|
||||
;;
|
||||
--no-sse-detect)
|
||||
sse_detect=0
|
||||
|
|
|
@ -149,21 +149,21 @@ aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
|
|||
|
||||
pickparams(&logN, &r, &p);
|
||||
N = (uint64_t)(1) << logN;
|
||||
if (crypto_scrypt(pwd, pwd_len, salt, saltlen, N, r, p, key, KEYLEN)) {
|
||||
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(),
|
||||
KEYLEN, key);
|
||||
if (rv != KEYLEN) {
|
||||
fprintf(stderr, "Key size is %d bytes - should be %d bits\n", i, KEYLEN);
|
||||
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
|
||||
|
||||
if (enc) {
|
||||
enc_setkey(key, (KEYLEN << 3), &(ctx->key));
|
||||
enc_setkey(key, (ctx->keylen << 3), &(ctx->key));
|
||||
// Derive nonce from salt
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
|
||||
time((time_t *)&tv);
|
||||
|
@ -181,7 +181,7 @@ aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
|
|||
tv = 0;
|
||||
} else {
|
||||
ctx->nonce = nonce;
|
||||
enc_setkey(key, (KEYLEN << 3), &(ctx->key));
|
||||
enc_setkey(key, (ctx->keylen << 3), &(ctx->key));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ aes_nonce(aes_ctx_t *ctx)
|
|||
void
|
||||
aes_clean_pkey(aes_ctx_t *ctx)
|
||||
{
|
||||
memset(ctx->pkey, 0, KEYLEN);
|
||||
memset(ctx->pkey, 0, ctx->keylen);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -30,20 +30,19 @@
|
|||
#include <openssl/evp.h>
|
||||
#endif
|
||||
#include <openssl/opensslv.h>
|
||||
#include <crypto_utils.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef KEYLEN
|
||||
#define KEYLEN 16
|
||||
#endif
|
||||
#define PBE_ROUNDS 1000
|
||||
|
||||
typedef struct {
|
||||
uint64_t nonce;
|
||||
AES_KEY key;
|
||||
uchar_t pkey[KEYLEN];
|
||||
int keylen;
|
||||
uchar_t pkey[MAX_KEYLEN];
|
||||
} aes_ctx_t;
|
||||
|
||||
int aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
|
||||
|
|
|
@ -407,7 +407,7 @@ hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
|||
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, KEYLEN) != 0)
|
||||
if (bdsp.blake2b_init_key(ctx, 32, actx->pkey, cctx->keylen) != 0)
|
||||
return (-1);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = (blake2b_state *)malloc(sizeof (blake2b_state));
|
||||
|
@ -421,7 +421,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, KEYLEN) != 0)
|
||||
if (bdsp.blake2b_init_key(ctx, 64, actx->pkey, cctx->keylen) != 0)
|
||||
return (-1);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = (blake2b_state *)malloc(sizeof (blake2b_state));
|
||||
|
@ -436,7 +436,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, KEYLEN);
|
||||
actx->pkey, cctx->keylen);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) {
|
||||
|
@ -450,7 +450,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, KEYLEN);
|
||||
actx->pkey, cctx->keylen);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = (Skein_512_Ctxt_t *)malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) {
|
||||
|
@ -465,7 +465,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, KEYLEN, EVP_sha256(), NULL);
|
||||
HMAC_Init_ex(ctx, actx->pkey, cctx->keylen, EVP_sha256(), NULL);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = (HMAC_CTX *)malloc(sizeof (HMAC_CTX));
|
||||
|
@ -482,7 +482,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, KEYLEN);
|
||||
opt_HMAC_SHA512t256_Init(ctx, actx->pkey, cctx->keylen);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context));
|
||||
|
@ -498,7 +498,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, KEYLEN, EVP_sha512(), NULL);
|
||||
HMAC_Init_ex(ctx, actx->pkey, cctx->keylen, EVP_sha512(), NULL);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = (HMAC_CTX *)malloc(sizeof (HMAC_CTX));
|
||||
|
@ -515,7 +515,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, KEYLEN);
|
||||
opt_HMAC_SHA512_Init(ctx, actx->pkey, cctx->keylen);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = (HMAC_SHA512_Context *)malloc(sizeof (HMAC_SHA512_Context));
|
||||
|
@ -538,7 +538,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, KEYLEN << 3) != 0)
|
||||
if (Keccak_Update(ctx, actx->pkey, cctx->keylen << 3) != 0)
|
||||
return (-1);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
|
@ -719,11 +719,13 @@ 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, uint64_t nonce, int enc_dec)
|
||||
uchar_t *salt, int saltlen, int keylen, uint64_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);
|
||||
cctx->keylen = keylen;
|
||||
actx->keylen = keylen;
|
||||
|
||||
if (enc_dec) {
|
||||
/*
|
||||
|
|
|
@ -37,6 +37,16 @@ extern "C" {
|
|||
#define CKSUM_MAX_BYTES 64
|
||||
#define DEFAULT_CKSUM "BLAKE256"
|
||||
|
||||
/*
|
||||
* Default key length for Encryption and Decryption
|
||||
*/
|
||||
#ifndef DEFAULT_KEYLEN
|
||||
#define DEFAULT_KEYLEN 32
|
||||
#define MAX_KEYLEN 32
|
||||
#else
|
||||
#define MAX_KEYLEN DEFAULT_KEYLEN
|
||||
#endif
|
||||
|
||||
#define ENCRYPT_FLAG 1
|
||||
#define DECRYPT_FLAG 0
|
||||
#define CRYPTO_ALG_AES 0x10
|
||||
|
@ -71,6 +81,7 @@ typedef struct {
|
|||
int enc_dec;
|
||||
uchar_t *salt;
|
||||
int saltlen;
|
||||
int keylen;
|
||||
} crypto_ctx_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -93,7 +104,7 @@ 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, uint64_t nonce, int enc_dec);
|
||||
uchar_t *salt, int saltlen, int keylen, uint64_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);
|
||||
void crypto_clean_pkey(crypto_ctx_t *cctx);
|
||||
|
|
95
main.c
95
main.c
|
@ -98,7 +98,7 @@ static int do_compress = 0;
|
|||
static int do_uncompress = 0;
|
||||
static int cksum_bytes, mac_bytes;
|
||||
static int cksum = 0, t_errored = 0;
|
||||
static int rab_blk_size = 0;
|
||||
static int rab_blk_size = 0, keylen;
|
||||
static crypto_ctx_t crypto_ctx;
|
||||
static char *pwd_file = NULL, *f_name = NULL;
|
||||
|
||||
|
@ -169,6 +169,18 @@ usage(void)
|
|||
" - Specify an average Dedupe block size. 1 - 4K, 2 - 8K ... 5 - 64K.\n"
|
||||
" '-M' - Display memory allocator statistics\n"
|
||||
" '-C' - Display compression statistics\n\n");
|
||||
fprintf(stderr, "\n"
|
||||
"8) Encryption flags:\n"
|
||||
" '-e' - Encrypt chunks with AES-CTR. The password can be prompted from the\n"
|
||||
" user or read from a file. Unique keys are generated every time\n"
|
||||
" pcompress is run even when giving the same password.\n"
|
||||
" '-w <pathname>'\n"
|
||||
" - Provide a file which contains the encryption password. This file must\n"
|
||||
" be readable and writable since it is zeroed out after the password is\n"
|
||||
" read.\n"
|
||||
" '-k <key length>\n"
|
||||
" - Specify key length. Can be 16 for 128 bit or 32 for 256 bit. Default\n"
|
||||
" is 32 for 256 bit keys.\n\n");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -787,7 +799,7 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
if (flags & MASK_CRYPTO_ALG) {
|
||||
int saltlen;
|
||||
uchar_t *salt1, *salt2;
|
||||
uint64_t nonce;
|
||||
uint64_t nonce, d3;
|
||||
uchar_t pw[MAX_PW_LEN];
|
||||
int pw_len;
|
||||
mac_ctx_t hdr_mac;
|
||||
|
@ -817,20 +829,34 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
UNCOMP_BAIL;
|
||||
}
|
||||
deserialize_checksum(salt2, salt1, saltlen);
|
||||
memset(salt1, 0, saltlen);
|
||||
free(salt1);
|
||||
|
||||
if (Read(compfd, &nonce, sizeof (nonce)) < sizeof (nonce)) {
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
memset(salt1, 0, saltlen);
|
||||
free(salt1);
|
||||
perror("Read: ");
|
||||
UNCOMP_BAIL;
|
||||
}
|
||||
nonce = ntohll(nonce);
|
||||
|
||||
if (version > 6) {
|
||||
if (Read(compfd, &keylen, sizeof (keylen)) < sizeof (keylen)) {
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
memset(salt1, 0, saltlen);
|
||||
free(salt1);
|
||||
perror("Read: ");
|
||||
UNCOMP_BAIL;
|
||||
}
|
||||
keylen = ntohl(keylen);
|
||||
}
|
||||
|
||||
if (Read(compfd, hdr_hash1, mac_bytes) < mac_bytes) {
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
memset(salt1, 0, saltlen);
|
||||
free(salt1);
|
||||
perror("Read: ");
|
||||
UNCOMP_BAIL;
|
||||
}
|
||||
|
@ -842,6 +868,8 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
if (pw_len == -1) {
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
memset(salt1, 0, saltlen);
|
||||
free(salt1);
|
||||
err_exit(0, "Failed to get password.\n");
|
||||
}
|
||||
} else {
|
||||
|
@ -874,6 +902,8 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
perror(" ");
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
memset(salt1, 0, saltlen);
|
||||
free(salt1);
|
||||
close(uncompfd); unlink(to_filename);
|
||||
err_exit(0, "Failed to get password.\n");
|
||||
}
|
||||
|
@ -881,16 +911,17 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
}
|
||||
|
||||
if (init_crypto(&crypto_ctx, pw, pw_len, encrypt_type, salt2,
|
||||
saltlen, nonce, DECRYPT_FLAG) == -1) {
|
||||
saltlen, keylen, nonce, DECRYPT_FLAG) == -1) {
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
memset(salt1, 0, saltlen);
|
||||
free(salt1);
|
||||
memset(pw, 0, MAX_PW_LEN);
|
||||
close(uncompfd); unlink(to_filename);
|
||||
err_exit(0, "Failed to initialize crypto\n");
|
||||
}
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
nonce = 0;
|
||||
memset(pw, 0, MAX_PW_LEN);
|
||||
|
||||
/*
|
||||
|
@ -905,12 +936,24 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (version));
|
||||
d1 = htons(flags);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (flags));
|
||||
nonce = htonll(chunksize);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&nonce, sizeof (nonce));
|
||||
d3 = htonll(chunksize);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d3, sizeof (nonce));
|
||||
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));
|
||||
d2 = htonl(keylen);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (keylen));
|
||||
}
|
||||
hmac_final(&hdr_mac, hdr_hash1, &hlen);
|
||||
hmac_cleanup(&hdr_mac);
|
||||
memset(salt1, 0, saltlen);
|
||||
free(salt1);
|
||||
nonce = 0;
|
||||
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");
|
||||
|
@ -1600,7 +1643,7 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
|||
close(fd);
|
||||
}
|
||||
if (init_crypto(&crypto_ctx, pw, pw_len, encrypt_type, NULL,
|
||||
0, 0, ENCRYPT_FLAG) == -1) {
|
||||
0, keylen, 0, ENCRYPT_FLAG) == -1) {
|
||||
memset(pw, 0, MAX_PW_LEN);
|
||||
err_exit(0, "Failed to initialize crypto\n");
|
||||
}
|
||||
|
@ -1791,14 +1834,28 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
|||
pos += sizeof (n_chunksize);
|
||||
memcpy(pos, &level, sizeof (level));
|
||||
pos += sizeof (level);
|
||||
|
||||
/*
|
||||
* If encryption is enabled, include salt, nonce and keylen in the header
|
||||
* to be HMAC-ed (archive version 7 and greater).
|
||||
*/
|
||||
if (encrypt_type) {
|
||||
*((int *)pos) = htonl(crypto_ctx.saltlen);
|
||||
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;
|
||||
*((int *)pos) = htonl(keylen);
|
||||
pos += sizeof (int);
|
||||
}
|
||||
if (Write(compfd, cread_buf, pos - cread_buf) != pos - cread_buf) {
|
||||
perror("Write ");
|
||||
COMP_BAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If encryption is enabled, compute header HMAC. Then
|
||||
* write the salt, nonce and header hmac in that order.
|
||||
* If encryption is enabled, compute header HMAC and write it.
|
||||
*/
|
||||
if (encrypt_type) {
|
||||
mac_ctx_t hdr_mac;
|
||||
|
@ -1817,12 +1874,6 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
|||
crypto_clean_pkey(&crypto_ctx);
|
||||
|
||||
pos = cread_buf;
|
||||
*((int *)pos) = htonl(crypto_ctx.saltlen);
|
||||
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;
|
||||
serialize_checksum(hdr_hash, pos, hlen);
|
||||
pos += hlen;
|
||||
if (Write(compfd, cread_buf, pos - cread_buf) != pos - cread_buf) {
|
||||
|
@ -2196,10 +2247,11 @@ main(int argc, char *argv[])
|
|||
exec_name = get_execname(argv[0]);
|
||||
level = 6;
|
||||
err = 0;
|
||||
keylen = DEFAULT_KEYLEN;
|
||||
slab_init();
|
||||
init_pcompress();
|
||||
|
||||
while ((opt = getopt(argc, argv, "dc:s:l:pt:MCDEew:rLPS:B:F")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "dc:s:l:pt:MCDEew:rLPS:B:Fk:")) != -1) {
|
||||
int ovr;
|
||||
|
||||
switch (opt) {
|
||||
|
@ -2297,6 +2349,13 @@ main(int argc, char *argv[])
|
|||
enable_rabin_split = 0;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
keylen = atoi(optarg);
|
||||
if ((keylen != 16 && keylen != 32) || keylen > MAX_KEYLEN) {
|
||||
err_exit(0, "Encryption KEY length should be 16 or 32.\n", optarg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if (get_checksum_props(optarg, &cksum, &cksum_bytes, &mac_bytes, 0) == -1) {
|
||||
err_exit(0, "Invalid checksum type %s\n", optarg);
|
||||
|
|
Loading…
Reference in a new issue