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.conscrypt; 19 20 import java.io.IOException; 21 import java.security.SecureRandom; 22 import libcore.io.Streams; 23 24 /** 25 * 26 * Represents server hello message. 27 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.1.3. 28 * Server hello.</a> 29 */ 30 public class ServerHello extends Message { 31 32 /** 33 * Server version 34 */ 35 byte[] server_version = new byte[2]; 36 37 /** 38 * Random bytes 39 */ 40 byte[] random = new byte[32]; 41 42 /** 43 * Session id 44 */ 45 byte[] session_id; 46 47 /** 48 * Selected cipher suite 49 */ 50 CipherSuite cipher_suite; 51 52 /** 53 * Selected compression method 54 */ 55 byte compression_method; 56 57 /** 58 * Creates outbound message 59 * @param sr 60 * @param server_version 61 * @param session_id 62 * @param cipher_suite 63 * @param compression_method 64 */ 65 public ServerHello(SecureRandom sr, byte[] server_version, 66 byte[] session_id, CipherSuite cipher_suite, byte compression_method) { 67 long gmt_unix_time = new java.util.Date().getTime() / 1000; 68 sr.nextBytes(random); 69 random[0] = (byte) ((gmt_unix_time & 0xFF000000) >>> 24); 70 random[1] = (byte) ((gmt_unix_time & 0xFF0000) >>> 16); 71 random[2] = (byte) ((gmt_unix_time & 0xFF00) >>> 8); 72 random[3] = (byte) (gmt_unix_time & 0xFF); 73 this.session_id = session_id; 74 this.cipher_suite = cipher_suite; 75 this.compression_method = compression_method; 76 this.server_version = server_version; 77 length = 38 + session_id.length; 78 } 79 80 /** 81 * Creates inbound message 82 * @param in 83 * @param length 84 * @throws IOException 85 */ 86 public ServerHello(HandshakeIODataStream in, int length) throws IOException { 87 88 server_version[0] = (byte) in.read(); 89 server_version[1] = (byte) in.read(); 90 Streams.readFully(in, random); 91 int size = in.readUint8(); 92 session_id = new byte[size]; 93 in.read(session_id, 0, size); 94 byte b0 = (byte) in.read(); 95 byte b1 = (byte) in.read(); 96 cipher_suite = CipherSuite.getByCode(b0, b1); 97 compression_method = (byte) in.read(); 98 this.length = 38 + session_id.length; 99 if (this.length != length) { 100 fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect ServerHello"); 101 } 102 103 } 104 105 /** 106 * Sends message 107 * @param out 108 */ 109 @Override 110 public void send(HandshakeIODataStream out) { 111 out.write(server_version); 112 out.write(random); 113 out.writeUint8(session_id.length); 114 out.write(session_id); 115 out.write(cipher_suite.toBytes()); 116 out.write(compression_method); 117 length = 38 + session_id.length; 118 } 119 120 /** 121 * Returns server random 122 * @return 123 */ 124 public byte[] getRandom() { 125 return random; 126 } 127 128 /** 129 * Returns message type 130 * @return 131 */ 132 @Override 133 public int getType() { 134 return Handshake.SERVER_HELLO; 135 } 136 } 137