xref: /btstack/test/mesh/provisioning_device_test.cpp (revision 77ba3d3f9fd2c90e975cda31e3c706784e95d43a)
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>
401fbe4564SMatthias Ringwald #include <stdlib.h>
411fbe4564SMatthias Ringwald #include <string.h>
42*77ba3d3fSMatthias Ringwald #include "mesh/pb_adv.h"
43*77ba3d3fSMatthias Ringwald #include "mesh/pb_gatt.h"
44870b3bb0SMilanka Ringwald #include "ble/gatt-service/mesh_provisioning_service_server.h"
45127b9cafSMilanka Ringwald #include "provisioning.h"
461fbe4564SMatthias Ringwald #include "provisioning_device.h"
471fbe4564SMatthias Ringwald #include "btstack.h"
481fbe4564SMatthias Ringwald 
491fbe4564SMatthias Ringwald #include "CppUTest/TestHarness.h"
501fbe4564SMatthias Ringwald #include "CppUTest/CommandLineTestRunner.h"
511fbe4564SMatthias Ringwald 
521fbe4564SMatthias Ringwald static void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){
531fbe4564SMatthias Ringwald     int i;
541fbe4564SMatthias Ringwald     for (i=0; i<size; i++){
551fbe4564SMatthias Ringwald         if (expected[i] != actual[i]) {
561fbe4564SMatthias Ringwald             printf("offset %u wrong\n", i);
571fbe4564SMatthias Ringwald             printf("expected: "); printf_hexdump(expected, size);
581fbe4564SMatthias Ringwald             printf("actual:   "); printf_hexdump(actual, size);
591fbe4564SMatthias Ringwald         }
601fbe4564SMatthias Ringwald         BYTES_EQUAL(expected[i], actual[i]);
611fbe4564SMatthias Ringwald     }
621fbe4564SMatthias Ringwald }
631fbe4564SMatthias Ringwald 
647dd36736SMilanka Ringwald void dump_data(uint8_t * buffer, uint16_t size){
651fbe4564SMatthias Ringwald     static int data_counter = 1;
661fbe4564SMatthias Ringwald     char var_name[80];
671fbe4564SMatthias Ringwald     sprintf(var_name, "test_data_%02u", data_counter);
681fbe4564SMatthias Ringwald     printf("uint8_t %s[] = { ", var_name);
691fbe4564SMatthias Ringwald     for (int i = 0; i < size ; i++){
701fbe4564SMatthias Ringwald         if ((i % 16) == 0) printf("\n    ");
711fbe4564SMatthias Ringwald         printf ("0x%02x, ", buffer[i]);
721fbe4564SMatthias Ringwald     }
731fbe4564SMatthias Ringwald     printf("};\n");
741fbe4564SMatthias Ringwald     data_counter++;
751fbe4564SMatthias Ringwald }
761fbe4564SMatthias Ringwald 
777dd36736SMilanka Ringwald int parse_hex(uint8_t * buffer, const char * hex_string){
781fbe4564SMatthias Ringwald     int len = 0;
791fbe4564SMatthias Ringwald     while (*hex_string){
801fbe4564SMatthias Ringwald         if (*hex_string == ' '){
811fbe4564SMatthias Ringwald             hex_string++;
821fbe4564SMatthias Ringwald             continue;
831fbe4564SMatthias Ringwald         }
841fbe4564SMatthias Ringwald         int high_nibble = nibble_for_char(*hex_string++);
851fbe4564SMatthias Ringwald         int low_nibble = nibble_for_char(*hex_string++);
861fbe4564SMatthias Ringwald         *buffer++ = (high_nibble << 4) | low_nibble;
871fbe4564SMatthias Ringwald         len++;
881fbe4564SMatthias Ringwald     }
891fbe4564SMatthias Ringwald     return len;
901fbe4564SMatthias Ringwald }
911fbe4564SMatthias Ringwald 
921fbe4564SMatthias Ringwald // returns if anything was done
931fbe4564SMatthias Ringwald extern "C" int mock_process_hci_cmd(void);
941fbe4564SMatthias Ringwald 
951fbe4564SMatthias Ringwald const static uint8_t device_uuid[] = { 0x00, 0x1B, 0xDC, 0x08, 0x10, 0x21, 0x0B, 0x0E, 0x0A, 0x0C, 0x00, 0x0B, 0x0E, 0x0A, 0x0C, 0x00 };
961fbe4564SMatthias Ringwald 
971fbe4564SMatthias Ringwald // pb-adv mock for testing
981fbe4564SMatthias Ringwald 
991fbe4564SMatthias Ringwald static btstack_packet_handler_t pb_adv_packet_handler;
1001fbe4564SMatthias Ringwald 
1011fbe4564SMatthias Ringwald static uint8_t * pdu_data;
1021fbe4564SMatthias Ringwald static uint16_t  pdu_size;
1031fbe4564SMatthias Ringwald 
1041fbe4564SMatthias Ringwald /**
1051fbe4564SMatthias Ringwald  * Initialize Provisioning Bearer using Advertisement Bearer
1061fbe4564SMatthias Ringwald  * @param DeviceUUID
1071fbe4564SMatthias Ringwald  */
108870b3bb0SMilanka Ringwald void pb_adv_init(const uint8_t * device_uuid){}
109870b3bb0SMilanka Ringwald void pb_gatt_init(const uint8_t * device_uuid){}
1101fbe4564SMatthias Ringwald 
111870b3bb0SMilanka Ringwald /**
112870b3bb0SMilanka Ringwald  * Close Link
113870b3bb0SMilanka Ringwald  * @param con_handle
114870b3bb0SMilanka Ringwald  * @param reason 0 = success, 1 = timeout, 2 = fail
115870b3bb0SMilanka Ringwald  */
116870b3bb0SMilanka Ringwald void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){}
117870b3bb0SMilanka Ringwald void pb_adv_close_link(hci_con_handle_t con_handle, uint8_t reason){}
118870b3bb0SMilanka Ringwald 
1191fbe4564SMatthias Ringwald 
1201fbe4564SMatthias Ringwald /**
1211fbe4564SMatthias Ringwald  * Register listener for Provisioning PDUs and MESH_PBV_ADV_SEND_COMPLETE
1221fbe4564SMatthias Ringwald  */
1231fbe4564SMatthias Ringwald void pb_adv_register_packet_handler(btstack_packet_handler_t packet_handler){
1241fbe4564SMatthias Ringwald     pb_adv_packet_handler = packet_handler;
1251fbe4564SMatthias Ringwald }
1261fbe4564SMatthias Ringwald 
127870b3bb0SMilanka Ringwald void pb_gatt_register_packet_handler(btstack_packet_handler_t packet_handler){
128870b3bb0SMilanka Ringwald     UNUSED(packet_handler);
129870b3bb0SMilanka Ringwald }
1301fbe4564SMatthias Ringwald /**
1311fbe4564SMatthias Ringwald  * Send Provisioning PDU
1321fbe4564SMatthias Ringwald  */
133beeedc45SMilanka Ringwald void pb_adv_send_pdu(uint16_t pb_transport_cid, const uint8_t * pdu, uint16_t size){
134beeedc45SMilanka Ringwald     UNUSED(pb_transport_cid);
1351fbe4564SMatthias Ringwald     pdu_data = (uint8_t*) pdu;
1361fbe4564SMatthias Ringwald     pdu_size = size;
1371fbe4564SMatthias Ringwald     // dump_data((uint8_t*)pdu,size);
1381fbe4564SMatthias Ringwald     // printf_hexdump(pdu, size);
1391fbe4564SMatthias Ringwald }
140870b3bb0SMilanka Ringwald void pb_gatt_send_pdu(uint16_t con_handle, const uint8_t * pdu, uint16_t pdu_size){}
1411fbe4564SMatthias Ringwald 
1421fbe4564SMatthias Ringwald static void perform_crypto_operations(void){
1431fbe4564SMatthias Ringwald     int more = 1;
1441fbe4564SMatthias Ringwald     while (more){
1451fbe4564SMatthias Ringwald         more = mock_process_hci_cmd();
1461fbe4564SMatthias Ringwald     }
1471fbe4564SMatthias Ringwald }
1481fbe4564SMatthias Ringwald 
1491fbe4564SMatthias Ringwald static void send_prov_pdu(const uint8_t * packet, uint16_t size){
1501fbe4564SMatthias Ringwald     pb_adv_packet_handler(PROVISIONING_DATA_PACKET, 0, (uint8_t*) packet, size);
1511fbe4564SMatthias Ringwald     perform_crypto_operations();
1521fbe4564SMatthias Ringwald }
1531fbe4564SMatthias Ringwald 
1541fbe4564SMatthias Ringwald static void pb_adv_emit_pdu_sent(uint8_t status){
1557bd12f9fSMilanka Ringwald     uint8_t event[] = { HCI_EVENT_MESH_META, 2, MESH_SUBEVENT_PB_TRANSPORT_PDU_SENT, status};
1561fbe4564SMatthias Ringwald     pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
1571fbe4564SMatthias Ringwald }
1581fbe4564SMatthias Ringwald 
1591fbe4564SMatthias Ringwald static int scan_hex_byte(const char * byte_string){
1601fbe4564SMatthias Ringwald     int upper_nibble = nibble_for_char(*byte_string++);
1611fbe4564SMatthias Ringwald     if (upper_nibble < 0) return -1;
1621fbe4564SMatthias Ringwald     int lower_nibble = nibble_for_char(*byte_string);
1631fbe4564SMatthias Ringwald     if (lower_nibble < 0) return -1;
1641fbe4564SMatthias Ringwald     return (upper_nibble << 4) | lower_nibble;
1651fbe4564SMatthias Ringwald }
1661fbe4564SMatthias Ringwald 
1671fbe4564SMatthias Ringwald static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){
1681fbe4564SMatthias Ringwald     int i;
1691fbe4564SMatthias Ringwald     for (i = 0; i < len; i++) {
1701fbe4564SMatthias Ringwald         int single_byte = scan_hex_byte(string);
1711fbe4564SMatthias Ringwald         if (single_byte < 0) return 0;
1721fbe4564SMatthias Ringwald         string += 2;
1731fbe4564SMatthias Ringwald         buffer[i] = (uint8_t)single_byte;
1741fbe4564SMatthias Ringwald         // don't check seperator after last byte
1751fbe4564SMatthias Ringwald         if (i == len - 1) {
1761fbe4564SMatthias Ringwald             return 1;
1771fbe4564SMatthias Ringwald         }
1781fbe4564SMatthias Ringwald         // optional seperator
1791fbe4564SMatthias Ringwald         char separator = *string;
1801fbe4564SMatthias Ringwald         if (separator == ':' && separator == '-' && separator == ' ') {
1811fbe4564SMatthias Ringwald             string++;
1821fbe4564SMatthias Ringwald         }
1831fbe4564SMatthias Ringwald     }
1841fbe4564SMatthias Ringwald     return 1;
1851fbe4564SMatthias Ringwald }
1861fbe4564SMatthias Ringwald 
187870b3bb0SMilanka Ringwald // void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){
188870b3bb0SMilanka Ringwald // }
189870b3bb0SMilanka Ringwald 
1901fbe4564SMatthias Ringwald static uint8_t      prov_static_oob_data[16];
1911fbe4564SMatthias Ringwald static const char * prov_static_oob_string = "00000000000000000102030405060708";
1921fbe4564SMatthias Ringwald 
1931fbe4564SMatthias Ringwald TEST_GROUP(Provisioning){
1941fbe4564SMatthias Ringwald     void setup(void){
1951fbe4564SMatthias Ringwald         btstack_crypto_init();
1961fbe4564SMatthias Ringwald         provisioning_device_init(device_uuid);
1971fbe4564SMatthias Ringwald         btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data);
1981fbe4564SMatthias Ringwald         provisioning_device_set_static_oob(16, prov_static_oob_data);
1991fbe4564SMatthias Ringwald         provisioning_device_set_output_oob_actions(0x08, 0x08);
2001fbe4564SMatthias Ringwald         provisioning_device_set_input_oob_actions(0x08, 0x08);
2011fbe4564SMatthias Ringwald         perform_crypto_operations();
2021fbe4564SMatthias Ringwald     }
2031fbe4564SMatthias Ringwald };
2041fbe4564SMatthias Ringwald 
2051fbe4564SMatthias Ringwald uint8_t prov_invite[] = { 0x00, 0x00 };
2061fbe4564SMatthias Ringwald uint8_t prov_capabilities[] = { 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, };
2071fbe4564SMatthias Ringwald uint8_t prov_start[] = { 0x02, 0x00, 0x00, 0x02, 0x00, 0x01 };
2081fbe4564SMatthias Ringwald uint8_t prov_public_key[] = { 0x03,
2091fbe4564SMatthias Ringwald     0xf0, 0xc8, 0x63, 0xf8, 0xe5, 0x55, 0x11, 0x4b, 0xf4, 0x88, 0x2c, 0xc7, 0x87, 0xb9, 0x5c, 0x27,
2101fbe4564SMatthias Ringwald     0x2a, 0x7f, 0xe4, 0xdc, 0xdd, 0xf1, 0x92, 0x2f, 0x4f, 0x18, 0xa4, 0x94, 0xe1, 0xc3, 0x57, 0xa1,
2111fbe4564SMatthias Ringwald     0xa6, 0xc3, 0x2d, 0x07, 0xbe, 0xb5, 0x76, 0xab, 0x60, 0x10, 0x68, 0x06, 0x8f, 0x0a, 0x9e, 0x01,
2121fbe4564SMatthias Ringwald     0x60, 0xc3, 0xa1, 0x41, 0x19, 0xf5, 0xd4, 0x26, 0xa7, 0x95, 0x5d, 0xa3, 0xe6, 0xed, 0x3e, 0x81, };
2131fbe4564SMatthias Ringwald uint8_t prov_confirm[] = { 0x05, 0x80, 0x4d, 0xdc, 0x3b, 0xba, 0x60, 0xd5, 0x93, 0x5b, 0x56, 0xef, 0xb5, 0xcb, 0x59, 0x31, 0xfa, };
2141fbe4564SMatthias Ringwald uint8_t prov_random[]  = { 0x06, 0x9b, 0x4d, 0x39, 0xf6, 0xf7, 0xe8, 0xa1, 0x05, 0xd3, 0xfe, 0xed, 0xa5, 0xd5, 0xf3, 0xd9, 0xe4, };
2151fbe4564SMatthias Ringwald uint8_t prov_data[] = {
2161fbe4564SMatthias Ringwald     0x07,
2171fbe4564SMatthias Ringwald     0x85, 0x66, 0xac, 0x46, 0x37, 0x34, 0x86, 0xe1, 0x3e, 0x4c, 0x13, 0x52, 0xd0, 0x6d, 0x34, 0x7d,
2181fbe4564SMatthias Ringwald     0xce, 0xf1, 0xd1, 0x7d, 0xbd, 0xbe, 0xcc, 0x99, 0xc3,
2191fbe4564SMatthias Ringwald     0x93, 0x87, 0xfc, 0xb0, 0x72, 0x0f, 0xd8, 0x8d };
2201fbe4564SMatthias Ringwald uint8_t prov_complete[] = { 0x08, };
2211fbe4564SMatthias Ringwald 
2221fbe4564SMatthias Ringwald TEST(Provisioning, Prov1){
2231fbe4564SMatthias Ringwald     // send prov inviate
2241fbe4564SMatthias Ringwald     send_prov_pdu(prov_invite, sizeof(prov_invite));
2251fbe4564SMatthias Ringwald     // check for prov cap
2261fbe4564SMatthias Ringwald     CHECK_EQUAL_ARRAY(prov_capabilities, pdu_data, sizeof(prov_capabilities));
2271fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2281fbe4564SMatthias Ringwald     // send prov start
2291fbe4564SMatthias Ringwald     send_prov_pdu(prov_start, sizeof(prov_start));
2301fbe4564SMatthias Ringwald     // send public key
2311fbe4564SMatthias Ringwald     send_prov_pdu(prov_public_key, sizeof(prov_public_key));
2321fbe4564SMatthias Ringwald     // check for public key
2331fbe4564SMatthias Ringwald     CHECK_EQUAL_ARRAY(prov_public_key, pdu_data, sizeof(prov_public_key));
2341fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2351fbe4564SMatthias Ringwald     // send prov confirm
2361fbe4564SMatthias Ringwald     send_prov_pdu(prov_confirm, sizeof(prov_confirm));
2371fbe4564SMatthias Ringwald     // check for prov confirm
2381fbe4564SMatthias Ringwald     CHECK_EQUAL_ARRAY(prov_confirm, pdu_data, sizeof(prov_confirm));
2391fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2401fbe4564SMatthias Ringwald     // send prov random
2411fbe4564SMatthias Ringwald     send_prov_pdu(prov_random, sizeof(prov_random));
2421fbe4564SMatthias Ringwald     // check for prov random
2431fbe4564SMatthias Ringwald     CHECK_EQUAL_ARRAY(prov_random, pdu_data, sizeof(prov_random));
2441fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2451fbe4564SMatthias Ringwald     // send prov data
2461fbe4564SMatthias Ringwald     send_prov_pdu(prov_data, sizeof(prov_data));
2471fbe4564SMatthias Ringwald     // check prov complete
2481fbe4564SMatthias Ringwald     CHECK_EQUAL_ARRAY(prov_complete, pdu_data, sizeof(prov_complete));
2491fbe4564SMatthias Ringwald     pb_adv_emit_pdu_sent(0);
2501fbe4564SMatthias Ringwald }
2511fbe4564SMatthias Ringwald 
2521fbe4564SMatthias Ringwald int main (int argc, const char * argv[]){
2531fbe4564SMatthias Ringwald     hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
2541fbe4564SMatthias Ringwald     return CommandLineTestRunner::RunAllTests(argc, argv);
2551fbe4564SMatthias Ringwald }
256