KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > maverick > ssl > SSLHandshakeProtocol


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.maverick.ssl;
21
22 import java.io.ByteArrayInputStream JavaDoc;
23 import java.io.ByteArrayOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.math.BigInteger JavaDoc;
26 import java.text.MessageFormat JavaDoc;
27
28 //#ifdef DEBUG
29
import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 //#endif
32

33 import com.maverick.crypto.asn1.ASN1Sequence;
34 import com.maverick.crypto.asn1.DERInputStream;
35 import com.maverick.crypto.asn1.x509.CertificateException;
36 import com.maverick.crypto.asn1.x509.X509Certificate;
37 import com.maverick.crypto.asn1.x509.X509CertificateStructure;
38 import com.maverick.crypto.digests.MD5Digest;
39 import com.maverick.crypto.digests.SHA1Digest;
40 import com.maverick.crypto.publickey.PublicKey;
41 import com.maverick.crypto.publickey.Rsa;
42 import com.maverick.crypto.publickey.RsaPublicKey;
43
44 /**
45  *
46  * @author Lee David Painter <a HREF="mailto:lee@3sp.com">&lt;lee@3sp.com&gt;</a>
47  */

48 class SSLHandshakeProtocol {
49
50     final static int HANDSHAKE_PROTOCOL_MSG = 22;
51
52     final static int HELLO_REQUEST_MSG = 0;
53     final static int CLIENT_HELLO_MSG = 1;
54     final static int SERVER_HELLO_MSG = 2;
55
56     final static int CERTIFICATE_MSG = 11;
57     final static int KEY_EXCHANGE_MSG = 12;
58
59     final static int CERTIFICATE_REQUEST_MSG = 13;
60     final static int SERVER_HELLO_DONE_MSG = 14;
61
62     final static int CERTIFICATE_VERIFY_MSG = 15;
63     final static int CLIENT_KEY_EXCHANGE_MSG = 16;
64     final static int FINISHED_MSG = 20;
65
66     final static int HANDSHAKE_PENDING_OR_COMPLETE = -1;
67
68     SSLContext context;
69     SSLTransportImpl socket;
70
71     MD5Digest handshakeMD5 = new MD5Digest();
72     SHA1Digest handshakeSHA1 = new SHA1Digest();
73
74     // The session components as selected by the server
75
SSLCipherSuiteID cipherSuiteID;
76     int compressionID;
77     byte[] sessionID;
78     int majorVersion;
79     int minorVersion;
80     byte[] clientRandom;
81     byte[] serverRandom;
82     byte[] premasterSecret;
83     byte[] masterSecret;
84
85     X509Certificate x509;
86
87     SSLCipherSuite pendingCipherSuite;
88     boolean wantsClientAuth = false;
89     int currentHandshakeStep = HANDSHAKE_PENDING_OR_COMPLETE;
90
91     // #ifdef DEBUG
92
Log log = LogFactory.getLog(SSLHandshakeProtocol.class);
93
94     // #endif
95

96     public SSLHandshakeProtocol(SSLTransportImpl socket, SSLContext context) throws IOException JavaDoc {
97         this.socket = socket;
98         this.context = context;
99
100     }
101
102     boolean isComplete() {
103         return currentHandshakeStep == HANDSHAKE_PENDING_OR_COMPLETE;
104     }
105
106     void processMessage(byte[] fragment, int off, int len) throws SSLException {
107
108         ByteArrayInputStream JavaDoc reader = new ByteArrayInputStream JavaDoc(fragment, off, len);
109
110         // Update the handshake hashes
111
updateHandshakeHashes(fragment);
112
113         while (reader.available() > 0 && !isComplete()) {
114
115             int type = reader.read();
116
117             int length = (reader.read() & 0xFF) << 16 | (reader.read() & 0xFF) << 8 | (reader.read() & 0xFF);
118
119             // #ifdef DEBUG
120
log.debug(MessageFormat.format(Messages.getString("SSLHandshakeProtocol.processingType"), new Object JavaDoc[] { new Integer JavaDoc(type), new Long JavaDoc(length) })); //$NON-NLS-1$
121
// #endif
122

123             byte[] msg = new byte[length];
124             try {
125                 reader.read(msg);
126             } catch (IOException JavaDoc ex) {
127                 throw new SSLException(SSLException.INTERNAL_ERROR, ex.getMessage() == null ? ex.getClass().getName()
128                     : ex.getMessage());
129             }
130
131             switch (type) {
132                 case HELLO_REQUEST_MSG:
133
134                     // #ifdef DEBUG
135
log.debug(Messages.getString("SSLHandshakeProtocol.receivedHELLO")); //$NON-NLS-1$
136
// #endif
137
/**
138                      * If we receive a hello request then a handshake must be
139                      * re-negotiated. But ignore it if were already performing a
140                      * handshake operation
141                      */

142                     if (currentHandshakeStep == HANDSHAKE_PENDING_OR_COMPLETE) {
143                         startHandshake();
144                     }
145                     break;
146
147                 case SERVER_HELLO_MSG:
148
149                     // #ifdef DEBUG
150
log.debug(Messages.getString("SSLHandshakeProtocol.receivedServerHELLO")); //$NON-NLS-1$
151
// #endif
152

153                     if (currentHandshakeStep != CLIENT_HELLO_MSG) {
154                         throw new SSLException(SSLException.PROTOCOL_VIOLATION,
155                             MessageFormat.format(Messages.getString("SSLHandshakeProtocol.receivedUnexpectedServerHello"), new Object JavaDoc[] { new Integer JavaDoc(currentHandshakeStep) })); //$NON-NLS-1$
156
}
157
158                     onServerHelloMsg(msg);
159                     break;
160
161                 case CERTIFICATE_MSG:
162
163                     // #ifdef DEBUG
164
log.debug(Messages.getString("SSLHandshakeProtocol.receivedServerCertificate")); //$NON-NLS-1$
165
// #endif
166

167                     if (currentHandshakeStep != SERVER_HELLO_MSG) {
168                         throw new SSLException(SSLException.PROTOCOL_VIOLATION,
169                             MessageFormat.format(Messages.getString("SSLHandshakeProtocol.unexpectedCertificateMessageReceived"), new Object JavaDoc[] { new Integer JavaDoc(currentHandshakeStep) })); //$NON-NLS-1$
170
}
171                     onCertificateMsg(msg);
172                     break;
173
174                 case KEY_EXCHANGE_MSG:
175
176                     // #ifdef DEBUG
177
log.debug(Messages.getString("SSLHandshakeProtocol.receivedUnsupportedServerKEX")); //$NON-NLS-1$
178
// #endif
179

180                     throw new SSLException(SSLException.UNSUPPORTED_OPERATION,
181                         Messages.getString("SSLHandshakeProtocol.kexNotSupported")); //$NON-NLS-1$
182

183                 case CERTIFICATE_REQUEST_MSG:
184
185                     // #ifdef DEBUG
186
log.debug(Messages.getString("SSLHandshakeProtocol.receivedUnsupportedClientCert")); //$NON-NLS-1$
187
// #endif
188

189                     wantsClientAuth = true;
190                     break;
191
192                 case SERVER_HELLO_DONE_MSG:
193
194                     // #ifdef DEBUG
195
log.debug(Messages.getString("SSLHandshakeProtocol.helloDone")); //$NON-NLS-1$
196
// #endif
197

198                     if (currentHandshakeStep != CERTIFICATE_MSG) {
199                         throw new SSLException(SSLException.PROTOCOL_VIOLATION,
200                             MessageFormat.format(Messages.getString("SSLHandshakeProtocol.unexpectedServerHelloDone"), new Object JavaDoc[] { new Integer JavaDoc(currentHandshakeStep) })); //$NON-NLS-1$
201
}
202
203                     if (wantsClientAuth) {
204
205                         // #ifdef DEBUG
206
log.debug(Messages.getString("SSLHandshakeProtocol.sendingNoCert")); //$NON-NLS-1$
207
// #endif
208
socket.sendMessage(SSLTransportImpl.ALERT_PROTOCOL, new byte[] { (byte) SSLTransportImpl.WARNING_ALERT,
209                             (byte) SSLException.NO_CERTIFICATE });
210                     }
211                     onServerHelloDoneMsg();
212                     break;
213
214                 case FINISHED_MSG:
215
216                     // #ifdef DEBUG
217
log.debug(Messages.getString("SSLHandshakeProtocol.receivedServerFinished")); //$NON-NLS-1$
218
// #endif
219

220                     if (currentHandshakeStep != FINISHED_MSG) {
221                         throw new SSLException(SSLException.PROTOCOL_VIOLATION);
222                     }
223
224                     currentHandshakeStep = HANDSHAKE_PENDING_OR_COMPLETE;
225
226                     break;
227
228                 default:
229
230             }
231         }
232     }
233     
234     public X509Certificate getCertificate() {
235         return x509;
236     }
237
238     private void sendMessage(int type, byte[] data) throws SSLException {
239
240         ByteArrayOutputStream JavaDoc msg = new ByteArrayOutputStream JavaDoc();
241
242         try {
243             msg.write(type);
244             msg.write((data.length >> 16) & 0xFF);
245             msg.write((data.length >> 8) & 0xFF);
246             msg.write(data.length);
247             msg.write(data);
248         } catch (IOException JavaDoc ex) {
249             throw new SSLException(SSLException.INTERNAL_ERROR, ex.getMessage() == null ? ex.getClass().getName() : ex.getMessage());
250         }
251
252         byte[] m = msg.toByteArray();
253
254         // Update the handshake hashes if its anything but the FINISHED_MSG
255
if (type != FINISHED_MSG) {
256             updateHandshakeHashes(m);
257
258         }
259         socket.sendMessage(HANDSHAKE_PROTOCOL_MSG, m);
260     }
261
262     public void startHandshake() throws SSLException {
263
264         if (currentHandshakeStep != HANDSHAKE_PENDING_OR_COMPLETE) {
265             throw new SSLException(SSLException.PROTOCOL_VIOLATION, Messages.getString("SSLHandshakeProtocol.alreadyInProgress")); //$NON-NLS-1$
266
}
267
268         // #ifdef DEBUG
269
log.debug(Messages.getString("SSLHandshakeProtocol.starting")); //$NON-NLS-1$
270
// #endif
271

272         sendClientHello();
273     }
274
275     private void calculateMasterSecret() throws SSLException {
276
277         // #ifdef DEBUG
278
log.debug(Messages.getString("SSLHandshakeProtocol.calculatingMasterSecret")); //$NON-NLS-1$
279
// #endif
280

281         try {
282             MD5Digest md5 = new MD5Digest();
283             SHA1Digest sha1 = new SHA1Digest();
284
285             ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc();
286
287             String JavaDoc[] mixers = new String JavaDoc[] { "A", "BB", "CCC" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
288

289             for (int i = 0; i < mixers.length; i++) {
290                 md5.reset();
291                 sha1.reset();
292                 sha1.update(mixers[i].getBytes(), 0, mixers[i].getBytes().length);
293                 sha1.update(premasterSecret, 0, premasterSecret.length);
294                 sha1.update(clientRandom, 0, clientRandom.length);
295                 sha1.update(serverRandom, 0, serverRandom.length);
296
297                 md5.update(premasterSecret, 0, premasterSecret.length);
298                 byte[] tmp = new byte[sha1.getDigestSize()];
299                 sha1.doFinal(tmp, 0);
300
301                 md5.update(tmp, 0, tmp.length);
302
303                 tmp = new byte[md5.getDigestSize()];
304                 md5.doFinal(tmp, 0);
305
306                 out.write(tmp);
307
308             }
309
310             masterSecret = out.toByteArray();
311         } catch (IOException JavaDoc ex) {
312             throw new SSLException(SSLException.INTERNAL_ERROR, ex.getMessage() == null ? ex.getClass().getName() : ex.getMessage());
313         }
314
315     }
316
317     private void calculatePreMasterSecret() {
318
319         // #ifdef DEBUG
320
log.debug(Messages.getString("SSLHandshakeProtocol.generatingPreMasterSecret")); //$NON-NLS-1$
321
// #endif
322

323         premasterSecret = new byte[48];
324         context.getRND().nextBytes(premasterSecret);
325         premasterSecret[0] = (byte) SSLTransportImpl.VERSION_MAJOR;
326         premasterSecret[1] = (byte) SSLTransportImpl.VERSION_MINOR;
327
328     }
329
330     private void debugBytes(byte[] b, String JavaDoc s) {
331
332         System.out.print(s + ": "); //$NON-NLS-1$
333

334         for (int i = 0; i < b.length; i++) {
335
336             System.out.print(Integer.toHexString((int) (b[i] & 0xFF)));
337
338         }
339
340         System.out.println();
341
342     }
343
344     private void onServerHelloDoneMsg() throws SSLException {
345
346         // Generate the premaster secret
347
calculatePreMasterSecret();
348
349         byte[] secret = null;
350
351         try {
352
353             // Encrypt the premaster secret
354
BigInteger JavaDoc input = new BigInteger JavaDoc(1, premasterSecret);
355
356             PublicKey key = x509.getPublicKey();
357
358             if (key instanceof RsaPublicKey) {
359
360                 BigInteger JavaDoc padded = Rsa.padPKCS1(input, 0x02, 128);
361                 BigInteger JavaDoc s = Rsa.doPublic(padded, ((RsaPublicKey) key).getModulus(), ((RsaPublicKey) key).getPublicExponent());
362
363                 secret = s.toByteArray();
364             } else {
365                 throw new SSLException(SSLException.UNSUPPORTED_CERTIFICATE);
366             }
367         } catch (CertificateException ex) {
368             throw new SSLException(SSLException.UNSUPPORTED_CERTIFICATE, ex.getMessage());
369         }
370
371         if (secret[0] == 0) {
372             byte[] tmp = new byte[secret.length - 1];
373             System.arraycopy(secret, 1, tmp, 0, secret.length - 1);
374             secret = tmp;
375         }
376
377         sendMessage(CLIENT_KEY_EXCHANGE_MSG, secret);
378
379         // Calculate the master secret
380
calculateMasterSecret();
381
382         // #ifdef DEBUG
383
log.debug(Messages.getString("SSLHandshakeProtocol.generatingKeyData")); //$NON-NLS-1$
384
// #endif
385

386         // Generate the keys etc and put the cipher into use
387
byte[] keydata;
388         int length = 0;
389
390         length += pendingCipherSuite.getKeyLength() * 2;
391         length += pendingCipherSuite.getMACLength() * 2;
392         length += pendingCipherSuite.getIVLength() * 2;
393
394         ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc();
395
396         MD5Digest md5 = new MD5Digest();
397         SHA1Digest sha1 = new SHA1Digest();
398
399         int turn = 0;
400         while (out.size() < length) {
401             md5.reset();
402             sha1.reset();
403
404             for (int i = 0; i <= turn; i++) {
405                 sha1.update((byte) ('A' + turn));
406             }
407
408             sha1.update(masterSecret, 0, masterSecret.length);
409             sha1.update(serverRandom, 0, serverRandom.length);
410             sha1.update(clientRandom, 0, clientRandom.length);
411
412             md5.update(masterSecret, 0, masterSecret.length);
413             byte[] tmp = new byte[sha1.getDigestSize()];
414             sha1.doFinal(tmp, 0);
415             md5.update(tmp, 0, tmp.length);
416             tmp = new byte[md5.getDigestSize()];
417             md5.doFinal(tmp, 0);
418
419             // Write out a block of key data
420
out.write(tmp, 0, tmp.length);
421
422             turn++;
423         }
424
425         keydata = out.toByteArray();
426
427         ByteArrayInputStream JavaDoc in = new ByteArrayInputStream JavaDoc(keydata);
428
429         byte[] encryptKey = new byte[pendingCipherSuite.getKeyLength()];
430         byte[] encryptIV = new byte[pendingCipherSuite.getIVLength()];
431         byte[] encryptMAC = new byte[pendingCipherSuite.getMACLength()];
432         byte[] decryptKey = new byte[pendingCipherSuite.getKeyLength()];
433         byte[] decryptIV = new byte[pendingCipherSuite.getIVLength()];
434         byte[] decryptMAC = new byte[pendingCipherSuite.getMACLength()];
435
436         try {
437             in.read(encryptMAC);
438             in.read(decryptMAC);
439             in.read(encryptKey);
440             in.read(decryptKey);
441             in.read(encryptIV);
442             in.read(decryptIV);
443         } catch (IOException JavaDoc ex) {
444             throw new SSLException(SSLException.INTERNAL_ERROR, ex.getMessage() == null ? ex.getClass().getName() : ex.getMessage());
445
446         }
447
448         pendingCipherSuite.init(encryptKey, encryptIV, encryptMAC, decryptKey, decryptIV, decryptMAC);
449
450         currentHandshakeStep = SERVER_HELLO_DONE_MSG;
451
452         // Send the change cipher spec
453
socket.sendCipherChangeSpec(pendingCipherSuite);
454
455         // Send the finished msg
456
sendHandshakeFinished();
457
458     }
459
460     SSLCipherSuite getPendingCipherSuite() {
461         return pendingCipherSuite;
462     }
463
464     void updateHandshakeHashes(byte[] data) {
465
466         // #ifdef DEBUG
467
log.debug(Messages.getString("SSLHandshakeProtocol.updatingHandshakeHashes")); //$NON-NLS-1$
468
// #endif
469

470         handshakeMD5.update(data, 0, data.length);
471         handshakeSHA1.update(data, 0, data.length);
472     }
473
474     private void completeHandshakeHashes() {
475
476         // #ifdef DEBUG
477
log.debug(Messages.getString("SSLHandshakeProtocol.completingHandshakeHashes")); //$NON-NLS-1$
478
// #endif
479

480         // Complete the handshale hashes
481
handshakeMD5.update((byte) 0x43);
482         handshakeMD5.update((byte) 0x4c);
483         handshakeMD5.update((byte) 0x4e);
484         handshakeMD5.update((byte) 0x54);
485
486         handshakeMD5.update(masterSecret, 0, masterSecret.length);
487
488         for (int i = 0; i < 48; i++) {
489             handshakeMD5.update((byte) 0x36);
490         }
491
492         byte[] tmp = new byte[handshakeMD5.getDigestSize()];
493         handshakeMD5.doFinal(tmp, 0);
494
495         handshakeMD5.reset();
496
497         // #ifdef DEBUG
498
log.debug(MessageFormat.format(Messages.getString("SSLHandshakeProtocol.masterSecret"), new Object JavaDoc[] { new Long JavaDoc(masterSecret.length), String.valueOf(masterSecret[0]) })); //$NON-NLS-1$
499
// #endif
500

501         handshakeMD5.update(masterSecret, 0, masterSecret.length);
502         for (int i = 0; i < 48; i++) {
503             handshakeMD5.update((byte) 0x5c);
504         }
505
506         handshakeMD5.update(tmp, 0, tmp.length);
507
508         handshakeSHA1.update((byte) 0x43);
509         handshakeSHA1.update((byte) 0x4c);
510         handshakeSHA1.update((byte) 0x4e);
511         handshakeSHA1.update((byte) 0x54);
512
513         handshakeSHA1.update(masterSecret, 0, masterSecret.length);
514         for (int i = 0; i < 40; i++) {
515             handshakeSHA1.update((byte) 0x36);
516         }
517
518         tmp = new byte[handshakeSHA1.getDigestSize()];
519         handshakeSHA1.doFinal(tmp, 0);
520
521         handshakeSHA1.reset();
522         handshakeSHA1.update(masterSecret, 0, masterSecret.length);
523         for (int i = 0; i < 40; i++) {
524             handshakeSHA1.update((byte) 0x5c);
525         }
526
527         handshakeSHA1.update(tmp, 0, tmp.length);
528
529     }
530
531     private void sendHandshakeFinished() throws SSLException {
532
533         completeHandshakeHashes();
534
535         // #ifdef DEBUG
536
log.debug("Sending client FINISHED"); //$NON-NLS-1$
537
// #endif
538

539         byte[] msg = new byte[handshakeMD5.getDigestSize() + handshakeSHA1.getDigestSize()];
540
541         handshakeMD5.doFinal(msg, 0);
542         handshakeSHA1.doFinal(msg, handshakeMD5.getDigestSize());
543
544         sendMessage(FINISHED_MSG, msg);
545
546         currentHandshakeStep = FINISHED_MSG;
547
548     }
549
550     private void onCertificateMsg(byte[] msg) throws SSLException {
551
552         ByteArrayInputStream JavaDoc in = new ByteArrayInputStream JavaDoc(msg);
553
554         // Get the length of the certificate chain
555
int length2 = (in.read() & 0xFF) << 16 | (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
556
557         try {
558
559             boolean trusted = false;
560
561             X509Certificate chainCert;
562             while (in.available() > 0 && !trusted) {
563                 // The length of the next certificate (we dont need this as rthe
564
// DERInputStream does the work
565
int certlen = (in.read() & 0xFF) << 16 | (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
566
567                 // Now read the certificate
568
DERInputStream der = new DERInputStream(in);
569
570                 ASN1Sequence certificate = (ASN1Sequence) der.readObject();
571
572                 // Get the x509 certificate structure
573
chainCert = new X509Certificate(X509CertificateStructure.getInstance(certificate));
574
575                 if (x509 == null)
576                     x509 = chainCert;
577
578                 // Verify if this part of the chain is trusted
579
try {
580                     trusted = context.getTrustedCACerts().isTrustedCertificate(chainCert,
581                         context.isInvalidCertificateAllowed(),
582                         context.isUntrustedCertificateAllowed());
583                 } catch (SSLException ex1) {
584                     // #ifdef DEBUG
585
log.warn(Messages.getString("SSLHandshakeProtocol.failedToVerifyCertAgainstTruststore"), ex1); //$NON-NLS-1$
586
// #endif
587
}
588             }
589
590             if (!trusted)
591                 throw new SSLException(SSLException.BAD_CERTIFICATE,
592                     Messages.getString("SSLHandshakeProtocol.certInvalidOrUntrusted")); //$NON-NLS-1$
593

594         } catch (IOException JavaDoc ex) {
595             throw new SSLException(SSLException.INTERNAL_ERROR, ex.getMessage());
596         }
597
598         // #ifdef DEBUG
599
log.debug(Messages.getString("SSLHandshakeProtocol.x509Cert")); //$NON-NLS-1$
600

601         log.debug(Messages.getString("SSLHandshakeProtocol.x509Cert.subject") + x509.getSubjectDN()); //$NON-NLS-1$
602

603         log.debug(Messages.getString("SSLHandshakeProtocol.x509Cert.issuer") + x509.getIssuerDN()); //$NON-NLS-1$
604
// #endif
605

606         currentHandshakeStep = CERTIFICATE_MSG;
607
608     }
609
610     private void onServerHelloMsg(byte[] msg) throws SSLException {
611
612         try {
613             ByteArrayInputStream JavaDoc in = new ByteArrayInputStream JavaDoc(msg);
614
615             majorVersion = in.read();
616             minorVersion = in.read();
617
618             serverRandom = new byte[32];
619             in.read(serverRandom);
620
621             sessionID = new byte[(in.read() & 0xFF)];
622             in.read(sessionID);
623
624             cipherSuiteID = new SSLCipherSuiteID(in.read(), in.read());
625
626             pendingCipherSuite = (SSLCipherSuite) context.getCipherSuiteClass(cipherSuiteID).newInstance();
627
628             compressionID = in.read();
629
630             currentHandshakeStep = SERVER_HELLO_MSG;
631         } catch (IllegalAccessException JavaDoc ex) {
632             throw new SSLException(SSLException.INTERNAL_ERROR, ex.getMessage() == null ? ex.getClass().getName() : ex.getMessage());
633
634         } catch (InstantiationException JavaDoc ex) {
635             throw new SSLException(SSLException.INTERNAL_ERROR, ex.getMessage() == null ? ex.getClass().getName() : ex.getMessage());
636         } catch (IOException JavaDoc ex) {
637             throw new SSLException(SSLException.INTERNAL_ERROR, ex.getMessage() == null ? ex.getClass().getName() : ex.getMessage());
638         }
639
640     }
641
642     private void sendClientHello() throws SSLException {
643
644         // #ifdef DEBUG
645
log.debug(Messages.getString("SSLHandshakeProtocol.sendingClientHello")); //$NON-NLS-1$
646
// #endif
647

648         ByteArrayOutputStream JavaDoc msg = new ByteArrayOutputStream JavaDoc();
649
650         try {
651             clientRandom = new byte[32];
652             context.getRND().nextBytes(clientRandom);
653             long time = System.currentTimeMillis();
654             clientRandom[0] = (byte) ((time >> 24) & 0xFF);
655             clientRandom[1] = (byte) ((time >> 16) & 0xFF);
656             clientRandom[2] = (byte) ((time >> 8) & 0xFF);
657             clientRandom[3] = (byte) (time & 0xFF);
658
659             // Write the version
660
msg.write(SSLTransportImpl.VERSION_MAJOR);
661             msg.write(SSLTransportImpl.VERSION_MINOR);
662
663             // Write the random bytes
664
msg.write(clientRandom);
665
666             // Write the session identifier - currently were not caching so zero
667
// length
668
msg.write(0);
669
670             // Write the cipher ids - TODO: we need to set the preferred as
671
// first
672
SSLCipherSuiteID[] ids = context.getCipherSuiteIDs();
673             msg.write(0);
674             msg.write(ids.length * 2);
675
676             for (int i = 0; i < ids.length; i++) {
677                 msg.write(ids[i].id1);
678                 msg.write(ids[i].id2);
679             }
680
681             // Compression - no compression is currently supported
682
msg.write(1);
683             msg.write(0);
684         } catch (IOException JavaDoc ex) {
685             throw new SSLException(SSLException.INTERNAL_ERROR, ex.getMessage() == null ? ex.getClass().getName() : ex.getMessage());
686         }
687
688         sendMessage(CLIENT_HELLO_MSG, msg.toByteArray());
689
690         currentHandshakeStep = CLIENT_HELLO_MSG;
691     }
692 }
693
Popular Tags