mirror of
https://github.com/ckolivas/lrzip.git
synced 2025-12-06 07:12:00 +01:00
Discard hash_iv entirely, using passphrase hash and centralise key generation.
Patch by Serge Belyshev.
This commit is contained in:
parent
a3e80871c2
commit
e856d481bf
21
lrzip.c
21
lrzip.c
|
|
@ -43,8 +43,6 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "liblrzip.h" /* flag defines */
|
#include "liblrzip.h" /* flag defines */
|
||||||
#include "sha4.h"
|
|
||||||
#include "aes.h"
|
|
||||||
|
|
||||||
#define MAGIC_LEN (39)
|
#define MAGIC_LEN (39)
|
||||||
|
|
||||||
|
|
@ -477,14 +475,12 @@ static void get_hash(rzip_control *control, int make_hash)
|
||||||
testphrase = calloc(PASS_LEN, 1);
|
testphrase = calloc(PASS_LEN, 1);
|
||||||
control->pass_hash = calloc(HASH_LEN, 1);
|
control->pass_hash = calloc(HASH_LEN, 1);
|
||||||
control->hash = calloc(HASH_LEN, 1);
|
control->hash = calloc(HASH_LEN, 1);
|
||||||
control->hash_iv = calloc(SALT_LEN, 1);
|
if (unlikely(!passphrase || !testphrase || !control->pass_hash || !control->hash))
|
||||||
if (unlikely(!passphrase || !testphrase || !control->pass_hash || !control->hash || !control->hash_iv))
|
|
||||||
fatal("Failed to calloc encrypt buffers in compress_file\n");
|
fatal("Failed to calloc encrypt buffers in compress_file\n");
|
||||||
mlock(passphrase, PASS_LEN);
|
mlock(passphrase, PASS_LEN);
|
||||||
mlock(testphrase, PASS_LEN);
|
mlock(testphrase, PASS_LEN);
|
||||||
mlock(control->pass_hash, HASH_LEN);
|
mlock(control->pass_hash, HASH_LEN);
|
||||||
mlock(control->hash, HASH_LEN);
|
mlock(control->hash, HASH_LEN);
|
||||||
mlock(control->hash_iv, SALT_LEN);
|
|
||||||
|
|
||||||
/* Disable stdin echo to screen */
|
/* Disable stdin echo to screen */
|
||||||
tcgetattr(fileno(stdin), &termios_p);
|
tcgetattr(fileno(stdin), &termios_p);
|
||||||
|
|
@ -510,18 +506,7 @@ retry_pass:
|
||||||
free(testphrase);
|
free(testphrase);
|
||||||
|
|
||||||
memcpy(passphrase + PASS_LEN - SALT_LEN, control->salt, SALT_LEN);
|
memcpy(passphrase + PASS_LEN - SALT_LEN, control->salt, SALT_LEN);
|
||||||
sha4(passphrase, PASS_LEN, control->pass_hash, 0);
|
lrz_keygen(control, passphrase);
|
||||||
|
|
||||||
print_maxverbose("Hashing passphrase %lld times\n", control->encloops);
|
|
||||||
for (i = 0; i < control->encloops; i++) {
|
|
||||||
for (j = 0; j < HASH_LEN; j++)
|
|
||||||
control->hash[j] ^= control->pass_hash[j];
|
|
||||||
sha4(control->hash, HASH_LEN, control->hash, 0);
|
|
||||||
if (unlikely(i == control->encloops - 1024)) {
|
|
||||||
for (j = 0; j < SALT_LEN; j++)
|
|
||||||
control->hash_iv[j] = control->hash[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(passphrase, 0, PASS_LEN);
|
memset(passphrase, 0, PASS_LEN);
|
||||||
munlock(passphrase, PASS_LEN);
|
munlock(passphrase, PASS_LEN);
|
||||||
free(passphrase);
|
free(passphrase);
|
||||||
|
|
@ -531,11 +516,9 @@ static void release_hashes(rzip_control *control)
|
||||||
{
|
{
|
||||||
memset(control->pass_hash, 0, HASH_LEN);
|
memset(control->pass_hash, 0, HASH_LEN);
|
||||||
memset(control->hash, 0, SALT_LEN);
|
memset(control->hash, 0, SALT_LEN);
|
||||||
memset(control->hash_iv, 0, SALT_LEN);
|
|
||||||
munlockall();
|
munlockall();
|
||||||
free(control->pass_hash);
|
free(control->pass_hash);
|
||||||
free(control->hash);
|
free(control->hash);
|
||||||
free(control->hash_iv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,6 @@ typedef uint32_t u32;
|
||||||
|
|
||||||
typedef struct rzip_control rzip_control;
|
typedef struct rzip_control rzip_control;
|
||||||
typedef struct md5_ctx md5_ctx;
|
typedef struct md5_ctx md5_ctx;
|
||||||
#include "aes.h" // for aes_context
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
# define mremap fake_mremap
|
# define mremap fake_mremap
|
||||||
|
|
@ -138,6 +137,7 @@ typedef struct md5_ctx md5_ctx;
|
||||||
|
|
||||||
#define PASS_LEN 512
|
#define PASS_LEN 512
|
||||||
#define HASH_LEN 64
|
#define HASH_LEN 64
|
||||||
|
#define BLOCKSALT_LEN 24
|
||||||
#define SALT_LEN 16
|
#define SALT_LEN 16
|
||||||
#define CBC_LEN 16
|
#define CBC_LEN 16
|
||||||
|
|
||||||
|
|
@ -203,8 +203,6 @@ struct rzip_control {
|
||||||
uchar salt[16];
|
uchar salt[16];
|
||||||
uchar *pass_hash;
|
uchar *pass_hash;
|
||||||
uchar *hash;
|
uchar *hash;
|
||||||
uchar *hash_iv;
|
|
||||||
aes_context aes_ctx;
|
|
||||||
unsigned char eof;
|
unsigned char eof;
|
||||||
unsigned char magic_written;
|
unsigned char magic_written;
|
||||||
md5_ctx ctx;
|
md5_ctx ctx;
|
||||||
|
|
|
||||||
2
runzip.c
2
runzip.c
|
|
@ -377,7 +377,7 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp
|
||||||
if (unlikely(read_1g(control, fd_in, md5_stored, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
|
if (unlikely(read_1g(control, fd_in, md5_stored, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
|
||||||
fatal("Failed to read md5 data in runzip_fd\n");
|
fatal("Failed to read md5 data in runzip_fd\n");
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
lrz_crypt(control, md5_stored, MD5_DIGEST_SIZE, control->hash_iv, 0);
|
lrz_crypt(control, md5_stored, MD5_DIGEST_SIZE, control->pass_hash, 0);
|
||||||
for (i = 0; i < MD5_DIGEST_SIZE; i++)
|
for (i = 0; i < MD5_DIGEST_SIZE; i++)
|
||||||
if (md5_stored[i] != md5_resblock[i]) {
|
if (md5_stored[i] != md5_resblock[i]) {
|
||||||
print_output("MD5 CHECK FAILED.\nStored:");
|
print_output("MD5 CHECK FAILED.\nStored:");
|
||||||
|
|
|
||||||
2
rzip.c
2
rzip.c
|
|
@ -978,7 +978,7 @@ retry:
|
||||||
}
|
}
|
||||||
/* When encrypting data, we encrypt the MD5 value as well */
|
/* When encrypting data, we encrypt the MD5 value as well */
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
lrz_crypt(control, md5_resblock, MD5_DIGEST_SIZE, control->hash_iv, 1);
|
lrz_crypt(control, md5_resblock, MD5_DIGEST_SIZE, control->pass_hash, 1);
|
||||||
if (unlikely(write_1g(control, md5_resblock, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
|
if (unlikely(write_1g(control, md5_resblock, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
|
||||||
fatal("Failed to write md5 in rzip_fd\n");
|
fatal("Failed to write md5 in rzip_fd\n");
|
||||||
|
|
||||||
|
|
|
||||||
8
stream.c
8
stream.c
|
|
@ -66,7 +66,7 @@ static struct compress_thread{
|
||||||
pthread_mutex_t mutex; /* This thread's mutex */
|
pthread_mutex_t mutex; /* This thread's mutex */
|
||||||
struct stream_info *sinfo;
|
struct stream_info *sinfo;
|
||||||
int streamno;
|
int streamno;
|
||||||
uchar salt[16];
|
uchar salt[BLOCKSALT_LEN];
|
||||||
} *cthread;
|
} *cthread;
|
||||||
|
|
||||||
static struct uncomp_thread{
|
static struct uncomp_thread{
|
||||||
|
|
@ -1186,7 +1186,8 @@ retry:
|
||||||
|
|
||||||
if (!ret && ENCRYPT) {
|
if (!ret && ENCRYPT) {
|
||||||
get_rand(cti->salt, 8);
|
get_rand(cti->salt, 8);
|
||||||
memcpy(cti->salt + 8, control->salt + 8, 8);
|
memcpy(cti->salt + 8, &cti->c_len, 8);
|
||||||
|
memcpy(cti->salt + 16, &cti->s_len, 8);
|
||||||
lrz_crypt(control, cti->s_buf, padded_len, cti->salt, 1);
|
lrz_crypt(control, cti->s_buf, padded_len, cti->salt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1435,7 +1436,8 @@ fill_another:
|
||||||
print_err("Failed to read_buf salt in fill_buffer\n");
|
print_err("Failed to read_buf salt in fill_buffer\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(salt + 8, control->salt + 8, 8);
|
memcpy(salt + 8, &c_len, 8);
|
||||||
|
memcpy(salt + 16, &u_len, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
padded_len = MAX(c_len, MIN_SIZE);
|
padded_len = MAX(c_len, MIN_SIZE);
|
||||||
|
|
|
||||||
80
util.c
80
util.c
|
|
@ -48,9 +48,13 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "lrzip_private.h"
|
#include "lrzip_private.h"
|
||||||
#include "liblrzip.h"
|
#include "liblrzip.h"
|
||||||
|
#include "sha4.h"
|
||||||
|
#include "aes.h"
|
||||||
|
|
||||||
|
|
||||||
static const char *infile = NULL;
|
static const char *infile = NULL;
|
||||||
static char delete_infile = 0;
|
static char delete_infile = 0;
|
||||||
|
|
@ -164,64 +168,82 @@ void lrz_crypt(rzip_control *control, uchar *buf, i64 len, uchar *salt, int encr
|
||||||
{
|
{
|
||||||
/* Encryption requires CBC_LEN blocks so we can use ciphertext
|
/* Encryption requires CBC_LEN blocks so we can use ciphertext
|
||||||
* stealing to not have to pad the block */
|
* stealing to not have to pad the block */
|
||||||
uchar ivec[80], tmp0[CBC_LEN], tmp1[CBC_LEN];
|
uchar key[HASH_LEN + BLOCKSALT_LEN], iv[HASH_LEN + BLOCKSALT_LEN];
|
||||||
uchar key[80], iv[80];
|
uchar tmp0[CBC_LEN], tmp1[CBC_LEN];
|
||||||
|
aes_context aes_ctx;
|
||||||
i64 N, M;
|
i64 N, M;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Generate unique key and IV for each block of data based on salt */
|
/* Generate unique key and IV for each block of data based on salt */
|
||||||
mlock(key, 80);
|
mlock(&aes_ctx, sizeof(aes_ctx));
|
||||||
mlock(iv, 80);
|
mlock(key, HASH_LEN + BLOCKSALT_LEN);
|
||||||
for (i = 0; i < 64; i++)
|
mlock(iv, HASH_LEN + BLOCKSALT_LEN);
|
||||||
|
for (i = 0; i < HASH_LEN; i++)
|
||||||
key[i] = control->pass_hash[i] ^ control->hash[i];
|
key[i] = control->pass_hash[i] ^ control->hash[i];
|
||||||
memcpy(key + 64, salt, 16);
|
memcpy(key + HASH_LEN, salt, BLOCKSALT_LEN);
|
||||||
sha4(key, 80, key, 0);
|
sha4(key, HASH_LEN + BLOCKSALT_LEN, key, 0);
|
||||||
for (i = 0; i < 64; i++)
|
for (i = 0; i < HASH_LEN; i++)
|
||||||
ivec[i] = key[i] ^ control->pass_hash[i];
|
iv[i] = key[i] ^ control->pass_hash[i];
|
||||||
memcpy(ivec + 64, salt, 16);
|
memcpy(iv + HASH_LEN, salt, BLOCKSALT_LEN);
|
||||||
sha4(ivec, 80, ivec, 0);
|
sha4(iv, HASH_LEN + BLOCKSALT_LEN, iv, 0);
|
||||||
|
|
||||||
M = len % CBC_LEN;
|
M = len % CBC_LEN;
|
||||||
N = len - M;
|
N = len - M;
|
||||||
|
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
print_maxverbose("Encrypting data \n");
|
print_maxverbose("Encrypting data \n");
|
||||||
if (unlikely(aes_setkey_enc(&control->aes_ctx, key, 128)))
|
if (unlikely(aes_setkey_enc(&aes_ctx, key, 128)))
|
||||||
failure("Failed to aes_setkey_enc in lrz_crypt\n");
|
failure("Failed to aes_setkey_enc in lrz_crypt\n");
|
||||||
aes_crypt_cbc(&control->aes_ctx, AES_ENCRYPT, N, ivec, buf, buf);
|
aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, N, iv, buf, buf);
|
||||||
|
|
||||||
if (M) {
|
if (M) {
|
||||||
memset(tmp0, 0, sizeof(tmp0));
|
memset(tmp0, 0, CBC_LEN);
|
||||||
memcpy(tmp0, buf + N, M);
|
memcpy(tmp0, buf + N, M);
|
||||||
aes_crypt_cbc(&control->aes_ctx, AES_ENCRYPT, CBC_LEN,
|
aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, CBC_LEN,
|
||||||
ivec, tmp0, tmp1);
|
iv, tmp0, tmp1);
|
||||||
memcpy(buf + N, buf + N - CBC_LEN, M);
|
memcpy(buf + N, buf + N - CBC_LEN, M);
|
||||||
memcpy(buf + N - CBC_LEN, tmp1, CBC_LEN);
|
memcpy(buf + N - CBC_LEN, tmp1, CBC_LEN);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (unlikely(aes_setkey_dec(&control->aes_ctx, key, 128)))
|
if (unlikely(aes_setkey_dec(&aes_ctx, key, 128)))
|
||||||
failure("Failed to aes_setkey_dec in lrz_crypt\n");
|
failure("Failed to aes_setkey_dec in lrz_crypt\n");
|
||||||
print_maxverbose("Decrypting data \n");
|
print_maxverbose("Decrypting data \n");
|
||||||
if (M) {
|
if (M) {
|
||||||
aes_crypt_cbc(&control->aes_ctx, AES_DECRYPT, N - CBC_LEN,
|
aes_crypt_cbc(&aes_ctx, AES_DECRYPT, N - CBC_LEN,
|
||||||
ivec, buf, buf);
|
iv, buf, buf);
|
||||||
aes_crypt_ecb(&control->aes_ctx, AES_DECRYPT,
|
aes_crypt_ecb(&aes_ctx, AES_DECRYPT,
|
||||||
buf + N - CBC_LEN, tmp0);
|
buf + N - CBC_LEN, tmp0);
|
||||||
memset(tmp1, 0, CBC_LEN);
|
memset(tmp1, 0, CBC_LEN);
|
||||||
memcpy(tmp1, buf + N, M);
|
memcpy(tmp1, buf + N, M);
|
||||||
xor128(tmp0, tmp1);
|
xor128(tmp0, tmp1);
|
||||||
memcpy(buf + N, tmp0, M);
|
memcpy(buf + N, tmp0, M);
|
||||||
memcpy(tmp1 + M, tmp0 + M, CBC_LEN - M);
|
memcpy(tmp1 + M, tmp0 + M, CBC_LEN - M);
|
||||||
aes_crypt_ecb(&control->aes_ctx, AES_DECRYPT, tmp1,
|
aes_crypt_ecb(&aes_ctx, AES_DECRYPT, tmp1,
|
||||||
buf + N - CBC_LEN);
|
buf + N - CBC_LEN);
|
||||||
xor128(buf + N - CBC_LEN, ivec);
|
xor128(buf + N - CBC_LEN, iv);
|
||||||
} else
|
} else
|
||||||
aes_crypt_cbc(&control->aes_ctx, AES_DECRYPT, len,
|
aes_crypt_cbc(&aes_ctx, AES_DECRYPT, len,
|
||||||
ivec, buf, buf);
|
iv, buf, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(ivec, 0, 80);
|
memset(&aes_ctx, 0, sizeof(aes_ctx));
|
||||||
memset(key, 0, 80);
|
memset(iv, 0, HASH_LEN + BLOCKSALT_LEN);
|
||||||
munlock(ivec, 80);
|
memset(key, 0, HASH_LEN + BLOCKSALT_LEN);
|
||||||
munlock(key, 80);
|
munlock(&aes_ctx, sizeof(aes_ctx));
|
||||||
}
|
munlock(iv, HASH_LEN + BLOCKSALT_LEN);
|
||||||
|
munlock(key, HASH_LEN + BLOCKSALT_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lrz_keygen(rzip_control *control, const uchar *passphrase)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
sha4(passphrase, PASS_LEN, control->pass_hash, 0);
|
||||||
|
|
||||||
|
print_maxverbose("Hashing passphrase %lld times\n", control->encloops);
|
||||||
|
for (i = 0; i < control->encloops; i++) {
|
||||||
|
for (j = 0; j < HASH_LEN; j++)
|
||||||
|
control->hash[j] ^= control->pass_hash[j];
|
||||||
|
sha4(control->hash, HASH_LEN, control->hash, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
1
util.h
1
util.h
|
|
@ -30,5 +30,6 @@ void failure(const char *format, ...);
|
||||||
void round_to_page(i64 *size);
|
void round_to_page(i64 *size);
|
||||||
void get_rand(uchar *buf, int len);
|
void get_rand(uchar *buf, int len);
|
||||||
void lrz_crypt(rzip_control *control, uchar *buf, i64 len, uchar *salt, int encrypt);
|
void lrz_crypt(rzip_control *control, uchar *buf, i64 len, uchar *salt, int encrypt);
|
||||||
|
void lrz_keygen(rzip_control *control, const uchar *passphrase);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue