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