ClientKeyExchange.java revision f33eae7e84eb6d3b0f4e86b59605bb3de73009f3
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 org.apache.harmony.xnet.provider.jsse.Message;
21import org.apache.harmony.xnet.provider.jsse.Handshake;
22import org.apache.harmony.xnet.provider.jsse.HandshakeIODataStream;
23
24import java.io.IOException;
25import java.math.BigInteger;
26
27/**
28 * Represents client key exchange message
29 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.7.
30 * Client key exchange message</a>
31 *
32 */
33public class ClientKeyExchange extends Message {
34
35    /**
36     * Exchange keys
37     */
38    final byte[] exchange_keys;
39
40    /**
41     * Equals true if TLS1.0 protocol is used
42     */
43    boolean isTLS;
44
45    /**
46     * Equals true if key exchange algorithm is RSA
47     */
48    final boolean isRSA;
49
50    /**
51     * Creates outbound message
52     * @param encrypted_pre_master_secret
53     * @param isTLS
54     */
55    public ClientKeyExchange(byte[] encrypted_pre_master_secret, boolean isTLS) {
56        this.exchange_keys = encrypted_pre_master_secret;
57        length = this.exchange_keys.length;
58        if (isTLS) {
59            length += 2;
60        }
61        this.isTLS = isTLS;
62        isRSA = true;
63    }
64
65    /**
66     * Creates outbound message
67     * @param dh_Yc
68     */
69    public ClientKeyExchange(BigInteger dh_Yc) {
70        byte[] bb = dh_Yc.toByteArray();
71        if (bb[0] == 0) {
72            exchange_keys = new byte[bb.length-1];
73            System.arraycopy(bb, 1, exchange_keys, 0, exchange_keys.length);
74        } else {
75            exchange_keys = bb;
76        }
77        length = exchange_keys.length +2;
78        isRSA = false;
79    }
80
81    /**
82     * Creates empty message
83     *
84     */
85    public ClientKeyExchange() {
86        exchange_keys = new byte[0];
87        length = 0;
88        isRSA = false;
89    }
90
91    /**
92     * Creates inbound message
93     * @param length
94     * @param isTLS
95     * @param isRSA
96     * @throws IOException
97     */
98    public ClientKeyExchange(HandshakeIODataStream in, int length, boolean isTLS, boolean isRSA)
99            throws IOException {
100        this.isTLS = isTLS;
101        this.isRSA = isRSA;
102        if (length == 0) {
103            this.length = 0;
104            exchange_keys = new byte[0];
105        } else {
106            int size;
107            if (isRSA && !isTLS) {// SSL3.0 RSA
108                size = length;
109                this.length = size;
110            } else { // DH or TLSv1 RSA
111                size = in.readUint16();
112                this.length = 2 + size;
113            }
114            exchange_keys = new byte[size];
115            in.read(exchange_keys, 0, size);
116            if (this.length != length) {
117                fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect ClientKeyExchange");
118            }
119        }
120    }
121
122    /**
123     * Sends message
124     * @param out
125     */
126    @Override
127    public void send(HandshakeIODataStream out) {
128        if (exchange_keys.length != 0) {
129            if (!isRSA || isTLS) {// DH or TLSv1 RSA
130                out.writeUint16(exchange_keys.length);
131            }
132            out.write(exchange_keys);
133        }
134    }
135
136    /**
137     * Returns message type
138     * @return
139     */
140    @Override
141    public int getType() {
142        return Handshake.CLIENT_KEY_EXCHANGE;
143    }
144
145    /**
146     * Returns true if the message is empty (in case of implicit DH Yc)
147     * @return
148     */
149    public boolean isEmpty() {
150        return (exchange_keys.length == 0);
151    }
152}
153