copenssl

OpenSSL 1.1.1 | enable-deprecated not working as intented


My existing code is complined with OpenSSL 1.0.2, and I am migration this to OpenSSL 1.1.1. During this I came accross OpenSSL Guide at https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes

As a PoC I wanted to allow the deprecated function, the way this is mentioned in the office guide.

Access to deprecated functions/macros has been removed by default. To enable access you must do two things. 1) Build OpenSSL with deprecation support (pass "enable-deprecated" as an argument to config) 2) Applications must define "OPENSSL_USE_DEPRECATED" before including OpenSSL header files

I have built OpenSSL 1.1.1 with the required parameter like this

./config enable-deprecated && make clean && make

After which I added #define OPENSSL_USE_DEPRECATED to my C code as well.

Sample Code (which works fine when compiled with OpenSSL 1.0.2)

gcc -std=c99 -o hmac_sha1_example hello.c -I/somepath/openssl-1.0.2k/openssl-1.0.2k/include -L/somepath/openssl-1.0.2k/ -lssl -lcrypto -ldl

But when compiled with OpenSSL 1.1.1 the compilation still fails with error: storage size of ‘ctx’ isn’t known HMAC_CTX ctx; (I did add -DOPENSSL_USE_DEPRECATED to the params during compile as well)

#include <stdio.h>
#include <string.h>
#define OPENSSL_USE_DEPRECATED
#include <openssl/hmac.h>

int main() {
    // Define the key and the message
    const char *key = "secret";
    const char *message = "Hello World!";
    
    // Buffer to hold the resulting HMAC
    unsigned char result[EVP_MAX_MD_SIZE];
    unsigned int result_len;

    // Initialize the HMAC context
    HMAC_CTX ctx;
    HMAC_CTX_init(&ctx);

    // Set up the HMAC context with the key and the SHA1 algorithm
    HMAC_Init_ex(&ctx, key, strlen(key), EVP_sha1(), NULL);
    HMAC_Update(&ctx, (unsigned char*)message, strlen(message));
    HMAC_Final(&ctx, result, &result_len);

    // Clean up the HMAC context
    HMAC_CTX_cleanup(&ctx);

    // Print the resulting HMAC
    printf("HMAC-SHA1: ");
    for (unsigned int i = 0; i < result_len; i++) {
        printf("%02x", result[i]);
    }
    printf("\n");

    return 0;
}

Any idea whether I am adding the enable-deprecated support incorrectly? I was trying to avoid the changes of "HMAC_CTX_new" and use enable-deprecated since it will give me a quick test for the openssl 1.1.1 instead of making changes everywhere


Solution

  • Preliminary notes:

    My advice is to switch to the new API, (as also pointed out in [SO]: error: aggregate ‘HMAC_CTX ctx’ has incomplete type and cannot be defined (@catnip's answer)), even if it's scary (as there could be many places to be changed), because eventually it will have to be done anyway (been there, done that).
    Also, if this change is required indeed in lots of places, you might go a step further and extract the common functionality in a function replacing it everywhere. There won't be an immediate benefit, but at a (potential) next time this will happen again, you won't have to sweep to all the locations.

    I took the liberty of changing the code to work with newer APIs.
    Note that starting with v3.0, those are deprecated!

    main00.c:

    #include <stdio.h>
    #include <string.h>
    
    #include <openssl/hmac.h>
    
    
    typedef const EVP_MD* (*HashFuncPtr)();
    
    
    int computeHash(const char *message, const char *key, const HashFuncPtr hash, unsigned char *result, unsigned int *size)
    {
        // Initialize the HMAC context
        HMAC_CTX *ctx = HMAC_CTX_new();
    
        // Set up the HMAC context with the key and the SHA1 algorithm
        HMAC_Init_ex(ctx, key, strlen(key), hash(), NULL);
        HMAC_Update(ctx, (unsigned char*)message, strlen(message));
        HMAC_Final(ctx, result, size);
        // Clean up the HMAC context
        HMAC_CTX_free(ctx);
        return 0;
    }
    
    
    int main()
    {
        // Define the key and the message
        const char *message = "Hello World!";
        const char *key = "secret";
        // Buffer to hold the resulting HMAC
        unsigned char result[EVP_MAX_MD_SIZE];
        unsigned int len;
        printf("%s\n", OPENSSL_VERSION_TEXT);
        computeHash(message, key, EVP_sha1, result, &len);
        // Print the resulting HMAC
        printf("HMAC-SHA1: ");
        for (unsigned int i = 0; i < len; ++i) {
            printf("%02x", result[i]);
        }
    
        printf("\nDone.\n\n");
        return 0;
    }
    

    Output:

    (qaic-env) [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackExchange/StackOverflow/q079157711]> ~/sopr.sh
    ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
    
    [064bit prompt]> ls
    main00.c  orig.c
    [064bit prompt]> # List available OpenSSL versions
    [064bit prompt]> ls /usr/local/pc064/openssl/openssl
    1.0.2u  1.1.1v  1.1.1w-depr  3.0.11  3.0.13  3.0.15  3.0.9  3.1.2  3.1.4  3.1.6  3.2.1  3.2.3  3.3.1  3.4.0
    1.1.1u  1.1.1w  3.0.10       3.0.12  3.0.14  3.0.8   3.1.1  3.1.3  3.1.5  3.1.7  3.2.2  3.3.0  3.3.2
    [064bit prompt]>
    [064bit prompt]> # Build code using 3 of them: note -Wno-deprecated-declarations (needed for v3.*)
    [064bit prompt]> for osslver in "1.1.1w" "3.0.15" "3.4.0"; do \
    > gcc -Wno-deprecated-declarations -I/usr/local/pc064/openssl/openssl/${osslver}/include -L/usr/local/pc064/openssl/openssl/${osslver}/lib -o main00_${osslver//./} main00.c -lcrypto; \
    > done
    [064bit prompt]>
    [064bit prompt]> ls
    main00.c  main00_111w  main00_3015  main00_340  orig.c
    [064bit prompt]>
    [064bit prompt]> # Run the 3 built executables
    [064bit prompt]> for osslver in "1.1.1w" "3.0.15" "3.4.0"; do \
    > LD_LIBRARY_PATH=/usr/local/pc064/openssl/openssl/${osslver}/lib:${LD_LIBRARY_PATH} ./main00_${osslver//./}; \
    > done
    OpenSSL 1.1.1w  11 Sep 2023
    HMAC-SHA1: 5efed98b0787c83f9cb0135ba283c390ca49320e
    Done.
    
    OpenSSL 3.0.15 3 Sep 2024
    HMAC-SHA1: 5efed98b0787c83f9cb0135ba283c390ca49320e
    Done.
    
    OpenSSL 3.4.0 22 Oct 2024
    HMAC-SHA1: 5efed98b0787c83f9cb0135ba283c390ca49320e
    Done.
    

    Note: There are OpenSSL builds available at [GitHub]: CristiFati/Prebuilt-Binaries - (master) Prebuilt-Binaries/OpenSSL for anyone who needs them