mirror of
https://github.com/espressif/openthread.git
synced 2026-07-28 22:57:47 +00:00
[thread-cert] refactor case 8.1.2, 8.2.1 and 8.2.2 using pktverify (#5411)
This commit is contained in:
@@ -30,6 +30,8 @@
|
||||
import unittest
|
||||
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_DISCOVERY_RESPONSE, HANDSHAKE_CLIENT_HELLO, HANDSHAKE_SERVER_HELLO, HANDSHAKE_SERVER_KEY_EXCHANGE, HANDSHAKE_SERVER_HELLO_DONE, HANDSHAKE_CLIENT_KEY_EXCHANGE, HANDSHAKE_HELLO_VERIFY_REQUEST, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV, NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV, CONTENT_CHANGE_CIPHER_SPEC, CONTENT_ALERT, CONTENT_HANDSHAKE
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
COMMISSIONER = 1
|
||||
JOINER = 2
|
||||
@@ -40,12 +42,14 @@ class Cert_8_1_02_Commissioning(thread_cert.TestCase):
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'masterkey': 'deadbeefdeadbeefdeadbeefdeadbeef',
|
||||
'name': 'COMMISSIONER',
|
||||
'masterkey': '00112233445566778899aabbccddeeff',
|
||||
'mode': 'rsdn',
|
||||
'panid': 0xface
|
||||
},
|
||||
JOINER: {
|
||||
'masterkey': '00112233445566778899aabbccddeeff',
|
||||
'name': 'JOINER',
|
||||
'masterkey': 'deadbeefdeadbeefdeadbeefdeadbeef',
|
||||
'mode': 'rsdn',
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
@@ -63,10 +67,50 @@ class Cert_8_1_02_Commissioning(thread_cert.TestCase):
|
||||
self.nodes[JOINER].interface_up()
|
||||
self.nodes[JOINER].joiner_start('10DKSP')
|
||||
self.simulator.go(10)
|
||||
self.assertNotEqual(
|
||||
self.nodes[JOINER].get_masterkey(),
|
||||
self.nodes[COMMISSIONER].get_masterkey(),
|
||||
)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
_cpkts = pkts.filter_wpan_src64(COMMISSIONER)
|
||||
_cpkts2 = pkts.filter_wpan_dst64(COMMISSIONER)
|
||||
|
||||
# Step 3: Verify the following details occur in the exchange between
|
||||
# Joiner_1 and the Commissioner
|
||||
# 1. UDP port (Specified by the Commissioner: in Discovery Response) is used as destination port for UDP datagrams from Joiner_1 to the Commissioner.
|
||||
_cpkts.filter_mle_cmd(MLE_DISCOVERY_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV,
|
||||
NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV
|
||||
} == set(p.thread_meshcop.tlv.type))
|
||||
|
||||
# 2. Joiner_1 sends an initial DTLS-ClientHello handshake record to the Commissioner
|
||||
_cpkts2.range(_cpkts.index).filter(lambda p: p.dtls.handshake.type == [HANDSHAKE_CLIENT_HELLO]).must_next()
|
||||
|
||||
# 3. The Commissioner must correctly receive the initial DTLS-ClientHello handshake record and send a DTLS-HelloVerifyRequest handshake record to Joiner_1
|
||||
_pkt = _cpkts.range(
|
||||
_cpkts2.index).filter(lambda p: p.dtls.handshake.type == [HANDSHAKE_HELLO_VERIFY_REQUEST]).must_next()
|
||||
_pkt.must_verify(lambda p: p.dtls.handshake.cookie is not None)
|
||||
|
||||
# 4. Joiner_1 receives the DTLS-HelloVerifyRequest handshake record and sends a subsequent DTLS-ClientHello handshake record in one UDP datagram to the Commissioner
|
||||
# 5. Verify that both DTLS-HelloVerifyRequest and subsequent DTLS-ClientHello contain the same cookie
|
||||
_cpkts2.filter(lambda p: p.dtls.handshake.type == [HANDSHAKE_CLIENT_HELLO]).must_next().must_verify(
|
||||
lambda p: p.dtls.handshake.cookie == _pkt.dtls.handshake.cookie)
|
||||
|
||||
# 6. The Commissioner must correctly receive the subsequent DTLSClientHello handshake record and then send, in order, DTLSServerHello, DTLS-ServerKeyExchange and DTLSServerHelloDone handshake records to Joiner_1
|
||||
_cpkts.filter(
|
||||
lambda p: p.dtls.handshake.type ==
|
||||
[HANDSHAKE_SERVER_HELLO, HANDSHAKE_SERVER_KEY_EXCHANGE, HANDSHAKE_SERVER_HELLO_DONE]).must_next()
|
||||
|
||||
# 7. Joiner_1 receives the DTLS-ServerHello, DTLSServerKeyExchange and DTLS-ServerHelloDone handshake records and sends, in order, a DTLS-ClientKeyExchange handshake record, a DTLS-ChangeCipherSpec record and an encrypted DTLS-Finished handshake record to the Commissioner.
|
||||
_cpkts2.filter(lambda p: p.dtls.handshake.type == [HANDSHAKE_CLIENT_KEY_EXCHANGE]).must_next().must_verify(
|
||||
lambda p: p.dtls.handshake.type == [HANDSHAKE_CLIENT_KEY_EXCHANGE] and set(
|
||||
p.dtls.record.content_type) == {CONTENT_CHANGE_CIPHER_SPEC, CONTENT_HANDSHAKE})
|
||||
|
||||
# 8. The Commissioner must receive the DTLS-ClientKeyExchange handshake record, the DTLS-ChangeCipherSpec and the encrypted DTLS-Finished handshake record, and then send a DTLS-Alert record with error code 20 (bad record MAC) - in one UDP datagram - to Joiner_1
|
||||
_cpkts.filter(
|
||||
lambda p: p.dtls.record.content_type == [CONTENT_ALERT] and p.dtls.alert_message.desc == 20).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
import unittest
|
||||
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_DISCOVERY_RESPONSE, HANDSHAKE_CLIENT_HELLO, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV, NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV, RLY_RX_URI, RLY_TX_URI
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
COMMISSIONER = 1
|
||||
JOINER_ROUTER = 2
|
||||
@@ -41,17 +43,20 @@ class Cert_8_2_01_JoinerRouter(thread_cert.TestCase):
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'masterkey': 'deadbeefdeadbeefdeadbeefdeadbeef',
|
||||
'name': 'COMMISSIONER',
|
||||
'masterkey': '00112233445566778899aabbccddeeff',
|
||||
'mode': 'rsdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
JOINER_ROUTER: {
|
||||
'name': 'JOINER_ROUTER',
|
||||
'masterkey': '00112233445566778899aabbccddeeff',
|
||||
'mode': 'rsdn',
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
JOINER: {
|
||||
'name': 'JOINER',
|
||||
'masterkey': '00112233445566778899aabbccddeeff',
|
||||
'mode': 'rsdn',
|
||||
'router_selection_jitter': 1
|
||||
@@ -99,6 +104,40 @@ class Cert_8_2_01_JoinerRouter(thread_cert.TestCase):
|
||||
self.nodes[JOINER].thread_start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[JOINER].get_state(), 'router')
|
||||
self.collect_rloc16s()
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
_cpkts = pkts.filter_wpan_src64(COMMISSIONER)
|
||||
_cpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
|
||||
# Step 3: Verify that the following details occur in the exchange between the Joiner,
|
||||
# the Joiner_Router and the Commissioner
|
||||
# 1. UDP port (Specified by the Commissioner: in Discovery Response) is used as destination port
|
||||
# for UDP datagrams from Joiner_1 to the Commissioner.
|
||||
pkts.range(_cpkts.index).filter_mle_cmd(MLE_DISCOVERY_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV,
|
||||
NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV
|
||||
} == set(p.thread_meshcop.tlv.type))
|
||||
|
||||
# 2. Joiner_1 sends an initial DTLS-ClientHello handshake record to the Commissioner
|
||||
pkts.filter(lambda p: p.dtls.handshake.type == [HANDSHAKE_CLIENT_HELLO]).must_next()
|
||||
|
||||
# 3. The Joiner_Router receives the initial DTLS-ClientHello handshake record and sends a RLY_RX.ntf
|
||||
# message to the Commissioner
|
||||
# Todo: verify coap payload
|
||||
jr_rloc16 = pv.vars["JOINER_ROUTER_RLOC16"]
|
||||
c_rloc16 = pv.vars["COMMISSIONER_RLOC16"]
|
||||
pkts.filter_coap_request(RLY_RX_URI).must_next().must_verify(
|
||||
lambda p: p.wpan.src16 == jr_rloc16 and p.wpan.dst16 == c_rloc16)
|
||||
|
||||
# 4. The Commissioner receives the RLY_RX.ntf message and sends a RLY_TX.ntf message to the Joiner_Router
|
||||
pkts.filter_coap_request(RLY_TX_URI).must_next().must_verify(
|
||||
lambda p: p.wpan.src16 == c_rloc16 and p.wpan.dst16 == jr_rloc16)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
import unittest
|
||||
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_DISCOVERY_RESPONSE, HANDSHAKE_CLIENT_HELLO, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV, NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV, RLY_RX_URI, RLY_TX_URI
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
COMMISSIONER = 1
|
||||
JOINER_ROUTER = 2
|
||||
@@ -41,17 +43,20 @@ class Cert_8_2_02_JoinerRouter(thread_cert.TestCase):
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'masterkey': 'deadbeefdeadbeefdeadbeefdeadbeef',
|
||||
'name': 'COMMISSIONER',
|
||||
'masterkey': '00112233445566778899aabbccddeeff',
|
||||
'mode': 'rsdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
JOINER_ROUTER: {
|
||||
'name': 'JOINER_ROUTER',
|
||||
'masterkey': '00112233445566778899aabbccddeeff',
|
||||
'mode': 'rsdn',
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
JOINER: {
|
||||
'name': 'JOINER',
|
||||
'masterkey': '00112233445566778899aabbccddeeff',
|
||||
'mode': 'rsdn',
|
||||
'router_selection_jitter': 1
|
||||
@@ -91,10 +96,40 @@ class Cert_8_2_02_JoinerRouter(thread_cert.TestCase):
|
||||
self.nodes[JOINER].interface_up()
|
||||
self.nodes[JOINER].joiner_start('20DKSP')
|
||||
self.simulator.go(10)
|
||||
self.assertNotEqual(
|
||||
self.nodes[JOINER].get_masterkey(),
|
||||
self.nodes[COMMISSIONER].get_masterkey(),
|
||||
)
|
||||
self.collect_rloc16s()
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
_cpkts = pkts.filter_wpan_src64(COMMISSIONER)
|
||||
_cpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
|
||||
# Step 3: Verify that the following details occur in the exchange between the Joiner,
|
||||
# the Joiner_Router and the Commissioner
|
||||
# 1. UDP port (Specified by the Commissioner: in Discovery Response) is used as destination port
|
||||
# for UDP datagrams from Joiner_1 to the Commissioner.
|
||||
pkts.range(_cpkts.index).filter_mle_cmd(MLE_DISCOVERY_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV,
|
||||
NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV
|
||||
} == set(p.thread_meshcop.tlv.type))
|
||||
|
||||
# 2. Joiner_1 sends an initial DTLS-ClientHello handshake record to the Commissioner
|
||||
pkts.filter(lambda p: p.dtls.handshake.type == [HANDSHAKE_CLIENT_HELLO]).must_next()
|
||||
|
||||
# 3. The Joiner_Router receives the initial DTLS-ClientHello handshake record and sends a RLY_RX.ntf
|
||||
# message to the Commissioner
|
||||
# Todo: verify coap payload
|
||||
jr_rloc16 = pv.vars["JOINER_ROUTER_RLOC16"]
|
||||
c_rloc16 = pv.vars["COMMISSIONER_RLOC16"]
|
||||
pkts.filter_coap_request(RLY_RX_URI).must_next().must_verify(
|
||||
lambda p: p.wpan.src16 == jr_rloc16 and p.wpan.dst16 == c_rloc16)
|
||||
|
||||
# 4. The Commissioner receives the RLY_RX.ntf message and sends a RLY_TX.ntf message to the Joiner_Router
|
||||
pkts.filter_coap_request(RLY_TX_URI).must_next().must_verify(
|
||||
lambda p: p.wpan.src16 == c_rloc16 and p.wpan.dst16 == jr_rloc16)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -73,6 +73,8 @@ MLE_CHILD_ID_RESPONSE = 12
|
||||
MLE_CHILD_UPDATE_REQUEST = 13
|
||||
MLE_CHILD_UPDATE_RESPONSE = 14
|
||||
MLE_ANNOUNCE = 15
|
||||
MLE_DISCOVERY_REQUEST = 16
|
||||
MLE_DISCOVERY_RESPONSE = 17
|
||||
|
||||
# COAP URIs
|
||||
ADDR_QRY_URI = '/a/aq'
|
||||
@@ -82,6 +84,8 @@ ADDR_SOL_URI = '/a/as'
|
||||
ADDR_REL_URI = '/a/ar'
|
||||
SVR_DATA_URI = '/a/sd'
|
||||
ND_DATA_URI = '/a/nd'
|
||||
RLY_RX_URI = '/c/rx'
|
||||
RLY_TX_URI = '/c/tx'
|
||||
|
||||
# MLE TLVs
|
||||
SOURCE_ADDRESS_TLV = 0
|
||||
@@ -124,6 +128,38 @@ NL_ND_OPTION_TLV = 8
|
||||
NL_ND_DATA_TLV = 9
|
||||
NL_THREAD_NETWORK_DATA_TLV = 10
|
||||
|
||||
# MeshCop TLVs
|
||||
NM_CHANNEL_TLV = 0
|
||||
NM_PAN_ID_TLV = 1
|
||||
NM_EXTENDED_PAN_ID_TLV = 2
|
||||
NM_NETWORK_NAME_TLV = 3
|
||||
NM_PSKC_TLV = 4
|
||||
NM_NETWORK_MASTER_KEY_TLV = 5
|
||||
NM_NETWORK_KEY_SEQUENCE_COUNTER_TLV = 6
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV = 7
|
||||
NM_STEERING_DATA_TLV = 8
|
||||
NM_SECURITY_POLICY_TLV = 12
|
||||
NM_COMMISSIONER_UDP_PORT_TLV = 15
|
||||
NM_JOINER_UDP_PORT_TLV = 18
|
||||
NM_CHANNEL_MASK_TLV = 53
|
||||
NM_DISCOVERY_RESPONSE_TLV = 129
|
||||
|
||||
# DTLS
|
||||
HANDSHAKE_HELLO_REQUEST = 0
|
||||
HANDSHAKE_CLIENT_HELLO = 1
|
||||
HANDSHAKE_SERVER_HELLO = 2
|
||||
HANDSHAKE_HELLO_VERIFY_REQUEST = 3
|
||||
HANDSHAKE_CERTIFICATE = 11
|
||||
HANDSHAKE_SERVER_KEY_EXCHANGE = 12
|
||||
HANDSHAKE_CERTIFICATE_REQUEST = 13
|
||||
HANDSHAKE_SERVER_HELLO_DONE = 14
|
||||
HANDSHAKE_CERTIFICATE_VERIFY = 15
|
||||
HANDSHAKE_CLIENT_KEY_EXCHANGE = 16
|
||||
HANDSHAKE_FINISHED = 20
|
||||
CONTENT_CHANGE_CIPHER_SPEC = 20
|
||||
CONTENT_ALERT = 21
|
||||
CONTENT_HANDSHAKE = 22
|
||||
|
||||
# DUA related constants
|
||||
|
||||
ADDRESS_QUERY_INITIAL_RETRY_DELAY = 15
|
||||
@@ -148,6 +184,7 @@ INFINITE_COST_TIMEOUT = 90
|
||||
REAL_LAYER_NAMES = {
|
||||
'mle',
|
||||
'coap',
|
||||
'dtls',
|
||||
'wpan',
|
||||
'eth',
|
||||
'tcp',
|
||||
|
||||
@@ -479,6 +479,12 @@ _LAYER_FIELDS = {
|
||||
'coap.tlv.router_mask_assigned': _auto,
|
||||
'coap.tlv.router_mask_id_seq': _auto,
|
||||
|
||||
# dtls
|
||||
'dtls.handshake.type': _list(_auto),
|
||||
'dtls.handshake.cookie': _auto,
|
||||
'dtls.record.content_type': _list(_auto),
|
||||
'dtls.alert_message.desc': _auto,
|
||||
|
||||
# thread_address
|
||||
'thread_address.tlv.type': _list(_auto),
|
||||
'thread_address.tlv.status': _auto,
|
||||
|
||||
Reference in New Issue
Block a user