xref: /btstack/test/mesh/provisioning_device_test.cpp (revision 2d97f8bb25b4696d0b0a2cb415bd983faaa60620)
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 "provisioning.h"
46 #include "provisioning_device.h"
47 #include "btstack.h"
48 
49 #include "CppUTest/TestHarness.h"
50 #include "CppUTest/CommandLineTestRunner.h"
51 
52 static void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){
53     int i;
54     for (i=0; i<size; i++){
55         if (expected[i] != actual[i]) {
56             printf("offset %u wrong\n", i);
57             printf("expected: "); printf_hexdump(expected, size);
58             printf("actual:   "); printf_hexdump(actual, size);
59         }
60         BYTES_EQUAL(expected[i], actual[i]);
61     }
62 }
63 
64 void dump_data(uint8_t * buffer, uint16_t size){
65     static int data_counter = 1;
66     char var_name[80];
67     sprintf(var_name, "test_data_%02u", data_counter);
68     printf("uint8_t %s[] = { ", var_name);
69     for (int i = 0; i < size ; i++){
70         if ((i % 16) == 0) printf("\n    ");
71         printf ("0x%02x, ", buffer[i]);
72     }
73     printf("};\n");
74     data_counter++;
75 }
76 
77 int parse_hex(uint8_t * buffer, const char * hex_string){
78     int len = 0;
79     while (*hex_string){
80         if (*hex_string == ' '){
81             hex_string++;
82             continue;
83         }
84         int high_nibble = nibble_for_char(*hex_string++);
85         int low_nibble = nibble_for_char(*hex_string++);
86         *buffer++ = (high_nibble << 4) | low_nibble;
87         len++;
88     }
89     return len;
90 }
91 
92 // returns if anything was done
93 extern "C" int mock_process_hci_cmd(void);
94 
95 const static uint8_t device_uuid[] = { 0x00, 0x1B, 0xDC, 0x08, 0x10, 0x21, 0x0B, 0x0E, 0x0A, 0x0C, 0x00, 0x0B, 0x0E, 0x0A, 0x0C, 0x00 };
96 
97 // pb-adv mock for testing
98 
99 static btstack_packet_handler_t pb_adv_packet_handler;
100 
101 static uint8_t * pdu_data;
102 static uint16_t  pdu_size;
103 
104 /**
105  * Initialize Provisioning Bearer using Advertisement Bearer
106  * @param DeviceUUID
107  */
108 void pb_adv_init(const uint8_t * device_uuid){}
109 void pb_gatt_init(const uint8_t * device_uuid){}
110 
111 /**
112  * Close Link
113  * @param con_handle
114  * @param reason 0 = success, 1 = timeout, 2 = fail
115  */
116 void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){}
117 void pb_adv_close_link(hci_con_handle_t con_handle, uint8_t reason){}
118 
119 
120 /**
121  * Register listener for Provisioning PDUs and MESH_PBV_ADV_SEND_COMPLETE
122  */
123 void pb_adv_register_packet_handler(btstack_packet_handler_t packet_handler){
124     pb_adv_packet_handler = packet_handler;
125 }
126 
127 void pb_gatt_register_packet_handler(btstack_packet_handler_t packet_handler){
128     UNUSED(packet_handler);
129 }
130 /**
131  * Send Provisioning PDU
132  */
133 void pb_adv_send_pdu(uint16_t pb_transport_cid, const uint8_t * pdu, uint16_t size){
134     UNUSED(pb_transport_cid);
135     pdu_data = (uint8_t*) pdu;
136     pdu_size = size;
137     // dump_data((uint8_t*)pdu,size);
138     // printf_hexdump(pdu, size);
139 }
140 void pb_gatt_send_pdu(uint16_t con_handle, const uint8_t * pdu, uint16_t pdu_size){}
141 
142 static mesh_network_key_t network_key;
143 mesh_network_key_t * btstack_memory_mesh_network_key_get(void){
144     return &network_key;
145 }
146 
147 static void perform_crypto_operations(void){
148     int more = 1;
149     while (more){
150         more = mock_process_hci_cmd();
151     }
152 }
153 
154 static void send_prov_pdu(const uint8_t * packet, uint16_t size){
155     pb_adv_packet_handler(PROVISIONING_DATA_PACKET, 0, (uint8_t*) packet, size);
156     perform_crypto_operations();
157 }
158 
159 static void pb_adv_emit_pdu_sent(uint8_t status){
160     uint8_t event[] = { HCI_EVENT_MESH_META, 2, MESH_SUBEVENT_PB_TRANSPORT_PDU_SENT, status};
161     pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
162 }
163 
164 static int scan_hex_byte(const char * byte_string){
165     int upper_nibble = nibble_for_char(*byte_string++);
166     if (upper_nibble < 0) return -1;
167     int lower_nibble = nibble_for_char(*byte_string);
168     if (lower_nibble < 0) return -1;
169     return (upper_nibble << 4) | lower_nibble;
170 }
171 
172 static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){
173     int i;
174     for (i = 0; i < len; i++) {
175         int single_byte = scan_hex_byte(string);
176         if (single_byte < 0) return 0;
177         string += 2;
178         buffer[i] = (uint8_t)single_byte;
179         // don't check seperator after last byte
180         if (i == len - 1) {
181             return 1;
182         }
183         // optional seperator
184         char separator = *string;
185         if (separator == ':' && separator == '-' && separator == ' ') {
186             string++;
187         }
188     }
189     return 1;
190 }
191 
192 // void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){
193 // }
194 
195 static uint8_t      prov_static_oob_data[16];
196 static const char * prov_static_oob_string = "00000000000000000102030405060708";
197 
198 TEST_GROUP(Provisioning){
199     void setup(void){
200         btstack_crypto_init();
201         provisioning_device_init(device_uuid);
202         btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data);
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 uint8_t prov_invite[] = { 0x00, 0x00 };
211 uint8_t prov_capabilities[] = { 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, };
212 uint8_t prov_start[] = { 0x02, 0x00, 0x00, 0x02, 0x00, 0x01 };
213 uint8_t prov_public_key[] = { 0x03,
214     0xf0, 0xc8, 0x63, 0xf8, 0xe5, 0x55, 0x11, 0x4b, 0xf4, 0x88, 0x2c, 0xc7, 0x87, 0xb9, 0x5c, 0x27,
215     0x2a, 0x7f, 0xe4, 0xdc, 0xdd, 0xf1, 0x92, 0x2f, 0x4f, 0x18, 0xa4, 0x94, 0xe1, 0xc3, 0x57, 0xa1,
216     0xa6, 0xc3, 0x2d, 0x07, 0xbe, 0xb5, 0x76, 0xab, 0x60, 0x10, 0x68, 0x06, 0x8f, 0x0a, 0x9e, 0x01,
217     0x60, 0xc3, 0xa1, 0x41, 0x19, 0xf5, 0xd4, 0x26, 0xa7, 0x95, 0x5d, 0xa3, 0xe6, 0xed, 0x3e, 0x81, };
218 uint8_t prov_confirm[] = { 0x05, 0x80, 0x4d, 0xdc, 0x3b, 0xba, 0x60, 0xd5, 0x93, 0x5b, 0x56, 0xef, 0xb5, 0xcb, 0x59, 0x31, 0xfa, };
219 uint8_t prov_random[]  = { 0x06, 0x9b, 0x4d, 0x39, 0xf6, 0xf7, 0xe8, 0xa1, 0x05, 0xd3, 0xfe, 0xed, 0xa5, 0xd5, 0xf3, 0xd9, 0xe4, };
220 uint8_t prov_data[] = {
221     0x07,
222     0x85, 0x66, 0xac, 0x46, 0x37, 0x34, 0x86, 0xe1, 0x3e, 0x4c, 0x13, 0x52, 0xd0, 0x6d, 0x34, 0x7d,
223     0xce, 0xf1, 0xd1, 0x7d, 0xbd, 0xbe, 0xcc, 0x99, 0xc3,
224     0x93, 0x87, 0xfc, 0xb0, 0x72, 0x0f, 0xd8, 0x8d };
225 uint8_t prov_complete[] = { 0x08, };
226 
227 TEST(Provisioning, Prov1){
228     // send prov inviate
229     send_prov_pdu(prov_invite, sizeof(prov_invite));
230     // check for prov cap
231     CHECK_EQUAL_ARRAY(prov_capabilities, pdu_data, sizeof(prov_capabilities));
232     pb_adv_emit_pdu_sent(0);
233     // send prov start
234     send_prov_pdu(prov_start, sizeof(prov_start));
235     // send public key
236     send_prov_pdu(prov_public_key, sizeof(prov_public_key));
237     // check for public key
238     CHECK_EQUAL_ARRAY(prov_public_key, pdu_data, sizeof(prov_public_key));
239     pb_adv_emit_pdu_sent(0);
240     // send prov confirm
241     send_prov_pdu(prov_confirm, sizeof(prov_confirm));
242     // check for prov confirm
243     CHECK_EQUAL_ARRAY(prov_confirm, pdu_data, sizeof(prov_confirm));
244     pb_adv_emit_pdu_sent(0);
245     // send prov random
246     send_prov_pdu(prov_random, sizeof(prov_random));
247     // check for prov random
248     CHECK_EQUAL_ARRAY(prov_random, pdu_data, sizeof(prov_random));
249     pb_adv_emit_pdu_sent(0);
250     // send prov data
251     send_prov_pdu(prov_data, sizeof(prov_data));
252     // check prov complete
253     CHECK_EQUAL_ARRAY(prov_complete, pdu_data, sizeof(prov_complete));
254     pb_adv_emit_pdu_sent(0);
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