From 053e94abbc89ee234f537dc0d4f7d4f6527ae796 Mon Sep 17 00:00:00 2001 From: tsousa111 Date: Tue, 27 Feb 2024 12:01:18 +0000 Subject: [PATCH] clang format and init tp03 --- .clang-format | 9 ++ TPs/TP03/pbenc_aes_ctr_hmac.c | 284 ++++++++++++++++++++++++++++++++++ 2 files changed, 293 insertions(+) create mode 100644 .clang-format create mode 100644 TPs/TP03/pbenc_aes_ctr_hmac.c diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..45b9ef8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,9 @@ +BasedOnStyle: LLVM +UseTab: Always +IndentWidth: 4 +TabWidth: 4 +BreakBeforeBraces: Attach +ColumnLimit: 100 +PenaltyReturnTypeOnItsOwnLine: 1000000 +AlwaysBreakAfterDefinitionReturnType: None +SeparateDefinitionBlocks: Always diff --git a/TPs/TP03/pbenc_aes_ctr_hmac.c b/TPs/TP03/pbenc_aes_ctr_hmac.c new file mode 100644 index 0000000..dc03ee6 --- /dev/null +++ b/TPs/TP03/pbenc_aes_ctr_hmac.c @@ -0,0 +1,284 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KEY_SIZE 32 +#define SALT_SIZE 16 +#define ITERATIONS 80000 + +int aes_ctr(const char *input_file, const char *output_file, const unsigned char *key, int enc) { + + int BUF_SIZE = 1024; + int cipher_block_size = EVP_CIPHER_block_size(EVP_aes_256_ctr()); + + int input_size = BUF_SIZE; + int output_size = input_size + (cipher_block_size - 1); + int u_len = 0, f_len = 0; + + unsigned char input_buf[input_size], output_buf[output_size]; + + FILE *finput = fopen(input_file, "rb"); + if (finput == NULL) { + fprintf(stderr, "Error opening input file\n"); + return 1; + } + + // Open output file + FILE *foutput = fopen(output_file, "ab"); + if (foutput == NULL) { + fprintf(stderr, "Error opening output file\n"); + fclose(finput); + return 1; + } + + EVP_CIPHER_CTX *ctx = NULL; + if (!(ctx = EVP_CIPHER_CTX_new())) { + fprintf(stderr, "Error creating context\n"); + fclose(finput); + fclose(foutput); + return 1; + } + + // EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL); + // if (!mac) { + // fprintf(stderr, "Error creating HMAC\n"); + // fclose(finput); + // fclose(foutput); + // return 1; + // } + // + // EVP_MAC_CTX *hctx = NULL; + // if (!(hctx = EVP_MAC_CTX_new(mac))) { + // fprintf(stderr, "Error creating HMAC context\n"); + // fclose(finput); + // fclose(foutput); + // return 1; + // } + // const OSSL_PARAM params[] = {OSSL_PARAM_UTF8_STRING(OSSL_MAC, "SHA256", 0), OSSL_PARAM_END}; + + // Set the digest type to SHA256 + // if (EVP_MAC_CTX_set_params(hctx, EVP_sha256()) != 1) { + // fprintf(stderr, "Error setting HMAC digest type\n"); + // fclose(finput); + // fclose(foutput); + // return 1; + // } + + // 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) { + fprintf(stderr, "Error generating IV\n"); + return 1; + } + if (fwrite(iv, 1, 16, foutput) != 16) { + fprintf(stderr, "Error writing IV to file\n"); + return 1; + } + } else { + // Seek forward by 16 bytes to ignore the salt + if (fseek(finput, 16, SEEK_SET) != 0) { + fprintf(stderr, "Error seeking to IV position in input file\n"); + return 1; + } + if (fread(iv, 1, 16, finput) != 16) { + fprintf(stderr, "Error reading IV from file\n"); + return 1; + } + } + + if (EVP_CipherInit_ex(ctx, EVP_aes_256_ctr(), NULL, key, 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); + return 1; + } + + if (EVP_MAC_init(hctx, key, 32, NULL) != 1) { + fprintf(stderr, "ERROR: EVP_MAC_init failed. OpenSSL error: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + fclose(finput); + fclose(foutput); + return 1; + } + + int read_size, len; + unsigned char *hmac = (unsigned char *)malloc(32); + 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) { + fprintf(stderr, "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); + } + + 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) { + fprintf(stderr, "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, const char *passphrase) { + unsigned char key[KEY_SIZE]; + unsigned char salt[SALT_SIZE]; + // Derive key from passphrase using PBKDF2 + char *output_file = malloc(strlen(input_file) + 5); + strcpy(output_file, input_file); + strcat(output_file, ".enc"); + + if (RAND_bytes(salt, SALT_SIZE) != 1) { + fprintf(stderr, "Error generating salt\n"); + return 1; + } + // Write salt to output file + FILE *foutput = fopen(output_file, "wb"); + if (foutput == NULL) { + fprintf(stderr, "Error opening output file\n"); + return 1; + } + if (fwrite(salt, 1, 16, foutput) != 16) { + fprintf(stderr, "Error writing salt to file\n"); + fclose(foutput); + return 1; + } + fclose(foutput); + + // Derive key from passphrase using PBKDF2 + if (PKCS5_PBKDF2_HMAC(passphrase, strlen(passphrase), salt, SALT_SIZE, ITERATIONS, EVP_sha256(), + KEY_SIZE * 2, key) != 1) { + fprintf(stderr, "Error deriving key from passphrase\n"); + return 1; + } + + aes_ctr(input_file, output_file, key, 1); + return 0; +} + +int decrypt(char *input_file, const char *passphrase) { + unsigned char key[KEY_SIZE]; + unsigned char salt[SALT_SIZE]; + // Derive key from passphrase using PBKDF2 + char *output_file = malloc(strlen(input_file) + 5); + strcpy(output_file, input_file); + strcat(output_file, ".dec"); + // Read salt from input file + FILE *finput = fopen(input_file, "rb"); + if (finput == NULL) { + fprintf(stderr, "Error opening input file\n"); + return 1; + } + if (fread(salt, 1, 16, finput) != 16) { + fprintf(stderr, "Error reading salt from file\n"); + fclose(finput); + return 1; + } + fclose(finput); + + // Derive key from passphrase using PBKDF2 + if (PKCS5_PBKDF2_HMAC(passphrase, strlen(passphrase), salt, SALT_SIZE, ITERATIONS, EVP_sha256(), + KEY_SIZE, key) != 1) { + fprintf(stderr, "Error deriving key from passphrase\n"); + return 1; + } + + aes_ctr(input_file, output_file, key, 0); + return 0; +} + +void disableEcho() { + struct termios oldTermios, newTermios; + tcgetattr(0, &oldTermios); + newTermios = oldTermios; + newTermios.c_lflag &= ~(ECHO); + tcsetattr(0, TCSANOW, &newTermios); +} + +void enableEcho() { + struct termios oldTermios; + tcgetattr(0, &oldTermios); + oldTermios.c_lflag |= ECHO; + tcsetattr(0, TCSANOW, &oldTermios); +} + +int main(int argc, char *argv[]) { + if (argc < 3) { + fprintf(stderr, "Usage: %s {enc|dec} [file_path]\n", argv[0]); + return 1; + } + + char *mode = argv[1]; + char *input_file = argv[2]; + + if (!(strcmp(mode, "enc") == 0 || strcmp(mode, "dec") == 0)) { + fprintf(stderr, "Invalid mode. Use 'enc' or 'dec'.\n"); + } + + if (argc != 3) { + fprintf(stderr, "Usage: %s {enc|dec} [file_path]\n", argv[0]); + return 1; + } + input_file = argv[2]; + + char passphrase[256]; // Assuming maximum passphrase length of 255 characters + printf("Enter passphrase: "); + disableEcho(); + if (fgets(passphrase, sizeof(passphrase), stdin) == NULL) { + fprintf(stderr, "Error reading passphrase from stdin\n"); + return 1; + } + enableEcho(); + passphrase[strcspn(passphrase, "\n")] = '\0'; // Remove trailing newline + int suc = 0; + if (strcmp(mode, "enc") == 0) { + suc = encrypt(input_file, passphrase); + } else { + suc = decrypt(input_file, passphrase); + } + if (suc == 0) { + printf("Operation completed successfully\n"); + } else { + printf("Operation failed\n"); + } + return 0; +}