/**
 * A Javascript implementation of Transport Layer Security (TLS).
 *
 * @author Dave Longley
 *
 * Copyright (c) 2009-2014 Digital Bazaar, Inc.
 *
 * The TLS Handshake Protocol involves the following steps:
 *
 * - Exchange hello messages to agree on algorithms, exchange random values,
 * and check for session resumption.
 *
 * - Exchange the necessary cryptographic parameters to allow the client and
 * server to agree on a premaster secret.
 *
 * - Exchange certificates and cryptographic information to allow the client
 * and server to authenticate themselves.
 *
 * - Generate a master secret from the premaster secret and exchanged random
 * values.
 *
 * - Provide security parameters to the record layer.
 *
 * - Allow the client and server to verify that their peer has calculated the
 * same security parameters and that the handshake occurred without tampering
 * by an attacker.
 *
 * Up to 4 different messages may be sent during a key exchange. The server
 * certificate, the server key exchange, the client certificate, and the
 * client key exchange.
 *
 * A typical handshake (from the client's perspective).
 *
 * 1. Client sends ClientHello.
 * 2. Client receives ServerHello.
 * 3. Client receives optional Certificate.
 * 4. Client receives optional ServerKeyExchange.
 * 5. Client receives ServerHelloDone.
 * 6. Client sends optional Certificate.
 * 7. Client sends ClientKeyExchange.
 * 8. Client sends optional CertificateVerify.
 * 9. Client sends ChangeCipherSpec.
 * 10. Client sends Finished.
 * 11. Client receives ChangeCipherSpec.
 * 12. Client receives Finished.
 * 13. Client sends/receives application data.
 *
 * To reuse an existing session:
 *
 * 1. Client sends ClientHello with session ID for reuse.
 * 2. Client receives ServerHello with same session ID if reusing.
 * 3. Client receives ChangeCipherSpec message if reusing.
 * 4. Client receives Finished.
 * 5. Client sends ChangeCipherSpec.
 * 6. Client sends Finished.
 *
 * Note: Client ignores HelloRequest if in the middle of a handshake.
 *
 * Record Layer:
 *
 * The record layer fragments information blocks into TLSPlaintext records
 * carrying data in chunks of 2^14 bytes or less. Client message boundaries are
 * not preserved in the record layer (i.e., multiple client messages of the
 * same ContentType MAY be coalesced into a single TLSPlaintext record, or a
 * single message MAY be fragmented across several records).
 *
 * struct {
 *   uint8 major;
 *   uint8 minor;
 * } ProtocolVersion;
 *
 * struct {
 *   ContentType type;
 *   ProtocolVersion version;
 *   uint16 length;
 *   opaque fragment[TLSPlaintext.length];
 * } TLSPlaintext;
 *
 * type:
 *   The higher-level protocol used to process the enclosed fragment.
 *
 * version:
 *   The version of the protocol being employed. TLS Version 1.2 uses version
 *   {3, 3}. TLS Version 1.0 uses version {3, 1}. Note that a client that
 *   supports multiple versions of TLS may not know what version will be
 *   employed before it receives the ServerHello.
 *
 * length:
 *   The length (in bytes) of the following TLSPlaintext.fragment. The length
 *   MUST NOT exceed 2^14 = 16384 bytes.
 *
 * fragment:
 *   The application data. This data is transparent and treated as an
 *   independent block to be dealt with by the higher-level protocol specified
 *   by the type field.
 *
 * Implementations MUST NOT send zero-length fragments of Handshake, Alert, or
 * ChangeCipherSpec content types. Zero-length fragments of Application data
 * MAY be sent as they are potentially useful as a traffic analysis
 * countermeasure.
 *
 * Note: Data of different TLS record layer content types MAY be interleaved.
 * Application data is generally of lower precedence for transmission than
 * other content types. However, records MUST be delivered to the network in
 * the same order as they are protected by the record layer. Recipients MUST
 * receive and process interleaved application layer traffic during handshakes
 * subsequent to the first one on a connection.
 *
 * struct {
 *   ContentType type;       // same as TLSPlaintext.type
 *   ProtocolVersion version;// same as TLSPlaintext.version
 *   uint16 length;
 *   opaque fragment[TLSCompressed.length];
 * } TLSCompressed;
 *
 * length:
 *   The length (in bytes) of the following TLSCompressed.fragment.
 *   The length MUST NOT exceed 2^14 + 1024.
 *
 * fragment:
 *   The compressed form of TLSPlaintext.fragment.
 *
 * Note: A CompressionMethod.null operation is an identity operation; no fields
 * are altered. In this implementation, since no compression is supported,
 * uncompressed records are always the same as compressed records.
 *
 * Encryption Information:
 *
 * The encryption and MAC functions translate a TLSCompressed structure into a
 * TLSCiphertext. The decryption functions reverse the process. The MAC of the
 * record also includes a sequence number so that missing, extra, or repeated
 * messages are detectable.
 *
 * struct {
 *   ContentType type;
 *   ProtocolVersion version;
 *   uint16 length;
 *   select (SecurityParameters.cipher_type) {
 *     case stream: GenericStreamCipher;
 *     case block:  GenericBlockCipher;
 *     case aead:   GenericAEADCipher;
 *   } fragment;
 * } TLSCiphertext;
 *
 * type:
 *   The type field is identical to TLSCompressed.type.
 *
 * version:
 *   The version field is identical to TLSCompressed.version.
 *
 * length:
 *   The length (in bytes) of the following TLSCiphertext.fragment.
 *   The length MUST NOT exceed 2^14 + 2048.
 *
 * fragment:
 *   The encrypted form of TLSCompressed.fragment, with the MAC.
 *
 * Note: Only CBC Block Ciphers are supported by this implementation.
 *
 * The TLSCompressed.fragment structures are converted to/from block
 * TLSCiphertext.fragment structures.
 *
 * struct {
 *   opaque IV[SecurityParameters.record_iv_length];
 *   block-ciphered struct {
 *     opaque content[TLSCompressed.length];
 *     opaque MAC[SecurityParameters.mac_length];
 *     uint8 padding[GenericBlockCipher.padding_length];
 *     uint8 padding_length;
 *   };
 * } GenericBlockCipher;
 *
 * The MAC is generated as described in Section 6.2.3.1.
 *
 * IV:
 *   The Initialization Vector (IV) SHOULD be chosen at random, and MUST be
 *   unpredictable. Note that in versions of TLS prior to 1.1, there was no
 *   IV field, and the last ciphertext block of the previous record (the "CBC
 *   residue") was used as the IV. This was changed to prevent the attacks
 *   described in [CBCATT]. For block ciphers, the IV length is of length
 *   SecurityParameters.record_iv_length, which is equal to the
 *   SecurityParameters.block_size.
 *
 * padding:
 *   Padding that is added to force the length of the plaintext to be an
 *   integral multiple of the block cipher's block length. The padding MAY be
 *   any length up to 255 bytes, as long as it results in the
 *   TLSCiphertext.length being an integral multiple of the block length.
 *   Lengths longer than necessary might be desirable to frustrate attacks on
 *   a protocol that are based on analysis of the lengths of exchanged
 *   messages. Each uint8 in the padding data vector MUST be filled with the
 *   padding length value. The receiver MUST check this padding and MUST use
 *   the bad_record_mac alert to indicate padding errors.
 *
 * padding_length:
 *   The padding length MUST be such that the total size of the
 *   GenericBlockCipher structure is a multiple of the cipher's block length.
 *   Legal values range from zero to 255, inclusive. This length specifies the
 *   length of the padding field exclusive of the padding_length field itself.
 *
 * The encrypted data length (TLSCiphertext.length) is one more than the sum of
 * SecurityParameters.block_length, TLSCompressed.length,
 * SecurityParameters.mac_length, and padding_length.
 *
 * Example: If the block length is 8 bytes, the content length
 * (TLSCompressed.length) is 61 bytes, and the MAC length is 20 bytes, then the
 * length before padding is 82 bytes (this does not include the IV. Thus, the
 * padding length modulo 8 must be equal to 6 in order to make the total length
 * an even multiple of 8 bytes (the block length). The padding length can be
 * 6, 14, 22, and so on, through 254. If the padding length were the minimum
 * necessary, 6, the padding would be 6 bytes, each containing the value 6.
 * Thus, the last 8 octets of the GenericBlockCipher before block encryption
 * would be xx 06 06 06 06 06 06 06, where xx is the last octet of the MAC.
 *
 * Note: With block ciphers in CBC mode (Cipher Block Chaining), it is critical
 * that the entire plaintext of the record be known before any ciphertext is
 * transmitted. Otherwise, it is possible for the attacker to mount the attack
 * described in [CBCATT].
 *
 * Implementation note: Canvel et al. [CBCTIME] have demonstrated a timing
 * attack on CBC padding based on the time required to compute the MAC. In
 * order to defend against this attack, implementations MUST ensure that
 * record processing time is essentially the same whether or not the padding
 * is correct. In general, the best way to do this is to compute the MAC even
 * if the padding is incorrect, and only then reject the packet. For instance,
 * if the pad appears to be incorrect, the implementation might assume a
 * zero-length pad and then compute the MAC. This leaves a small timing
 * channel, since MAC performance depends, to some extent, on the size of the
 * data fragment, but it is not believed to be large enough to be exploitable,
 * due to the large block size of existing MACs and the small size of the
 * timing signal.
 */
