xref: /btstack/test/mesh/provisioning_device_test.cpp (revision d567aeb32398f2a708611c446bcd9bad85a152cd)
11fbe4564SMatthias Ringwald /*
21fbe4564SMatthias Ringwald  * Copyright (C) 2017 BlueKitchen GmbH
31fbe4564SMatthias Ringwald  *
41fbe4564SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
51fbe4564SMatthias Ringwald  * modification, are permitted provided that the following conditions
61fbe4564SMatthias Ringwald  * are met:
71fbe4564SMatthias Ringwald  *
81fbe4564SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
91fbe4564SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
101fbe4564SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
111fbe4564SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
121fbe4564SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
131fbe4564SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
141fbe4564SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
151fbe4564SMatthias Ringwald  *    from this software without specific prior written permission.
161fbe4564SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
171fbe4564SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
181fbe4564SMatthias Ringwald  *    monetary gain.
191fbe4564SMatthias Ringwald  *
201fbe4564SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
211fbe4564SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
221fbe4564SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
231fbe4564SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
241fbe4564SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
251fbe4564SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
261fbe4564SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
271fbe4564SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
281fbe4564SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
291fbe4564SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
301fbe4564SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311fbe4564SMatthias Ringwald  * SUCH DAMAGE.
321fbe4564SMatthias Ringwald  *
331fbe4564SMatthias Ringwald  * Please inquire about commercial licensing options at
341fbe4564SMatthias Ringwald  * [email protected]
351fbe4564SMatthias Ringwald  *
361fbe4564SMatthias Ringwald  */
371fbe4564SMatthias Ringwald 
381fbe4564SMatthias Ringwald #include <stdint.h>
391fbe4564SMatthias Ringwald #include <stdio.h>
40df71a9a4SMatthias Ringwald #include "btstack_memory.h"
41*d567aeb3SMatthias Ringwald #include "mesh/gatt-service/mesh_provisioning_service_server.h"
42f4854a5eSMatthias Ringwald #include "hci_dump.h"
4331437b52SMatthias Ringwald #include "hci_dump_posix_fs.h"
44f4854a5eSMatthias Ringwald #include "mesh/mesh_node.h"
4577ba3d3fSMatthias Ringwald #include "mesh/pb_adv.h"
4677ba3d3fSMatthias Ringwald #include "mesh/pb_gatt.h"
47f4854a5eSMatthias Ringwald #include "mesh/provisioning.h"
48f4854a5eSMatthias Ringwald #include "mesh/provisioning_device.h"
491fbe4564SMatthias Ringwald 
501fbe4564SMatthias Ringwald #include "CppUTest/TestHarness.h"
511fbe4564SMatthias Ringwald #include "CppUTest/CommandLineTestRunner.h"
521fbe4564SMatthias Ringwald 
53df71a9a4SMatthias Ringwald #include "mock.h"
54df71a9a4SMatthias Ringwald 
CHECK_EQUAL_ARRAY(const char * name,uint8_t * expected,uint8_t * actual,int size)55b31f07b7SMatthias Ringwald static void CHECK_EQUAL_ARRAY(const char * name, uint8_t * expected, uint8_t * actual, int size){
561fbe4564SMatthias Ringwald     int i;
571fbe4564SMatthias Ringwald     for (i=0; i<size; i++){
581fbe4564SMatthias Ringwald         if (expected[i] != actual[i]) {
59b31f07b7SMatthias Ringwald             printf("%s: offset %u wrong\n", name, i);
601fbe4564SMatthias Ringwald             printf("expected: "); printf_hexdump(expected, size);
611fbe4564SMatthias Ringwald             printf("actual:   "); printf_hexdump(actual, size);
621fbe4564SMatthias Ringwald         }
631fbe4564SMatthias Ringwald         BYTES_EQUAL(expected[i], actual[i]);
641fbe4564SMatthias Ringwald     }
651fbe4564SMatthias Ringwald }
661fbe4564SMatthias Ringwald 
671fbe4564SMatthias Ringwald const static uint8_t device_uuid[] = { 0x00, 0x1B, 0xDC, 0x08, 0x10, 0x21, 0x0B, 0x0E, 0x0A, 0x0C, 0x00, 0x0B, 0x0E, 0x0A, 0x0C, 0x00 };
681fbe4564SMatthias Ringwald 
691fbe4564SMatthias Ringwald // pb-adv mock for testing
701fbe4564SMatthias Ringwald 
711fbe4564SMatthias Ringwald static btstack_packet_handler_t pb_adv_packet_handler;
721fbe4564SMatthias Ringwald 
731fbe4564SMatthias Ringwald static uint8_t * pdu_data;
741fbe4564SMatthias Ringwald static uint16_t  pdu_size;
751fbe4564SMatthias Ringwald 
761fbe4564SMatthias Ringwald /**
771fbe4564SMatthias Ringwald  * Initialize Provisioning Bearer using Advertisement Bearer
781fbe4564SMatthias Ringwald  * @param DeviceUUID
791fbe4564SMatthias Ringwald  */
pb_adv_init(void)808936a143SMatthias Ringwald void pb_adv_init(void){}
pb_gatt_init(void)8154274a76SMatthias Ringwald void pb_gatt_init(void){}
821fbe4564SMatthias Ringwald 
83870b3bb0SMilanka Ringwald /**
84870b3bb0SMilanka Ringwald  * Close Link
85870b3bb0SMilanka Ringwald  * @param con_handle
86870b3bb0SMilanka Ringwald  * @param reason 0 = success, 1 = timeout, 2 = fail
87870b3bb0SMilanka Ringwald  */
pb_gatt_close_link(hci_con_handle_t con_handle,uint8_t reason)88df71a9a4SMatthias Ringwald void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){
89df71a9a4SMatthias Ringwald     UNUSED(con_handle);
90df71a9a4SMatthias Ringwald     UNUSED(reason);
91df71a9a4SMatthias Ringwald }
pb_adv_close_link(hci_con_handle_t con_handle,uint8_t reason)92df71a9a4SMatthias Ringwald void pb_adv_close_link(hci_con_handle_t con_handle, uint8_t reason){
93df71a9a4SMatthias Ringwald     UNUSED(con_handle);
94df71a9a4SMatthias Ringwald     UNUSED(reason);
95df71a9a4SMatthias Ringwald }
96870b3bb0SMilanka Ringwald 
971fbe4564SMatthias Ringwald 
981fbe4564SMatthias Ringwald /**
991fbe4564SMatthias Ringwald  * Register listener for Provisioning PDUs and MESH_PBV_ADV_SEND_COMPLETE
1001fbe4564SMatthias Ringwald  */
pb_adv_register_device_packet_handler(btstack_packet_handler_t packet_handler)101fe430865SMatthias Ringwald void pb_adv_register_device_packet_handler(btstack_packet_handler_t packet_handler){
1021fbe4564SMatthias Ringwald     pb_adv_packet_handler = packet_handler;
1031fbe4564SMatthias Ringwald }
1041fbe4564SMatthias Ringwald 
pb_gatt_register_packet_handler(btstack_packet_handler_t packet_handler)105870b3bb0SMilanka Ringwald void pb_gatt_register_packet_handler(btstack_packet_handler_t packet_handler){
106870b3bb0SMilanka Ringwald     UNUSED(packet_handler);
107870b3bb0SMilanka Ringwald }
1081fbe4564SMatthias Ringwald /**
1091fbe4564SMatthias Ringwald  * Send Provisioning PDU
1101fbe4564SMatthias Ringwald  */
pb_adv_send_pdu(uint16_t pb_transport_cid,const uint8_t * pdu,uint16_t size)111beeedc45SMilanka Ringwald void pb_adv_send_pdu(uint16_t pb_transport_cid, const uint8_t * pdu, uint16_t size){
112beeedc45SMilanka Ringwald     UNUSED(pb_transport_cid);
1131fbe4564SMatthias Ringwald     pdu_data = (uint8_t*) pdu;
1141fbe4564SMatthias Ringwald     pdu_size = size;
1151fbe4564SMatthias Ringwald     // dump_data((uint8_t*)pdu,size);
1161fbe4564SMatthias Ringwald     // printf_hexdump(pdu, size);
1171fbe4564SMatthias Ringwald }
pb_gatt_send_pdu(uint16_t con_handle,const uint8_t * pdu,uint16_t _pdu_size)118df71a9a4SMatthias Ringwald void pb_gatt_send_pdu(uint16_t con_handle, const uint8_t * pdu, uint16_t _pdu_size){
119df71a9a4SMatthias Ringwald     UNUSED(con_handle);
120df71a9a4SMatthias Ringwald     UNUSED(pdu);
121df71a9a4SMatthias Ringwald     UNUSED(_pdu_size);
122df71a9a4SMatthias Ringwald }
1231fbe4564SMatthias Ringwald 
mesh_network_key_get_free_index(void)1240500a934SMatthias Ringwald uint16_t mesh_network_key_get_free_index(void){
1250500a934SMatthias Ringwald     return 0;
1260500a934SMatthias Ringwald }
127d6915e6fSMatthias Ringwald 
1282d97f8bbSMatthias Ringwald static mesh_network_key_t network_key;
btstack_memory_mesh_network_key_get(void)129d6915e6fSMatthias Ringwald extern "C" mesh_network_key_t * btstack_memory_mesh_network_key_get(void){
1302d97f8bbSMatthias Ringwald     return &network_key;
1312d97f8bbSMatthias Ringwald }
1322d97f8bbSMatthias Ringwald 
perform_crypto_operations(void)1331fbe4564SMatthias Ringwald static void perform_crypto_operations(void){
1341fbe4564SMatthias Ringwald     int more = 1;
1351fbe4564SMatthias Ringwald     while (more){
1361fbe4564SMatthias Ringwald         more = mock_process_hci_cmd();
1371fbe4564SMatthias Ringwald     }
1381fbe4564SMatthias Ringwald }
1391fbe4564SMatthias Ringwald 
send_prov_pdu(const uint8_t * packet,uint16_t size)1401fbe4564SMatthias Ringwald static void send_prov_pdu(const uint8_t * packet, uint16_t size){
1411fbe4564SMatthias Ringwald     pb_adv_packet_handler(PROVISIONING_DATA_PACKET, 0, (uint8_t*) packet, size);
1421fbe4564SMatthias Ringwald     perform_crypto_operations();
1431fbe4564SMatthias Ringwald }
1441fbe4564SMatthias Ringwald 
pb_adv_emit_pdu_sent(uint8_t status)1451fbe4564SMatthias Ringwald static void pb_adv_emit_pdu_sent(uint8_t status){
1467bd12f9fSMilanka Ringwald     uint8_t event[] = { HCI_EVENT_MESH_META, 2, MESH_SUBEVENT_PB_TRANSPORT_PDU_SENT, status};
1471fbe4564SMatthias Ringwald     pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
1481fbe4564SMatthias Ringwald }
1491fbe4564SMatthias Ringwald 
scan_hex_byte(const char * byte_string)1501fbe4564SMatthias Ringwald static int scan_hex_byte(const char * byte_string){
1511fbe4564SMatthias Ringwald     int upper_nibble = nibble_for_char(*byte_string++);
1521fbe4564SMatthias Ringwald     if (upper_nibble < 0) return -1;
1531fbe4564SMatthias Ringwald     int lower_nibble = nibble_for_char(*byte_string);
1541fbe4564SMatthias Ringwald     if (lower_nibble < 0) return -1;
1551fbe4564SMatthias Ringwald     return (upper_nibble << 4) | lower_nibble;
1561fbe4564SMatthias Ringwald }
1571fbe4564SMatthias Ringwald 
btstack_parse_hex(const char * string,uint16_t len,uint8_t * buffer)1581fbe4564SMatthias Ringwald static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){
1591fbe4564SMatthias Ringwald     int i;
1601fbe4564SMatthias Ringwald     for (i = 0; i < len; i++) {
1611fbe4564SMatthias Ringwald         int single_byte = scan_hex_byte(string);
1621fbe4564SMatthias Ringwald         if (single_byte < 0) return 0;
1631fbe4564SMatthias Ringwald         string += 2;
1641fbe4564SMatthias Ringwald         buffer[i] = (uint8_t)single_byte;
1651fbe4564SMatthias Ringwald         // don't check seperator after last byte
1661fbe4564SMatthias Ringwald         if (i == len - 1) {
1671fbe4564SMatthias Ringwald             return 1;
1681fbe4564SMatthias Ringwald         }
1691fbe4564SMatthias Ringwald         // optional seperator
1701fbe4564SMatthias Ringwald         char separator = *string;
1711fbe4564SMatthias Ringwald         if (separator == ':' && separator == '-' && separator == ' ') {
1721fbe4564SMatthias Ringwald             string++;
1731fbe4564SMatthias Ringwald         }
1741fbe4564SMatthias Ringwald     }
1751fbe4564SMatthias Ringwald     return 1;
1761fbe4564SMatthias Ringwald }
1771fbe4564SMatthias Ringwald 
178870b3bb0SMilanka Ringwald // void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){
179870b3bb0SMilanka Ringwald // }
180870b3bb0SMilanka Ringwald 
1811fbe4564SMatthias Ringwald static uint8_t      prov_static_oob_data[16];
1821fbe4564SMatthias Ringwald static const char * prov_static_oob_string = "00000000000000000102030405060708";
1831fbe4564SMatthias Ringwald 
TEST_GROUP(Provisioning)1841fbe4564SMatthias Ringwald TEST_GROUP(Provisioning){
1851fbe4564SMatthias Ringwald     void setup(void){
186b31f07b7SMatthias Ringwald         mock_init();
187b31f07b7SMatthias Ringwald         for (unsigned int i = 0 ; i < 4 ; i ++){
188b31f07b7SMatthias Ringwald             printf("rand: %08x\n", rand());
189b31f07b7SMatthias Ringwald         }
1901fbe4564SMatthias Ringwald         btstack_crypto_init();
1918936a143SMatthias Ringwald         provisioning_device_init();
1928936a143SMatthias Ringwald         mesh_node_set_device_uuid(device_uuid);
1931fbe4564SMatthias Ringwald         btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data);
1941fbe4564SMatthias Ringwald         provisioning_device_set_static_oob(16, prov_static_oob_data);
1951fbe4564SMatthias Ringwald         provisioning_device_set_output_oob_actions(0x08, 0x08);
1961fbe4564SMatthias Ringwald         provisioning_device_set_input_oob_actions(0x08, 0x08);
1971fbe4564SMatthias Ringwald         perform_crypto_operations();
1981fbe4564SMatthias Ringwald     }
1991fbe4564SMatthias Ringwald };
2001fbe4564SMatthias Ringwald 
2011fbe4564SMatthias Ringwald uint8_t prov_invite[] = { 0x00, 0x00 };
2021fbe4564SMatthias Ringwald uint8_t prov_capabilities[] = { 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, };
2031fbe4564SMatthias Ringwald uint8_t prov_start[] = { 0x02, 0x00, 0x00, 0x02, 0x00, 0x01 };
2041fbe4564SMatthias Ringwald uint8_t prov_public_key[] = { 0x03,
205b084b67cSMatthias Ringwald                               0x8E, 0x9D, 0xEE, 0x76, 0x17, 0x67, 0x4A, 0xCD, 0xBE, 0xA5, 0x4D, 0xCD, 0xAB, 0x7E, 0xA3, 0x83,
206b084b67cSMatthias Ringwald                               0x26, 0xF6, 0x87, 0x22, 0x7F, 0x97, 0xE7, 0xC4, 0xEE, 0xF5, 0x2F, 0x7C, 0x80, 0x5A, 0xEB, 0x2A,
207b084b67cSMatthias Ringwald                               0x59, 0x46, 0x99, 0xDF, 0x60, 0x54, 0x53, 0x47, 0x48, 0xF8, 0xA1, 0x99, 0xF0, 0x02, 0xE7, 0x23,
208b084b67cSMatthias Ringwald                               0x2C, 0x52, 0x9C, 0xBA, 0x0F, 0x54, 0x94, 0x1F, 0xE4, 0xB7, 0x02, 0x89, 0x9E, 0x03, 0xFA, 0x43 };
209b084b67cSMatthias Ringwald uint8_t prov_confirm[] = { 0x05,
210b084b67cSMatthias Ringwald                            0x5F, 0xDE, 0x98, 0x35, 0x7F, 0x0B, 0xA2, 0xB2, 0x94, 0x72, 0x03, 0xD6, 0x82, 0x57, 0xF0, 0x6E };
211b084b67cSMatthias Ringwald uint8_t prov_random[]  = { 0x06, 0xC2, 0xE1, 0xF1, 0xF9, 0x7D, 0x3F, 0x9E, 0xCF, 0xE6, 0x73, 0xB8, 0x5C, 0x2E, 0x97, 0x4A, 0x25, };
2121fbe4564SMatthias Ringwald uint8_t prov_data[] = {
2131fbe4564SMatthias Ringwald     0x07,
2141fbe4564SMatthias Ringwald     0x85, 0x66, 0xac, 0x46, 0x37, 0x34, 0x86, 0xe1, 0x3e, 0x4c, 0x13, 0x52, 0xd0, 0x6d, 0x34, 0x7d,
2151fbe4564SMatthias Ringwald     0xce, 0xf1, 0xd1, 0x7d, 0xbd, 0xbe, 0xcc, 0x99, 0xc3,
2161fbe4564SMatthias Ringwald     0x93, 0x87, 0xfc, 0xb0, 0x72, 0x0f, 0xd8, 0x8d };
2171fbe4564SMatthias Ringwald uint8_t prov_complete[] = { 0x08, };
2181fbe4564SMatthias Ringwald 
TEST(Provisioning,Prov1)2191fbe4564SMatthias Ringwald TEST(Provisioning, Prov1){
2201fbe4564SMatthias Ringwald     // send prov inviate
2211fbe4564SMatthias Ringwald     send_prov_pdu(prov_invite, sizeof(prov_invite));
2221fbe4564SMatthias Ringwald     // check for prov cap
223b31f07b7SMatthias Ringwald     CHECK_EQUAL_ARRAY("prov_capabilities", prov_capabilities, pdu_data, sizeof(prov_capabilities));
2241fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2251fbe4564SMatthias Ringwald     // send prov start
2261fbe4564SMatthias Ringwald     send_prov_pdu(prov_start, sizeof(prov_start));
2271fbe4564SMatthias Ringwald     // send public key
2281fbe4564SMatthias Ringwald     send_prov_pdu(prov_public_key, sizeof(prov_public_key));
2291fbe4564SMatthias Ringwald     // check for public key
230b31f07b7SMatthias Ringwald     CHECK_EQUAL_ARRAY("prov_public_key", prov_public_key, pdu_data, sizeof(prov_public_key));
2311fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2321fbe4564SMatthias Ringwald     // send prov confirm
2331fbe4564SMatthias Ringwald     send_prov_pdu(prov_confirm, sizeof(prov_confirm));
2341fbe4564SMatthias Ringwald     // check for prov confirm
235b31f07b7SMatthias Ringwald     CHECK_EQUAL_ARRAY("prov_confirm", prov_confirm, pdu_data, sizeof(prov_confirm));
2361fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2371fbe4564SMatthias Ringwald     // send prov random
2381fbe4564SMatthias Ringwald     send_prov_pdu(prov_random, sizeof(prov_random));
2391fbe4564SMatthias Ringwald     // check for prov random
240b31f07b7SMatthias Ringwald     CHECK_EQUAL_ARRAY("prov_random", prov_random, pdu_data, sizeof(prov_random));
2411fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2421fbe4564SMatthias Ringwald     // send prov data
2431fbe4564SMatthias Ringwald     send_prov_pdu(prov_data, sizeof(prov_data));
2441fbe4564SMatthias Ringwald     // check prov complete
245b31f07b7SMatthias Ringwald     CHECK_EQUAL_ARRAY("prov_complete", prov_complete, pdu_data, sizeof(prov_complete));
2461fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2471fbe4564SMatthias Ringwald }
2481fbe4564SMatthias Ringwald 
main(int argc,const char * argv[])2491fbe4564SMatthias Ringwald int main (int argc, const char * argv[]){
25031437b52SMatthias Ringwald     // log into file using HCI_DUMP_PACKETLOGGER format
25131437b52SMatthias Ringwald     const char * log_path = "hci_dump.pklg";
25231437b52SMatthias Ringwald     hci_dump_posix_fs_open(log_path, HCI_DUMP_PACKETLOGGER);
25331437b52SMatthias Ringwald     hci_dump_init(hci_dump_posix_fs_get_instance());
25431437b52SMatthias Ringwald     printf("Packet Log: %s\n", log_path);
25531437b52SMatthias Ringwald 
2561fbe4564SMatthias Ringwald     return CommandLineTestRunner::RunAllTests(argc, argv);
2571fbe4564SMatthias Ringwald }
258