Bug 1497859

Summary: Document forwards incompatibility of SSL_OP_NO_TLSv1_1 flag between openssl-1.0.0 and openssl-1.0.1. Document runtime behavior of SSLeay() function.
Product: Red Hat Enterprise Linux 6 Reporter: Sailesh Mukil <mukil.sailesh>
Component: Red_Hat_Enterprise_Linux-Release_Notes-6-en-USAssignee: Lenka Špačková <lkuprova>
Status: CLOSED CURRENTRELEASE QA Contact:
Severity: high Docs Contact: Mirek Jahoda <mjahoda>
Priority: unspecified    
Version: 6.7CC: mjahoda, rhel-docs, tmraz
Target Milestone: rcKeywords: Documentation, Reopened
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Known Issue
Doc Text:
A runtime version of *OpenSSL* is masked and `SSL_OP_NO_TLSv1_1` must not be used with *OpenSSL* 1.0.0 Because certain applications perform incorrect version check of the *OpenSSL* version, the actual runtime version of *OpenSSL* is masked and the build-time version is reported instead. Consequently, it is impossible to detect the currently running *OpenSSL* version using the `SSLeay()` function. Additionally, passing the value equivalent to the `SSL_OP_NO_TLSv1_1` option as present on *OpenSSL* 1.0.1 to the `SSL_CTX_set_options()` function when running with *OpenSSL* 1.0.0 breaks the SSL/TLS support completely. To work around this problem, use another way to detect the currently running *OpenSSL* version. For example, it is possible to obtain a list of enabled ciphers with the `SSL_get_ciphers()` function and search a *TLS* 1.2 cipher by parsing the list using the `SSL_CIPHER_description()` function. This indicates an application that runs with the *OpenSSL* version later than 1.0.0 because *TLS* 1.2 support is present since version 1.0.1.
Story Points: ---
Clone Of: Environment:
Last Closed: 2017-11-29 13:35:16 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Sailesh Mukil 2017-10-02 21:52:46 UTC
Description of problem:

