xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/tools/log2smtest.rb (revision 042d53a763ad75cb1465103098bb88c245d95138)
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(&params);'
1019*042d53a7SEvalZero    else
1020*042d53a7SEvalZero        puts '    ble_sm_test_util_peer_sc_good(&params);'
1021*042d53a7SEvalZero    end
1022*042d53a7SEvalZeroelse
1023*042d53a7SEvalZero    if $ctxt[:we_are_init]
1024*042d53a7SEvalZero        puts '    ble_sm_test_util_us_lgcy_good(&params);'
1025*042d53a7SEvalZero    else
1026*042d53a7SEvalZero        puts '    ble_sm_test_util_peer_lgcy_good(&params);'
1027*042d53a7SEvalZero    end
1028*042d53a7SEvalZeroend
1029*042d53a7SEvalZeroputs '}'
1030