I am seeing some strange behaviour with openssl, versions 0.9.8e, f, g
and h on a Gentoo Linux 2.6.22 machine Intel Core2 (amd64 architecture).
Following some googling with gentoo, I have built each version with
and without enable-tlsext.

The problem that I am seeing is that an openssl server, using any of
the above named releases, is successfully serving some connections and
rejecting others (all when using the same certificates). I first encountered
this with exim 4.69 and TLS and apache 2.2.8-r4 with SSLv3.

I reproduced the problem using openssl s_client and openssl s_server,
which I hoped would simplify debugging.

The problem, simply stated:

From my own machine, Apache https works correctly with:

w3m (using whichever the current version of libssl I am testing)
firefox 2.009 - using 32 bit pre-compiled binaries (thus not the
currently installed libssl)
opera 9.50 - again with pre-compiled 32 bit binaries (thus not the
currently installed libssl)
openssl s_client -connect j-e-s.net:443 -debug -state -msg -ssl3

From my wife's machine - running Debian Linux on Intel 32, the https
server also works for:

firefox 2.009
opera 9.50
A very old version of Netscape - I can't currently get the version
number
w3m
openssl s_client ...

However, from Windows XP and Windows 98 using IE6 and IE7, Firefox
2.x, Opera 8.x, and some version of Safari, it fails. Again, no version
numbers, as these are non-technical friends who tried remote
connections and reported failures)

The same problem arises from a FreeBSD 7 machine using Firefox 2.x, w3m, and
openssl s_client.

I began testing with s_client and s_server to simplify debugging:

A successful session runs through (-debug and -msg omitted, as
there's no problem to be seen

++++++++++++++++++++++++++++++++++++++++++++++++++ +++++

root@boah:/root# openssl s_client -connect j-e-s.net:443 -state -ssl3
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=0 /C=NL/ST=NH/O=j-e-s.net/CN=j-e-s.net
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /C=NL/ST=NH/O=j-e-s.net/CN=j-e-s.net
verify error:num=27:certificate not trusted
verify return:1
depth=0 /C=NL/ST=NH/O=j-e-s.net/CN=j-e-s.net
verify error:num=21:unable to verify the first certificate
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read finished A
---
Certificate chain
0 s:/C=NL/ST=NH/O=j-e-s.net/CN=j-e-s.net
i:/O=j-e-s.net/emailAddress=jes@j-e-s.net/L=Amsterdam/ST=NH/C=NL/CN=Jim Segr\
ave
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIC7jCCAdYCAhALMA0GCSqGSIb3DQEBBAUAMHYxEjAQBgNVBA oTCWotZS1zLm5l
[snip]
JtyoEPpZrqvLKMPcWT1Pu3n0y9xpkh9kQ5KhW2o0KWXfMQ==
-----END CERTIFICATE-----
subject=/C=NL/ST=NH/O=j-e-s.net/CN=j-e-s.net
issuer=/O=j-e-s.net/emailAddress=jes@j-e-s.net/L=Amsterdam/ST=NH/C=NL/CN=Jim
Segrave
---
No client certificate CA names sent
---
SSL handshake has read 1590 bytes and written 442 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 1024 bit
SSL-Session:
Protocol : SSLv3
Cipher : DHE-RSA-AES256-SHA
Session-ID:
1FFB6D486555ABDD06EDC8DC6E20BBE96C54151F31BC1919B7 37BF72A4C84354
Session-ID-ctx:
Master-Key:
BC107DE1CD0E0A0B37854EB68AC4D983839EC49375EA209458 46D8172E56D427A69A8D78B9C\
C39C862B5A44A0054AB79
Key-Arg : None
Start Time: 1213966029
Timeout : 7200 (sec)
Verify return code: 21
---
++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++

Here is a client view of a failed session from a FreeBSD machine using
the command

openssl s_client -connect j-e-s.net:443 -debug -msg -stat -ssl3

I've snipped some but not all of the hex dump away to concentrate on
the problem areas. Note that the encryption/integrity choice 00 39, is
DHE-RSA-AES256-SHA, the same as in the successful session above, so
it's not an encryption error for some protocol. Following this is the
output from the openssl s_server to which this was connecting, so the
messages can be matched up:

CONNECTED(00000003)
write to 0x606160 [0x67d000] (98 bytes => 98 (0x62))
>>> SSL 3.0 Handshake [length 005d], ClientHello

01 00 00 59 03 00 48 5b aa fa 5e 8e b8 30 28 5b
4e 87 4c 3e 2a 28 fa 94 fb 6e 12 6c 2a 54 82 0c
14 96 f0 f8 64 35 00 00 32 00 39 00 38 00 35 00
88 00 87 00 84 00 16 00 13 00 0a 00 33 00 32 00
2f 00 45 00 44 00 41 00 05 00 04 00 15 00 12 00
09 00 14 00 11 00 08 00 06 00 03 01 00

read from 0x606160 [0x678000] (5 bytes => 5 (0x5))
0000 - 16 03 00 00 4a ....J
read from 0x606160 [0x678005] (74 bytes => 74 (0x4A))
<<< SSL 3.0 Handshake [length 004a], ServerHello
02 00 00 46 03 00 48 5b aa fa 24 51 cf c1 fa af
8f d2 ec 0f b6 6f 8a cd 62 68 41 f6 fc ba 0b 22
a4 7e 38 c8 51 01 20 3d 45 e5 2f 70 e2 43 c2 67
1d 46 49 18 4b c0 90 b3 a2 41 d2 b6 65 73 28 6e
3b 1f 31 b1 15 95 65 00 39 00

read from 0x606160 [0x678000] (5 bytes => 5 (0x5))
0000 - 16 03 00 02 fc .....
read from 0x606160 [0x678005] (764 bytes => 764 (0x2FC))
<<< SSL 3.0 Handshake [length 02fc], Certificate
[snip data]

read from 0x606160 [0x678000] (5 bytes => 5 (0x5))
0000 - 16 03 00 02 8d .....
read from 0x606160 [0x678005] (653 bytes => 653 (0x28D))
<<< SSL 3.0 Handshake [length 028d], ServerKeyExchange
[snip data]

read from 0x606160 [0x678000] (5 bytes => 5 (0x5))
0000 - 16 03 00 00 04 .....
read from 0x606160 [0x678005] (4 bytes => 4 (0x4))
<<< SSL 3.0 Handshake [length 0004], ServerHelloDone
0e 00 00 00

>>> SSL 3.0 Handshake [length 0106], ClientKeyExchange

[snip data]
write to 0x606160 [0x683000] (267 bytes => 267 (0x10B))
[snip data]

>>> SSL 3.0 ChangeCipherSpec [length 0001]

01
write to 0x606160 [0x683000] (6 bytes => 6 (0x6))
0000 - 14 03 00 00 01 01 ......

Here I've left the data in, as it's very relevant - the unencrypted
hash of the handshake messages etc:

>>> SSL 3.0 Handshake [length 0028], Finished

14 00 00 24 df e8 75 30 88 46 8d 3e 96 51 30 90
2c 7d 47 c9 da 19 13 5c c1 43 f2 05 82 d9 bf 51
33 9e 4b 06 c8 c3 74 75

The encrypted version of the hash of the handshake messages:

write to 0x606160 [0x683000] (69 bytes => 69 (0x45))
0000 - 16 03 00 00 40 a5 fb 1a-87 b0 a7 f9 6e c7 2d f8 ....@.......n.-.
0010 - ed 50 57 8c 29 4e 19 78-b6 3b 0d f6 d0 6b 87 38 .PW.)N.x.;...k.8
0020 - d8 e2 8f 45 7b 3a 18 76-ec b7 35 3f f9 42 c2 52 ...E{:.v..5?.B.R
0030 - 00 47 b5 65 79 b4 64 13-a4 d0 0d fe 8e b1 5c e0 .G.ey.d.......\.
0040 - 9b 37 e1 d6 30 .7..0

The openssl s_server was not impressed:

read from 0x606160 [0x678000] (5 bytes => 5 (0x5))
0000 - 15 03 00 00 02 .....
read from 0x606160 [0x678005] (2 bytes => 2 (0x2))
0000 - 02 28 .(
<<< SSL 3.0 Alert [length 0002], fatal handshake_failure
02 28

++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++

Here's what the server saw during that same session (port 443 is
being redirected to port 2443):

Script started on Fri 20 Jun 2008 03:04:29 PM CEST
root:/var/tmp$ openssl s_server -accept 2443 -cert /etc/apache2/ssl/jes-net-1024.crt -key /etc/apache2/ssl/jes-net-1024.key -dhparam /etc/apache2/ssl/dh.parm -state -debug -msg

Setting temp DH parameters
Using default temp ECDH parameters
ACCEPT
SSL_accept:before/accept initialization

read from 0x6889b0 [0x68e090] (11 bytes => 11 (0xB))
read from 0x6889b0 [0x68e09b] (87 bytes => 87 (0x57))
<<< SSL 3.0 Handshake [length 005d], ClientHello
01 00 00 59 03 00 48 5b aa fa 5e 8e b8 30 28 5b
4e 87 4c 3e 2a 28 fa 94 fb 6e 12 6c 2a 54 82 0c
14 96 f0 f8 64 35 00 00 32 00 39 00 38 00 35 00
88 00 87 00 84 00 16 00 13 00 0a 00 33 00 32 00
2f 00 45 00 44 00 41 00 05 00 04 00 15 00 12 00
09 00 14 00 11 00 08 00 06 00 03 01 00
SSL_accept:SSLv3 read client hello A

>>> SSL 3.0 Handshake [length 004a], ServerHello

02 00 00 46 03 00 48 5b aa fa 24 51 cf c1 fa af
8f d2 ec 0f b6 6f 8a cd 62 68 41 f6 fc ba 0b 22
a4 7e 38 c8 51 01 20 3d 45 e5 2f 70 e2 43 c2 67
1d 46 49 18 4b c0 90 b3 a2 41 d2 b6 65 73 28 6e
3b 1f 31 b1 15 95 65 00 39 00
write to 0x6889b0 [0x6982e0] (79 bytes => 79 (0x4F))

SSL_accept:SSLv3 write server hello A
>>> SSL 3.0 Handshake [length 02fc], Certificate

[snip data]
write to 0x6889b0 [0x6982e0] (769 bytes => 769 (0x301))
0000 - 16 03 00 02 fc 0b 00 02-f8 00 02 f5 00 02 f2 30 ...............0
[snip remainder]

SSL_accept:SSLv3 write certificate A
>>> SSL 3.0 Handshake [length 028d], ServerKeyExchange

[snip data]
write to 0x6889b0 [0x6982e0] (658 bytes => 658 (0x292))
0000 - 16 03 00 02 8d 0c 00 02-89 01 00 c7 62 b9 1e 78 ............b..x
[snip remainder]

SSL_accept:SSLv3 write key exchange A

>>> SSL 3.0 Handshake [length 0004], ServerHelloDone

0e 00 00 00
write to 0x6889b0 [0x6982e0] (9 bytes => 9 (0x9))
0000 - 16 03 00 00 04 0e ......
0009 -
SSL_accept:SSLv3 write server done A

SSL_accept:SSLv3 flush data

read from 0x6889b0 [0x68e090] (5 bytes => 5 (0x5))
0000 - 16 03 00 01 06 .....
read from 0x6889b0 [0x68e095] (262 bytes => 262 (0x106))
0000 - 10 00 01 02 01 00 55 f5-cb 5f 1a 15 c9 e9 f9 2e ......U.._......
[snip data]
<<< SSL 3.0 Handshake [length 0106], ClientKeyExchange
10 00 01 02 01 00 55 f5 cb 5f 1a 15 c9 e9 f9 2e
[snip data]

SSL_accept:SSLv3 read client key exchange A
read from 0x6889b0 [0x68e090] (5 bytes => 5 (0x5))
0000 - 14 03 00 00 01 .....
read from 0x6889b0 [0x68e095] (1 bytes => 1 (0x1))
0000 - 01 .
<<< SSL 3.0 ChangeCipherSpec [length 0001]
01

read from 0x6889b0 [0x68e090] (5 bytes => 5 (0x5))
0000 - 16 03 00 00 40 ....@

Here's the encrypted closing handshake from the client - note that it
matches the encrypted write from the client log:

read from 0x6889b0 [0x68e095] (64 bytes => 64 (0x40))
0000 - a5 fb 1a 87 b0 a7 f9 6e-c7 2d f8 ed 50 57 8c 29 .......n.-..PW.)
0010 - 4e 19 78 b6 3b 0d f6 d0-6b 87 38 d8 e2 8f 45 7b N.x.;...k.8...E{
0020 - 3a 18 76 ec b7 35 3f f9-42 c2 52 00 47 b5 65 79 :.v..5?.B.R.G.ey
0030 - b4 64 13 a4 d0 0d fe 8e-b1 5c e0 9b 37 e1 d6 30 .d.......\..7..0

And here's the decrypted closing handshake, which again, matches the
unencrypted data from the client log:

<<< SSL 3.0 Handshake [length 0028], Finished
14 00 00 24 df e8 75 30 88 46 8d 3e 96 51 30 90
2c 7d 47 c9 da 19 13 5c c1 43 f2 05 82 d9 bf 51
33 9e 4b 06 c8 c3 74 75

And here the server complains:

write to 0x6889b0 [0x6982e0] (7 bytes => 7 (0x7))
0000 - 15 03 00 00 02 02 28 ......(
>>> SSL 3.0 Alert [length 0002], fatal handshake_failure

02 28
SSL3 alert write:fatal:handshake failure
SSL_accept:failed in SSLv3 read finished A
ERROR
12325:error:1408C095:SSL routines:SSL3_GET_FINISHED:digest check failed:s3_both.c:231:
shutting down SSL
CONNECTION CLOSED
ACCEPT
++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++

Now the same FreeBSD openssl s_client isn't broken - if I aim it for
example, at www.amazon.com:443, the session comes up without problems.

Nor is the openssl s_client on my machine broken - I too, can connect
to various public https sites using the openssl s_client.

So the problem appears to be that if both s_clients are working, then
the server must be erroneous, but in a way that is compatible with my
local client and not with other, remote clients.

Does anyone have any further ideas?

I may be able to create a debugging openssl on the FreeBSD server
where I can track how the closing handshake is built by the client
(although I'm not sure where to find the places where the digest is
being built so I can dump the data and results. Any help there would be
appreciated).

Similarly I can do the same for a local client and a server, as I'd
like to know how it is that a local client can create the closing
handshake data such that it's accepted by other https servers as well
as this one, whereas some other s_clients and many other browsers do
not generate closing handshakes that this server accepts.


--
Jim Segrave jes@j-e-s.net


__________________________________________________ ____________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-users@openssl.org
Automated List Manager majordomo@openssl.org