diff --git a/lrzip.c b/lrzip.c index 3fe651f..43fa050 100644 --- a/lrzip.c +++ b/lrzip.c @@ -43,8 +43,6 @@ #include "util.h" #include "stream.h" #include "liblrzip.h" /* flag defines */ -#include "sha4.h" -#include "aes.h" #define MAGIC_LEN (39) @@ -477,14 +475,12 @@ static void get_hash(rzip_control *control, int make_hash) testphrase = calloc(PASS_LEN, 1); control->pass_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 || !control->hash_iv)) + if (unlikely(!passphrase || !testphrase || !control->pass_hash || !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->hash, HASH_LEN); - mlock(control->hash_iv, SALT_LEN); /* Disable stdin echo to screen */ tcgetattr(fileno(stdin), &termios_p); @@ -510,18 +506,7 @@ retry_pass: free(testphrase); memcpy(passphrase + PASS_LEN - SALT_LEN, control->salt, SALT_LEN); - 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); - if (unlikely(i == control->encloops - 1024)) { - for (j = 0; j < SALT_LEN; j++) - control->hash_iv[j] = control->hash[j]; - } - } + lrz_keygen(control, passphrase); memset(passphrase, 0, PASS_LEN); munlock(passphrase, PASS_LEN); free(passphrase); @@ -531,11 +516,9 @@ static void release_hashes(rzip_control *control) { memset(control->pass_hash, 0, HASH_LEN); memset(control->hash, 0, SALT_LEN); - memset(control->hash_iv, 0, SALT_LEN); munlockall(); free(control->pass_hash); free(control->hash); - free(control->hash_iv); } /* diff --git a/lrzip_private.h b/lrzip_private.h index 6be8dad..f810c76 100644 --- a/lrzip_private.h +++ b/lrzip_private.h @@ -94,7 +94,6 @@ typedef uint32_t u32; typedef struct rzip_control rzip_control; typedef struct md5_ctx md5_ctx; -#include "aes.h" // for aes_context #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) # define mremap fake_mremap @@ -138,6 +137,7 @@ typedef struct md5_ctx md5_ctx; #define PASS_LEN 512 #define HASH_LEN 64 +#define BLOCKSALT_LEN 24 #define SALT_LEN 16 #define CBC_LEN 16 @@ -203,8 +203,6 @@ struct rzip_control { uchar salt[16]; uchar *pass_hash; uchar *hash; - uchar *hash_iv; - aes_context aes_ctx; unsigned char eof; unsigned char magic_written; md5_ctx ctx; diff --git a/runzip.c b/runzip.c index 89dc0dc..38859d6 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_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++) if (md5_stored[i] != md5_resblock[i]) { print_output("MD5 CHECK FAILED.\nStored:"); diff --git a/rzip.c b/rzip.c index 8f6025b..088947f 100644 --- a/rzip.c +++ b/rzip.c @@ -978,7 +978,7 @@ retry: } /* When encrypting data, we encrypt the MD5 value as well */ 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)) fatal("Failed to write md5 in rzip_fd\n"); diff --git a/stream.c b/stream.c index 059cedc..b351b40 100644 --- a/stream.c +++ b/stream.c @@ -66,7 +66,7 @@ static struct compress_thread{ pthread_mutex_t mutex; /* This thread's mutex */ struct stream_info *sinfo; int streamno; - uchar salt[16]; + uchar salt[BLOCKSALT_LEN]; } *cthread; static struct uncomp_thread{ @@ -1186,7 +1186,8 @@ retry: if (!ret && ENCRYPT) { 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); } @@ -1435,7 +1436,8 @@ fill_another: print_err("Failed to read_buf salt in fill_buffer\n"); 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); diff --git a/util.c b/util.c index a272a74..9287c25 100644 --- a/util.c +++ b/util.c @@ -48,9 +48,13 @@ #include #include +#include #include #include "lrzip_private.h" #include "liblrzip.h" +#include "sha4.h" +#include "aes.h" + static const char *infile = NULL; 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 * stealing to not have to pad the block */ - uchar ivec[80], tmp0[CBC_LEN], tmp1[CBC_LEN]; - uchar key[80], iv[80]; + uchar key[HASH_LEN + BLOCKSALT_LEN], iv[HASH_LEN + BLOCKSALT_LEN]; + uchar tmp0[CBC_LEN], tmp1[CBC_LEN]; + aes_context aes_ctx; i64 N, M; int i; /* Generate unique key and IV for each block of data based on salt */ - mlock(key, 80); - mlock(iv, 80); - for (i = 0; i < 64; i++) + mlock(&aes_ctx, sizeof(aes_ctx)); + mlock(key, HASH_LEN + BLOCKSALT_LEN); + mlock(iv, HASH_LEN + BLOCKSALT_LEN); + for (i = 0; i < HASH_LEN; i++) key[i] = control->pass_hash[i] ^ control->hash[i]; - memcpy(key + 64, salt, 16); - sha4(key, 80, key, 0); - for (i = 0; i < 64; i++) - ivec[i] = key[i] ^ control->pass_hash[i]; - memcpy(ivec + 64, salt, 16); - sha4(ivec, 80, ivec, 0); + memcpy(key + HASH_LEN, salt, BLOCKSALT_LEN); + sha4(key, HASH_LEN + BLOCKSALT_LEN, key, 0); + for (i = 0; i < HASH_LEN; i++) + iv[i] = key[i] ^ control->pass_hash[i]; + memcpy(iv + HASH_LEN, salt, BLOCKSALT_LEN); + sha4(iv, HASH_LEN + BLOCKSALT_LEN, iv, 0); M = len % CBC_LEN; N = len - M; if (encrypt) { 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"); - 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) { - memset(tmp0, 0, sizeof(tmp0)); + memset(tmp0, 0, CBC_LEN); memcpy(tmp0, buf + N, M); - aes_crypt_cbc(&control->aes_ctx, AES_ENCRYPT, CBC_LEN, - ivec, tmp0, tmp1); + aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, CBC_LEN, + iv, tmp0, tmp1); memcpy(buf + N, buf + N - CBC_LEN, M); memcpy(buf + N - CBC_LEN, tmp1, CBC_LEN); } } 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"); print_maxverbose("Decrypting data \n"); if (M) { - aes_crypt_cbc(&control->aes_ctx, AES_DECRYPT, N - CBC_LEN, - ivec, buf, buf); - aes_crypt_ecb(&control->aes_ctx, AES_DECRYPT, + aes_crypt_cbc(&aes_ctx, AES_DECRYPT, N - CBC_LEN, + iv, buf, buf); + aes_crypt_ecb(&aes_ctx, AES_DECRYPT, buf + N - CBC_LEN, tmp0); memset(tmp1, 0, CBC_LEN); memcpy(tmp1, buf + N, M); xor128(tmp0, tmp1); memcpy(buf + N, tmp0, 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); - xor128(buf + N - CBC_LEN, ivec); + xor128(buf + N - CBC_LEN, iv); } else - aes_crypt_cbc(&control->aes_ctx, AES_DECRYPT, len, - ivec, buf, buf); + aes_crypt_cbc(&aes_ctx, AES_DECRYPT, len, + iv, buf, buf); } - memset(ivec, 0, 80); - memset(key, 0, 80); - munlock(ivec, 80); - munlock(key, 80); -} \ No newline at end of file + memset(&aes_ctx, 0, sizeof(aes_ctx)); + memset(iv, 0, HASH_LEN + BLOCKSALT_LEN); + memset(key, 0, HASH_LEN + BLOCKSALT_LEN); + 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); + } +} diff --git a/util.h b/util.h index f74a677..1c95bdb 100644 --- a/util.h +++ b/util.h @@ -30,5 +30,6 @@ void failure(const char *format, ...); void round_to_page(i64 *size); void get_rand(uchar *buf, int len); void lrz_crypt(rzip_control *control, uchar *buf, i64 len, uchar *salt, int encrypt); +void lrz_keygen(rzip_control *control, const uchar *passphrase); #endif