xref: /btstack/test/mesh/provisioning_provisioner_test.cpp (revision beeedc4565a23c6396505b62d2169f287210174d)
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 "ble/mesh/pb_adv.h"
43 #include "provisioning_provisioner.h"
44 #include "btstack.h"
45 
46 #include "CppUTest/TestHarness.h"
47 #include "CppUTest/CommandLineTestRunner.h"
48 
49 static void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){
50     int i;
51     for (i=0; i<size; i++){
52         if (expected[i] != actual[i]) {
53             printf("offset %u wrong\n", i);
54             printf("expected: "); printf_hexdump(expected, size);
55             printf("actual:   "); printf_hexdump(actual, size);
56         }
57         BYTES_EQUAL(expected[i], actual[i]);
58     }
59 }
60 
61 static void dump_data(uint8_t * buffer, uint16_t size){
62     static int data_counter = 1;
63     char var_name[80];
64     sprintf(var_name, "test_data_%02u", data_counter);
65     printf("uint8_t %s[] = { ", var_name);
66     for (int i = 0; i < size ; i++){
67         if ((i % 16) == 0) printf("\n    ");
68         printf ("0x%02x, ", buffer[i]);
69     }
70     printf("};\n");
71     data_counter++;
72 }
73 
74 static int parse_hex(uint8_t * buffer, const char * hex_string){
75     int len = 0;
76     while (*hex_string){
77         if (*hex_string == ' '){
78             hex_string++;
79             continue;
80         }
81         int high_nibble = nibble_for_char(*hex_string++);
82         int low_nibble = nibble_for_char(*hex_string++);
83         *buffer++ = (high_nibble << 4) | low_nibble;
84         len++;
85     }
86     return len;
87 }
88 
89 // returns if anything was done
90 extern "C" int mock_process_hci_cmd(void);
91 
92 // pb-adv mock for testing
93 
94 static btstack_packet_handler_t pb_adv_packet_handler;
95 
96 static uint8_t * pdu_data;
97 static uint16_t  pdu_size;
98 
99 static void pb_adv_emit_link_open(uint8_t status, uint16_t pb_adv_cid){
100     uint8_t event[6] = { HCI_EVENT_MESH_META, 6, MESH_PB_ADV_LINK_OPEN, status};
101     little_endian_store_16(event, 4, pb_adv_cid);
102     pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
103 }
104 
105 static void pb_adv_emit_pdu_sent(uint8_t status){
106     uint8_t event[] = { HCI_EVENT_MESH_META, 2, MESH_PB_ADV_PDU_SENT, status};
107     pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
108 }
109 
110 void pb_adv_init(const uint8_t * device_uuid){
111     printf("pb_adv_init\n");
112 }
113 
114 void pb_adv_close_link(uint16_t pb_adv_cid, uint8_t reason){
115 }
116 
117 void pb_adv_register_packet_handler(btstack_packet_handler_t packet_handler){
118     pb_adv_packet_handler = packet_handler;
119 }
120 
121 void pb_adv_send_pdu(uint16_t pb_transport_cid, const uint8_t * pdu, uint16_t size){
122     UNUSED(pb_transport_cid);
123     pdu_data = (uint8_t*) pdu;
124     pdu_size = size;
125     // dump_data((uint8_t*)pdu,size);
126     // printf_hexdump(pdu, size);
127 }
128 
129 uint16_t pb_adv_create_link(const uint8_t * device_uuid){
130     // just simluate opened
131     pb_adv_emit_link_open(0, 1);
132     return 1;
133 }
134 
135 //
136 static void perform_crypto_operations(void){
137     int more = 1;
138     while (more){
139         more = mock_process_hci_cmd();
140     }
141 }
142 
143 static void send_prov_pdu(const uint8_t * packet, uint16_t size){
144     pb_adv_packet_handler(PROVISIONING_DATA_PACKET, 0, (uint8_t*) packet, size);
145     perform_crypto_operations();
146 }
147 
148 
149 static int scan_hex_byte(const char * byte_string){
150     int upper_nibble = nibble_for_char(*byte_string++);
151     if (upper_nibble < 0) return -1;
152     int lower_nibble = nibble_for_char(*byte_string);
153     if (lower_nibble < 0) return -1;
154     return (upper_nibble << 4) | lower_nibble;
155 }
156 
157 static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){
158     int i;
159     for (i = 0; i < len; i++) {
160         int single_byte = scan_hex_byte(string);
161         if (single_byte < 0) return 0;
162         string += 2;
163         buffer[i] = (uint8_t)single_byte;
164         // don't check seperator after last byte
165         if (i == len - 1) {
166             return 1;
167         }
168         // optional seperator
169         char separator = *string;
170         if (separator == ':' && separator == '-' && separator == ' ') {
171             string++;
172         }
173     }
174     return 1;
175 }
176 
177 static uint8_t      prov_static_oob_data[16];
178 static const char * prov_static_oob_string = "00000000000000000102030405060708";
179 
180 static void provisioning_handle_pdu(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
181     if (packet_type != HCI_EVENT_PACKET) return;
182     switch(packet[0]){
183         case HCI_EVENT_MESH_META:
184             switch(packet[2]){
185                 case MESH_PB_PROV_CAPABILITIES:
186                     printf("Provisioner capabilities\n");
187                     provisioning_provisioner_select_authentication_method(1, 0, 0, 0, 0, 0);
188                     break;
189                 default:
190                     break;
191             }
192         default:
193             break;
194     }
195 }
196 
197 TEST_GROUP(Provisioning){
198     void setup(void){
199         btstack_crypto_init();
200         provisioning_provisioner_init();
201         btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data);
202         provisioning_provisioner_register_packet_handler(&provisioning_handle_pdu);
203         // provisioning_device_set_static_oob(16, prov_static_oob_data);
204         // provisioning_device_set_output_oob_actions(0x08, 0x08);
205         // provisioning_device_set_input_oob_actions(0x08, 0x08);
206         perform_crypto_operations();
207     }
208 };
209 
210 const static uint8_t device_uuid[] = { 0x00, 0x1B, 0xDC, 0x08, 0x10, 0x21, 0x0B, 0x0E, 0x0A, 0x0C, 0x00, 0x0B, 0x0E, 0x0A, 0x0C, 0x00 };
211 
212 uint8_t prov_invite[] = { 0x00, 0x00 };
213 uint8_t prov_capabilities[] = { 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, };
214 uint8_t prov_start[] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
215 uint8_t prov_public_key[] = { 0x03,
216     0xf0, 0xc8, 0x63, 0xf8, 0xe5, 0x55, 0x11, 0x4b, 0xf4, 0x88, 0x2c, 0xc7, 0x87, 0xb9, 0x5c, 0x27,
217     0x2a, 0x7f, 0xe4, 0xdc, 0xdd, 0xf1, 0x92, 0x2f, 0x4f, 0x18, 0xa4, 0x94, 0xe1, 0xc3, 0x57, 0xa1,
218     0xa6, 0xc3, 0x2d, 0x07, 0xbe, 0xb5, 0x76, 0xab, 0x60, 0x10, 0x68, 0x06, 0x8f, 0x0a, 0x9e, 0x01,
219     0x60, 0xc3, 0xa1, 0x41, 0x19, 0xf5, 0xd4, 0x26, 0xa7, 0x95, 0x5d, 0xa3, 0xe6, 0xed, 0x3e, 0x81, };
220 uint8_t prov_confirm[] = {   0x05, 0x3d, 0x0d, 0x55, 0xc4, 0x83, 0xb9, 0x49, 0x6f, 0xab, 0x05, 0xdd, 0xb2, 0x3b, 0x5b, 0xc2, 0x9d};
221 uint8_t prov_random[]  = {   0x06, 0xe9, 0xc5, 0xf1, 0xb0, 0xc4, 0x15, 0x8a, 0xe5, 0x9b, 0x4d, 0x39, 0xf6, 0xf7, 0xe8, 0xa1, 0x05};
222 uint8_t prov_data[] = {
223     0x07, 0x47, 0x1a, 0x19, 0xcc, 0x17, 0x5c, 0xd0, 0xe8, 0x10, 0x3c, 0x85,
224     0x0a, 0x36, 0x10, 0x07, 0x35, 0x17, 0x41, 0x6a, 0xc3, 0x1e, 0x07, 0xe7,
225     0x90, 0x77, 0x3b, 0xab, 0xbb, 0x40, 0x37, 0x75, 0xb7
226 };
227 uint8_t prov_complete[] = { 0x08, };
228 
229 static void expect_packet(const char * packet_name, const uint8_t * packet_data, uint16_t packet_len){
230     printf("Expect '%s'\n", packet_name);
231     CHECK(pdu_data != NULL);
232     CHECK_EQUAL_ARRAY((uint8_t*)packet_data, pdu_data, packet_len);
233 }
234 
235 #define EXPECT_PACKET(packet) expect_packet(#packet, packet, sizeof(packet))
236 
237 TEST(Provisioning, Prov1){
238     // simulate unprovisioned device beacon
239     provisioning_provisioner_start_provisioning(device_uuid);
240     // wait for prov invite
241     EXPECT_PACKET(prov_invite);
242     pb_adv_emit_pdu_sent(0);
243     // send capabilities
244     send_prov_pdu(prov_capabilities, sizeof(prov_capabilities));
245     // wait for start
246     EXPECT_PACKET(prov_start);
247     pb_adv_emit_pdu_sent(0);
248     // wait for public key
249     EXPECT_PACKET(prov_public_key);
250     pb_adv_emit_pdu_sent(0);
251     // send public key
252     send_prov_pdu(prov_public_key, sizeof(prov_public_key));
253     // wait for confirm
254     EXPECT_PACKET(prov_confirm);
255     pb_adv_emit_pdu_sent(0);
256     // send prov confirm
257     send_prov_pdu(prov_confirm, sizeof(prov_confirm));
258     // wait for random
259     CHECK_EQUAL_ARRAY(prov_random, pdu_data, sizeof(prov_random));
260     pb_adv_emit_pdu_sent(0);
261     // send prov random
262     send_prov_pdu(prov_random, sizeof(prov_random));
263     // wait for prov data
264     EXPECT_PACKET(prov_data);
265     pb_adv_emit_pdu_sent(0);
266     // send prov complete
267     send_prov_pdu(prov_complete, sizeof(prov_complete));
268 }
269 
270 int main (int argc, const char * argv[]){
271     hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
272     return CommandLineTestRunner::RunAllTests(argc, argv);
273 }
274