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