Hi,
I am working on a Project where the communication between the clients and the servers shall be secured with a private PKI. Because the lifespan of the individual certificates is very long, nearly 20 years (not our decision) we thought that a regular rekey of the root ca and a renew of the hierarchy would be a good idea.
After the setup of the ca hierarchy and some initial tests i ran into a problem with the ssl handshake in java (1.6 and 7).
Setup
I did my tests with the following ca hierarchy:
First Generation Hierarchy:
RootCA1(self-signed) --->
IntermediateCA1 --->
Client
Second Generation Hierarchy:
RootCA2(self-signed) --->
IntermediateCA2 --->
Server
and for the renew a self-issued certificate (NewWithOld) that connects
RootCA1(SS) -->
RootCA2(SS) called
RootCA2(self-issued)
So basically the certificate chain for the server certificate is
RootCA1(SS) ---
RootCA2(SI) ---
IntermediateCA2 ---
Server
Now if my client calls the server the server sends its certificate chain until
RootCA2(SI) (omits
RootCA1(SS) ) which I think is fine. The client finds a trusted certificate (
RootCA1(SS) ) sends its Certificate Message, then sends the ClientKeyExchange Message and the Certificate Verify Message and I think on this messages the handshake fails.
--------------------
Client Side Logs
On the Client side I see in the logs:
***
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
main, WRITE: TLSv1 Handshake, length = 4083
SESSION KEYGEN:
PreMaster Secret:
0000: 03 01 AC EF 48 EB 4E B5 0C D2 70 4D 4B 7D D8 64 ....H.N...pMK..d
0010: 36 6B 3A 0F FB B3 25 A7 80 50 D0 CF 04 8E A4 59 6k:...%..P.....Y
0020: D2 79 B4 B6 BC 1B 0F 87 27 2F 0D 0E 9B B2 23 BB .y......'/....#.
CONNECTION KEYGEN:
Client Nonce:
0000: 4F 3D 39 8B 99 BC 5A C1 F3 55 72 64 EF C4 1C F5 O=9...Z..Urd....
0010: F7 FC 50 34 91 B0 25 AB 53 7F 13 39 44 8C CD 38 ..P4..%.S..9D..8
Server Nonce:
0000: 4F 3D 39 8B 4E 95 9E AC 3A 24 6C 2D F0 47 33 9A O=9.N...:$l-.G3.
0010: CB 75 29 6A 56 84 7A E2 3B 73 D4 5D FE 81 98 66 .u)jV.z.;s.]...f
Master Secret:
0000: 8B B1 0E 08 DE CA D4 2F 9B 92 DF 36 9B 3D 6A 2C ......./...6.=j,
0010: 01 0E C0 F6 C0 97 2A 61 31 D1 6F C8 3B E4 67 AD ......*a1.o.;.g.
0020: 02 B0 E9 84 7A A0 6B 6A 18 FF 85 CA 44 5B BC 69 ....z.kj....D[.i
Client MAC write Secret:
0000: 53 5D B5 D9 37 2C EC 48 42 98 0B 08 75 BC F8 6B S]..7,.HB...u..k
0010: 3B 41 A0 86 ;A..
Server MAC write Secret:
0000: DD 87 01 BA BB 92 7C 4D 62 37 EF 9D 9B B5 2A A4 .......Mb7....*.
0010: 8E C8 21 76 ..!v
Client write key:
0000: F2 AF 1E A9 7F 54 D6 5A 4F 72 F8 28 63 B1 7F 1E .....T.ZOr.(c...
Server write key:
0000: 04 C5 2F 4E AD 81 CA 1F 14 E8 CB 75 1F 9A 95 A4 ../N.......u....
Client write IV:
0000: D6 1B 56 F9 42 51 56 1F AB D6 88 2C 68 A1 11 6B ..V.BQV....,h..k
Server write IV:
0000: E0 C4 8D 1A 67 1C DA C4 80 69 D5 18 1C 1A 80 7D ....g....i......
*** CertificateVerify
main, WRITE: TLSv1 Handshake, length = 262
main, WRITE: TLSv1 Change Cipher Spec, length = 1
*** Finished
verify_data: { 1, 81, 68, 144, 225, 47, 165, 196, 156, 232, 251, 135 }
***
main, WRITE: TLSv1 Handshake, length = 48
main, waiting for close_notify or alert: state 1
main, Exception while waiting for close java.net.SocketException: Software caused connection abort: recv failed
main, handling exception: java.net.SocketException: Software caused connection abort: recv failed
%% Invalidated: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
------------------------------
Server side logs
On the server side I just see the end of the client certificate chain which ends with
RootCA1(SS) and then this exception:
***
http-bio-8443-exec-2, handling exception: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
%% Invalidated: [Session-2, TLS_RSA_WITH_AES_128_CBC_SHA]
http-bio-8443-exec-2, SEND TLSv1 ALERT: fatal, description = internal_error
http-bio-8443-exec-2, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 50 ......P
http-bio-8443-exec-2, called closeSocket()
http-bio-8443-exec-2, IOException in getSession(): javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
http-bio-8443-exec-2, called close()
http-bio-8443-exec-2, called closeInternal(true)
Finalizer, called close()
Finalizer, called closeInternal(true)
Finalizer, called close()
Finalizer, called closeInternal(true)
Configuration
The Client Keystore contains
RootCA1(SS),
IntermediateCA1,
Client and windows and portacle can build the chain. The client truststore just contains
RootCA1(SS).
The Server Keystores contains
RootCA1(SS),
RootCA2(SI),
IntermediateCA2,
Server and windows and portacle can build the chain but keytool also just displays it until
RootCA2(S1). The server truststore just contains
RootCA1(SS). Unlimited strength policies files are installed and working. All certificates use BasicConstraints, Root CAs got a unlimited path length (wanted to test the behaviour with pathlength 1 later), intermediate got pathlength 0 and client and server are end entities. They also all use Subject- and AuthorityKeyIdentifier.
I initially tried it with 1.6.0_24 but after reading this blog https://blogs.oracle.com/xuelei/entry/undertanding_self_issued_certificate which states that self-issued certificates should be supported i tried it with 1.7.0_03 but got exactly the same exception.
Anybody got an luck with self-issued certificates with java 6 or 7? I mean I am not really surprised that I ran into this problems but I thought it should work after reading that blog entry. I could not find really much help online because self-issued is commonly misused as a synonym for self-signed.
Edited by: 915046 on 16.02.2012 10:26 added some italics for readability
Edited by: 915046 on 16.02.2012 10:43 fixed the link to the blog