(This is somewhat related to https://bugzilla.redhat.com/show_bug.cgi?id=1301301, but a little different)

I work on a project where we use OpenSSL by dynamically linking against it. We recently noticed an issue, where the SSLeay() function does not return the version of the OpenSSL library it's linked against, but rather returns the version that it was compiled against.

We used a small test program to verify this as well:
`#include <openssl/ssl.h>

int main()
{
unsigned long ssl_version;
ssl_version = SSLeay();

    printf("Compiled with: %lx (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT);
    printf("Running with:  %lx (%s)\n", ssl_version, SSLeay_version(SSLEAY_VERSION));

    return 0;
}`

We built this on a RHEL6.4 machine which contains "OpenSSL 1.0.0-fips 29 Mar 2010".

And we ran it on a RHEL6.7 machine which contains "OpenSSL 1.0.1e-fips 11 Feb 2013". We get:

Compiled with: 10000003 (OpenSSL 1.0.0-fips 29 Mar 2010)
Running with: 10000003 (OpenSSL 1.0.0-fips 29 Mar 2010)
When we compile and run it on the same RHEL6.7 machine, we get:

Compiled with: 1000105f (OpenSSL 1.0.1e-fips 11 Feb 2013)
Running with: 1000105f (OpenSSL 1.0.1e-fips 11 Feb 2013)
When we compile it on RHEL6.7 and run it on RHEL6.4, we get:

Compiled with: 1000105f (OpenSSL 1.0.1e-fips 11 Feb 2013)
Running with: 10000003 (OpenSSL 1.0.0-fips 29 Mar 2010)
So it looks like compiling against a newer version and running against an older version is fine, but not the other way round.

Under GDB I noticed that there are 2 definitions of SSLeay() in the same dynamically linked libcrypto.so:

(gdb) disas 0x000000384906bfd0
Dump of assembler code for function SSLeay:
0x000000384906bfd0 <+0>:	mov $0x1000105f,%eax
0x000000384906bfd5 <+5>:	retq

(gdb) disas
Dump of assembler code for function SSLeay:
=> 0x000000384906bfc0 <+0>:	mov $0x10000003,%eax
0x000000384906bfc5 <+5>:	retq

Which is confusing to me, why would it have a hardcoded version of a specific older OpenSSL version in the SO? Unless I'm grossly misunderstanding something.

So, my question is, is this a bug in OpenSSL? Or are we not supposed to be building against an older OpenSSL and running against a newer version?


Version-Release number of selected component (if applicable):
OpenSSL 1.0.1e

How reproducible:
Always

Steps to Reproduce:
1. Compile binary against OpenSSL 1.0.0
2. Run same binary on system with OpenSSL 1.0.1

Actual results:
Compiled with: 10000003 (OpenSSL 1.0.0-fips 29 Mar 2010)
Running with: 10000003 (OpenSSL 1.0.0-fips 29 Mar 2010)

Expected results:
Compiled with: 10000003 (OpenSSL 1.0.0-fips 29 Mar 2010)
Running with: 1000105f (OpenSSL 1.0.1e-fips 11 Feb 2013)

Additional info:

Comment 2 Tomas Mraz 2017-10-03 06:36:03 UTC
This is done on purpose. Some applications perform incorrect (too sensitive) version check and the only way to avoid it is to mask the actual run-time version of OpenSSL built against an old OpenSSL release.

You need to build against the oldest OpenSSL version with which you need your software to run. So if your intention is to be able to run the software with RHEL-6.4 then you must also build it on this RHEL release. You should be able to run it with any newer RHEL-6 version as well. But of course you cannot use new features of the newer OpenSSL version except these that do not require any new API call.

Comment 3 Sailesh Mukil 2017-10-03 18:15:32 UTC
Thanks for your response Tomas. I just have a follow up question.

Isn't that breaking the expectations of SSLeay() ? And is this behavior documented anywhere? The OpenSSL documentation specifies that this function call would return the version information of the library that it's linked against and our application was built with that expectation.

Comment 4 Tomas Mraz 2017-10-04 07:57:04 UTC
It is not documented, it should be transparent to applications.

In what exact way it is breaking your application?

Comment 5 Sailesh Mukil 2017-10-04 23:18:32 UTC
Some of our build machines are on CentOS 6.4 with OpenSSL 1.0.0, but some of our users run on CentOS6.7 which has OpenSSL 1.0.1e.

We also let the users choose their TLS versions. We have some runtime checks with SSLeay() to make sure that the version of TLS they selected is supported on that system.

Eg: If they select TLSv1.2, and have only OpenSSL 1.0.0 on their system, we return an error.

We have to do this runtime check because of the following OpenSSL API breakage bug:

"When disabling, say, TLS1.1 we pass an option bitmask to SSL_CTX_set_options() that includes SSL_OP_NO_TLSv1_1. In OpenSSL 1.0.1 this is defined as 0x10000000L but in 1.0.0 it is not defined.

However, in OpenSSL 1.0.0 *another* option for SSL_CTX_set_options() has the *same* value (0x10000000L). This means that passing SSL_OP_NO_TLSv1_1 to OpenSSL 1.0.0 actually does something completely different. This lack of backwards compatibility is the bug."

So, now even though we are running on a system which has OpenSSL 1.0.1e, SSLeay() returns the version number as 1.0.0, so it's not really transparent to applications. According to the documentation, it should return OpenSSL 1.0.1e when invoked on a system with OpenSSL 1.0.1e, right?

This problem doesn't exist on newer OpenSSL versions, i.e. 1.0.2 and up according to the OpenSSL guys.

Thanks for your time.

Comment 6 Tomas Mraz 2017-10-09 09:28:58 UTC
Hmm, you're right with the backwards (or rather forwards) compatibility issue in regards to the SSL_OP_NO_TLSv1_1 flag. This is an unfortunate thing but I am afraid we cannot fix that at this point.

The only thing I can suggest to you is to find out another way how to detect that you're running against OpenSSL 1.0.1 and not 1.0.0 - you could for example use SSL_get_ciphers() to obtain the list of enabled ciphers and try to find a TLS1.2 cipher in that list by parsing 
SSL_CIPHER_description() output.

Comment 7 Sailesh Mukil 2017-10-09 16:41:22 UTC
Thanks for the suggestion, that seems like it would work. I'll try that moving forward.

Also, could we mark this as a known issue?

Comment 8 Tomas Mraz 2017-10-10 06:34:20 UTC
We can persuade that.

Comment 11 Lenka Špačková 2017-11-29 13:35:16 UTC
Hi all, 
Thank you very much for your input. I have added this known issue to RHEL 6.9 Release Notes:
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/6.9_release_notes/known_issues_security

Also, I will make sure it is repeated in the Release Notes for the next minor version.