(function() {
/* ########## Begin module implementation ########## */
function initModule(forge) {

/**
 * Generates pseudo random bytes by mixing the result of two hash functions,
 * MD5 and SHA-1.
 *
 * prf_TLS1(secret, label, seed) =
 *   P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed);
 *
 * Each P_hash function functions as follows:
 *
 * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
 *                        HMAC_hash(secret, A(2) + seed) +
 *                        HMAC_hash(secret, A(3) + seed) + ...
 * A() is defined as:
 *   A(0) = seed
 *   A(i) = HMAC_hash(secret, A(i-1))
 *
 * The '+' operator denotes concatenation.
 *
 * As many iterations A(N) as are needed are performed to generate enough
 * pseudo random byte output. If an iteration creates more data than is
 * necessary, then it is truncated.
 *
 * Therefore:
 * A(1) = HMAC_hash(secret, A(0))
 *      = HMAC_hash(secret, seed)
 * A(2) = HMAC_hash(secret, A(1))
 *      = HMAC_hash(secret, HMAC_hash(secret, seed))
 *
 * Therefore:
 * P_hash(secret, seed) =
 *   HMAC_hash(secret, HMAC_hash(secret, A(0)) + seed) +
 *   HMAC_hash(secret, HMAC_hash(secret, A(1)) + seed) +
 *   ...
 *
 * Therefore:
 * P_hash(secret, seed) =
 *   HMAC_hash(secret, HMAC_hash(secret, seed) + seed) +
 *   HMAC_hash(secret, HMAC_hash(secret, HMAC_hash(secret, seed)) + seed) +
 *   ...
 *
 * @param secret the secret to use.
 * @param label the label to use.
 * @param seed the seed value to use.
 * @param length the number of bytes to generate.
 *
 * @return the pseudo random bytes in a byte buffer.
 */
var prf_TLS1 = function(secret, label, seed, length) {
  var rval = forge.util.createBuffer();

  /* For TLS 1.0, the secret is split in half, into two secrets of equal
    length. If the secret has an odd length then the last byte of the first
    half will be the same as the first byte of the second. The length of the
    two secrets is half of the secret rounded up. */
  var idx = (secret.length >> 1);
  var slen = idx + (secret.length & 1);
  var s1 = secret.substr(0, slen);
  var s2 = secret.substr(idx, slen);
  var ai = forge.util.createBuffer();
  var hmac = forge.hmac.create();
  seed = label + seed;

  // determine the number of iterations that must be performed to generate
  // enough output bytes, md5 creates 16 byte hashes, sha1 creates 20
  var md5itr = Math.ceil(length / 16);
  var sha1itr = Math.ceil(length / 20);

  // do md5 iterations
  hmac.start('MD5', s1);
  var md5bytes = forge.util.createBuffer();
  ai.putBytes(seed);
  for(var i = 0; i < md5itr; ++i) {
    // HMAC_hash(secret, A(i-1))
    hmac.start(null, null);
    hmac.update(ai.getBytes());
    ai.putBuffer(hmac.digest());

    // HMAC_hash(secret, A(i) + seed)
    hmac.start(null, null);
    hmac.update(ai.bytes() + seed);
    md5bytes.putBuffer(hmac.digest());
  }

  // do sha1 iterations
  hmac.start('SHA1', s2);
  var sha1bytes = forge.util.createBuffer();
  ai.clear();
  ai.putBytes(seed);
  for(var i = 0; i < sha1itr; ++i) {
    // HMAC_hash(secret, A(i-1))
    hmac.start(null, null);
    hmac.update(ai.getBytes());
    ai.putBuffer(hmac.digest());

    // HMAC_hash(secret, A(i) + seed)
    hmac.start(null, null);
    hmac.update(ai.bytes() + seed);
    sha1bytes.putBuffer(hmac.digest());
  }

  // XOR the md5 bytes with the sha1 bytes
  rval.putBytes(forge.util.xorBytes(
    md5bytes.getBytes(), sha1bytes.getBytes(), length));

  return rval;
};

/**
 * Generates pseudo random bytes using a SHA256 algorithm. For TLS 1.2.
 *
 * @param secret the secret to use.
 * @param label the label to use.
 * @param seed the seed value to use.
 * @param length the number of bytes to generate.
 *
 * @return the pseudo random bytes in a byte buffer.
 */
var prf_sha256 = function(secret, label, seed, length) {
   // FIXME: implement me for TLS 1.2
};

/**
 * Gets a MAC for a record using the SHA-1 hash algorithm.
 *
 * @param key the mac key.
 * @param state the sequence number (array of two 32-bit integers).
 * @param record the record.
 *
 * @return the sha-1 hash (20 bytes) for the given record.
 */
var hmac_sha1 = function(key, seqNum, record) {
  /* MAC is computed like so:
  HMAC_hash(
    key, seqNum +
      TLSCompressed.type +
      TLSCompressed.version +
      TLSCompressed.length +
      TLSCompressed.fragment)
  */
  var hmac = forge.hmac.create();
  hmac.start('SHA1', key);
  var b = forge.util.createBuffer();
  b.putInt32(seqNum[0]);
  b.putInt32(seqNum[1]);
  b.putByte(record.type);
  b.putByte(record.version.major);
  b.putByte(record.version.minor);
  b.putInt16(record.length);
  b.putBytes(record.fragment.bytes());
  hmac.update(b.getBytes());
  return hmac.digest().getBytes();
};

/**
 * Compresses the TLSPlaintext record into a TLSCompressed record using the
 * deflate algorithm.
 *
 * @param c the TLS connection.
 * @param record the TLSPlaintext record to compress.
 * @param s the ConnectionState to use.
 *
 * @return true on success, false on failure.
 */
var deflate = function(c, record, s) {
  var rval = false;

  try {
    var bytes = c.deflate(record.fragment.getBytes());
    record.fragment = forge.util.createBuffer(bytes);
    record.length = bytes.length;
    rval = true;
  } catch(ex) {
    // deflate error, fail out
  }

  return rval;
};

/**
 * Decompresses the TLSCompressed record into a TLSPlaintext record using the
 * deflate algorithm.
 *
 * @param c the TLS connection.
 * @param record the TLSCompressed record to decompress.
 * @param s the ConnectionState to use.
 *
 * @return true on success, false on failure.
 */
var inflate = function(c, record, s) {
  var rval = false;

  try {
    var bytes = c.inflate(record.fragment.getBytes());
    record.fragment = forge.util.createBuffer(bytes);
    record.length = bytes.length;
    rval = true;
  } catch(ex) {
    // inflate error, fail out
  }

  return rval;
};

/**
 * Reads a TLS variable-length vector from a byte buffer.
 *
 * Variable-length vectors are defined by specifying a subrange of legal
 * lengths, inclusively, using the notation <floor..ceiling>. When these are
 * encoded, the actual length precedes the vector's contents in the byte
 * stream. The length will be in the form of a number consuming as many bytes
 * as required to hold the vector's specified maximum (ceiling) length. A
 * variable-length vector with an actual length field of zero is referred to
 * as an empty vector.
 *
 * @param b the byte buffer.
 * @param lenBytes the number of bytes required to store the length.
 *
 * @return the resulting byte buffer.
 */
var readVector = function(b, lenBytes) {
  var len = 0;
  switch(lenBytes) {
  case 1:
    len = b.getByte();
    break;
  case 2:
    len = b.getInt16();
    break;
  case 3:
    len = b.getInt24();
    break;
  case 4:
    len = b.getInt32();
    break;
  }

  // read vector bytes into a new buffer
  return forge.util.createBuffer(b.getBytes(len));
};

/**
 * Writes a TLS variable-length vector to a byte buffer.
 *
 * @param b the byte buffer.
 * @param lenBytes the number of bytes required to store the length.
 * @param v the byte buffer vector.
 */
var writeVector = function(b, lenBytes, v) {
  // encode length at the start of the vector, where the number of bytes for
  // the length is the maximum number of bytes it would take to encode the
  // vector's ceiling
  b.putInt(v.length(), lenBytes << 3);
  b.putBuffer(v);
};

/**
 * The tls implementation.
 */
var tls = {};

/**
 * Version: TLS 1.2 = 3.3, TLS 1.1 = 3.2, TLS 1.0 = 3.1. Both TLS 1.1 and
 * TLS 1.2 were still too new (ie: openSSL didn't implement them) at the time
 * of this implementation so TLS 1.0 was implemented instead.
 */
tls.Versions = {
  TLS_1_0: {major: 3, minor: 1},
  TLS_1_1: {major: 3, minor: 2},
  TLS_1_2: {major: 3, minor: 3}
};
tls.SupportedVersions = [
  tls.Versions.TLS_1_1,
  tls.Versions.TLS_1_0
];
tls.Version = tls.SupportedVersions[0];

/**
 * Maximum fragment size. True maximum is 16384, but we fragment before that
 * to allow for unusual small increases during compression.
 */
tls.MaxFragment = 16384 - 1024;

/**
 * Whether this entity is considered the "client" or "server".
 * enum { server, client } ConnectionEnd;
 */
tls.ConnectionEnd = {
  server: 0,
  client: 1
};

/**
 * Pseudo-random function algorithm used to generate keys from the master
 * secret.
 * enum { tls_prf_sha256 } PRFAlgorithm;
 */
tls.PRFAlgorithm = {
  tls_prf_sha256: 0
};

/**
 * Bulk encryption algorithms.
 * enum { null, rc4, des3, aes } BulkCipherAlgorithm;
 */
tls.BulkCipherAlgorithm = {
  none: null,
  rc4: 0,
  des3: 1,
  aes: 2
};

/**
 * Cipher types.
 * enum { stream, block, aead } CipherType;
 */
tls.CipherType = {
  stream: 0,
  block: 1,
  aead: 2
};

/**
 * MAC (Message Authentication Code) algorithms.
 * enum { null, hmac_md5, hmac_sha1, hmac_sha256,
 *   hmac_sha384, hmac_sha512} MACAlgorithm;
 */
tls.MACAlgorithm = {
  none: null,
  hmac_md5: 0,
  hmac_sha1: 1,
  hmac_sha256: 2,
  hmac_sha384: 3,
  hmac_sha512: 4
};

/**
 * Compression algorithms.
 * enum { null(0), deflate(1), (255) } CompressionMethod;
 */
tls.CompressionMethod = {
  none: 0,
  deflate: 1
};

/**
 * TLS record content types.
 * enum {
 *   change_cipher_spec(20), alert(21), handshake(22),
 *   application_data(23), (255)
 * } ContentType;
 */
tls.ContentType = {
  change_cipher_spec: 20,
  alert: 21,
  handshake: 22,
  application_data: 23,
  heartbeat: 24
};

/**
 * TLS handshake types.
 * enum {
 *   hello_request(0), client_hello(1), server_hello(2),
 *   certificate(11), server_key_exchange (12),
 *   certificate_request(13), server_hello_done(14),
 *   certificate_verify(15), client_key_exchange(16),
 *   finished(20), (255)
 * } HandshakeType;
 */
tls.HandshakeType = {
  hello_request: 0,
  client_hello: 1,
  server_hello: 2,
  certificate: 11,
  server_key_exchange: 12,
  certificate_request: 13,
  server_hello_done: 14,
  certificate_verify: 15,
  client_key_exchange: 16,
  finished: 20
};

/**
 * TLS Alert Protocol.
 *
 * enum { warning(1), fatal(2), (255) } AlertLevel;
 *
 * enum {
 *   close_notify(0),
 *   unexpected_message(10),
 *   bad_record_mac(20),
 *   decryption_failed(21),
 *   record_overflow(22),
 *   decompression_failure(30),
 *   handshake_failure(40),
 *   bad_certificate(42),
 *   unsupported_certificate(43),
 *   certificate_revoked(44),
 *   certificate_expired(45),
 *   certificate_unknown(46),
 *   illegal_parameter(47),
 *   unknown_ca(48),
 *   access_denied(49),
 *   decode_error(50),
 *   decrypt_error(51),
 *   export_restriction(60),
 *   protocol_version(70),
 *   insufficient_security(71),
 *   internal_error(80),
 *   user_canceled(90),
 *   no_renegotiation(100),
 *   (255)
 * } AlertDescription;
 *
 * struct {
 *   AlertLevel level;
 *   AlertDescription description;
 * } Alert;
 */
tls.Alert = {};
tls.Alert.Level = {
  warning: 1,
  fatal: 2
};
tls.Alert.Description = {
  close_notify: 0,
  unexpected_message: 10,
  bad_record_mac: 20,
  decryption_failed: 21,
  record_overflow: 22,
  decompression_failure: 30,
  handshake_failure: 40,
  bad_certificate: 42,
  unsupported_certificate: 43,
  certificate_revoked: 44,
  certificate_expired: 45,
  certificate_unknown: 46,
  illegal_parameter: 47,
  unknown_ca: 48,
  access_denied: 49,
  decode_error: 50,
  decrypt_error: 51,
  export_restriction: 60,
  protocol_version: 70,
  insufficient_security: 71,
  internal_error: 80,
  user_canceled: 90,
  no_renegotiation: 100
};

/**
 * TLS Heartbeat Message types.
 * enum {
 *   heartbeat_request(1),
 *   heartbeat_response(2),
 *   (255)
 * } HeartbeatMessageType;
 */
tls.HeartbeatMessageType = {
  heartbeat_request: 1,
  heartbeat_response: 2
};

/**
 * Supported cipher suites.
 */
tls.CipherSuites = {};

/**
 * Gets a supported cipher suite from its 2 byte ID.
 *
 * @param twoBytes two bytes in a string.
 *
 * @return the matching supported cipher suite or null.
 */
tls.getCipherSuite = function(twoBytes) {
  var rval = null;
  for(var key in tls.CipherSuites) {
    var cs = tls.CipherSuites[key];
    if(cs.id[0] === twoBytes.charCodeAt(0) &&
      cs.id[1] === twoBytes.charCodeAt(1)) {
      rval = cs;
      break;
    }
  }
  return rval;
};

/**
 * Called when an unexpected record is encountered.
 *
 * @param c the connection.
 * @param record the record.
 */
tls.handleUnexpected = function(c, record) {
  // if connection is client and closed, ignore unexpected messages
  var ignore = (!c.open && c.entity === tls.ConnectionEnd.client);
  if(!ignore) {
    c.error(c, {
      message: 'Unexpected message. Received TLS record out of order.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.unexpected_message
      }
    });
  }
};

/**
 * Called when a client receives a HelloRequest record.
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleHelloRequest = function(c, record, length) {
  // ignore renegotiation requests from the server during a handshake, but
  // if handshaking, send a warning alert that renegotation is denied
  if(!c.handshaking && c.handshakes > 0) {
    // send alert warning
    tls.queue(c, tls.createAlert(c, {
       level: tls.Alert.Level.warning,
       description: tls.Alert.Description.no_renegotiation
    }));
    tls.flush(c);
  }

  // continue
  c.process();
};

/**
 * Parses a hello message from a ClientHello or ServerHello record.
 *
 * @param record the record to parse.
 *
 * @return the parsed message.
 */
tls.parseHelloMessage = function(c, record, length) {
  var msg = null;

  var client = (c.entity === tls.ConnectionEnd.client);

  // minimum of 38 bytes in message
  if(length < 38) {
    c.error(c, {
      message: client ?
        'Invalid ServerHello message. Message too short.' :
        'Invalid ClientHello message. Message too short.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.illegal_parameter
      }
    });
  } else {
    // use 'remaining' to calculate # of remaining bytes in the message
    var b = record.fragment;
    var remaining = b.length();
    msg = {
      version: {
        major: b.getByte(),
        minor: b.getByte()
      },
      random: forge.util.createBuffer(b.getBytes(32)),
      session_id: readVector(b, 1),
      extensions: []
    };
    if(client) {
      msg.cipher_suite = b.getBytes(2);
      msg.compression_method = b.getByte();
    } else {
      msg.cipher_suites = readVector(b, 2);
      msg.compression_methods = readVector(b, 1);
    }

    // read extensions if there are any bytes left in the message
    remaining = length - (remaining - b.length());
    if(remaining > 0) {
      // parse extensions
      var exts = readVector(b, 2);
      while(exts.length() > 0) {
        msg.extensions.push({
          type: [exts.getByte(), exts.getByte()],
          data: readVector(exts, 2)
        });
      }

      // TODO: make extension support modular
      if(!client) {
        for(var i = 0; i < msg.extensions.length; ++i) {
          var ext = msg.extensions[i];

          // support SNI extension
          if(ext.type[0] === 0x00 && ext.type[1] === 0x00) {
            // get server name list
            var snl = readVector(ext.data, 2);
            while(snl.length() > 0) {
              // read server name type
              var snType = snl.getByte();

              // only HostName type (0x00) is known, break out if
              // another type is detected
              if(snType !== 0x00) {
                break;
              }

              // add host name to server name list
              c.session.extensions.server_name.serverNameList.push(
                readVector(snl, 2).getBytes());
            }
          }
        }
      }
    }

    // version already set, do not allow version change
    if(c.session.version) {
      if(msg.version.major !== c.session.version.major ||
        msg.version.minor !== c.session.version.minor) {
        return c.error(c, {
          message: 'TLS version change is disallowed during renegotiation.',
          send: true,
          alert: {
            level: tls.Alert.Level.fatal,
            description: tls.Alert.Description.protocol_version
          }
        });
      }
    }

    // get the chosen (ServerHello) cipher suite
    if(client) {
      // FIXME: should be checking configured acceptable cipher suites
      c.session.cipherSuite = tls.getCipherSuite(msg.cipher_suite);
    } else {
      // get a supported preferred (ClientHello) cipher suite
      // choose the first supported cipher suite
      var tmp = forge.util.createBuffer(msg.cipher_suites.bytes());
      while(tmp.length() > 0) {
        // FIXME: should be checking configured acceptable suites
        // cipher suites take up 2 bytes
        c.session.cipherSuite = tls.getCipherSuite(tmp.getBytes(2));
        if(c.session.cipherSuite !== null) {
          break;
        }
      }
    }

    // cipher suite not supported
    if(c.session.cipherSuite === null) {
      return c.error(c, {
        message: 'No cipher suites in common.',
        send: true,
        alert: {
          level: tls.Alert.Level.fatal,
          description: tls.Alert.Description.handshake_failure
        },
        cipherSuite: forge.util.bytesToHex(msg.cipher_suite)
      });
    }

    // TODO: handle compression methods
    if(client) {
      c.session.compressionMethod = msg.compression_method;
    } else {
      // no compression
      c.session.compressionMethod = tls.CompressionMethod.none;
    }
  }

  return msg;
};

/**
 * Creates security parameters for the given connection based on the given
 * hello message.
 *
 * @param c the TLS connection.
 * @param msg the hello message.
 */
tls.createSecurityParameters = function(c, msg) {
  /* Note: security params are from TLS 1.2, some values like prf_algorithm
  are ignored for TLS 1.0/1.1 and the builtin as specified in the spec is
  used. */

  // TODO: handle other options from server when more supported

  // get client and server randoms
  var client = (c.entity === tls.ConnectionEnd.client);
  var msgRandom = msg.random.bytes();
  var cRandom = client ? c.session.sp.client_random : msgRandom;
  var sRandom = client ? msgRandom : tls.createRandom().getBytes();

  // create new security parameters
  c.session.sp = {
    entity: c.entity,
    prf_algorithm: tls.PRFAlgorithm.tls_prf_sha256,
    bulk_cipher_algorithm: null,
    cipher_type: null,
    enc_key_length: null,
    block_length: null,
    fixed_iv_length: null,
    record_iv_length: null,
    mac_algorithm: null,
    mac_length: null,
    mac_key_length: null,
    compression_algorithm: c.session.compressionMethod,
    pre_master_secret: null,
    master_secret: null,
    client_random: cRandom,
    server_random: sRandom
  };
};

/**
 * Called when a client receives a ServerHello record.
 *
 * When a ServerHello message will be sent:
 *   The server will send this message in response to a client hello 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.
 *
 * uint24 length;
 * struct {
 *   ProtocolVersion server_version;
 *   Random random;
 *   SessionID session_id;
 *   CipherSuite cipher_suite;
 *   CompressionMethod compression_method;
 *   select(extensions_present) {
 *     case false:
 *       struct {};
 *     case true:
 *       Extension extensions<0..2^16-1>;
 *   };
 * } ServerHello;
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleServerHello = function(c, record, length) {
  var msg = tls.parseHelloMessage(c, record, length);
  if(c.fail) {
    return;
  }

  // ensure server version is compatible
  if(msg.version.minor <= c.version.minor) {
    c.version.minor = msg.version.minor;
  } else {
    return c.error(c, {
      message: 'Incompatible TLS version.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.protocol_version
      }
    });
  }

  // indicate session version has been set
  c.session.version = c.version;

  // get the session ID from the message
  var sessionId = msg.session_id.bytes();

  // if the session ID is not blank and matches the cached one, resume
  // the session
  if(sessionId.length > 0 && sessionId === c.session.id) {
    // resuming session, expect a ChangeCipherSpec next
    c.expect = SCC;
    c.session.resuming = true;

    // get new server random
    c.session.sp.server_random = msg.random.bytes();
  } else {
    // not resuming, expect a server Certificate message next
    c.expect = SCE;
    c.session.resuming = false;

    // create new security parameters
    tls.createSecurityParameters(c, msg);
  }

  // set new session ID
  c.session.id = sessionId;

  // continue
  c.process();
};

/**
 * Called when a server receives a ClientHello record.
 *
 * When a ClientHello message will be sent:
 *   When a client first connects to a server it is required to send the
 *   client hello as its first message. The client can also send a client
 *   hello in response to a hello request or on its own initiative in order
 *   to renegotiate the security parameters in an existing connection.
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleClientHello = function(c, record, length) {
  var msg = tls.parseHelloMessage(c, record, length);
  if(c.fail) {
    return;
  }

  // get the session ID from the message
  var sessionId = msg.session_id.bytes();

  // see if the given session ID is in the cache
  var session = null;
  if(c.sessionCache) {
    session = c.sessionCache.getSession(sessionId);
    if(session === null) {
      // session ID not found
      sessionId = '';
    } else if(session.version.major !== msg.version.major ||
      session.version.minor > msg.version.minor) {
      // if session version is incompatible with client version, do not resume
      session = null;
      sessionId = '';
    }
  }

  // no session found to resume, generate a new session ID
  if(sessionId.length === 0) {
    sessionId = forge.random.getBytes(32);
  }

  // update session
  c.session.id = sessionId;
  c.session.clientHelloVersion = msg.version;
  c.session.sp = {};
  if(session) {
    // use version and security parameters from resumed session
    c.version = c.session.version = session.version;
    c.session.sp = session.sp;
  } else {
    // use highest compatible minor version
    var version;
    for(var i = 1; i < tls.SupportedVersions.length; ++i) {
      version = tls.SupportedVersions[i];
      if(version.minor <= msg.version.minor) {
        break;
      }
    }
    c.version = {major: version.major, minor: version.minor};
    c.session.version = c.version;
  }

  // if a session is set, resume it
  if(session !== null) {
    // resuming session, expect a ChangeCipherSpec next
    c.expect = CCC;
    c.session.resuming = true;

    // get new client random
    c.session.sp.client_random = msg.random.bytes();
  } else {
    // not resuming, expect a Certificate or ClientKeyExchange
    c.expect = (c.verifyClient !== false) ? CCE : CKE;
    c.session.resuming = false;

    // create new security parameters
    tls.createSecurityParameters(c, msg);
  }

  // connection now open
  c.open = true;

  // queue server hello
  tls.queue(c, tls.createRecord(c, {
    type: tls.ContentType.handshake,
    data: tls.createServerHello(c)
  }));

  if(c.session.resuming) {
    // queue change cipher spec message
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.change_cipher_spec,
      data: tls.createChangeCipherSpec()
    }));

    // create pending state
    c.state.pending = tls.createConnectionState(c);

    // change current write state to pending write state
    c.state.current.write = c.state.pending.write;

    // queue finished
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.handshake,
      data: tls.createFinished(c)
    }));
  } else {
    // queue server certificate
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.handshake,
      data: tls.createCertificate(c)
    }));

    if(!c.fail) {
      // queue server key exchange
      tls.queue(c, tls.createRecord(c, {
        type: tls.ContentType.handshake,
        data: tls.createServerKeyExchange(c)
      }));

      // request client certificate if set
      if(c.verifyClient !== false) {
        // queue certificate request
        tls.queue(c, tls.createRecord(c, {
          type: tls.ContentType.handshake,
          data: tls.createCertificateRequest(c)
        }));
      }

      // queue server hello done
      tls.queue(c, tls.createRecord(c, {
        type: tls.ContentType.handshake,
        data: tls.createServerHelloDone(c)
      }));
    }
  }

  // send records
  tls.flush(c);

  // continue
  c.process();
};

/**
 * Called when a client receives a Certificate record.
 *
 * When this message will be sent:
 *   The server must send a certificate whenever the agreed-upon key exchange
 *   method is not an anonymous one. This message will always immediately
 *   follow the server hello message.
 *
 * Meaning of this message:
 *   The certificate type must be appropriate for the selected cipher suite's
 *   key exchange algorithm, and is generally an X.509v3 certificate. It must
 *   contain a key which matches the key exchange method, as follows. Unless
 *   otherwise specified, the signing algorithm for the certificate must be
 *   the same as the algorithm for the certificate key. Unless otherwise
 *   specified, the public key may be of any length.
 *
 * opaque ASN.1Cert<1..2^24-1>;
 * struct {
 *   ASN.1Cert certificate_list<1..2^24-1>;
 * } Certificate;
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleCertificate = function(c, record, length) {
  // minimum of 3 bytes in message
  if(length < 3) {
    return c.error(c, {
      message: 'Invalid Certificate message. Message too short.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.illegal_parameter
      }
    });
  }

  var b = record.fragment;
  var msg = {
    certificate_list: readVector(b, 3)
  };

  /* The sender's certificate will be first in the list (chain), each
    subsequent one that follows will certify the previous one, but root
    certificates (self-signed) that specify the certificate authority may
    be omitted under the assumption that clients must already possess it. */
  var cert, asn1;
  var certs = [];
  try {
    while(msg.certificate_list.length() > 0) {
      // each entry in msg.certificate_list is a vector with 3 len bytes
      cert = readVector(msg.certificate_list, 3);
      asn1 = forge.asn1.fromDer(cert);
      cert = forge.pki.certificateFromAsn1(asn1, true);
      certs.push(cert);
    }
  } catch(ex) {
    return c.error(c, {
      message: 'Could not parse certificate list.',
      cause: ex,
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.bad_certificate
      }
    });
  }

  // ensure at least 1 certificate was provided if in client-mode
  // or if verifyClient was set to true to require a certificate
  // (as opposed to 'optional')
  var client = (c.entity === tls.ConnectionEnd.client);
  if((client || c.verifyClient === true) && certs.length === 0) {
    // error, no certificate
    c.error(c, {
      message: client ?
        'No server certificate provided.' :
        'No client certificate provided.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.illegal_parameter
      }
    });
  } else if(certs.length === 0) {
    // no certs to verify
    // expect a ServerKeyExchange or ClientKeyExchange message next
    c.expect = client ? SKE : CKE;
  } else {
    // save certificate in session
    if(client) {
      c.session.serverCertificate = certs[0];
    } else {
      c.session.clientCertificate = certs[0];
    }

    if(tls.verifyCertificateChain(c, certs)) {
      // expect a ServerKeyExchange or ClientKeyExchange message next
      c.expect = client ? SKE : CKE;
    }
  }

  // continue
  c.process();
};

