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: [], surplus_binary: '', cipher:) ⇒ Record

Returns a new instance of Record.

Parameters:



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/tttls1.3/message/record.rb', line 23

def initialize(type:,
               legacy_record_version: ProtocolVersion::TLS_1_2,
               messages: [],
               surplus_binary: '',
               cipher:)
  @type = type
  @legacy_record_version = legacy_record_version
  @messages = messages
  @surplus_binary = surplus_binary
  @cipher = cipher
end

Instance Attribute Details

#cipherObject (readonly)

Returns the value of attribute cipher.



16
17
18
# File 'lib/tttls1.3/message/record.rb', line 16

def cipher
  @cipher
end

#legacy_record_versionObject (readonly)

Returns the value of attribute legacy_record_version.



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

def legacy_record_version
  @legacy_record_version
end

#messagesObject (readonly)

Returns the value of attribute messages.



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

def messages
  @messages
end

#surplus_binaryObject (readonly)

Returns the value of attribute surplus_binary.



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

def surplus_binary
  @surplus_binary
end

#typeObject (readonly)

Returns the value of attribute type.



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

def type
  @type
end

Class Method Details

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

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

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

Parameters:

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

    surplus_binary

Returns:

Raises:



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
# File 'lib/tttls1.3/message/record.rb', line 75

def self.deserialize(binary, cipher, buffered = '')
  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
    fragment, inner_type = cipher.decrypt(fragment, binary.slice(0, 5))
  end
  messages, surplus_binary = deserialize_fragment(buffered + fragment,
                                                  inner_type || type)

  Record.new(type: type,
             legacy_record_version: legacy_record_version,
             messages: messages,
             surplus_binary: surplus_binary,
             cipher: cipher)
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)


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/tttls1.3/message/record.rb', line 43

def serialize(record_size_limit = DEFAULT_RECORD_SIZE_LIMIT)
  tlsplaintext = @messages.map(&:serialize).join + @surplus_binary
  if messages_type == ContentType::APPLICATION_DATA
    max = cipher.tlsplaintext_length_limit(record_size_limit)
    fragments = tlsplaintext.scan(/.{1,#{max}}/m)
  else
    fragments = [tlsplaintext]
  end
  fragments = [''] if fragments.empty?

  binary = ''
  fragments.each do |s|
    binary += @type + @legacy_record_version
    binary += @cipher.encrypt(s, messages_type).prefix_uint16_length
  end

  binary
end