Skip to content

Commit 828e313

Browse files
committed
optimized AES encryption's memory allocation
1 parent e09eecc commit 828e313

File tree

2 files changed

+81
-63
lines changed

2 files changed

+81
-63
lines changed

Makefile

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
33

44
EXECUTABLE=bethela
55
INSTALLPATH=/usr/local/bin
6-
DFLAGS=
6+
RBUFFER_FLAG=
77

88
OS := $(shell uname)
99

@@ -57,6 +57,10 @@ COMPILATION_MSG="compiling AES aarch64 neon version"
5757
VERSION_FLAGS=-DUSE_ARM_AES -D_USE_ARM_NEON_AES -march=armv8-a+crypto
5858
endif
5959

60+
ifeq ($(RBUFFER), stack)
61+
RBUFFER_FLAG=-D_USE_RBUFFER_ON_STACK
62+
endif
63+
6064
.PHONY: default environment compile install uninstall encrypt_decrypt randfile checkfile genkeys vig_encrypt_decrypt clean
6165

6266
default:
@@ -66,6 +70,7 @@ default:
6670
@echo "TYPE : release, debug, debug_threads"
6771
@echo "VERSION : portable, aesni, neon"
6872
@echo "LINK : dynamic, static"
73+
@echo "RBUFFER : heap, stack"
6974
@echo ""
7075
@echo "Makefile recipes"
7176

@@ -74,7 +79,7 @@ environment:
7479

7580
compile:
7681
@echo $(COMPILATION_MSG)
77-
$(CXX) $(LINKER) $(CXX_STANDARD) main.cpp -o $(EXECUTABLE) $(VERSION_FLAGS) $(THREADING) $(CXX_FLAGS) $(DFLAGS)
82+
$(CXX) $(LINKER) $(CXX_STANDARD) main.cpp -o $(EXECUTABLE) $(RBUFFER_FLAG) $(VERSION_FLAGS) $(THREADING) $(CXX_FLAGS)
7883

7984
install:
8085
ifeq ($(OS), Linux)
@@ -130,7 +135,7 @@ clean:
130135
@rm RandFile
131136

132137
simple-test:
133-
@$(MAKE) compile CXX=clang++ TYPE=release VERSION=aesni LINK=dynamic
138+
@$(MAKE) compile CXX=clang++ TYPE=debug VERSION=aesni LINK=dynamic
134139
@$(MAKE) genkeys CXX=clang++
135140
@$(MAKE) randfile CXX=clang++
136141
@$(MAKE) encrypt_decrypt

main.cpp

