class TTTLS13::Message::ClientHello

Attributes

cipher_suites[R]
extensions[R]
legacy_compression_methods[R]
legacy_session_id[R]
legacy_version[R]
msg_type[R]
random[R]

Public Class Methods

deserialize(binary) click to toggle source

@param binary [String]

@raise [TTTLS13::Error::ErrorAlerts]

@return [TTTLS13::Message::ClientHello] rubocop: disable Metrics/AbcSize rubocop: disable Metrics/MethodLength

# File lib/tttls1.3/message/client_hello.rb, line 89
def self.deserialize(binary)
  raise Error::ErrorAlerts, :internal_error if binary.nil?
  raise Error::ErrorAlerts, :decode_error if binary.length < 39
  raise Error::ErrorAlerts, :internal_error \
    unless binary[0] == HandshakeType::CLIENT_HELLO

  msg_len = Convert.bin2i(binary.slice(1, 3))
  legacy_version = binary.slice(4, 2)
  random = binary.slice(6, 32)
  lsid_len = Convert.bin2i(binary[38])
  legacy_session_id = binary.slice(39, lsid_len)
  i = 39 + lsid_len
  cs_len = Convert.bin2i(binary.slice(i, 2))
  i += 2
  cs_bin = binary.slice(i, cs_len)
  cipher_suites = CipherSuites.deserialize(cs_bin)
  i += cs_len
  cm_len = Convert.bin2i(binary[i])
  i += 1
  legacy_compression_methods = binary.slice(i, cm_len).split('')
  i += cm_len
  exs_len = Convert.bin2i(binary.slice(i, 2))
  i += 2
  exs_bin = binary.slice(i, exs_len)
  extensions = Extensions.deserialize(exs_bin,
                                      HandshakeType::CLIENT_HELLO)
  i += exs_len
  raise Error::ErrorAlerts, :decode_error unless i == msg_len + 4 &&
                                                 i == binary.length

  ClientHello.new(legacy_version: legacy_version,
                  random: random,
                  legacy_session_id: legacy_session_id,
                  cipher_suites: cipher_suites,
                  legacy_compression_methods: legacy_compression_methods,
                  extensions: extensions)
end
new(legacy_version: ProtocolVersion::TLS_1_2, random: OpenSSL::Random.random_bytes(32), legacy_session_id: OpenSSL::Random.random_bytes(32), cipher_suites:, legacy_compression_methods: ["\x00"], extensions: Extensions.new) click to toggle source

@param legacy_version [String] @param random [String] @param legacy_session_id [String] @param cipher_suites [TTTLS13::CipherSuites] @param legacy_compression_methods [Array of String] @param extensions [TTTLS13::Message::Extensions] rubocop: disable Metrics/ParameterLists

# File lib/tttls1.3/message/client_hello.rb, line 53
def initialize(legacy_version: ProtocolVersion::TLS_1_2,
               random: OpenSSL::Random.random_bytes(32),
               legacy_session_id: OpenSSL::Random.random_bytes(32),
               cipher_suites:,
               legacy_compression_methods: ["\x00"],
               extensions: Extensions.new)
  @msg_type = HandshakeType::CLIENT_HELLO
  @legacy_version = legacy_version
  @random = random
  @legacy_session_id = legacy_session_id
  @cipher_suites = cipher_suites
  @legacy_compression_methods = legacy_compression_methods
  @extensions = extensions
end

Public Instance Methods

appearable_extensions?() click to toggle source

@return [Boolean]

# File lib/tttls1.3/message/client_hello.rb, line 130
def appearable_extensions?
  exs = @extensions.keys - APPEARABLE_CH_EXTENSIONS
  return true if exs.empty?

  !(exs - DEFINED_EXTENSIONS).empty?
end
negotiated_tls_1_3?() click to toggle source

@return [Boolean]

# File lib/tttls1.3/message/client_hello.rb, line 138
def negotiated_tls_1_3?
  sv = @extensions[ExtensionType::SUPPORTED_VERSIONS]

  @legacy_version == ProtocolVersion::TLS_1_2 &&
    (sv&.versions || []).include?(ProtocolVersion::TLS_1_3)
end
serialize() click to toggle source

@return [String]

# File lib/tttls1.3/message/client_hello.rb, line 70
def serialize
  binary = ''
  binary += @legacy_version
  binary += @random
  binary += @legacy_session_id.prefix_uint8_length
  binary += @cipher_suites.serialize
  binary += @legacy_compression_methods.join.prefix_uint8_length
  binary += @extensions.serialize

  @msg_type + binary.prefix_uint24_length
end
valid_key_share?() click to toggle source

@return [Boolean]

# File lib/tttls1.3/message/client_hello.rb, line 146
def valid_key_share?
  ks = @extensions[Message::ExtensionType::KEY_SHARE]
  ks_groups = ks&.key_share_entry&.map(&:group) || []
  sg = @extensions[Message::ExtensionType::SUPPORTED_GROUPS]
  sg_groups = sg&.named_group_list || []

  # Each KeyShareEntry value MUST correspond to a group offered in the
  # "supported_groups" extension and MUST appear in the same order.
  #
  # Clients MUST NOT offer multiple KeyShareEntry values for the same
  # group.
  (ks_groups - sg_groups).empty? &&
    sg_groups.filter { |g| ks_groups.include?(g) } == ks_groups &&
    ks_groups.uniq == ks_groups
end