HandshakeProtocol.java revision 0c131a2ca38465b7d1df4eaee63ac73ce4d5986d
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.xnet.provider.jsse;
19
20import java.math.BigInteger;
21import java.security.GeneralSecurityException;
22import java.security.KeyFactory;
23import java.security.MessageDigest;
24import java.security.NoSuchAlgorithmException;
25import java.security.PublicKey;
26import java.security.interfaces.RSAKey;
27import java.security.spec.InvalidKeySpecException;
28import java.security.spec.RSAPublicKeySpec;
29import java.util.Arrays;
30import java.util.Vector;
31
32import javax.net.ssl.SSLEngineResult;
33import javax.net.ssl.SSLException;
34import javax.net.ssl.SSLHandshakeException;
35
36/**
37 * Base class for ClientHandshakeImpl and ServerHandshakeImpl classes.
38 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.
39 * Handshake protocol</a>
40 *
41 */
42public abstract class HandshakeProtocol {
43
44    /**
45     * Handshake status NEED_UNWRAP - HandshakeProtocol needs to receive data
46     */
47    public final static int NEED_UNWRAP = 1;
48
49    /**
50     * Handshake status NOT_HANDSHAKING - is not currently handshaking
51     */
52    public final static int NOT_HANDSHAKING = 2;
53
54    /**
55     * Handshake status FINISHED - HandshakeProtocol has just finished
56     */
57    public final static int FINISHED = 3;
58
59    /**
60     * Handshake status NEED_TASK - HandshakeProtocol needs the results of delegated task
61     */
62    public final static int NEED_TASK = 4;
63
64    /**
65     * Current handshake status
66     */
67    protected int status = NOT_HANDSHAKING;
68
69    /**
70     * IO stream for income/outcome handshake data
71     */
72    protected HandshakeIODataStream io_stream = new HandshakeIODataStream();
73
74    /**
75     * SSL Record Protocol implementation.
76     */
77    protected SSLRecordProtocol recordProtocol;
78
79    /**
80     * SSLParameters suplied by SSLSocket or SSLEngine
81     */
82    protected SSLParameters parameters;
83
84    /**
85     * Delegated tasks for this handshake implementation
86     */
87    protected Vector<DelegatedTask> delegatedTasks = new Vector<DelegatedTask>();
88
89    /**
90     * Indicates non-blocking handshake
91     */
92    protected boolean nonBlocking;
93
94    /**
95     * Pending session
96     */
97    protected SSLSessionImpl session;
98
99    /**
100     * Sended and received handshake messages
101     */
102    protected ClientHello clientHello;
103    protected ServerHello serverHello;
104    protected CertificateMessage serverCert;
105    protected ServerKeyExchange serverKeyExchange;
106    protected CertificateRequest certificateRequest;
107    protected ServerHelloDone serverHelloDone;
108    protected CertificateMessage clientCert;
109    protected ClientKeyExchange clientKeyExchange;
110    protected CertificateVerify certificateVerify;
111    protected Finished clientFinished;
112    protected Finished serverFinished;
113
114    /**
115     * Indicates that change cipher spec message has been received
116     */
117    protected boolean changeCipherSpecReceived = false;
118
119    /**
120     * Indicates previous session resuming
121     */
122    protected boolean isResuming = false;
123
124    /**
125     *  Premaster secret
126     */
127    protected byte[] preMasterSecret;
128
129    /**
130     * Exception occured in delegated task
131     */
132    protected Exception delegatedTaskErr;
133
134    // reference verify_data used to verify finished message
135    private byte[] verify_data = new byte[12];
136
137    // Encoding of "master secret" string: "master secret".getBytes()
138    private byte[] master_secret_bytes =
139            {109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116 };
140
141    // indicates whether protocol needs to send change cipher spec message
142    private boolean needSendCCSpec = false;
143
144    // indicates whether protocol needs to send change cipher spec message
145    protected boolean needSendHelloRequest = false;
146
147    /**
148     * SSLEngine owning this HandshakeProtocol
149     */
150    public SSLEngineImpl engineOwner;
151
152    /**
153     * SSLSocket owning this HandshakeProtocol
154     */
155    // BEGIN android-removed
156    // public SSLSocketImpl socketOwner;
157    // END android-removed
158
159    /**
160     * Creates HandshakeProtocol instance
161     * @param owner
162     */
163    protected HandshakeProtocol(Object owner) {
164        if (owner instanceof SSLEngineImpl) {
165            engineOwner = (SSLEngineImpl) owner;
166            nonBlocking = true;
167            this.parameters = engineOwner.sslParameters;
168        }
169        // BEGIN android-removed
170        // else if (owner instanceof SSLSocketImpl) {
171        //     socketOwner = (SSLSocketImpl) owner;
172        //     nonBlocking = false;
173        //     this.parameters = socketOwner.sslParameters;
174        // }
175        // END android-removed
176    }
177
178    /**
179     * Sets SSL Record Protocol
180     * @param recordProtocol
181     */
182    public void setRecordProtocol(SSLRecordProtocol recordProtocol) {
183        this.recordProtocol = recordProtocol;
184    }
185
186    /**
187     * Start session negotiation
188     * @param session
189     */
190    public abstract void start();
191
192    /**
193     * Stops the current session renegotiation process.
194     * Such functionality is needed when it is session renegotiation
195     * process and no_renegotiation alert message is received
196     * from another peer.
197     * @param session
198     */
199    protected void stop() {
200        clearMessages();
201        status = NOT_HANDSHAKING;
202    }
203
204    /**
205     * Returns handshake status
206     * @return
207     */
208    public SSLEngineResult.HandshakeStatus getStatus() {
209        if (io_stream.hasData() || needSendCCSpec ||
210                needSendHelloRequest || delegatedTaskErr != null) {
211            return SSLEngineResult.HandshakeStatus.NEED_WRAP;
212        }
213        if (!delegatedTasks.isEmpty()) {
214            return SSLEngineResult.HandshakeStatus.NEED_TASK;
215        }
216
217        switch (status) {
218        case HandshakeProtocol.NEED_UNWRAP:
219            return SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
220        case HandshakeProtocol.FINISHED:
221            status = NOT_HANDSHAKING;
222            clearMessages();
223            return SSLEngineResult.HandshakeStatus.FINISHED;
224        default: // HandshakeProtocol.NOT_HANDSHAKING:
225            return SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
226        }
227    }
228
229    /**
230     * Returns pending session
231     * @return session
232     */
233    public SSLSessionImpl getSession() {
234        return session;
235    }
236
237    protected void sendChangeCipherSpec() {
238        needSendCCSpec = true;
239    }
240
241    protected void sendHelloRequest() {
242        needSendHelloRequest = true;
243    }
244
245    /**
246     * Proceses inbound ChangeCipherSpec message
247     */
248    abstract void receiveChangeCipherSpec();
249
250    /**
251     * Creates and sends finished message
252     */
253    abstract void makeFinished();
254
255    /**
256     * Proceses inbound handshake messages
257     * @param bytes
258     */
259    public abstract void unwrap(byte[] bytes);
260
261    /**
262     * Processes SSLv2 Hello message
263     * @param bytes
264     */
265    public abstract void unwrapSSLv2(byte[] bytes);
266
267    /**
268     * Proceses outbound handshake messages
269     * @return
270     */
271    public byte[] wrap() {
272        if (delegatedTaskErr != null) {
273            // process error occured in delegated task
274            Exception e = delegatedTaskErr;
275            delegatedTaskErr = null;
276            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
277                    "Error occured in delegated task:" + e.getMessage(), e);
278        }
279        if (io_stream.hasData()) {
280            return recordProtocol.wrap(ContentType.HANDSHAKE, io_stream);
281        } else if (needSendCCSpec) {
282            makeFinished();
283            needSendCCSpec = false;
284            return recordProtocol.getChangeCipherSpecMesage(getSession());
285        } else if (needSendHelloRequest) {
286            needSendHelloRequest = false;
287            return recordProtocol.wrap(ContentType.HANDSHAKE,
288                    // hello request message
289                    // (see TLS v 1 specification:
290                    // http://www.ietf.org/rfc/rfc2246.txt)
291                    new byte[] {0, 0, 0, 0}, 0, 4);
292        } else {
293            return null; // nothing to send;
294        }
295    }
296
297    /**
298     * Sends fatal alert, breaks execution
299     *
300     * @param description
301     */
302    protected void sendWarningAlert(byte description) {
303        recordProtocol.alert(AlertProtocol.WARNING, description);
304    }
305
306    /**
307     * Sends fatal alert, breaks execution
308     *
309     * @param description
310     * @param reason
311     */
312    protected void fatalAlert(byte description, String reason) {
313        throw new AlertException(description, new SSLHandshakeException(reason));
314    }
315
316    /**
317     * Sends fatal alert, breaks execution
318     *
319     * @param description
320     * @param reason
321     * @param cause
322     */
323    protected void fatalAlert(byte description, String reason, Exception cause) {
324        throw new AlertException(description, new SSLException(reason, cause));
325    }
326
327    /**
328     * Sends fatal alert, breaks execution
329     *
330     * @param description
331     * @param cause
332     */
333    protected void fatalAlert(byte description, SSLException cause) {
334        throw new AlertException(description, cause);
335    }
336
337    /**
338     * Computers reference TLS verify_data that is used to verify finished message
339     * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS spec. 7.4.9. Finished</a>
340     * @param label
341     */
342    protected void computerReferenceVerifyDataTLS(String label) {
343        computerVerifyDataTLS(label, verify_data);
344    }
345
346    /**
347     * Computer TLS verify_data
348     * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS spec. 7.4.9. Finished</a>
349     * @param label
350     * @param buf
351     */
352    protected void computerVerifyDataTLS(String label, byte[] buf) {
353        byte[] md5_digest = io_stream.getDigestMD5();
354        byte[] sha_digest = io_stream.getDigestSHA();
355
356        byte[] digest = new byte[md5_digest.length + sha_digest.length];
357        System.arraycopy(md5_digest, 0, digest, 0, md5_digest.length);
358        System.arraycopy(sha_digest, 0, digest, md5_digest.length,
359                sha_digest.length);
360        try {
361            PRF.computePRF(buf, session.master_secret,
362                    label.getBytes(), digest);
363        } catch (GeneralSecurityException e) {
364            fatalAlert(AlertProtocol.INTERNAL_ERROR, "PRF error", e);
365        }
366    }
367
368    /**
369     * Computer reference SSLv3 verify_data that is used to verify finished message
370     * @see "SSLv3 spec. 7.6.9. Finished"
371     * @param label
372     */
373    protected void computerReferenceVerifyDataSSLv3(byte[] sender) {
374        verify_data = new byte[36];
375        computerVerifyDataSSLv3(sender, verify_data);
376    }
377
378    /**
379     * Computer SSLv3 verify_data
380     * @see "SSLv3 spec. 7.6.9. Finished"
381     * @param label
382     * @param buf
383     */
384    protected void computerVerifyDataSSLv3(byte[] sender, byte[] buf) {
385        MessageDigest md5;
386        MessageDigest sha;
387        try {
388            md5 = MessageDigest.getInstance("MD5");
389            sha = MessageDigest.getInstance("SHA-1");
390        } catch (Exception e) {
391            fatalAlert(AlertProtocol.INTERNAL_ERROR,
392                       "Could not initialize the Digest Algorithms.",
393                       e);
394            return;
395        }
396        try {
397            byte[] hanshake_messages = io_stream.getMessages();
398            md5.update(hanshake_messages);
399            md5.update(sender);
400            md5.update(session.master_secret);
401            byte[] b = md5.digest(SSLv3Constants.MD5pad1);
402            md5.update(session.master_secret);
403            md5.update(SSLv3Constants.MD5pad2);
404            System.arraycopy(md5.digest(b), 0, buf, 0, 16);
405
406            sha.update(hanshake_messages);
407            sha.update(sender);
408            sha.update(session.master_secret);
409            b = sha.digest(SSLv3Constants.SHApad1);
410            sha.update(session.master_secret);
411            sha.update(SSLv3Constants.SHApad2);
412            System.arraycopy(sha.digest(b), 0, buf, 16, 20);
413        } catch (Exception e) {
414            fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);
415
416        }
417    }
418
419    /**
420     * Verifies finished data
421     *
422     * @param data
423     * @param isServer
424     */
425    protected void verifyFinished(byte[] data) {
426        if (!Arrays.equals(verify_data, data)) {
427            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "Incorrect FINISED");
428        }
429    }
430
431    /**
432     * Sends fatal alert "UNEXPECTED MESSAGE"
433     *
434     */
435    protected void unexpectedMessage() {
436        fatalAlert(AlertProtocol.UNEXPECTED_MESSAGE, "UNEXPECTED MESSAGE");
437    }
438
439    /**
440     * Writes message to HandshakeIODataStream
441     *
442     * @param message
443     */
444    public void send(Message message) {
445        io_stream.writeUint8(message.getType());
446        io_stream.writeUint24(message.length());
447        message.send(io_stream);
448    }
449
450    /**
451     * Computers master secret
452     *
453     */
454    public void computerMasterSecret() {
455        byte[] seed = new byte[64];
456        System.arraycopy(clientHello.getRandom(), 0, seed, 0, 32);
457        System.arraycopy(serverHello.getRandom(), 0, seed, 32, 32);
458        session.master_secret = new byte[48];
459        if (serverHello.server_version[1] == 1) { // TLSv1
460            try {
461                PRF.computePRF(session.master_secret, preMasterSecret,
462                        master_secret_bytes, seed);
463            } catch (GeneralSecurityException e) {
464                fatalAlert(AlertProtocol.INTERNAL_ERROR, "PRF error", e);
465            }
466        } else { // SSL3.0
467            PRF.computePRF_SSLv3(session.master_secret, preMasterSecret, seed);
468        }
469
470        //delete preMasterSecret from memory
471        Arrays.fill(preMasterSecret, (byte)0);
472        preMasterSecret = null;
473    }
474
475    /**
476     * Returns a delegated task.
477     * @return Delegated task or null
478     */
479    public Runnable getTask() {
480        if (delegatedTasks.isEmpty()) {
481            return null;
482        }
483        return delegatedTasks.remove(0);
484    }
485
486    /**
487     *
488     * Clears previously sended and received handshake messages
489     */
490    protected void clearMessages() {
491        io_stream.clearBuffer();
492        clientHello = null;
493        serverHello = null;
494        serverCert = null;
495        serverKeyExchange = null;
496        certificateRequest = null;
497        serverHelloDone = null;
498        clientCert = null;
499        clientKeyExchange = null;
500        certificateVerify = null;
501        clientFinished = null;
502        serverFinished = null;
503    }
504
505    /**
506     * Returns RSA key length
507     * @param pk
508     * @return
509     * @throws NoSuchAlgorithmException
510     * @throws InvalidKeySpecException
511     */
512    protected static int getRSAKeyLength(PublicKey pk)
513            throws NoSuchAlgorithmException, InvalidKeySpecException {
514
515        BigInteger mod;
516        if (pk instanceof RSAKey) {
517            mod = ((RSAKey) pk).getModulus();
518        } else {
519            KeyFactory kf = KeyFactory.getInstance("RSA");
520            mod = kf.getKeySpec(pk, RSAPublicKeySpec.class)
521                    .getModulus();
522        }
523        return mod.bitLength();
524    }
525
526    /**
527     * Shutdownes the protocol. It will be impossiblke to use the instance
528     * after the calling of this method.
529     */
530    protected void shutdown() {
531        clearMessages();
532        session = null;
533        preMasterSecret = null;
534        delegatedTasks.clear();
535    }
536}
537