Package ch.ethz.inf.vs.scandium.dtls

Source Code of ch.ethz.inf.vs.scandium.dtls.Finished

/*******************************************************************************
* Copyright (c) 2014, Institute for Pervasive Computing, ETH Zurich.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Scandium (Sc) Security for Californium.
******************************************************************************/
package ch.ethz.inf.vs.scandium.dtls;

import java.util.Arrays;

import ch.ethz.inf.vs.scandium.dtls.AlertMessage.AlertDescription;
import ch.ethz.inf.vs.scandium.dtls.AlertMessage.AlertLevel;
import ch.ethz.inf.vs.scandium.util.DatagramReader;
import ch.ethz.inf.vs.scandium.util.DatagramWriter;

/**
* A Finished message is always sent immediately after a
* {@link ChangeCipherSpecMessage} to verify that the key exchange and
* authentication processes were successful. It is essential that a
* {@link ChangeCipherSpecMessage} be received between the other handshake
* messages and the Finished message. The Finished message is the first one
* protected with the just negotiated algorithms, keys, and secrets. The value
* handshake_messages includes all handshake messages starting at
* {@link ClientHello} up to, but not including, this {@link Finished} message.
* See <a href="http://tools.ietf.org/html/rfc5246#section-7.4.9">RFC 5246</a>.
*
* @author Stefan Jucker
*
*/
public class Finished extends HandshakeMessage {

  // Members ////////////////////////////////////////////////////////

  private byte[] verifyData;

  // Constructors ///////////////////////////////////////////////////

  /**
   * Generates the verify data according to <a
   * href="http://tools.ietf.org/html/rfc5246#section-7.4.9">RFC 5246</a>:<br />
   * <code>PRF(master_secret,
   * finished_label, Hash(handshake_messages))</code>.
   *
   * @param masterSecret
   *            the master_secret
   * @param isClient
   *            to determine the finished_label
   * @param handshakeHash
   *            the hash
   */
  public Finished(byte[] masterSecret, boolean isClient, byte[] handshakeHash) {
    verifyData = getVerifyData(masterSecret, isClient, handshakeHash);
  }

  /**
   * Called when reconstructing byteArray.
   *
   * @param verifyData
   */
  public Finished(byte[] verifyData) {
    this.verifyData = verifyData;
  }

  // Methods ////////////////////////////////////////////////////////
 
  /**
   * See <a href="http://tools.ietf.org/html/rfc5246#section-7.4.9">RFC
   * 5246</a>: All of the data from all messages in this handshake (not
   * including any HelloRequest messages) up to, but not including, this
   * message. This is only data visible at the handshake layer and does not
   * include record layer headers.
   *
   * @param masterSecret
   *            the master secret.
   * @param isClient
   *            whether the verify data comes from the client or the server.
   * @param handshakeHash
   *            the handshake hash.
   * @throws HandshakeException if the data can not be verified.
   */
  public void verifyData(byte[] masterSecret, boolean isClient, byte[] handshakeHash) throws HandshakeException {

    byte[] myVerifyData = getVerifyData(masterSecret, isClient, handshakeHash);
   
    boolean verified = Arrays.equals(myVerifyData, verifyData);
    if (!verified) {
      String message = "Could not verify the finished message:\nExpected: " + ByteArrayUtils.toHexString(myVerifyData) + "\nReceived: " + ByteArrayUtils.toHexString(verifyData);
      AlertMessage alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.HANDSHAKE_FAILURE);
      throw new HandshakeException(message, alert);
    }
  }

  private byte[] getVerifyData(byte[] masterSecret, boolean isClient, byte[] handshakeHash) {
    byte[] data = null;

    int labelId = (isClient) ? Handshaker.CLIENT_FINISHED_LABEL : Handshaker.SERVER_FINISHED_LABEL;
   
    /*
     * See http://tools.ietf.org/html/rfc5246#section-7.4.9: verify_data =
     * PRF(master_secret, finished_label, Hash(handshake_messages))
     * [0..verify_data_length-1];
     */
    data = Handshaker.doPRF(masterSecret, labelId, handshakeHash);

    return data;
  }

  @Override
  public HandshakeType getMessageType() {
    return HandshakeType.FINISHED;
  }

  @Override
  public int getMessageLength() {
    return verifyData.length;
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder(super.toString());
    sb.append("\t\tVerify Data: " + ByteArrayUtils.toHexString(verifyData) + "\n");

    return sb.toString();
  }

  // Serialization //////////////////////////////////////////////////

  @Override
  public byte[] fragmentToByteArray() {
    DatagramWriter writer = new DatagramWriter();
   
    writer.writeBytes(verifyData);

    return writer.toByteArray();
  }

  public static HandshakeMessage fromByteArray(byte[] byteArray) {
    DatagramReader reader = new DatagramReader(byteArray);

    byte[] verifyData = reader.readBytesLeft();

    return new Finished(verifyData);
  }

}
TOP

Related Classes of ch.ethz.inf.vs.scandium.dtls.Finished

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.