Class: TTTLS13::Message::Record

Inherits:
Object
  • Object
show all
Defined in:
lib/tttls1.3/message/record.rb

Overview

rubocop: disable Metrics/ClassLength

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type:, legacy_record_version: ProtocolVersion::TLS_1_2, messages:, cipher:) ⇒ Record

Returns a new instance of Record.

Parameters:



20
21
22
23
24
25
26
27
28
# File 'lib/tttls1.3/message/record.rb', line 20

def initialize(type:,
               legacy_record_version: ProtocolVersion::TLS_1_2,
               messages:,
               cipher:)
  @type = type
  @legacy_record_version = legacy_record_version
  @messages = messages
  @cipher = cipher
end

Instance Attribute Details

#cipherObject (readonly)

Returns the value of attribute cipher.



14
15
16
# File 'lib/tttls1.3/message/record.rb', line 14

def cipher
  @cipher
end

#legacy_record_versionObject (readonly)

Returns the value of attribute legacy_record_version.



12
13
14
# File 'lib/tttls1.3/message/record.rb', line 12

def legacy_record_version
  @legacy_record_version
end

#messagesObject (readonly)

Returns the value of attribute messages.



13
14
15
# File 'lib/tttls1.3/message/record.rb', line 13

def messages
  @messages
end

#typeObject (readonly)

Returns the value of attribute type.



11
12
13
# File 'lib/tttls1.3/message/record.rb', line 11

def type
  @type
end

Class Method Details

.deserialize(binary, cipher, buffered = '', record_size_limit = DEFAULT_RECORD_SIZE_LIMIT) ⇒ TTTLS13::Message::Record, ...

NOTE: If previous Record has surplus_binary, surplus_binary should is given to Record.deserialize as buffered.

rubocop: disable Metrics/AbcSize rubocop: disable Metrics/CyclomaticComplexity rubocop: disable Metrics/PerceivedComplexity

Parameters:

  • binary (String)
  • cipher (TTTLS13::Cryptograph::$Object)
  • buffered (String) (defaults to: '')

    surplus_binary

  • record_size_limit (Integer) (defaults to: DEFAULT_RECORD_SIZE_LIMIT)

Returns:

Raises:



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/tttls1.3/message/record.rb', line 70

def self.deserialize(binary, cipher, buffered = '',
                     record_size_limit = DEFAULT_RECORD_SIZE_LIMIT)
  raise Error::ErrorAlerts, :internal_error if binary.nil?
  raise Error::ErrorAlerts, :decode_error if binary.length < 5

  type = binary[0]
  legacy_record_version = binary.slice(1, 2)
  fragment_len = Convert.bin2i(binary.slice(3, 2))
  raise Error::ErrorAlerts, :record_overflow \
    if (cipher.is_a?(Cryptograph::Passer) && fragment_len > 2**14) ||
       (cipher.is_a?(Cryptograph::Aead) && fragment_len > 2**14 + 256)

  fragment = binary.slice(5, fragment_len)
  raise Error::ErrorAlerts, :decode_error \
    unless binary.length == 5 + fragment_len

  if type == ContentType::APPLICATION_DATA
    if fragment.length - cipher.auth_tag_len > record_size_limit
      raise Error::ErrorAlerts, :record_overflow
    end

    fragment, inner_type = cipher.decrypt(fragment, binary.slice(0, 5))
  end

  messages, orig_msgs, surplus_binary = deserialize_fragment(
    buffered + fragment,
    inner_type || type
  )
  record = Record.new(
    type: type,
    legacy_record_version: legacy_record_version,
    messages: messages,
    cipher: cipher
  )
  [record, orig_msgs, surplus_binary]
end

Instance Method Details

#serialize(record_size_limit = DEFAULT_RECORD_SIZE_LIMIT) ⇒ String

NOTE: serialize joins messages. If serialize is received Server Parameters(EE, CT, CV), it returns one binary.

Parameters:

  • record_size_limit (Integer) (defaults to: DEFAULT_RECORD_SIZE_LIMIT)

Returns:

  • (String)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/tttls1.3/message/record.rb', line 38

def serialize(record_size_limit = DEFAULT_RECORD_SIZE_LIMIT)
  tlsplaintext = @messages.map(&:serialize).join
  if @cipher.is_a?(Cryptograph::Aead)
    max = @cipher.tlsplaintext_length_limit(record_size_limit)
    fragments = tlsplaintext.scan(/.{1,#{max}}/m)
  else
    fragments = [tlsplaintext]
  end

  fragments.map do |s|
    @type + @legacy_record_version \
    + @cipher.encrypt(s, messages_type).prefix_uint16_length
  end.join
end