1 /* 2 * Copyright (C) 2017 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #include <stdint.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include "mesh/pb_adv.h" 43 #include "mesh/pb_gatt.h" 44 #include "ble/gatt-service/mesh_provisioning_service_server.h" 45 #include "mesh/provisioning.h" 46 #include "mesh/provisioning_provisioner.h" 47 #include "hci_dump.h" 48 #include "mock.h" 49 50 #include "CppUTest/TestHarness.h" 51 #include "CppUTest/CommandLineTestRunner.h" 52 53 static void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){ 54 int i; 55 for (i=0; i<size; i++){ 56 if (expected[i] != actual[i]) { 57 printf("offset %u wrong\n", i); 58 printf("expected: "); printf_hexdump(expected, size); 59 printf("actual: "); printf_hexdump(actual, size); 60 } 61 BYTES_EQUAL(expected[i], actual[i]); 62 } 63 } 64 65 // pb-adv mock for testing 66 67 static btstack_packet_handler_t pb_adv_packet_handler; 68 69 static uint8_t * pdu_data; 70 static uint16_t pdu_size; 71 72 static void pb_adv_emit_link_open(uint8_t status, uint16_t pb_adv_cid){ 73 uint8_t event[7] = { HCI_EVENT_MESH_META, 5, MESH_SUBEVENT_PB_TRANSPORT_LINK_OPEN, status}; 74 little_endian_store_16(event, 4, pb_adv_cid); 75 event[6] = MESH_PB_TYPE_ADV; 76 pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event)); 77 } 78 79 static void pb_adv_emit_pdu_sent(uint8_t status){ 80 uint8_t event[] = { HCI_EVENT_MESH_META, 2, MESH_SUBEVENT_PB_TRANSPORT_PDU_SENT, status}; 81 pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event)); 82 } 83 84 void pb_adv_init(void){} 85 void pb_gatt_init(void){} 86 87 void pb_adv_close_link(uint16_t pb_adv_cid, uint8_t reason){ 88 UNUSED(pb_adv_cid); 89 UNUSED(reason); 90 } 91 92 void pb_adv_register_provisioner_packet_handler(btstack_packet_handler_t packet_handler){ 93 pb_adv_packet_handler = packet_handler; 94 } 95 96 void pb_gatt_register_packet_handler(btstack_packet_handler_t packet_handler){ 97 UNUSED(packet_handler); 98 } 99 100 void pb_adv_send_pdu(uint16_t pb_transport_cid, const uint8_t * pdu, uint16_t size){ 101 UNUSED(pb_transport_cid); 102 pdu_data = (uint8_t*) pdu; 103 pdu_size = size; 104 // dump_data((uint8_t*)pdu,size); 105 // printf_hexdump(pdu, size); 106 } 107 void pb_gatt_send_pdu(uint16_t con_handle, const uint8_t * pdu, uint16_t _pdu_size){ 108 UNUSED(con_handle); 109 UNUSED(pdu); 110 UNUSED(_pdu_size); 111 } 112 113 uint16_t pb_adv_create_link(const uint8_t * device_uuid){ 114 UNUSED(device_uuid); 115 // just simluate opened 116 pb_adv_emit_link_open(0, 1); 117 return 1; 118 } 119 120 // 121 static void perform_crypto_operations(void){ 122 int more = 1; 123 while (more){ 124 more = mock_process_hci_cmd(); 125 } 126 } 127 128 static void send_prov_pdu(const uint8_t * packet, uint16_t size){ 129 pb_adv_packet_handler(PROVISIONING_DATA_PACKET, 0, (uint8_t*) packet, size); 130 perform_crypto_operations(); 131 } 132 133 134 static int scan_hex_byte(const char * byte_string){ 135 int upper_nibble = nibble_for_char(*byte_string++); 136 if (upper_nibble < 0) return -1; 137 int lower_nibble = nibble_for_char(*byte_string); 138 if (lower_nibble < 0) return -1; 139 return (upper_nibble << 4) | lower_nibble; 140 } 141 142 static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){ 143 int i; 144 for (i = 0; i < len; i++) { 145 int single_byte = scan_hex_byte(string); 146 if (single_byte < 0) return 0; 147 string += 2; 148 buffer[i] = (uint8_t)single_byte; 149 // don't check seperator after last byte 150 if (i == len - 1) { 151 return 1; 152 } 153 // optional seperator 154 char separator = *string; 155 if (separator == ':' && separator == '-' && separator == ' ') { 156 string++; 157 } 158 } 159 return 1; 160 } 161 162 static uint8_t prov_static_oob_data[16]; 163 static const char * prov_static_oob_string = "00000000000000000102030405060708"; 164 165 static void provisioning_handle_pdu(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 166 UNUSED(channel); 167 UNUSED(size); 168 if (packet_type != HCI_EVENT_PACKET) return; 169 switch(packet[0]){ 170 case HCI_EVENT_MESH_META: 171 switch(packet[2]){ 172 case MESH_SUBEVENT_PB_PROV_CAPABILITIES: 173 printf("Provisioner capabilities\n"); 174 provisioning_provisioner_select_authentication_method(1, 0, 0, 0, 0, 0); 175 break; 176 default: 177 break; 178 } 179 default: 180 break; 181 } 182 } 183 184 TEST_GROUP(Provisioning){ 185 void setup(void){ 186 mock_init(); 187 btstack_crypto_init(); 188 provisioning_provisioner_init(); 189 btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data); 190 provisioning_provisioner_register_packet_handler(&provisioning_handle_pdu); 191 // provisioning_device_set_static_oob(16, prov_static_oob_data); 192 // provisioning_device_set_output_oob_actions(0x08, 0x08); 193 // provisioning_device_set_input_oob_actions(0x08, 0x08); 194 perform_crypto_operations(); 195 } 196 }; 197 198 const static uint8_t device_uuid[] = { 0x00, 0x1B, 0xDC, 0x08, 0x10, 0x21, 0x0B, 0x0E, 0x0A, 0x0C, 0x00, 0x0B, 0x0E, 0x0A, 0x0C, 0x00 }; 199 200 uint8_t prov_invite[] = { 0x00, 0x00 }; 201 uint8_t prov_capabilities[] = { 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, }; 202 uint8_t prov_start[] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }; 203 uint8_t prov_public_key[] = { 0x03, 204 0x8E, 0x9D, 0xEE, 0x76, 0x17, 0x67, 0x4A, 0xCD, 0xBE, 0xA5, 0x4D, 0xCD, 0xAB, 0x7E, 0xA3, 0x83, 205 0x26, 0xF6, 0x87, 0x22, 0x7F, 0x97, 0xE7, 0xC4, 0xEE, 0xF5, 0x2F, 0x7C, 0x80, 0x5A, 0xEB, 0x2A, 206 0x59, 0x46, 0x99, 0xDF, 0x60, 0x54, 0x53, 0x47, 0x48, 0xF8, 0xA1, 0x99, 0xF0, 0x02, 0xE7, 0x23, 207 0x2C, 0x52, 0x9C, 0xBA, 0x0F, 0x54, 0x94, 0x1F, 0xE4, 0xB7, 0x02, 0x89, 0x9E, 0x03, 0xFA, 0x43 }; 208 uint8_t prov_confirm[] = { 0x05, 0xF3, 0x73, 0xAB, 0xD8, 0xA6, 0x51, 0xD4, 0x18, 0x78, 0x47, 0xBA, 0xD8, 0x07, 0x6E, 0x09, 0x05 }; 209 uint8_t prov_random[] = { 0x06, 0xED, 0x77, 0xBA, 0x5D, 0x2F, 0x16, 0x0B, 0x84, 0xC2, 0xE1, 0xF1, 0xF9, 0x7D, 0x3F, 0x9E, 0xCF }; 210 uint8_t prov_data[] = { 211 0x07, 0x89, 0x8B, 0xBF, 0x53, 0xDC, 0xA6, 0xD8, 0x55, 0x1B, 0x9A, 0xA9, 0x57, 0x8C, 0x8E, 0xAC, 0x25, 0x13, 0x80, 0xC3, 212 0x8B, 0xA2, 0xF8, 0xAA, 0x13, 0xAF, 0x60, 0x1A, 0x5B, 0x12, 0xE9, 0xD5, 0x5F, 213 }; 214 uint8_t prov_complete[] = { 0x08, }; 215 216 static void expect_packet(const char * packet_name, const uint8_t * packet_data, uint16_t packet_len){ 217 printf("Expect '%s'\n", packet_name); 218 CHECK(pdu_data != NULL); 219 CHECK_EQUAL_ARRAY((uint8_t*)packet_data, pdu_data, packet_len); 220 } 221 222 #define EXPECT_PACKET(packet) expect_packet(#packet, packet, sizeof(packet)) 223 224 TEST(Provisioning, Prov1){ 225 // simulate unprovisioned device beacon 226 provisioning_provisioner_start_provisioning(device_uuid); 227 // wait for prov invite 228 EXPECT_PACKET(prov_invite); 229 pb_adv_emit_pdu_sent(0); 230 // send capabilities 231 send_prov_pdu(prov_capabilities, sizeof(prov_capabilities)); 232 // wait for start 233 EXPECT_PACKET(prov_start); 234 pb_adv_emit_pdu_sent(0); 235 // wait for public key 236 EXPECT_PACKET(prov_public_key); 237 pb_adv_emit_pdu_sent(0); 238 // send public key 239 send_prov_pdu(prov_public_key, sizeof(prov_public_key)); 240 // wait for confirm 241 EXPECT_PACKET(prov_confirm); 242 pb_adv_emit_pdu_sent(0); 243 // send prov confirm 244 send_prov_pdu(prov_confirm, sizeof(prov_confirm)); 245 // wait for random 246 CHECK_EQUAL_ARRAY(prov_random, pdu_data, sizeof(prov_random)); 247 pb_adv_emit_pdu_sent(0); 248 // send prov random 249 send_prov_pdu(prov_random, sizeof(prov_random)); 250 // wait for prov data 251 EXPECT_PACKET(prov_data); 252 pb_adv_emit_pdu_sent(0); 253 // send prov complete 254 send_prov_pdu(prov_complete, sizeof(prov_complete)); 255 } 256 257 int main (int argc, const char * argv[]){ 258 hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER); 259 return CommandLineTestRunner::RunAllTests(argc, argv); 260 } 261