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> 42f4854a5eSMatthias Ringwald #include "ble/gatt-service/mesh_provisioning_service_server.h" 43f4854a5eSMatthias Ringwald #include "hci_dump.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 531fbe4564SMatthias Ringwald static void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){ 541fbe4564SMatthias Ringwald int i; 551fbe4564SMatthias Ringwald for (i=0; i<size; i++){ 561fbe4564SMatthias Ringwald if (expected[i] != actual[i]) { 571fbe4564SMatthias Ringwald printf("offset %u wrong\n", i); 581fbe4564SMatthias Ringwald printf("expected: "); printf_hexdump(expected, size); 591fbe4564SMatthias Ringwald printf("actual: "); printf_hexdump(actual, size); 601fbe4564SMatthias Ringwald } 611fbe4564SMatthias Ringwald BYTES_EQUAL(expected[i], actual[i]); 621fbe4564SMatthias Ringwald } 631fbe4564SMatthias Ringwald } 641fbe4564SMatthias Ringwald 657dd36736SMilanka Ringwald void dump_data(uint8_t * buffer, uint16_t size){ 661fbe4564SMatthias Ringwald static int data_counter = 1; 671fbe4564SMatthias Ringwald char var_name[80]; 681fbe4564SMatthias Ringwald sprintf(var_name, "test_data_%02u", data_counter); 691fbe4564SMatthias Ringwald printf("uint8_t %s[] = { ", var_name); 701fbe4564SMatthias Ringwald for (int i = 0; i < size ; i++){ 711fbe4564SMatthias Ringwald if ((i % 16) == 0) printf("\n "); 721fbe4564SMatthias Ringwald printf ("0x%02x, ", buffer[i]); 731fbe4564SMatthias Ringwald } 741fbe4564SMatthias Ringwald printf("};\n"); 751fbe4564SMatthias Ringwald data_counter++; 761fbe4564SMatthias Ringwald } 771fbe4564SMatthias Ringwald 787dd36736SMilanka Ringwald int parse_hex(uint8_t * buffer, const char * hex_string){ 791fbe4564SMatthias Ringwald int len = 0; 801fbe4564SMatthias Ringwald while (*hex_string){ 811fbe4564SMatthias Ringwald if (*hex_string == ' '){ 821fbe4564SMatthias Ringwald hex_string++; 831fbe4564SMatthias Ringwald continue; 841fbe4564SMatthias Ringwald } 851fbe4564SMatthias Ringwald int high_nibble = nibble_for_char(*hex_string++); 861fbe4564SMatthias Ringwald int low_nibble = nibble_for_char(*hex_string++); 871fbe4564SMatthias Ringwald *buffer++ = (high_nibble << 4) | low_nibble; 881fbe4564SMatthias Ringwald len++; 891fbe4564SMatthias Ringwald } 901fbe4564SMatthias Ringwald return len; 911fbe4564SMatthias Ringwald } 921fbe4564SMatthias Ringwald 931fbe4564SMatthias Ringwald // returns if anything was done 941fbe4564SMatthias Ringwald extern "C" int mock_process_hci_cmd(void); 951fbe4564SMatthias Ringwald 961fbe4564SMatthias Ringwald const static uint8_t device_uuid[] = { 0x00, 0x1B, 0xDC, 0x08, 0x10, 0x21, 0x0B, 0x0E, 0x0A, 0x0C, 0x00, 0x0B, 0x0E, 0x0A, 0x0C, 0x00 }; 971fbe4564SMatthias Ringwald 981fbe4564SMatthias Ringwald // pb-adv mock for testing 991fbe4564SMatthias Ringwald 1001fbe4564SMatthias Ringwald static btstack_packet_handler_t pb_adv_packet_handler; 1011fbe4564SMatthias Ringwald 1021fbe4564SMatthias Ringwald static uint8_t * pdu_data; 1031fbe4564SMatthias Ringwald static uint16_t pdu_size; 1041fbe4564SMatthias Ringwald 1051fbe4564SMatthias Ringwald /** 1061fbe4564SMatthias Ringwald * Initialize Provisioning Bearer using Advertisement Bearer 1071fbe4564SMatthias Ringwald * @param DeviceUUID 1081fbe4564SMatthias Ringwald */ 1098936a143SMatthias Ringwald void pb_adv_init(void){} 11054274a76SMatthias Ringwald void pb_gatt_init(void){} 1111fbe4564SMatthias Ringwald 112870b3bb0SMilanka Ringwald /** 113870b3bb0SMilanka Ringwald * Close Link 114870b3bb0SMilanka Ringwald * @param con_handle 115870b3bb0SMilanka Ringwald * @param reason 0 = success, 1 = timeout, 2 = fail 116870b3bb0SMilanka Ringwald */ 117870b3bb0SMilanka Ringwald void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){} 118870b3bb0SMilanka Ringwald void pb_adv_close_link(hci_con_handle_t con_handle, uint8_t reason){} 119870b3bb0SMilanka Ringwald 1201fbe4564SMatthias Ringwald 1211fbe4564SMatthias Ringwald /** 1221fbe4564SMatthias Ringwald * Register listener for Provisioning PDUs and MESH_PBV_ADV_SEND_COMPLETE 1231fbe4564SMatthias Ringwald */ 124*fe430865SMatthias Ringwald void pb_adv_register_device_packet_handler(btstack_packet_handler_t packet_handler){ 1251fbe4564SMatthias Ringwald pb_adv_packet_handler = packet_handler; 1261fbe4564SMatthias Ringwald } 1271fbe4564SMatthias Ringwald 128870b3bb0SMilanka Ringwald void pb_gatt_register_packet_handler(btstack_packet_handler_t packet_handler){ 129870b3bb0SMilanka Ringwald UNUSED(packet_handler); 130870b3bb0SMilanka Ringwald } 1311fbe4564SMatthias Ringwald /** 1321fbe4564SMatthias Ringwald * Send Provisioning PDU 1331fbe4564SMatthias Ringwald */ 134beeedc45SMilanka Ringwald void pb_adv_send_pdu(uint16_t pb_transport_cid, const uint8_t * pdu, uint16_t size){ 135beeedc45SMilanka Ringwald UNUSED(pb_transport_cid); 1361fbe4564SMatthias Ringwald pdu_data = (uint8_t*) pdu; 1371fbe4564SMatthias Ringwald pdu_size = size; 1381fbe4564SMatthias Ringwald // dump_data((uint8_t*)pdu,size); 1391fbe4564SMatthias Ringwald // printf_hexdump(pdu, size); 1401fbe4564SMatthias Ringwald } 141870b3bb0SMilanka Ringwald void pb_gatt_send_pdu(uint16_t con_handle, const uint8_t * pdu, uint16_t pdu_size){} 1421fbe4564SMatthias Ringwald 1430500a934SMatthias Ringwald uint16_t mesh_network_key_get_free_index(void){ 1440500a934SMatthias Ringwald return 0; 1450500a934SMatthias Ringwald } 146d6915e6fSMatthias Ringwald 1472d97f8bbSMatthias Ringwald static mesh_network_key_t network_key; 148d6915e6fSMatthias Ringwald extern "C" mesh_network_key_t * btstack_memory_mesh_network_key_get(void){ 1492d97f8bbSMatthias Ringwald return &network_key; 1502d97f8bbSMatthias Ringwald } 1512d97f8bbSMatthias Ringwald 1521fbe4564SMatthias Ringwald static void perform_crypto_operations(void){ 1531fbe4564SMatthias Ringwald int more = 1; 1541fbe4564SMatthias Ringwald while (more){ 1551fbe4564SMatthias Ringwald more = mock_process_hci_cmd(); 1561fbe4564SMatthias Ringwald } 1571fbe4564SMatthias Ringwald } 1581fbe4564SMatthias Ringwald 1591fbe4564SMatthias Ringwald static void send_prov_pdu(const uint8_t * packet, uint16_t size){ 1601fbe4564SMatthias Ringwald pb_adv_packet_handler(PROVISIONING_DATA_PACKET, 0, (uint8_t*) packet, size); 1611fbe4564SMatthias Ringwald perform_crypto_operations(); 1621fbe4564SMatthias Ringwald } 1631fbe4564SMatthias Ringwald 1641fbe4564SMatthias Ringwald static void pb_adv_emit_pdu_sent(uint8_t status){ 1657bd12f9fSMilanka Ringwald uint8_t event[] = { HCI_EVENT_MESH_META, 2, MESH_SUBEVENT_PB_TRANSPORT_PDU_SENT, status}; 1661fbe4564SMatthias Ringwald pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event)); 1671fbe4564SMatthias Ringwald } 1681fbe4564SMatthias Ringwald 1691fbe4564SMatthias Ringwald static int scan_hex_byte(const char * byte_string){ 1701fbe4564SMatthias Ringwald int upper_nibble = nibble_for_char(*byte_string++); 1711fbe4564SMatthias Ringwald if (upper_nibble < 0) return -1; 1721fbe4564SMatthias Ringwald int lower_nibble = nibble_for_char(*byte_string); 1731fbe4564SMatthias Ringwald if (lower_nibble < 0) return -1; 1741fbe4564SMatthias Ringwald return (upper_nibble << 4) | lower_nibble; 1751fbe4564SMatthias Ringwald } 1761fbe4564SMatthias Ringwald 1771fbe4564SMatthias Ringwald static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){ 1781fbe4564SMatthias Ringwald int i; 1791fbe4564SMatthias Ringwald for (i = 0; i < len; i++) { 1801fbe4564SMatthias Ringwald int single_byte = scan_hex_byte(string); 1811fbe4564SMatthias Ringwald if (single_byte < 0) return 0; 1821fbe4564SMatthias Ringwald string += 2; 1831fbe4564SMatthias Ringwald buffer[i] = (uint8_t)single_byte; 1841fbe4564SMatthias Ringwald // don't check seperator after last byte 1851fbe4564SMatthias Ringwald if (i == len - 1) { 1861fbe4564SMatthias Ringwald return 1; 1871fbe4564SMatthias Ringwald } 1881fbe4564SMatthias Ringwald // optional seperator 1891fbe4564SMatthias Ringwald char separator = *string; 1901fbe4564SMatthias Ringwald if (separator == ':' && separator == '-' && separator == ' ') { 1911fbe4564SMatthias Ringwald string++; 1921fbe4564SMatthias Ringwald } 1931fbe4564SMatthias Ringwald } 1941fbe4564SMatthias Ringwald return 1; 1951fbe4564SMatthias Ringwald } 1961fbe4564SMatthias Ringwald 197870b3bb0SMilanka Ringwald // void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){ 198870b3bb0SMilanka Ringwald // } 199870b3bb0SMilanka Ringwald 2001fbe4564SMatthias Ringwald static uint8_t prov_static_oob_data[16]; 2011fbe4564SMatthias Ringwald static const char * prov_static_oob_string = "00000000000000000102030405060708"; 2021fbe4564SMatthias Ringwald 2031fbe4564SMatthias Ringwald TEST_GROUP(Provisioning){ 2041fbe4564SMatthias Ringwald void setup(void){ 2051fbe4564SMatthias Ringwald btstack_crypto_init(); 2068936a143SMatthias Ringwald provisioning_device_init(); 2078936a143SMatthias Ringwald mesh_node_set_device_uuid(device_uuid); 2081fbe4564SMatthias Ringwald btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data); 2091fbe4564SMatthias Ringwald provisioning_device_set_static_oob(16, prov_static_oob_data); 2101fbe4564SMatthias Ringwald provisioning_device_set_output_oob_actions(0x08, 0x08); 2111fbe4564SMatthias Ringwald provisioning_device_set_input_oob_actions(0x08, 0x08); 2121fbe4564SMatthias Ringwald perform_crypto_operations(); 2131fbe4564SMatthias Ringwald } 2141fbe4564SMatthias Ringwald }; 2151fbe4564SMatthias Ringwald 2161fbe4564SMatthias Ringwald uint8_t prov_invite[] = { 0x00, 0x00 }; 2171fbe4564SMatthias Ringwald uint8_t prov_capabilities[] = { 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, }; 2181fbe4564SMatthias Ringwald uint8_t prov_start[] = { 0x02, 0x00, 0x00, 0x02, 0x00, 0x01 }; 2191fbe4564SMatthias Ringwald uint8_t prov_public_key[] = { 0x03, 2201fbe4564SMatthias Ringwald 0xf0, 0xc8, 0x63, 0xf8, 0xe5, 0x55, 0x11, 0x4b, 0xf4, 0x88, 0x2c, 0xc7, 0x87, 0xb9, 0x5c, 0x27, 2211fbe4564SMatthias Ringwald 0x2a, 0x7f, 0xe4, 0xdc, 0xdd, 0xf1, 0x92, 0x2f, 0x4f, 0x18, 0xa4, 0x94, 0xe1, 0xc3, 0x57, 0xa1, 2221fbe4564SMatthias Ringwald 0xa6, 0xc3, 0x2d, 0x07, 0xbe, 0xb5, 0x76, 0xab, 0x60, 0x10, 0x68, 0x06, 0x8f, 0x0a, 0x9e, 0x01, 2231fbe4564SMatthias Ringwald 0x60, 0xc3, 0xa1, 0x41, 0x19, 0xf5, 0xd4, 0x26, 0xa7, 0x95, 0x5d, 0xa3, 0xe6, 0xed, 0x3e, 0x81, }; 2241fbe4564SMatthias Ringwald uint8_t prov_confirm[] = { 0x05, 0x80, 0x4d, 0xdc, 0x3b, 0xba, 0x60, 0xd5, 0x93, 0x5b, 0x56, 0xef, 0xb5, 0xcb, 0x59, 0x31, 0xfa, }; 2251fbe4564SMatthias Ringwald uint8_t prov_random[] = { 0x06, 0x9b, 0x4d, 0x39, 0xf6, 0xf7, 0xe8, 0xa1, 0x05, 0xd3, 0xfe, 0xed, 0xa5, 0xd5, 0xf3, 0xd9, 0xe4, }; 2261fbe4564SMatthias Ringwald uint8_t prov_data[] = { 2271fbe4564SMatthias Ringwald 0x07, 2281fbe4564SMatthias Ringwald 0x85, 0x66, 0xac, 0x46, 0x37, 0x34, 0x86, 0xe1, 0x3e, 0x4c, 0x13, 0x52, 0xd0, 0x6d, 0x34, 0x7d, 2291fbe4564SMatthias Ringwald 0xce, 0xf1, 0xd1, 0x7d, 0xbd, 0xbe, 0xcc, 0x99, 0xc3, 2301fbe4564SMatthias Ringwald 0x93, 0x87, 0xfc, 0xb0, 0x72, 0x0f, 0xd8, 0x8d }; 2311fbe4564SMatthias Ringwald uint8_t prov_complete[] = { 0x08, }; 2321fbe4564SMatthias Ringwald 2331fbe4564SMatthias Ringwald TEST(Provisioning, Prov1){ 2341fbe4564SMatthias Ringwald // send prov inviate 2351fbe4564SMatthias Ringwald send_prov_pdu(prov_invite, sizeof(prov_invite)); 2361fbe4564SMatthias Ringwald // check for prov cap 2371fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_capabilities, pdu_data, sizeof(prov_capabilities)); 2381fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 2391fbe4564SMatthias Ringwald // send prov start 2401fbe4564SMatthias Ringwald send_prov_pdu(prov_start, sizeof(prov_start)); 2411fbe4564SMatthias Ringwald // send public key 2421fbe4564SMatthias Ringwald send_prov_pdu(prov_public_key, sizeof(prov_public_key)); 2431fbe4564SMatthias Ringwald // check for public key 2441fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_public_key, pdu_data, sizeof(prov_public_key)); 2451fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 2461fbe4564SMatthias Ringwald // send prov confirm 2471fbe4564SMatthias Ringwald send_prov_pdu(prov_confirm, sizeof(prov_confirm)); 2481fbe4564SMatthias Ringwald // check for prov confirm 2491fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_confirm, pdu_data, sizeof(prov_confirm)); 2501fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 2511fbe4564SMatthias Ringwald // send prov random 2521fbe4564SMatthias Ringwald send_prov_pdu(prov_random, sizeof(prov_random)); 2531fbe4564SMatthias Ringwald // check for prov random 2541fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_random, pdu_data, sizeof(prov_random)); 2551fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 2561fbe4564SMatthias Ringwald // send prov data 2571fbe4564SMatthias Ringwald send_prov_pdu(prov_data, sizeof(prov_data)); 2581fbe4564SMatthias Ringwald // check prov complete 2591fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_complete, pdu_data, sizeof(prov_complete)); 2601fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 2611fbe4564SMatthias Ringwald } 2621fbe4564SMatthias Ringwald 2631fbe4564SMatthias Ringwald int main (int argc, const char * argv[]){ 2641fbe4564SMatthias Ringwald hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER); 2651fbe4564SMatthias Ringwald return CommandLineTestRunner::RunAllTests(argc, argv); 2661fbe4564SMatthias Ringwald } 267