xref: /btstack/test/mesh/provisioning_provisioner_test.cpp (revision cd5f23a3250874824c01a2b3326a9522fea3f99f)
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