/**
 * Called when a client receives a ServerKeyExchange record.
 *
 * When this message will be sent:
 *   This message will be sent immediately after the server certificate
 *   message (or the server hello message, if this is an anonymous
 *   negotiation).
 *
 *   The server key exchange message is sent by the server only when the
 *   server certificate message (if sent) does not contain enough data to
 *   allow the client to exchange a premaster secret.
 *
 * Meaning of this message:
 *   This message conveys cryptographic information to allow the client to
 *   communicate the premaster secret: either an RSA public key to encrypt
 *   the premaster secret with, or a Diffie-Hellman public key with which the
 *   client can complete a key exchange (with the result being the premaster
 *   secret.)
 *
 * enum {
 *   dhe_dss, dhe_rsa, dh_anon, rsa, dh_dss, dh_rsa
 * } KeyExchangeAlgorithm;
 *
 * struct {
 *   opaque dh_p<1..2^16-1>;
 *   opaque dh_g<1..2^16-1>;
 *   opaque dh_Ys<1..2^16-1>;
 * } ServerDHParams;
 *
 * struct {
 *   select(KeyExchangeAlgorithm) {
 *     case dh_anon:
 *       ServerDHParams params;
 *     case dhe_dss:
 *     case dhe_rsa:
 *       ServerDHParams params;
 *       digitally-signed struct {
 *         opaque client_random[32];
 *         opaque server_random[32];
 *         ServerDHParams params;
 *       } signed_params;
 *     case rsa:
 *     case dh_dss:
 *     case dh_rsa:
 *       struct {};
 *   };
 * } ServerKeyExchange;
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleServerKeyExchange = function(c, record, length) {
  // this implementation only supports RSA, no Diffie-Hellman support
  // so any length > 0 is invalid
  if(length > 0) {
    return c.error(c, {
      message: 'Invalid key parameters. Only RSA is supported.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.unsupported_certificate
      }
    });
  }

  // expect an optional CertificateRequest message next
  c.expect = SCR;

  // continue
  c.process();
};

/**
 * Called when a client receives a ClientKeyExchange record.
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleClientKeyExchange = function(c, record, length) {
  // this implementation only supports RSA, no Diffie-Hellman support
  // so any length < 48 is invalid
  if(length < 48) {
    return c.error(c, {
      message: 'Invalid key parameters. Only RSA is supported.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.unsupported_certificate
      }
    });
  }

  var b = record.fragment;
  var msg = {
    enc_pre_master_secret: readVector(b, 2).getBytes()
  };

  // do rsa decryption
  var privateKey = null;
  if(c.getPrivateKey) {
    try {
      privateKey = c.getPrivateKey(c, c.session.serverCertificate);
      privateKey = forge.pki.privateKeyFromPem(privateKey);
    } catch(ex) {
      c.error(c, {
        message: 'Could not get private key.',
        cause: ex,
        send: true,
        alert: {
          level: tls.Alert.Level.fatal,
          description: tls.Alert.Description.internal_error
        }
      });
    }
  }

  if(privateKey === null) {
    return c.error(c, {
      message: 'No private key set.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.internal_error
      }
    });
  }

  try {
    // decrypt 48-byte pre-master secret
    var sp = c.session.sp;
    sp.pre_master_secret = privateKey.decrypt(msg.enc_pre_master_secret);

    // ensure client hello version matches first 2 bytes
    var version = c.session.clientHelloVersion;
    if(version.major !== sp.pre_master_secret.charCodeAt(0) ||
      version.minor !== sp.pre_master_secret.charCodeAt(1)) {
      // error, do not send alert (see BLEI attack below)
      throw new Error('TLS version rollback attack detected.');
    }
  } catch(ex) {
    /* Note: Daniel Bleichenbacher [BLEI] can be used to attack a
      TLS server which is using PKCS#1 encoded RSA, so instead of
      failing here, we generate 48 random bytes and use that as
      the pre-master secret. */
    sp.pre_master_secret = forge.random.getBytes(48);
  }

  // expect a CertificateVerify message if a Certificate was received that
  // does not have fixed Diffie-Hellman params, otherwise expect
  // ChangeCipherSpec
  c.expect = CCC;
  if(c.session.clientCertificate !== null) {
    // only RSA support, so expect CertificateVerify
    // TODO: support Diffie-Hellman
    c.expect = CCV;
  }

  // continue
  c.process();
};

/**
 * Called when a client receives a CertificateRequest record.
 *
 * When this message will be sent:
 *   A non-anonymous server can optionally request a certificate from the
 *   client, if appropriate for the selected cipher suite. This message, if
 *   sent, will immediately follow the Server Key Exchange message (if it is
 *   sent; otherwise, the Server Certificate message).
 *
 * enum {
 *   rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
 *   rsa_ephemeral_dh_RESERVED(5), dss_ephemeral_dh_RESERVED(6),
 *   fortezza_dms_RESERVED(20), (255)
 * } ClientCertificateType;
 *
 * opaque DistinguishedName<1..2^16-1>;
 *
 * struct {
 *   ClientCertificateType certificate_types<1..2^8-1>;
 *   SignatureAndHashAlgorithm supported_signature_algorithms<2^16-1>;
 *   DistinguishedName certificate_authorities<0..2^16-1>;
 * } CertificateRequest;
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleCertificateRequest = function(c, record, length) {
  // minimum of 3 bytes in message
  if(length < 3) {
    return c.error(c, {
      message: 'Invalid CertificateRequest. Message too short.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.illegal_parameter
      }
    });
  }

  // TODO: TLS 1.2+ has different format including
  // SignatureAndHashAlgorithm after cert types
  var b = record.fragment;
  var msg = {
    certificate_types: readVector(b, 1),
    certificate_authorities: readVector(b, 2)
  };

  // save certificate request in session
  c.session.certificateRequest = msg;

  // expect a ServerHelloDone message next
  c.expect = SHD;

  // continue
  c.process();
};

/**
 * Called when a server receives a CertificateVerify record.
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleCertificateVerify = function(c, record, length) {
  if(length < 2) {
    return c.error(c, {
      message: 'Invalid CertificateVerify. Message too short.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.illegal_parameter
      }
    });
  }

  // rewind to get full bytes for message so it can be manually
  // digested below (special case for CertificateVerify messages because
  // they must be digested *after* handling as opposed to all others)
  var b = record.fragment;
  b.read -= 4;
  var msgBytes = b.bytes();
  b.read += 4;

  var msg = {
    signature: readVector(b, 2).getBytes()
  };

  // TODO: add support for DSA

  // generate data to verify
  var verify = forge.util.createBuffer();
  verify.putBuffer(c.session.md5.digest());
  verify.putBuffer(c.session.sha1.digest());
  verify = verify.getBytes();

  try {
    var cert = c.session.clientCertificate;
    /*b = forge.pki.rsa.decrypt(
      msg.signature, cert.publicKey, true, verify.length);
    if(b !== verify) {*/
    if(!cert.publicKey.verify(verify, msg.signature, 'NONE')) {
      throw new Error('CertificateVerify signature does not match.');
    }

    // digest message now that it has been handled
    c.session.md5.update(msgBytes);
    c.session.sha1.update(msgBytes);
  } catch(ex) {
    return c.error(c, {
      message: 'Bad signature in CertificateVerify.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.handshake_failure
      }
    });
  }

  // expect ChangeCipherSpec
  c.expect = CCC;

  // continue
  c.process();
};

/**
 * Called when a client receives a ServerHelloDone record.
 *
 * When this message will be sent:
 *   The server hello done message is sent by the server to indicate the end
 *   of the server hello and associated messages. After sending this message
 *   the server will wait for a client response.
 *
 * Meaning of this message:
 *   This message means that the server is done sending messages to support
 *   the key exchange, and the client can proceed with its phase of the key
 *   exchange.
 *
 *   Upon receipt of the server hello done message the client should verify
 *   that the server provided a valid certificate if required and check that
 *   the server hello parameters are acceptable.
 *
 * struct {} ServerHelloDone;
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleServerHelloDone = function(c, record, length) {
  // len must be 0 bytes
  if(length > 0) {
    return c.error(c, {
      message: 'Invalid ServerHelloDone message. Invalid length.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.record_overflow
      }
    });
  }

  if(c.serverCertificate === null) {
    // no server certificate was provided
    var error = {
      message: 'No server certificate provided. Not enough security.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.insufficient_security
      }
    };

    // call application callback
    var depth = 0;
    var ret = c.verify(c, error.alert.description, depth, []);
    if(ret !== true) {
      // check for custom alert info
      if(ret || ret === 0) {
        // set custom message and alert description
        if(typeof ret === 'object' && !forge.util.isArray(ret)) {
          if(ret.message) {
            error.message = ret.message;
          }
          if(ret.alert) {
            error.alert.description = ret.alert;
          }
        } else if(typeof ret === 'number') {
          // set custom alert description
          error.alert.description = ret;
        }
      }

      // send error
      return c.error(c, error);
    }
  }

  // create client certificate message if requested
  if(c.session.certificateRequest !== null) {
    record = tls.createRecord(c, {
      type: tls.ContentType.handshake,
      data: tls.createCertificate(c)
    });
    tls.queue(c, record);
  }

  // create client key exchange message
  record = tls.createRecord(c, {
     type: tls.ContentType.handshake,
     data: tls.createClientKeyExchange(c)
  });
  tls.queue(c, record);

  // expect no messages until the following callback has been called
  c.expect = SER;

  // create callback to handle client signature (for client-certs)
  var callback = function(c, signature) {
    if(c.session.certificateRequest !== null &&
      c.session.clientCertificate !== null) {
      // create certificate verify message
      tls.queue(c, tls.createRecord(c, {
        type: tls.ContentType.handshake,
        data: tls.createCertificateVerify(c, signature)
      }));
    }

    // create change cipher spec message
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.change_cipher_spec,
      data: tls.createChangeCipherSpec()
    }));

    // create pending state
    c.state.pending = tls.createConnectionState(c);

    // change current write state to pending write state
    c.state.current.write = c.state.pending.write;

    // create finished message
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.handshake,
      data: tls.createFinished(c)
    }));

    // expect a server ChangeCipherSpec message next
    c.expect = SCC;

    // send records
    tls.flush(c);

    // continue
    c.process();
  };

  // if there is no certificate request or no client certificate, do
  // callback immediately
  if(c.session.certificateRequest === null ||
    c.session.clientCertificate === null) {
    return callback(c, null);
  }

  // otherwise get the client signature
  tls.getClientSignature(c, callback);
};

/**
 * Called when a ChangeCipherSpec record is received.
 *
 * @param c the connection.
 * @param record the record.
 */
