ServerKeyExchange.java revision f33eae7e84eb6d3b0f4e86b59605bb3de73009f3
194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/*
294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  Licensed to the Apache Software Foundation (ASF) under one or more
394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  contributor license agreements.  See the NOTICE file distributed with
494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  this work for additional information regarding copyright ownership.
594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  The ASF licenses this file to You under the Apache License, Version 2.0
694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  (the "License"); you may not use this file except in compliance with
794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  the License.  You may obtain a copy of the License at
894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *
994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *     http://www.apache.org/licenses/LICENSE-2.0
1094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *
1194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  Unless required by applicable law or agreed to in writing, software
1294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  distributed under the License is distributed on an "AS IS" BASIS,
1394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  See the License for the specific language governing permissions and
1594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *  limitations under the License.
1694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */
1794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodpackage org.apache.harmony.xnet.provider.jsse;
1994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport org.apache.harmony.xnet.provider.jsse.Message;
2194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport java.io.IOException;
2394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport java.math.BigInteger;
2494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport java.security.KeyFactory;
2594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport java.security.interfaces.RSAPublicKey;
2694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport java.security.spec.RSAPublicKeySpec;
2794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/**
2994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *
3094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Represents server key exchange message.
3194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.3.
3294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Server key exchange message.</a>
3394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *
3494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */
3594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodpublic class ServerKeyExchange extends Message {
3694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
3794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                           //          ServerRSAParams        ServerDHParams
3894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    final BigInteger par1; //            rsa_modulus               dh_p
3994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    final byte[] bytes1;
4094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    final BigInteger par2; //            rsa_exponent              dh_g
4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    final byte[] bytes2;
4394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    final BigInteger par3; //                                      dh_Ys
4594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    final byte[] bytes3;
4694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    /**
4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * Signature
4994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     */
5094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    final byte[] hash;
5194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
5294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    private RSAPublicKey key;
5394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
5494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    /**
5594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * Creates outbound message
5694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @param par1 rsa_modulus or dh_p
5794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @param par2 rsa_exponent or dh_g
5894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @param par3 dh_Ys for ServerDHParams; should be null for ServerRSAParams
5994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @param hash should be null for anonymous SignatureAlgorithm
6094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     */
6194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    public ServerKeyExchange(BigInteger par1, BigInteger par2, BigInteger par3,
6294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            byte[] hash) {
6394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        this.par1 = par1;
6494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        this.par2 = par2;
6594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        this.par3 = par3;
6694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        this.hash = hash;
6794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
6894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bytes1 = toUnsignedByteArray(this.par1);
6994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
7094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bytes2 = toUnsignedByteArray(this.par2);
7194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
7294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        length = 4 + bytes1.length + bytes2.length;
7394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (hash != null) {
7494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            length += 2 + hash.length;
7594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
7694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (par3 == null) {
7794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            bytes3 = null;
7894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return;
7994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
8094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bytes3 = toUnsignedByteArray(this.par3);
8194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        length += 2 + bytes3.length;
8294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
8394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
8494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    /**
8594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * Remove first byte if 0. Needed because BigInteger.toByteArray() sometimes
8694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * returns a zero prefix.
8794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     */
8894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    public static byte[] toUnsignedByteArray(BigInteger bi) {
8994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (bi == null) {
9094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return null;
9194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
9294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        byte[] bb = bi.toByteArray();
9394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // bb is not null, and has at least 1 byte - ZERO is represented as [0]
9494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (bb[0] == 0) {
9594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            byte[] noZero = new byte[bb.length - 1];
9694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            System.arraycopy(bb, 1, noZero, 0, noZero.length);
9794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return noZero;
9894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        } else {
9994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return bb;
10094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
10194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
10294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
10394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    /**
10494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * Creates inbound message
10594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @param in
10694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @param length
10794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @param keyExchange
10894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @throws IOException
10994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     */
11094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    public ServerKeyExchange(HandshakeIODataStream in, int length,
11194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            int keyExchange) throws IOException {
11294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
11394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        int size = in.readUint16();
11494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bytes1 = in.read(size);
11594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        par1 = new BigInteger(1, bytes1);
11694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        this.length = 2 + bytes1.length;
11794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        size = in.readUint16();
11894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        bytes2 = in.read(size);
11994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        par2 = new BigInteger(1, bytes2);
12094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        this.length += 2 + bytes2.length;
12194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (keyExchange != CipherSuite.KeyExchange_RSA_EXPORT) {
12294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            size = in.readUint16();
12394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            bytes3 = in.read(size);
12494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            par3 = new BigInteger(1, bytes3);
12594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            this.length += 2 + bytes3.length;
12694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        } else {
12794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            par3 = null;
12894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            bytes3 = null;
12994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
13094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (keyExchange != CipherSuite.KeyExchange_DH_anon_EXPORT
13194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                && keyExchange != CipherSuite.KeyExchange_DH_anon) {
13294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            size = in.readUint16();
13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            hash = in.read(size);
13494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            this.length += 2 + hash.length;
13594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        } else {
13694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            hash = null;
13794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
13894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (this.length != length) {
13994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            fatalAlert(AlertProtocol.DECODE_ERROR,
14094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    "DECODE ERROR: incorrect ServerKeyExchange");
14194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
14294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
14394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
14494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    /**
14594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * Sends message
14694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @param out
14794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     */
14894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    @Override
14994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    public void send(HandshakeIODataStream out) {
15094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        out.writeUint16(bytes1.length);
15194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        out.write(bytes1);
15294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        out.writeUint16(bytes2.length);
15394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        out.write(bytes2);
15494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (bytes3 != null) {
15594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            out.writeUint16(bytes3.length);
15694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            out.write(bytes3);
15794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
15894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (hash != null) {
15994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            out.writeUint16(hash.length);
16094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            out.write(hash);
16194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
16294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
16394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
16494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    /**
16594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * Returns RSAPublicKey generated using ServerRSAParams
16694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * (rsa_modulus and rsa_exponent).
16794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     *
16894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @return
16994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     */
17094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    public RSAPublicKey getRSAPublicKey() {
17194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (key != null) {
17294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return key;
17394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
17494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        try {
17594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            KeyFactory kf = KeyFactory.getInstance("RSA");
17694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            key = (RSAPublicKey) kf.generatePublic(new RSAPublicKeySpec(par1,
17794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    par2));
17894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        } catch (Exception e) {
17994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return null;
18094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
18194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return key;
18294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
18394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
18494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    /**
18594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * Returns message type
18694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * @return
18794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     */
18894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    @Override
18994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    public int getType() {
19094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return Handshake.SERVER_KEY_EXCHANGE;
19194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
19294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
19394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
19494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood