JSSE TlsPrfGenerator ArrayIndexOutOfBoundsException

Christopher Meyer christopher.meyer at rub.de
Tue May 29 13:42:54 UTC 2012


Hi,
during some research we noticed an interesting implementation bug inside the 
com.sun.crypto.provider.TlsPrfGenerator.expand(..) function.

The problem is that an internal for loop das some XOR magic on passed arrays:
for (int i = 0; i < secLen; i++) {
            pad1[i] ^= secret[i + secOff];
            pad2[i] ^= secret[i + secOff];
        }

But nowhere is checked if the passed arrays are of a suitable length (at least 
== secLen). We were able to get into a state where secLen is greather than 
pad1.length and thus leading to an ArrayIndexOutOfBoundsException while 
iterating. 
This caused the SSLSocket to terminate (which is ok), but finally sending a 
TLSv1 FATAL ALERT:  internal_error where  instead a TLSv1 FATAL ALERT:  
handshake_failure should be returned.

>From developers point of view this seems to be a careless mistake, but from 
cryptographers point of view these different error messages may give some 
valuable hints on how the message was decrypted (chosen-ciphertext attacks).
The problem was found during research on Bleichenbacher's attack on SSL. A 
non-conforming PKCS message with two 0x0 separation bytes in combination with 
2048/4096 bit RSA keys will reproduce this scenario.



StackTraces (good/bad case) follow below:


how it should look like (1024 bit RSA keys):
--------------------------------------------

*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
SESSION KEYGEN:
PreMaster Secret:
0000: 29 1B DD F3 23 2D 59 1F   65 17 93 EF 85 F3 1F 7F  )...#-Y.e.......
0010: 69 BB FF C9 57 0B 67 4B   41 69 F9 CB 85 D9 71 D7  i...W.gKAi....q.
0020: 8F 63 71 C9 8D AB 00 03   01 E5 A5 8B BD 45 C4 99  .cq..........E..
0030: FF 5B F5 D2 DB A1 59 21   30 37 94 7C 2E 48 6A 8D  .[....Y!07...Hj.
0040: 08 9B 5F 91 2E 1C 49 8E   FD 6B E8 A2 56 8F 81 A7  .._...I..k..V...
0050: CD CD 10 4C 03 28 6B                               ...L.(k
RSA PreMasterSecret version error: expectedTLSv1 or TLSv1, decrypted: 
Unknown-41.27
Generating new random premaster secret
SESSION KEYGEN:
PreMaster Secret:
0000: 03 01 E0 75 34 84 96 F2   CB 65 3E 09 C8 82 E3 38  ...u4....e>....8
0010: CA 1B 0E 85 6B 8A E5 BA   7F C5 51 ED F1 ED 4F 8F  ....k.....Q...O.
0020: BFinalizer, called close()
3 59Finalizer, called closeInternal(true)
 C3 C7 72 B2 17 53   55 F3 40 3B A9 4C 16 42  .Y..r..SU.@;.L.B
CONNECTION KEYGEN:
Client Nonce:
0000: 00 00 01 37 28 27 B6 E0   3E D5 6F 8D 3D D6 B0 D8  ...7('..>.o.=...
0010: 13 D2 62 75 2F 21 0C 6E   3D 76 B1 86 12 18 81 55  ..bu/!.n=v.....U
Server Nonce:
0000: 4F C4 CF B6 42 29 3C CD   97 44 C1 66 1A 5F 3B 5A  O...B)<..D.f._;Z
0010: 3A EF 06 08 8A 48 E2 39   A8 42 0C 96 52 1F 7F 4F  :....H.9.B..R..O
Master Secret:
0000: C3 8F 4D 51 9D 20 BB 17   42 0F 70 E2 C2 5E BB AA  ..MQ. ..B.p..^..
0010: E2 55 45 BE D6 3D D3 11   B5 E7 59 E3 A1 26 EB 14  .UE..=....Y..&..
0020: FE 07 AF 80 6D 5A EC FB   11 12 CD EF 08 ED 31 7E  ....mZ........1.
Client MAC write Secret:
0000: F6 0B 0B 73 6E FC CE 0A   F3 64 F2 6C 5E D9 DF F2  ...sn....d.l^...
0010: A8 A4 98 22                                        ..."
Server MAC write Secret:
0000: D8 AC 63 54 F3 EA F6 55   C7 FE 08 70 FA 7D B8 32  ..cT...U...p...2
0010: 7A 21 4E 1B                                        z!N.
Client write key:
0000: 43 22 FA 3A B2 80 CE 5E   37 41 8C 23 7D 40 28 5C  C".:...^7A.#.@(\
Server write key:
0000: DF CF 6F CD 1F FD F4 37   E1 93 DE BF 89 16 6E 5F  ..o....7......n_
Client write IV:
0000: DC 57 88 79 7B 78 B2 30   29 D4 3C 3F BF CB 01 57  .W.y.x.0).<?...W
Server write IV:
0000: EA A7 4B 01 69 C6 10 5B   41 E3 CD 58 95 26 A0 F2  ..K.i..[A..X.&..
Thread-2, READ: TLSv1 Change Cipher Spec, length = 1
Thread-2, READ: TLSv1 Handshake, length = 48

========> 
========> 
========> Thread-2, SEND TLSv1 ALERT:  fatal, description = handshake_failure
========> 
========> 

Thread-2, WRITE: TLSv1 Alert, length = 2
Thread-2, called closeSocket()
Thread-2, handling exception: javax.net.ssl.SSLHandshakeException: Invalid 
padding
javax.net.ssl.SSLHandshakeException: Invalid padding
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1697)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:904)
	at 
sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1190)
	at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:657)
	at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:108)
	at java.io.OutputStream.write(OutputStream.java:75)
	at 
de.rub.nds.research.ssl.stack.tests.common.SSLServer.run(SSLServer.java:86)
	at java.lang.Thread.run(Thread.java:679)
Caused by: javax.crypto.BadPaddingException: Padding length invalid: 55
	at sun.security.ssl.CipherBox.removePadding(CipherBox.java:423)
	at sun.security.ssl.CipherBox.decrypt(CipherBox.java:271)
	at sun.security.ssl.InputRecord.decrypt(InputRecord.java:172)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:892)
	... 6 more





how it looks when dealing with 2048, 4096 bit RSA keys:
-------------------------------------------------------

*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
SESSION KEYGEN:
PreMaster Secret:
0000: 2B 05 89 91 6F F5 87 35   B9 8B 77 69 CF 83 8F CF  +...o..5..wi....
0010: 6F 23 37 C9 E3 2F A9 51   C7 9D 3B 81 37 CB 61 F3  o#7../.Q..;.7.a.
0020: CB 29 21 E9 05 B7 73 8B   7F 6D 69 91 51 31 35 33  .)!...s..mi.Q153
0030: E5 03 A9 69 D3 23 9B 13   F3 4B 67 89 FD C9 9B 4D  ...i.#...Kg....M
0040: A3 BB E5 AB 5D 85 D7 1D   79 8F 45 17 17 93 55 15  ....]...y.E...U.
0050: AD B7 17 33 CD 39 83 F7   6F 1F 4D EF A7 DD A5 55  ...3.9..o.M....U
0060: 0B A7 FB 99 33 09 00 03   01 1F EE 99 A8 6F C9 51  ....3........o.Q
0070: 7B 06 28 ED ED 34 84 65Finalizer, called close()
Finalizer, called closeInternal(true)
   8B 7E 0A D3 05 57 1B E7  ..(..4.e.....W..
0080: CA 80 FC 34 6D A4 3D 9D   B4 49 DB 85 24 71 3F CF  ...4m.=..I..$q?.
0090: 8C E6 CA 63 1F 01 2A                               ...c..*
Thread-2, handling exception: java.lang.ArrayIndexOutOfBoundsException: 64

========> 
========> 
========> Thread-2, SEND TLSv1 ALERT:  fatal, description = internal_error
========> 
========> 

Thread-2, WRITE: TLSv1 Alert, length = 2
Thread-2, called closeSocket()
javax.net.ssl.SSLException: java.lang.ArrayIndexOutOfBoundsException: 64
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1697)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1660)
	at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1643)
	at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1569)
	at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:113)
	at java.io.OutputStream.write(OutputStream.java:75)
	at 
de.rub.nds.research.ssl.stack.tests.common.SSLServer.run(SSLServer.java:86)
	at java.lang.Thread.run(Thread.java:679)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 64
	at com.sun.crypto.provider.TlsPrfGenerator.expand(TlsPrfGenerator.java:216)
	at com.sun.crypto.provider.TlsPrfGenerator.doPRF(TlsPrfGenerator.java:187)
	at com.sun.crypto.provider.TlsPrfGenerator.doPRF(TlsPrfGenerator.java:159)
	at 
com.sun.crypto.provider.TlsMasterSecretGenerator.engineGenerateKey(TlsMasterSecretGenerator.java:107)
	at javax.crypto.KeyGenerator.generateKey(KeyGenerator.java:516)
	at sun.security.ssl.Handshaker.calculateMasterSecret(Handshaker.java:769)
	at sun.security.ssl.Handshaker.calculateKeys(Handshaker.java:732)
	at 
sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:235)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:609)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:545)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:945)
	at 
sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1190)
	at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:657)
	at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:108)
	... 3 more


We only tested this with 1024, 2048, 4096 bit keys. 
Maybe a simple length check inside the expand function could solve the issue.


Regards,
Chris

______________________________________

Dipl.-Ing. Christopher Meyer

Horst Görtz Institute for IT-Security 
Chair for Network and Data Security 
Ruhr-University Bochum, Germany

Universitätsstr. 150, ID 2/415
D-44801 Bochum, Germany
http:// www.nds.rub.de

Phone: (+49) (0)234 / 32 - 29815
Fax: (+49) (0)234 / 32 - 14347





More information about the security-dev mailing list