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 $@
|
$(COMPILE) $(GEN_OPT) $(CRYPTO_CPPFLAGS) $(CPPFLAGS) $(@:.o=.c) -o $@
|
||||||
|
|
||||||
$(CRYPTO_ASM_OBJS): $(CRYPTO_ASM_SRCS) $(CRYPTO_ASM_HDRS)
|
$(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)
|
$(CRYPTO_COMPAT_OBJS): $(CRYPTO_COMPAT_SRCS) $(CRYPTO_COMPAT_HDRS)
|
||||||
$(COMPILE) $(GEN_OPT) $(CRYPTO_CPPFLAGS) $(CPPFLAGS) $(@:.o=.c) -o $@
|
$(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
|
'-C' - Display compression statistics
|
||||||
|
|
||||||
Encryption flags:
|
Encryption flags:
|
||||||
'-e' Encrypt chunks with AES. The password can be prompted from the user
|
'-e' Encrypt chunks with AES-CTR. The password can be prompted from the user
|
||||||
or read from a file. Whether 128-Bit or 256-Bit keys are used depends
|
or read from a file. Unique keys are generated every time pcompress is
|
||||||
on how the pcompress binary was built. Default build uses 128-Bit keys.
|
run even when giving the same password. Of course enough info is stored\
|
||||||
Unique keys are generated every time pcompress is run even when giving
|
in the compresse file so that the key used for the file can be
|
||||||
the same password. Of course enough info is stored in the compressed
|
re-created given the correct password.
|
||||||
file so that the key used for the file can be re-created given the
|
|
||||||
correct password.
|
|
||||||
|
|
||||||
The Scrypt algorithm from Tarsnap is used
|
The Scrypt algorithm from Tarsnap is used
|
||||||
(See: http://www.tarsnap.com/scrypt.html) for generating keys from
|
(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
|
be readable and writable since it is zeroed out after the password is
|
||||||
read.
|
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'.
|
NOTE: When using pipe-mode via -p the only way to provide a password is to use '-w'.
|
||||||
|
|
||||||
Environment Variables
|
Environment Variables
|
||||||
|
|
5
config
5
config
|
@ -26,7 +26,8 @@ ${prog} [<options>]
|
||||||
version 1.3 (default: retain compatibility). Hash formats changed from
|
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
|
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.
|
1.3 need to be decompressed by version 1.4 onwards.
|
||||||
--use-key256 Use 256-bit encryption keys. Default key length is 128-bit.
|
--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.
|
--help Display this help message.
|
||||||
|
|
||||||
_EOF
|
_EOF
|
||||||
|
@ -145,7 +146,7 @@ do
|
||||||
bzlib_prefix=`echo ${arg1} | cut -f2 -d"="`
|
bzlib_prefix=`echo ${arg1} | cut -f2 -d"="`
|
||||||
;;
|
;;
|
||||||
--use-key256)
|
--use-key256)
|
||||||
keylen='-DKEYLEN=32'
|
keylen='-DDEFAULT_KEYLEN=16'
|
||||||
;;
|
;;
|
||||||
--no-sse-detect)
|
--no-sse-detect)
|
||||||
sse_detect=0
|
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);
|
pickparams(&logN, &r, &p);
|
||||||
N = (uint64_t)(1) << logN;
|
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");
|
fprintf(stderr, "Scrypt failed\n");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
rv = PKCS5_PBKDF2_HMAC(pwd, pwd_len, salt, saltlen, PBE_ROUNDS, EVP_sha256(),
|
rv = PKCS5_PBKDF2_HMAC(pwd, pwd_len, salt, saltlen, PBE_ROUNDS, EVP_sha256(),
|
||||||
KEYLEN, key);
|
ctx->keylen, key);
|
||||||
if (rv != KEYLEN) {
|
if (rv != ctx->keylen) {
|
||||||
fprintf(stderr, "Key size is %d bytes - should be %d bits\n", i, KEYLEN);
|
fprintf(stderr, "Key size is %d bytes - should be %d bits\n", i, ctx->keylen);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (enc) {
|
if (enc) {
|
||||||
enc_setkey(key, (KEYLEN << 3), &(ctx->key));
|
enc_setkey(key, (ctx->keylen << 3), &(ctx->key));
|
||||||
// Derive nonce from salt
|
// Derive nonce from salt
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
|
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
|
||||||
time((time_t *)&tv);
|
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;
|
tv = 0;
|
||||||
} else {
|
} else {
|
||||||
ctx->nonce = nonce;
|
ctx->nonce = nonce;
|
||||||
enc_setkey(key, (KEYLEN << 3), &(ctx->key));
|
enc_setkey(key, (ctx->keylen << 3), &(ctx->key));
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,7 @@ aes_nonce(aes_ctx_t *ctx)
|
||||||
void
|
void
|
||||||
aes_clean_pkey(aes_ctx_t *ctx)
|
aes_clean_pkey(aes_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
memset(ctx->pkey, 0, KEYLEN);
|
memset(ctx->pkey, 0, ctx->keylen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -30,20 +30,19 @@
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#endif
|
#endif
|
||||||
#include <openssl/opensslv.h>
|
#include <openssl/opensslv.h>
|
||||||
|
#include <crypto_utils.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef KEYLEN
|
|
||||||
#define KEYLEN 16
|
|
||||||
#endif
|
|
||||||
#define PBE_ROUNDS 1000
|
#define PBE_ROUNDS 1000
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t nonce;
|
uint64_t nonce;
|
||||||
AES_KEY key;
|
AES_KEY key;
|
||||||
uchar_t pkey[KEYLEN];
|
int keylen;
|
||||||
|
uchar_t pkey[MAX_KEYLEN];
|
||||||
} aes_ctx_t;
|
} aes_ctx_t;
|
||||||
|
|
||||||
int aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
|
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) {
|
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, KEYLEN) != 0)
|
if (bdsp.blake2b_init_key(ctx, 32, actx->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 +421,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, KEYLEN) != 0)
|
if (bdsp.blake2b_init_key(ctx, 64, actx->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 +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));
|
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, KEYLEN);
|
actx->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 +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));
|
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, KEYLEN);
|
actx->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 +465,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, KEYLEN, EVP_sha256(), NULL);
|
HMAC_Init_ex(ctx, actx->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 +482,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, KEYLEN);
|
opt_HMAC_SHA512t256_Init(ctx, actx->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 +498,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, KEYLEN, EVP_sha512(), NULL);
|
HMAC_Init_ex(ctx, actx->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 +515,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, KEYLEN);
|
opt_HMAC_SHA512_Init(ctx, actx->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 +538,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, KEYLEN << 3) != 0)
|
if (Keccak_Update(ctx, actx->pkey, cctx->keylen << 3) != 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
mctx->mac_ctx = ctx;
|
mctx->mac_ctx = ctx;
|
||||||
|
|
||||||
|
@ -719,11 +719,13 @@ 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, 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) {
|
if (crypto_alg == CRYPTO_ALG_AES) {
|
||||||
aes_ctx_t *actx = (aes_ctx_t *)malloc(sizeof (aes_ctx_t));
|
aes_ctx_t *actx = (aes_ctx_t *)malloc(sizeof (aes_ctx_t));
|
||||||
aes_module_init(&proc_info);
|
aes_module_init(&proc_info);
|
||||||
|
cctx->keylen = keylen;
|
||||||
|
actx->keylen = keylen;
|
||||||
|
|
||||||
if (enc_dec) {
|
if (enc_dec) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -37,6 +37,16 @@ extern "C" {
|
||||||
#define CKSUM_MAX_BYTES 64
|
#define CKSUM_MAX_BYTES 64
|
||||||
#define DEFAULT_CKSUM "BLAKE256"
|
#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 ENCRYPT_FLAG 1
|
||||||
#define DECRYPT_FLAG 0
|
#define DECRYPT_FLAG 0
|
||||||
#define CRYPTO_ALG_AES 0x10
|
#define CRYPTO_ALG_AES 0x10
|
||||||
|
@ -71,6 +81,7 @@ typedef struct {
|
||||||
int enc_dec;
|
int enc_dec;
|
||||||
uchar_t *salt;
|
uchar_t *salt;
|
||||||
int saltlen;
|
int saltlen;
|
||||||
|
int keylen;
|
||||||
} crypto_ctx_t;
|
} crypto_ctx_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -93,7 +104,7 @@ 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, 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);
|
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);
|
uint64_t crypto_nonce(crypto_ctx_t *cctx);
|
||||||
void crypto_clean_pkey(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 do_uncompress = 0;
|
||||||
static int cksum_bytes, mac_bytes;
|
static int cksum_bytes, mac_bytes;
|
||||||
static int cksum = 0, t_errored = 0;
|
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 crypto_ctx_t crypto_ctx;
|
||||||
static char *pwd_file = NULL, *f_name = NULL;
|
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"
|
" - Specify an average Dedupe block size. 1 - 4K, 2 - 8K ... 5 - 64K.\n"
|
||||||
" '-M' - Display memory allocator statistics\n"
|
" '-M' - Display memory allocator statistics\n"
|
||||||
" '-C' - Display compression statistics\n\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
|
void
|
||||||
|
@ -787,7 +799,7 @@ start_decompress(const char *filename, const char *to_filename)
|
||||||
if (flags & MASK_CRYPTO_ALG) {
|
if (flags & MASK_CRYPTO_ALG) {
|
||||||
int saltlen;
|
int saltlen;
|
||||||
uchar_t *salt1, *salt2;
|
uchar_t *salt1, *salt2;
|
||||||
uint64_t nonce;
|
uint64_t nonce, d3;
|
||||||
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;
|
||||||
|
@ -817,20 +829,34 @@ start_decompress(const char *filename, const char *to_filename)
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
deserialize_checksum(salt2, salt1, saltlen);
|
deserialize_checksum(salt2, salt1, saltlen);
|
||||||
memset(salt1, 0, saltlen);
|
|
||||||
free(salt1);
|
|
||||||
|
|
||||||
if (Read(compfd, &nonce, sizeof (nonce)) < sizeof (nonce)) {
|
if (Read(compfd, &nonce, sizeof (nonce)) < sizeof (nonce)) {
|
||||||
memset(salt2, 0, saltlen);
|
memset(salt2, 0, saltlen);
|
||||||
free(salt2);
|
free(salt2);
|
||||||
|
memset(salt1, 0, saltlen);
|
||||||
|
free(salt1);
|
||||||
perror("Read: ");
|
perror("Read: ");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
nonce = ntohll(nonce);
|
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) {
|
if (Read(compfd, hdr_hash1, mac_bytes) < mac_bytes) {
|
||||||
memset(salt2, 0, saltlen);
|
memset(salt2, 0, saltlen);
|
||||||
free(salt2);
|
free(salt2);
|
||||||
|
memset(salt1, 0, saltlen);
|
||||||
|
free(salt1);
|
||||||
perror("Read: ");
|
perror("Read: ");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
|
@ -842,6 +868,8 @@ start_decompress(const char *filename, const char *to_filename)
|
||||||
if (pw_len == -1) {
|
if (pw_len == -1) {
|
||||||
memset(salt2, 0, saltlen);
|
memset(salt2, 0, saltlen);
|
||||||
free(salt2);
|
free(salt2);
|
||||||
|
memset(salt1, 0, saltlen);
|
||||||
|
free(salt1);
|
||||||
err_exit(0, "Failed to get password.\n");
|
err_exit(0, "Failed to get password.\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -874,6 +902,8 @@ start_decompress(const char *filename, const char *to_filename)
|
||||||
perror(" ");
|
perror(" ");
|
||||||
memset(salt2, 0, saltlen);
|
memset(salt2, 0, saltlen);
|
||||||
free(salt2);
|
free(salt2);
|
||||||
|
memset(salt1, 0, saltlen);
|
||||||
|
free(salt1);
|
||||||
close(uncompfd); unlink(to_filename);
|
close(uncompfd); unlink(to_filename);
|
||||||
err_exit(0, "Failed to get password.\n");
|
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,
|
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);
|
memset(salt2, 0, saltlen);
|
||||||
free(salt2);
|
free(salt2);
|
||||||
|
memset(salt1, 0, saltlen);
|
||||||
|
free(salt1);
|
||||||
memset(pw, 0, MAX_PW_LEN);
|
memset(pw, 0, MAX_PW_LEN);
|
||||||
close(uncompfd); unlink(to_filename);
|
close(uncompfd); unlink(to_filename);
|
||||||
err_exit(0, "Failed to initialize crypto\n");
|
err_exit(0, "Failed to initialize crypto\n");
|
||||||
}
|
}
|
||||||
memset(salt2, 0, saltlen);
|
memset(salt2, 0, saltlen);
|
||||||
free(salt2);
|
free(salt2);
|
||||||
nonce = 0;
|
|
||||||
memset(pw, 0, MAX_PW_LEN);
|
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));
|
hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (version));
|
||||||
d1 = htons(flags);
|
d1 = htons(flags);
|
||||||
hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (flags));
|
hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (flags));
|
||||||
nonce = htonll(chunksize);
|
d3 = htonll(chunksize);
|
||||||
hmac_update(&hdr_mac, (uchar_t *)&nonce, sizeof (nonce));
|
hmac_update(&hdr_mac, (uchar_t *)&d3, sizeof (nonce));
|
||||||
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) {
|
||||||
|
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_final(&hdr_mac, hdr_hash1, &hlen);
|
||||||
hmac_cleanup(&hdr_mac);
|
hmac_cleanup(&hdr_mac);
|
||||||
|
memset(salt1, 0, saltlen);
|
||||||
|
free(salt1);
|
||||||
|
nonce = 0;
|
||||||
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");
|
||||||
|
@ -1600,7 +1643,7 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
if (init_crypto(&crypto_ctx, pw, pw_len, encrypt_type, NULL,
|
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);
|
memset(pw, 0, MAX_PW_LEN);
|
||||||
err_exit(0, "Failed to initialize crypto\n");
|
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);
|
pos += sizeof (n_chunksize);
|
||||||
memcpy(pos, &level, sizeof (level));
|
memcpy(pos, &level, sizeof (level));
|
||||||
pos += 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) {
|
if (Write(compfd, cread_buf, pos - cread_buf) != pos - cread_buf) {
|
||||||
perror("Write ");
|
perror("Write ");
|
||||||
COMP_BAIL;
|
COMP_BAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If encryption is enabled, compute header HMAC. Then
|
* If encryption is enabled, compute header HMAC and write it.
|
||||||
* write the salt, nonce and header hmac in that order.
|
|
||||||
*/
|
*/
|
||||||
if (encrypt_type) {
|
if (encrypt_type) {
|
||||||
mac_ctx_t hdr_mac;
|
mac_ctx_t hdr_mac;
|
||||||
|
@ -1817,12 +1874,6 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
||||||
crypto_clean_pkey(&crypto_ctx);
|
crypto_clean_pkey(&crypto_ctx);
|
||||||
|
|
||||||
pos = cread_buf;
|
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);
|
serialize_checksum(hdr_hash, pos, hlen);
|
||||||
pos += hlen;
|
pos += hlen;
|
||||||
if (Write(compfd, cread_buf, pos - cread_buf) != pos - cread_buf) {
|
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]);
|
exec_name = get_execname(argv[0]);
|
||||||
level = 6;
|
level = 6;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
keylen = DEFAULT_KEYLEN;
|
||||||
slab_init();
|
slab_init();
|
||||||
init_pcompress();
|
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;
|
int ovr;
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
@ -2297,6 +2349,13 @@ main(int argc, char *argv[])
|
||||||
enable_rabin_split = 0;
|
enable_rabin_split = 0;
|
||||||
break;
|
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':
|
case 'S':
|
||||||
if (get_checksum_props(optarg, &cksum, &cksum_bytes, &mac_bytes, 0) == -1) {
|
if (get_checksum_props(optarg, &cksum, &cksum_bytes, &mac_bytes, 0) == -1) {
|
||||||
err_exit(0, "Invalid checksum type %s\n", optarg);
|
err_exit(0, "Invalid checksum type %s\n", optarg);
|
||||||
|
|
Loading…
Reference in a new issue