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