Skip to content
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 3.0.0alpha16 interop issue with 0.9.8zh - Diffie-Hellman invalid public key #15465

Closed
rainerjung opened this issue May 25, 2021 · 4 comments
Assignees
Labels
branch: master Merge to master branch branch: 3.0 Merge to openssl-3.0 branch triaged: bug The issue/pr is/fixes a bug

Comments

@rainerjung
Copy link
Contributor

I ran into an interop problem when doing release testing for httpd 2.4.48 using OpenSSL 3.0.0alpha16 in the server and OpenSSL 0.9.8zh in the client. First I made TLS 1.0 work by adding "@SECLEVEL=0" at the end of the SSLCipherSuite config lines, but I still see sporadic failures:

SSL Library Error: error:02800066:Diffie-Hellman routines::invalid public key

I think they might have to do with restricting the allowed params for DH in OpenSSL 3. So it seems sometimes 0.9.8 generates DH keys that do not fulfil the stricter requirements of version 3. That means using such old client software will most of the time succeed with an TLS 1.0 handshake, but sporadically it will fail. I am not arware of a workaround.

Of course TLS 1.0 should no longer be used, but since it is supported in OpenSSL 3, the behavior of sporadic interop failures is a bit problematic and should at least be documented.

With a bit of help how to add more debug info, I could do a custom httpd build. But I will try to reproduce with s_server and s_client first and hope there's enough debug flags there to understand the used DH params.

@rainerjung rainerjung added the issue: bug report The issue was opened to report a bug label May 25, 2021
@mattcaswell mattcaswell added triaged: bug The issue/pr is/fixes a bug and removed issue: bug report The issue was opened to report a bug labels May 25, 2021
@mattcaswell
Copy link
Member

mattcaswell commented May 25, 2021

But I will try to reproduce with s_server and s_client first

Thanks @rainerjung - that would be very helpful

@rainerjung
Copy link
Contributor Author

I can not reproduce with 0.9.8 s_client, but with a very simple programmatic client using 0.9.8.

I am convinced, that the problem is due to the missing padding (DH_compute_key_padded(()) in OpenSSL before 1.0.2 introduced in this commit first in 1.0.2:

6c4b351

OpenSSL 3 sets DH_R_INVALID_PUBKEY in crypto/dh/dh_key.c line 392 when the size of the public key is not correct. Although the error only happens spuriously it happens roughly 1/256 of the attempts, which would be a good fit to the average likelyness, that the key has at least one byte less as size.

The stricter check in 3 was added in 9aaecbf as a side effect of FFDHE support. Since the padding is mentioned in section 4.2.8.1 of RFC 8446 and was introduced in 1.0.2 as a client in 2013 the interop break with older OpenSSL might be OK.

A very verbose dump of s_server shows the following differences between a working handshake and a breaking one:

Working:

SSL_accept:SSLv3/TLS write server done
read from 0x1570270 [0x14e5858] (262 bytes => 262 (0x106))
...
<<< TLS 1.0, Handshake [length 0106], ClientKeyExchange
...
read from 0x1570270 [0x14e5853] (5 bytes => 5 (0x5))
0000 - 14 03 01 00 01 .....
<<< TLS 1.0, RecordHeader [length 0005]
14 03 01 00 01
SSL_accept:SSLv3/TLS read client key exchange
read from 0x1570270 [0x14e5858] (1 bytes => 1 (0x1))
0000 - 01 .
read from 0x1570270 [0x14e5853] (5 bytes => 5 (0x5))
0000 - 16 03 01 00 30 ....0
<<< TLS 1.0, RecordHeader [length 0005]
16 03 01 00 30
SSL_accept:SSLv3/TLS read change cipher spec

Broken:

SSL_accept:SSLv3/TLS write server done
read from 0x154d590 [0x1505898] (261 bytes => 261 (0x105))
...
<<< TLS 1.0, Handshake [length 0105], ClientKeyExchange
...

TLS 1.0, RecordHeader [length 0005]
15 03 01 00 02
write to 0x154d590 [0x14ebdc0] (7 bytes => 7 (0x7))
0000 - 15 03 01 00 02 02 50 ......P
TLS 1.0, Alert [length 0002], fatal internal_error
02 50
SSL3 alert write:fatal:internal error
SSL_accept:error in error
00879386C87F0000:error:02800066:Diffie-Hellman routines:(unknown function):invalid public key:crypto/dh/dh_key.c:399:
00879386C87F0000:error:0A0C0103:SSL routines:(unknown function):internal error:ssl/statem/statem_srvr.c:2983:

@arekm
Copy link

arekm commented Feb 2, 2022

This works as reproducer for me and openssl 1.1.1l is involved.

Server side with openssl 3.0.1:

openssl s_server --accept *:5666 --nocert -cipher "ALL:@SECLEVEL=0"

client side openssl 1.1.1l:

while (true); do echo "x" | openssl s_client --connect server:5666 -cipher "ALL:@SECLEVEL=0" || break; done

Once a while server reports:

80BB0D5D387F0000:error:02800066:Diffie-Hellman routines:ossl_dh_buf2key:invalid public key:crypto/dh/dh_key.c:399:
80BB0D5D387F0000:error:0A0C0103:SSL routines:tls_process_cke_dhe:internal error:ssl/statem/statem_srvr.c:2989:

Not seeing this between 3.0.1 <--> 3.0.1 and 1.1.1l <--> 1.1.1l. (but I wasn't testing these for longer than few minutes). Only when 3.0.1 is server and 1.1.1l is a client (not vice versa).

Real life cases where this happens: Nagios nrpe client (openssl 1.1.1l) checking nrpe server (openssl 3.0.1) and sometimes reporting: "CHECK_NRPE: (ssl_err != 5) Error - Could not complete SSL handshake with 1.2.3.4: 1"

Client side:

140492789227456:error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error:ssl/record/rec_layer_s3.c:1543:SSL alert number 80
CONNECTED(00000003)
---
no peer certificate available
---
No client certificate CA names sent
Server Temp Key: DH, 3072 bits
---
SSL handshake has read 862 bytes and written 888 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ADH-AES256-GCM-SHA384
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ADH-AES256-GCM-SHA384
    Session-ID:
    Session-ID-ctx:
    Master-Key: 0B88E0DFFA1FC2D2C570C9F2C44077A39EC353277E44BD8E136BB4F2216912F29E87D1CFD3E33882B67521BE4200A0F3
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1643803581
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: yes
---

Server side:

-----BEGIN SSL SESSION PARAMETERS-----
MF8CAQECAgMDBAIApwQABDB3DQKTbnKNc7entUqww1f8+hWM4+kGqCFASblOgjAD
KJagYaFYR8E4FgFuXmf+9bOhBgIEYfpzhqIEAgIcIKQGBAQBAAAArQMCAQGzAwIB
AA==
-----END SSL SESSION PARAMETERS-----
Shared ciphers:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:ECDHE-ECDSA-ARIA256-GCM-SHA384:ECDHE-ARIA256-GCM-SHA384:DHE-DSS-ARIA256-GCM-SHA384:DHE-RSA-ARIA256-GCM-SHA384:ADH-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-CCM:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM:ECDHE-ECDSA-ARIA128-GCM-SHA256:ECDHE-ARIA128-GCM-SHA256:DHE-DSS-ARIA128-GCM-SHA256:DHE-RSA-ARIA128-GCM-SHA256:ADH-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-RSA-CAMELLIA256-SHA384:DHE-RSA-CAMELLIA256-SHA256:DHE-DSS-CAMELLIA256-SHA256:ADH-AES256-SHA256:ADH-CAMELLIA256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-RSA-CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA256:DHE-DSS-CAMELLIA128-SHA256:ADH-AES128-SHA256:ADH-CAMELLIA128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:AECDH-AES256-SHA:ADH-AES256-SHA:ADH-CAMELLIA256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:AECDH-AES128-SHA:ADH-AES128-SHA:ADH-CAMELLIA128-SHA:AES256-GCM-SHA384:AES256-CCM8:AES256-CCM:ARIA256-GCM-SHA384:AES128-GCM-SHA256:AES128-CCM8:AES128-CCM:ARIA128-GCM-SHA256:AES256-SHA256:CAMELLIA256-SHA256:AES128-SHA256:CAMELLIA128-SHA256:AES256-SHA:CAMELLIA256-SHA:AES128-SHA:CAMELLIA128-SHA
Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:ECDSA+SHA1:RSA+SHA224:RSA+SHA1:DSA+SHA224:DSA+SHA1:DSA+SHA256:DSA+SHA384:DSA+SHA512
Shared Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:ECDSA+SHA1:RSA+SHA224:RSA+SHA1:DSA+SHA224:DSA+SHA1:DSA+SHA256:DSA+SHA384:DSA+SHA512
Supported Elliptic Curve Point Formats: uncompressed:ansiX962_compressed_prime:ansiX962_compressed_char2
Supported groups: x25519:secp256r1:x448:secp521r1:secp384r1
Shared groups: x25519:secp256r1:x448:secp521r1:secp384r1
CIPHER is ADH-AES256-GCM-SHA384
Secure Renegotiation IS supported
x
ERROR
802B1BDBAD7F0000:error:02800066:Diffie-Hellman routines:ossl_dh_buf2key:invalid public key:crypto/dh/dh_key.c:399:
802B1BDBAD7F0000:error:0A0C0103:SSL routines:tls_process_cke_dhe:internal error:ssl/statem/statem_srvr.c:2989:

@t8m t8m self-assigned this Feb 2, 2022
@t8m t8m added branch: 3.0 Merge to openssl-3.0 branch branch: master Merge to master branch labels Feb 2, 2022
t8m added a commit to t8m/openssl that referenced this issue Feb 2, 2022
It does not make sense to check the size because this
function can be used in other contexts than in TLS-1.3 and
the value might not be padded to the size of p.

However it makes sense to do the partial pubkey check because
there is no valid reason having the pubkey value outside the
1 < pubkey < p-1 bounds.

Fixes openssl#15465
@t8m
Copy link
Member

t8m commented Feb 2, 2022

Fix in #17630

pld-gitsync pushed a commit to pld-linux/openssl that referenced this issue Feb 2, 2022
openssl-machine pushed a commit that referenced this issue Feb 7, 2022
It does not make sense to check the size because this
function can be used in other contexts than in TLS-1.3 and
the value might not be padded to the size of p.

However it makes sense to do the partial pubkey check because
there is no valid reason having the pubkey value outside the
1 < pubkey < p-1 bounds.

Fixes #15465

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from #17630)

(cherry picked from commit 2c0f7d4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
branch: master Merge to master branch branch: 3.0 Merge to openssl-3.0 branch triaged: bug The issue/pr is/fixes a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants