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

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

/*******************************************************************************
* 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.List;

import ch.ethz.inf.vs.scandium.util.DatagramReader;
import ch.ethz.inf.vs.scandium.util.DatagramWriter;

/**
* The server will send this message in response to a {@link ClientHello}
* message when it was able to find an acceptable set of algorithms. If it
* cannot find such a match, it will respond with a handshake failure alert. See
* <a href="http://tools.ietf.org/html/rfc5246#section-7.4.1.3">RFC 5246</a> for
* further details.
*
* @author Stefan Jucker
*
*/
public class ServerHello extends HandshakeMessage {

  // DTLS-specific constants ///////////////////////////////////////////

  private static final int VERSION_BITS = 8; // for major and minor each

  private static final int RANDOM_BYTES = 32;

  private static final int SESSION_ID_LENGTH_BITS = 8;

  private static final int CIPHER_SUITE_BITS = 16;

  private static final int COMPRESSION_METHOD_BITS = 8;

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

  /**
   * This field will contain the lower of that suggested by the client in the
   * {@link ClientHello} and the highest supported by the server.
   */
  private ProtocolVersion serverVersion;

  /**
   * This structure is generated by the server and MUST be independently
   * generated from the {@link ClientHello}.random.
   */
  private Random random;

  /**
   * This is the identity of the session corresponding to this connection.
   */
  private SessionId sessionId;

  /**
   * The single {@link CipherSuite} selected by the server from the list in
   * {@link ClientHello}.cipher_suites.
   */
  private CipherSuite cipherSuite;

  /**
   * The single compression algorithm selected by the server from the list in
   * ClientHello.compression_methods.
   */
  private CompressionMethod compressionMethod;

  /**
   * A list of extensions. Note that only extensions offered by the client can
   * appear in the server's list.
   */
  private HelloExtensions extensions = null;

  // Constructor ////////////////////////////////////////////////////

  /**
   * Constructs a full ServerHello message. Only the HelloExtensions are
   * optional. See <a
   * href="http://tools.ietf.org/html/rfc5246#section-7.4.1.3">7.4.1.3. Server
   * Hello</a> for details.
   *
   * @param version
   *            the negotiated version (highest supported by server).
   * @param random
   *            the server's random.
   * @param sessionId
   *            the new session's identifier.
   * @param cipherSuite
   *            the negotiated cipher suite.
   * @param compressionMethod
   *            the negotiated compression method.
   * @param extensions
   *            a list of extensions supported by the client (potentially
   *            empty).
   */
  public ServerHello(ProtocolVersion version, Random random, SessionId sessionId, CipherSuite cipherSuite, CompressionMethod compressionMethod, HelloExtensions extensions) {
    this.serverVersion = version;
    this.random = random;
    this.sessionId = sessionId;
    this.cipherSuite = cipherSuite;
    this.compressionMethod = compressionMethod;
    this.extensions = extensions;
  }

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

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

    writer.write(serverVersion.getMajor(), VERSION_BITS);
    writer.write(serverVersion.getMinor(), VERSION_BITS);

    writer.writeBytes(random.getRandomBytes());

    writer.write(sessionId.length(), SESSION_ID_LENGTH_BITS);
    writer.writeBytes(sessionId.getSessionId());

    writer.write(cipherSuite.getCode(), CIPHER_SUITE_BITS);
    writer.write(compressionMethod.getCode(), COMPRESSION_METHOD_BITS);

    if (extensions != null) {
      writer.writeBytes(extensions.toByteArray());
    }

    return writer.toByteArray();
  }

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

    int major = reader.read(VERSION_BITS);
    int minor = reader.read(VERSION_BITS);
    ProtocolVersion version = new ProtocolVersion(major, minor);

    Random random = new Random(reader.readBytes(RANDOM_BYTES));

    int sessionIdLength = reader.read(SESSION_ID_LENGTH_BITS);
    SessionId sessionId = new SessionId(reader.readBytes(sessionIdLength));

    CipherSuite cipherSuite = CipherSuite.getTypeByCode(reader.read(CIPHER_SUITE_BITS));
    CompressionMethod compressionMethod = CompressionMethod.getMethodByCode(reader.read(COMPRESSION_METHOD_BITS));

    byte[] bytesLeft = reader.readBytesLeft();
    HelloExtensions extensions = null;
    if (bytesLeft.length > 0) {
      extensions = HelloExtensions.fromByteArray(bytesLeft);
    }

    return new ServerHello(version, random, sessionId, cipherSuite, compressionMethod, extensions);
  }

  // Methods ////////////////////////////////////////////////////////

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

  @Override
  public int getMessageLength() {

    /*
     * if no extensions set, empty; otherwise 2 bytes for field length and
     * then the length of the extensions. See
     * http://tools.ietf.org/html/rfc5246#section-7.4.1.2
     */
    int extensionsLength = (extensions != null) ? (2 + extensions.getLength()) : 0;

    /*
     * fixed sizes: version (2) + random (32) + session ID length (1) +
     * cipher suit (2) + compression method (1) = 38, variable sizes: session
     * ID
     */

    return 38 + sessionId.length() + extensionsLength;
  }

  public ProtocolVersion getServerVersion() {
    return serverVersion;
  }

  public void setServerVersion(ProtocolVersion serverVersion) {
    this.serverVersion = serverVersion;
  }

  public Random getRandom() {
    return random;
  }

  public void setRandom(Random random) {
    this.random = random;
  }

  public SessionId getSessionId() {
    return sessionId;
  }

  public void setSessionId(SessionId sessionId) {
    this.sessionId = sessionId;
  }

  public CipherSuite getCipherSuite() {
    return cipherSuite;
  }

  public void setCipherSuite(CipherSuite cipherSuite) {
    this.cipherSuite = cipherSuite;
  }

  public CompressionMethod getCompressionMethod() {
    return compressionMethod;
  }

  public void setCompressionMethod(CompressionMethod compressionMethod) {
    this.compressionMethod = compressionMethod;
  }
 
  public HelloExtensions getExtensions() {
    return extensions;
  }

  public void setExtensions(HelloExtensions extensions) {
    this.extensions = extensions;
  }
 
  /**
   * Gets the client's certificate type.
   *
   * @return the client's certificate type extension if available,
   *         otherwise <code>null</code>.
   */
  public ClientCertificateTypeExtension getClientCertificateTypeExtension() {
    if (extensions != null) {
      List<HelloExtension> exts = extensions.getExtensions();
      for (HelloExtension helloExtension : exts) {
        if (helloExtension instanceof ClientCertificateTypeExtension) {
          return (ClientCertificateTypeExtension) helloExtension;
        }
      }
    }
    return null;
  }
 
  /**
   *
   * @return the client's certificate type extension if available,
   *         otherwise <code>null</code>.
   */
  public ServerCertificateTypeExtension getServerCertificateTypeExtension() {
    if (extensions != null) {
      List<HelloExtension> exts = extensions.getExtensions();
      for (HelloExtension helloExtension : exts) {
        if (helloExtension instanceof ServerCertificateTypeExtension) {
          return (ServerCertificateTypeExtension) helloExtension;
        }
      }
    }
    return null;
  }
 
  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append(super.toString());
    sb.append("\t\tServer Version: " + serverVersion.getMajor() + ", " + serverVersion.getMinor() + "\n");
    sb.append("\t\tRandom: \n" + random.toString());
    sb.append("\t\tSession ID Length: " + sessionId.length() + "\n");
    if (sessionId.length() > 0) {
      sb.append("\t\tSession ID: " + ByteArrayUtils.toHexString(sessionId.getSessionId()) + "\n");
    }
    sb.append("\t\tCipher Suite: " + cipherSuite.toString() + "\n");
    sb.append("\t\tCompression Method: " + compressionMethod.toString() + "\n");
   
    if (extensions != null) {
      sb.append(extensions.toString());
    }

    return sb.toString();
  }

}
TOP

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

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.