-2

I'm trying to decrypt a message encrypted with AES 192 ECB and getting a segmentation fault and don't know where to look anymore. I know ECB is unsafe, but it is not for a production application.

  • I already checked my readFile method, it works (I wrote the ciphre back into a file and checked with the diff tool)
  • The key is 24 Bytes long (checked with ls and hexdump)
  • ECB has no IV-Vector as far as I know, so I have set it to NULL
  • for the decryption part I used the example at https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption to get started
  • I think the problem is at EVP_DecryptUpdate
  • I tried to track it down further with gdb but I have no experience with this and only got

0x00007ffff798089d in ?? () from /usr/lib64/libcrypto.so.1.1

Thank you for your time.

#include <stdio.h>
#include <stdlib.h>

#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/conf.h>
#include <openssl/sha.h>

int readFile(char* filename, unsigned char** data){
        FILE *fp;
        unsigned char* tmp;
        long fsize = 0;

        if ((fp = fopen(filename, "rb")) == NULL){
                perror(filename);
                exit(EXIT_FAILURE);
        }

        // get length by going to end of the file and checking the position.
        // Rewinding to start afterwards
        fseek(fp, 0, SEEK_END);
        fsize = ftell(fp);
        rewind(fp);

        if((tmp = malloc(fsize))){
                fread(tmp, fsize, 1, fp);
                fclose(fp);
        } else {
                fclose(fp);
                perror(filename);
                exit(EXIT_FAILURE);
        }
        *data = tmp;
        return fsize;
}

int decryptAES192ECB(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *plaintext){
    EVP_CIPHER_CTX *ctx;
    int len;
    int plaintext_len;

    /* Create and initialise the context */
    if(!(ctx = EVP_CIPHER_CTX_new()))
        handleErrors();

    /*
     * Initialise the decryption operation. IMPORTANT - ensure you use a key
     * and IV size appropriate for your cipher
     */
    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_192_ecb(), NULL, key, NULL))
        handleErrors();

    /*
     * Provide the message to be decrypted, and obtain the plaintext output.
     * EVP_DecryptUpdate can be called multiple times if necessary.
     */
    if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
        handleErrors();
    plaintext_len = len;

    /*
     * Finalise the decryption. Further plaintext bytes may be written at
     * this stage.
     */
    if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
        handleErrors();
    plaintext_len += len;

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);

    return plaintext_len;
}

int main(int argc, char **argv){
        unsigned char *source_cipher, *source_key;
        long source_cipher_len = readFile("source-cipher.bin", &source_cipher);
        long source_key_len = readFile("source-key.bin", &source_key);

        unsigned char* plaintext;
        decryptAES192ECB(source_cipher, source_cipher_len, source_key, plaintext);

        return 0;
}

Edit: Solution is to add

unsigned char* plaintext = malloc(source_cipher_len);

to main method before decryptAES192ECB call and to remove

handleErrors();

after EVP_DecryptFinal_ex call in decryptAES192ECB.

Akreter
  • 25
  • 4
  • So you caught your copy/paste `plaintext` / `ciphertext` mess up in `EVP_DecryptUpdate()`, good. – David C. Rankin Jun 06 '21 at 00:28
  • `plaintext` is _unitialized_ in `main`. I tried: `unsigned char *plaintext = "abcdef";` but `unsigned char *plaintext = malloc(1000000);` gets you past the segfault. But, it generates an error return for `EVP_DecryptFinal_ex`, which is progress [sort of ;-)]. Note that I'm just putting ascii text in both the `.bin` files, so it might help to know what should actually go into these two input files. – Craig Estey Jun 06 '21 at 00:30
  • yes, stupid mistake I made when I searched for the error. – Akreter Jun 06 '21 at 00:32
  • @Craig Estey thanks! I thought openssl would initialize it, but I guess then I would have to give it an unsigned char**? Now I get the same error as you. I will look for an alternative with the files, as the decrypting is part of a bigger task for university. I don't know the content and don't want to leak anything. – Akreter Jun 06 '21 at 00:53
  • You have `"IMPORTANT - ensure you use a key and IV size appropriate for your cipher"`, but then you give the `iv` parameter as `NULL` to `EVP_DecryptInit_ex()`. I think that is where things start to fall apart. All AES will use a block size of 128-bit as given in the example you link to, e.g. `unsigned char *iv = (unsigned char *)"0123456789012345";` – David C. Rankin Jun 06 '21 at 01:15
  • @CraigEstey your answer fixed it. The error on EVP_DecryptFinal_ex comes because of a wrong key (see here https://stackoverflow.com/a/50349279/10814631). Feel free to post your comment as an answer! – Akreter Jun 06 '21 at 01:28
  • @DavidC.Rankin thats true for cbc mode in the example. But I'm using ecb mode. This mode is unsafe because there is no IV and same plain text blocks are encrypted to the same cipher blocks. I got it fixed now thanks to Craig, but thanks for your time! – Akreter Jun 06 '21 at 01:32

1 Answers1

0

This is prefaced by the top comments.

your answer fixed it. The error on EVP_DecryptFinal_ex comes because of a wrong key Feel free to post your comment as an answer! – Akreter

plaintext is uninitialized in main.

I tried:

unsigned char *plaintext = "abcdef";

This didn't work too well and I suspect that plaintext is an output buffer, so:

unsigned char *plaintext = malloc(1000000);

gets you past the segfault.

But, it generates an error return for EVP_DecryptFinal_ex, which is progress [sort of ;-)].

Note that I'm just putting [dummy] ascii text in both the .bin files, so it might help to know what should actually go into these two input files. With the correct/real data, I think things will work [as you mentioned above].

Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • Just adding my findings to help anyone with the same problem: the plaintext has the same length as the ciphered text, so you can just do ```malloc(ciphertext_len)```. The ```digital envelope routines: EVP_DecryptFInal_ex: bad decrypt``` error could mean that key and cipher don't match which is the case for my task as I have to find the right key – Akreter Jun 06 '21 at 11:28