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
Preliminary notes:
According to [OpenSSL]: Downloads (emphasis is mine):
All older versions (including 1.1.1, 1.1.0, 1.0.2, 1.0.0 and 0.9.8) are now out of support and should not be used.
making this an exercise in futility
In v1.1.*, OpenSSL team did some refactors like is hiding some implementation details (something similar to PIMPL, if you will), changing the API and others. One effect is that hmac.h no longer defines HMAC_CTX (struct hmac_ctx_st
alias). It is now forward declared in ossl_typ.h, meaning that it can't be used plainly, only as a pointer (or (C++) reference)
Just out of curiosity, I built OpenSSL-1.1.1w (with enable-deprecated). Not sure if I screwed something up (it built fine), but the include folder contents is identical with the one of a regular build, so defining OPENSSL_USE_DEPRECATED wouldn't have any (different) effect
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