001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Boris Kuznetsov
020: * @version $Revision$
021: */package org.apache.harmony.xnet.provider.jsse;
022:
023: import org.apache.harmony.xnet.provider.jsse.SSLv3Constants;
024: import org.apache.harmony.xnet.provider.jsse.SSLSessionImpl;
025: import org.apache.harmony.xnet.provider.jsse.ProtocolVersion;
026:
027: import java.io.IOException;
028: import java.math.BigInteger;
029: import java.security.AccessController;
030: import java.security.KeyFactory;
031: import java.security.KeyPair;
032: import java.security.KeyPairGenerator;
033: import java.security.NoSuchAlgorithmException;
034: import java.security.PrivateKey;
035: import java.security.PrivilegedExceptionAction;
036: import java.security.PublicKey;
037: import java.security.cert.CertificateException;
038: import java.security.cert.X509Certificate;
039: import java.security.interfaces.RSAPublicKey;
040:
041: import java.util.Arrays;
042:
043: import javax.crypto.Cipher;
044: import javax.crypto.KeyAgreement;
045: import javax.crypto.interfaces.DHPublicKey;
046: import javax.crypto.spec.DHParameterSpec;
047: import javax.crypto.spec.DHPublicKeySpec;
048: import javax.net.ssl.X509ExtendedKeyManager;
049: import javax.net.ssl.X509KeyManager;
050: import javax.net.ssl.X509TrustManager;
051:
052: /**
053: * Server side handshake protocol implementation.
054: * Handshake protocol operates on top of the Record Protocol.
055: * It responsible for negotiating a session.
056: *
057: * The implementation proceses inbound client handshake messages,
058: * creates and sends respond messages. Outbound messages are supplied
059: * to Record Protocol. Detected errors are reported to the Alert protocol.
060: *
061: * @see TLS 1.0 spec., 7.4. Handshake protocol.
062: * (http://www.ietf.org/rfc/rfc2246.txt)
063: *
064: */
065: public class ServerHandshakeImpl extends HandshakeProtocol {
066:
067: // private key used in key exchange
068: private PrivateKey privKey;
069:
070: /**
071: * Creates Server Handshake Implementation
072: *
073: * @param owner
074: */
075: public ServerHandshakeImpl(Object owner) {
076: super (owner);
077: status = NEED_UNWRAP;
078: }
079:
080: /**
081: * Start session negotiation
082: * @param session
083: */
084: public void start() {
085: if (session == null) { // initial handshake
086: status = NEED_UNWRAP;
087: return; // wait client hello
088: }
089: if (clientHello != null && this .status != FINISHED) {
090: // current negotiation has not completed
091: return; // ignore
092: }
093:
094: // renegotiation
095: sendHelloRequest();
096: status = NEED_UNWRAP;
097: }
098:
099: /**
100: * Proceses inbound handshake messages
101: * @param bytes
102: */
103: public void unwrap(byte[] bytes) {
104:
105: io_stream.append(bytes);
106: while (io_stream.available() > 0) {
107: int handshakeType;
108: int length;
109: io_stream.mark();
110: try {
111: handshakeType = io_stream.read();
112: length = io_stream.readUint24();
113: if (io_stream.available() < length) {
114: io_stream.reset();
115: return;
116: }
117:
118: switch (handshakeType) {
119: case 1: // CLIENT_HELLO
120: if (clientHello != null && this .status != FINISHED) {
121: // Client hello has been received during handshake
122: unexpectedMessage();
123: return;
124: }
125: // if protocol planed to send Hello Request message
126: // - cancel this demand.
127: needSendHelloRequest = false;
128: clientHello = new ClientHello(io_stream, length);
129: if (nonBlocking) {
130: delegatedTasks
131: .add(new DelegatedTask(
132: new PrivilegedExceptionAction() {
133: public Object run()
134: throws Exception {
135: processClientHello();
136: return null;
137: }
138: }, this , AccessController
139: .getContext()));
140: return;
141: }
142: processClientHello();
143: break;
144:
145: case 11: // CLIENT CERTIFICATE
146: if (isResuming || certificateRequest == null
147: || serverHelloDone == null
148: || clientCert != null) {
149: unexpectedMessage();
150: return;
151: }
152: clientCert = new CertificateMessage(io_stream,
153: length);
154: if (clientCert.certs.length == 0) {
155: if (parameters.getNeedClientAuth()) {
156: fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
157: "HANDSHAKE FAILURE: no client certificate received");
158: }
159: } else {
160: String authType = clientCert.certs[0]
161: .getPublicKey().getAlgorithm();
162: try {
163: parameters.getTrustManager()
164: .checkClientTrusted(
165: clientCert.certs, authType);
166: } catch (CertificateException e) {
167: fatalAlert(AlertProtocol.BAD_CERTIFICATE,
168: "Untrusted Client Certificate ", e);
169: }
170: session.peerCertificates = clientCert.certs;
171: }
172: break;
173:
174: case 15: // CERTIFICATE_VERIFY
175: if (isResuming
176: || clientKeyExchange == null
177: || clientCert == null
178: || clientKeyExchange.isEmpty() //client certificate
179: // contains fixed DH
180: // parameters
181: || certificateVerify != null
182: || changeCipherSpecReceived) {
183: unexpectedMessage();
184: return;
185: }
186: certificateVerify = new CertificateVerify(
187: io_stream, length);
188:
189: DigitalSignature ds = new DigitalSignature(
190: session.cipherSuite.keyExchange);
191: ds.init(serverCert.certs[0]);
192: byte[] md5_hash = null;
193: byte[] sha_hash = null;
194:
195: if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT
196: || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA
197: || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_RSA
198: || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_RSA_EXPORT) {
199: md5_hash = io_stream.getDigestMD5withoutLast();
200: sha_hash = io_stream.getDigestSHAwithoutLast();
201: } else if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS
202: || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT) {
203: sha_hash = io_stream.getDigestSHAwithoutLast();
204: } else if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon
205: || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {
206: }
207: ds.setMD5(md5_hash);
208: ds.setSHA(sha_hash);
209: if (!ds
210: .verifySignature(certificateVerify.signedHash)) {
211: fatalAlert(AlertProtocol.DECRYPT_ERROR,
212: "DECRYPT ERROR: CERTIFICATE_VERIFY incorrect signature");
213: }
214: break;
215: case 16: // CLIENT_KEY_EXCHANGE
216: if (isResuming
217: || serverHelloDone == null
218: || clientKeyExchange != null
219: || (clientCert == null && parameters
220: .getNeedClientAuth())) {
221: unexpectedMessage();
222: return;
223: }
224: if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA
225: || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
226: clientKeyExchange = new ClientKeyExchange(
227: io_stream, length,
228: serverHello.server_version[1] == 1,
229: true);
230: Cipher c = null;
231: try {
232: c = Cipher
233: .getInstance("RSA/ECB/PKCS1Padding");
234: c.init(Cipher.DECRYPT_MODE, privKey);
235: preMasterSecret = c
236: .doFinal(clientKeyExchange.exchange_keys);
237: // check preMasterSecret:
238: if (preMasterSecret.length != 48
239: || preMasterSecret[0] != clientHello.client_version[0]
240: || preMasterSecret[1] != clientHello.client_version[1]) {
241: // incorrect preMasterSecret
242: // prevent an attack (see TLS 1.0 spec., 7.4.7.1.)
243: preMasterSecret = new byte[48];
244: parameters.getSecureRandom().nextBytes(
245: preMasterSecret);
246: }
247: } catch (Exception e) {
248: fatalAlert(AlertProtocol.INTERNAL_ERROR,
249: "INTERNAL ERROR", e);
250: }
251: } else { // diffie hellman key exchange
252: clientKeyExchange = new ClientKeyExchange(
253: io_stream, length,
254: serverHello.server_version[1] == 1,
255: false);
256: if (clientKeyExchange.isEmpty()) {
257: // TODO check that client cert. DH params
258: // matched server cert. DH params
259:
260: // client cert. contains fixed DH parameters
261: preMasterSecret = ((DHPublicKey) clientCert.certs[0]
262: .getPublicKey()).getY()
263: .toByteArray();
264: } else {
265: PublicKey clientPublic;
266: KeyAgreement agreement;
267: try {
268: KeyFactory kf = null;
269: try {
270: kf = KeyFactory.getInstance("DH");
271: } catch (NoSuchAlgorithmException ee) {
272: kf = KeyFactory
273: .getInstance("DiffieHellman");
274: }
275: try {
276: agreement = KeyAgreement
277: .getInstance("DH");
278: } catch (NoSuchAlgorithmException ee) {
279: agreement = KeyAgreement
280: .getInstance("DiffieHellman");
281: }
282: clientPublic = kf
283: .generatePublic(new DHPublicKeySpec(
284: new BigInteger(
285: 1,
286: clientKeyExchange.exchange_keys),
287: serverKeyExchange.par1,
288: serverKeyExchange.par2));
289: agreement.init(privKey);
290: agreement.doPhase(clientPublic, true);
291: preMasterSecret = agreement
292: .generateSecret();
293: } catch (Exception e) {
294: fatalAlert(
295: AlertProtocol.INTERNAL_ERROR,
296: "INTERNAL ERROR", e);
297: return;
298: }
299: }
300: }
301:
302: computerMasterSecret();
303: break;
304:
305: case 20: // FINISHED
306: if (!isResuming && !changeCipherSpecReceived) {
307: unexpectedMessage();
308: return;
309: }
310:
311: clientFinished = new Finished(io_stream, length);
312: verifyFinished(clientFinished.getData());
313: parameters.getServerSessionContext().putSession(
314: session);
315: if (!isResuming) {
316: sendChangeCipherSpec();
317: } else {
318: session.lastAccessedTime = System
319: .currentTimeMillis();
320: status = FINISHED;
321: }
322: break;
323: default:
324: unexpectedMessage();
325: return;
326: }
327: } catch (IOException e) {
328: // io stream dosn't contain complete handshake message
329: io_stream.reset();
330: return;
331: }
332: }
333: }
334:
335: /**
336: * Processes SSLv2 Hello message
337: * @ see TLS 1.0 spec., E.1. Version 2 client hello
338: * @param bytes
339: */
340: public void unwrapSSLv2(byte[] bytes) {
341: try {
342: io_stream.append(bytes);
343: io_stream.mark();
344: try {
345: clientHello = new ClientHello(io_stream);
346: } catch (IOException e) {
347: io_stream.reset();
348: return;
349: }
350: if (nonBlocking) {
351: delegatedTasks.add(new DelegatedTask(
352: new PrivilegedExceptionAction() {
353: public Object run() throws Exception {
354: processClientHello();
355: return null;
356: }
357: }, this , AccessController.getContext()));
358: return;
359: }
360: processClientHello();
361: } catch (Exception e) {
362: fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR",
363: e);
364: }
365: }
366:
367: /**
368: *
369: * Processes Client Hello message.
370: * Server responds to client hello message with server hello
371: * and (if necessary) server certificate, server key exchange,
372: * certificate request, and server hello done messages.
373: */
374: void processClientHello() {
375: CipherSuite cipher_suite;
376:
377: // check that clientHello contains CompressionMethod.null
378: checkCompression: {
379: for (int i = 0; i < clientHello.compression_methods.length; i++) {
380: if (clientHello.compression_methods[i] == 0) {
381: break checkCompression;
382: }
383: }
384: fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
385: "HANDSHAKE FAILURE. Incorrect client hello message");
386: }
387:
388: if (!ProtocolVersion.isSupported(clientHello.client_version)) {
389: fatalAlert(AlertProtocol.PROTOCOL_VERSION,
390: "PROTOCOL VERSION. Unsupported client version "
391: + clientHello.client_version[0]
392: + clientHello.client_version[1]);
393: }
394:
395: isResuming = false;
396: FIND: if (clientHello.session_id.length != 0) {
397: // client wishes to reuse session
398:
399: SSLSessionImpl sessionToResume;
400: boolean reuseCurrent = false;
401:
402: // reuse current session
403: if (session != null
404: && Arrays
405: .equals(session.id, clientHello.session_id)) {
406: if (session.isValid()) {
407: isResuming = true;
408: break FIND;
409: }
410: reuseCurrent = true;
411: }
412:
413: // find session in cash
414: sessionToResume = findSessionToResume(clientHello.session_id);
415: if (sessionToResume == null || !sessionToResume.isValid()) {
416: if (!parameters.getEnableSessionCreation()) {
417: if (reuseCurrent) {
418: // we can continue current session
419: sendWarningAlert(AlertProtocol.NO_RENEGOTIATION);
420: status = NOT_HANDSHAKING;
421: clearMessages();
422: return;
423: } else {
424: fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
425: "SSL Session may not be created");
426: }
427: }
428: session = null;
429: } else {
430: session = (SSLSessionImpl) sessionToResume.clone();
431: isResuming = true;
432: }
433: }
434:
435: if (isResuming) {
436: cipher_suite = session.cipherSuite;
437: // clientHello.cipher_suites must include at least cipher_suite from the session
438: checkCipherSuite: {
439: for (int i = 0; i < clientHello.cipher_suites.length; i++) {
440: if (cipher_suite
441: .equals(clientHello.cipher_suites[i])) {
442: break checkCipherSuite;
443: }
444: }
445: fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
446: "HANDSHAKE FAILURE. Incorrect client hello message");
447: }
448: } else {
449: cipher_suite = selectSuite(clientHello.cipher_suites);
450: if (cipher_suite == null) {
451: fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
452: "HANDSHAKE FAILURE. NO COMMON SUITE");
453: }
454: if (!parameters.getEnableSessionCreation()) {
455: fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
456: "SSL Session may not be created");
457: }
458: session = new SSLSessionImpl(cipher_suite, parameters
459: .getSecureRandom());
460: }
461:
462: recordProtocol.setVersion(clientHello.client_version);
463: session.protocol = ProtocolVersion
464: .getByVersion(clientHello.client_version);
465: session.clientRandom = clientHello.random;
466:
467: // create server hello message
468: serverHello = new ServerHello(parameters.getSecureRandom(),
469: clientHello.client_version, session.getId(),
470: cipher_suite, (byte) 0); //CompressionMethod.null
471: session.serverRandom = serverHello.random;
472: send(serverHello);
473: if (isResuming) {
474: sendChangeCipherSpec();
475: return;
476: }
477:
478: // create and send server certificate message if needed
479: if (!cipher_suite.isAnonymous()) { // need to send server certificate
480: X509Certificate[] certs = null;
481: String certType = null;
482: if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA
483: || cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT
484: || cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_RSA
485: || cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_RSA_EXPORT) {
486: certType = "RSA";
487: } else if (cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_DSS
488: || cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT) {
489: certType = "DSA";
490: } else if (cipher_suite.keyExchange == CipherSuite.KeyExchange_DH_DSS) {
491: certType = "DH_DSA";
492: } else if (cipher_suite.keyExchange == CipherSuite.KeyExchange_DH_RSA) {
493: certType = "DH_RSA";
494: }
495: // obtain certificates from key manager
496: String alias = null;
497: X509KeyManager km = parameters.getKeyManager();
498: if (km instanceof X509ExtendedKeyManager) {
499: X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) km;
500: if (this .socketOwner != null) {
501: alias = ekm.chooseServerAlias(certType, null,
502: this .socketOwner);
503: } else {
504: alias = ekm.chooseEngineServerAlias(certType, null,
505: this .engineOwner);
506: }
507: if (alias != null) {
508: certs = ekm.getCertificateChain(alias);
509: }
510: } else {
511: alias = km.chooseServerAlias(certType, null,
512: this .socketOwner);
513: if (alias != null) {
514: certs = km.getCertificateChain(alias);
515: }
516: }
517:
518: if (certs == null) {
519: fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
520: "NO SERVER CERTIFICATE FOUND");
521: return;
522: }
523: session.localCertificates = certs;
524: serverCert = new CertificateMessage(certs);
525: privKey = parameters.getKeyManager().getPrivateKey(alias);
526: send(serverCert);
527: }
528:
529: // create and send server key exchange message if needed
530: RSAPublicKey rsakey = null;
531: DHPublicKeySpec dhkeySpec = null;
532: byte[] hash = null;
533: BigInteger p = null;
534: BigInteger g = null;
535:
536: KeyPairGenerator kpg = null;
537:
538: try {
539: if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
540: PublicKey pk = serverCert.certs[0].getPublicKey();
541: if (getRSAKeyLength(pk) > 512) {
542: // key is longer than 512 bits
543: kpg = KeyPairGenerator.getInstance("RSA");
544: kpg.initialize(512);
545: }
546: } else if (cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_DSS
547: || cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT
548: || cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_RSA
549: || cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_RSA_EXPORT
550: || cipher_suite.keyExchange == CipherSuite.KeyExchange_DH_anon
551: || cipher_suite.keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {
552: try {
553: kpg = KeyPairGenerator.getInstance("DH");
554: } catch (NoSuchAlgorithmException ee) {
555: kpg = KeyPairGenerator.getInstance("DiffieHellman");
556: }
557: p = new BigInteger(1, DHParameters.getPrime());
558: g = new BigInteger("2");
559: DHParameterSpec spec = new DHParameterSpec(p, g);
560: kpg.initialize(spec);
561: }
562: } catch (Exception e) {
563: fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR",
564: e);
565: }
566:
567: if (kpg != null) {
568: // need to send server key exchange message
569: DigitalSignature ds = new DigitalSignature(
570: cipher_suite.keyExchange);
571: KeyPair kp = null;
572: try {
573: kp = kpg.genKeyPair();
574: if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
575: rsakey = (RSAPublicKey) kp.getPublic();
576: } else {
577: DHPublicKey dhkey = (DHPublicKey) kp.getPublic();
578: KeyFactory kf = null;
579: try {
580: kf = KeyFactory.getInstance("DH");
581: } catch (NoSuchAlgorithmException e) {
582: kf = KeyFactory.getInstance("DiffieHellman");
583: }
584: dhkeySpec = (DHPublicKeySpec) kf.getKeySpec(dhkey,
585: DHPublicKeySpec.class);
586: }
587: if (!cipher_suite.isAnonymous()) { // calculate signed_params
588:
589: // init by private key which correspond to
590: // server certificate
591: ds.init(privKey);
592:
593: // use emphemeral key for key exchange
594: privKey = kp.getPrivate();
595: ds.update(clientHello.getRandom());
596: ds.update(serverHello.getRandom());
597:
598: byte[] tmp;
599: byte[] tmpLength = new byte[2];
600: //FIXME 1_byte==0x00
601: if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
602: tmp = rsakey.getModulus().toByteArray();
603: tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
604: tmpLength[1] = (byte) (tmp.length & 0xFF);
605: ds.update(tmpLength);
606: ds.update(tmp);
607: tmp = rsakey.getPublicExponent().toByteArray();
608: tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
609: tmpLength[1] = (byte) (tmp.length & 0xFF);
610: ds.update(tmp);
611: } else {
612: tmp = dhkeySpec.getP().toByteArray();
613: tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
614: tmpLength[1] = (byte) (tmp.length & 0xFF);
615: ds.update(tmp);
616: tmp = dhkeySpec.getG().toByteArray();
617: tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
618: tmpLength[1] = (byte) (tmp.length & 0xFF);
619: ds.update(tmp);
620: tmp = dhkeySpec.getY().toByteArray();
621: tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
622: tmpLength[1] = (byte) (tmp.length & 0xFF);
623: ds.update(tmp);
624: }
625: hash = ds.sign();
626: } else {
627: privKey = kp.getPrivate(); // use emphemeral key for key exchange
628: }
629: } catch (Exception e) {
630: fatalAlert(AlertProtocol.INTERNAL_ERROR,
631: "INTERNAL ERROR", e);
632: }
633:
634: if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
635: serverKeyExchange = new ServerKeyExchange(rsakey
636: .getModulus(), rsakey.getPublicExponent(),
637: null, hash);
638: } else {
639: serverKeyExchange = new ServerKeyExchange(p, g,
640: dhkeySpec.getY(), hash);
641: }
642: send(serverKeyExchange);
643: }
644:
645: // CERTIFICATE_REQUEST
646: certRequest: if (parameters.getWantClientAuth()
647: || parameters.getNeedClientAuth()) {
648: X509Certificate[] accepted;
649: try {
650: X509TrustManager tm = parameters.getTrustManager();
651: accepted = tm.getAcceptedIssuers();
652: } catch (ClassCastException e) {
653: // don't send certificateRequest
654: break certRequest;
655: }
656: byte[] requestedClientCertTypes = { 1, 2 }; // rsa sign, dsa sign
657: certificateRequest = new CertificateRequest(
658: requestedClientCertTypes, accepted);
659: send(certificateRequest);
660: }
661:
662: // SERVER_HELLO_DONE
663: serverHelloDone = new ServerHelloDone();
664: send(serverHelloDone);
665: status = NEED_UNWRAP;
666: }
667:
668: /**
669: * Creates and sends finished message
670: */
671: protected void makeFinished() {
672: byte[] verify_data;
673: boolean isTLS = (serverHello.server_version[1] == 1); // TLS 1.0 protocol
674: if (isTLS) {
675: verify_data = new byte[12];
676: computerVerifyDataTLS("server finished", verify_data);
677: } else { // SSL 3.0 protocol (http://wp.netscape.com/eng/ssl3)
678: verify_data = new byte[36];
679: computerVerifyDataSSLv3(SSLv3Constants.server, verify_data);
680: }
681: serverFinished = new Finished(verify_data);
682: send(serverFinished);
683: if (isResuming) {
684: if (isTLS) {
685: computerReferenceVerifyDataTLS("client finished");
686: } else {
687: computerReferenceVerifyDataSSLv3(SSLv3Constants.client);
688: }
689: status = NEED_UNWRAP;
690: } else {
691: session.lastAccessedTime = System.currentTimeMillis();
692: status = FINISHED;
693: }
694: }
695:
696: // find sesssion in the session hash
697: private SSLSessionImpl findSessionToResume(byte[] session_id) {
698: return (SSLSessionImpl) parameters.getServerSessionContext()
699: .getSession(session_id);
700: }
701:
702: // find appropriate cipher_suite in the client suites
703: private CipherSuite selectSuite(CipherSuite[] client_suites) {
704: for (int i = 0; i < client_suites.length; i++) {
705: if (!client_suites[i].supported) {
706: continue;
707: }
708: for (int j = 0; j < parameters.enabledCipherSuites.length; j++) {
709: if (client_suites[i]
710: .equals(parameters.enabledCipherSuites[j])) {
711: return client_suites[i];
712: }
713: }
714: }
715: return null;
716: }
717:
718: /**
719: * Proceses inbound ChangeCipherSpec message
720: */
721: public void receiveChangeCipherSpec() {
722: if (isResuming) {
723: if (serverFinished == null) {
724: unexpectedMessage();
725: } else {
726: changeCipherSpecReceived = true;
727: }
728: } else {
729: if ((parameters.getNeedClientAuth() && clientCert == null)
730: || clientKeyExchange == null
731: || (clientCert != null
732: && !clientKeyExchange.isEmpty() && certificateVerify == null)) {
733: unexpectedMessage();
734: } else {
735: changeCipherSpecReceived = true;
736: }
737: if (serverHello.server_version[1] == 1) {
738: computerReferenceVerifyDataTLS("client finished");
739: } else {
740: computerReferenceVerifyDataSSLv3(SSLv3Constants.client);
741: }
742: }
743: }
744:
745: }
|