1*042d53a7SEvalZero#!/usr/bin/env ruby 2*042d53a7SEvalZero 3*042d53a7SEvalZero# 4*042d53a7SEvalZero# Licensed to the Apache Software Foundation (ASF) under one 5*042d53a7SEvalZero# or more contributor license agreements. See the NOTICE file 6*042d53a7SEvalZero# distributed with this work for additional information 7*042d53a7SEvalZero# regarding copyright ownership. The ASF licenses this file 8*042d53a7SEvalZero# to you under the Apache License, Version 2.0 (the 9*042d53a7SEvalZero# "License"); you may not use this file except in compliance 10*042d53a7SEvalZero# with the License. You may obtain a copy of the License at 11*042d53a7SEvalZero# 12*042d53a7SEvalZero# http://www.apache.org/licenses/LICENSE-2.0 13*042d53a7SEvalZero# 14*042d53a7SEvalZero# Unless required by applicable law or agreed to in writing, 15*042d53a7SEvalZero# software distributed under the License is distributed on an 16*042d53a7SEvalZero# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17*042d53a7SEvalZero# KIND, either express or implied. See the License for the 18*042d53a7SEvalZero# specific language governing permissions and limitations 19*042d53a7SEvalZero# under the License. 20*042d53a7SEvalZero# 21*042d53a7SEvalZero 22*042d53a7SEvalZero### This script converts a bletiny log into a security manager unit test. The 23*042d53a7SEvalZero### input log must contain the connection establishment and complete pairing 24*042d53a7SEvalZero### procedure. 25*042d53a7SEvalZero### 26*042d53a7SEvalZero### Arguments: None 27*042d53a7SEvalZero### Stdin: bletiny log file 28*042d53a7SEvalZero 29*042d53a7SEvalZero$PAIR_ALG_STRINGS = { 30*042d53a7SEvalZero 0 => [ 'BLE_SM_PAIR_ALG_JW', 'just works', 'jw' ], 31*042d53a7SEvalZero 1 => [ 'BLE_SM_PAIR_ALG_PASSKEY', 'passkey entry', 'pk' ], 32*042d53a7SEvalZero 2 => [ 'BLE_SM_PAIR_ALG_OOB', 'out of band', 'ob' ], 33*042d53a7SEvalZero 3 => [ 'BLE_SM_PAIR_ALG_NUMCMP', 'numeric comparison', 'nc' ] 34*042d53a7SEvalZero} 35*042d53a7SEvalZero 36*042d53a7SEvalZero$ADDR_TYPE_STRINGS = { 37*042d53a7SEvalZero 0 => 'BLE_ADDR_TYPE_PUBLIC', 38*042d53a7SEvalZero 1 => 'BLE_ADDR_TYPE_RANDOM', 39*042d53a7SEvalZero 2 => 'BLE_ADDR_TYPE_RPA_PUB_DEFAULT', 40*042d53a7SEvalZero 3 => 'BLE_ADDR_TYPE_RPA_RND_DEFAULT', 41*042d53a7SEvalZero} 42*042d53a7SEvalZero 43*042d53a7SEvalZero$ACTION_STRINGS = { 44*042d53a7SEvalZero 0 => 'BLE_SM_IOACT_NONE', 45*042d53a7SEvalZero 1 => 'BLE_SM_IOACT_OOB', 46*042d53a7SEvalZero 2 => 'BLE_SM_IOACT_INPUT', 47*042d53a7SEvalZero 3 => 'BLE_SM_IOACT_DISP', 48*042d53a7SEvalZero 4 => 'BLE_SM_IOACT_NUMCMP', 49*042d53a7SEvalZero} 50*042d53a7SEvalZero 51*042d53a7SEvalZero$prev_idx = 0 52*042d53a7SEvalZero$ctxt = {} 53*042d53a7SEvalZero 54*042d53a7SEvalZerodef test_case_name 55*042d53a7SEvalZero type_str = $ctxt[:sc] ? "sc" : "lgcy" 56*042d53a7SEvalZero init_str = $ctxt[:we_are_init] ? "us" : "peer" 57*042d53a7SEvalZero alg_str = $PAIR_ALG_STRINGS[$ctxt[:pair_alg]][2] 58*042d53a7SEvalZero iio_cap_str = "iio#{$ctxt[:pair_req][:io_cap]}" 59*042d53a7SEvalZero rio_cap_str = "rio#{$ctxt[:pair_rsp][:io_cap]}" 60*042d53a7SEvalZero bonding_str = "b#{$ctxt[:bonding] ? 1 : 0}" 61*042d53a7SEvalZero iat_str = "iat#{$ctxt[:addrs][:init_type]}" 62*042d53a7SEvalZero rat_str = "rat#{$ctxt[:addrs][:resp_type]}" 63*042d53a7SEvalZero ikey_str = "ik#{$ctxt[:pair_rsp][:init_key_dist]}" 64*042d53a7SEvalZero rkey_str = "rk#{$ctxt[:pair_rsp][:resp_key_dist]}" 65*042d53a7SEvalZero 66*042d53a7SEvalZero "ble_sm_" + 67*042d53a7SEvalZero "#{type_str}_#{init_str}_#{alg_str}_#{iio_cap_str}_#{rio_cap_str}_" + 68*042d53a7SEvalZero "#{bonding_str}_#{iat_str}_#{rat_str}_#{ikey_str}_#{rkey_str}" 69*042d53a7SEvalZeroend 70*042d53a7SEvalZero 71*042d53a7SEvalZerodef test_case_comment 72*042d53a7SEvalZero<<-eos 73*042d53a7SEvalZero/** 74*042d53a7SEvalZero * #{$ctxt[:sc] ? 'Secure connections' : 'Legacy'} pairing 75*042d53a7SEvalZero * Master: #{$ctxt[:we_are_init] ? "us" : "peer"} 76*042d53a7SEvalZero * Pair algorithm: #{$PAIR_ALG_STRINGS[$ctxt[:pair_alg]][1]} 77*042d53a7SEvalZero * Initiator IO capabilities: #{$ctxt[:pair_req][:io_cap]} 78*042d53a7SEvalZero * Responder IO capabilities: #{$ctxt[:pair_rsp][:io_cap]} 79*042d53a7SEvalZero * Bonding: #{$ctxt[:bonding]} 80*042d53a7SEvalZero * Initiator address type: #{$ADDR_TYPE_STRINGS[$ctxt[:addrs][:init_type]]} 81*042d53a7SEvalZero * Responder address type: #{$ADDR_TYPE_STRINGS[$ctxt[:addrs][:resp_type]]} 82*042d53a7SEvalZero * Initiator key distribution: #{$ctxt[:pair_rsp][:init_key_dist]} 83*042d53a7SEvalZero * Responder key distribution: #{$ctxt[:pair_rsp][:resp_key_dist]} 84*042d53a7SEvalZero */ 85*042d53a7SEvalZeroeos 86*042d53a7SEvalZeroend 87*042d53a7SEvalZero 88*042d53a7SEvalZerodef to_hex_s(byte) 89*042d53a7SEvalZero if byte.is_a?(String) 90*042d53a7SEvalZero byte = s_to_i(byte) 91*042d53a7SEvalZero end 92*042d53a7SEvalZero 93*042d53a7SEvalZero "0x#{byte.to_s(16).rjust(2, '0')}" 94*042d53a7SEvalZeroend 95*042d53a7SEvalZero 96*042d53a7SEvalZero# to_i(0) but interpret leading zeros as decimal. 97*042d53a7SEvalZerodef s_to_i(s) 98*042d53a7SEvalZero if s[0..1] == "0x" 99*042d53a7SEvalZero return s.to_i(16) 100*042d53a7SEvalZero else 101*042d53a7SEvalZero return s.to_i(10) 102*042d53a7SEvalZero end 103*042d53a7SEvalZeroend 104*042d53a7SEvalZero 105*042d53a7SEvalZerodef invalid_byte_line(msg, line) 106*042d53a7SEvalZero str = "invalid byte line" 107*042d53a7SEvalZero if msg != nil 108*042d53a7SEvalZero str += ": #{msg}" 109*042d53a7SEvalZero end 110*042d53a7SEvalZero 111*042d53a7SEvalZero str += "; line=#{line}" 112*042d53a7SEvalZero 113*042d53a7SEvalZero raise str 114*042d53a7SEvalZeroend 115*042d53a7SEvalZero 116*042d53a7SEvalZerodef token_string_to_bytes(line, delim = ' ') 117*042d53a7SEvalZero tokens = line.split(delim) 118*042d53a7SEvalZero bytes = [] 119*042d53a7SEvalZero tokens.each do |token| 120*042d53a7SEvalZero begin 121*042d53a7SEvalZero byte = token.to_i(16) 122*042d53a7SEvalZero bytes << byte 123*042d53a7SEvalZero rescue 124*042d53a7SEvalZero invalid_byte_line("token=#{token}", line) 125*042d53a7SEvalZero end 126*042d53a7SEvalZero end 127*042d53a7SEvalZero 128*042d53a7SEvalZero return bytes 129*042d53a7SEvalZeroend 130*042d53a7SEvalZero 131*042d53a7SEvalZerodef txrx_prefix(is_tx) 132*042d53a7SEvalZero if is_tx 133*042d53a7SEvalZero return "tx" 134*042d53a7SEvalZero else 135*042d53a7SEvalZero return "rx" 136*042d53a7SEvalZero end 137*042d53a7SEvalZeroend 138*042d53a7SEvalZero 139*042d53a7SEvalZerodef reqrsp_s(is_req) 140*042d53a7SEvalZero reqrsp = nil 141*042d53a7SEvalZero if is_req 142*042d53a7SEvalZero return "req" 143*042d53a7SEvalZero else 144*042d53a7SEvalZero return "rsp" 145*042d53a7SEvalZero end 146*042d53a7SEvalZeroend 147*042d53a7SEvalZero 148*042d53a7SEvalZerodef bytes_to_arr_body(bytes, indent) 149*042d53a7SEvalZero lines = [] 150*042d53a7SEvalZero 151*042d53a7SEvalZero idx = 0 152*042d53a7SEvalZero while idx < bytes.size 153*042d53a7SEvalZero slice_len = nil 154*042d53a7SEvalZero if bytes.size - idx >= 8 155*042d53a7SEvalZero slice_len = 8 156*042d53a7SEvalZero else 157*042d53a7SEvalZero slice_len = bytes.size - idx 158*042d53a7SEvalZero end 159*042d53a7SEvalZero 160*042d53a7SEvalZero slice = bytes[idx...(idx + slice_len)] 161*042d53a7SEvalZero line = ' ' * indent + 162*042d53a7SEvalZero slice.map{|b| to_hex_s(b)}.join(", ") + "," 163*042d53a7SEvalZero lines << line 164*042d53a7SEvalZero 165*042d53a7SEvalZero idx += slice_len 166*042d53a7SEvalZero end 167*042d53a7SEvalZero 168*042d53a7SEvalZero return lines.join("\n") << "\n" 169*042d53a7SEvalZeroend 170*042d53a7SEvalZero 171*042d53a7SEvalZerodef bytes_to_arr(bytes, name, indent) 172*042d53a7SEvalZero str = "#{' ' * indent}.#{name} = {\n" 173*042d53a7SEvalZero str << bytes_to_arr_body(bytes, indent + 4) 174*042d53a7SEvalZero str << "#{' ' * indent}}," 175*042d53a7SEvalZero 176*042d53a7SEvalZero return str 177*042d53a7SEvalZeroend 178*042d53a7SEvalZero 179*042d53a7SEvalZerodef addr_string_to_bytes(addr_string) 180*042d53a7SEvalZero token_string_to_bytes(addr_string, ':').reverse 181*042d53a7SEvalZeroend 182*042d53a7SEvalZero 183*042d53a7SEvalZerodef parse_pair_cmd(line, is_req) 184*042d53a7SEvalZero suffix = reqrsp_s(is_req) 185*042d53a7SEvalZero re = %r{ 186*042d53a7SEvalZero pair\s#{suffix}; 187*042d53a7SEvalZero \s 188*042d53a7SEvalZero conn=\d+ 189*042d53a7SEvalZero \s 190*042d53a7SEvalZero io_cap=(?<io_cap>\d+) 191*042d53a7SEvalZero \s 192*042d53a7SEvalZero oob_data_flag=(?<oob_data_flag>\d+) 193*042d53a7SEvalZero \s 194*042d53a7SEvalZero authreq=(?<authreq>0x[0-9a-f]+) 195*042d53a7SEvalZero \s 196*042d53a7SEvalZero mac_enc_key_size=(?<max_enc_key_size>\d+) 197*042d53a7SEvalZero \s 198*042d53a7SEvalZero init_key_dist=(?<init_key_dist>\d+) 199*042d53a7SEvalZero \s 200*042d53a7SEvalZero resp_key_dist=(?<resp_key_dist>\d+) 201*042d53a7SEvalZero }x 202*042d53a7SEvalZero 203*042d53a7SEvalZero m = re.match(line) 204*042d53a7SEvalZero if m == nil 205*042d53a7SEvalZero return nil 206*042d53a7SEvalZero end 207*042d53a7SEvalZero 208*042d53a7SEvalZero cmd = {} 209*042d53a7SEvalZero cmd[:io_cap] = s_to_i(m[:io_cap]) 210*042d53a7SEvalZero cmd[:oob_data_flag] = s_to_i(m[:oob_data_flag]) 211*042d53a7SEvalZero cmd[:authreq] = s_to_i(m[:authreq]) 212*042d53a7SEvalZero cmd[:max_enc_key_size] = s_to_i(m[:max_enc_key_size]) 213*042d53a7SEvalZero cmd[:init_key_dist] = s_to_i(m[:init_key_dist]) 214*042d53a7SEvalZero cmd[:resp_key_dist] = s_to_i(m[:resp_key_dist]) 215*042d53a7SEvalZero 216*042d53a7SEvalZero return cmd 217*042d53a7SEvalZeroend 218*042d53a7SEvalZero 219*042d53a7SEvalZerodef parse_privkey(line) 220*042d53a7SEvalZero if !(line =~ /our privkey=(.+)/) 221*042d53a7SEvalZero return nil 222*042d53a7SEvalZero end 223*042d53a7SEvalZero return token_string_to_bytes($1) 224*042d53a7SEvalZeroend 225*042d53a7SEvalZero 226*042d53a7SEvalZerodef parse_public_key(line, is_tx) 227*042d53a7SEvalZero prefix = txrx_prefix(is_tx) 228*042d53a7SEvalZero if !(line =~ /#{prefix}ed sm command: public key; conn=\d+ x=(.+) y=(.+)/) 229*042d53a7SEvalZero return nil 230*042d53a7SEvalZero end 231*042d53a7SEvalZero 232*042d53a7SEvalZero pubkey = {} 233*042d53a7SEvalZero pubkey[:x] = token_string_to_bytes($1) 234*042d53a7SEvalZero pubkey[:y] = token_string_to_bytes($2) 235*042d53a7SEvalZero 236*042d53a7SEvalZero if pubkey[:x].size != 32 237*042d53a7SEvalZero raise "invalid public key: x length incorrect; line=#{line}" 238*042d53a7SEvalZero end 239*042d53a7SEvalZero 240*042d53a7SEvalZero if pubkey[:y].size != 32 241*042d53a7SEvalZero raise "invalid public key: y length incorrect; line=#{line}" 242*042d53a7SEvalZero end 243*042d53a7SEvalZero 244*042d53a7SEvalZero return pubkey 245*042d53a7SEvalZeroend 246*042d53a7SEvalZero 247*042d53a7SEvalZerodef parse_confirm(line, is_tx) 248*042d53a7SEvalZero prefix = txrx_prefix(is_tx) 249*042d53a7SEvalZero if !(line =~ /#{prefix}ed sm command: confirm; conn=\d+ value=(.+)/) 250*042d53a7SEvalZero return nil 251*042d53a7SEvalZero end 252*042d53a7SEvalZero 253*042d53a7SEvalZero bytes = token_string_to_bytes($1) 254*042d53a7SEvalZero if bytes.size != 16 255*042d53a7SEvalZero raise "invalid confirm line (length mismatch): #{line}" 256*042d53a7SEvalZero end 257*042d53a7SEvalZero 258*042d53a7SEvalZero return { :value => bytes } 259*042d53a7SEvalZeroend 260*042d53a7SEvalZero 261*042d53a7SEvalZerodef parse_random(line, is_tx) 262*042d53a7SEvalZero prefix = txrx_prefix(is_tx) 263*042d53a7SEvalZero if !(line =~ /#{prefix}ed sm command: random; conn=\d+ value=(.+)/) 264*042d53a7SEvalZero return nil 265*042d53a7SEvalZero end 266*042d53a7SEvalZero 267*042d53a7SEvalZero bytes = token_string_to_bytes($1) 268*042d53a7SEvalZero if bytes.size != 16 269*042d53a7SEvalZero raise "invalid random line (length mismatch): #{line}" 270*042d53a7SEvalZero end 271*042d53a7SEvalZero 272*042d53a7SEvalZero return { :value => bytes } 273*042d53a7SEvalZeroend 274*042d53a7SEvalZero 275*042d53a7SEvalZerodef parse_stk(line) 276*042d53a7SEvalZero if !(line =~ /^ out=(.+)/) 277*042d53a7SEvalZero return nil 278*042d53a7SEvalZero end 279*042d53a7SEvalZero 280*042d53a7SEvalZero bytes = token_string_to_bytes($1) 281*042d53a7SEvalZero if bytes.size != 16 282*042d53a7SEvalZero raise "invalid stk line (length mismatch): #{line}" 283*042d53a7SEvalZero end 284*042d53a7SEvalZero 285*042d53a7SEvalZero return bytes 286*042d53a7SEvalZeroend 287*042d53a7SEvalZero 288*042d53a7SEvalZerodef parse_dhkey_check(line, is_tx) 289*042d53a7SEvalZero prefix = txrx_prefix(is_tx) 290*042d53a7SEvalZero if !(line =~ /#{prefix}ed sm command: dhkey check; conn=\d+ value=(.+)/) 291*042d53a7SEvalZero return nil 292*042d53a7SEvalZero end 293*042d53a7SEvalZero 294*042d53a7SEvalZero bytes = token_string_to_bytes($1) 295*042d53a7SEvalZero if bytes.size != 16 296*042d53a7SEvalZero raise "invalid dhkey_check line (length mismatch): #{line}" 297*042d53a7SEvalZero end 298*042d53a7SEvalZero 299*042d53a7SEvalZero return { :value => bytes } 300*042d53a7SEvalZeroend 301*042d53a7SEvalZero 302*042d53a7SEvalZerodef parse_ltk(line) 303*042d53a7SEvalZero if !(line =~ /persisting.+ltk=([^ ]+)/) 304*042d53a7SEvalZero return nil 305*042d53a7SEvalZero end 306*042d53a7SEvalZero 307*042d53a7SEvalZero bytes = $1.split(":") 308*042d53a7SEvalZero if bytes.size != 16 309*042d53a7SEvalZero raise "invalid ltk line (length mismatch): exp=16 got=#{bytes.size} " + 310*042d53a7SEvalZero "line=#{line}" 311*042d53a7SEvalZero end 312*042d53a7SEvalZero 313*042d53a7SEvalZero return bytes 314*042d53a7SEvalZeroend 315*042d53a7SEvalZero 316*042d53a7SEvalZerodef parse_enc_info(line, is_tx) 317*042d53a7SEvalZero prefix = txrx_prefix(is_tx) 318*042d53a7SEvalZero if !(line =~ /#{prefix}ed sm command: enc info; conn=\d+ ltk=(.+)/) 319*042d53a7SEvalZero return nil 320*042d53a7SEvalZero end 321*042d53a7SEvalZero 322*042d53a7SEvalZero bytes = token_string_to_bytes($1) 323*042d53a7SEvalZero if bytes.size != 16 324*042d53a7SEvalZero raise "invalid enc info line (length mismatch): #{line}" 325*042d53a7SEvalZero end 326*042d53a7SEvalZero 327*042d53a7SEvalZero return { :ltk => bytes } 328*042d53a7SEvalZeroend 329*042d53a7SEvalZero 330*042d53a7SEvalZerodef parse_master_id(line, is_tx) 331*042d53a7SEvalZero prefix = txrx_prefix(is_tx) 332*042d53a7SEvalZero if !(line =~ /#{prefix}ed sm command: master id; conn=\d+ ediv=(.+) rand=(.+)/) 333*042d53a7SEvalZero return nil 334*042d53a7SEvalZero end 335*042d53a7SEvalZero 336*042d53a7SEvalZero return { 337*042d53a7SEvalZero :ediv => s_to_i($1), 338*042d53a7SEvalZero :rand => s_to_i($2), 339*042d53a7SEvalZero } 340*042d53a7SEvalZeroend 341*042d53a7SEvalZero 342*042d53a7SEvalZerodef parse_id_info(line, is_tx) 343*042d53a7SEvalZero prefix = txrx_prefix(is_tx) 344*042d53a7SEvalZero if !(line =~ /#{prefix}ed sm command: id info; conn=\d+ irk=(.+)/) 345*042d53a7SEvalZero return nil 346*042d53a7SEvalZero end 347*042d53a7SEvalZero 348*042d53a7SEvalZero bytes = token_string_to_bytes($1) 349*042d53a7SEvalZero if bytes.size != 16 350*042d53a7SEvalZero raise "invalid id info line (length mismatch): #{line}" 351*042d53a7SEvalZero end 352*042d53a7SEvalZero 353*042d53a7SEvalZero return { :irk => bytes } 354*042d53a7SEvalZeroend 355*042d53a7SEvalZero 356*042d53a7SEvalZerodef parse_id_addr_info(line, is_tx) 357*042d53a7SEvalZero prefix = txrx_prefix(is_tx) 358*042d53a7SEvalZero if !(line =~ /#{prefix}ed sm command: id addr info; conn=\d+ addr_type=(\d+) addr=(.+)/) 359*042d53a7SEvalZero return nil 360*042d53a7SEvalZero end 361*042d53a7SEvalZero 362*042d53a7SEvalZero bytes = addr_string_to_bytes($2) 363*042d53a7SEvalZero if bytes.size != 6 364*042d53a7SEvalZero raise "invalid id addr info line (length mismatch): #{line}" 365*042d53a7SEvalZero end 366*042d53a7SEvalZero 367*042d53a7SEvalZero return { 368*042d53a7SEvalZero :addr_type => s_to_i($1), 369*042d53a7SEvalZero :addr => bytes, 370*042d53a7SEvalZero } 371*042d53a7SEvalZeroend 372*042d53a7SEvalZero 373*042d53a7SEvalZerodef parse_sign_info(line, is_tx) 374*042d53a7SEvalZero prefix = txrx_prefix(is_tx) 375*042d53a7SEvalZero if !(line =~ /#{prefix}ed sm command: sign info; conn=\d+ sig_key=(.+)/) 376*042d53a7SEvalZero return nil 377*042d53a7SEvalZero end 378*042d53a7SEvalZero 379*042d53a7SEvalZero bytes = token_string_to_bytes($1) 380*042d53a7SEvalZero if bytes.size != 16 381*042d53a7SEvalZero raise "invalid sign info line (length mismatch): #{line}" 382*042d53a7SEvalZero end 383*042d53a7SEvalZero 384*042d53a7SEvalZero return { 385*042d53a7SEvalZero :sig_key => bytes, 386*042d53a7SEvalZero } 387*042d53a7SEvalZeroend 388*042d53a7SEvalZero 389*042d53a7SEvalZerodef parse_passkey_info(line) 390*042d53a7SEvalZero passkey_info = {} 391*042d53a7SEvalZero 392*042d53a7SEvalZero case line 393*042d53a7SEvalZero when /passkey action event; action=4 numcmp=(\d+)/ 394*042d53a7SEvalZero passkey_info[:action] = 4 395*042d53a7SEvalZero passkey_info[:numcmp] = $1.to_i(10) 396*042d53a7SEvalZero when /^b passkey conn=\d+ action=1 oob=(\S+)/ 397*042d53a7SEvalZero passkey_info[:action] = 1 398*042d53a7SEvalZero passkey_info[:oob] = token_string_to_bytes($1, ':') 399*042d53a7SEvalZero when /^b passkey conn=\d+ action=2 key=(\d+)/ 400*042d53a7SEvalZero passkey_info[:action] = 2 401*042d53a7SEvalZero passkey_info[:key] = $1.to_i(10) 402*042d53a7SEvalZero when /b passkey conn=\d+ action=3 key=(\d+)/ 403*042d53a7SEvalZero passkey_info[:action] = 3 404*042d53a7SEvalZero passkey_info[:key] = $1.to_i(10) 405*042d53a7SEvalZero else 406*042d53a7SEvalZero return nil 407*042d53a7SEvalZero end 408*042d53a7SEvalZero 409*042d53a7SEvalZero return passkey_info 410*042d53a7SEvalZeroend 411*042d53a7SEvalZero 412*042d53a7SEvalZerodef parse_addrs(line) 413*042d53a7SEvalZero 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+)/) 414*042d53a7SEvalZero return nil 415*042d53a7SEvalZero end 416*042d53a7SEvalZero 417*042d53a7SEvalZero our_ota_addr_bytes = addr_string_to_bytes($2) 418*042d53a7SEvalZero our_id_addr_bytes = addr_string_to_bytes($4) 419*042d53a7SEvalZero peer_ota_addr_bytes = addr_string_to_bytes($6) 420*042d53a7SEvalZero peer_id_addr_bytes = addr_string_to_bytes($8) 421*042d53a7SEvalZero 422*042d53a7SEvalZero if $ctxt[:we_are_init] 423*042d53a7SEvalZero init_id_bytes = our_id_addr_bytes 424*042d53a7SEvalZero init_ota_bytes = our_ota_addr_bytes 425*042d53a7SEvalZero resp_id_bytes = peer_id_addr_bytes 426*042d53a7SEvalZero resp_ota_bytes = peer_ota_addr_bytes 427*042d53a7SEvalZero init_addr_type = s_to_i($1) 428*042d53a7SEvalZero resp_addr_type = s_to_i($5) 429*042d53a7SEvalZero else 430*042d53a7SEvalZero init_id_bytes = peer_id_addr_bytes 431*042d53a7SEvalZero init_ota_bytes = peer_ota_addr_bytes 432*042d53a7SEvalZero resp_id_bytes = our_id_addr_bytes 433*042d53a7SEvalZero resp_ota_bytes = our_ota_addr_bytes 434*042d53a7SEvalZero init_addr_type = s_to_i($5) 435*042d53a7SEvalZero resp_addr_type = s_to_i($1) 436*042d53a7SEvalZero end 437*042d53a7SEvalZero 438*042d53a7SEvalZero if init_id_bytes == init_ota_bytes 439*042d53a7SEvalZero init_ota_bytes = [0] * 6 440*042d53a7SEvalZero end 441*042d53a7SEvalZero if resp_id_bytes == resp_ota_bytes 442*042d53a7SEvalZero resp_ota_bytes = [0] * 6 443*042d53a7SEvalZero end 444*042d53a7SEvalZero 445*042d53a7SEvalZero return { 446*042d53a7SEvalZero :init_type => init_addr_type, 447*042d53a7SEvalZero :resp_type => resp_addr_type, 448*042d53a7SEvalZero :init_id_addr => init_id_bytes, 449*042d53a7SEvalZero :resp_id_addr => resp_id_bytes, 450*042d53a7SEvalZero :init_rpa => init_ota_bytes, 451*042d53a7SEvalZero :resp_rpa => resp_ota_bytes, 452*042d53a7SEvalZero } 453*042d53a7SEvalZeroend 454*042d53a7SEvalZero 455*042d53a7SEvalZerodef detect_initiator(lines) 456*042d53a7SEvalZero lines.each do |line| 457*042d53a7SEvalZero if line =~ /txed sm command: pair req/ 458*042d53a7SEvalZero $ctxt[:we_are_init] = true 459*042d53a7SEvalZero elsif line =~ /txed sm command: pair rsp/ 460*042d53a7SEvalZero $ctxt[:we_are_init] = false 461*042d53a7SEvalZero end 462*042d53a7SEvalZero end 463*042d53a7SEvalZero 464*042d53a7SEvalZero if $ctxt[:we_are_init] == nil 465*042d53a7SEvalZero raise "could not detect which peer is the initiator" 466*042d53a7SEvalZero end 467*042d53a7SEvalZeroend 468*042d53a7SEvalZero 469*042d53a7SEvalZerodef pair_cmd_to_s(cmd, is_req) 470*042d53a7SEvalZero suffix = reqrsp_s(is_req) 471*042d53a7SEvalZero return <<-eos 472*042d53a7SEvalZero .pair_#{suffix} = { 473*042d53a7SEvalZero .io_cap = #{to_hex_s(cmd[:io_cap])}, 474*042d53a7SEvalZero .oob_data_flag = #{to_hex_s(cmd[:oob_data_flag])}, 475*042d53a7SEvalZero .authreq = #{to_hex_s(cmd[:authreq])}, 476*042d53a7SEvalZero .max_enc_key_size = #{to_hex_s(cmd[:max_enc_key_size])}, 477*042d53a7SEvalZero .init_key_dist = #{to_hex_s(cmd[:init_key_dist])}, 478*042d53a7SEvalZero .resp_key_dist = #{to_hex_s(cmd[:resp_key_dist])}, 479*042d53a7SEvalZero }, 480*042d53a7SEvalZero eos 481*042d53a7SEvalZeroend 482*042d53a7SEvalZero 483*042d53a7SEvalZerodef privkey_to_s(privkey) 484*042d53a7SEvalZero return bytes_to_arr(privkey, "our_priv_key", 8) 485*042d53a7SEvalZeroend 486*042d53a7SEvalZero 487*042d53a7SEvalZerodef public_key_to_s(public_key, is_req) 488*042d53a7SEvalZero suffix = reqrsp_s(is_req) 489*042d53a7SEvalZero return <<-eos 490*042d53a7SEvalZero .public_key_#{suffix} = { 491*042d53a7SEvalZero#{bytes_to_arr(public_key[:x], "x", 12)} 492*042d53a7SEvalZero#{bytes_to_arr(public_key[:y], "y", 12)} 493*042d53a7SEvalZero }, 494*042d53a7SEvalZero eos 495*042d53a7SEvalZeroend 496*042d53a7SEvalZero 497*042d53a7SEvalZerodef confirm_to_s(confirm, is_req, idx) 498*042d53a7SEvalZero return <<-eos 499*042d53a7SEvalZero .confirm_#{reqrsp_s(is_req)}[#{idx}] = { 500*042d53a7SEvalZero#{bytes_to_arr(confirm[:value], "value", 12)} 501*042d53a7SEvalZero }, 502*042d53a7SEvalZero eos 503*042d53a7SEvalZeroend 504*042d53a7SEvalZero 505*042d53a7SEvalZerodef random_to_s(random, is_req, idx) 506*042d53a7SEvalZero return <<-eos 507*042d53a7SEvalZero .random_#{reqrsp_s(is_req)}[#{idx}] = { 508*042d53a7SEvalZero#{bytes_to_arr(random[:value], "value", 12)} 509*042d53a7SEvalZero }, 510*042d53a7SEvalZero eos 511*042d53a7SEvalZeroend 512*042d53a7SEvalZero 513*042d53a7SEvalZerodef ltk_to_s(ltk) 514*042d53a7SEvalZero return bytes_to_arr(ltk, "ltk", 8) 515*042d53a7SEvalZeroend 516*042d53a7SEvalZero 517*042d53a7SEvalZerodef stk_to_s(stk) 518*042d53a7SEvalZero return bytes_to_arr(stk, "stk", 8) 519*042d53a7SEvalZeroend 520*042d53a7SEvalZero 521*042d53a7SEvalZerodef enc_info_to_s(id_info, is_req) 522*042d53a7SEvalZero return <<-eos 523*042d53a7SEvalZero .enc_info_#{reqrsp_s(is_req)} = { 524*042d53a7SEvalZero#{bytes_to_arr(id_info[:ltk], "ltk", 12)} 525*042d53a7SEvalZero }, 526*042d53a7SEvalZero eos 527*042d53a7SEvalZeroend 528*042d53a7SEvalZero 529*042d53a7SEvalZerodef master_id_to_s(master_id, is_req) 530*042d53a7SEvalZero return <<-eos 531*042d53a7SEvalZero .master_id_#{reqrsp_s(is_req)} = { 532*042d53a7SEvalZero .ediv = 0x#{master_id[:ediv].to_s(16)}, 533*042d53a7SEvalZero .rand_val = 0x#{master_id[:rand].to_s(16)}, 534*042d53a7SEvalZero }, 535*042d53a7SEvalZero eos 536*042d53a7SEvalZeroend 537*042d53a7SEvalZero 538*042d53a7SEvalZerodef id_info_to_s(id_info, is_req) 539*042d53a7SEvalZero return <<-eos 540*042d53a7SEvalZero .id_info_#{reqrsp_s(is_req)} = { 541*042d53a7SEvalZero#{bytes_to_arr(id_info[:irk], "irk", 12)} 542*042d53a7SEvalZero }, 543*042d53a7SEvalZero eos 544*042d53a7SEvalZeroend 545*042d53a7SEvalZero 546*042d53a7SEvalZerodef id_addr_info_to_s(id_addr_info, is_req) 547*042d53a7SEvalZero return <<-eos 548*042d53a7SEvalZero .id_addr_info_#{reqrsp_s(is_req)} = { 549*042d53a7SEvalZero .addr_type = #{id_addr_info[:addr_type]}, 550*042d53a7SEvalZero#{bytes_to_arr(id_addr_info[:addr], "bd_addr", 12)} 551*042d53a7SEvalZero }, 552*042d53a7SEvalZero eos 553*042d53a7SEvalZeroend 554*042d53a7SEvalZero 555*042d53a7SEvalZerodef sign_info_to_s(sign_info, is_req) 556*042d53a7SEvalZero return <<-eos 557*042d53a7SEvalZero .sign_info_#{reqrsp_s(is_req)} = { 558*042d53a7SEvalZero#{bytes_to_arr(sign_info[:sig_key], "sig_key", 12)} 559*042d53a7SEvalZero }, 560*042d53a7SEvalZero eos 561*042d53a7SEvalZeroend 562*042d53a7SEvalZero 563*042d53a7SEvalZerodef passkey_info_fill(passkey_info) 564*042d53a7SEvalZero case passkey_info[:action] 565*042d53a7SEvalZero # None 566*042d53a7SEvalZero when 0 567*042d53a7SEvalZero $ctxt[:pair_alg] = 0 568*042d53a7SEvalZero $ctxt[:authenticated] = false 569*042d53a7SEvalZero 570*042d53a7SEvalZero # OOB 571*042d53a7SEvalZero when 1 572*042d53a7SEvalZero $ctxt[:pair_alg] = 2 573*042d53a7SEvalZero $ctxt[:authenticated] = true 574*042d53a7SEvalZero 575*042d53a7SEvalZero # Input 576*042d53a7SEvalZero when 2 577*042d53a7SEvalZero $ctxt[:pair_alg] = 1 578*042d53a7SEvalZero $ctxt[:authenticated] = true 579*042d53a7SEvalZero 580*042d53a7SEvalZero # Display 581*042d53a7SEvalZero when 3 582*042d53a7SEvalZero $ctxt[:pair_alg] = 1 583*042d53a7SEvalZero $ctxt[:authenticated] = true 584*042d53a7SEvalZero 585*042d53a7SEvalZero # Numeric comparison 586*042d53a7SEvalZero when 4 587*042d53a7SEvalZero $ctxt[:pair_alg] = 3 588*042d53a7SEvalZero $ctxt[:authenticated] = true 589*042d53a7SEvalZero 590*042d53a7SEvalZero else 591*042d53a7SEvalZero raise "invalid MITM action: #{passkey_info[:action]}" 592*042d53a7SEvalZero end 593*042d53a7SEvalZeroend 594*042d53a7SEvalZero 595*042d53a7SEvalZerodef passkey_info_s 596*042d53a7SEvalZero passkey_info = $ctxt[:passkey_info] 597*042d53a7SEvalZero action_str = $ACTION_STRINGS[passkey_info[:action]] 598*042d53a7SEvalZero 599*042d53a7SEvalZero result = <<-eos 600*042d53a7SEvalZero .pair_alg = #{$ctxt[:pair_alg]}, 601*042d53a7SEvalZero .authenticated = #{$ctxt[:authenticated]}, 602*042d53a7SEvalZero .passkey_info = { 603*042d53a7SEvalZero .passkey = { 604*042d53a7SEvalZero .action = #{action_str}, 605*042d53a7SEvalZero eos 606*042d53a7SEvalZero 607*042d53a7SEvalZero if passkey_info[:key] != nil 608*042d53a7SEvalZero result << <<-eos 609*042d53a7SEvalZero .passkey = #{passkey_info[:key].to_i}, 610*042d53a7SEvalZero eos 611*042d53a7SEvalZero end 612*042d53a7SEvalZero if passkey_info[:oob] != nil 613*042d53a7SEvalZero result << <<-eos 614*042d53a7SEvalZero#{bytes_to_arr(passkey_info[:oob], "oob", 16)} 615*042d53a7SEvalZero eos 616*042d53a7SEvalZero end 617*042d53a7SEvalZero if passkey_info[:numcmp] != nil 618*042d53a7SEvalZero result << <<-eos 619*042d53a7SEvalZero .numcmp_accept = 1, 620*042d53a7SEvalZero eos 621*042d53a7SEvalZero end 622*042d53a7SEvalZero 623*042d53a7SEvalZero result << <<-eos 624*042d53a7SEvalZero }, 625*042d53a7SEvalZero eos 626*042d53a7SEvalZero 627*042d53a7SEvalZero if passkey_info[:numcmp] != nil 628*042d53a7SEvalZero result << <<-eos 629*042d53a7SEvalZero .exp_numcmp = #{passkey_info[:numcmp].to_i}, 630*042d53a7SEvalZero eos 631*042d53a7SEvalZero end 632*042d53a7SEvalZero 633*042d53a7SEvalZero result << <<-eos 634*042d53a7SEvalZero }, 635*042d53a7SEvalZero eos 636*042d53a7SEvalZeroend 637*042d53a7SEvalZero 638*042d53a7SEvalZerodef addrs_to_s(addrs) 639*042d53a7SEvalZero s = '' 640*042d53a7SEvalZero 641*042d53a7SEvalZero init_type = addrs[:init_type] 642*042d53a7SEvalZero resp_type = addrs[:resp_type] 643*042d53a7SEvalZero 644*042d53a7SEvalZero if init_type != 0 645*042d53a7SEvalZero s += " .init_addr_type = #{$ADDR_TYPE_STRINGS[init_type]},\n" 646*042d53a7SEvalZero end 647*042d53a7SEvalZero s += bytes_to_arr(addrs[:init_id_addr], "init_id_addr", 8) + "\n" 648*042d53a7SEvalZero if init_type >= 2 649*042d53a7SEvalZero s += bytes_to_arr(addrs[:init_rpa], "init_rpa", 8) + "\n" 650*042d53a7SEvalZero end 651*042d53a7SEvalZero 652*042d53a7SEvalZero if resp_type != 0 653*042d53a7SEvalZero s += " .resp_addr_type = #{$ADDR_TYPE_STRINGS[resp_type]},\n" 654*042d53a7SEvalZero end 655*042d53a7SEvalZero s += bytes_to_arr(addrs[:resp_id_addr], "resp_id_addr", 8) + "\n" 656*042d53a7SEvalZero if resp_type >= 2 657*042d53a7SEvalZero s += bytes_to_arr(addrs[:resp_rpa], "resp_rpa", 8) + "\n" 658*042d53a7SEvalZero end 659*042d53a7SEvalZero 660*042d53a7SEvalZero return s 661*042d53a7SEvalZeroend 662*042d53a7SEvalZero 663*042d53a7SEvalZerodef dhkey_check_to_s(dhkey_check, is_req) 664*042d53a7SEvalZero return <<-eos 665*042d53a7SEvalZero .dhkey_check_#{reqrsp_s(is_req)} = { 666*042d53a7SEvalZero#{bytes_to_arr(dhkey_check[:value], "value", 12)} 667*042d53a7SEvalZero }, 668*042d53a7SEvalZero eos 669*042d53a7SEvalZeroend 670*042d53a7SEvalZero 671*042d53a7SEvalZerodef extract_one(lines, ignore_prev = false) 672*042d53a7SEvalZero if ignore_prev 673*042d53a7SEvalZero start = 0 674*042d53a7SEvalZero else 675*042d53a7SEvalZero start = $prev_idx 676*042d53a7SEvalZero end 677*042d53a7SEvalZero 678*042d53a7SEvalZero (start...lines.size).each do |idx| 679*042d53a7SEvalZero line = lines[idx] 680*042d53a7SEvalZero result = yield(line) 681*042d53a7SEvalZero if result != nil 682*042d53a7SEvalZero if !ignore_prev 683*042d53a7SEvalZero $prev_idx = idx 684*042d53a7SEvalZero end 685*042d53a7SEvalZero return result 686*042d53a7SEvalZero end 687*042d53a7SEvalZero end 688*042d53a7SEvalZero 689*042d53a7SEvalZero return nil 690*042d53a7SEvalZeroend 691*042d53a7SEvalZero 692*042d53a7SEvalZerodef extract_pair_req(lines) 693*042d53a7SEvalZero return extract_one(lines) {|line| parse_pair_cmd(line, true)} 694*042d53a7SEvalZeroend 695*042d53a7SEvalZero 696*042d53a7SEvalZerodef extract_pair_rsp(lines) 697*042d53a7SEvalZero return extract_one(lines) {|line| parse_pair_cmd(line, false)} 698*042d53a7SEvalZeroend 699*042d53a7SEvalZero 700*042d53a7SEvalZerodef extract_privkey(lines) 701*042d53a7SEvalZero return extract_one(lines) {|line| parse_privkey(line)} 702*042d53a7SEvalZeroend 703*042d53a7SEvalZero 704*042d53a7SEvalZerodef extract_public_key_req(lines) 705*042d53a7SEvalZero return extract_one(lines) do |line| 706*042d53a7SEvalZero parse_public_key(line, $ctxt[:we_are_init]) 707*042d53a7SEvalZero end 708*042d53a7SEvalZeroend 709*042d53a7SEvalZero 710*042d53a7SEvalZerodef extract_public_key_rsp(lines) 711*042d53a7SEvalZero return extract_one(lines) do |line| 712*042d53a7SEvalZero parse_public_key(line, !$ctxt[:we_are_init]) 713*042d53a7SEvalZero end 714*042d53a7SEvalZeroend 715*042d53a7SEvalZero 716*042d53a7SEvalZerodef extract_confirm_req(lines) 717*042d53a7SEvalZero return extract_one(lines) do |line| 718*042d53a7SEvalZero parse_confirm(line, $ctxt[:we_are_init]) 719*042d53a7SEvalZero end 720*042d53a7SEvalZeroend 721*042d53a7SEvalZero 722*042d53a7SEvalZerodef extract_confirm_rsp(lines) 723*042d53a7SEvalZero return extract_one(lines) do |line| 724*042d53a7SEvalZero parse_confirm(line, !$ctxt[:we_are_init]) 725*042d53a7SEvalZero end 726*042d53a7SEvalZeroend 727*042d53a7SEvalZero 728*042d53a7SEvalZerodef extract_random_req(lines) 729*042d53a7SEvalZero return extract_one(lines) do |line| 730*042d53a7SEvalZero parse_random(line, $ctxt[:we_are_init]) 731*042d53a7SEvalZero end 732*042d53a7SEvalZeroend 733*042d53a7SEvalZero 734*042d53a7SEvalZerodef extract_random_rsp(lines) 735*042d53a7SEvalZero return extract_one(lines) do |line| 736*042d53a7SEvalZero parse_random(line, !$ctxt[:we_are_init]) 737*042d53a7SEvalZero end 738*042d53a7SEvalZeroend 739*042d53a7SEvalZero 740*042d53a7SEvalZerodef extract_confirm_random(lines) 741*042d53a7SEvalZero confirm_reqs = [] 742*042d53a7SEvalZero confirm_rsps = [] 743*042d53a7SEvalZero random_reqs = [] 744*042d53a7SEvalZero random_rsps = [] 745*042d53a7SEvalZero 746*042d53a7SEvalZero idx = 0 747*042d53a7SEvalZero loop do 748*042d53a7SEvalZero confirm_req = extract_confirm_req(lines) 749*042d53a7SEvalZero if confirm_req != nil 750*042d53a7SEvalZero confirm_reqs << confirm_req 751*042d53a7SEvalZero end 752*042d53a7SEvalZero 753*042d53a7SEvalZero confirm_rsp = extract_confirm_rsp(lines) 754*042d53a7SEvalZero break if confirm_rsp == nil 755*042d53a7SEvalZero if idx >= 20 756*042d53a7SEvalZero raise "too many confirm rsps (>20)" 757*042d53a7SEvalZero end 758*042d53a7SEvalZero confirm_rsps << confirm_rsp 759*042d53a7SEvalZero 760*042d53a7SEvalZero random_req = extract_random_req(lines) 761*042d53a7SEvalZero break if random_req == nil 762*042d53a7SEvalZero random_reqs << random_req 763*042d53a7SEvalZero 764*042d53a7SEvalZero random_rsp = extract_random_rsp(lines) 765*042d53a7SEvalZero break if random_rsp == nil 766*042d53a7SEvalZero random_rsps << random_rsp 767*042d53a7SEvalZero 768*042d53a7SEvalZero idx += 1 769*042d53a7SEvalZero end 770*042d53a7SEvalZero 771*042d53a7SEvalZero return confirm_reqs, confirm_rsps, random_reqs, random_rsps 772*042d53a7SEvalZeroend 773*042d53a7SEvalZero 774*042d53a7SEvalZerodef extract_stk(lines) 775*042d53a7SEvalZero return extract_one(lines, true) do |line| 776*042d53a7SEvalZero parse_stk(line) 777*042d53a7SEvalZero end 778*042d53a7SEvalZeroend 779*042d53a7SEvalZero 780*042d53a7SEvalZerodef extract_dhkey_check_req(lines) 781*042d53a7SEvalZero return extract_one(lines) do |line| 782*042d53a7SEvalZero parse_dhkey_check(line, $ctxt[:we_are_init]) 783*042d53a7SEvalZero end 784*042d53a7SEvalZeroend 785*042d53a7SEvalZero 786*042d53a7SEvalZerodef extract_dhkey_check_rsp(lines) 787*042d53a7SEvalZero return extract_one(lines) do |line| 788*042d53a7SEvalZero parse_dhkey_check(line, !$ctxt[:we_are_init]) 789*042d53a7SEvalZero end 790*042d53a7SEvalZeroend 791*042d53a7SEvalZero 792*042d53a7SEvalZerodef extract_enc_info_req(lines) 793*042d53a7SEvalZero return extract_one(lines) do |line| 794*042d53a7SEvalZero parse_enc_info(line, !$ctxt[:we_are_init]) 795*042d53a7SEvalZero end 796*042d53a7SEvalZeroend 797*042d53a7SEvalZero 798*042d53a7SEvalZerodef extract_enc_info_rsp(lines) 799*042d53a7SEvalZero return extract_one(lines) do |line| 800*042d53a7SEvalZero parse_enc_info(line, $ctxt[:we_are_init]) 801*042d53a7SEvalZero end 802*042d53a7SEvalZeroend 803*042d53a7SEvalZero 804*042d53a7SEvalZerodef extract_master_id_req(lines) 805*042d53a7SEvalZero return extract_one(lines) do |line| 806*042d53a7SEvalZero parse_master_id(line, !$ctxt[:we_are_init]) 807*042d53a7SEvalZero end 808*042d53a7SEvalZeroend 809*042d53a7SEvalZero 810*042d53a7SEvalZerodef extract_master_id_rsp(lines) 811*042d53a7SEvalZero return extract_one(lines) do |line| 812*042d53a7SEvalZero parse_master_id(line, $ctxt[:we_are_init]) 813*042d53a7SEvalZero end 814*042d53a7SEvalZeroend 815*042d53a7SEvalZero 816*042d53a7SEvalZerodef extract_id_info_req(lines) 817*042d53a7SEvalZero return extract_one(lines) do |line| 818*042d53a7SEvalZero parse_id_info(line, !$ctxt[:we_are_init]) 819*042d53a7SEvalZero end 820*042d53a7SEvalZeroend 821*042d53a7SEvalZero 822*042d53a7SEvalZerodef extract_id_info_rsp(lines) 823*042d53a7SEvalZero return extract_one(lines) do |line| 824*042d53a7SEvalZero parse_id_info(line, $ctxt[:we_are_init]) 825*042d53a7SEvalZero end 826*042d53a7SEvalZeroend 827*042d53a7SEvalZero 828*042d53a7SEvalZerodef extract_id_addr_info_req(lines) 829*042d53a7SEvalZero return extract_one(lines) do |line| 830*042d53a7SEvalZero parse_id_addr_info(line, !$ctxt[:we_are_init]) 831*042d53a7SEvalZero end 832*042d53a7SEvalZeroend 833*042d53a7SEvalZero 834*042d53a7SEvalZerodef extract_id_addr_info_rsp(lines) 835*042d53a7SEvalZero return extract_one(lines) do |line| 836*042d53a7SEvalZero parse_id_addr_info(line, $ctxt[:we_are_init]) 837*042d53a7SEvalZero end 838*042d53a7SEvalZeroend 839*042d53a7SEvalZero 840*042d53a7SEvalZerodef extract_sign_info_req(lines) 841*042d53a7SEvalZero return extract_one(lines) do |line| 842*042d53a7SEvalZero parse_sign_info(line, !$ctxt[:we_are_init]) 843*042d53a7SEvalZero end 844*042d53a7SEvalZeroend 845*042d53a7SEvalZero 846*042d53a7SEvalZerodef extract_sign_info_rsp(lines) 847*042d53a7SEvalZero return extract_one(lines) do |line| 848*042d53a7SEvalZero parse_sign_info(line, $ctxt[:we_are_init]) 849*042d53a7SEvalZero end 850*042d53a7SEvalZeroend 851*042d53a7SEvalZero 852*042d53a7SEvalZerodef extract_ltk(lines) 853*042d53a7SEvalZero return extract_one(lines) do |line| 854*042d53a7SEvalZero parse_ltk(line) 855*042d53a7SEvalZero end 856*042d53a7SEvalZeroend 857*042d53a7SEvalZero 858*042d53a7SEvalZerodef extract_passkey_info(lines) 859*042d53a7SEvalZero passkey_info = extract_one(lines, true) do |line| 860*042d53a7SEvalZero parse_passkey_info(line) 861*042d53a7SEvalZero end 862*042d53a7SEvalZero 863*042d53a7SEvalZero if passkey_info == nil 864*042d53a7SEvalZero passkey_info = { :action => 0 } 865*042d53a7SEvalZero end 866*042d53a7SEvalZero 867*042d53a7SEvalZero return passkey_info 868*042d53a7SEvalZeroend 869*042d53a7SEvalZero 870*042d53a7SEvalZerodef extract_addrs(lines) 871*042d53a7SEvalZero return extract_one(lines) do |line| 872*042d53a7SEvalZero parse_addrs(line) 873*042d53a7SEvalZero end 874*042d53a7SEvalZeroend 875*042d53a7SEvalZero 876*042d53a7SEvalZero 877*042d53a7SEvalZerolines = STDIN.readlines 878*042d53a7SEvalZero 879*042d53a7SEvalZerodetect_initiator(lines) 880*042d53a7SEvalZero$ctxt[:pair_req] = extract_pair_req(lines) 881*042d53a7SEvalZero$ctxt[:pair_rsp] = extract_pair_rsp(lines) 882*042d53a7SEvalZero$ctxt[:privkey] = extract_privkey(lines) 883*042d53a7SEvalZero$ctxt[:public_key_req] = extract_public_key_req(lines) 884*042d53a7SEvalZero$ctxt[:public_key_rsp] = extract_public_key_rsp(lines) 885*042d53a7SEvalZero$ctxt[:confirm_reqs], $ctxt[:confirm_rsps], $ctxt[:random_reqs], $ctxt[:random_rsps] = extract_confirm_random(lines) 886*042d53a7SEvalZero$ctxt[:passkey_info] = extract_passkey_info(lines) 887*042d53a7SEvalZero$ctxt[:dhkey_check_req] = extract_dhkey_check_req(lines) 888*042d53a7SEvalZero$ctxt[:dhkey_check_rsp] = extract_dhkey_check_rsp(lines) 889*042d53a7SEvalZero$ctxt[:enc_info_req] = extract_enc_info_req(lines) 890*042d53a7SEvalZero$ctxt[:master_id_req] = extract_master_id_req(lines) 891*042d53a7SEvalZero$ctxt[:id_info_req] = extract_id_info_req(lines) 892*042d53a7SEvalZero$ctxt[:id_addr_info_req] = extract_id_addr_info_req(lines) 893*042d53a7SEvalZero$ctxt[:sign_info_req] = extract_sign_info_req(lines) 894*042d53a7SEvalZero$ctxt[:enc_info_rsp] = extract_enc_info_rsp(lines) 895*042d53a7SEvalZero$ctxt[:master_id_rsp] = extract_master_id_rsp(lines) 896*042d53a7SEvalZero$ctxt[:id_info_rsp] = extract_id_info_rsp(lines) 897*042d53a7SEvalZero$ctxt[:id_addr_info_rsp] = extract_id_addr_info_rsp(lines) 898*042d53a7SEvalZero$ctxt[:sign_info_rsp] = extract_sign_info_rsp(lines) 899*042d53a7SEvalZero$ctxt[:addrs] = extract_addrs(lines) 900*042d53a7SEvalZero$ctxt[:ltk] = extract_ltk(lines) 901*042d53a7SEvalZero$ctxt[:stk] = extract_stk(lines) 902*042d53a7SEvalZero 903*042d53a7SEvalZeroexpected_confirm_rsps = nil 904*042d53a7SEvalZeroexpected_random_reqs = nil 905*042d53a7SEvalZeroexpected_random_rsps = nil 906*042d53a7SEvalZeroif $ctxt[:confirm_reqs].size == 0 907*042d53a7SEvalZero expected_confirm_rsps = 1 908*042d53a7SEvalZero expected_random_reqs = 1 909*042d53a7SEvalZero expected_random_rsps = 1 910*042d53a7SEvalZeroelse 911*042d53a7SEvalZero expected_confirm_rsps = $ctxt[:confirm_reqs].size 912*042d53a7SEvalZero expected_random_reqs = $ctxt[:random_reqs].size 913*042d53a7SEvalZero expected_random_rsps = $ctxt[:random_rsps].size 914*042d53a7SEvalZeroend 915*042d53a7SEvalZero 916*042d53a7SEvalZeroif $ctxt[:confirm_rsps].size != expected_confirm_rsps 917*042d53a7SEvalZero raise "wrong number of confirm responses " + 918*042d53a7SEvalZero "(exp=#{expected_confirm_rsps}; got=#{$ctxt[:confirm_rsps].size}" 919*042d53a7SEvalZeroend 920*042d53a7SEvalZero 921*042d53a7SEvalZeroif $ctxt[:random_reqs].size != expected_random_reqs 922*042d53a7SEvalZero raise "wrong number of random requests " + 923*042d53a7SEvalZero "(exp=#{expected_random_reqs}; got=#{$ctxt[:random_reqs].size}" 924*042d53a7SEvalZeroend 925*042d53a7SEvalZero 926*042d53a7SEvalZeroif $ctxt[:random_rsps].size != expected_random_rsps 927*042d53a7SEvalZero raise "wrong number of random responses " + 928*042d53a7SEvalZero "(exp=#{expected_random_rsps}; got=#{$ctxt[:random_rsps].size}" 929*042d53a7SEvalZeroend 930*042d53a7SEvalZero 931*042d53a7SEvalZeropasskey_info_fill($ctxt[:passkey_info]) 932*042d53a7SEvalZero 933*042d53a7SEvalZero$ctxt[:sc] = $ctxt[:public_key_req] != nil 934*042d53a7SEvalZero$ctxt[:bonding] = $ctxt[:pair_req][:authreq] & 1 == 1 && 935*042d53a7SEvalZero $ctxt[:pair_rsp][:authreq] & 1 == 1 936*042d53a7SEvalZero 937*042d53a7SEvalZeroputs test_case_comment() 938*042d53a7SEvalZeroputs <<-eos 939*042d53a7SEvalZeroTEST_CASE(#{test_case_name()}) 940*042d53a7SEvalZero{ 941*042d53a7SEvalZero struct ble_sm_test_params params; 942*042d53a7SEvalZero 943*042d53a7SEvalZero params = (struct ble_sm_test_params) { 944*042d53a7SEvalZeroeos 945*042d53a7SEvalZero 946*042d53a7SEvalZeroputs addrs_to_s($ctxt[:addrs]) 947*042d53a7SEvalZero 948*042d53a7SEvalZeroputs pair_cmd_to_s($ctxt[:pair_req], true) 949*042d53a7SEvalZeroputs pair_cmd_to_s($ctxt[:pair_rsp], false) 950*042d53a7SEvalZero 951*042d53a7SEvalZeroif $ctxt[:sc] 952*042d53a7SEvalZero puts privkey_to_s($ctxt[:privkey]) 953*042d53a7SEvalZero puts public_key_to_s($ctxt[:public_key_req], true) 954*042d53a7SEvalZero puts public_key_to_s($ctxt[:public_key_req], false) 955*042d53a7SEvalZeroend 956*042d53a7SEvalZero 957*042d53a7SEvalZero$ctxt[:confirm_rsps].size.times do |i| 958*042d53a7SEvalZero confirm_req = $ctxt[:confirm_reqs][i] 959*042d53a7SEvalZero confirm_rsp = $ctxt[:confirm_rsps][i] 960*042d53a7SEvalZero random_req = $ctxt[:random_reqs][i] 961*042d53a7SEvalZero random_rsp = $ctxt[:random_rsps][i] 962*042d53a7SEvalZero 963*042d53a7SEvalZero if confirm_req != nil 964*042d53a7SEvalZero puts confirm_to_s(confirm_req, true, i) 965*042d53a7SEvalZero end 966*042d53a7SEvalZero 967*042d53a7SEvalZero puts confirm_to_s(confirm_rsp, false, i) 968*042d53a7SEvalZero puts random_to_s(random_req, true, i) 969*042d53a7SEvalZero puts random_to_s(random_rsp, false, i) 970*042d53a7SEvalZeroend 971*042d53a7SEvalZero 972*042d53a7SEvalZeroif $ctxt[:sc] 973*042d53a7SEvalZero puts dhkey_check_to_s($ctxt[:dhkey_check_req], true) 974*042d53a7SEvalZero puts dhkey_check_to_s($ctxt[:dhkey_check_rsp], false) 975*042d53a7SEvalZeroend 976*042d53a7SEvalZero 977*042d53a7SEvalZeroif $ctxt[:enc_info_req] != nil 978*042d53a7SEvalZero puts enc_info_to_s($ctxt[:enc_info_req], true) 979*042d53a7SEvalZeroend 980*042d53a7SEvalZeroif $ctxt[:master_id_req] != nil 981*042d53a7SEvalZero puts master_id_to_s($ctxt[:master_id_req], true) 982*042d53a7SEvalZeroend 983*042d53a7SEvalZeroif $ctxt[:id_info_req] != nil 984*042d53a7SEvalZero puts id_info_to_s($ctxt[:id_info_req], true) 985*042d53a7SEvalZeroend 986*042d53a7SEvalZeroif $ctxt[:id_addr_info_req] != nil 987*042d53a7SEvalZero puts id_addr_info_to_s($ctxt[:id_addr_info_req], true) 988*042d53a7SEvalZeroend 989*042d53a7SEvalZeroif $ctxt[:sign_info_req] != nil 990*042d53a7SEvalZero puts sign_info_to_s($ctxt[:sign_info_req], true) 991*042d53a7SEvalZeroend 992*042d53a7SEvalZeroif $ctxt[:enc_info_rsp] != nil 993*042d53a7SEvalZero puts enc_info_to_s($ctxt[:enc_info_rsp], false) 994*042d53a7SEvalZeroend 995*042d53a7SEvalZeroif $ctxt[:master_id_rsp] != nil 996*042d53a7SEvalZero puts master_id_to_s($ctxt[:master_id_rsp], false) 997*042d53a7SEvalZeroend 998*042d53a7SEvalZeroif $ctxt[:id_info_rsp] != nil 999*042d53a7SEvalZero puts id_info_to_s($ctxt[:id_info_rsp], false) 1000*042d53a7SEvalZeroend 1001*042d53a7SEvalZeroif $ctxt[:id_addr_info_rsp] != nil 1002*042d53a7SEvalZero puts id_addr_info_to_s($ctxt[:id_addr_info_rsp], false) 1003*042d53a7SEvalZeroend 1004*042d53a7SEvalZeroif $ctxt[:sign_info_rsp] != nil 1005*042d53a7SEvalZero puts sign_info_to_s($ctxt[:sign_info_rsp], false) 1006*042d53a7SEvalZeroend 1007*042d53a7SEvalZeroif $ctxt[:sc] 1008*042d53a7SEvalZero puts ltk_to_s($ctxt[:ltk]) 1009*042d53a7SEvalZeroelse 1010*042d53a7SEvalZero puts stk_to_s($ctxt[:stk]) 1011*042d53a7SEvalZeroend 1012*042d53a7SEvalZeroputs passkey_info_s() 1013*042d53a7SEvalZero 1014*042d53a7SEvalZeroputs ' };' 1015*042d53a7SEvalZero 1016*042d53a7SEvalZeroif $ctxt[:sc] 1017*042d53a7SEvalZero if $ctxt[:we_are_init] 1018*042d53a7SEvalZero puts ' ble_sm_test_util_us_sc_good(¶ms);' 1019*042d53a7SEvalZero else 1020*042d53a7SEvalZero puts ' ble_sm_test_util_peer_sc_good(¶ms);' 1021*042d53a7SEvalZero end 1022*042d53a7SEvalZeroelse 1023*042d53a7SEvalZero if $ctxt[:we_are_init] 1024*042d53a7SEvalZero puts ' ble_sm_test_util_us_lgcy_good(¶ms);' 1025*042d53a7SEvalZero else 1026*042d53a7SEvalZero puts ' ble_sm_test_util_peer_lgcy_good(¶ms);' 1027*042d53a7SEvalZero end 1028*042d53a7SEvalZeroend 1029*042d53a7SEvalZeroputs '}' 1030