tls.handleChangeCipherSpec = function(c, record) {
  if(record.fragment.getByte() !== 0x01) {
    return c.error(c, {
      message: 'Invalid ChangeCipherSpec message received.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.illegal_parameter
      }
    });
  }

  // create pending state if:
  // 1. Resuming session in client mode OR
  // 2. NOT resuming session in server mode
  var client = (c.entity === tls.ConnectionEnd.client);
  if((c.session.resuming && client) || (!c.session.resuming && !client)) {
    c.state.pending = tls.createConnectionState(c);
  }

  // change current read state to pending read state
  c.state.current.read = c.state.pending.read;

  // clear pending state if:
  // 1. NOT resuming session in client mode OR
  // 2. resuming a session in server mode
  if((!c.session.resuming && client) || (c.session.resuming && !client)) {
    c.state.pending = null;
  }

  // expect a Finished record next
  c.expect = client ? SFI : CFI;

  // continue
  c.process();
};

/**
 * Called when a Finished record is received.
 *
 * When this message will be sent:
 *   A finished message is always sent immediately after a change
 *   cipher spec message to verify that the key exchange and
 *   authentication processes were successful. It is essential that a
 *   change cipher spec message be received between the other
 *   handshake messages and the Finished message.
 *
 * Meaning of this message:
 *   The finished message is the first protected with the just-
 *   negotiated algorithms, keys, and secrets. Recipients of finished
 *   messages must verify that the contents are correct.  Once a side
 *   has sent its Finished message and received and validated the
 *   Finished message from its peer, it may begin to send and receive
 *   application data over the connection.
 *
 * struct {
 *   opaque verify_data[verify_data_length];
 * } Finished;
 *
 * verify_data
 *   PRF(master_secret, finished_label, Hash(handshake_messages))
 *     [0..verify_data_length-1];
 *
 * finished_label
 *   For Finished messages sent by the client, the string
 *   "client finished". For Finished messages sent by the server, the
 *   string "server finished".
 *
 * verify_data_length depends on the cipher suite. If it is not specified
 * by the cipher suite, then it is 12. Versions of TLS < 1.2 always used
 * 12 bytes.
 *
 * @param c the connection.
 * @param record the record.
 * @param length the length of the handshake message.
 */
tls.handleFinished = function(c, record, length) {
  // rewind to get full bytes for message so it can be manually
  // digested below (special case for Finished messages because they
  // must be digested *after* handling as opposed to all others)
  var b = record.fragment;
  b.read -= 4;
  var msgBytes = b.bytes();
  b.read += 4;

  // message contains only verify_data
  var vd = record.fragment.getBytes();

  // ensure verify data is correct
  b = forge.util.createBuffer();
  b.putBuffer(c.session.md5.digest());
  b.putBuffer(c.session.sha1.digest());

  // set label based on entity type
  var client = (c.entity === tls.ConnectionEnd.client);
  var label = client ? 'server finished' : 'client finished';

  // TODO: determine prf function and verify length for TLS 1.2
  var sp = c.session.sp;
  var vdl = 12;
  var prf = prf_TLS1;
  b = prf(sp.master_secret, label, b.getBytes(), vdl);
  if(b.getBytes() !== vd) {
    return c.error(c, {
      message: 'Invalid verify_data in Finished message.',
      send: true,
      alert: {
        level: tls.Alert.Level.fatal,
        description: tls.Alert.Description.decrypt_error
      }
    });
  }

  // digest finished message now that it has been handled
  c.session.md5.update(msgBytes);
  c.session.sha1.update(msgBytes);

  // resuming session as client or NOT resuming session as server
  if((c.session.resuming && client) || (!c.session.resuming && !client)) {
    // create change cipher spec message
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.change_cipher_spec,
      data: tls.createChangeCipherSpec()
    }));

    // change current write state to pending write state, clear pending
    c.state.current.write = c.state.pending.write;
    c.state.pending = null;

    // create finished message
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.handshake,
      data: tls.createFinished(c)
    }));
  }

  // expect application data next
  c.expect = client ? SAD : CAD;

  // handshake complete
  c.handshaking = false;
  ++c.handshakes;

  // save access to peer certificate
  c.peerCertificate = client ?
    c.session.serverCertificate : c.session.clientCertificate;

  // send records
  tls.flush(c);

  // now connected
  c.isConnected = true;
  c.connected(c);

  // continue
  c.process();
};

/**
 * Called when an Alert record is received.
 *
 * @param c the connection.
 * @param record the record.
 */
tls.handleAlert = function(c, record) {
  // read alert
  var b = record.fragment;
  var alert = {
    level: b.getByte(),
    description: b.getByte()
  };

  // TODO: consider using a table?
  // get appropriate message
  var msg;
  switch(alert.description) {
  case tls.Alert.Description.close_notify:
    msg = 'Connection closed.';
    break;
  case tls.Alert.Description.unexpected_message:
    msg = 'Unexpected message.';
    break;
  case tls.Alert.Description.bad_record_mac:
    msg = 'Bad record MAC.';
    break;
  case tls.Alert.Description.decryption_failed:
    msg = 'Decryption failed.';
    break;
  case tls.Alert.Description.record_overflow:
    msg = 'Record overflow.';
    break;
  case tls.Alert.Description.decompression_failure:
    msg = 'Decompression failed.';
    break;
  case tls.Alert.Description.handshake_failure:
    msg = 'Handshake failure.';
    break;
  case tls.Alert.Description.bad_certificate:
    msg = 'Bad certificate.';
    break;
  case tls.Alert.Description.unsupported_certificate:
    msg = 'Unsupported certificate.';
    break;
  case tls.Alert.Description.certificate_revoked:
    msg = 'Certificate revoked.';
    break;
  case tls.Alert.Description.certificate_expired:
    msg = 'Certificate expired.';
    break;
  case tls.Alert.Description.certificate_unknown:
    msg = 'Certificate unknown.';
    break;
  case tls.Alert.Description.illegal_parameter:
    msg = 'Illegal parameter.';
    break;
  case tls.Alert.Description.unknown_ca:
    msg = 'Unknown certificate authority.';
    break;
  case tls.Alert.Description.access_denied:
    msg = 'Access denied.';
    break;
  case tls.Alert.Description.decode_error:
    msg = 'Decode error.';
    break;
  case tls.Alert.Description.decrypt_error:
    msg = 'Decrypt error.';
    break;
  case tls.Alert.Description.export_restriction:
    msg = 'Export restriction.';
    break;
  case tls.Alert.Description.protocol_version:
    msg = 'Unsupported protocol version.';
    break;
  case tls.Alert.Description.insufficient_security:
    msg = 'Insufficient security.';
    break;
  case tls.Alert.Description.internal_error:
    msg = 'Internal error.';
    break;
  case tls.Alert.Description.user_canceled:
    msg = 'User canceled.';
    break;
  case tls.Alert.Description.no_renegotiation:
    msg = 'Renegotiation not supported.';
    break;
  default:
    msg = 'Unknown error.';
    break;
  }

  // close connection on close_notify, not an error
  if(alert.description === tls.Alert.Description.close_notify) {
    return c.close();
  }

  // call error handler
  c.error(c, {
    message: msg,
    send: false,
    // origin is the opposite end
    origin: (c.entity === tls.ConnectionEnd.client) ? 'server' : 'client',
    alert: alert
  });

  // continue
  c.process();
};

/**
 * Called when a Handshake record is received.
 *
 * @param c the connection.
 * @param record the record.
 */
tls.handleHandshake = function(c, record) {
  // get the handshake type and message length
  var b = record.fragment;
  var type = b.getByte();
  var length = b.getInt24();

  // see if the record fragment doesn't yet contain the full message
  if(length > b.length()) {
    // cache the record, clear its fragment, and reset the buffer read
    // pointer before the type and length were read
    c.fragmented = record;
    record.fragment = forge.util.createBuffer();
    b.read -= 4;

    // continue
    return c.process();
  }

  // full message now available, clear cache, reset read pointer to
  // before type and length
  c.fragmented = null;
  b.read -= 4;

  // save the handshake bytes for digestion after handler is found
  // (include type and length of handshake msg)
  var bytes = b.bytes(length + 4);

  // restore read pointer
  b.read += 4;

  // handle expected message
  if(type in hsTable[c.entity][c.expect]) {
    // initialize server session
    if(c.entity === tls.ConnectionEnd.server && !c.open && !c.fail) {
      c.handshaking = true;
      c.session = {
        version: null,
        extensions: {
          server_name: {
            serverNameList: []
          }
        },
        cipherSuite: null,
        compressionMethod: null,
        serverCertificate: null,
        clientCertificate: null,
        md5: forge.md.md5.create(),
        sha1: forge.md.sha1.create()
      };
    }

    /* Update handshake messages digest. Finished and CertificateVerify
      messages are not digested here. They can't be digested as part of
      the verify_data that they contain. These messages are manually
      digested in their handlers. HelloRequest messages are simply never
      included in the handshake message digest according to spec. */
    if(type !== tls.HandshakeType.hello_request &&
      type !== tls.HandshakeType.certificate_verify &&
      type !== tls.HandshakeType.finished) {
      c.session.md5.update(bytes);
      c.session.sha1.update(bytes);
    }

    // handle specific handshake type record
    hsTable[c.entity][c.expect][type](c, record, length);
  } else {
    // unexpected record
    tls.handleUnexpected(c, record);
  }
};

/**
 * Called when an ApplicationData record is received.
 *
 * @param c the connection.
 * @param record the record.
 */
tls.handleApplicationData = function(c, record) {
  // buffer data, notify that its ready
  c.data.putBuffer(record.fragment);
  c.dataReady(c);

  // continue
  c.process();
};

/**
 * Called when a Heartbeat record is received.
 *
 * @param c the connection.
 * @param record the record.
 */
tls.handleHeartbeat = function(c, record) {
  // get the heartbeat type and payload
  var b = record.fragment;
  var type = b.getByte();
  var length = b.getInt16();
  var payload = b.getBytes(length);

  if(type === tls.HeartbeatMessageType.heartbeat_request) {
    // discard request during handshake or if length is too large
    if(c.handshaking || length > payload.length) {
      // continue
      return c.process();
    }
    // retransmit payload
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.heartbeat,
      data: tls.createHeartbeat(
        tls.HeartbeatMessageType.heartbeat_response, payload)
    }));
    tls.flush(c);
  } else if(type === tls.HeartbeatMessageType.heartbeat_response) {
    // check payload against expected payload, discard heartbeat if no match
    if(payload !== c.expectedHeartbeatPayload) {
      // continue
      return c.process();
    }

    // notify that a valid heartbeat was received
    if(c.heartbeatReceived) {
      c.heartbeatReceived(c, forge.util.createBuffer(payload));
    }
  }

  // continue
  c.process();
};

/**
 * The transistional state tables for receiving TLS records. It maps the
 * current TLS engine state and a received record to a function to handle the
 * record and update the state.
 *
 * For instance, if the current state is SHE, then the TLS engine is expecting
 * a ServerHello record. Once a record is received, the handler function is
 * looked up using the state SHE and the record's content type.
 *
 * The resulting function will either be an error handler or a record handler.
 * The function will take whatever action is appropriate and update the state
 * for the next record.
 *
 * The states are all based on possible server record types. Note that the
 * client will never specifically expect to receive a HelloRequest or an alert
 * from the server so there is no state that reflects this. These messages may
 * occur at any time.
 *
 * There are two tables for mapping states because there is a second tier of
 * types for handshake messages. Once a record with a content type of handshake
 * is received, the handshake record handler will look up the handshake type in
 * the secondary map to get its appropriate handler.
 *
 * Valid message orders are as follows:
 *
 * =======================FULL HANDSHAKE======================
 * Client                                               Server
 *
 * ClientHello                  -------->
 *                                                 ServerHello
 *                                                Certificate*
 *                                          ServerKeyExchange*
 *                                         CertificateRequest*
 *                              <--------      ServerHelloDone
 * Certificate*
 * ClientKeyExchange
 * CertificateVerify*
 * [ChangeCipherSpec]
 * Finished                     -------->
 *                                          [ChangeCipherSpec]
 *                              <--------             Finished
 * Application Data             <------->     Application Data
 *
 * =====================SESSION RESUMPTION=====================
 * Client                                                Server
 *
 * ClientHello                   -------->
 *                                                  ServerHello
 *                                           [ChangeCipherSpec]
 *                               <--------             Finished
 * [ChangeCipherSpec]
 * Finished                      -------->
 * Application Data              <------->     Application Data
 */
// client expect states (indicate which records are expected to be received)
var SHE = 0; // rcv server hello
var SCE = 1; // rcv server certificate
var SKE = 2; // rcv server key exchange
var SCR = 3; // rcv certificate request
var SHD = 4; // rcv server hello done
var SCC = 5; // rcv change cipher spec
var SFI = 6; // rcv finished
var SAD = 7; // rcv application data
var SER = 8; // not expecting any messages at this point

// server expect states
var CHE = 0; // rcv client hello
var CCE = 1; // rcv client certificate
var CKE = 2; // rcv client key exchange
var CCV = 3; // rcv certificate verify
var CCC = 4; // rcv change cipher spec
var CFI = 5; // rcv finished
var CAD = 6; // rcv application data
var CER = 7; // not expecting any messages at this point

// map client current expect state and content type to function
var __ = tls.handleUnexpected;
var R0 = tls.handleChangeCipherSpec;
var R1 = tls.handleAlert;
var R2 = tls.handleHandshake;
var R3 = tls.handleApplicationData;
var R4 = tls.handleHeartbeat;
var ctTable = [];
ctTable[tls.ConnectionEnd.client] = [
//      CC,AL,HS,AD,HB
/*SHE*/[__,R1,R2,__,R4],
/*SCE*/[__,R1,R2,__,R4],
/*SKE*/[__,R1,R2,__,R4],
/*SCR*/[__,R1,R2,__,R4],
/*SHD*/[__,R1,R2,__,R4],
/*SCC*/[R0,R1,__,__,R4],
/*SFI*/[__,R1,R2,__,R4],
/*SAD*/[__,R1,R2,R3,R4],
/*SER*/[__,R1,R2,__,R4]
];

// map server current expect state and content type to function
ctTable[tls.ConnectionEnd.server] = [
//      CC,AL,HS,AD
/*CHE*/[__,R1,R2,__,R4],
/*CCE*/[__,R1,R2,__,R4],
/*CKE*/[__,R1,R2,__,R4],
/*CCV*/[__,R1,R2,__,R4],
/*CCC*/[R0,R1,__,__,R4],
/*CFI*/[__,R1,R2,__,R4],
/*CAD*/[__,R1,R2,R3,R4],
/*CER*/[__,R1,R2,__,R4]
];

