1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.math.BigInteger; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.KeyFactory; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.KeyPair; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.KeyPairGenerator; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.NoSuchAlgorithmException; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivateKey; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivilegedExceptionAction; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PublicKey; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.interfaces.RSAPublicKey; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.Cipher; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.KeyAgreement; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.interfaces.DHPublicKey; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.spec.DHParameterSpec; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.spec.DHPublicKeySpec; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.X509ExtendedKeyManager; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.X509KeyManager; 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.X509TrustManager; 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Server side handshake protocol implementation. 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Handshake protocol operates on top of the Record Protocol. 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It responsible for negotiating a session. 46f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 47f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * The implementation processes inbound client handshake messages, 48f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * creates and sends respond messages. Outbound messages are supplied 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to Record Protocol. Detected errors are reported to the Alert protocol. 50f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4. 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Handshake protocol.</a> 53f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class ServerHandshakeImpl extends HandshakeProtocol { 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // private key used in key exchange 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private PrivateKey privKey; 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates Server Handshake Implementation 62f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param owner 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public ServerHandshakeImpl(Object owner) { 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(owner); 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = NEED_UNWRAP; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Start session negotiation 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 73f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void start() { 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (session == null) { // initial handshake 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = NEED_UNWRAP; 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; // wait client hello 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientHello != null && this.status != FINISHED) { 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // current negotiation has not completed 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; // ignore 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 83f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // renegotiation 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sendHelloRequest(); 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = NEED_UNWRAP; 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Proceses inbound handshake messages 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param bytes 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 93f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void unwrap(byte[] bytes) { 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project io_stream.append(bytes); 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (io_stream.available() > 0) { 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int handshakeType; 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project io_stream.mark(); 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeType = io_stream.read(); 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length = io_stream.readUint24(); 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (io_stream.available() < length) { 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project io_stream.reset(); 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (handshakeType) { 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 1: // CLIENT_HELLO 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientHello != null && this.status != FINISHED) { 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Client hello has been received during handshake 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // if protocol planed to send Hello Request message 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // - cancel this demand. 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project needSendHelloRequest = false; 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientHello = new ClientHello(io_stream, length); 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (nonBlocking) { 12190b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes delegatedTasks.add(new DelegatedTask(new Runnable() { 12290b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes public void run() { 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project processClientHello(); 124f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson } 12590b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes }, this)); 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project processClientHello(); 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 11: // CLIENT CERTIFICATE 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming || certificateRequest == null 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || serverHelloDone == null || clientCert != null) { 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientCert = new CertificateMessage(io_stream, length); 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientCert.certs.length == 0) { 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (parameters.getNeedClientAuth()) { 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 1414ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "HANDSHAKE FAILURE: no client certificate received"); 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 144b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom String authType = clientCert.getAuthType(); 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parameters.getTrustManager().checkClientTrusted( 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientCert.certs, authType); 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (CertificateException e) { 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.BAD_CERTIFICATE, 1504ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "Untrusted Client Certificate ", e); 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.peerCertificates = clientCert.certs; 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 15: // CERTIFICATE_VERIFY 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || clientKeyExchange == null 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || clientCert == null 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || clientKeyExchange.isEmpty() //client certificate 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // contains fixed DH 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // parameters 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || certificateVerify != null 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || changeCipherSpecReceived) { 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project certificateVerify = new CertificateVerify(io_stream, length); 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 170b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom String authType = clientCert.getAuthType(); 171b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom DigitalSignature ds = new DigitalSignature(authType); 172b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom ds.init(clientCert.certs[0]); 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] md5_hash = null; 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] sha_hash = null; 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 176b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom if ("RSA".equals(authType)) { 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project md5_hash = io_stream.getDigestMD5withoutLast(); 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sha_hash = io_stream.getDigestSHAwithoutLast(); 179b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom } else if ("DSA".equals(authType)) { 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sha_hash = io_stream.getDigestSHAwithoutLast(); 181b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom // The Signature should be empty in case of anonymous signature algorithm: 182b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom // } else if ("DH".equals(authType)) { 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.setMD5(md5_hash); 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.setSHA(sha_hash); 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!ds.verifySignature(certificateVerify.signedHash)) { 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.DECRYPT_ERROR, 1884ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "DECRYPT ERROR: CERTIFICATE_VERIFY incorrect signature"); 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 16: // CLIENT_KEY_EXCHANGE 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || serverHelloDone == null 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || clientKeyExchange != null 1954ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom || (clientCert == null && parameters.getNeedClientAuth())) { 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 199aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom if (session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA 200aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom || session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) { 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientKeyExchange = new ClientKeyExchange(io_stream, 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length, serverHello.server_version[1] == 1, 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project true); 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Cipher c = null; 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project c = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 207b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom c.init(Cipher.UNWRAP_MODE, privKey); 208b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom preMasterSecret = c.unwrap(clientKeyExchange.exchange_keys, 209b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom "preMasterSecret", 210b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom Cipher.SECRET_KEY).getEncoded(); 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check preMasterSecret: 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (preMasterSecret.length != 48 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || preMasterSecret[0] != clientHello.client_version[0] 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || preMasterSecret[1] != clientHello.client_version[1]) { 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // incorrect preMasterSecret 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // prevent an attack (see TLS 1.0 spec., 7.4.7.1.) 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project preMasterSecret = new byte[48]; 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parameters.getSecureRandom().nextBytes( 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project preMasterSecret); 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.INTERNAL_ERROR, 2234ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "INTERNAL ERROR", e); 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { // diffie hellman key exchange 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientKeyExchange = new ClientKeyExchange(io_stream, 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length, serverHello.server_version[1] == 1, 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project false); 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientKeyExchange.isEmpty()) { 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // TODO check that client cert. DH params 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // matched server cert. DH params 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 233f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // client cert. contains fixed DH parameters 2344ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom preMasterSecret = ((DHPublicKey) clientCert.certs[0].getPublicKey()).getY().toByteArray(); 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 2374ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom KeyFactory kf = KeyFactory.getInstance("DH"); 2384ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom KeyAgreement agreement = KeyAgreement.getInstance("DH"); 2394ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom PublicKey clientPublic = kf.generatePublic(new DHPublicKeySpec( 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new BigInteger( 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1, 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientKeyExchange.exchange_keys), 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverKeyExchange.par1, 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverKeyExchange.par2)); 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project agreement.init(privKey); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project agreement.doPhase(clientPublic, true); 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project preMasterSecret = agreement.generateSecret(); 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.INTERNAL_ERROR, 2504ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "INTERNAL ERROR", e); 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerMasterSecret(); 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 20: // FINISHED 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isResuming && !changeCipherSpecReceived) { 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientFinished = new Finished(io_stream, length); 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project verifyFinished(clientFinished.getData()); 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.context = parameters.getServerSessionContext(); 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parameters.getServerSessionContext().putSession(session); 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isResuming) { 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sendChangeCipherSpec(); 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.lastAccessedTime = System.currentTimeMillis(); 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = FINISHED; 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project default: 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // io stream dosn't contain complete handshake message 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project io_stream.reset(); 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Processes SSLv2 Hello message 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @ see TLS 1.0 spec., E.1. Version 2 client hello 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param bytes 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 292f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void unwrapSSLv2(byte[] bytes) { 294f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson io_stream.append(bytes); 295f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson io_stream.mark(); 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 297f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson clientHello = new ClientHello(io_stream); 298f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson } catch (IOException e) { 299f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson io_stream.reset(); 300f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson return; 301f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson } 302f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson if (nonBlocking) { 30390b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes delegatedTasks.add(new DelegatedTask(new Runnable() { 30490b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes public void run() { 30590b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes processClientHello(); 30690b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes } 30790b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes }, this)); 308f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson return; 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 310f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson processClientHello(); 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 314f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 315f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Processes Client Hello message. 316f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Server responds to client hello message with server hello 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and (if necessary) server certificate, server key exchange, 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * certificate request, and server hello done messages. 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project void processClientHello() { 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CipherSuite cipher_suite; 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check that clientHello contains CompressionMethod.null 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkCompression: { 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < clientHello.compression_methods.length; i++) { 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientHello.compression_methods[i] == 0) { 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break checkCompression; 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 3314ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "HANDSHAKE FAILURE. Incorrect client hello message"); 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 333f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 3343e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom byte[] server_version = clientHello.client_version; 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!ProtocolVersion.isSupported(clientHello.client_version)) { 3363e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom if (clientHello.client_version[0] >= 3) { 3373e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom // Protocol from the future, admit that the newest thing we know is TLSv1 3383e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom server_version = ProtocolVersion.TLSv1.version; 3393e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom } else { 3403e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom fatalAlert(AlertProtocol.PROTOCOL_VERSION, 3413e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom "PROTOCOL VERSION. Unsupported client version " 3423e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom + clientHello.client_version[0] 3433e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom + clientHello.client_version[1]); 3443e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom } 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isResuming = false; 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project FIND: if (clientHello.session_id.length != 0) { 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // client wishes to reuse session 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLSessionImpl sessionToResume; 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean reuseCurrent = false; 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // reuse current session 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (session != null 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && Arrays.equals(session.id, clientHello.session_id)) { 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (session.isValid()) { 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isResuming = true; 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break FIND; 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reuseCurrent = true; 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 363f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // find session in cash 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sessionToResume = findSessionToResume(clientHello.session_id); 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (sessionToResume == null || !sessionToResume.isValid()) { 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!parameters.getEnableSessionCreation()) { 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reuseCurrent) { 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we can continue current session 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sendWarningAlert(AlertProtocol.NO_RENEGOTIATION); 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = NOT_HANDSHAKING; 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clearMessages(); 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 375f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson // throw AlertException 376f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "SSL Session may not be created"); 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session = null; 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session = (SSLSessionImpl)sessionToResume.clone(); 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isResuming = true; 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming) { 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cipher_suite = session.cipherSuite; 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // clientHello.cipher_suites must include at least cipher_suite from the session 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkCipherSuite: { 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < clientHello.cipher_suites.length; i++) { 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (cipher_suite.equals(clientHello.cipher_suites[i])) { 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break checkCipherSuite; 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 3954ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "HANDSHAKE FAILURE. Incorrect client hello message"); 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cipher_suite = selectSuite(clientHello.cipher_suites); 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (cipher_suite == null) { 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "HANDSHAKE FAILURE. NO COMMON SUITE"); 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!parameters.getEnableSessionCreation()) { 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 4044ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "SSL Session may not be created"); 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 40607ced5b685db42cc46a9567600c1f37326ab8f8aElliott Hughes session = new SSLSessionImpl(cipher_suite, parameters.getSecureRandom()); 4077329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom if (engineOwner != null) { 4087329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom session.setPeer(engineOwner.getPeerHost(), engineOwner.getPeerPort()); 4097329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } else { 4107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom session.setPeer(socketOwner.getInetAddress().getHostName(), socketOwner.getPort()); 4117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 4143e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom recordProtocol.setVersion(server_version); 4153e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom session.protocol = ProtocolVersion.getByVersion(server_version); 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.clientRandom = clientHello.random; 417f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // create server hello message 419f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes serverHello = new ServerHello(parameters.getSecureRandom(), 4203e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom server_version, 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.getId(), cipher_suite, (byte) 0); //CompressionMethod.null 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.serverRandom = serverHello.random; 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(serverHello); 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming) { 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sendChangeCipherSpec(); 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 428f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // create and send server certificate message if needed 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!cipher_suite.isAnonymous()) { // need to send server certificate 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project X509Certificate[] certs = null; 4324ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String certType = cipher_suite.getServerKeyType(); 4334ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom if (certType == null) { 4344ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "NO CERT TYPE FOR " + cipher_suite.getName()); 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // obtain certificates from key manager 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String alias = null; 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project X509KeyManager km = parameters.getKeyManager(); 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (km instanceof X509ExtendedKeyManager) { 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project X509ExtendedKeyManager ekm = (X509ExtendedKeyManager)km; 4417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom if (this.socketOwner != null) { 4427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom alias = ekm.chooseServerAlias(certType, null, 4437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom this.socketOwner); 4447329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } else { 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project alias = ekm.chooseEngineServerAlias(certType, null, 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.engineOwner); 4477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (alias != null) { 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project certs = ekm.getCertificateChain(alias); 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 4527329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom alias = km.chooseServerAlias(certType, null, this.socketOwner); 4537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom if (alias != null) { 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project certs = km.getCertificateChain(alias); 4557329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (certs == null) { 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "NO SERVER CERTIFICATE FOUND"); 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.localCertificates = certs; 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverCert = new CertificateMessage(certs); 464b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom privKey = km.getPrivateKey(alias); 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(serverCert); 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // create and send server key exchange message if needed 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project RSAPublicKey rsakey = null; 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project DHPublicKeySpec dhkeySpec = null; 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] hash = null; 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project BigInteger p = null; 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project BigInteger g = null; 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project KeyPairGenerator kpg = null; 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 478aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) { 479f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes PublicKey pk = serverCert.certs[0].getPublicKey(); 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (getRSAKeyLength(pk) > 512) { 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // key is longer than 512 bits 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project kpg = KeyPairGenerator.getInstance("RSA"); 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project kpg.initialize(512); 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 485aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom } else if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_DSS 486aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_DSS_EXPORT 487aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_RSA 488aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_RSA_EXPORT 489aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DH_anon 490aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DH_anon_EXPORT) { 4914ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom kpg = KeyPairGenerator.getInstance("DH"); 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project p = new BigInteger(1, DHParameters.getPrime()); 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project g = new BigInteger("2"); 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project DHParameterSpec spec = new DHParameterSpec(p, g); 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project kpg.initialize(spec); 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e); 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (kpg != null) { 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // need to send server key exchange message 503b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom DigitalSignature ds = new DigitalSignature(cipher_suite.authType); 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project KeyPair kp = null; 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project kp = kpg.genKeyPair(); 507aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) { 508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project rsakey = (RSAPublicKey) kp.getPublic(); 509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project DHPublicKey dhkey = (DHPublicKey) kp.getPublic(); 5114ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom KeyFactory kf = KeyFactory.getInstance("DH"); 5124ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom dhkeySpec = kf.getKeySpec(dhkey, DHPublicKeySpec.class); 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!cipher_suite.isAnonymous()) { // calculate signed_params 515f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // init by private key which correspond to 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // server certificate 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.init(privKey); 519f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // use emphemeral key for key exchange 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project privKey = kp.getPrivate(); 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.update(clientHello.getRandom()); 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.update(serverHello.getRandom()); 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] tmp; 526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] tmpLength = new byte[2]; 527f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes//FIXME 1_byte==0x00 528aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) { 529c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache tmp = ServerKeyExchange.toUnsignedByteArray(rsakey.getModulus()); 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8); 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[1] = (byte) (tmp.length & 0xFF); 532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.update(tmpLength); 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.update(tmp); 534c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache tmp = ServerKeyExchange.toUnsignedByteArray(rsakey.getPublicExponent()); 535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8); 536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[1] = (byte) (tmp.length & 0xFF); 537c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache ds.update(tmpLength); 538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.update(tmp); 539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 540c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache tmp = ServerKeyExchange.toUnsignedByteArray(dhkeySpec.getP()); 541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8); 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[1] = (byte) (tmp.length & 0xFF); 543c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache ds.update(tmpLength); 544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.update(tmp); 545c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache tmp = ServerKeyExchange.toUnsignedByteArray(dhkeySpec.getG()); 546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8); 547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[1] = (byte) (tmp.length & 0xFF); 548c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache ds.update(tmpLength); 549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.update(tmp); 550c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache tmp = ServerKeyExchange.toUnsignedByteArray(dhkeySpec.getY()); 551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8); 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tmpLength[1] = (byte) (tmp.length & 0xFF); 553c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache ds.update(tmpLength); 554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.update(tmp); 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project hash = ds.sign(); 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project privKey = kp.getPrivate(); // use emphemeral key for key exchange 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e); 562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 564aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) { 565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverKeyExchange = new ServerKeyExchange(rsakey.getModulus(), 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project rsakey.getPublicExponent(), null, hash); 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverKeyExchange = new ServerKeyExchange(p, 569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project g, dhkeySpec.getY(), hash); 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(serverKeyExchange); 572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // CERTIFICATE_REQUEST 575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project certRequest: if (parameters.getWantClientAuth() 576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || parameters.getNeedClientAuth()) { 577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project X509Certificate[] accepted; 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project X509TrustManager tm = parameters.getTrustManager(); 580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project accepted = tm.getAcceptedIssuers(); 581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ClassCastException e) { 582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // don't send certificateRequest 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break certRequest; 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 5854ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom byte[] requestedClientCertTypes = { CipherSuite.TLS_CT_RSA_SIGN, 5864ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom CipherSuite.TLS_CT_DSS_SIGN }; 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project certificateRequest = new CertificateRequest( 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project requestedClientCertTypes, accepted); 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(certificateRequest); 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // SERVER_HELLO_DONE 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverHelloDone = new ServerHelloDone(); 594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(serverHelloDone); 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = NEED_UNWRAP; 596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 597f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates and sends finished message 600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 601f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void makeFinished() { 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] verify_data; 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean isTLS = (serverHello.server_version[1] == 1); // TLS 1.0 protocol 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isTLS) { 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project verify_data = new byte[12]; 607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerVerifyDataTLS("server finished", verify_data); 608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { // SSL 3.0 protocol (http://wp.netscape.com/eng/ssl3) 609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project verify_data = new byte[36]; 610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerVerifyDataSSLv3(SSLv3Constants.server, verify_data); 611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverFinished = new Finished(verify_data); 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(serverFinished); 614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming) { 615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isTLS) { 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerReferenceVerifyDataTLS("client finished"); 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 618f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes computerReferenceVerifyDataSSLv3(SSLv3Constants.client); 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = NEED_UNWRAP; 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.lastAccessedTime = System.currentTimeMillis(); 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = FINISHED; 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // find sesssion in the session hash 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private SSLSessionImpl findSessionToResume(byte[] session_id) { 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return (SSLSessionImpl)parameters.getServerSessionContext().getSession(session_id); 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 631f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // find appropriate cipher_suite in the client suites 6334ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom private CipherSuite selectSuite(CipherSuite[] clientSuites) { 6344ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom for (CipherSuite clientSuite : clientSuites) { 6354ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom if (!clientSuite.supported) { 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 6384ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom for (CipherSuite enabledCipherSuite : parameters.getEnabledCipherSuitesMember()) { 6394ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom if (clientSuite.equals(enabledCipherSuite)) { 6404ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom return clientSuite; 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 648f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * Processes inbound ChangeCipherSpec message 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 650f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 651f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes public void receiveChangeCipherSpec() { 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming) { 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverFinished == null) { 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project changeCipherSpecReceived = true; 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((parameters.getNeedClientAuth() && clientCert == null) 660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || clientKeyExchange == null 6617c935d4e4ca990334200cf5eb4fbcfac718c6b45gcollins || (clientCert != null && clientCert.certs.length > 0 6626882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom && !clientKeyExchange.isEmpty() 6636882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom && certificateVerify == null)) { 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project changeCipherSpecReceived = true; 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverHello.server_version[1] == 1) { 669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerReferenceVerifyDataTLS("client finished"); 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerReferenceVerifyDataSSLv3(SSLv3Constants.client); 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 677