Lines changed: 73 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,7 @@ int main(int argc, char *args[]) {
250250

251251
bool run_thread = true;
252252

253-
254-
char *next_buffer = new char[BUFFER_BYTESIZE];
255-
char *prev_buffer = new char[BUFFER_BYTESIZE];
256-
Krypt::Bytes *enc_buffer = new Krypt::Bytes[BUFFER_BYTESIZE];
253+
char *read_buffer = new char[BUFFER_BYTESIZE];
257254

258255
while (run_thread) {
259256
std::string target_file;
@@ -295,84 +292,100 @@ int main(int argc, char *args[]) {
295292
output_file.open(outfname, std::ios::binary | std::ios::app);
296293
output_file.write(reinterpret_cast<const char *>(iv), AES_BLOCKSIZE);
297294

298-
char *swap_buffer_ptr;
295+
// new encryption
299296

300-
curr_file.read(prev_buffer, BUFFER_BYTESIZE);
301-
size_t prev_buffer_size = curr_file.gcount();
302-
size_t next_buffer_size = 0;
297+
/// last read block of buffer is empty.
298+
bool last_read_empty = false;
299+
300+
/// second last read block is a whole BUFFER_BYTESIZE.
301+
bool prev_read_whole = true;
302+
303+
char empty_padding_block[AES_BLOCKSIZE] = {
304+
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
305+
};
306+
307+
char encrypted_block_holder[AES_BLOCKSIZE] = {};
303308

304309
while (!curr_file.eof()) {
305-
curr_file.read(next_buffer, BUFFER_BYTESIZE);
306-
next_buffer_size = curr_file.gcount();
310+
curr_file.read(read_buffer, BUFFER_BYTESIZE);
311+
size_t read_buffer_size = curr_file.gcount();
307312

308-
if (!next_buffer_size) {
313+
last_read_empty = !read_buffer_size;
314+
if (last_read_empty) {
315+
// no bytes left to read.
309316
break;
310317
}
311318

312-
for (size_t index = 0; index < prev_buffer_size; index += AES_BLOCKSIZE) {
313-
aes_scheme.blockEncrypt(
314-
reinterpret_cast<unsigned char *>(prev_buffer + index),
315-
reinterpret_cast<unsigned char *>(enc_buffer + index), iv
316-
);
319+
prev_read_whole = read_buffer_size == BUFFER_BYTESIZE;
320+
321+
if (prev_read_whole) { // just encrypt all the blocks.
322+
for (size_t index = 0; index < BUFFER_BYTESIZE; index += AES_BLOCKSIZE) {
323+
aes_scheme.blockEncrypt(
324+
reinterpret_cast<unsigned char *>(read_buffer + index),
325+
reinterpret_cast<unsigned char *>(encrypted_block_holder), iv
326+
);
327+
std::memcpy(read_buffer + index, encrypted_block_holder, AES_BLOCKSIZE);
328+
}
329+
330+
output_file.write(reinterpret_cast<char *>(read_buffer), BUFFER_BYTESIZE);
331+
} else if (read_buffer_size % AES_BLOCKSIZE == 0) {
332+
for (size_t index = 0; index < read_buffer_size; index += AES_BLOCKSIZE) {
333+
aes_scheme.blockEncrypt(
334+
reinterpret_cast<unsigned char *>(read_buffer + index),
335+
reinterpret_cast<unsigned char *>(encrypted_block_holder), iv
336+
);
337+
std::memcpy(read_buffer + index, encrypted_block_holder, AES_BLOCKSIZE);
338+
}
339+
340+
last_read_empty = prev_read_whole = true;
341+
342+
output_file.write(reinterpret_cast<char *>(read_buffer), read_buffer_size);
343+
break;
344+
} else { // this branch in decryption is non existent.
345+
size_t remaining_blocks = read_buffer_size / AES_BLOCKSIZE;
346+
size_t remaining_bytes = read_buffer_size % AES_BLOCKSIZE;
347+
size_t index = 0;
348+
349+
if (remaining_blocks) {
350+
for (; index < remaining_blocks; ++index) {
351+
aes_scheme.blockEncrypt(
352+
reinterpret_cast<unsigned char *>(read_buffer + (index * AES_BLOCKSIZE)),
353+
reinterpret_cast<unsigned char *>(encrypted_block_holder), iv
354+
);
355+
std::memcpy(read_buffer + (index * AES_BLOCKSIZE), encrypted_block_holder, AES_BLOCKSIZE);
356+
}
357+
358+
output_file.write(reinterpret_cast<char *>(read_buffer), remaining_blocks * AES_BLOCKSIZE);
359+
}
360+
361+
if (remaining_bytes) {
362+
Krypt::ByteArray cipher = aes_scheme.encrypt(
363+
reinterpret_cast<unsigned char *>(read_buffer + (index * AES_BLOCKSIZE)), remaining_bytes, iv
364+
);
365+
output_file.write(reinterpret_cast<char *>(cipher.array), cipher.length);
366+
}
317367
}
318-
319-
output_file.write(reinterpret_cast<char *>(enc_buffer), prev_buffer_size);
320-
321-
swap_buffer_ptr = next_buffer;
322-
next_buffer = prev_buffer;
323-
prev_buffer = swap_buffer_ptr;
324-
swap_buffer_ptr = nullptr;
325-
std::swap(next_buffer_size, prev_buffer_size);
326368
}
327369

328-
size_t remaining_blocks = prev_buffer_size / AES_BLOCKSIZE;
329-
size_t remaining_bytes = prev_buffer_size % AES_BLOCKSIZE;
330-
size_t index = 0;
331-
332-
bool excludeLastBlock = (remaining_blocks && remaining_bytes == 0);
333-
334-
if (remaining_blocks) {
335-
for (; index < remaining_blocks - excludeLastBlock; ++index) {
336-
aes_scheme.blockEncrypt(
337-
reinterpret_cast<unsigned char *>(prev_buffer + (index * AES_BLOCKSIZE)),
338-
reinterpret_cast<unsigned char *>(enc_buffer + (index * AES_BLOCKSIZE)), iv
339-
);
340-
}
341-
342-
output_file.write(
343-
reinterpret_cast<char *>(enc_buffer), (remaining_blocks - excludeLastBlock) * AES_BLOCKSIZE
370+
if (last_read_empty && prev_read_whole) {
371+
aes_scheme.blockEncrypt(
372+
reinterpret_cast<unsigned char *>(empty_padding_block),
373+
reinterpret_cast<unsigned char *>(encrypted_block_holder), iv
344374
);
345-
}
346-
347-
Krypt::ByteArray cipher;
348375

349-
if (excludeLastBlock) {
350-
cipher = aes_scheme.encrypt(
351-
reinterpret_cast<unsigned char *>(prev_buffer + (index * AES_BLOCKSIZE)), AES_BLOCKSIZE, iv
352-
);
353-
} else {
354-
cipher = aes_scheme.encrypt(
355-
reinterpret_cast<unsigned char *>(prev_buffer + (index * AES_BLOCKSIZE)), remaining_bytes, iv
356-
);
376+
output_file.write(reinterpret_cast<char *>(encrypted_block_holder), AES_BLOCKSIZE);
357377
}
358378

359-
output_file.write(reinterpret_cast<char *>(cipher.array), cipher.length);
360-
379+
// new encryption
361380
cnt++;
362381

363382
std::memset((unsigned char *) iv, 0x00, AES_BLOCKSIZE);
364383
delete[] iv;
365-
366384
checkif_replace(args[COMMAND], target_file);
367385
}
368386
}
369387

370-
std::memset((char *) next_buffer, 0x00, BUFFER_BYTESIZE);
371-
std::memset((Krypt::Bytes *) enc_buffer, 0x00, BUFFER_BYTESIZE);
372-
373-
delete[] next_buffer;
374-
delete[] prev_buffer;
375-
delete[] enc_buffer;
388+
delete[] read_buffer;
376389
};
377390

378391
std::vector<std::thread> threads;

0 commit comments

Comments
 (0)