Hubert Kario via RT
2016-07-22 14:56:11 UTC
the issue is present in master 0ed26acce328ec16a3aa and looks to have been
introduced in commit:
$ git bisect bad
5b8fa431ae8eb5a18ba913494119e394230d4b70 is the first bad commit
commit 5b8fa431ae8eb5a18ba913494119e394230d4b70
Author: David Benjamin <***@google.com>
Date: Thu Jun 16 14:15:19 2016 -0400
Make RSA key exchange code actually constant-time.
Using RSA_PKCS1_PADDING with RSA_private_decrypt is inherently unsafe.
The API requires writing output on success and touching the error queue
on error. Thus, although the padding check itself is constant-time as of
294d1e36c2495ff00e697c9ff622856d3114f14f, and the logic after the
decryption in the SSL code is constant-time as of
adb46dbc6dd7347750df2468c93e8c34bcb93a4b, the API boundary in the middle
still leaks whether the padding check succeeded, giving us our
much-loved Bleichenbacher padding oracle.
Instead, PKCS#1 padding must be handled by the caller which uses
RSA_NO_PADDING, in timing-sensitive code integrated with the
Bleichenbacher mitigation. Removing PKCS#1 padding in constant time is
actually much simpler when the expected length is a constant (and if
it's not a constant, avoiding a padding oracle seems unlikely), so just
do it inline.
Signed-off-by: Kurt Roeckx <***@roeckx.be>
Reviewed-by: Rich Salz <***@openssl.org>
GH: #1222
:040000 040000 bd98bdbeaeddbc22f8a37324aaa1f1a527712a02
9cc68f63ca3b34ed1f13b05029c3b4bb968a21cb M ssl
when the OpenSSL receives a Client Key Exchange message that has the encrypted
premaster secret comprised only of zero bytes, or equal to server's modulus,
the server just aborts the connection without sending an Alert message
OpenSSL 1.0.2 (b746aa3fe05b5b) and 1.0.1 (6adf409c7432b9) do send Alert
messages in this situation
Reproducer:
===========
(requires Python 2.6, 3.2 or later)
git clone https://github.com/tomato42/tlsfuzzer.git
pushd tlsfuzzer
git clone https://github.com/warner/python-ecdsa .python-ecdsa
ln -s .python-ecdsa/ecdsa ecdsa
git clone https://github.com/tomato42/tlslite-ng.git .tlslite-ng
pushd .tlslite-ng
popd
ln -s .tlslite-ng/tlslite tlslite
popd
openssl req -x509 -newkey rsa -keyout localhost.key -out localhost.crt \
-nodes -batch -subj /CN=localhost
openssl s_server -www -key localhost.key -cert localhost.crt
# in another terminal, same directory
PYTHONPATH=tlsfuzzer python
tlsfuzzer/scripts/test-invalid-rsa-key-exchange-messages.py
--
Regards,
Hubert Kario
Senior Quality Engineer, QE BaseOS Security team
Web: www.cz.redhat.com
Red Hat Czech s.r.o., PurkyÅova 99/71, 612 45, Brno, Czech Republic
introduced in commit:
$ git bisect bad
5b8fa431ae8eb5a18ba913494119e394230d4b70 is the first bad commit
commit 5b8fa431ae8eb5a18ba913494119e394230d4b70
Author: David Benjamin <***@google.com>
Date: Thu Jun 16 14:15:19 2016 -0400
Make RSA key exchange code actually constant-time.
Using RSA_PKCS1_PADDING with RSA_private_decrypt is inherently unsafe.
The API requires writing output on success and touching the error queue
on error. Thus, although the padding check itself is constant-time as of
294d1e36c2495ff00e697c9ff622856d3114f14f, and the logic after the
decryption in the SSL code is constant-time as of
adb46dbc6dd7347750df2468c93e8c34bcb93a4b, the API boundary in the middle
still leaks whether the padding check succeeded, giving us our
much-loved Bleichenbacher padding oracle.
Instead, PKCS#1 padding must be handled by the caller which uses
RSA_NO_PADDING, in timing-sensitive code integrated with the
Bleichenbacher mitigation. Removing PKCS#1 padding in constant time is
actually much simpler when the expected length is a constant (and if
it's not a constant, avoiding a padding oracle seems unlikely), so just
do it inline.
Signed-off-by: Kurt Roeckx <***@roeckx.be>
Reviewed-by: Rich Salz <***@openssl.org>
GH: #1222
:040000 040000 bd98bdbeaeddbc22f8a37324aaa1f1a527712a02
9cc68f63ca3b34ed1f13b05029c3b4bb968a21cb M ssl
when the OpenSSL receives a Client Key Exchange message that has the encrypted
premaster secret comprised only of zero bytes, or equal to server's modulus,
the server just aborts the connection without sending an Alert message
OpenSSL 1.0.2 (b746aa3fe05b5b) and 1.0.1 (6adf409c7432b9) do send Alert
messages in this situation
Reproducer:
===========
(requires Python 2.6, 3.2 or later)
git clone https://github.com/tomato42/tlsfuzzer.git
pushd tlsfuzzer
git clone https://github.com/warner/python-ecdsa .python-ecdsa
ln -s .python-ecdsa/ecdsa ecdsa
git clone https://github.com/tomato42/tlslite-ng.git .tlslite-ng
pushd .tlslite-ng
popd
ln -s .tlslite-ng/tlslite tlslite
popd
openssl req -x509 -newkey rsa -keyout localhost.key -out localhost.crt \
-nodes -batch -subj /CN=localhost
openssl s_server -www -key localhost.key -cert localhost.crt
# in another terminal, same directory
PYTHONPATH=tlsfuzzer python
tlsfuzzer/scripts/test-invalid-rsa-key-exchange-messages.py
--
Regards,
Hubert Kario
Senior Quality Engineer, QE BaseOS Security team
Web: www.cz.redhat.com
Red Hat Czech s.r.o., PurkyÅova 99/71, 612 45, Brno, Czech Republic
--
Ticket here: http://rt.openssl.org/Ticket/Display.html?id=4623
Please log in as guest with password guest if prompted
Ticket here: http://rt.openssl.org/Ticket/Display.html?id=4623
Please log in as guest with password guest if prompted