From 1e1f4450e8da41a7d775066971782de3f323671a Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Tue, 12 Jul 2022 14:41:18 +0200 Subject: [PATCH 1/7] Feat: Only use one loop and calculte checksum on the fly --- Implementierung/Makefile | 2 +- Implementierung/lib/md2_impls/md2_2.h | 21 ++++++++ Implementierung/src/md2.c | 6 +++ Implementierung/src/md2_impls/md2_2.c | 76 +++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 Implementierung/lib/md2_impls/md2_2.h create mode 100644 Implementierung/src/md2_impls/md2_2.c diff --git a/Implementierung/Makefile b/Implementierung/Makefile index 1c7ed9f..843d95b 100644 --- a/Implementierung/Makefile +++ b/Implementierung/Makefile @@ -1,6 +1,6 @@ -SRC = src/main.c src/helper.c src/io.c src/md2.c src/md2_impls/md2_common.c src/md2_impls/md2_0.c +SRC = src/main.c src/helper.c src/io.c src/md2.c src/md2_impls/md2_common.c src/md2_impls/md2_0.c src/md2_impls/md2_2.c OBJ = ${subst src,build,${SRC:.c=.o}} CC = gcc CFLAGS = -Ilib -ggdb -std=c11 -g -Wall -Wextra -no-pie -O3 diff --git a/Implementierung/lib/md2_impls/md2_2.h b/Implementierung/lib/md2_impls/md2_2.h new file mode 100644 index 0000000..3e6ff3f --- /dev/null +++ b/Implementierung/lib/md2_impls/md2_2.h @@ -0,0 +1,21 @@ +#ifndef MD2_2_H +#define MD2_2_H + +#include +#include +#include +#include +#include +#include + +/** + * @brief This implementation loads the file in bits and not at once + * + * @param _ unused + * @param filename name of the file to load + * @param out + */ +void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]); +void md2_checksum_2(size_t len, uint8_t* buf); + +#endif // MD2_2_H \ No newline at end of file diff --git a/Implementierung/src/md2.c b/Implementierung/src/md2.c index 8be67f4..da49453 100644 --- a/Implementierung/src/md2.c +++ b/Implementierung/src/md2.c @@ -2,6 +2,7 @@ // include all implementations #include "../lib/md2_impls/md2_0.h" +#include "../lib/md2_impls/md2_2.h" md2_hash_func md2_hash; md2_checksum_func md2_checksum; @@ -22,6 +23,11 @@ bool md2_choose_implementation(int i) { md2_checksum = md2_checksum_0; return true; + case 2: + md2_hash = md2_hash_2; + md2_checksum = md2_checksum_2; + return true; + default: return false; } diff --git a/Implementierung/src/md2_impls/md2_2.c b/Implementierung/src/md2_impls/md2_2.c new file mode 100644 index 0000000..874c097 --- /dev/null +++ b/Implementierung/src/md2_impls/md2_2.c @@ -0,0 +1,76 @@ +#include "../../lib/md2_impls/md2_2.h" + +#include "../../lib/md2_impls/md2_common.h" + +void process_block_hash(uint8_t block[16], uint8_t messageDigestBuf[48]) { + for (int j = 0; j < 16; j++) { + messageDigestBuf[16 + j] = block[j]; + messageDigestBuf[32 + j] = (messageDigestBuf[16 + j] ^ messageDigestBuf[j]); + } + + u_int8_t t = 0; + + for (int j = 0; j < 18; j++) { + for (int k = 0; k < 48; k++) { + t = messageDigestBuf[k] = messageDigestBuf[k] ^ MD2_PI_SUBST[t]; + } + t = (t + j) % 256; + } +} + +void process_block_checksum(uint8_t block[16], uint8_t checksum[16], + uint8_t* l) { + for (int j = 0; j < 16; j++) { + u_int8_t c = block[j]; + // reference is wrong. It says: Set C[j] to S[c xor L]. But it should be: + (*l) = checksum[j] ^= MD2_PI_SUBST[c ^ (*l)]; + } +} + +void md2_checksum_2(size_t len, uint8_t* buf) { + uint8_t l = 0; + + for (size_t i = 0; i < len / 16; i++) { + process_block_checksum(buf + (i * 16), buf + len, &l); + } +} + +void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { + // === step 1 === + int paddingNeeded = 16 - (len % 16); + uint8_t originalPadding = paddingNeeded; + len += paddingNeeded; + + // printf("len: %d\n", len); + + // +16 for the checksum + uint8_t* newBuf = calloc(len + 16, sizeof(uint8_t)); + // TODO: null check + memcpy(newBuf, buf, len - paddingNeeded); + + // printBuf(len + 16, newBuf); + + while (paddingNeeded > 0) { + newBuf[len - paddingNeeded] = originalPadding; + paddingNeeded--; + } + // printf("buf with padding: "); + // printBuf(len + 16, newBuf); + + // === step 3 === + uint8_t* messageDigestBuf = calloc(48, sizeof(uint8_t)); + + // === step 4 === + uint8_t l = 0; + // <= because we need to hash the last block too + for (size_t i = 0; i < len / 16; i++) { + process_block_checksum(newBuf + (i * 16), newBuf + len, &l); + process_block_hash(newBuf + (i * 16), messageDigestBuf); + } + + process_block_hash(newBuf + len, messageDigestBuf); + + memcpy(out, messageDigestBuf, 16); + + free(newBuf); +} From d35d338fb1e8fa8280e687025b365167bd3d3c5f Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Tue, 12 Jul 2022 16:02:30 +0200 Subject: [PATCH 2/7] Fix: missing free --- Implementierung/src/md2_impls/md2_2.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Implementierung/src/md2_impls/md2_2.c b/Implementierung/src/md2_impls/md2_2.c index 874c097..1fac14a 100644 --- a/Implementierung/src/md2_impls/md2_2.c +++ b/Implementierung/src/md2_impls/md2_2.c @@ -27,13 +27,8 @@ void process_block_checksum(uint8_t block[16], uint8_t checksum[16], } } -void md2_checksum_2(size_t len, uint8_t* buf) { - uint8_t l = 0; - - for (size_t i = 0; i < len / 16; i++) { - process_block_checksum(buf + (i * 16), buf + len, &l); - } -} +// unused! +void md2_checksum_2(size_t, uint8_t*) {} void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { // === step 1 === @@ -44,7 +39,7 @@ void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { // printf("len: %d\n", len); // +16 for the checksum - uint8_t* newBuf = calloc(len + 16, sizeof(uint8_t)); + uint8_t* newBuf = calloc(len, sizeof(uint8_t)); // TODO: null check memcpy(newBuf, buf, len - paddingNeeded); @@ -62,15 +57,18 @@ void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { // === step 4 === uint8_t l = 0; - // <= because we need to hash the last block too + uint8_t* checksum = calloc(16, sizeof(uint8_t)); + for (size_t i = 0; i < len / 16; i++) { - process_block_checksum(newBuf + (i * 16), newBuf + len, &l); + process_block_checksum(newBuf + (i * 16), checksum, &l); process_block_hash(newBuf + (i * 16), messageDigestBuf); } - process_block_hash(newBuf + len, messageDigestBuf); + process_block_hash(checksum, messageDigestBuf); memcpy(out, messageDigestBuf, 16); free(newBuf); + free(messageDigestBuf); + free(checksum); } From 4a678b863b652e00c1dd194ace37d465021fdc17 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Tue, 12 Jul 2022 22:33:01 +0200 Subject: [PATCH 3/7] Feat: Implement V2 --- Implementierung/lib/io.h | 11 +++++ Implementierung/lib/md2_impls/md2_2.h | 2 + Implementierung/src/io.c | 43 +++++++++++-------- Implementierung/src/main.c | 56 +++++++++++++++++-------- Implementierung/src/md2_impls/md2_2.c | 59 ++++++++++++++++----------- 5 files changed, 113 insertions(+), 58 deletions(-) diff --git a/Implementierung/lib/io.h b/Implementierung/lib/io.h index f780a77..6887f25 100644 --- a/Implementierung/lib/io.h +++ b/Implementierung/lib/io.h @@ -10,6 +10,17 @@ #include #include +/** + * @brief Open a file and load its stats + * + * @param path the filepath + * @param file where the pointer of the file handle should be stored + * @param file_stat pointer to a stat struct + * @return true it worked + * @return false there was an error + */ +bool open_file(const char* path, FILE** file, struct stat* file_stat); + /** * @brief reads a file at a path * diff --git a/Implementierung/lib/md2_impls/md2_2.h b/Implementierung/lib/md2_impls/md2_2.h index 3e6ff3f..4e64689 100644 --- a/Implementierung/lib/md2_impls/md2_2.h +++ b/Implementierung/lib/md2_impls/md2_2.h @@ -8,6 +8,8 @@ #include #include +#include "../io.h" + /** * @brief This implementation loads the file in bits and not at once * diff --git a/Implementierung/src/io.c b/Implementierung/src/io.c index dedb5ce..4983811 100644 --- a/Implementierung/src/io.c +++ b/Implementierung/src/io.c @@ -1,26 +1,35 @@ #include "../lib/io.h" +bool open_file(const char* path, FILE** file, struct stat* file_stat) { + (*file) = fopen(path, "r"); + if ((*file) == NULL) { + printf("Fopen error: %d\n", errno); + fclose((*file)); + return false; + } + + int status = fstat(fileno((*file)), file_stat); + if (status == -1) { + printf("Fstat error: %d\n", errno); + fclose((*file)); + return false; + }; + + if ((file_stat->st_mode & S_IFMT) != S_IFREG) { + printf("File is not a regular file!\n"); + fclose((*file)); + return false; + } + + return true; +} + uint8_t* read_file(const char* path, size_t* size) { // Read the contents of the file specified by path into a heap-allocated // buffer and return a pointer to that buffer. - FILE* f = fopen(path, "r"); - if (f == NULL) { - printf("Fopen error: %d\n", errno); - fclose(f); - return NULL; - } - + FILE* f; struct stat statOfFile; - int status = fstat(fileno(f), &statOfFile); - if (status == -1) { - printf("Fstat error: %d\n", errno); - fclose(f); - return NULL; - }; - - if ((statOfFile.st_mode & S_IFMT) != S_IFREG) { - printf("File is not a regular file!\n"); - fclose(f); + if (!open_file(path, &f, &statOfFile)) { return NULL; } diff --git a/Implementierung/src/main.c b/Implementierung/src/main.c index 9bdb675..08d26de 100644 --- a/Implementierung/src/main.c +++ b/Implementierung/src/main.c @@ -62,6 +62,38 @@ unsigned runTests(struct configuration* c) { return failed; } +bool calculate_hash(struct configuration c, char* hash) { + size_t len; + uint8_t* data; + + if (c.implementationToUse != 2) { + data = read_file(c.filename, &len); + } else { + data = (uint8_t*)c.filename; + len = 0; + } + + if (data == NULL) { + printf("Error reading file %s!", c.filename); + return false; + } + + uint8_t out[16]; + if (c.doBenchmark) { + double duration = + run_benchmark(c.benchmarkingCycles, md2_hash, len, data, out); + printf("Running %d cycles took %f seconds\n", c.benchmarkingCycles, + duration); + } else { + md2_hash(len, data, out); + } + + md2_encode_hash(out, hash); + + if (c.implementationToUse != 2) free(data); + return true; +} + int main(int argc, char** argv) { struct configuration c; enum argumentParseResult result = parseArguments(argc, argv, &c); @@ -87,33 +119,21 @@ int main(int argc, char** argv) { "benchmark cycles: %d\n", c.implementationToUse, c.doBenchmark, c.benchmarkingCycles); + if (c.runTests && c.implementationToUse == 2) { + fprintf(stderr, "Cannot run tests on implementation 2!"); + return EXIT_FAILURE; + } + if (c.runTests) { printf("Running tests...\n\n"); return runTests(&c); } printf("Hashing file %s...\n\n", c.filename); - size_t len; - uint8_t* data = read_file(c.filename, &len); - if (data == NULL) { - printf("Error reading file %s!", c.filename); - return EXIT_FAILURE; - } - uint8_t out[16]; char hash[32]; - if (c.doBenchmark) { - double duration = - run_benchmark(c.benchmarkingCycles, md2_hash, len, data, out); - printf("Running %d cycles took %f seconds\n", c.benchmarkingCycles, - duration); - } else { - md2_hash(len, data, out); - } - md2_encode_hash(out, hash); + calculate_hash(c, hash); printf("Hash: %s\n", hash); - free(data); - return 0; } diff --git a/Implementierung/src/md2_impls/md2_2.c b/Implementierung/src/md2_impls/md2_2.c index 1fac14a..f8d54d8 100644 --- a/Implementierung/src/md2_impls/md2_2.c +++ b/Implementierung/src/md2_impls/md2_2.c @@ -27,30 +27,26 @@ void process_block_checksum(uint8_t block[16], uint8_t checksum[16], } } -// unused! -void md2_checksum_2(size_t, uint8_t*) {} - -void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { - // === step 1 === +void apply_padding(size_t len, uint8_t buf[16]) { int paddingNeeded = 16 - (len % 16); uint8_t originalPadding = paddingNeeded; len += paddingNeeded; - // printf("len: %d\n", len); - - // +16 for the checksum - uint8_t* newBuf = calloc(len, sizeof(uint8_t)); - // TODO: null check - memcpy(newBuf, buf, len - paddingNeeded); - - // printBuf(len + 16, newBuf); - while (paddingNeeded > 0) { - newBuf[len - paddingNeeded] = originalPadding; + buf[len - paddingNeeded] = originalPadding; paddingNeeded--; } - // printf("buf with padding: "); - // printBuf(len + 16, newBuf); + printf("buf with padding: "); + md2_print_buf(len, buf); +} + +// unused! +void md2_checksum_2(size_t, uint8_t*) {} + +void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { + FILE* file; + struct stat file_stat; + open_file((char*)buf, &file, &file_stat); // === step 3 === uint8_t* messageDigestBuf = calloc(48, sizeof(uint8_t)); @@ -59,16 +55,33 @@ void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { uint8_t l = 0; uint8_t* checksum = calloc(16, sizeof(uint8_t)); - for (size_t i = 0; i < len / 16; i++) { - process_block_checksum(newBuf + (i * 16), checksum, &l); - process_block_hash(newBuf + (i * 16), messageDigestBuf); - } + uint8_t* data = malloc(16); + size_t bytes_left_to_read = file_stat.st_size; + size_t bytes_left_to_process = 0; + + while (bytes_left_to_read != 0) { + bytes_left_to_process = bytes_left_to_read >= 16 ? 16 : bytes_left_to_read; + + fread(data, 1, bytes_left_to_process, file); + if (ferror(file) || feof(file)) { + fprintf(stderr, "Error reading the file!"); + return; + } + + process_block_checksum(data, checksum, &l); + process_block_hash(data, messageDigestBuf); + + bytes_left_to_read -= bytes_left_to_process; + }; + + apply_padding(bytes_left_to_process % 16, data); + process_block_checksum(data, checksum, &l); + process_block_hash(data, messageDigestBuf); process_block_hash(checksum, messageDigestBuf); - memcpy(out, messageDigestBuf, 16); - free(newBuf); + free(data); free(messageDigestBuf); free(checksum); } From 03016a1979ad0adde298763e07c2e63779ae6739 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Tue, 12 Jul 2022 22:35:13 +0200 Subject: [PATCH 4/7] Fix: close file --- Implementierung/src/md2_impls/md2_2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Implementierung/src/md2_impls/md2_2.c b/Implementierung/src/md2_impls/md2_2.c index f8d54d8..f1ab4b6 100644 --- a/Implementierung/src/md2_impls/md2_2.c +++ b/Implementierung/src/md2_impls/md2_2.c @@ -74,6 +74,8 @@ void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { bytes_left_to_read -= bytes_left_to_process; }; + fclose(file); + apply_padding(bytes_left_to_process % 16, data); process_block_checksum(data, checksum, &l); process_block_hash(data, messageDigestBuf); From 2a6bb4354ed1b8b979c74775d2e4b56730e09735 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Tue, 12 Jul 2022 22:36:26 +0200 Subject: [PATCH 5/7] Fix: fail on error --- Implementierung/src/md2_impls/md2_2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Implementierung/src/md2_impls/md2_2.c b/Implementierung/src/md2_impls/md2_2.c index f1ab4b6..e250f05 100644 --- a/Implementierung/src/md2_impls/md2_2.c +++ b/Implementierung/src/md2_impls/md2_2.c @@ -46,7 +46,10 @@ void md2_checksum_2(size_t, uint8_t*) {} void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { FILE* file; struct stat file_stat; - open_file((char*)buf, &file, &file_stat); + if (!open_file((char*)buf, &file, &file_stat)) { + fprintf(stderr, "Error opening the file!"); + return; + } // === step 3 === uint8_t* messageDigestBuf = calloc(48, sizeof(uint8_t)); From 21d351c7e2b1672a4abb49be8bc5a646d544d838 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Tue, 12 Jul 2022 22:37:54 +0200 Subject: [PATCH 6/7] Fix: handle file opening errors --- Implementierung/src/io.c | 1 - Implementierung/src/md2_impls/md2_2.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Implementierung/src/io.c b/Implementierung/src/io.c index 4983811..00840d2 100644 --- a/Implementierung/src/io.c +++ b/Implementierung/src/io.c @@ -4,7 +4,6 @@ bool open_file(const char* path, FILE** file, struct stat* file_stat) { (*file) = fopen(path, "r"); if ((*file) == NULL) { printf("Fopen error: %d\n", errno); - fclose((*file)); return false; } diff --git a/Implementierung/src/md2_impls/md2_2.c b/Implementierung/src/md2_impls/md2_2.c index e250f05..b51a47a 100644 --- a/Implementierung/src/md2_impls/md2_2.c +++ b/Implementierung/src/md2_impls/md2_2.c @@ -47,7 +47,7 @@ void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { FILE* file; struct stat file_stat; if (!open_file((char*)buf, &file, &file_stat)) { - fprintf(stderr, "Error opening the file!"); + fprintf(stderr, "Error opening the file!\n"); return; } From 82f3f7efa83f7ce053bc24f6de60f6274ede66ea Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Tue, 12 Jul 2022 22:53:17 +0200 Subject: [PATCH 7/7] Chore: improove error handling and logging --- Implementierung/src/io.c | 7 ++++--- Implementierung/src/main.c | 19 +++++++++++++++---- Implementierung/src/md2_impls/md2_2.c | 5 +---- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Implementierung/src/io.c b/Implementierung/src/io.c index 00840d2..339bd75 100644 --- a/Implementierung/src/io.c +++ b/Implementierung/src/io.c @@ -3,19 +3,20 @@ bool open_file(const char* path, FILE** file, struct stat* file_stat) { (*file) = fopen(path, "r"); if ((*file) == NULL) { - printf("Fopen error: %d\n", errno); + if (errno == 0) errno = EIO; return false; } int status = fstat(fileno((*file)), file_stat); if (status == -1) { - printf("Fstat error: %d\n", errno); + if (errno == 0) errno = EIO; fclose((*file)); return false; }; if ((file_stat->st_mode & S_IFMT) != S_IFREG) { printf("File is not a regular file!\n"); + errno = ENOENT; fclose((*file)); return false; } @@ -38,8 +39,8 @@ uint8_t* read_file(const char* path, size_t* size) { fread(data, statOfFile.st_blksize, statOfFile.st_blocks, f); // size_t bytesRead = fread(data, sizeof(uint8_t), statOfFile.st_size, f); if (bytesRead != 0 && !feof(f)) { - printf("Error reading file!\n"); fclose(f); + if (errno == 0) errno = EIO; return NULL; } diff --git a/Implementierung/src/main.c b/Implementierung/src/main.c index 08d26de..42b8e6f 100644 --- a/Implementierung/src/main.c +++ b/Implementierung/src/main.c @@ -74,10 +74,11 @@ bool calculate_hash(struct configuration c, char* hash) { } if (data == NULL) { - printf("Error reading file %s!", c.filename); + printf("Error reading file %s!\n", c.filename); return false; } + errno = 0; uint8_t out[16]; if (c.doBenchmark) { double duration = @@ -88,6 +89,10 @@ bool calculate_hash(struct configuration c, char* hash) { md2_hash(len, data, out); } + if (errno != 0) { + return false; + } + md2_encode_hash(out, hash); if (c.implementationToUse != 2) free(data); @@ -120,7 +125,7 @@ int main(int argc, char** argv) { c.implementationToUse, c.doBenchmark, c.benchmarkingCycles); if (c.runTests && c.implementationToUse == 2) { - fprintf(stderr, "Cannot run tests on implementation 2!"); + fprintf(stderr, "Cannot run tests on implementation 2!\n"); return EXIT_FAILURE; } @@ -132,8 +137,14 @@ int main(int argc, char** argv) { printf("Hashing file %s...\n\n", c.filename); char hash[32]; - calculate_hash(c, hash); + if (!calculate_hash(c, hash)) { + if (errno != 0) { + fprintf(stderr, "\n\033[0;31mAn error occured: %s\033[0m\n", + strerror(errno)); + } + return EXIT_FAILURE; + } printf("Hash: %s\n", hash); - return 0; + return EXIT_SUCCESS; } diff --git a/Implementierung/src/md2_impls/md2_2.c b/Implementierung/src/md2_impls/md2_2.c index b51a47a..1349c0f 100644 --- a/Implementierung/src/md2_impls/md2_2.c +++ b/Implementierung/src/md2_impls/md2_2.c @@ -36,8 +36,6 @@ void apply_padding(size_t len, uint8_t buf[16]) { buf[len - paddingNeeded] = originalPadding; paddingNeeded--; } - printf("buf with padding: "); - md2_print_buf(len, buf); } // unused! @@ -47,7 +45,6 @@ void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { FILE* file; struct stat file_stat; if (!open_file((char*)buf, &file, &file_stat)) { - fprintf(stderr, "Error opening the file!\n"); return; } @@ -67,7 +64,7 @@ void md2_hash_2(size_t len, const uint8_t buf[len], uint8_t out[16]) { fread(data, 1, bytes_left_to_process, file); if (ferror(file) || feof(file)) { - fprintf(stderr, "Error reading the file!"); + if (errno == 0) errno = EIO; return; }