Hardening consulting

Bored by OpenSSL warnings under valgrind ?

Problem

OpenSSL has the "good" idea to use the stack as a source of entropy. This is the cause of the 2008 debian bug: the debian maintainer for OpenSSL was annoyed by valgrind warnings. So he did a fix that removed the error but introduced a main security issue: after the fix, the number of possible keys was so weak that it was possible to list them. The consequence is that all the cryptographic materials generated by this version had to be regenerated, and it probably remains plenty of servers running with vulnerable keys.

So ok, the maintainer has been blamed, he did his mea culpa. But what can you do when you're annoyed by all these warnings ?

Valgrind

It's because you have uninitialized value !

Valgrind proposes suppressions, which is a way to express the fact that "if you see that call stack with uninitialized values, then don't care, that's expected". With such suppression, you won't get a warning when hitting that call stack.

Most of the time, the problem remains because data are still marked as undefined. So any computation made with these data will be marked as undefined too, and you get a sort of an "undefined contamination". You can track the call that first make your undefined data by using the --track-origins=yes parameter, but be aware that it makes your program run really slower (even more slower than a normal valgrind execution).

If you install openSSL debugging symbols, you will get that kind of things (for example with FreeRDP doing TLS security):

==11827== Conditional jump or move depends on uninitialised value(s)
==11827==    at 0x6ACD2FE: gcc_read_server_network_data (gcc.c:1287)
==11827==    by 0x6AC9DEE: gcc_read_server_data_blocks (gcc.c:473)
==11827==    by 0x6AC9697: gcc_read_conference_create_response (gcc.c:275)
==11827==    by 0x6ACF995: mcs_recv_connect_response (mcs.c:662)
==11827==    by 0x6B04479: rdp_client_connect_mcs_connect_response (connection.c:632)
==11827==    by 0x6B0B741: rdp_recv_callback (rdp.c:1127)
==11827==    by 0x6B11C9B: transport_check_fds (transport.c:1080)
==11827==    by 0x6B0B8FC: rdp_check_fds (rdp.c:1189)
==11827==    by 0x6B036D4: rdp_client_connect (connection.c:302)
==11827==    by 0x6AF0A78: freerdp_connect (freerdp.c:98)
==11827==    by 0x4E58156: xf_thread (xf_client.c:1451)
==11827==    by 0x8556181: start_thread (pthread_create.c:312)
==11827==  Uninitialised value was created by a stack allocation
==11827==    at 0xBE25DF7: aesni_cbc_encrypt (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)

Well, you're really happy to know that it's the fault of aesni_cbc_encrypt !

What's next ?

Googling a little, you will read on many forums "easy, just recompile your openSSL with -DPURIFY". I don't know if the ones that suggest that have already done it, because recompiling OpenSSL is a real pain. Just do a apt-get source openssl to see the mass of patches that distributions apply on top of the original code. So you're not really doing tests in the same environment as your distribution.

I was resolving to compile my own libssl with correct CFLAGS or worst, seek a PPA that would have already done it. When I have suddenly remembered that during a recent compilation of Pulseaudio, there were a valgrind option. It's there that I found something that was going to help me.

So you need help ?

I have discovered that Valgrind ships an API that allows the audited program to collaborate with valgrind. The API allows to give indications on what it is doing, and most notably specify that some data range should be marked as initialized. You do it this way:

#include <valgrind/memcheck.h>

...

int readSSL(....) {
    ...

    status = SSL_read(tls, data, length);
    if (status > 0) {
        ...
        VALGRIND_MAKE_MEM_DEFINED(data, status);
        ...
    }

    ...
}

The VALGRIND_MAKE_MEM_DEFINED() call informs valgrind that these bytes, retrieved from OpenSSL, have nothing undefined. So valgrind is happy (and so us) and it doesn't print any warning related to undefined variables from this data range.

Of course, it works only when you have the source code and you're ready to modify it. But it's the case with FreeRDP, so no need to refrain us from doing it.

To conclude

I have added a Valgrind helper capability in this pull request, I think this will greatly help us. And as you have probably noticed, Pulseaudio is great as the solution was hidden in its source code :).