Class: PWN::SDR::Decoder::Bluetooth::LinkLayer

Inherits:
Object
  • Object
show all
Defined in:
lib/pwn/sdr/decoder/bluetooth.rb

Overview

Connected header/CTE and selected control fields, after CRC verification.

Class Method Summary collapse

Class Method Details

.parse(opts = {}) ⇒ Object



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/pwn/sdr/decoder/bluetooth.rb', line 247

public_class_method def self.parse(opts = {})
  header = opts[:header]
  payload = opts[:payload]
  encrypted = opts[:encrypted]
  byte = header[0]
  if header.length == 3
    cte = header[2]
    return nil unless (2..20).cover?(cte & 31) && cte.nobits?(0x20) && cte >> 6 != 3
  end
  hex = payload.pack('C*').unpack1('H*').upcase
  fields = { pdu_type: byte.allbits?(3) ? 'LL_CONTROL' : 'LL_DATA',
             header_length: header.length, cte_info: header[2], llid: byte & 3,
             nesn: (byte >> 2) & 1, sn: (byte >> 3) & 1, md: (byte >> 4) & 1,
             encrypted: encrypted, payload_hex: encrypted ? nil : hex,
             ciphertext_hex: encrypted ? hex : nil }
  if !encrypted && byte.allbits?(3)
    return nil if payload.empty?

    fields[:control_opcode] = payload[0]
    if payload[0] == 1
      return nil unless payload.length == 8 && payload[5].nobits?(0xE0) && payload[1, 5].sum { |v| v.to_s(2).count('1') } >= 2

      fields[:channel_map_hex] = payload[1, 5].pack('C*').unpack1('H*').upcase
      fields[:instant] = payload[6] | (payload[7] << 8)
    end
  end
  fields
end