Home | History | Annotate | Download | only in jsse
      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