From bdc10744fb338ae197692713a0b48a7ccc36f566 Mon Sep 17 00:00:00 2001 From: JF Date: Sun, 26 Apr 2020 10:25:59 +0200 Subject: Add Nimble in libs directory --- .../mynewt-nimble/nimble/host/tools/log2smtest.rb | 1029 ++++++++++++++++++++ 1 file changed, 1029 insertions(+) create mode 100755 src/libs/mynewt-nimble/nimble/host/tools/log2smtest.rb (limited to 'src/libs/mynewt-nimble/nimble/host/tools') diff --git a/src/libs/mynewt-nimble/nimble/host/tools/log2smtest.rb b/src/libs/mynewt-nimble/nimble/host/tools/log2smtest.rb new file mode 100755 index 00000000..e253e69f --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/tools/log2smtest.rb @@ -0,0 +1,1029 @@ +#!/usr/bin/env ruby + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +### This script converts a bletiny log into a security manager unit test. The +### input log must contain the connection establishment and complete pairing +### procedure. +### +### Arguments: None +### Stdin: bletiny log file + +$PAIR_ALG_STRINGS = { + 0 => [ 'BLE_SM_PAIR_ALG_JW', 'just works', 'jw' ], + 1 => [ 'BLE_SM_PAIR_ALG_PASSKEY', 'passkey entry', 'pk' ], + 2 => [ 'BLE_SM_PAIR_ALG_OOB', 'out of band', 'ob' ], + 3 => [ 'BLE_SM_PAIR_ALG_NUMCMP', 'numeric comparison', 'nc' ] +} + +$ADDR_TYPE_STRINGS = { + 0 => 'BLE_ADDR_TYPE_PUBLIC', + 1 => 'BLE_ADDR_TYPE_RANDOM', + 2 => 'BLE_ADDR_TYPE_RPA_PUB_DEFAULT', + 3 => 'BLE_ADDR_TYPE_RPA_RND_DEFAULT', +} + +$ACTION_STRINGS = { + 0 => 'BLE_SM_IOACT_NONE', + 1 => 'BLE_SM_IOACT_OOB', + 2 => 'BLE_SM_IOACT_INPUT', + 3 => 'BLE_SM_IOACT_DISP', + 4 => 'BLE_SM_IOACT_NUMCMP', +} + +$prev_idx = 0 +$ctxt = {} + +def test_case_name + type_str = $ctxt[:sc] ? "sc" : "lgcy" + init_str = $ctxt[:we_are_init] ? "us" : "peer" + alg_str = $PAIR_ALG_STRINGS[$ctxt[:pair_alg]][2] + iio_cap_str = "iio#{$ctxt[:pair_req][:io_cap]}" + rio_cap_str = "rio#{$ctxt[:pair_rsp][:io_cap]}" + bonding_str = "b#{$ctxt[:bonding] ? 1 : 0}" + iat_str = "iat#{$ctxt[:addrs][:init_type]}" + rat_str = "rat#{$ctxt[:addrs][:resp_type]}" + ikey_str = "ik#{$ctxt[:pair_rsp][:init_key_dist]}" + rkey_str = "rk#{$ctxt[:pair_rsp][:resp_key_dist]}" + + "ble_sm_" + + "#{type_str}_#{init_str}_#{alg_str}_#{iio_cap_str}_#{rio_cap_str}_" + + "#{bonding_str}_#{iat_str}_#{rat_str}_#{ikey_str}_#{rkey_str}" +end + +def test_case_comment +<<-eos +/** + * #{$ctxt[:sc] ? 'Secure connections' : 'Legacy'} pairing + * Master: #{$ctxt[:we_are_init] ? "us" : "peer"} + * Pair algorithm: #{$PAIR_ALG_STRINGS[$ctxt[:pair_alg]][1]} + * Initiator IO capabilities: #{$ctxt[:pair_req][:io_cap]} + * Responder IO capabilities: #{$ctxt[:pair_rsp][:io_cap]} + * Bonding: #{$ctxt[:bonding]} + * Initiator address type: #{$ADDR_TYPE_STRINGS[$ctxt[:addrs][:init_type]]} + * Responder address type: #{$ADDR_TYPE_STRINGS[$ctxt[:addrs][:resp_type]]} + * Initiator key distribution: #{$ctxt[:pair_rsp][:init_key_dist]} + * Responder key distribution: #{$ctxt[:pair_rsp][:resp_key_dist]} + */ +eos +end + +def to_hex_s(byte) + if byte.is_a?(String) + byte = s_to_i(byte) + end + + "0x#{byte.to_s(16).rjust(2, '0')}" +end + +# to_i(0) but interpret leading zeros as decimal. +def s_to_i(s) + if s[0..1] == "0x" + return s.to_i(16) + else + return s.to_i(10) + end +end + +def invalid_byte_line(msg, line) + str = "invalid byte line" + if msg != nil + str += ": #{msg}" + end + + str += "; line=#{line}" + + raise str +end + +def token_string_to_bytes(line, delim = ' ') + tokens = line.split(delim) + bytes = [] + tokens.each do |token| + begin + byte = token.to_i(16) + bytes << byte + rescue + invalid_byte_line("token=#{token}", line) + end + end + + return bytes +end + +def txrx_prefix(is_tx) + if is_tx + return "tx" + else + return "rx" + end +end + +def reqrsp_s(is_req) + reqrsp = nil + if is_req + return "req" + else + return "rsp" + end +end + +def bytes_to_arr_body(bytes, indent) + lines = [] + + idx = 0 + while idx < bytes.size + slice_len = nil + if bytes.size - idx >= 8 + slice_len = 8 + else + slice_len = bytes.size - idx + end + + slice = bytes[idx...(idx + slice_len)] + line = ' ' * indent + + slice.map{|b| to_hex_s(b)}.join(", ") + "," + lines << line + + idx += slice_len + end + + return lines.join("\n") << "\n" +end + +def bytes_to_arr(bytes, name, indent) + str = "#{' ' * indent}.#{name} = {\n" + str << bytes_to_arr_body(bytes, indent + 4) + str << "#{' ' * indent}}," + + return str +end + +def addr_string_to_bytes(addr_string) + token_string_to_bytes(addr_string, ':').reverse +end + +def parse_pair_cmd(line, is_req) + suffix = reqrsp_s(is_req) + re = %r{ + pair\s#{suffix}; + \s + conn=\d+ + \s + io_cap=(?\d+) + \s + oob_data_flag=(?\d+) + \s + authreq=(?0x[0-9a-f]+) + \s + mac_enc_key_size=(?\d+) + \s + init_key_dist=(?\d+) + \s + resp_key_dist=(?\d+) + }x + + m = re.match(line) + if m == nil + return nil + end + + cmd = {} + cmd[:io_cap] = s_to_i(m[:io_cap]) + cmd[:oob_data_flag] = s_to_i(m[:oob_data_flag]) + cmd[:authreq] = s_to_i(m[:authreq]) + cmd[:max_enc_key_size] = s_to_i(m[:max_enc_key_size]) + cmd[:init_key_dist] = s_to_i(m[:init_key_dist]) + cmd[:resp_key_dist] = s_to_i(m[:resp_key_dist]) + + return cmd +end + +def parse_privkey(line) + if !(line =~ /our privkey=(.+)/) + return nil + end + return token_string_to_bytes($1) +end + +def parse_public_key(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: public key; conn=\d+ x=(.+) y=(.+)/) + return nil + end + + pubkey = {} + pubkey[:x] = token_string_to_bytes($1) + pubkey[:y] = token_string_to_bytes($2) + + if pubkey[:x].size != 32 + raise "invalid public key: x length incorrect; line=#{line}" + end + + if pubkey[:y].size != 32 + raise "invalid public key: y length incorrect; line=#{line}" + end + + return pubkey +end + +def parse_confirm(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: confirm; conn=\d+ value=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid confirm line (length mismatch): #{line}" + end + + return { :value => bytes } +end + +def parse_random(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: random; conn=\d+ value=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid random line (length mismatch): #{line}" + end + + return { :value => bytes } +end + +def parse_stk(line) + if !(line =~ /^ out=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid stk line (length mismatch): #{line}" + end + + return bytes +end + +def parse_dhkey_check(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: dhkey check; conn=\d+ value=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid dhkey_check line (length mismatch): #{line}" + end + + return { :value => bytes } +end + +def parse_ltk(line) + if !(line =~ /persisting.+ltk=([^ ]+)/) + return nil + end + + bytes = $1.split(":") + if bytes.size != 16 + raise "invalid ltk line (length mismatch): exp=16 got=#{bytes.size} " + + "line=#{line}" + end + + return bytes +end + +def parse_enc_info(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: enc info; conn=\d+ ltk=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid enc info line (length mismatch): #{line}" + end + + return { :ltk => bytes } +end + +def parse_master_id(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: master id; conn=\d+ ediv=(.+) rand=(.+)/) + return nil + end + + return { + :ediv => s_to_i($1), + :rand => s_to_i($2), + } +end + +def parse_id_info(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: id info; conn=\d+ irk=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid id info line (length mismatch): #{line}" + end + + return { :irk => bytes } +end + +def parse_id_addr_info(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: id addr info; conn=\d+ addr_type=(\d+) addr=(.+)/) + return nil + end + + bytes = addr_string_to_bytes($2) + if bytes.size != 6 + raise "invalid id addr info line (length mismatch): #{line}" + end + + return { + :addr_type => s_to_i($1), + :addr => bytes, + } +end + +def parse_sign_info(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: sign info; conn=\d+ sig_key=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid sign info line (length mismatch): #{line}" + end + + return { + :sig_key => bytes, + } +end + +def parse_passkey_info(line) + passkey_info = {} + + case line + when /passkey action event; action=4 numcmp=(\d+)/ + passkey_info[:action] = 4 + passkey_info[:numcmp] = $1.to_i(10) + when /^b passkey conn=\d+ action=1 oob=(\S+)/ + passkey_info[:action] = 1 + passkey_info[:oob] = token_string_to_bytes($1, ':') + when /^b passkey conn=\d+ action=2 key=(\d+)/ + passkey_info[:action] = 2 + passkey_info[:key] = $1.to_i(10) + when /b passkey conn=\d+ action=3 key=(\d+)/ + passkey_info[:action] = 3 + passkey_info[:key] = $1.to_i(10) + else + return nil + end + + return passkey_info +end + +def parse_addrs(line) + if !(line =~ /our_ota_addr_type=(\d+) our_ota_addr=(\S+) our_id_addr_type=(\d+) our_id_addr=(\S+) peer_ota_addr_type=(\d+) peer_ota_addr=(\S+) peer_id_addr_type=(\d+) peer_id_addr=(\S+)/) + return nil + end + + our_ota_addr_bytes = addr_string_to_bytes($2) + our_id_addr_bytes = addr_string_to_bytes($4) + peer_ota_addr_bytes = addr_string_to_bytes($6) + peer_id_addr_bytes = addr_string_to_bytes($8) + + if $ctxt[:we_are_init] + init_id_bytes = our_id_addr_bytes + init_ota_bytes = our_ota_addr_bytes + resp_id_bytes = peer_id_addr_bytes + resp_ota_bytes = peer_ota_addr_bytes + init_addr_type = s_to_i($1) + resp_addr_type = s_to_i($5) + else + init_id_bytes = peer_id_addr_bytes + init_ota_bytes = peer_ota_addr_bytes + resp_id_bytes = our_id_addr_bytes + resp_ota_bytes = our_ota_addr_bytes + init_addr_type = s_to_i($5) + resp_addr_type = s_to_i($1) + end + + if init_id_bytes == init_ota_bytes + init_ota_bytes = [0] * 6 + end + if resp_id_bytes == resp_ota_bytes + resp_ota_bytes = [0] * 6 + end + + return { + :init_type => init_addr_type, + :resp_type => resp_addr_type, + :init_id_addr => init_id_bytes, + :resp_id_addr => resp_id_bytes, + :init_rpa => init_ota_bytes, + :resp_rpa => resp_ota_bytes, + } +end + +def detect_initiator(lines) + lines.each do |line| + if line =~ /txed sm command: pair req/ + $ctxt[:we_are_init] = true + elsif line =~ /txed sm command: pair rsp/ + $ctxt[:we_are_init] = false + end + end + + if $ctxt[:we_are_init] == nil + raise "could not detect which peer is the initiator" + end +end + +def pair_cmd_to_s(cmd, is_req) + suffix = reqrsp_s(is_req) + return <<-eos + .pair_#{suffix} = { + .io_cap = #{to_hex_s(cmd[:io_cap])}, + .oob_data_flag = #{to_hex_s(cmd[:oob_data_flag])}, + .authreq = #{to_hex_s(cmd[:authreq])}, + .max_enc_key_size = #{to_hex_s(cmd[:max_enc_key_size])}, + .init_key_dist = #{to_hex_s(cmd[:init_key_dist])}, + .resp_key_dist = #{to_hex_s(cmd[:resp_key_dist])}, + }, + eos +end + +def privkey_to_s(privkey) + return bytes_to_arr(privkey, "our_priv_key", 8) +end + +def public_key_to_s(public_key, is_req) + suffix = reqrsp_s(is_req) + return <<-eos + .public_key_#{suffix} = { +#{bytes_to_arr(public_key[:x], "x", 12)} +#{bytes_to_arr(public_key[:y], "y", 12)} + }, + eos +end + +def confirm_to_s(confirm, is_req, idx) + return <<-eos + .confirm_#{reqrsp_s(is_req)}[#{idx}] = { +#{bytes_to_arr(confirm[:value], "value", 12)} + }, + eos +end + +def random_to_s(random, is_req, idx) + return <<-eos + .random_#{reqrsp_s(is_req)}[#{idx}] = { +#{bytes_to_arr(random[:value], "value", 12)} + }, + eos +end + +def ltk_to_s(ltk) + return bytes_to_arr(ltk, "ltk", 8) +end + +def stk_to_s(stk) + return bytes_to_arr(stk, "stk", 8) +end + +def enc_info_to_s(id_info, is_req) + return <<-eos + .enc_info_#{reqrsp_s(is_req)} = { +#{bytes_to_arr(id_info[:ltk], "ltk", 12)} + }, + eos +end + +def master_id_to_s(master_id, is_req) + return <<-eos + .master_id_#{reqrsp_s(is_req)} = { + .ediv = 0x#{master_id[:ediv].to_s(16)}, + .rand_val = 0x#{master_id[:rand].to_s(16)}, + }, + eos +end + +def id_info_to_s(id_info, is_req) + return <<-eos + .id_info_#{reqrsp_s(is_req)} = { +#{bytes_to_arr(id_info[:irk], "irk", 12)} + }, + eos +end + +def id_addr_info_to_s(id_addr_info, is_req) + return <<-eos + .id_addr_info_#{reqrsp_s(is_req)} = { + .addr_type = #{id_addr_info[:addr_type]}, +#{bytes_to_arr(id_addr_info[:addr], "bd_addr", 12)} + }, + eos +end + +def sign_info_to_s(sign_info, is_req) + return <<-eos + .sign_info_#{reqrsp_s(is_req)} = { +#{bytes_to_arr(sign_info[:sig_key], "sig_key", 12)} + }, + eos +end + +def passkey_info_fill(passkey_info) + case passkey_info[:action] + # None + when 0 + $ctxt[:pair_alg] = 0 + $ctxt[:authenticated] = false + + # OOB + when 1 + $ctxt[:pair_alg] = 2 + $ctxt[:authenticated] = true + + # Input + when 2 + $ctxt[:pair_alg] = 1 + $ctxt[:authenticated] = true + + # Display + when 3 + $ctxt[:pair_alg] = 1 + $ctxt[:authenticated] = true + + # Numeric comparison + when 4 + $ctxt[:pair_alg] = 3 + $ctxt[:authenticated] = true + + else + raise "invalid MITM action: #{passkey_info[:action]}" + end +end + +def passkey_info_s + passkey_info = $ctxt[:passkey_info] + action_str = $ACTION_STRINGS[passkey_info[:action]] + + result = <<-eos + .pair_alg = #{$ctxt[:pair_alg]}, + .authenticated = #{$ctxt[:authenticated]}, + .passkey_info = { + .passkey = { + .action = #{action_str}, + eos + + if passkey_info[:key] != nil + result << <<-eos + .passkey = #{passkey_info[:key].to_i}, + eos + end + if passkey_info[:oob] != nil + result << <<-eos +#{bytes_to_arr(passkey_info[:oob], "oob", 16)} + eos + end + if passkey_info[:numcmp] != nil + result << <<-eos + .numcmp_accept = 1, + eos + end + + result << <<-eos + }, + eos + + if passkey_info[:numcmp] != nil + result << <<-eos + .exp_numcmp = #{passkey_info[:numcmp].to_i}, + eos + end + + result << <<-eos + }, + eos +end + +def addrs_to_s(addrs) + s = '' + + init_type = addrs[:init_type] + resp_type = addrs[:resp_type] + + if init_type != 0 + s += " .init_addr_type = #{$ADDR_TYPE_STRINGS[init_type]},\n" + end + s += bytes_to_arr(addrs[:init_id_addr], "init_id_addr", 8) + "\n" + if init_type >= 2 + s += bytes_to_arr(addrs[:init_rpa], "init_rpa", 8) + "\n" + end + + if resp_type != 0 + s += " .resp_addr_type = #{$ADDR_TYPE_STRINGS[resp_type]},\n" + end + s += bytes_to_arr(addrs[:resp_id_addr], "resp_id_addr", 8) + "\n" + if resp_type >= 2 + s += bytes_to_arr(addrs[:resp_rpa], "resp_rpa", 8) + "\n" + end + + return s +end + +def dhkey_check_to_s(dhkey_check, is_req) + return <<-eos + .dhkey_check_#{reqrsp_s(is_req)} = { +#{bytes_to_arr(dhkey_check[:value], "value", 12)} + }, + eos +end + +def extract_one(lines, ignore_prev = false) + if ignore_prev + start = 0 + else + start = $prev_idx + end + + (start...lines.size).each do |idx| + line = lines[idx] + result = yield(line) + if result != nil + if !ignore_prev + $prev_idx = idx + end + return result + end + end + + return nil +end + +def extract_pair_req(lines) + return extract_one(lines) {|line| parse_pair_cmd(line, true)} +end + +def extract_pair_rsp(lines) + return extract_one(lines) {|line| parse_pair_cmd(line, false)} +end + +def extract_privkey(lines) + return extract_one(lines) {|line| parse_privkey(line)} +end + +def extract_public_key_req(lines) + return extract_one(lines) do |line| + parse_public_key(line, $ctxt[:we_are_init]) + end +end + +def extract_public_key_rsp(lines) + return extract_one(lines) do |line| + parse_public_key(line, !$ctxt[:we_are_init]) + end +end + +def extract_confirm_req(lines) + return extract_one(lines) do |line| + parse_confirm(line, $ctxt[:we_are_init]) + end +end + +def extract_confirm_rsp(lines) + return extract_one(lines) do |line| + parse_confirm(line, !$ctxt[:we_are_init]) + end +end + +def extract_random_req(lines) + return extract_one(lines) do |line| + parse_random(line, $ctxt[:we_are_init]) + end +end + +def extract_random_rsp(lines) + return extract_one(lines) do |line| + parse_random(line, !$ctxt[:we_are_init]) + end +end + +def extract_confirm_random(lines) + confirm_reqs = [] + confirm_rsps = [] + random_reqs = [] + random_rsps = [] + + idx = 0 + loop do + confirm_req = extract_confirm_req(lines) + if confirm_req != nil + confirm_reqs << confirm_req + end + + confirm_rsp = extract_confirm_rsp(lines) + break if confirm_rsp == nil + if idx >= 20 + raise "too many confirm rsps (>20)" + end + confirm_rsps << confirm_rsp + + random_req = extract_random_req(lines) + break if random_req == nil + random_reqs << random_req + + random_rsp = extract_random_rsp(lines) + break if random_rsp == nil + random_rsps << random_rsp + + idx += 1 + end + + return confirm_reqs, confirm_rsps, random_reqs, random_rsps +end + +def extract_stk(lines) + return extract_one(lines, true) do |line| + parse_stk(line) + end +end + +def extract_dhkey_check_req(lines) + return extract_one(lines) do |line| + parse_dhkey_check(line, $ctxt[:we_are_init]) + end +end + +def extract_dhkey_check_rsp(lines) + return extract_one(lines) do |line| + parse_dhkey_check(line, !$ctxt[:we_are_init]) + end +end + +def extract_enc_info_req(lines) + return extract_one(lines) do |line| + parse_enc_info(line, !$ctxt[:we_are_init]) + end +end + +def extract_enc_info_rsp(lines) + return extract_one(lines) do |line| + parse_enc_info(line, $ctxt[:we_are_init]) + end +end + +def extract_master_id_req(lines) + return extract_one(lines) do |line| + parse_master_id(line, !$ctxt[:we_are_init]) + end +end + +def extract_master_id_rsp(lines) + return extract_one(lines) do |line| + parse_master_id(line, $ctxt[:we_are_init]) + end +end + +def extract_id_info_req(lines) + return extract_one(lines) do |line| + parse_id_info(line, !$ctxt[:we_are_init]) + end +end + +def extract_id_info_rsp(lines) + return extract_one(lines) do |line| + parse_id_info(line, $ctxt[:we_are_init]) + end +end + +def extract_id_addr_info_req(lines) + return extract_one(lines) do |line| + parse_id_addr_info(line, !$ctxt[:we_are_init]) + end +end + +def extract_id_addr_info_rsp(lines) + return extract_one(lines) do |line| + parse_id_addr_info(line, $ctxt[:we_are_init]) + end +end + +def extract_sign_info_req(lines) + return extract_one(lines) do |line| + parse_sign_info(line, !$ctxt[:we_are_init]) + end +end + +def extract_sign_info_rsp(lines) + return extract_one(lines) do |line| + parse_sign_info(line, $ctxt[:we_are_init]) + end +end + +def extract_ltk(lines) + return extract_one(lines) do |line| + parse_ltk(line) + end +end + +def extract_passkey_info(lines) + passkey_info = extract_one(lines, true) do |line| + parse_passkey_info(line) + end + + if passkey_info == nil + passkey_info = { :action => 0 } + end + + return passkey_info +end + +def extract_addrs(lines) + return extract_one(lines) do |line| + parse_addrs(line) + end +end + + +lines = STDIN.readlines + +detect_initiator(lines) +$ctxt[:pair_req] = extract_pair_req(lines) +$ctxt[:pair_rsp] = extract_pair_rsp(lines) +$ctxt[:privkey] = extract_privkey(lines) +$ctxt[:public_key_req] = extract_public_key_req(lines) +$ctxt[:public_key_rsp] = extract_public_key_rsp(lines) +$ctxt[:confirm_reqs], $ctxt[:confirm_rsps], $ctxt[:random_reqs], $ctxt[:random_rsps] = extract_confirm_random(lines) +$ctxt[:passkey_info] = extract_passkey_info(lines) +$ctxt[:dhkey_check_req] = extract_dhkey_check_req(lines) +$ctxt[:dhkey_check_rsp] = extract_dhkey_check_rsp(lines) +$ctxt[:enc_info_req] = extract_enc_info_req(lines) +$ctxt[:master_id_req] = extract_master_id_req(lines) +$ctxt[:id_info_req] = extract_id_info_req(lines) +$ctxt[:id_addr_info_req] = extract_id_addr_info_req(lines) +$ctxt[:sign_info_req] = extract_sign_info_req(lines) +$ctxt[:enc_info_rsp] = extract_enc_info_rsp(lines) +$ctxt[:master_id_rsp] = extract_master_id_rsp(lines) +$ctxt[:id_info_rsp] = extract_id_info_rsp(lines) +$ctxt[:id_addr_info_rsp] = extract_id_addr_info_rsp(lines) +$ctxt[:sign_info_rsp] = extract_sign_info_rsp(lines) +$ctxt[:addrs] = extract_addrs(lines) +$ctxt[:ltk] = extract_ltk(lines) +$ctxt[:stk] = extract_stk(lines) + +expected_confirm_rsps = nil +expected_random_reqs = nil +expected_random_rsps = nil +if $ctxt[:confirm_reqs].size == 0 + expected_confirm_rsps = 1 + expected_random_reqs = 1 + expected_random_rsps = 1 +else + expected_confirm_rsps = $ctxt[:confirm_reqs].size + expected_random_reqs = $ctxt[:random_reqs].size + expected_random_rsps = $ctxt[:random_rsps].size +end + +if $ctxt[:confirm_rsps].size != expected_confirm_rsps + raise "wrong number of confirm responses " + + "(exp=#{expected_confirm_rsps}; got=#{$ctxt[:confirm_rsps].size}" +end + +if $ctxt[:random_reqs].size != expected_random_reqs + raise "wrong number of random requests " + + "(exp=#{expected_random_reqs}; got=#{$ctxt[:random_reqs].size}" +end + +if $ctxt[:random_rsps].size != expected_random_rsps + raise "wrong number of random responses " + + "(exp=#{expected_random_rsps}; got=#{$ctxt[:random_rsps].size}" +end + +passkey_info_fill($ctxt[:passkey_info]) + +$ctxt[:sc] = $ctxt[:public_key_req] != nil +$ctxt[:bonding] = $ctxt[:pair_req][:authreq] & 1 == 1 && + $ctxt[:pair_rsp][:authreq] & 1 == 1 + +puts test_case_comment() +puts <<-eos +TEST_CASE(#{test_case_name()}) +{ + struct ble_sm_test_params params; + + params = (struct ble_sm_test_params) { +eos + +puts addrs_to_s($ctxt[:addrs]) + +puts pair_cmd_to_s($ctxt[:pair_req], true) +puts pair_cmd_to_s($ctxt[:pair_rsp], false) + +if $ctxt[:sc] + puts privkey_to_s($ctxt[:privkey]) + puts public_key_to_s($ctxt[:public_key_req], true) + puts public_key_to_s($ctxt[:public_key_req], false) +end + +$ctxt[:confirm_rsps].size.times do |i| + confirm_req = $ctxt[:confirm_reqs][i] + confirm_rsp = $ctxt[:confirm_rsps][i] + random_req = $ctxt[:random_reqs][i] + random_rsp = $ctxt[:random_rsps][i] + + if confirm_req != nil + puts confirm_to_s(confirm_req, true, i) + end + + puts confirm_to_s(confirm_rsp, false, i) + puts random_to_s(random_req, true, i) + puts random_to_s(random_rsp, false, i) +end + +if $ctxt[:sc] + puts dhkey_check_to_s($ctxt[:dhkey_check_req], true) + puts dhkey_check_to_s($ctxt[:dhkey_check_rsp], false) +end + +if $ctxt[:enc_info_req] != nil + puts enc_info_to_s($ctxt[:enc_info_req], true) +end +if $ctxt[:master_id_req] != nil + puts master_id_to_s($ctxt[:master_id_req], true) +end +if $ctxt[:id_info_req] != nil + puts id_info_to_s($ctxt[:id_info_req], true) +end +if $ctxt[:id_addr_info_req] != nil + puts id_addr_info_to_s($ctxt[:id_addr_info_req], true) +end +if $ctxt[:sign_info_req] != nil + puts sign_info_to_s($ctxt[:sign_info_req], true) +end +if $ctxt[:enc_info_rsp] != nil + puts enc_info_to_s($ctxt[:enc_info_rsp], false) +end +if $ctxt[:master_id_rsp] != nil + puts master_id_to_s($ctxt[:master_id_rsp], false) +end +if $ctxt[:id_info_rsp] != nil + puts id_info_to_s($ctxt[:id_info_rsp], false) +end +if $ctxt[:id_addr_info_rsp] != nil + puts id_addr_info_to_s($ctxt[:id_addr_info_rsp], false) +end +if $ctxt[:sign_info_rsp] != nil + puts sign_info_to_s($ctxt[:sign_info_rsp], false) +end +if $ctxt[:sc] + puts ltk_to_s($ctxt[:ltk]) +else + puts stk_to_s($ctxt[:stk]) +end +puts passkey_info_s() + +puts ' };' + +if $ctxt[:sc] + if $ctxt[:we_are_init] + puts ' ble_sm_test_util_us_sc_good(¶ms);' + else + puts ' ble_sm_test_util_peer_sc_good(¶ms);' + end +else + if $ctxt[:we_are_init] + puts ' ble_sm_test_util_us_lgcy_good(¶ms);' + else + puts ' ble_sm_test_util_peer_lgcy_good(¶ms);' + end +end +puts '}' -- cgit v1.2.3