diff --git a/lrzip.c b/lrzip.c index bd41eab..f5f048f 100644 --- a/lrzip.c +++ b/lrzip.c @@ -433,7 +433,7 @@ void close_tmpinbuf(rzip_control *control) free(control->tmp_inbuf); } -static void get_pass(char *s) +static int get_pass(char *s) { int len; @@ -448,6 +448,7 @@ static void get_pass(char *s) len = strlen(s); if (unlikely(0 == len)) failure("Empty passphrase\n"); + return len; } static void get_hash(rzip_control *control, int make_hash) @@ -459,13 +460,13 @@ static void get_hash(rzip_control *control, int make_hash) passphrase = calloc(PASS_LEN, 1); testphrase = calloc(PASS_LEN, 1); - control->pass_hash = calloc(HASH_LEN, 1); + control->salt_pass = calloc(PASS_LEN, 1); control->hash = calloc(HASH_LEN, 1); - if (unlikely(!passphrase || !testphrase || !control->pass_hash || !control->hash)) + if (unlikely(!passphrase || !testphrase || !control->salt_pass || !control->hash)) fatal("Failed to calloc encrypt buffers in compress_file\n"); mlock(passphrase, PASS_LEN); mlock(testphrase, PASS_LEN); - mlock(control->pass_hash, HASH_LEN); + mlock(control->salt_pass, PASS_LEN); mlock(control->hash, HASH_LEN); /* Disable stdin echo to screen */ @@ -474,7 +475,7 @@ static void get_hash(rzip_control *control, int make_hash) tcsetattr(fileno(stdin), 0, &termios_p); retry_pass: print_output("Enter passphrase: "); - get_pass(passphrase); + control->salt_pass_len = get_pass(passphrase) + SALT_LEN; print_output("\n"); if (make_hash) { print_output("Re-enter passphrase: "); @@ -491,8 +492,9 @@ retry_pass: munlock(testphrase, PASS_LEN); free(testphrase); - memcpy(passphrase + PASS_LEN - SALT_LEN, control->salt, SALT_LEN); - lrz_keygen(control, passphrase); + memcpy(control->salt_pass, control->salt, SALT_LEN); + memcpy(control->salt_pass + SALT_LEN, passphrase, PASS_LEN - SALT_LEN); + lrz_stretch(control); memset(passphrase, 0, PASS_LEN); munlock(passphrase, PASS_LEN); free(passphrase); @@ -500,10 +502,10 @@ retry_pass: static void release_hashes(rzip_control *control) { - memset(control->pass_hash, 0, HASH_LEN); + memset(control->salt_pass, 0, PASS_LEN); memset(control->hash, 0, SALT_LEN); munlockall(); - free(control->pass_hash); + free(control->salt_pass); free(control->hash); } diff --git a/lrzip_private.h b/lrzip_private.h index 0f74475..a99e49c 100644 --- a/lrzip_private.h +++ b/lrzip_private.h @@ -199,8 +199,9 @@ struct rzip_control { int fd_hist; i64 encloops; i64 secs; - uchar salt[16]; - uchar *pass_hash; + uchar salt[8]; + uchar *salt_pass; + int salt_pass_len; uchar *hash; unsigned char eof; unsigned char magic_written; diff --git a/runzip.c b/runzip.c index 6dd3ad5..55a38b7 100644 --- a/runzip.c +++ b/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)) fatal("Failed to read md5 data in runzip_fd\n"); if (ENCRYPT) - lrz_decrypt(control, md5_stored, MD5_DIGEST_SIZE, control->pass_hash); + lrz_decrypt(control, md5_stored, MD5_DIGEST_SIZE, control->salt_pass); for (i = 0; i < MD5_DIGEST_SIZE; i++) if (md5_stored[i] != md5_resblock[i]) { print_output("MD5 CHECK FAILED.\nStored:"); diff --git a/rzip.c b/rzip.c index 6361139..872f243 100644 --- a/rzip.c +++ b/rzip.c @@ -987,7 +987,7 @@ retry: } /* When encrypting data, we encrypt the MD5 value as well */ if (ENCRYPT) - lrz_encrypt(control, md5_resblock, MD5_DIGEST_SIZE, control->pass_hash); + lrz_encrypt(control, md5_resblock, MD5_DIGEST_SIZE, control->salt_pass); if (unlikely(write_1g(control, md5_resblock, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE)) fatal("Failed to write md5 in rzip_fd\n"); diff --git a/util.c b/util.c index 6a1f137..c178206 100644 --- a/util.c +++ b/util.c @@ -52,12 +52,10 @@ #include #include "lrzip_private.h" #include "liblrzip.h" +#include "util.h" #include "sha4.h" #include "aes.h" -#define LRZ_DECRYPT (0) -#define LRZ_ENCRYPT (1) - static const char *infile = NULL; static char delete_infile = 0; static const char *outfile = NULL; @@ -166,11 +164,30 @@ static void xor128 (void *pa, const void *pb) a [1] ^= b [1]; } -static void lrz_crypt(rzip_control *control, uchar *buf, i64 len, uchar *salt, int encrypt) +static void lrz_keygen(const rzip_control *control, const uchar *salt, uchar *key, uchar *iv) +{ + uchar buf [HASH_LEN + SALT_LEN + PASS_LEN]; + mlock(buf, HASH_LEN + SALT_LEN + PASS_LEN); + + memcpy(buf, control->hash, HASH_LEN); + memcpy(buf + HASH_LEN, salt, SALT_LEN); + memcpy(buf + HASH_LEN + SALT_LEN, control->salt_pass, control->salt_pass_len); + sha4(buf, HASH_LEN + SALT_LEN + control->salt_pass_len, key, 0); + + memcpy(buf, key, HASH_LEN); + memcpy(buf + HASH_LEN, salt, SALT_LEN); + memcpy(buf + HASH_LEN + SALT_LEN, control->salt_pass, control->salt_pass_len); + sha4(buf, HASH_LEN + SALT_LEN + control->salt_pass_len, iv, 0); + + memset(buf, 0, sizeof(buf)); + munlock(buf, sizeof(buf)); +} + +void lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt, int encrypt) { /* Encryption requires CBC_LEN blocks so we can use ciphertext * stealing to not have to pad the block */ - uchar key[HASH_LEN + SALT_LEN], iv[HASH_LEN + SALT_LEN]; + uchar key[HASH_LEN], iv[HASH_LEN]; uchar tmp0[CBC_LEN], tmp1[CBC_LEN]; aes_context aes_ctx; i64 N, M; @@ -178,16 +195,10 @@ static void lrz_crypt(rzip_control *control, uchar *buf, i64 len, uchar *salt, i /* Generate unique key and IV for each block of data based on salt */ mlock(&aes_ctx, sizeof(aes_ctx)); - mlock(key, HASH_LEN + SALT_LEN); - mlock(iv, HASH_LEN + SALT_LEN); - for (i = 0; i < HASH_LEN; i++) - key[i] = control->pass_hash[i] ^ control->hash[i]; - memcpy(key + HASH_LEN, salt, SALT_LEN); - sha4(key, HASH_LEN + SALT_LEN, key, 0); - for (i = 0; i < HASH_LEN; i++) - iv[i] = key[i] ^ control->pass_hash[i]; - memcpy(iv + HASH_LEN, salt, SALT_LEN); - sha4(iv, HASH_LEN + SALT_LEN, iv, 0); + mlock(key, HASH_LEN); + mlock(iv, HASH_LEN); + + lrz_keygen(control, salt, key, iv); M = len % CBC_LEN; N = len - M; @@ -229,33 +240,29 @@ static void lrz_crypt(rzip_control *control, uchar *buf, i64 len, uchar *salt, i } memset(&aes_ctx, 0, sizeof(aes_ctx)); - memset(iv, 0, HASH_LEN + SALT_LEN); - memset(key, 0, HASH_LEN + SALT_LEN); + memset(iv, 0, HASH_LEN); + memset(key, 0, HASH_LEN); munlock(&aes_ctx, sizeof(aes_ctx)); - munlock(iv, HASH_LEN + SALT_LEN); - munlock(key, HASH_LEN + SALT_LEN); + munlock(iv, HASH_LEN); + munlock(key, HASH_LEN); } -inline void lrz_encrypt(rzip_control *control, uchar *buf, i64 len, uchar *salt) +void lrz_stretch(rzip_control *control) { - lrz_crypt(control, buf, len, salt, LRZ_ENCRYPT); -} + sha4_context ctx; + i64 j, n, counter; -inline void lrz_decrypt(rzip_control *control, uchar *buf, i64 len, uchar *salt) -{ - lrz_crypt(control, buf, len, salt, LRZ_DECRYPT); -} + mlock(&ctx, sizeof(ctx)); + sha4_starts(&ctx, 0); -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); + n = control->encloops * HASH_LEN / (control->salt_pass_len + sizeof(i64)); + print_maxverbose("Hashing passphrase %lld (%lld) times \n", control->encloops, n); + for (j = 0; j < n; j ++) { + counter = htole64(j); + sha4_update(&ctx, (uchar *)&counter, sizeof(counter)); + sha4_update(&ctx, control->salt_pass, control->salt_pass_len); } + sha4_finish(&ctx, control->hash); + memset(&ctx, 0, sizeof(ctx)); + munlock(&ctx, sizeof(ctx)); } diff --git a/util.h b/util.h index fb6050b..a5a868e 100644 --- a/util.h +++ b/util.h @@ -29,8 +29,21 @@ void fatal(const char *format, ...); void failure(const char *format, ...); void round_to_page(i64 *size); void get_rand(uchar *buf, int len); -inline void lrz_encrypt(rzip_control *control, uchar *buf, i64 len, uchar *salt); -inline void lrz_decrypt(rzip_control *control, uchar *buf, i64 len, uchar *salt); -void lrz_keygen(rzip_control *control, const uchar *passphrase); +void lrz_stretch(rzip_control *control); +void lrz_stretch2(rzip_control *control); +void lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt, int encrypt); + +#define LRZ_DECRYPT (0) +#define LRZ_ENCRYPT (1) + +static void lrz_encrypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt) +{ + lrz_crypt(control, buf, len, salt, LRZ_ENCRYPT); +} + +static void lrz_decrypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt) +{ + lrz_crypt(control, buf, len, salt, LRZ_DECRYPT); +} #endif