From c5938c6a8b5ae2120b2d20272b6719f2b80ae640 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Mar 2011 23:52:39 +1100 Subject: [PATCH] Implement the actual aes cbc encryption and decryption. --- lrzip.c | 17 +++++++---- lrzip_private.h | 5 ++-- stream.c | 78 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 85 insertions(+), 15 deletions(-) diff --git a/lrzip.c b/lrzip.c index 9b02b8b..0539f95 100644 --- a/lrzip.c +++ b/lrzip.c @@ -44,6 +44,7 @@ #include "stream.h" #include "liblrzip.h" /* flag defines */ #include "sha4.h" +#include "aes.h" #define MAGIC_LEN (39) @@ -479,6 +480,7 @@ retry_pass: goto retry_pass; } } + print_output("\n"); termios_p.c_lflag |= ECHO; tcsetattr(fileno(stdin), 0, &termios_p); free(testphrase); @@ -486,10 +488,10 @@ retry_pass: memcpy(passphrase + PASS_LEN - SALT_LEN, control->salt, SALT_LEN); sha4(passphrase, PASS_LEN, control->hash, 0); - /* Copy the first hashed passphrase and use it to xor every - * cycle */ + /* Copy the first hashed passphrase and use it to xor every cycle */ memcpy(passphrase, control->hash, HASH_LEN); + 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] ^= passphrase[j]; @@ -634,8 +636,11 @@ void decompress_file(rzip_control *control) print_verbose("CRC32 "); print_verbose("being used for integrity testing.\n"); - if (ENCRYPT) + if (ENCRYPT) { get_hash(control, 0); + if (unlikely(aes_setkey_dec(&control->aes_ctx, control->hash, 128))) + failure("Failed to aes_setkey_dec in decompress_file\n"); + } print_progress("Decompressing...\n"); @@ -921,9 +926,11 @@ void compress_file(rzip_control *control) int fd_in, fd_out; char header[MAGIC_LEN]; - if (ENCRYPT) + if (ENCRYPT) { get_hash(control, 1); - + if (unlikely(aes_setkey_enc(&control->aes_ctx, control->hash, 128))) + failure("Failed to aes_setkey_enc in compress_file\n"); + } memset(header, 0, sizeof(header)); if (!STDIN) { diff --git a/lrzip_private.h b/lrzip_private.h index fde4c06..88006de 100644 --- a/lrzip_private.h +++ b/lrzip_private.h @@ -94,6 +94,7 @@ 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 +139,7 @@ typedef struct md5_ctx md5_ctx; #define PASS_LEN 512 #define HASH_LEN 64 #define SALT_LEN 16 +#define CBC_LEN 16 /* Needs to be less than 31 bits and page aligned on 32 bits */ #define two_gig ((1ull << 31) - 4096) @@ -197,12 +199,11 @@ struct rzip_control { int fd_out; int fd_hist; i64 encloops; - uchar loop_byte1; - uchar loop_byte2; i64 secs; uchar salt[16]; uchar *hash; uchar *hash_iv; + aes_context aes_ctx; unsigned char eof; unsigned char magic_written; md5_ctx ctx; diff --git a/stream.c b/stream.c index 42cfeef..f151490 100644 --- a/stream.c +++ b/stream.c @@ -1134,6 +1134,7 @@ static void *compthread(void *data) struct compress_thread *cti; struct stream_info *ctis; int waited = 0, ret = 0; + i64 padded_len; /* Make sure this thread doesn't already exist */ @@ -1165,6 +1166,33 @@ retry: else failure("Dunno wtf compression to use!\n"); } + if (!ret && ENCRYPT) { + int encrypt_pad = 0; + uchar *enc_buf; + + /* We must pad the block length to a mutliple of CBC_LEN to be + * able to encrypt. We pad it with random data */ + if (cti->c_len % CBC_LEN) + encrypt_pad = CBC_LEN - (cti->c_len % CBC_LEN); + padded_len = cti->c_len + encrypt_pad; + enc_buf = malloc(padded_len); + if (unlikely(!enc_buf)) + fatal("Failed to malloc enc_buf in compthread\n"); + if (encrypt_pad) { + cti->s_buf = realloc(cti->s_buf, padded_len); + if (unlikely(!cti->s_buf)) + fatal("Failed to realloc s_buf in compthread with encrypt_pad\n"); + get_rand(cti->s_buf + cti->c_len, encrypt_pad); + } + print_maxverbose("Encrypting block \n"); + if (unlikely(aes_crypt_cbc(&control->aes_ctx, AES_ENCRYPT, + padded_len, control->hash_iv, cti->s_buf, enc_buf))) + failure("Failed to aes_crypt_cbc in compthread\n"); + free(cti->s_buf); + cti->s_buf = enc_buf; + } else + padded_len = cti->c_len; + /* If compression fails for whatever reason multithreaded, then wait * for the previous thread to finish, serialising the work to decrease * the memory requirements, increasing the chance of success */ @@ -1224,6 +1252,7 @@ retry: fatal("Failed to seekto cur_pos in compthread %d\n", i); print_maxverbose("Thread %ld writing %lld compressed bytes from stream %d\n", i, cti->c_len, cti->streamno); + /* We store the real length even if it's padded longer */ if (unlikely(write_u8(control, ctis->fd, cti->c_type) || write_i64(control, ctis->fd, cti->c_len) || write_i64(control, ctis->fd, cti->s_len) || @@ -1232,10 +1261,10 @@ retry: } ctis->cur_pos += 25; - if (unlikely(write_buf(control, ctis->fd, cti->s_buf, cti->c_len))) + if (unlikely(write_buf(control, ctis->fd, cti->s_buf, padded_len))) fatal("Failed to write_buf in compthread %d\n", i); - ctis->cur_pos += cti->c_len; + ctis->cur_pos += padded_len; free(cti->s_buf); lock_mutex(&output_lock); @@ -1357,6 +1386,7 @@ static int fill_buffer(rzip_control *control, struct stream_info *sinfo, int str struct stream *s = &sinfo->s[streamno]; uchar c_type, *s_buf; stream_thread_struct *st; + i64 padded_len; if (s->buf) free(s->buf); @@ -1400,15 +1430,47 @@ fill_another: fsync(control->fd_out); - s_buf = malloc(u_len); - if (unlikely(u_len && !s_buf)) - fatal("Unable to malloc buffer of size %lld in fill_buffer\n", u_len); - sinfo->ram_alloced += u_len; + s_buf = malloc(c_len); + if (unlikely(c_len && !s_buf)) + fatal("Unable to malloc buffer of size %lld in fill_buffer\n", c_len); + sinfo->ram_alloced += c_len; - if (unlikely(read_buf(control, sinfo->fd, s_buf, c_len))) + if (ENCRYPT) { + /* If the data was encrypted, we need to read the padded data + * at the end and then discard it once it's decrypted */ + int decrypt_pad = 0; + + if (c_len % CBC_LEN) + decrypt_pad = CBC_LEN - (c_len % CBC_LEN); + padded_len = c_len + decrypt_pad; + if (decrypt_pad) { + s_buf = realloc(s_buf, padded_len); + if (unlikely(!s_buf)) + fatal("Failed to 1st realloc s_buf in fill_buffer\n"); + } + } else + padded_len = c_len; + + if (unlikely(read_buf(control, sinfo->fd, s_buf, padded_len))) return -1; - sinfo->total_read += c_len; + sinfo->total_read += padded_len; + + if (ENCRYPT) { + uchar *dec_buf; + + dec_buf = malloc(padded_len); + if (unlikely(!dec_buf)) + fatal("Failed to malloc dec_buf in fill_buffer\n"); + print_maxverbose("Decrypting block \n"); + if (unlikely(aes_crypt_cbc(&control->aes_ctx, AES_DECRYPT, + padded_len, control->hash_iv, s_buf, dec_buf))) + failure("Failed to aes_crypt_cbc in fill_buffer\n"); + free(s_buf); + s_buf = realloc(dec_buf, c_len); + if (unlikely(!s_buf)) + fatal("Failed to 2nd realloc s_buf in fill_buffer\n"); + } ucthread[s->uthread_no].s_buf = s_buf; ucthread[s->uthread_no].c_len = c_len;