1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1838375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Rootpackage org.conscrypt; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLProtocolException; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class performs functionality dedicated to SSL record layer. 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It unpacks and routes income data to the appropriate 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * client protocol (handshake, alert, application data protocols) 27f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * and packages outcome data into SSL/TLS records. 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Initially created object has null connection state and does not 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * perform any cryptography computations over the income/outcome data. 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * After handshake protocol agreed upon security parameters they are placed 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * into SSLSessionImpl object and available for record protocol as 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * pending session. The order of setting up of the pending session 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as an active session differs for client and server modes. 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * So for client mode the parameters are provided by handshake protocol 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * during retrieving of change_cipher_spec message to be sent (by calling of 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * getChangeCipherSpecMesage method). 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * For server side mode record protocol retrieves the parameters from 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * handshake protocol after receiving of client's change_cipher_spec message. 396670318007799f403594f0760382b8c23f7dda0fJesse Wilson * After the pending session has been set up as a current session, 406670318007799f403594f0760382b8c23f7dda0fJesse Wilson * new connection state object is created and used for encryption/decryption 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of the messages. 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Among with base functionality this class provides the information about 436670318007799f403594f0760382b8c23f7dda0fJesse Wilson * constrains on the data length, and information about correspondence 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of plain and encrypted data lengths. 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * For more information on TLS v1 see http://www.ietf.org/rfc/rfc2246.txt, 46f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * on SSL v3 see http://wp.netscape.com/eng/ssl3, 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * on SSL v2 see http://wp.netscape.com/eng/security/SSL_2.html. 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class SSLRecordProtocol { 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 52f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Maximum length of allowed plain data fragment 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as specified by TLS specification. 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 556670318007799f403594f0760382b8c23f7dda0fJesse Wilson protected static final int MAX_DATA_LENGTH = 16384; // 2^14 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Maximum length of allowed compressed data fragment 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as specified by TLS specification. 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 606670318007799f403594f0760382b8c23f7dda0fJesse Wilson protected static final int MAX_COMPRESSED_DATA_LENGTH 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project = MAX_DATA_LENGTH + 1024; 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Maximum length of allowed ciphered data fragment 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as specified by TLS specification. 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 666670318007799f403594f0760382b8c23f7dda0fJesse Wilson protected static final int MAX_CIPHERED_DATA_LENGTH 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project = MAX_COMPRESSED_DATA_LENGTH + 1024; 68f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes /** 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Maximum length of ssl record. It is counted as: 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * type(1) + version(2) + length(2) + MAX_CIPHERED_DATA_LENGTH 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 726670318007799f403594f0760382b8c23f7dda0fJesse Wilson protected static final int MAX_SSL_PACKET_SIZE 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project = MAX_CIPHERED_DATA_LENGTH + 5; 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // the SSL session used for connection 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private SSLSessionImpl session; 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // protocol version of the connection 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private byte[] version; 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // input stream of record protocol 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private SSLInputStream in; 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // handshake protocol object to which handshaking data will be transmitted 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private HandshakeProtocol handshakeProtocol; 826670318007799f403594f0760382b8c23f7dda0fJesse Wilson // alert protocol to indicate alerts occurred/received 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private AlertProtocol alertProtocol; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // application data object to which application data will be transmitted 8538375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Root private Appendable appData; 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // connection state holding object 87f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private ConnectionState 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project activeReadState, activeWriteState, pendingConnectionState; 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // logger 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Logger.Stream logger = Logger.getStream("record"); 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // flag indicating if session object has been changed after 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // handshake phase (to distinguish session pending state) 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean sessionWasChanged = false; 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // change cipher spec message content 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final byte[] change_cipher_spec_byte = new byte[] {1}; 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates an instance of record protocol and tunes 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * up the client protocols to use ut. 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param handshakeProtocol: HandshakeProtocol 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param alertProtocol: AlertProtocol 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in: SSLInputStream 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param appData: Appendable 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected SSLRecordProtocol(HandshakeProtocol handshakeProtocol, 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AlertProtocol alertProtocol, 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLInputStream in, 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Appendable appData) { 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.handshakeProtocol = handshakeProtocol; 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.handshakeProtocol.setRecordProtocol(this); 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.alertProtocol = alertProtocol; 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.alertProtocol.setRecordProtocol(this); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.in = in; 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.appData = appData; 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the session obtained during the handshake negotiation. 1226670318007799f403594f0760382b8c23f7dda0fJesse Wilson * If the handshake process was not completed, method returns null. 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the session in effect. 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected SSLSessionImpl getSession() { 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return session; 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the minimum possible length of the SSL record. 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int getMinRecordSize() { 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return (activeReadState == null) 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ? 6 // type + version + length + 1 byte of data 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project : 5 + activeReadState.getMinFragmentSize(); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the record length for the specified incoming data length. 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * If actual resulting record length is greater than 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * MAX_CIPHERED_DATA_LENGTH, MAX_CIPHERED_DATA_LENGTH is returned. 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int getRecordSize(int data_size) { 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (activeWriteState == null) { 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 5+data_size; // type + version + length + data_size 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int res = 5 + activeWriteState.getFragmentSize(data_size); 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return (res > MAX_CIPHERED_DATA_LENGTH) 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ? MAX_CIPHERED_DATA_LENGTH // so the source data should be 1516670318007799f403594f0760382b8c23f7dda0fJesse Wilson // split into several packets 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project : res; 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the upper bound of length of data containing in the record with 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified length. 159f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * If the provided record_size is greater or equal to 160f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * MAX_CIPHERED_DATA_LENGTH the returned value will be 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * MAX_DATA_LENGTH 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * counted as for data with 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * MAX_CIPHERED_DATA_LENGTH length. 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int getDataSize(int record_size) { 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project record_size -= 5; // - (type + version + length + data_size) 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (record_size > MAX_CIPHERED_DATA_LENGTH) { 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // the data of such size consists of the several packets 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return MAX_DATA_LENGTH; 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (activeReadState == null) { 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return record_size; 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 174f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson return activeReadState.getContentSize(record_size); 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Depending on the Connection State (Session) encrypts and compress 179f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * the provided data, and packs it into TLSCiphertext structure. 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param content_type: int 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return ssl packet created over the current connection state 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected byte[] wrap(byte content_type, DataStream dataStream) { 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] fragment = dataStream.getData(MAX_DATA_LENGTH); 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return wrap(content_type, fragment, 0, fragment.length); 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Depending on the Connection State (Session) encrypts and compress 190f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * the provided data, and packs it into TLSCiphertext structure. 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param content_type: int 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param fragment: byte[] 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return ssl packet created over the current connection state 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected byte[] wrap(byte content_type, 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] fragment, int offset, int len) { 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("SSLRecordProtocol.wrap: TLSPlaintext.fragment[" 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project +len+"]:"); 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.print(fragment, offset, len); 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (len > MAX_DATA_LENGTH) { 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new AlertException( 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AlertProtocol.INTERNAL_ERROR, 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new SSLProtocolException( 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "The provided chunk of data is too big: " + len 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + " > MAX_DATA_LENGTH == "+MAX_DATA_LENGTH)); 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] ciphered_fragment = fragment; 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (activeWriteState != null) { 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ciphered_fragment = 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project activeWriteState.encrypt(content_type, fragment, offset, len); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (ciphered_fragment.length > MAX_CIPHERED_DATA_LENGTH) { 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new AlertException( 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AlertProtocol.INTERNAL_ERROR, 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new SSLProtocolException( 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "The ciphered data increased more than on 1024 bytes")); 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("SSLRecordProtocol.wrap: TLSCiphertext.fragment[" 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project +ciphered_fragment.length+"]:"); 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.print(ciphered_fragment); 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return packetize(content_type, version, ciphered_fragment); 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private byte[] packetize(byte type, byte[] version, byte[] fragment) { 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] buff = new byte[5+fragment.length]; 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buff[0] = type; 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (version != null) { 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buff[1] = version[0]; 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buff[2] = version[1]; 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buff[1] = 3; 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buff[2] = 1; 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buff[3] = (byte) ((0x00FF00 & fragment.length) >> 8); 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buff[4] = (byte) (0x0000FF & fragment.length); 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(fragment, 0, buff, 5, fragment.length); 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return buff; 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Set the ssl session to be used after sending the changeCipherSpec message 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param session: SSLSessionImpl 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void setSession(SSLSessionImpl session) { 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!sessionWasChanged) { 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // session was not changed for current handshake process 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("SSLRecordProtocol.setSession: Set pending session"); 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println(" cipher name: " + session.getCipherSuite()); 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.session = session; 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // create new connection state 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pendingConnectionState = ((version == null) || (version[1] == 1)) 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ? (ConnectionState) new ConnectionStateTLS(getSession()) 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project : (ConnectionState) new ConnectionStateSSLv3(getSession()); 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sessionWasChanged = true; 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // wait for rehandshaking's session 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sessionWasChanged = false; 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the change cipher spec message to be sent to another peer. 269f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * The pending connection state will be built on the base of provided 270f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * session object 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The calling of this method triggers pending write connection state to 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * be active. 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return ssl record containing the "change cipher spec" message. 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected byte[] getChangeCipherSpecMesage(SSLSessionImpl session) { 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // make change_cipher_spec_message: 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] change_cipher_spec_message; 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (activeWriteState == null) { 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project change_cipher_spec_message = new byte[] { 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ContentType.CHANGE_CIPHER_SPEC, version[0], 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project version[1], 0, 1, 1 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }; 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project change_cipher_spec_message = 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project packetize(ContentType.CHANGE_CIPHER_SPEC, version, 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project activeWriteState.encrypt(ContentType.CHANGE_CIPHER_SPEC, 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project change_cipher_spec_byte, 0, 1)); 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setSession(session); 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project activeWriteState = pendingConnectionState; 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("SSLRecordProtocol.getChangeCipherSpecMesage"); 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("activeWriteState = pendingConnectionState"); 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.print(change_cipher_spec_message); 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return change_cipher_spec_message; 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Retrieves the fragment field of TLSCiphertext, and than 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * depending on the established Connection State 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * decrypts and decompresses it. The following structure is expected 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * on the input at the moment of the call: 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * struct { 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ContentType type; 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ProtocolVersion version; 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * uint16 length; 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * select (CipherSpec.cipher_type) { 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * case stream: GenericStreamCipher; 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * case block: GenericBlockCipher; 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * } fragment; 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * } TLSCiphertext; 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (as specified by RFC 2246, TLS v1 Protocol specification) 316f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * In addition this method can recognize SSLv2 hello message which 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * are often used to establish the SSL/TLS session. 319f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 3206670318007799f403594f0760382b8c23f7dda0fJesse Wilson * @throws IOException if some io errors have been occurred 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws EndOfSourceException if underlying input stream 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * has ran out of data. 3236670318007799f403594f0760382b8c23f7dda0fJesse Wilson * @throws EndOfBufferException if there was not enough data 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to build complete ssl packet. 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the type of unwrapped message. 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int unwrap() throws IOException { 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("SSLRecordProtocol.unwrap: BEGIN ["); 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int type = in.readUint8(); 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((type < ContentType.CHANGE_CIPHER_SPEC) 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || (type > ContentType.APPLICATION_DATA)) { 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("Non v3.1 message type:" + type); 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type >= 0x80) { 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // it is probably SSL v2 client_hello message 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // (see SSL v2 spec at: 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // http://wp.netscape.com/eng/security/SSL_2.html) 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length = (type & 0x7f) << 8 | in.read(); 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] fragment = in.read(length); 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeProtocol.unwrapSSLv2(fragment); 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println( 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "SSLRecordProtocol:unwrap ] END, SSLv2 type"); 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ContentType.HANDSHAKE; 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new AlertException(AlertProtocol.UNEXPECTED_MESSAGE, 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new SSLProtocolException( 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Unexpected message type has been received: "+type)); 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("Got the message of type: " + type); 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (version != null) { 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((in.read() != version[0]) 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || (in.read() != version[1])) { 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new AlertException(AlertProtocol.UNEXPECTED_MESSAGE, 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new SSLProtocolException( 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Unexpected message type has been received: " + 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project type)); 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 366f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson in.skip(2); // just skip the version number 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length = in.readUint16(); 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("TLSCiphertext.fragment["+length+"]: ..."); 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length > MAX_CIPHERED_DATA_LENGTH) { 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new AlertException(AlertProtocol.RECORD_OVERFLOW, 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new SSLProtocolException( 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Received message is too big.")); 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] fragment = in.read(length); 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.print(fragment); 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (activeReadState != null) { 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fragment = activeReadState.decrypt((byte) type, fragment); 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("TLSPlaintext.fragment:"); 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.print(fragment); 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fragment.length > MAX_DATA_LENGTH) { 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new AlertException(AlertProtocol.DECOMPRESSION_FAILURE, 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new SSLProtocolException( 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Decompressed plain data is too big.")); 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (type) { 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ContentType.CHANGE_CIPHER_SPEC: 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // notify handshake protocol: 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeProtocol.receiveChangeCipherSpec(); 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setSession(handshakeProtocol.getSession()); 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // change cipher spec message has been received, so: 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("activeReadState = pendingConnectionState"); 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project activeReadState = pendingConnectionState; 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ContentType.ALERT: 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project alert(fragment[0], fragment[1]); 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ContentType.HANDSHAKE: 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeProtocol.unwrap(fragment); 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ContentType.APPLICATION_DATA: 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println( 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "TLSCiphertext.unwrap: APP DATA["+length+"]:"); 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println(new String(fragment)); 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project appData.append(fragment); 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project default: 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new AlertException(AlertProtocol.UNEXPECTED_MESSAGE, 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new SSLProtocolException( 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Unexpected message type has been received: " + 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project type)); 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("SSLRecordProtocol:unwrap ] END, type: " + type); 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return type; 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Passes the alert information to the alert protocol. 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param level: byte 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param description: byte 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void alert(byte level, byte description) { 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (logger != null) { 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project logger.println("SSLRecordProtocol.allert: "+level+" "+description); 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project alertProtocol.alert(level, description); 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets up the SSL version used in this connection. 4446670318007799f403594f0760382b8c23f7dda0fJesse Wilson * This method is calling from the handshake protocol after 4453e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom * it becomes known which protocol version will be used. 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param ver: byte[] 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void setVersion(byte[] ver) { 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.version = ver; 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4546670318007799f403594f0760382b8c23f7dda0fJesse Wilson * Shuts down the protocol. It will be impossible to use the instance 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * after the calling of this method. 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void shutdown() { 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project session = null; 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project version = null; 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in = null; 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeProtocol = null; 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project alertProtocol = null; 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project appData = null; 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pendingConnectionState != null) { 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pendingConnectionState.shutdown(); 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pendingConnectionState = null; 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (activeReadState != null) { 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project activeReadState.shutdown(); 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project activeReadState = null; 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (activeReadState != null) { 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project activeReadState.shutdown(); 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project activeWriteState = null; 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 478