1*1fbe4564SMatthias Ringwald /* 2*1fbe4564SMatthias Ringwald * Copyright (C) 2017 BlueKitchen GmbH 3*1fbe4564SMatthias Ringwald * 4*1fbe4564SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*1fbe4564SMatthias Ringwald * modification, are permitted provided that the following conditions 6*1fbe4564SMatthias Ringwald * are met: 7*1fbe4564SMatthias Ringwald * 8*1fbe4564SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*1fbe4564SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*1fbe4564SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*1fbe4564SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*1fbe4564SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*1fbe4564SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*1fbe4564SMatthias Ringwald * contributors may be used to endorse or promote products derived 15*1fbe4564SMatthias Ringwald * from this software without specific prior written permission. 16*1fbe4564SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*1fbe4564SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*1fbe4564SMatthias Ringwald * monetary gain. 19*1fbe4564SMatthias Ringwald * 20*1fbe4564SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*1fbe4564SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*1fbe4564SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*1fbe4564SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*1fbe4564SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*1fbe4564SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*1fbe4564SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*1fbe4564SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*1fbe4564SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*1fbe4564SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*1fbe4564SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*1fbe4564SMatthias Ringwald * SUCH DAMAGE. 32*1fbe4564SMatthias Ringwald * 33*1fbe4564SMatthias Ringwald * Please inquire about commercial licensing options at 34*1fbe4564SMatthias Ringwald * [email protected] 35*1fbe4564SMatthias Ringwald * 36*1fbe4564SMatthias Ringwald */ 37*1fbe4564SMatthias Ringwald 38*1fbe4564SMatthias Ringwald #include <stdint.h> 39*1fbe4564SMatthias Ringwald #include <stdio.h> 40*1fbe4564SMatthias Ringwald #include <stdlib.h> 41*1fbe4564SMatthias Ringwald #include <string.h> 42*1fbe4564SMatthias Ringwald #include "ble/mesh/pb_adv.h" 43*1fbe4564SMatthias Ringwald #include "provisioning_device.h" 44*1fbe4564SMatthias Ringwald #include "btstack.h" 45*1fbe4564SMatthias Ringwald 46*1fbe4564SMatthias Ringwald #include "CppUTest/TestHarness.h" 47*1fbe4564SMatthias Ringwald #include "CppUTest/CommandLineTestRunner.h" 48*1fbe4564SMatthias Ringwald 49*1fbe4564SMatthias Ringwald static void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){ 50*1fbe4564SMatthias Ringwald int i; 51*1fbe4564SMatthias Ringwald for (i=0; i<size; i++){ 52*1fbe4564SMatthias Ringwald if (expected[i] != actual[i]) { 53*1fbe4564SMatthias Ringwald printf("offset %u wrong\n", i); 54*1fbe4564SMatthias Ringwald printf("expected: "); printf_hexdump(expected, size); 55*1fbe4564SMatthias Ringwald printf("actual: "); printf_hexdump(actual, size); 56*1fbe4564SMatthias Ringwald } 57*1fbe4564SMatthias Ringwald BYTES_EQUAL(expected[i], actual[i]); 58*1fbe4564SMatthias Ringwald } 59*1fbe4564SMatthias Ringwald } 60*1fbe4564SMatthias Ringwald 61*1fbe4564SMatthias Ringwald static void dump_data(uint8_t * buffer, uint16_t size){ 62*1fbe4564SMatthias Ringwald static int data_counter = 1; 63*1fbe4564SMatthias Ringwald char var_name[80]; 64*1fbe4564SMatthias Ringwald sprintf(var_name, "test_data_%02u", data_counter); 65*1fbe4564SMatthias Ringwald printf("uint8_t %s[] = { ", var_name); 66*1fbe4564SMatthias Ringwald for (int i = 0; i < size ; i++){ 67*1fbe4564SMatthias Ringwald if ((i % 16) == 0) printf("\n "); 68*1fbe4564SMatthias Ringwald printf ("0x%02x, ", buffer[i]); 69*1fbe4564SMatthias Ringwald } 70*1fbe4564SMatthias Ringwald printf("};\n"); 71*1fbe4564SMatthias Ringwald data_counter++; 72*1fbe4564SMatthias Ringwald } 73*1fbe4564SMatthias Ringwald 74*1fbe4564SMatthias Ringwald static int parse_hex(uint8_t * buffer, const char * hex_string){ 75*1fbe4564SMatthias Ringwald int len = 0; 76*1fbe4564SMatthias Ringwald while (*hex_string){ 77*1fbe4564SMatthias Ringwald if (*hex_string == ' '){ 78*1fbe4564SMatthias Ringwald hex_string++; 79*1fbe4564SMatthias Ringwald continue; 80*1fbe4564SMatthias Ringwald } 81*1fbe4564SMatthias Ringwald int high_nibble = nibble_for_char(*hex_string++); 82*1fbe4564SMatthias Ringwald int low_nibble = nibble_for_char(*hex_string++); 83*1fbe4564SMatthias Ringwald *buffer++ = (high_nibble << 4) | low_nibble; 84*1fbe4564SMatthias Ringwald len++; 85*1fbe4564SMatthias Ringwald } 86*1fbe4564SMatthias Ringwald return len; 87*1fbe4564SMatthias Ringwald } 88*1fbe4564SMatthias Ringwald 89*1fbe4564SMatthias Ringwald // returns if anything was done 90*1fbe4564SMatthias Ringwald extern "C" int mock_process_hci_cmd(void); 91*1fbe4564SMatthias Ringwald 92*1fbe4564SMatthias Ringwald const static uint8_t device_uuid[] = { 0x00, 0x1B, 0xDC, 0x08, 0x10, 0x21, 0x0B, 0x0E, 0x0A, 0x0C, 0x00, 0x0B, 0x0E, 0x0A, 0x0C, 0x00 }; 93*1fbe4564SMatthias Ringwald 94*1fbe4564SMatthias Ringwald // pb-adv mock for testing 95*1fbe4564SMatthias Ringwald 96*1fbe4564SMatthias Ringwald static btstack_packet_handler_t pb_adv_packet_handler; 97*1fbe4564SMatthias Ringwald 98*1fbe4564SMatthias Ringwald static uint8_t * pdu_data; 99*1fbe4564SMatthias Ringwald static uint16_t pdu_size; 100*1fbe4564SMatthias Ringwald 101*1fbe4564SMatthias Ringwald /** 102*1fbe4564SMatthias Ringwald * Initialize Provisioning Bearer using Advertisement Bearer 103*1fbe4564SMatthias Ringwald * @param DeviceUUID 104*1fbe4564SMatthias Ringwald */ 105*1fbe4564SMatthias Ringwald void pb_adv_init(const uint8_t * device_uuid){ 106*1fbe4564SMatthias Ringwald printf("pb_adv_init\n"); 107*1fbe4564SMatthias Ringwald } 108*1fbe4564SMatthias Ringwald 109*1fbe4564SMatthias Ringwald void pb_adv_close_link(uint16_t pb_adv_cid, uint8_t reason){ 110*1fbe4564SMatthias Ringwald } 111*1fbe4564SMatthias Ringwald 112*1fbe4564SMatthias Ringwald /** 113*1fbe4564SMatthias Ringwald * Register listener for Provisioning PDUs and MESH_PBV_ADV_SEND_COMPLETE 114*1fbe4564SMatthias Ringwald */ 115*1fbe4564SMatthias Ringwald void pb_adv_register_packet_handler(btstack_packet_handler_t packet_handler){ 116*1fbe4564SMatthias Ringwald pb_adv_packet_handler = packet_handler; 117*1fbe4564SMatthias Ringwald } 118*1fbe4564SMatthias Ringwald 119*1fbe4564SMatthias Ringwald /** 120*1fbe4564SMatthias Ringwald * Send Provisioning PDU 121*1fbe4564SMatthias Ringwald */ 122*1fbe4564SMatthias Ringwald void pb_adv_send_pdu(const uint8_t * pdu, uint16_t size){ 123*1fbe4564SMatthias Ringwald pdu_data = (uint8_t*) pdu; 124*1fbe4564SMatthias Ringwald pdu_size = size; 125*1fbe4564SMatthias Ringwald // dump_data((uint8_t*)pdu,size); 126*1fbe4564SMatthias Ringwald // printf_hexdump(pdu, size); 127*1fbe4564SMatthias Ringwald } 128*1fbe4564SMatthias Ringwald 129*1fbe4564SMatthias Ringwald static void perform_crypto_operations(void){ 130*1fbe4564SMatthias Ringwald int more = 1; 131*1fbe4564SMatthias Ringwald while (more){ 132*1fbe4564SMatthias Ringwald more = mock_process_hci_cmd(); 133*1fbe4564SMatthias Ringwald } 134*1fbe4564SMatthias Ringwald } 135*1fbe4564SMatthias Ringwald 136*1fbe4564SMatthias Ringwald static void send_prov_pdu(const uint8_t * packet, uint16_t size){ 137*1fbe4564SMatthias Ringwald pb_adv_packet_handler(PROVISIONING_DATA_PACKET, 0, (uint8_t*) packet, size); 138*1fbe4564SMatthias Ringwald perform_crypto_operations(); 139*1fbe4564SMatthias Ringwald } 140*1fbe4564SMatthias Ringwald 141*1fbe4564SMatthias Ringwald static void pb_adv_emit_pdu_sent(uint8_t status){ 142*1fbe4564SMatthias Ringwald uint8_t event[] = { HCI_EVENT_MESH_META, 2, MESH_PB_ADV_PDU_SENT, status}; 143*1fbe4564SMatthias Ringwald pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event)); 144*1fbe4564SMatthias Ringwald } 145*1fbe4564SMatthias Ringwald 146*1fbe4564SMatthias Ringwald static int scan_hex_byte(const char * byte_string){ 147*1fbe4564SMatthias Ringwald int upper_nibble = nibble_for_char(*byte_string++); 148*1fbe4564SMatthias Ringwald if (upper_nibble < 0) return -1; 149*1fbe4564SMatthias Ringwald int lower_nibble = nibble_for_char(*byte_string); 150*1fbe4564SMatthias Ringwald if (lower_nibble < 0) return -1; 151*1fbe4564SMatthias Ringwald return (upper_nibble << 4) | lower_nibble; 152*1fbe4564SMatthias Ringwald } 153*1fbe4564SMatthias Ringwald 154*1fbe4564SMatthias Ringwald static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){ 155*1fbe4564SMatthias Ringwald int i; 156*1fbe4564SMatthias Ringwald for (i = 0; i < len; i++) { 157*1fbe4564SMatthias Ringwald int single_byte = scan_hex_byte(string); 158*1fbe4564SMatthias Ringwald if (single_byte < 0) return 0; 159*1fbe4564SMatthias Ringwald string += 2; 160*1fbe4564SMatthias Ringwald buffer[i] = (uint8_t)single_byte; 161*1fbe4564SMatthias Ringwald // don't check seperator after last byte 162*1fbe4564SMatthias Ringwald if (i == len - 1) { 163*1fbe4564SMatthias Ringwald return 1; 164*1fbe4564SMatthias Ringwald } 165*1fbe4564SMatthias Ringwald // optional seperator 166*1fbe4564SMatthias Ringwald char separator = *string; 167*1fbe4564SMatthias Ringwald if (separator == ':' && separator == '-' && separator == ' ') { 168*1fbe4564SMatthias Ringwald string++; 169*1fbe4564SMatthias Ringwald } 170*1fbe4564SMatthias Ringwald } 171*1fbe4564SMatthias Ringwald return 1; 172*1fbe4564SMatthias Ringwald } 173*1fbe4564SMatthias Ringwald 174*1fbe4564SMatthias Ringwald static uint8_t prov_static_oob_data[16]; 175*1fbe4564SMatthias Ringwald static const char * prov_static_oob_string = "00000000000000000102030405060708"; 176*1fbe4564SMatthias Ringwald 177*1fbe4564SMatthias Ringwald TEST_GROUP(Provisioning){ 178*1fbe4564SMatthias Ringwald void setup(void){ 179*1fbe4564SMatthias Ringwald btstack_crypto_init(); 180*1fbe4564SMatthias Ringwald provisioning_device_init(device_uuid); 181*1fbe4564SMatthias Ringwald btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data); 182*1fbe4564SMatthias Ringwald provisioning_device_set_static_oob(16, prov_static_oob_data); 183*1fbe4564SMatthias Ringwald provisioning_device_set_output_oob_actions(0x08, 0x08); 184*1fbe4564SMatthias Ringwald provisioning_device_set_input_oob_actions(0x08, 0x08); 185*1fbe4564SMatthias Ringwald perform_crypto_operations(); 186*1fbe4564SMatthias Ringwald } 187*1fbe4564SMatthias Ringwald }; 188*1fbe4564SMatthias Ringwald 189*1fbe4564SMatthias Ringwald uint8_t prov_invite[] = { 0x00, 0x00 }; 190*1fbe4564SMatthias Ringwald uint8_t prov_capabilities[] = { 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, }; 191*1fbe4564SMatthias Ringwald uint8_t prov_start[] = { 0x02, 0x00, 0x00, 0x02, 0x00, 0x01 }; 192*1fbe4564SMatthias Ringwald uint8_t prov_public_key[] = { 0x03, 193*1fbe4564SMatthias Ringwald 0xf0, 0xc8, 0x63, 0xf8, 0xe5, 0x55, 0x11, 0x4b, 0xf4, 0x88, 0x2c, 0xc7, 0x87, 0xb9, 0x5c, 0x27, 194*1fbe4564SMatthias Ringwald 0x2a, 0x7f, 0xe4, 0xdc, 0xdd, 0xf1, 0x92, 0x2f, 0x4f, 0x18, 0xa4, 0x94, 0xe1, 0xc3, 0x57, 0xa1, 195*1fbe4564SMatthias Ringwald 0xa6, 0xc3, 0x2d, 0x07, 0xbe, 0xb5, 0x76, 0xab, 0x60, 0x10, 0x68, 0x06, 0x8f, 0x0a, 0x9e, 0x01, 196*1fbe4564SMatthias Ringwald 0x60, 0xc3, 0xa1, 0x41, 0x19, 0xf5, 0xd4, 0x26, 0xa7, 0x95, 0x5d, 0xa3, 0xe6, 0xed, 0x3e, 0x81, }; 197*1fbe4564SMatthias Ringwald uint8_t prov_confirm[] = { 0x05, 0x80, 0x4d, 0xdc, 0x3b, 0xba, 0x60, 0xd5, 0x93, 0x5b, 0x56, 0xef, 0xb5, 0xcb, 0x59, 0x31, 0xfa, }; 198*1fbe4564SMatthias Ringwald uint8_t prov_random[] = { 0x06, 0x9b, 0x4d, 0x39, 0xf6, 0xf7, 0xe8, 0xa1, 0x05, 0xd3, 0xfe, 0xed, 0xa5, 0xd5, 0xf3, 0xd9, 0xe4, }; 199*1fbe4564SMatthias Ringwald uint8_t prov_data[] = { 200*1fbe4564SMatthias Ringwald 0x07, 201*1fbe4564SMatthias Ringwald 0x85, 0x66, 0xac, 0x46, 0x37, 0x34, 0x86, 0xe1, 0x3e, 0x4c, 0x13, 0x52, 0xd0, 0x6d, 0x34, 0x7d, 202*1fbe4564SMatthias Ringwald 0xce, 0xf1, 0xd1, 0x7d, 0xbd, 0xbe, 0xcc, 0x99, 0xc3, 203*1fbe4564SMatthias Ringwald 0x93, 0x87, 0xfc, 0xb0, 0x72, 0x0f, 0xd8, 0x8d }; 204*1fbe4564SMatthias Ringwald uint8_t prov_complete[] = { 0x08, }; 205*1fbe4564SMatthias Ringwald 206*1fbe4564SMatthias Ringwald TEST(Provisioning, Prov1){ 207*1fbe4564SMatthias Ringwald // send prov inviate 208*1fbe4564SMatthias Ringwald send_prov_pdu(prov_invite, sizeof(prov_invite)); 209*1fbe4564SMatthias Ringwald // check for prov cap 210*1fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_capabilities, pdu_data, sizeof(prov_capabilities)); 211*1fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 212*1fbe4564SMatthias Ringwald // send prov start 213*1fbe4564SMatthias Ringwald send_prov_pdu(prov_start, sizeof(prov_start)); 214*1fbe4564SMatthias Ringwald // send public key 215*1fbe4564SMatthias Ringwald send_prov_pdu(prov_public_key, sizeof(prov_public_key)); 216*1fbe4564SMatthias Ringwald // check for public key 217*1fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_public_key, pdu_data, sizeof(prov_public_key)); 218*1fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 219*1fbe4564SMatthias Ringwald // send prov confirm 220*1fbe4564SMatthias Ringwald send_prov_pdu(prov_confirm, sizeof(prov_confirm)); 221*1fbe4564SMatthias Ringwald // check for prov confirm 222*1fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_confirm, pdu_data, sizeof(prov_confirm)); 223*1fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 224*1fbe4564SMatthias Ringwald // send prov random 225*1fbe4564SMatthias Ringwald send_prov_pdu(prov_random, sizeof(prov_random)); 226*1fbe4564SMatthias Ringwald // check for prov random 227*1fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_random, pdu_data, sizeof(prov_random)); 228*1fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 229*1fbe4564SMatthias Ringwald // send prov data 230*1fbe4564SMatthias Ringwald send_prov_pdu(prov_data, sizeof(prov_data)); 231*1fbe4564SMatthias Ringwald // check prov complete 232*1fbe4564SMatthias Ringwald CHECK_EQUAL_ARRAY(prov_complete, pdu_data, sizeof(prov_complete)); 233*1fbe4564SMatthias Ringwald pb_adv_emit_pdu_sent(0); 234*1fbe4564SMatthias Ringwald } 235*1fbe4564SMatthias Ringwald 236*1fbe4564SMatthias Ringwald int main (int argc, const char * argv[]){ 237*1fbe4564SMatthias Ringwald hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER); 238*1fbe4564SMatthias Ringwald return CommandLineTestRunner::RunAllTests(argc, argv); 239*1fbe4564SMatthias Ringwald } 240