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.security.Key; 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.PublicKey; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.Cipher; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.KeyAgreement; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.interfaces.DHKey; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.interfaces.DHPublicKey; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.spec.DHParameterSpec; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.spec.DHPublicKeySpec; 37b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstromimport javax.crypto.spec.SecretKeySpec; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.X509ExtendedKeyManager; 39b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstromimport javax.net.ssl.X509KeyManager; 406d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condraimport javax.net.ssl.X509TrustManager; 41b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstromimport javax.security.auth.x500.X500Principal; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Client side handshake protocol implementation. 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Handshake protocol operates on top of the Record Protocol. 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It is responsible for session negotiating. 47f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 48f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * The implementation processes inbound server handshake messages, 49f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * creates and sends respond messages. Outbound messages are supplied 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to Record Protocol. Detected errors are reported to the Alert protocol. 51f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7. The 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * TLS Handshake Protocol</a> 54f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 56f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughespublic class ClientHandshakeImpl extends HandshakeProtocol { 57f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates Client Handshake Implementation 60f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param owner 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ClientHandshakeImpl(Object owner) { 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(owner); 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 66f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Starts handshake 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 70f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes */ 71f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void start() { 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (session == null) { // initial handshake 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session = findSessionToResume(); 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { // start session renegotiation 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientHello != null && this.status != FINISHED) { 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // current negotiation has not completed 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; // ignore 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!session.isValid()) { 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session = null; 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (session != null) { 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isResuming = true; 86f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } else if (parameters.getEnableSessionCreation()){ 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isResuming = false; 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session = new SSLSessionImpl(parameters.getSecureRandom()); 897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom if (engineOwner != null) { 907329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom session.setPeer(engineOwner.getPeerHost(), engineOwner.getPeerPort()); 917329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } else { 926d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra session.setPeer(socketOwner.getPeerHostName(), socketOwner.getPeerPort()); 937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } 944ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom session.protocol = ProtocolVersion.getLatestVersion(parameters.getEnabledProtocols()); 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project recordProtocol.setVersion(session.protocol.version); 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "SSL Session may not be created "); 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project startSession(); 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 101f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Starts renegotiation on a new session 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void renegotiateNewSession() { 107f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (parameters.getEnableSessionCreation()){ 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isResuming = false; 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session = new SSLSessionImpl(parameters.getSecureRandom()); 1107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom if (engineOwner != null) { 1117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom session.setPeer(engineOwner.getPeerHost(), engineOwner.getPeerPort()); 1127329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } else { 1136d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra session.setPeer(socketOwner.getPeerHostName(), socketOwner.getPeerPort()); 1147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } 1154ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom session.protocol = ProtocolVersion.getLatestVersion(parameters.getEnabledProtocols()); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project recordProtocol.setVersion(session.protocol.version); 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project startSession(); 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = NOT_HANDSHAKING; 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sendWarningAlert(AlertProtocol.NO_RENEGOTIATION); 121f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Starts/resumes session 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void startSession() { 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CipherSuite[] cipher_suites; 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming) { 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cipher_suites = new CipherSuite[] { session.cipherSuite }; 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cipher_suites = parameters.getEnabledCipherSuitesMember(); 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientHello = new ClientHello(parameters.getSecureRandom(), 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.protocol.version, session.id, cipher_suites); 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.clientRandom = clientHello.random; 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(clientHello); 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = NEED_UNWRAP; 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 142f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * Processes inbound handshake messages 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param bytes 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 145f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void unwrap(byte[] bytes) { 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this.delegatedTaskErr != null) { 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Exception e = this.delegatedTaskErr; 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.delegatedTaskErr = null; 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "Error in delegated task", e); 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int handshakeType; 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project io_stream.append(bytes); 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (io_stream.available() > 0) { 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project io_stream.mark(); 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length; 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeType = io_stream.read(); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length = io_stream.readUint24(); 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (io_stream.available() < length) { 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project io_stream.reset(); 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (handshakeType) { 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 0: // HELLO_REQUEST 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // we don't need to take this message into account 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // during FINISH message verification, so remove it 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project io_stream.removeFromMarkedPosition(); 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientHello != null 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && (clientFinished == null || serverFinished == null)) { 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //currently negotiating - ignore 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // renegotiate 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (session.isValid()) { 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session = (SSLSessionImpl) session.clone(); 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isResuming = true; 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project startSession(); 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // if SSLSession is invalidated (e.g. timeout limit is 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // exceeded) connection can't resume the session. 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project renegotiateNewSession(); 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 2: // SERVER_HELLO 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientHello == null || serverHello != null) { 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverHello = new ServerHello(io_stream, length); 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //check protocol version 1934ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom ProtocolVersion servProt = ProtocolVersion.getByVersion(serverHello.server_version); 194f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes String[] enabled = parameters.getEnabledProtocols(); 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project find: { 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < enabled.length; i++) { 1974ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom if (servProt.equals(ProtocolVersion.getByName(enabled[i]))) { 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break find; 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 2024ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "Bad server hello protocol version"); 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 204f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check compression method 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverHello.compression_method != 0) { 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 2084ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "Bad server hello compression method"); 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 210f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //check cipher_suite 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CipherSuite[] enabledSuites = parameters.getEnabledCipherSuitesMember(); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project find: { 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < enabledSuites.length; i++) { 2154ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom if (serverHello.cipher_suite.equals(enabledSuites[i])) { 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break find; 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 2204ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "Bad server hello cipher suite"); 221f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming) { 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverHello.session_id.length == 0) { 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // server is not willing to establish the new connection 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // using specified session 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isResuming = false; 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (!Arrays.equals(serverHello.session_id, clientHello.session_id)) { 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project isResuming = false; 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (!session.protocol.equals(servProt)) { 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 2324ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "Bad server hello protocol version"); 2334ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom } else if (!session.cipherSuite.equals(serverHello.cipher_suite)) { 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, 2354ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom "Bad server hello cipher suite"); 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverHello.server_version[1] == 1) { 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerReferenceVerifyDataTLS("server finished"); 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerReferenceVerifyDataSSLv3(SSLv3Constants.server); 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.protocol = servProt; 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project recordProtocol.setVersion(session.protocol.version); 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.cipherSuite = serverHello.cipher_suite; 246f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson session.id = serverHello.session_id.clone(); 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.serverRandom = serverHello.random; 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 11: // CERTIFICATE 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverHello == null || serverKeyExchange != null 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || serverCert != null || isResuming) { 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverCert = new CertificateMessage(io_stream, length); 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 12: // SERVER_KEY_EXCHANGE 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverHello == null || serverKeyExchange != null 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || isResuming) { 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverKeyExchange = new ServerKeyExchange(io_stream, 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length, session.cipherSuite.keyExchange); 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 13: // CERTIFICATE_REQUEST 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverCert == null || certificateRequest != null 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || session.cipherSuite.isAnonymous() || isResuming) { 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2724ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom certificateRequest = new CertificateRequest(io_stream, length); 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 14: // SERVER_HELLO_DONE 2754ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom if (serverHello == null || serverHelloDone != null || isResuming) { 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverHelloDone = new ServerHelloDone(io_stream, length); 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this.nonBlocking) { 28190b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes delegatedTasks.add(new DelegatedTask(new Runnable() { 28290b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes public void run() { 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project processServerHelloDone(); 284f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson } 28590b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes }, this)); 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project processServerHelloDone(); 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 20: // FINISHED 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!changeCipherSpecReceived) { 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverFinished = new Finished(io_stream, length); 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project verifyFinished(serverFinished.getData()); 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.lastAccessedTime = System.currentTimeMillis(); 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.context = parameters.getClientSessionContext(); 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parameters.getClientSessionContext().putSession(session); 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming) { 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sendChangeCipherSpec(); 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.lastAccessedTime = System.currentTimeMillis(); 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = FINISHED; 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // XXX there is no cleanup work 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project default: 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // io stream dosn't contain complete handshake message 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project io_stream.reset(); 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 322f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Processes SSLv2 Hello message. 323f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * SSLv2 client hello message message is an unexpected message 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for client side of handshake protocol. 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @ see TLS 1.0 spec., E.1. Version 2 client hello 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param bytes 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 328f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void unwrapSSLv2(byte[] bytes) { 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates and sends Finished message 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 336f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void makeFinished() { 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] verify_data; 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverHello.server_version[1] == 1) { 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project verify_data = new byte[12]; 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerVerifyDataTLS("client finished", verify_data); 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project verify_data = new byte[36]; 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerVerifyDataSSLv3(SSLv3Constants.client, verify_data); 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientFinished = new Finished(verify_data); 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(clientFinished); 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming) { 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.lastAccessedTime = System.currentTimeMillis(); 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = FINISHED; 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverHello.server_version[1] == 1) { 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerReferenceVerifyDataTLS("server finished"); 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerReferenceVerifyDataSSLv3(SSLv3Constants.server); 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = NEED_UNWRAP; 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Processes ServerHelloDone: makes verification of the server messages; sends 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * client messages, computers masterSecret, sends ChangeCipherSpec 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project void processServerHelloDone() { 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project PrivateKey clientKey = null; 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverCert != null) { 369b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom if (session.cipherSuite.isAnonymous()) { 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project verifyServerCert(); 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 375b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom if (!session.cipherSuite.isAnonymous()) { 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Client certificate 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (certificateRequest != null) { 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project X509Certificate[] certs = null; 384b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom // obtain certificates from key manager 385b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom String alias = null; 386b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom String[] certTypes = certificateRequest.getTypesAsString(); 387b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom X500Principal[] issuers = certificateRequest.certificate_authorities; 388b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom X509KeyManager km = parameters.getKeyManager(); 389b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom if (km instanceof X509ExtendedKeyManager) { 390b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom X509ExtendedKeyManager ekm = (X509ExtendedKeyManager)km; 391b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom if (this.socketOwner != null) { 392b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom alias = ekm.chooseClientAlias(certTypes, issuers, this.socketOwner); 393b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom } else { 394b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom alias = ekm.chooseEngineClientAlias(certTypes, issuers, this.engineOwner); 395b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom } 396b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom if (alias != null) { 397b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom certs = ekm.getCertificateChain(alias); 398b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom } 399b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom } else { 400b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom alias = km.chooseClientAlias(certTypes, issuers, this.socketOwner); 401b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom if (alias != null) { 402b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom certs = km.getCertificateChain(alias); 403b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom } 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 405b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.localCertificates = certs; 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientCert = new CertificateMessage(certs); 408b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom clientKey = km.getPrivateKey(alias); 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(clientCert); 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Client key exchange 412aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom if (session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA 413aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom || session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) { 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // RSA encrypted premaster secret message 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Cipher c; 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project c = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverKeyExchange != null) { 419b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom c.init(Cipher.WRAP_MODE, serverKeyExchange 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getRSAPublicKey()); 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 422b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom c.init(Cipher.WRAP_MODE, serverCert.certs[0]); 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.INTERNAL_ERROR, 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Unexpected exception", e); 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project preMasterSecret = new byte[48]; 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parameters.getSecureRandom().nextBytes(preMasterSecret); 4316882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom System.arraycopy(clientHello.client_version, 0, preMasterSecret, 0, 2); 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientKeyExchange = new ClientKeyExchange(c 434b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom .wrap(new SecretKeySpec(preMasterSecret, "preMasterSecret")), 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverHello.server_version[1] == 1); 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.INTERNAL_ERROR, 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Unexpected exception", e); 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 4434ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom KeyFactory kf = KeyFactory.getInstance("DH"); 4444ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom KeyAgreement agreement = KeyAgreement.getInstance("DH"); 4454ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH"); 4464ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom PublicKey serverPublic; 4474ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom DHParameterSpec spec; 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverKeyExchange != null) { 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverPublic = kf.generatePublic(new DHPublicKeySpec( 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverKeyExchange.par3, serverKeyExchange.par1, 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverKeyExchange.par2)); 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project spec = new DHParameterSpec(serverKeyExchange.par1, 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverKeyExchange.par2); 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project serverPublic = serverCert.certs[0].getPublicKey(); 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project spec = ((DHPublicKey) serverPublic).getParams(); 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project kpg.initialize(spec); 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project KeyPair kp = kpg.generateKeyPair(); 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Key key = kp.getPublic(); 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientCert != null 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && serverCert != null 464aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom && (session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_RSA 465aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom || session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_DSS)) { 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project PublicKey client_pk = clientCert.certs[0].getPublicKey(); 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project PublicKey server_pk = serverCert.certs[0].getPublicKey(); 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (client_pk instanceof DHKey 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && server_pk instanceof DHKey) { 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (((DHKey) client_pk).getParams().getG().equals( 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((DHKey) server_pk).getParams().getG()) 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && ((DHKey) client_pk).getParams().getP() 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .equals(((DHKey) server_pk).getParams().getG())) { 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // client cert message DH public key parameters 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // matched those specified by the 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // server in its certificate, 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientKeyExchange = new ClientKeyExchange(); // empty 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project clientKeyExchange = new ClientKeyExchange( 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ((DHPublicKey) key).getY()); 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project key = kp.getPrivate(); 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project agreement.init(key); 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project agreement.doPhase(serverPublic, true); 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project preMasterSecret = agreement.generateSecret(); 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.INTERNAL_ERROR, 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Unexpected exception", e); 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (clientKeyExchange != null) { 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(clientKeyExchange); 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project computerMasterSecret(); 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // send certificate verify for all certificates except those containing 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // fixed DH parameters 5027c935d4e4ca990334200cf5eb4fbcfac718c6b45gcollins if (clientCert != null && clientCert.certs.length > 0 && !clientKeyExchange.isEmpty()) { 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Certificate verify 504b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom String authType = clientKey.getAlgorithm(); 505b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom DigitalSignature ds = new DigitalSignature(authType); 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.init(clientKey); 507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 508b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom if ("RSA".equals(authType)) { 509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.setMD5(io_stream.getDigestMD5()); 510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.setSHA(io_stream.getDigestSHA()); 511b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom } else if ("DSA".equals(authType)) { 512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ds.setSHA(io_stream.getDigestSHA()); 513b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom // The Signature should be empty in case of anonymous signature algorithm: 514b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom // } else if ("DH".equals(authType)) { 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project certificateVerify = new CertificateVerify(ds.sign()); 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project send(certificateVerify); 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sendChangeCipherSpec(); 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 522f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Verifies certificate path 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void verifyServerCert() { 5274ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String authType = session.cipherSuite.getAuthType(serverKeyExchange != null); 5284ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom if (authType == null) { 529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 5316d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra String hostname = null; 5326d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra if (engineOwner != null) { 5336d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra hostname = engineOwner.getPeerHost(); 5346d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } else { 5356d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra // we don't want to do an inet address lookup here in case we're talking to a proxy 5366d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra hostname = socketOwner.getWrappedHostName(); 5376d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } 538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 5396d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra X509TrustManager x509tm = parameters.getTrustManager(); 5406d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra if (x509tm instanceof TrustManagerImpl) { 5416d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra TrustManagerImpl tm = (TrustManagerImpl) x509tm; 5426d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra tm.checkServerTrusted(serverCert.certs, authType, hostname); 5436d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } else { 5446d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra x509tm.checkServerTrusted(serverCert.certs, authType); 5456d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } 546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (CertificateException e) { 547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fatalAlert(AlertProtocol.BAD_CERTIFICATE, "Not trusted server certificate", e); 548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session.peerCertificates = serverCert.certs; 551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 554f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * Processes ChangeCipherSpec message 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 556f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson @Override 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void receiveChangeCipherSpec() { 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isResuming) { 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (serverHello == null) { 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (clientFinished == null) { 563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unexpectedMessage(); 564f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project changeCipherSpecReceived = true; 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Find session to resume in client session context 569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private SSLSessionImpl findSessionToResume() { 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String host = null; 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int port = -1; 572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (engineOwner != null) { 573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project host = engineOwner.getPeerHost(); 574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port = engineOwner.getPeerPort(); 5757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom } else { 5766d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra host = socketOwner.getPeerHostName(); 5776d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra port = socketOwner.getPeerPort(); 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (host == null || port == -1) { 580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; // starts new session 581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 582f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ClientSessionContext context = parameters.getClientSessionContext(); 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLSessionImpl session 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project = (SSLSessionImpl) context.getSession(host, port); 586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (session != null) { 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session = (SSLSessionImpl) session.clone(); 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return session; 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 593