-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Openssl 1.1 #507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Openssl 1.1 #507
Conversation
The above OpenSSL header declares a function 'HMAC' which when included causes various compilation issues due to redefined types. Be explicit about our HMAC namespace, we avoid those and will be able to include above header. Signed-off-by: André Draszik <git@andred.net>
OpenSSL v1.1 made various types opaque - change the existing code to prepare for that to make it clearer what the actual OpenSSL v1.1 changes entail. This is the first step, dealing with EVP_CIPHER_CTX Signed-off-by: André Draszik <git@andred.net>
OpenSSL v1.1 made various types opaque - change the existing code to prepare for that to make it clearer what the actual OpenSSL v1.1 changes entail. This is the second step, dealing with HMAC_CTX Signed-off-by: André Draszik <git@andred.net>
OpenSSL v1.1: * made various types opaque and as such added various new allocators / destructors for those types * completely removed the old locking functions as they are now unneeded Change the code to employ the relevant changes in case we're compiling against OpenSSL >= v1.1.0 rc3 Signed-off-by: André Draszik <git@andred.net>
While LibreSSL strives to be API compatible with OpenSSL, it does so against the version when it was forked, 1.0.1g LibreSSL defines its own LIBRESSL_VERSION_NUMBER but at the same time it defines OPENSSL_VERSION_NUMBER to an insane value, which causes issues now. By detecting this case and setting a more reasonable version number, we can compile against LibreSSL again. Signed-off-by: André Draszik <git@andred.net>
#include <atomic> | ||
#include <mutex> | ||
|
||
#if defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x20000000L) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though in the Libressl code they said they never change the OPENSSL_VERSION_NUMBER from 0x20000000L, what would happen if they updated openssl version used, for say, from 1.0 to 1.1. It's could be more complicated situation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it makes sense to speculate what LibreSSL might or might not do in the future. If they change the API, code using LibreSSL will have to follow. This is no different behaviour than before this PR - with the current code-base, if LibreSSL decided to change the API tomorrow, things would break.
The approach suggested here is what I've seen several other open-source projects taking.
It avoids additional clutter, as it redefines the version number to correctly reflect the API that LibreSSL actually implements.
The alternative would be to implement proper configuration checks using CMake, to detect features / APIs, rather than clutter the code with ifdefs. I don't really care about LibreSSL, so if you want I can drop this commit. It looked like a low-hanging fruit.
|
||
#if defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x20000000L) | ||
#undef OPENSSL_VERSION_NUMBER | ||
#define OPENSSL_VERSION_NUMBER 0x1000107fL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this version number comes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per the commit message:
...
While LibreSSL strives to be API compatible with OpenSSL,
it does so against the version when it was forked, 1.0.1g
...
|
||
EVP_CIPHER_CTX m_ctx; | ||
EVP_CIPHER_CTX *m_ctx; | ||
#if OPENSSL_VERSION_NUMBER < 0x10100003L |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not good to appear in multiple locations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Do you have a better suggestion? What about two subclasses, where each of them implements specifics for each OpenSSL version. I am not using C++ much day-to-day, so there might be better options?
toMove.m_ctx.engine = nullptr; | ||
Init(); | ||
EVP_CIPHER_CTX_copy (m_ctx, toMove.m_ctx); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In original impl, there are several fields set up to nullptr, and I checked the code of EVP_CIPHER_CTX_copy, it doesn't cleanup in arg, I guess we should call EVP_CIPHER_CTX_cleanup(toMove.m_ctx) here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well spotted. EVP_CIPHER_CTX_cleanup() has been removed in OpenSSL 1.1 and instead EVP_CIPHER_CTX_reset() is to be used, so this adds another ifdef,
I'll do that.
Why don't we just switch to pointer impl if OPENSSL made the type opaque? |
m_ctx.engine = nullptr; | ||
#if OPENSSL_VERSION_NUMBER < 0x10100003L | ||
EVP_CIPHER_CTX_cleanup(m_ctx); | ||
m_ctx = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After openssl 1.1 m_ctx will be acquired from heap, so here we should free it right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is OK. The code paths are slightly different (I think it's a bit ugly and hard to follow, actually). The idea was to be able to reuse the same EVP_CIPHER_CTX throughout the lifetime of a class OpenSSLCipher rather then freeing and re-allocating to achieve a more static memory allocation modelling, comparable to the OpenSSL 1.0 implementation.
Cleanup() is called from the destructor and from ::Reset(). For OpenSSL 1.1:
- Cleanup() itself doesn't do anything to the EVP_CIPHER_CTX
- the destructor does Cleanup(), followed by EVP_CIPHER_CTX_free()
- ::Reset() does Cleanup(), followed by Init(), which itself does EVP_CIPHER_CTX_reset()
hence we achieve re-use of the handle, rather than free() + malloc()
For OpenSSL 1.0:
- Cleanup() itself invalidates the static handle as per your comment
- the destructor does Cleanup()
- ::Reset() does Cleanup(), followed by Init(), which itself reinitialises the static handle
I have pulled this PR to our local branch, after reviewing and making proper changes, we will push out to this repo, probably in early next week. |
OpenSSL 1.0 doesn't have APIs for allocation: #362 (comment) |
We have merged this pull request and done several changes. Check out the latest code in master branch. |
I can't push to #362, so this is an updated version.
Compared to #362, this fixes a few issues detected so far: