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


Reply via email to