From cddc411a19babd7890c8e0606933aee8afb85174 Mon Sep 17 00:00:00 2001 From: afonso Date: Thu, 22 Feb 2024 22:32:33 +0000 Subject: [PATCH] [c] changed cfich_chacha20.c to handle any file size --- TPs/TP02/c/src/cfich_chacha20.c | 281 ++++++++++++-------------------- 1 file changed, 100 insertions(+), 181 deletions(-) diff --git a/TPs/TP02/c/src/cfich_chacha20.c b/TPs/TP02/c/src/cfich_chacha20.c index a2940c9..b26b390 100644 --- a/TPs/TP02/c/src/cfich_chacha20.c +++ b/TPs/TP02/c/src/cfich_chacha20.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -7,33 +9,50 @@ void setup(char *key_file) { FILE *f = fopen(key_file, "wb"); if (f == NULL) { printf("Error opening file\n"); - goto close; + return; } unsigned char key_bytes[32]; if (RAND_bytes(key_bytes, 32) != 1) { printf("Error generating random bytes\n"); - goto close; + fclose(f); + return; } if (fwrite(key_bytes, 1, 32, f) != 32) { printf("Error writing to file\n"); - goto close; } - goto close; -close: fclose(f); } -int encrypt(char *input_file, char *key_file) { - FILE *fkey = fopen(key_file, "rb"); +int chacha20(const char *input_file, const char *output_file, const char *key_file, int enc) { + int BUF_SIZE = 1024; + + int u_len = 0, f_len = 0; + + unsigned char input_buf[BUF_SIZE], output_buf[BUF_SIZE]; + + FILE *finput = fopen(input_file, "rb"); + if (finput == NULL) { + printf("Error opening input file\n"); + return 1; + } + + // Open output file + FILE *foutput = fopen(output_file, "wb"); + if (foutput == NULL) { + printf("Error opening output file\n"); + fclose(finput); + return 1; + } + + FILE *fkey = fopen(key_file, "rb"); if (fkey == NULL) { printf("Error opening key file\n"); return 1; } - unsigned char key_bytes[32]; if (fread(key_bytes, 1, 32, fkey) != 32) { printf("Error reading key from file\n"); @@ -42,204 +61,104 @@ int encrypt(char *input_file, char *key_file) { } fclose(fkey); - FILE *finput = fopen(input_file, "rb"); - if (finput == NULL) { - printf("Error opening input file\n"); - return 1; - } - // Determining file size - fseek(finput, 0, SEEK_END); - unsigned long fsize = ftell(finput); - rewind(finput); - - unsigned char *plaintext = malloc(fsize * sizeof(unsigned char)); - if (plaintext == NULL) { - printf("Error allocating memory\n"); - fclose(finput); - return 1; - } - - if (fread(plaintext, 1, fsize, finput) != fsize) { - printf("Error reading file\n"); - fclose(finput); - free(plaintext); - return 1; - } - fclose(finput); - - unsigned char nonce[16]; - if (RAND_bytes(nonce, 16) != 1) { - printf("Error generating nonce\n"); - free(plaintext); - return 1; - } - - // Encrypt the plaintext using chacha20 - unsigned char ciphertext[fsize]; - EVP_CIPHER_CTX *ctx; + EVP_CIPHER_CTX *ctx = NULL; if (!(ctx = EVP_CIPHER_CTX_new())) { printf("Error creating context\n"); - free(plaintext); + fclose(finput); + fclose(foutput); return 1; } - if (EVP_EncryptInit_ex(ctx, EVP_chacha20(), NULL, key_bytes, nonce) != 1) { - printf("Error initializing encryption\n"); - free(plaintext); - EVP_CIPHER_CTX_free(ctx); - return 1; - } - - int len; - if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, fsize) != 1) { - printf("Error encrypting\n"); - EVP_CIPHER_CTX_free(ctx); - free(plaintext); + // If enc is 1, then we are encrypting, else we are decrypting + // If we are encrypting, we need to generate an IV + // If we are decrypting, we need to read the IV from the file + unsigned char iv[16]; + if (enc) { + if (RAND_bytes(iv, 16) != 1) { + printf("Error generating IV\n"); return 1; } + if (fwrite(iv, 1, 16, foutput) != 16) { + printf("Error writing IV to file\n"); + return 1; + } + } else { + if (fread(iv, 1, 16, finput) != 16) { + printf("Error reading IV from file\n"); + return 1; + } + } - if (EVP_EncryptFinal_ex(ctx, ciphertext + len, &len) != 1) { - printf("Error finalizing encryption\n"); + if (EVP_CipherInit_ex(ctx, EVP_chacha20(), NULL, key_bytes, iv, enc) != 1) { + fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", + ERR_error_string(ERR_get_error(), NULL)); EVP_CIPHER_CTX_free(ctx); - free(plaintext); return 1; } - // Add the nonce to the beginning of the file - char *nonce_and_ciphertext = malloc(16 + (fsize * sizeof(unsigned char))); - memcpy(nonce_and_ciphertext, nonce, 16); - memcpy(nonce_and_ciphertext + 16, ciphertext, fsize); + int read_size, len; + while ((read_size = fread(input_buf, 1, BUF_SIZE, finput)) > 0) { + printf("Read %d bytes, passing through CipherUpdate...\n", read_size); + if (EVP_CipherUpdate(ctx, output_buf, &len, input_buf, read_size) != 1) { + fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + fclose(finput); + fclose(foutput); + return 1; + } + printf("\tGot back %d bytes from CipherUpdate...\n", len); + printf("Writing %d bytes to %s...\n", len, output_file); + if (fwrite(output_buf, 1, len, foutput) != len) { + printf("Error writing to output file\n"); + return 1; + } + printf("\tWrote %d bytes\n", len); + u_len += len; + } + if (read_size == -1) { + fprintf(stderr, "ERROR: Reading from the file %s failed.\n", input_file); + } - // Create output file + if (EVP_CipherFinal_ex(ctx, output_buf, &f_len) != 1) { + fprintf(stderr, "ERROR: EVP_CipherFinal_ex failed. OpenSSL error: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + fclose(finput); + fclose(foutput); + return 1; + } + printf("u_len: %d, f_len: %d\n", u_len, f_len); + + if (f_len) { + printf("Writing final %d bytes to %s...\n", f_len, output_file); + if (fwrite(output_buf, 1, f_len, foutput) != f_len) { + printf("Error writing to output file\n"); + fclose(finput); + fclose(foutput); + return 1; + } + } + printf("\tWrote last %d bytes\n", f_len); + fclose(finput); + fclose(foutput); + + return 0; +} + +int encrypt(char *input_file, char *key_file) { char *output_file = malloc(strlen(input_file) + 5); strcpy(output_file, input_file); strcat(output_file, ".enc"); - FILE *foutput = fopen(output_file, "wb"); - if (foutput == NULL) { - printf("Error opening output file\n"); - EVP_CIPHER_CTX_free(ctx); - return 1; - } - if (fwrite(nonce_and_ciphertext, 1, 16 + fsize, foutput) != (16 + fsize)) { - printf("Error writing to output file\n"); - fclose(foutput); - free(plaintext); - free(nonce_and_ciphertext); - free(output_file); - EVP_CIPHER_CTX_free(ctx); - return 1; - } - - fclose(foutput); - free(plaintext); - free(nonce_and_ciphertext); - free(output_file); - EVP_CIPHER_CTX_free(ctx); + chacha20(input_file, output_file, key_file, 1); return 0; } int decrypt(char *input_file, char *key_file) { - FILE *fkey = fopen(key_file, "rb"); - - if (fkey == NULL) { - printf("Error opening key file\n"); - return 1; - } - - unsigned char key_bytes[32]; - if (fread(key_bytes, 1, 32, fkey) != 32) { - printf("Error reading key from file\n"); - fclose(fkey); - return 1; - } - fclose(fkey); - - FILE *finput = fopen(input_file, "rb"); - if (finput == NULL) { - printf("Error opening input file\n"); - return 1; - } - // Determining file size - fseek(finput, 0, SEEK_END); - unsigned long fsize = ftell(finput); - rewind(finput); - - unsigned char *nonce_and_ciphertext = malloc(fsize * sizeof(unsigned char)); - if (nonce_and_ciphertext == NULL) { - printf("Error allocating memory\n"); - fclose(finput); - return 1; - } - - if (fread(nonce_and_ciphertext, 1, fsize, finput) != fsize) { - printf("Error reading file\n"); - fclose(finput); - free(nonce_and_ciphertext); - return 1; - } - fclose(finput); - - unsigned char nonce[16]; - memcpy(nonce, nonce_and_ciphertext, 16); - unsigned char *ciphertext = malloc((fsize * sizeof(unsigned char)) - 16); - memcpy(ciphertext, nonce_and_ciphertext + 16, fsize - 16); - - // Decrypt the ciphertext using chacha20 - unsigned char plaintext[fsize - 16]; - EVP_CIPHER_CTX *ctx; - if (!(ctx = EVP_CIPHER_CTX_new())) { - printf("Error creating context\n"); - free(nonce_and_ciphertext); - free(ciphertext); - return 1; - } - - if (EVP_DecryptInit_ex(ctx, EVP_chacha20(), NULL, key_bytes, nonce) != 1) { - printf("Error initializing decryption\n"); - free(nonce_and_ciphertext); - free(ciphertext); - return 1; - } - - int len; - if (EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, fsize - 16) != 1) { - printf("Error decrypting\n"); - free(nonce_and_ciphertext); - free(ciphertext); - return 1; - } - - if (EVP_DecryptFinal_ex(ctx, plaintext + len, &len) != 1) { - printf("Error finalizing decryption\n"); - free(nonce_and_ciphertext); - free(ciphertext); - return 1; - } - free(ciphertext); - - // Create output file char *output_file = malloc(strlen(input_file) + 5); strcpy(output_file, input_file); strcat(output_file, ".dec"); - FILE *foutput = fopen(output_file, "wb"); - if (foutput == NULL) { - printf("Error opening output file\n"); - return 1; - } - - if (fwrite(plaintext, 1, fsize - 16, foutput) != (fsize - 16)) { - printf("Error writing to output file\n"); - fclose(foutput); - free(nonce_and_ciphertext); - free(output_file); - return 1; - } - - fclose(foutput); - free(nonce_and_ciphertext); - free(output_file); + chacha20(input_file, output_file, key_file, 0); return 0; }