// map client current expect state and handshake type to function
var H0 = tls.handleHelloRequest;
var H1 = tls.handleServerHello;
var H2 = tls.handleCertificate;
var H3 = tls.handleServerKeyExchange;
var H4 = tls.handleCertificateRequest;
var H5 = tls.handleServerHelloDone;
var H6 = tls.handleFinished;
var hsTable = [];
hsTable[tls.ConnectionEnd.client] = [
//      HR,01,SH,03,04,05,06,07,08,09,10,SC,SK,CR,HD,15,CK,17,18,19,FI
/*SHE*/[__,__,H1,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__],
/*SCE*/[H0,__,__,__,__,__,__,__,__,__,__,H2,H3,H4,H5,__,__,__,__,__,__],
/*SKE*/[H0,__,__,__,__,__,__,__,__,__,__,__,H3,H4,H5,__,__,__,__,__,__],
/*SCR*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,H4,H5,__,__,__,__,__,__],
/*SHD*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,H5,__,__,__,__,__,__],
/*SCC*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__],
/*SFI*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H6],
/*SAD*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__],
/*SER*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__]
];

// map server current expect state and handshake type to function
// Note: CAD[CH] does not map to FB because renegotation is prohibited
var H7 = tls.handleClientHello;
var H8 = tls.handleClientKeyExchange;
var H9 = tls.handleCertificateVerify;
hsTable[tls.ConnectionEnd.server] = [
//      01,CH,02,03,04,05,06,07,08,09,10,CC,12,13,14,CV,CK,17,18,19,FI
/*CHE*/[__,H7,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__],
/*CCE*/[__,__,__,__,__,__,__,__,__,__,__,H2,__,__,__,__,__,__,__,__,__],
/*CKE*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H8,__,__,__,__],
/*CCV*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H9,__,__,__,__,__],
/*CCC*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__],
/*CFI*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H6],
/*CAD*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__],
/*CER*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__]
];

/**
 * Generates the master_secret and keys using the given security parameters.
 *
 * The security parameters for a TLS connection state are defined as such:
 *
 * struct {
 *   ConnectionEnd          entity;
 *   PRFAlgorithm           prf_algorithm;
 *   BulkCipherAlgorithm    bulk_cipher_algorithm;
 *   CipherType             cipher_type;
 *   uint8                  enc_key_length;
 *   uint8                  block_length;
 *   uint8                  fixed_iv_length;
 *   uint8                  record_iv_length;
 *   MACAlgorithm           mac_algorithm;
 *   uint8                  mac_length;
 *   uint8                  mac_key_length;
 *   CompressionMethod      compression_algorithm;
 *   opaque                 master_secret[48];
 *   opaque                 client_random[32];
 *   opaque                 server_random[32];
 * } SecurityParameters;
 *
 * Note that this definition is from TLS 1.2. In TLS 1.0 some of these
 * parameters are ignored because, for instance, the PRFAlgorithm is a
 * builtin-fixed algorithm combining iterations of MD5 and SHA-1 in TLS 1.0.
 *
 * The Record Protocol requires an algorithm to generate keys required by the
 * current connection state.
 *
 * The master secret is expanded into a sequence of secure bytes, which is then
 * split to a client write MAC key, a server write MAC key, a client write
 * encryption key, and a server write encryption key. In TLS 1.0 a client write
 * IV and server write IV are also generated. Each of these is generated from
 * the byte sequence in that order. Unused values are empty. In TLS 1.2, some
 * AEAD ciphers may additionally require a client write IV and a server write
 * IV (see Section 6.2.3.3).
 *
 * When keys, MAC keys, and IVs are generated, the master secret is used as an
 * entropy source.
 *
 * To generate the key material, compute:
 *
 * master_secret = PRF(pre_master_secret, "master secret",
 *                     ClientHello.random + ServerHello.random)
 *
 * key_block = PRF(SecurityParameters.master_secret,
 *                 "key expansion",
 *                 SecurityParameters.server_random +
 *                 SecurityParameters.client_random);
 *
 * until enough output has been generated. Then, the key_block is
 * partitioned as follows:
 *
 * client_write_MAC_key[SecurityParameters.mac_key_length]
 * server_write_MAC_key[SecurityParameters.mac_key_length]
 * client_write_key[SecurityParameters.enc_key_length]
 * server_write_key[SecurityParameters.enc_key_length]
 * client_write_IV[SecurityParameters.fixed_iv_length]
 * server_write_IV[SecurityParameters.fixed_iv_length]
 *
 * In TLS 1.2, the client_write_IV and server_write_IV are only generated for
 * implicit nonce techniques as described in Section 3.2.1 of [AEAD]. This
 * implementation uses TLS 1.0 so IVs are generated.
 *
 * Implementation note: The currently defined cipher suite which requires the
 * most material is AES_256_CBC_SHA256. It requires 2 x 32 byte keys and 2 x 32
 * byte MAC keys, for a total 128 bytes of key material. In TLS 1.0 it also
 * requires 2 x 16 byte IVs, so it actually takes 160 bytes of key material.
 *
 * @param c the connection.
 * @param sp the security parameters to use.
 *
 * @return the security keys.
 */
tls.generateKeys = function(c, sp) {
  // TLS_RSA_WITH_AES_128_CBC_SHA (required to be compliant with TLS 1.2) &
  // TLS_RSA_WITH_AES_256_CBC_SHA are the only cipher suites implemented
  // at present

  // TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA is required to be compliant with
  // TLS 1.0 but we don't care right now because AES is better and we have
  // an implementation for it

  // TODO: TLS 1.2 implementation
  /*
  // determine the PRF
  var prf;
  switch(sp.prf_algorithm) {
  case tls.PRFAlgorithm.tls_prf_sha256:
    prf = prf_sha256;
    break;
  default:
    // should never happen
    throw new Error('Invalid PRF');
  }
  */

  // TLS 1.0/1.1 implementation
  var prf = prf_TLS1;

  // concatenate server and client random
  var random = sp.client_random + sp.server_random;

  // only create master secret if session is new
  if(!c.session.resuming) {
    // create master secret, clean up pre-master secret
    sp.master_secret = prf(
      sp.pre_master_secret, 'master secret', random, 48).bytes();
    sp.pre_master_secret = null;
  }

  // generate the amount of key material needed
  random = sp.server_random + sp.client_random;
  var length = 2 * sp.mac_key_length + 2 * sp.enc_key_length;

  // include IV for TLS/1.0
  var tls10 = (c.version.major === tls.Versions.TLS_1_0.major &&
    c.version.minor === tls.Versions.TLS_1_0.minor);
  if(tls10) {
    length += 2 * sp.fixed_iv_length;
  }
  var km = prf(sp.master_secret, 'key expansion', random, length);

  // split the key material into the MAC and encryption keys
  var rval = {
    client_write_MAC_key: km.getBytes(sp.mac_key_length),
    server_write_MAC_key: km.getBytes(sp.mac_key_length),
    client_write_key: km.getBytes(sp.enc_key_length),
    server_write_key: km.getBytes(sp.enc_key_length)
  };

  // include TLS 1.0 IVs
  if(tls10) {
    rval.client_write_IV = km.getBytes(sp.fixed_iv_length);
    rval.server_write_IV = km.getBytes(sp.fixed_iv_length);
  }

  return rval;
};

/**
 * Creates a new initialized TLS connection state. A connection state has
 * a read mode and a write mode.
 *
 * compression state:
 *   The current state of the compression algorithm.
 *
 * cipher state:
 *   The current state of the encryption algorithm. This will consist of the
 *   scheduled key for that connection. For stream ciphers, this will also
 *   contain whatever state information is necessary to allow the stream to
 *   continue to encrypt or decrypt data.
 *
 * MAC key:
 *   The MAC key for the connection.
 *
 * sequence number:
 *   Each connection state contains a sequence number, which is maintained
 *   separately for read and write states. The sequence number MUST be set to
 *   zero whenever a connection state is made the active state. Sequence
 *   numbers are of type uint64 and may not exceed 2^64-1. Sequence numbers do
 *   not wrap. If a TLS implementation would need to wrap a sequence number,
 *   it must renegotiate instead. A sequence number is incremented after each
 *   record: specifically, the first record transmitted under a particular
 *   connection state MUST use sequence number 0.
 *
 * @param c the connection.
 *
 * @return the new initialized TLS connection state.
 */
tls.createConnectionState = function(c) {
  var client = (c.entity === tls.ConnectionEnd.client);

  var createMode = function() {
    var mode = {
      // two 32-bit numbers, first is most significant
      sequenceNumber: [0, 0],
      macKey: null,
      macLength: 0,
      macFunction: null,
      cipherState: null,
      cipherFunction: function(record) {return true;},
      compressionState: null,
      compressFunction: function(record) {return true;},
      updateSequenceNumber: function() {
        if(mode.sequenceNumber[1] === 0xFFFFFFFF) {
          mode.sequenceNumber[1] = 0;
          ++mode.sequenceNumber[0];
        } else {
          ++mode.sequenceNumber[1];
        }
      }
    };
    return mode;
  };
  var state = {
    read: createMode(),
    write: createMode()
  };

  // update function in read mode will decrypt then decompress a record
  state.read.update = function(c, record) {
    if(!state.read.cipherFunction(record, state.read)) {
      c.error(c, {
        message: 'Could not decrypt record or bad MAC.',
        send: true,
        alert: {
          level: tls.Alert.Level.fatal,
          // doesn't matter if decryption failed or MAC was
          // invalid, return the same error so as not to reveal
          // which one occurred
          description: tls.Alert.Description.bad_record_mac
        }
      });
    } else if(!state.read.compressFunction(c, record, state.read)) {
      c.error(c, {
        message: 'Could not decompress record.',
        send: true,
        alert: {
          level: tls.Alert.Level.fatal,
          description: tls.Alert.Description.decompression_failure
        }
      });
    }
    return !c.fail;
  };

  // update function in write mode will compress then encrypt a record
  state.write.update = function(c, record) {
    if(!state.write.compressFunction(c, record, state.write)) {
      // error, but do not send alert since it would require
      // compression as well
      c.error(c, {
        message: 'Could not compress record.',
        send: false,
        alert: {
          level: tls.Alert.Level.fatal,
          description: tls.Alert.Description.internal_error
        }
      });
    } else if(!state.write.cipherFunction(record, state.write)) {
      // error, but do not send alert since it would require
      // encryption as well
      c.error(c, {
        message: 'Could not encrypt record.',
        send: false,
        alert: {
          level: tls.Alert.Level.fatal,
          description: tls.Alert.Description.internal_error
        }
      });
    }
    return !c.fail;
  };

  // handle security parameters
  if(c.session) {
    var sp = c.session.sp;
    c.session.cipherSuite.initSecurityParameters(sp);

    // generate keys
    sp.keys = tls.generateKeys(c, sp);
    state.read.macKey = client ?
      sp.keys.server_write_MAC_key : sp.keys.client_write_MAC_key;
    state.write.macKey = client ?
      sp.keys.client_write_MAC_key : sp.keys.server_write_MAC_key;

    // cipher suite setup
    c.session.cipherSuite.initConnectionState(state, c, sp);

    // compression setup
    switch(sp.compression_algorithm) {
    case tls.CompressionMethod.none:
      break;
    case tls.CompressionMethod.deflate:
      state.read.compressFunction = inflate;
      state.write.compressFunction = deflate;
      break;
    default:
      throw new Error('Unsupported compression algorithm.');
    }
  }

  return state;
};

/**
 * Creates a Random structure.
 *
 * struct {
 *   uint32 gmt_unix_time;
 *   opaque random_bytes[28];
 * } Random;
 *
 * gmt_unix_time:
 *   The current time and date in standard UNIX 32-bit format (seconds since
 *   the midnight starting Jan 1, 1970, UTC, ignoring leap seconds) according
 *   to the sender's internal clock. Clocks are not required to be set
 *   correctly by the basic TLS protocol; higher-level or application
 *   protocols may define additional requirements. Note that, for historical
 *   reasons, the data element is named using GMT, the predecessor of the
 *   current worldwide time base, UTC.
 * random_bytes:
 *   28 bytes generated by a secure random number generator.
 *
 * @return the Random structure as a byte array.
 */
tls.createRandom = function() {
  // get UTC milliseconds
  var d = new Date();
  var utc = +d + d.getTimezoneOffset() * 60000;
  var rval = forge.util.createBuffer();
  rval.putInt32(utc);
  rval.putBytes(forge.random.getBytes(28));
  return rval;
};

/**
 * Creates a TLS record with the given type and data.
 *
 * @param c the connection.
 * @param options:
 *   type: the record type.
 *   data: the plain text data in a byte buffer.
 *
 * @return the created record.
 */
tls.createRecord = function(c, options) {
  if(!options.data) {
    return null;
  }
  var record = {
    type: options.type,
    version: {
      major: c.version.major,
      minor: c.version.minor
    },
    length: options.data.length(),
    fragment: options.data
  };
  return record;
};

/**
 * Creates a TLS alert record.
 *
 * @param c the connection.
 * @param alert:
 *   level: the TLS alert level.
 *   description: the TLS alert description.
 *
 * @return the created alert record.
 */
tls.createAlert = function(c, alert) {
  var b = forge.util.createBuffer();
  b.putByte(alert.level);
  b.putByte(alert.description);
  return tls.createRecord(c, {
    type: tls.ContentType.alert,
    data: b
  });
};

/* The structure of a TLS handshake message.
 *
 * struct {
 *    HandshakeType msg_type;    // handshake type
 *    uint24 length;             // bytes in message
 *    select(HandshakeType) {
 *       case hello_request:       HelloRequest;
 *       case client_hello:        ClientHello;
 *       case server_hello:        ServerHello;
 *       case certificate:         Certificate;
 *       case server_key_exchange: ServerKeyExchange;
 *       case certificate_request: CertificateRequest;
 *       case server_hello_done:   ServerHelloDone;
 *       case certificate_verify:  CertificateVerify;
 *       case client_key_exchange: ClientKeyExchange;
 *       case finished:            Finished;
 *    } body;
 * } Handshake;
 */

/**
 * Creates a ClientHello message.
 *
 * opaque SessionID<0..32>;
 * enum { null(0), deflate(1), (255) } CompressionMethod;
 * uint8 CipherSuite[2];
 *
 * struct {
 *   ProtocolVersion client_version;
 *   Random random;
 *   SessionID session_id;
 *   CipherSuite cipher_suites<2..2^16-2>;
 *   CompressionMethod compression_methods<1..2^8-1>;
 *   select(extensions_present) {
 *     case false:
 *       struct {};
 *     case true:
 *       Extension extensions<0..2^16-1>;
 *   };
 * } ClientHello;
 *
 * The extension format for extended client hellos and server hellos is:
 *
 * struct {
 *   ExtensionType extension_type;
 *   opaque extension_data<0..2^16-1>;
 * } Extension;
 *
 * Here:
 *
 * - "extension_type" identifies the particular extension type.
 * - "extension_data" contains information specific to the particular
 * extension type.
 *
 * The extension types defined in this document are:
 *
 * enum {
 *   server_name(0), max_fragment_length(1),
 *   client_certificate_url(2), trusted_ca_keys(3),
 *   truncated_hmac(4), status_request(5), (65535)
 * } ExtensionType;
 *
 * @param c the connection.
 *
 * @return the ClientHello byte buffer.
 */
tls.createClientHello = function(c) {
  // save hello version
  c.session.clientHelloVersion = {
    major: c.version.major,
    minor: c.version.minor
  };

  // create supported cipher suites
  var cipherSuites = forge.util.createBuffer();
  for(var i = 0; i < c.cipherSuites.length; ++i) {
    var cs = c.cipherSuites[i];
    cipherSuites.putByte(cs.id[0]);
    cipherSuites.putByte(cs.id[1]);
  }
  var cSuites = cipherSuites.length();

  // create supported compression methods, null always supported, but
  // also support deflate if connection has inflate and deflate methods
  var compressionMethods = forge.util.createBuffer();
  compressionMethods.putByte(tls.CompressionMethod.none);
  // FIXME: deflate support disabled until issues with raw deflate data
  // without zlib headers are resolved
  /*
  if(c.inflate !== null && c.deflate !== null) {
    compressionMethods.putByte(tls.CompressionMethod.deflate);
  }
  */
  var cMethods = compressionMethods.length();

  // create TLS SNI (server name indication) extension if virtual host
  // has been specified, see RFC 3546
  var extensions = forge.util.createBuffer();
  if(c.virtualHost) {
    // create extension struct
    var ext = forge.util.createBuffer();
    ext.putByte(0x00); // type server_name (ExtensionType is 2 bytes)
    ext.putByte(0x00);

    /* In order to provide the server name, clients MAY include an
     * extension of type "server_name" in the (extended) client hello.
     * The "extension_data" field of this extension SHALL contain
     * "ServerNameList" where:
     *
     * struct {
     *   NameType name_type;
     *   select(name_type) {
     *     case host_name: HostName;
     *   } name;
     * } ServerName;
     *
     * enum {
     *   host_name(0), (255)
     * } NameType;
     *
     * opaque HostName<1..2^16-1>;
     *
     * struct {
     *   ServerName server_name_list<1..2^16-1>
     * } ServerNameList;
     */
    var serverName = forge.util.createBuffer();
    serverName.putByte(0x00); // type host_name
    writeVector(serverName, 2, forge.util.createBuffer(c.virtualHost));

    // ServerNameList is in extension_data
    var snList = forge.util.createBuffer();
    writeVector(snList, 2, serverName);
    writeVector(ext, 2, snList);
    extensions.putBuffer(ext);
  }
  var extLength = extensions.length();
  if(extLength > 0) {
    // add extension vector length
    extLength += 2;
  }

  // determine length of the handshake message
  // cipher suites and compression methods size will need to be
  // updated if more get added to the list
  var sessionId = c.session.id;
  var length =
    sessionId.length + 1 + // session ID vector
    2 +                    // version (major + minor)
    4 + 28 +               // random time and random bytes
    2 + cSuites +          // cipher suites vector
    1 + cMethods +         // compression methods vector
    extLength;             // extensions vector

  // build record fragment
  var rval = forge.util.createBuffer();
  rval.putByte(tls.HandshakeType.client_hello);
  rval.putInt24(length);                     // handshake length
  rval.putByte(c.version.major);             // major version
  rval.putByte(c.version.minor);             // minor version
  rval.putBytes(c.session.sp.client_random); // random time + bytes
  writeVector(rval, 1, forge.util.createBuffer(sessionId));
  writeVector(rval, 2, cipherSuites);
  writeVector(rval, 1, compressionMethods);
  if(extLength > 0) {
    writeVector(rval, 2, extensions);
  }
  return rval;
};

/**
 * Creates a ServerHello message.
 *
 * @param c the connection.
 *
 * @return the ServerHello byte buffer.
 */
tls.createServerHello = function(c) {
  // determine length of the handshake message
  var sessionId = c.session.id;
  var length =
    sessionId.length + 1 + // session ID vector
    2 +                    // version (major + minor)
    4 + 28 +               // random time and random bytes
    2 +                    // chosen cipher suite
    1;                     // chosen compression method

  // build record fragment
  var rval = forge.util.createBuffer();
  rval.putByte(tls.HandshakeType.server_hello);
  rval.putInt24(length);                     // handshake length
  rval.putByte(c.version.major);             // major version
  rval.putByte(c.version.minor);             // minor version
  rval.putBytes(c.session.sp.server_random); // random time + bytes
  writeVector(rval, 1, forge.util.createBuffer(sessionId));
  rval.putByte(c.session.cipherSuite.id[0]);
  rval.putByte(c.session.cipherSuite.id[1]);
  rval.putByte(c.session.compressionMethod);
  return rval;
};

/**
 * Creates a Certificate message.
 *
 * When this message will be sent:
 *   This is the first message the client can send after receiving a server
 *   hello done message and the first message the server can send after
 *   sending a ServerHello. This client message is only sent if the server
 *   requests a certificate. If no suitable certificate is available, the
 *   client should send a certificate message containing no certificates. If
 *   client authentication is required by the server for the handshake to
 *   continue, it may respond with a fatal handshake failure alert.
 *
 * opaque ASN.1Cert<1..2^24-1>;
 *
 * struct {
 *   ASN.1Cert certificate_list<0..2^24-1>;
 * } Certificate;
 *
 * @param c the connection.
 *
 * @return the Certificate byte buffer.
 */
tls.createCertificate = function(c) {
  // TODO: check certificate request to ensure types are supported

  // get a certificate (a certificate as a PEM string)
  var client = (c.entity === tls.ConnectionEnd.client);
  var cert = null;
  if(c.getCertificate) {
    var hint;
    if(client) {
      hint = c.session.certificateRequest;
    } else {
      hint = c.session.extensions.server_name.serverNameList;
    }
    cert = c.getCertificate(c, hint);
  }

  // buffer to hold certificate list
  var certList = forge.util.createBuffer();
  if(cert !== null) {
    try {
      // normalize cert to a chain of certificates
      if(!forge.util.isArray(cert)) {
        cert = [cert];
      }
      var asn1 = null;
      for(var i = 0; i < cert.length; ++i) {
        var msg = forge.pem.decode(cert[i])[0];
        if(msg.type !== 'CERTIFICATE' &&
          msg.type !== 'X509 CERTIFICATE' &&
          msg.type !== 'TRUSTED CERTIFICATE') {
          var error = new Error('Could not convert certificate from PEM; PEM ' +
            'header type is not "CERTIFICATE", "X509 CERTIFICATE", or ' +
            '"TRUSTED CERTIFICATE".');
          error.headerType = msg.type;
          throw error;
        }
        if(msg.procType && msg.procType.type === 'ENCRYPTED') {
          throw new Error('Could not convert certificate from PEM; PEM is encrypted.');
        }

        var der = forge.util.createBuffer(msg.body);
        if(asn1 === null) {
          asn1 = forge.asn1.fromDer(der.bytes(), false);
        }

        // certificate entry is itself a vector with 3 length bytes
        var certBuffer = forge.util.createBuffer();
        writeVector(certBuffer, 3, der);

        // add cert vector to cert list vector
        certList.putBuffer(certBuffer);
      }

      // save certificate
      cert = forge.pki.certificateFromAsn1(asn1);
      if(client) {
        c.session.clientCertificate = cert;
      } else {
        c.session.serverCertificate = cert;
      }
    } catch(ex) {
      return c.error(c, {
        message: 'Could not send certificate list.',
        cause: ex,
        send: true,
        alert: {
          level: tls.Alert.Level.fatal,
          description: tls.Alert.Description.bad_certificate
        }
      });
    }
  }

  // determine length of the handshake message
  var length = 3 + certList.length(); // cert list vector

  // build record fragment
  var rval = forge.util.createBuffer();
  rval.putByte(tls.HandshakeType.certificate);
  rval.putInt24(length);
  writeVector(rval, 3, certList);
  return rval;
};

/**
 * Creates a ClientKeyExchange message.
 *
 * When this message will be sent:
 *   This message is always sent by the client. It will immediately follow the
 *   client certificate message, if it is sent. Otherwise it will be the first
 *   message sent by the client after it receives the server hello done
 *   message.
 *
 * Meaning of this message:
 *   With this message, the premaster secret is set, either though direct
 *   transmission of the RSA-encrypted secret, or by the transmission of
 *   Diffie-Hellman parameters which will allow each side to agree upon the
 *   same premaster secret. When the key exchange method is DH_RSA or DH_DSS,
 *   client certification has been requested, and the client was able to
 *   respond with a certificate which contained a Diffie-Hellman public key
 *   whose parameters (group and generator) matched those specified by the
 *   server in its certificate, this message will not contain any data.
 *
 * Meaning of this message:
 *   If RSA is being used for key agreement and authentication, the client
 *   generates a 48-byte premaster secret, encrypts it using the public key
 *   from the server's certificate or the temporary RSA key provided in a
 *   server key exchange message, and sends the result in an encrypted
 *   premaster secret message. This structure is a variant of the client
 *   key exchange message, not a message in itself.
 *
 * struct {
 *   select(KeyExchangeAlgorithm) {
 *     case rsa: EncryptedPreMasterSecret;
 *     case diffie_hellman: ClientDiffieHellmanPublic;
 *   } exchange_keys;
 * } ClientKeyExchange;
 *
 * struct {
 *   ProtocolVersion client_version;
 *   opaque random[46];
 * } PreMasterSecret;
 *
 * struct {
 *   public-key-encrypted PreMasterSecret pre_master_secret;
 * } EncryptedPreMasterSecret;
 *
 * A public-key-encrypted element is encoded as a vector <0..2^16-1>.
 *
 * @param c the connection.
 *
 * @return the ClientKeyExchange byte buffer.
 */
tls.createClientKeyExchange = function(c) {
  // create buffer to encrypt
  var b = forge.util.createBuffer();

  // add highest client-supported protocol to help server avoid version
  // rollback attacks
  b.putByte(c.session.clientHelloVersion.major);
  b.putByte(c.session.clientHelloVersion.minor);

  // generate and add 46 random bytes
  b.putBytes(forge.random.getBytes(46));

  // save pre-master secret
  var sp = c.session.sp;
  sp.pre_master_secret = b.getBytes();

  // RSA-encrypt the pre-master secret
  var key = c.session.serverCertificate.publicKey;
  b = key.encrypt(sp.pre_master_secret);

  /* Note: The encrypted pre-master secret will be stored in a
    public-key-encrypted opaque vector that has the length prefixed using
    2 bytes, so include those 2 bytes in the handshake message length. This
    is done as a minor optimization instead of calling writeVector(). */

  // determine length of the handshake message
  var length = b.length + 2;

  // build record fragment
  var rval = forge.util.createBuffer();
  rval.putByte(tls.HandshakeType.client_key_exchange);
  rval.putInt24(length);
  // add vector length bytes
  rval.putInt16(b.length);
  rval.putBytes(b);
  return rval;
};

/**
 * Creates a ServerKeyExchange message.
 *
 * @param c the connection.
 *
 * @return the ServerKeyExchange byte buffer.
 */
tls.createServerKeyExchange = function(c) {
  // this implementation only supports RSA, no Diffie-Hellman support,
  // so this record is empty

  // determine length of the handshake message
  var length = 0;

  // build record fragment
  var rval = forge.util.createBuffer();
  if(length > 0) {
    rval.putByte(tls.HandshakeType.server_key_exchange);
    rval.putInt24(length);
  }
  return rval;
};

/**
 * Gets the signed data used to verify a client-side certificate. See
 * tls.createCertificateVerify() for details.
 *
 * @param c the connection.
 * @param callback the callback to call once the signed data is ready.
 */
tls.getClientSignature = function(c, callback) {
  // generate data to RSA encrypt
  var b = forge.util.createBuffer();
  b.putBuffer(c.session.md5.digest());
  b.putBuffer(c.session.sha1.digest());
  b = b.getBytes();

  // create default signing function as necessary
  c.getSignature = c.getSignature || function(c, b, callback) {
    // do rsa encryption, call callback
    var privateKey = null;
    if(c.getPrivateKey) {
      try {
        privateKey = c.getPrivateKey(c, c.session.clientCertificate);
        privateKey = forge.pki.privateKeyFromPem(privateKey);
      } catch(ex) {
        c.error(c, {
          message: 'Could not get private key.',
          cause: ex,
          send: true,
          alert: {
            level: tls.Alert.Level.fatal,
            description: tls.Alert.Description.internal_error
          }
        });
      }
    }
    if(privateKey === null) {
      c.error(c, {
        message: 'No private key set.',
        send: true,
        alert: {
          level: tls.Alert.Level.fatal,
          description: tls.Alert.Description.internal_error
        }
      });
    } else {
      b = privateKey.sign(b, null);
    }
    callback(c, b);
  };

  // get client signature
  c.getSignature(c, b, callback);
};

/**
 * Creates a CertificateVerify message.
 *
 * Meaning of this message:
 *   This structure conveys the client's Diffie-Hellman public value
 *   (Yc) if it was not already included in the client's certificate.
 *   The encoding used for Yc is determined by the enumerated
 *   PublicValueEncoding. This structure is a variant of the client
 *   key exchange message, not a message in itself.
 *
 * When this message will be sent:
 *   This message is used to provide explicit verification of a client
 *   certificate. This message is only sent following a client
 *   certificate that has signing capability (i.e. all certificates
 *   except those containing fixed Diffie-Hellman parameters). When
 *   sent, it will immediately follow the client key exchange message.
 *
 * struct {
 *   Signature signature;
 * } CertificateVerify;
 *
 * CertificateVerify.signature.md5_hash
 *   MD5(handshake_messages);
 *
 * Certificate.signature.sha_hash
 *   SHA(handshake_messages);
 *
 * Here handshake_messages refers to all handshake messages sent or
 * received starting at client hello up to but not including this
 * message, including the type and length fields of the handshake
 * messages.
 *
 * select(SignatureAlgorithm) {
 *   case anonymous: struct { };
 *   case rsa:
 *     digitally-signed struct {
 *       opaque md5_hash[16];
 *       opaque sha_hash[20];
 *     };
 *   case dsa:
 *     digitally-signed struct {
 *       opaque sha_hash[20];
 *     };
 * } Signature;
 *
 * In digital signing, one-way hash functions are used as input for a
 * signing algorithm. A digitally-signed element is encoded as an opaque
 * vector <0..2^16-1>, where the length is specified by the signing
 * algorithm and key.
 *
 * In RSA signing, a 36-byte structure of two hashes (one SHA and one
 * MD5) is signed (encrypted with the private key). It is encoded with
 * PKCS #1 block type 0 or type 1 as described in [PKCS1].
 *
 * In DSS, the 20 bytes of the SHA hash are run directly through the
 * Digital Signing Algorithm with no additional hashing.
 *
 * @param c the connection.
 * @param signature the signature to include in the message.
 *
 * @return the CertificateVerify byte buffer.
 */
tls.createCertificateVerify = function(c, signature) {
  /* Note: The signature will be stored in a "digitally-signed" opaque
    vector that has the length prefixed using 2 bytes, so include those
    2 bytes in the handshake message length. This is done as a minor
    optimization instead of calling writeVector(). */

  // determine length of the handshake message
  var length = signature.length + 2;

  // build record fragment
  var rval = forge.util.createBuffer();
  rval.putByte(tls.HandshakeType.certificate_verify);
  rval.putInt24(length);
  // add vector length bytes
  rval.putInt16(signature.length);
  rval.putBytes(signature);
  return rval;
};

/**
 * Creates a CertificateRequest message.
 *
 * @param c the connection.
 *
 * @return the CertificateRequest byte buffer.
 */
tls.createCertificateRequest = function(c) {
  // TODO: support other certificate types
  var certTypes = forge.util.createBuffer();

  // common RSA certificate type
  certTypes.putByte(0x01);

  // TODO: verify that this data format is correct
  // add distinguished names from CA store
  var cAs = forge.util.createBuffer();
  for(var key in c.caStore.certs) {
    var cert = c.caStore.certs[key];
    var dn = forge.pki.distinguishedNameToAsn1(cert.subject);
    cAs.putBuffer(forge.asn1.toDer(dn));
  }

  // TODO: TLS 1.2+ has a different format

  // determine length of the handshake message
  var length =
    1 + certTypes.length() +
    2 + cAs.length();

  // build record fragment
  var rval = forge.util.createBuffer();
  rval.putByte(tls.HandshakeType.certificate_request);
  rval.putInt24(length);
  writeVector(rval, 1, certTypes);
  writeVector(rval, 2, cAs);
  return rval;
};

/**
 * Creates a ServerHelloDone message.
 *
 * @param c the connection.
 *
 * @return the ServerHelloDone byte buffer.
 */
tls.createServerHelloDone = function(c) {
  // build record fragment
  var rval = forge.util.createBuffer();
  rval.putByte(tls.HandshakeType.server_hello_done);
  rval.putInt24(0);
  return rval;
};

/**
 * Creates a ChangeCipherSpec message.
 *
 * The change cipher spec protocol exists to signal transitions in
 * ciphering strategies. The protocol consists of a single message,
 * which is encrypted and compressed under the current (not the pending)
 * connection state. The message consists of a single byte of value 1.
 *
 * struct {
 *   enum { change_cipher_spec(1), (255) } type;
 * } ChangeCipherSpec;
 *
 * @return the ChangeCipherSpec byte buffer.
 */
tls.createChangeCipherSpec = function() {
  var rval = forge.util.createBuffer();
  rval.putByte(0x01);
  return rval;
};

/**
 * Creates a Finished message.
 *
 * struct {
 *   opaque verify_data[12];
 * } Finished;
 *
 * verify_data
 *   PRF(master_secret, finished_label, MD5(handshake_messages) +
 *   SHA-1(handshake_messages)) [0..11];
 *
 * finished_label
 *   For Finished messages sent by the client, the string "client
 *   finished". For Finished messages sent by the server, the
 *   string "server finished".
 *
 * handshake_messages
 *   All of the data from all handshake messages up to but not
 *   including this message. This is only data visible at the
 *   handshake layer and does not include record layer headers.
 *   This is the concatenation of all the Handshake structures as
 *   defined in 7.4 exchanged thus far.
 *
 * @param c the connection.
 *
 * @return the Finished byte buffer.
 */
tls.createFinished = function(c) {
  // generate verify_data
  var b = forge.util.createBuffer();
  b.putBuffer(c.session.md5.digest());
  b.putBuffer(c.session.sha1.digest());

  // TODO: determine prf function and verify length for TLS 1.2
  var client = (c.entity === tls.ConnectionEnd.client);
  var sp = c.session.sp;
  var vdl = 12;
  var prf = prf_TLS1;
  var label = client ? 'client finished' : 'server finished';
  b = prf(sp.master_secret, label, b.getBytes(), vdl);

  // build record fragment
  var rval = forge.util.createBuffer();
  rval.putByte(tls.HandshakeType.finished);
  rval.putInt24(b.length());
  rval.putBuffer(b);
  return rval;
};

/**
 * Creates a HeartbeatMessage (See RFC 6520).
 *
 * struct {
 *   HeartbeatMessageType type;
 *   uint16 payload_length;
 *   opaque payload[HeartbeatMessage.payload_length];
 *   opaque padding[padding_length];
 * } HeartbeatMessage;
 *
 * The total length of a HeartbeatMessage MUST NOT exceed 2^14 or
 * max_fragment_length when negotiated as defined in [RFC6066].
 *
 * type: The message type, either heartbeat_request or heartbeat_response.
 *
 * payload_length: The length of the payload.
 *
 * payload: The payload consists of arbitrary content.
 *
 * padding: The padding is random content that MUST be ignored by the
 *   receiver. The length of a HeartbeatMessage is TLSPlaintext.length
 *   for TLS and DTLSPlaintext.length for DTLS. Furthermore, the
 *   length of the type field is 1 byte, and the length of the
 *   payload_length is 2. Therefore, the padding_length is
 *   TLSPlaintext.length - payload_length - 3 for TLS and
 *   DTLSPlaintext.length - payload_length - 3 for DTLS. The
 *   padding_length MUST be at least 16.
 *
 * The sender of a HeartbeatMessage MUST use a random padding of at
 * least 16 bytes. The padding of a received HeartbeatMessage message
 * MUST be ignored.
 *
 * If the payload_length of a received HeartbeatMessage is too large,
 * the received HeartbeatMessage MUST be discarded silently.
 *
 * @param c the connection.
 * @param type the tls.HeartbeatMessageType.
 * @param payload the heartbeat data to send as the payload.
 * @param [payloadLength] the payload length to use, defaults to the
 *          actual payload length.
 *
 * @return the HeartbeatRequest byte buffer.
 */
tls.createHeartbeat = function(type, payload, payloadLength) {
  if(typeof payloadLength === 'undefined') {
    payloadLength = payload.length;
  }
  // build record fragment
  var rval = forge.util.createBuffer();
  rval.putByte(type);               // heartbeat message type
  rval.putInt16(payloadLength);     // payload length
  rval.putBytes(payload);           // payload
  // padding
  var plaintextLength = rval.length();
  var paddingLength = Math.max(16, plaintextLength - payloadLength - 3);
  rval.putBytes(forge.random.getBytes(paddingLength));
  return rval;
};

/**
 * Fragments, compresses, encrypts, and queues a record for delivery.
 *
 * @param c the connection.
 * @param record the record to queue.
 */
tls.queue = function(c, record) {
  // error during record creation
  if(!record) {
    return;
  }

  // if the record is a handshake record, update handshake hashes
  if(record.type === tls.ContentType.handshake) {
    var bytes = record.fragment.bytes();
    c.session.md5.update(bytes);
    c.session.sha1.update(bytes);
    bytes = null;
  }

  // handle record fragmentation
  var records;
  if(record.fragment.length() <= tls.MaxFragment) {
    records = [record];
  } else {
    // fragment data as long as it is too long
    records = [];
    var data = record.fragment.bytes();
    while(data.length > tls.MaxFragment) {
      records.push(tls.createRecord(c, {
        type: record.type,
        data: forge.util.createBuffer(data.slice(0, tls.MaxFragment))
      }));
      data = data.slice(tls.MaxFragment);
    }
    // add last record
    if(data.length > 0) {
      records.push(tls.createRecord(c, {
        type: record.type,
        data: forge.util.createBuffer(data)
      }));
    }
  }

  // compress and encrypt all fragmented records
  for(var i = 0; i < records.length && !c.fail; ++i) {
    // update the record using current write state
    var rec = records[i];
    var s = c.state.current.write;
    if(s.update(c, rec)) {
      // store record
      c.records.push(rec);
    }
  }
};

/**
 * Flushes all queued records to the output buffer and calls the
 * tlsDataReady() handler on the given connection.
 *
 * @param c the connection.
 *
 * @return true on success, false on failure.
 */
tls.flush = function(c) {
  for(var i = 0; i < c.records.length; ++i) {
    var record = c.records[i];

    // add record header and fragment
    c.tlsData.putByte(record.type);
    c.tlsData.putByte(record.version.major);
    c.tlsData.putByte(record.version.minor);
    c.tlsData.putInt16(record.fragment.length());
    c.tlsData.putBuffer(c.records[i].fragment);
  }
  c.records = [];
  return c.tlsDataReady(c);
};

/**
 * Maps a pki.certificateError to a tls.Alert.Description.
 *
 * @param error the error to map.
 *
 * @return the alert description.
 */
var _certErrorToAlertDesc = function(error) {
  switch(error) {
  case true:
    return true;
  case forge.pki.certificateError.bad_certificate:
    return tls.Alert.Description.bad_certificate;
  case forge.pki.certificateError.unsupported_certificate:
    return tls.Alert.Description.unsupported_certificate;
  case forge.pki.certificateError.certificate_revoked:
    return tls.Alert.Description.certificate_revoked;
  case forge.pki.certificateError.certificate_expired:
    return tls.Alert.Description.certificate_expired;
  case forge.pki.certificateError.certificate_unknown:
    return tls.Alert.Description.certificate_unknown;
  case forge.pki.certificateError.unknown_ca:
    return tls.Alert.Description.unknown_ca;
  default:
    return tls.Alert.Description.bad_certificate;
  }
};

/**
 * Maps a tls.Alert.Description to a pki.certificateError.
 *
 * @param desc the alert description.
 *
 * @return the certificate error.
 */
var _alertDescToCertError = function(desc) {
  switch(desc) {
  case true:
    return true;
  case tls.Alert.Description.bad_certificate:
    return forge.pki.certificateError.bad_certificate;
  case tls.Alert.Description.unsupported_certificate:
    return forge.pki.certificateError.unsupported_certificate;
  case tls.Alert.Description.certificate_revoked:
    return forge.pki.certificateError.certificate_revoked;
  case tls.Alert.Description.certificate_expired:
    return forge.pki.certificateError.certificate_expired;
  case tls.Alert.Description.certificate_unknown:
    return forge.pki.certificateError.certificate_unknown;
  case tls.Alert.Description.unknown_ca:
    return forge.pki.certificateError.unknown_ca;
  default:
    return forge.pki.certificateError.bad_certificate;
  }
};

/**
 * Verifies a certificate chain against the given connection's
 * Certificate Authority store.
 *
 * @param c the TLS connection.
 * @param chain the certificate chain to verify, with the root or highest
 *          authority at the end.
 *
 * @return true if successful, false if not.
 */
tls.verifyCertificateChain = function(c, chain) {
  try {
    // verify chain
    forge.pki.verifyCertificateChain(c.caStore, chain,
      function verify(vfd, depth, chain) {
        // convert pki.certificateError to tls alert description
        var desc = _certErrorToAlertDesc(vfd);

        // call application callback
        var ret = c.verify(c, vfd, depth, chain);
        if(ret !== true) {
          if(typeof ret === 'object' && !forge.util.isArray(ret)) {
            // throw custom error
            var error = new Error('The application rejected the certificate.');
            error.send = true;
            error.alert = {
              level: tls.Alert.Level.fatal,
              description: tls.Alert.Description.bad_certificate
            };
            if(ret.message) {
              error.message = ret.message;
            }
            if(ret.alert) {
              error.alert.description = ret.alert;
            }
            throw error;
          }

          // convert tls alert description to pki.certificateError
          if(ret !== vfd) {
            ret = _alertDescToCertError(ret);
          }
        }

        return ret;
      });
  } catch(ex) {
    // build tls error if not already customized
    var err = ex;
    if(typeof err !== 'object' || forge.util.isArray(err)) {
      err = {
        send: true,
        alert: {
          level: tls.Alert.Level.fatal,
          description: _certErrorToAlertDesc(ex)
        }
      };
    }
    if(!('send' in err)) {
      err.send = true;
    }
    if(!('alert' in err)) {
      err.alert = {
        level: tls.Alert.Level.fatal,
        description: _certErrorToAlertDesc(err.error)
      };
    }

    // send error
    c.error(c, err);
  }

  return !c.fail;
};

/**
 * Creates a new TLS session cache.
 *
 * @param cache optional map of session ID to cached session.
 * @param capacity the maximum size for the cache (default: 100).
 *
 * @return the new TLS session cache.
 */
tls.createSessionCache = function(cache, capacity) {
  var rval = null;

  // assume input is already a session cache object
  if(cache && cache.getSession && cache.setSession && cache.order) {
    rval = cache;
  } else {
    // create cache
    rval = {};
    rval.cache = cache || {};
    rval.capacity = Math.max(capacity || 100, 1);
    rval.order = [];

    // store order for sessions, delete session overflow
    for(var key in cache) {
      if(rval.order.length <= capacity) {
        rval.order.push(key);
      } else {
        delete cache[key];
      }
    }

    // get a session from a session ID (or get any session)
    rval.getSession = function(sessionId) {
      var session = null;
      var key = null;

      // if session ID provided, use it
      if(sessionId) {
        key = forge.util.bytesToHex(sessionId);
      } else if(rval.order.length > 0) {
        // get first session from cache
        key = rval.order[0];
      }

      if(key !== null && key in rval.cache) {
        // get cached session and remove from cache
        session = rval.cache[key];
        delete rval.cache[key];
        for(var i in rval.order) {
          if(rval.order[i] === key) {
            rval.order.splice(i, 1);
            break;
          }
        }
      }

      return session;
    };

    // set a session in the cache
    rval.setSession = function(sessionId, session) {
      // remove session from cache if at capacity
      if(rval.order.length === rval.capacity) {
        var key = rval.order.shift();
        delete rval.cache[key];
      }
      // add session to cache
      var key = forge.util.bytesToHex(sessionId);
      rval.order.push(key);
      rval.cache[key] = session;
    };
  }

  return rval;
};

/**
 * Creates a new TLS connection.
 *
 * See public createConnection() docs for more details.
 *
 * @param options the options for this connection.
 *
 * @return the new TLS connection.
 */
tls.createConnection = function(options) {
  var caStore = null;
  if(options.caStore) {
    // if CA store is an array, convert it to a CA store object
    if(forge.util.isArray(options.caStore)) {
      caStore = forge.pki.createCaStore(options.caStore);
    } else {
      caStore = options.caStore;
    }
  } else {
    // create empty CA store
    caStore = forge.pki.createCaStore();
  }

  // setup default cipher suites
  var cipherSuites = options.cipherSuites || null;
  if(cipherSuites === null) {
    cipherSuites = [];
    for(var key in tls.CipherSuites) {
      cipherSuites.push(tls.CipherSuites[key]);
    }
  }

  // set default entity
  var entity = (options.server || false) ?
    tls.ConnectionEnd.server : tls.ConnectionEnd.client;

  // create session cache if requested
  var sessionCache = options.sessionCache ?
    tls.createSessionCache(options.sessionCache) : null;

  // create TLS connection
  var c = {
    version: {major: tls.Version.major, minor: tls.Version.minor},
    entity: entity,
    sessionId: options.sessionId,
    caStore: caStore,
    sessionCache: sessionCache,
    cipherSuites: cipherSuites,
    connected: options.connected,
    virtualHost: options.virtualHost || null,
    verifyClient: options.verifyClient || false,
    verify: options.verify || function(cn, vfd, dpth, cts) {return vfd;},
    getCertificate: options.getCertificate || null,
    getPrivateKey: options.getPrivateKey || null,
    getSignature: options.getSignature || null,
    input: forge.util.createBuffer(),
    tlsData: forge.util.createBuffer(),
    data: forge.util.createBuffer(),
    tlsDataReady: options.tlsDataReady,
    dataReady: options.dataReady,
    heartbeatReceived: options.heartbeatReceived,
    closed: options.closed,
    error: function(c, ex) {
      // set origin if not set
      ex.origin = ex.origin ||
        ((c.entity === tls.ConnectionEnd.client) ? 'client' : 'server');

      // send TLS alert
      if(ex.send) {
        tls.queue(c, tls.createAlert(c, ex.alert));
        tls.flush(c);
      }

      // error is fatal by default
      var fatal = (ex.fatal !== false);
      if(fatal) {
        // set fail flag
        c.fail = true;
      }

      // call error handler first
      options.error(c, ex);

      if(fatal) {
        // fatal error, close connection, do not clear fail
        c.close(false);
      }
    },
    deflate: options.deflate || null,
    inflate: options.inflate || null
  };

  /**
   * Resets a closed TLS connection for reuse. Called in c.close().
   *
   * @param clearFail true to clear the fail flag (default: true).
   */
  c.reset = function(clearFail) {
    c.version = {major: tls.Version.major, minor: tls.Version.minor};
    c.record = null;
    c.session = null;
    c.peerCertificate = null;
    c.state = {
      pending: null,
      current: null
    };
    c.expect = (c.entity === tls.ConnectionEnd.client) ? SHE : CHE;
    c.fragmented = null;
    c.records = [];
    c.open = false;
    c.handshakes = 0;
    c.handshaking = false;
    c.isConnected = false;
    c.fail = !(clearFail || typeof(clearFail) === 'undefined');
    c.input.clear();
    c.tlsData.clear();
    c.data.clear();
    c.state.current = tls.createConnectionState(c);
  };

  // do initial reset of connection
  c.reset();

  /**
   * Updates the current TLS engine state based on the given record.
   *
   * @param c the TLS connection.
   * @param record the TLS record to act on.
   */
  var _update = function(c, record) {
    // get record handler (align type in table by subtracting lowest)
    var aligned = record.type - tls.ContentType.change_cipher_spec;
    var handlers = ctTable[c.entity][c.expect];
    if(aligned in handlers) {
      handlers[aligned](c, record);
    } else {
      // unexpected record
      tls.handleUnexpected(c, record);
    }
  };

  /**
   * Reads the record header and initializes the next record on the given
   * connection.
   *
   * @param c the TLS connection with the next record.
   *
   * @return 0 if the input data could be processed, otherwise the
   *         number of bytes required for data to be processed.
   */
  var _readRecordHeader = function(c) {
    var rval = 0;

    // get input buffer and its length
    var b = c.input;
    var len = b.length();

    // need at least 5 bytes to initialize a record
    if(len < 5) {
      rval = 5 - len;
    } else {
      // enough bytes for header
      // initialize record
      c.record = {
        type: b.getByte(),
        version: {
          major: b.getByte(),
          minor: b.getByte()
        },
        length: b.getInt16(),
        fragment: forge.util.createBuffer(),
        ready: false
      };

      // check record version
      var compatibleVersion = (c.record.version.major === c.version.major);
      if(compatibleVersion && c.session && c.session.version) {
        // session version already set, require same minor version
        compatibleVersion = (c.record.version.minor === c.version.minor);
      }
      if(!compatibleVersion) {
        c.error(c, {
          message: 'Incompatible TLS version.',
          send: true,
          alert: {
            level: tls.Alert.Level.fatal,
            description: tls.Alert.Description.protocol_version
          }
        });
      }
    }

    return rval;
  };

  /**
   * Reads the next record's contents and appends its message to any
   * previously fragmented message.
   *
   * @param c the TLS connection with the next record.
   *
   * @return 0 if the input data could be processed, otherwise the
   *         number of bytes required for data to be processed.
   */
  var _readRecord = function(c) {
    var rval = 0;

    // ensure there is enough input data to get the entire record
    var b = c.input;
    var len = b.length();
    if(len < c.record.length) {
      // not enough data yet, return how much is required
      rval = c.record.length - len;
    } else {
      // there is enough data to parse the pending record
      // fill record fragment and compact input buffer
      c.record.fragment.putBytes(b.getBytes(c.record.length));
      b.compact();

      // update record using current read state
      var s = c.state.current.read;
      if(s.update(c, c.record)) {
        // see if there is a previously fragmented message that the
        // new record's message fragment should be appended to
        if(c.fragmented !== null) {
          // if the record type matches a previously fragmented
          // record, append the record fragment to it
          if(c.fragmented.type === c.record.type) {
            // concatenate record fragments
            c.fragmented.fragment.putBuffer(c.record.fragment);
            c.record = c.fragmented;
          } else {
            // error, invalid fragmented record
            c.error(c, {
              message: 'Invalid fragmented record.',
              send: true,
              alert: {
                level: tls.Alert.Level.fatal,
                description:
                  tls.Alert.Description.unexpected_message
              }
            });
          }
        }

        // record is now ready
        c.record.ready = true;
      }
    }

    return rval;
  };

  /**
   * Performs a handshake using the TLS Handshake Protocol, as a client.
   *
   * This method should only be called if the connection is in client mode.
   *
   * @param sessionId the session ID to use, null to start a new one.
   */
  c.handshake = function(sessionId) {
    // error to call this in non-client mode
    if(c.entity !== tls.ConnectionEnd.client) {
      // not fatal error
      c.error(c, {
        message: 'Cannot initiate handshake as a server.',
        fatal: false
      });
    } else if(c.handshaking) {
      // handshake is already in progress, fail but not fatal error
      c.error(c, {
        message: 'Handshake already in progress.',
        fatal: false
      });
    } else {
      // clear fail flag on reuse
      if(c.fail && !c.open && c.handshakes === 0) {
        c.fail = false;
      }

      // now handshaking
      c.handshaking = true;

      // default to blank (new session)
      sessionId = sessionId || '';

      // if a session ID was specified, try to find it in the cache
      var session = null;
      if(sessionId.length > 0) {
        if(c.sessionCache) {
          session = c.sessionCache.getSession(sessionId);
        }

        // matching session not found in cache, clear session ID
        if(session === null) {
          sessionId = '';
        }
      }

      // no session given, grab a session from the cache, if available
      if(sessionId.length === 0 && c.sessionCache) {
        session = c.sessionCache.getSession();
        if(session !== null) {
          sessionId = session.id;
        }
      }

      // set up session
      c.session = {
        id: sessionId,
        version: null,
        cipherSuite: null,
        compressionMethod: null,
        serverCertificate: null,
        certificateRequest: null,
        clientCertificate: null,
        sp: {},
        md5: forge.md.md5.create(),
        sha1: forge.md.sha1.create()
      };

      // use existing session information
      if(session) {
        // only update version on connection, session version not yet set
        c.version = session.version;
        c.session.sp = session.sp;
      }

      // generate new client random
      c.session.sp.client_random = tls.createRandom().getBytes();

      // connection now open
      c.open = true;

      // send hello
      tls.queue(c, tls.createRecord(c, {
        type: tls.ContentType.handshake,
        data: tls.createClientHello(c)
      }));
      tls.flush(c);
    }
  };

  /**
   * Called when TLS protocol data has been received from somewhere and should
   * be processed by the TLS engine.
   *
   * @param data the TLS protocol data, as a string, to process.
   *
   * @return 0 if the data could be processed, otherwise the number of bytes
   *         required for data to be processed.
   */
  c.process = function(data) {
    var rval = 0;

    // buffer input data
    if(data) {
      c.input.putBytes(data);
    }

    // process next record if no failure, process will be called after
    // each record is handled (since handling can be asynchronous)
    if(!c.fail) {
      // reset record if ready and now empty
      if(c.record !== null &&
        c.record.ready && c.record.fragment.isEmpty()) {
        c.record = null;
      }

      // if there is no pending record, try to read record header
      if(c.record === null) {
        rval = _readRecordHeader(c);
      }

      // read the next record (if record not yet ready)
      if(!c.fail && c.record !== null && !c.record.ready) {
        rval = _readRecord(c);
      }

      // record ready to be handled, update engine state
      if(!c.fail && c.record !== null && c.record.ready) {
        _update(c, c.record);
      }
    }

    return rval;
  };

  /**
   * Requests that application data be packaged into a TLS record. The
   * tlsDataReady handler will be called when the TLS record(s) have been
   * prepared.
   *
   * @param data the application data, as a raw 'binary' encoded string, to
   *          be sent; to send utf-16/utf-8 string data, use the return value
   *          of util.encodeUtf8(str).
   *
   * @return true on success, false on failure.
   */
  c.prepare = function(data) {
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.application_data,
      data: forge.util.createBuffer(data)
    }));
    return tls.flush(c);
  };

  /**
   * Requests that a heartbeat request be packaged into a TLS record for
   * transmission. The tlsDataReady handler will be called when TLS record(s)
   * have been prepared.
   *
   * When a heartbeat response has been received, the heartbeatReceived
   * handler will be called with the matching payload. This handler can
   * be used to clear a retransmission timer, etc.
   *
   * @param payload the heartbeat data to send as the payload in the message.
   * @param [payloadLength] the payload length to use, defaults to the
   *          actual payload length.
   *
   * @return true on success, false on failure.
   */
  c.prepareHeartbeatRequest = function(payload, payloadLength) {
    if(payload instanceof forge.util.ByteBuffer) {
      payload = payload.bytes();
    }
    if(typeof payloadLength === 'undefined') {
      payloadLength = payload.length;
    }
    c.expectedHeartbeatPayload = payload;
    tls.queue(c, tls.createRecord(c, {
      type: tls.ContentType.heartbeat,
      data: tls.createHeartbeat(
        tls.HeartbeatMessageType.heartbeat_request, payload, payloadLength)
    }));
    return tls.flush(c);
  };

  /**
   * Closes the connection (sends a close_notify alert).
   *
   * @param clearFail true to clear the fail flag (default: true).
   */
  c.close = function(clearFail) {
    // save session if connection didn't fail
    if(!c.fail && c.sessionCache && c.session) {
      // only need to preserve session ID, version, and security params
      var session = {
        id: c.session.id,
        version: c.session.version,
        sp: c.session.sp
      };
      session.sp.keys = null;
      c.sessionCache.setSession(session.id, session);
    }

    if(c.open) {
      // connection no longer open, clear input
      c.open = false;
      c.input.clear();

      // if connected or handshaking, send an alert
      if(c.isConnected || c.handshaking) {
        c.isConnected = c.handshaking = false;

        // send close_notify alert
        tls.queue(c, tls.createAlert(c, {
          level: tls.Alert.Level.warning,
          description: tls.Alert.Description.close_notify
        }));
        tls.flush(c);
      }

      // call handler
      c.closed(c);
    }

    // reset TLS connection, do not clear fail flag
    c.reset(clearFail);
  };

  return c;
};

/* TLS API */
forge.tls = forge.tls || {};

// expose non-functions
for(var key in tls) {
  if(typeof tls[key] !== 'function') {
    forge.tls[key] = tls[key];
  }
}

// expose prf_tls1 for testing
forge.tls.prf_tls1 = prf_TLS1;

// expose sha1 hmac method
forge.tls.hmac_sha1 = hmac_sha1;

// expose session cache creation
forge.tls.createSessionCache = tls.createSessionCache;

/**
 * Creates a new TLS connection. This does not make any assumptions about the
 * transport layer that TLS is working on top of, ie: it does not assume there
 * is a TCP/IP connection or establish one. A TLS connection is totally
 * abstracted away from the layer is runs on top of, it merely establishes a
 * secure channel between a client" and a "server".
 *
 * A TLS connection contains 4 connection states: pending read and write, and
 * current read and write.
 *
 * At initialization, the current read and write states will be null. Only once
 * the security parameters have been set and the keys have been generated can
 * the pending states be converted into current states. Current states will be
 * updated for each record processed.
 *
 * A custom certificate verify callback may be provided to check information
 * like the common name on the server's certificate. It will be called for
 * every certificate in the chain. It has the following signature:
 *
 * variable func(c, certs, index, preVerify)
 * Where:
 * c         The TLS connection
 * verified  Set to true if certificate was verified, otherwise the alert
 *           tls.Alert.Description for why the certificate failed.
 * depth     The current index in the chain, where 0 is the server's cert.
 * certs     The certificate chain, *NOTE* if the server was anonymous then
 *           the chain will be empty.
 *
 * The function returns true on success and on failure either the appropriate
 * tls.Alert.Description or an object with 'alert' set to the appropriate
 * tls.Alert.Description and 'message' set to a custom error message. If true
 * is not returned then the connection will abort using, in order of
 * availability, first the returned alert description, second the preVerify
 * alert description, and lastly the default 'bad_certificate'.
 *
 * There are three callbacks that can be used to make use of client-side
 * certificates where each takes the TLS connection as the first parameter:
 *
 * getCertificate(conn, hint)
 *   The second parameter is a hint as to which certificate should be
 *   returned. If the connection entity is a client, then the hint will be
 *   the CertificateRequest message from the server that is part of the
 *   TLS protocol. If the connection entity is a server, then it will be
 *   the servername list provided via an SNI extension the ClientHello, if
 *   one was provided (empty array if not). The hint can be examined to
 *   determine which certificate to use (advanced). Most implementations
 *   will just return a certificate. The return value must be a
 *   PEM-formatted certificate or an array of PEM-formatted certificates
 *   that constitute a certificate chain, with the first in the array/chain
 *   being the client's certificate.
 * getPrivateKey(conn, certificate)
 *   The second parameter is an forge.pki X.509 certificate object that
 *   is associated with the requested private key. The return value must
 *   be a PEM-formatted private key.
 * getSignature(conn, bytes, callback)
 *   This callback can be used instead of getPrivateKey if the private key
 *   is not directly accessible in javascript or should not be. For
 *   instance, a secure external web service could provide the signature
 *   in exchange for appropriate credentials. The second parameter is a
 *   string of bytes to be signed that are part of the TLS protocol. These
 *   bytes are used to verify that the private key for the previously
 *   provided client-side certificate is accessible to the client. The
 *   callback is a function that takes 2 parameters, the TLS connection
 *   and the RSA encrypted (signed) bytes as a string. This callback must
 *   be called once the signature is ready.
 *
 * @param options the options for this connection:
 *   server: true if the connection is server-side, false for client.
 *   sessionId: a session ID to reuse, null for a new connection.
 *   caStore: an array of certificates to trust.
 *   sessionCache: a session cache to use.
 *   cipherSuites: an optional array of cipher suites to use,
 *     see tls.CipherSuites.
 *   connected: function(conn) called when the first handshake completes.
 *   virtualHost: the virtual server name to use in a TLS SNI extension.
 *   verifyClient: true to require a client certificate in server mode,
 *     'optional' to request one, false not to (default: false).
 *   verify: a handler used to custom verify certificates in the chain.
 *   getCertificate: an optional callback used to get a certificate or
 *     a chain of certificates (as an array).
 *   getPrivateKey: an optional callback used to get a private key.
 *   getSignature: an optional callback used to get a signature.
 *   tlsDataReady: function(conn) called when TLS protocol data has been
 *     prepared and is ready to be used (typically sent over a socket
 *     connection to its destination), read from conn.tlsData buffer.
 *   dataReady: function(conn) called when application data has
 *     been parsed from a TLS record and should be consumed by the
 *     application, read from conn.data buffer.
 *   closed: function(conn) called when the connection has been closed.
 *   error: function(conn, error) called when there was an error.
 *   deflate: function(inBytes) if provided, will deflate TLS records using
 *     the deflate algorithm if the server supports it.
 *   inflate: function(inBytes) if provided, will inflate TLS records using
 *     the deflate algorithm if the server supports it.
 *
 * @return the new TLS connection.
 */
