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