forge.tls.createConnection = tls.createConnection;

} // end module implementation

/* ########## Begin module wrapper ########## */
var name = 'tls';
if(typeof define !== 'function') {
  // NodeJS -> AMD
  if(typeof module === 'object' && module.exports) {
    var nodeJS = true;
    define = function(ids, factory) {
      factory(require, module);
    };
  } else {
    // <script>
    if(typeof forge === 'undefined') {
      forge = {};
    }
    return initModule(forge);
  }
}
// AMD
var deps;
var defineFunc = function(require, module) {
  module.exports = function(forge) {
    var mods = deps.map(function(dep) {
      return require(dep);
    }).concat(initModule);
    // handle circular dependencies
    forge = forge || {};
    forge.defined = forge.defined || {};
    if(forge.defined[name]) {
      return forge[name];
    }
    forge.defined[name] = true;
    for(var i = 0; i < mods.length; ++i) {
      mods[i](forge);
    }
    return forge[name];
  };
};
var tmpDefine = define;
define = function(ids, factory) {
  deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2);
  if(nodeJS) {
    delete define;
    return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0));
  }
  define = tmpDefine;
  return define.apply(null, Array.prototype.slice.call(arguments, 0));
};
define([
  'require',
  'module',
  './asn1',
  './hmac',
  './md',
  './pem',
  './pki',
  './random',
  './util'], function() {
  defineFunc.apply(null, Array.prototype.slice.call(arguments, 0));
});
})();
