xref: /btstack/test/fuzz/fuzz_gatt_client.c (revision a8d51f092f1b660d0f6921369ad2bc3f9368296c)
1 #include <stdint.h>
2 #include <stddef.h>
3 
4 #include "ble/gatt_client.h"
5 #include "btstack_run_loop_posix.h"
6 #include "btstack_memory.h"
7 
8 static  void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
9 
10 static int hci_transport_fuzz_set_baudrate(uint32_t baudrate){
11     return 0;
12 }
13 
14 static int hci_transport_fuzz_can_send_now(uint8_t packet_type){
15     return 1;
16 }
17 
18 static int hci_transport_fuzz_send_packet(uint8_t packet_type, uint8_t * packet, int size){
19     return 0;
20 }
21 
22 static void hci_transport_fuzz_init(const void * transport_config){
23 }
24 
25 static int hci_transport_fuzz_open(void){
26     return 0;
27 }
28 
29 static int hci_transport_fuzz_close(void){
30     return 0;
31 }
32 
33 static void hci_transport_fuzz_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
34     packet_handler = handler;
35 }
36 
37 static const hci_transport_t hci_transport_fuzz = {
38         /* const char * name; */                                        "FUZZ",
39         /* void   (*init) (const void *transport_config); */            &hci_transport_fuzz_init,
40         /* int    (*open)(void); */                                     &hci_transport_fuzz_open,
41         /* int    (*close)(void); */                                    &hci_transport_fuzz_close,
42         /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_fuzz_register_packet_handler,
43         /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_fuzz_can_send_now,
44         /* int    (*send_packet)(...); */                               &hci_transport_fuzz_send_packet,
45         /* int    (*set_baudrate)(uint32_t baudrate); */                &hci_transport_fuzz_set_baudrate,
46         /* void   (*reset_link)(void); */                               NULL,
47         /* void   (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
48 };
49 
50 static void gatt_client_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
51 }
52 
53 void set_gatt_service_uuid16(gatt_client_service_t * service, const uint8_t *data, size_t size){
54     service->start_group_handle = 0x0001;
55     service->end_group_handle = 0xffff;
56     memset(service->uuid128, 0, 16);
57     service->uuid16 = big_endian_read_16(data, 0);
58 }
59 
60 void set_gatt_service_uuid128(gatt_client_service_t * service, const uint8_t *data, size_t size){
61     service->start_group_handle = 0x0001;
62     service->end_group_handle = 0xffff;
63     service->uuid16 = 0;
64     memcpy(service->uuid128, data, 16);
65 }
66 
67 void set_gatt_characteristic_uuid16(gatt_client_characteristic_t * characteristic, const uint8_t *data, size_t size){
68     characteristic->start_handle = 0x0001;
69     characteristic->value_handle = 0x0002;
70     characteristic->end_handle = 0xffff;
71     characteristic->uuid16 = big_endian_read_16(data, 0);
72     memset(characteristic->uuid128, 0, 16);
73 }
74 
75 void set_gatt_characteristic_uuid128(gatt_client_characteristic_t * characteristic, const uint8_t *data, size_t size){
76     characteristic->start_handle = 0x0001;
77     characteristic->value_handle = 0x0002;
78     characteristic->end_handle = 0xffff;
79     characteristic->uuid16 = 0;
80     memcpy(characteristic->uuid128, data, 16);
81 }
82 
83 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
84     const hci_con_handle_t ble_handle = 0x0005;
85 
86     static bool gatt_client_initiated = false;
87     if (!gatt_client_initiated){
88         btstack_memory_init();
89         btstack_run_loop_init(btstack_run_loop_posix_get_instance());
90         // init hci, simulate connection
91         hci_init(&hci_transport_fuzz, NULL);
92         hci_setup_test_connections_fuzz();
93 
94         gatt_client_init();
95         gatt_client_mtu_enable_auto_negotiation(0);
96         gatt_client_initiated = true;
97     }
98 
99     // use first byte of random data to pick gatt_client request / set gatt client state
100     // then, only use data from second byte as response
101     // prepare test data
102     if (size < 1) return 0;
103     uint8_t  cmd_type  = (data[0] & 0x1F);
104     size--;
105     data++;
106 
107     uint8_t  uuid128[16];
108     uint16_t uuid16;
109     int offset = 0;
110     gatt_client_service_t service;
111     gatt_client_characteristic_t characteristic;
112     gatt_client_characteristic_descriptor_t descriptor;
113 
114     switch (cmd_type){
115         case 1:
116             gatt_client_discover_primary_services(gatt_client_packet_handler, ble_handle);
117             break;
118         case 2:
119             offset = 2;
120             if (size < offset) return 0;
121             uuid16 = big_endian_read_16(data, 0);
122             gatt_client_discover_primary_services_by_uuid16(gatt_client_packet_handler, ble_handle, uuid16);
123             break;
124         case 3:
125             offset = 16;
126             if (size < offset) return 0;
127             memcpy(uuid128, data, 16);
128             gatt_client_discover_primary_services_by_uuid128(gatt_client_packet_handler, ble_handle, uuid128);
129             break;
130         case 4:
131             offset = 2;
132             if (size < offset) return 0;
133             set_gatt_service_uuid16(&service, data, size);
134             gatt_client_find_included_services_for_service(gatt_client_packet_handler, ble_handle, &service);
135             break;
136         case 5:
137             offset = 2;
138             if (size < offset) return 0;
139             set_gatt_service_uuid16(&service, data, size);
140             gatt_client_discover_characteristics_for_service(gatt_client_packet_handler, ble_handle, &service);
141             break;
142         case 6:
143             offset = 2;
144             if (size < offset) return 0;
145             uuid16 = big_endian_read_16(data, 0);
146             gatt_client_discover_characteristics_for_handle_range_by_uuid16(gatt_client_packet_handler, ble_handle, 0x0001, 0xffff, uuid16);
147             break;
148         case 7:
149             offset = 16;
150             if (size < offset) return 0;
151             memcpy(uuid128, data, 16);
152             gatt_client_discover_characteristics_for_handle_range_by_uuid128(gatt_client_packet_handler, ble_handle, 0x0001, 0xffff, uuid128);
153             break;
154         case 8:
155             offset = 4;
156             if (size < offset) return 0;
157             set_gatt_service_uuid16(&service, data, size);
158             uuid16 = big_endian_read_16(data, 2);
159             gatt_client_discover_characteristics_for_service_by_uuid16(gatt_client_packet_handler, ble_handle, &service, uuid16);
160             break;
161         case 9:
162             offset = 18;
163             if (size < offset) return 0;
164             set_gatt_service_uuid16(&service, data, size);
165             memcpy(uuid128, data + 2, 16);
166             gatt_client_discover_characteristics_for_service_by_uuid128(gatt_client_packet_handler, ble_handle, &service, uuid128);
167             break;
168         case 10:
169             offset = 2;
170             if (size < offset) return 0;
171             set_gatt_characteristic_uuid16(&characteristic, data, size);
172             gatt_client_discover_characteristic_descriptors(gatt_client_packet_handler, ble_handle, &characteristic);
173             break;
174         case 11:
175             offset = 2;
176             if (size < offset) return 0;
177             set_gatt_characteristic_uuid16(&characteristic, data, size);
178             gatt_client_read_value_of_characteristic(gatt_client_packet_handler, ble_handle, &characteristic);
179             break;
180         case 12:
181             offset = 2;
182             if (size < offset) return 0;
183             set_gatt_characteristic_uuid16(&characteristic, data, size);
184             gatt_client_read_value_of_characteristics_by_uuid16(gatt_client_packet_handler, ble_handle, characteristic.start_handle, characteristic.end_handle, characteristic.uuid16);
185             break;
186         case 13:
187             offset = 16;
188             if (size < offset) return 0;
189             set_gatt_characteristic_uuid128(&characteristic, data, size);
190             gatt_client_read_value_of_characteristics_by_uuid128(gatt_client_packet_handler, ble_handle, characteristic.start_handle, characteristic.end_handle, characteristic.uuid128);
191             break;
192         case 14:
193             offset = 2;
194             if (size < offset) return 0;
195             set_gatt_characteristic_uuid16(&characteristic, data, size);
196             gatt_client_read_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, &characteristic);
197             break;
198         case 15:
199             offset = 4;
200             if (size < offset) return 0;
201             set_gatt_characteristic_uuid16(&characteristic, data, size);
202             gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset(gatt_client_packet_handler, ble_handle, characteristic.value_handle, big_endian_read_16(data, 2));
203             break;
204         case 16:
205             gatt_client_read_multiple_characteristic_values(gatt_client_packet_handler, ble_handle, 0, NULL);
206             break;
207         case 17:
208             gatt_client_write_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
209             break;
210         case 18:
211             gatt_client_write_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
212             break;
213         case 19:
214             gatt_client_reliable_write_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
215             break;
216         case 20:
217             gatt_client_read_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5);
218             break;
219         case 21:
220             gatt_client_read_long_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5);
221             break;
222         case 22:
223             gatt_client_write_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
224             break;
225         case 23:
226             gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
227             break;
228         case 24:
229             offset = 2;
230             if (size < offset) return 0;
231             set_gatt_characteristic_uuid16(&characteristic, data, size);
232             gatt_client_write_client_characteristic_configuration(gatt_client_packet_handler, ble_handle, &characteristic, 1);
233             break;
234         case 25:
235             gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL);
236             break;
237         case 26:
238             gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL);
239             gatt_client_execute_write(gatt_client_packet_handler, ble_handle);
240             break;
241         case 27:
242             gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL);
243             gatt_client_cancel_write(gatt_client_packet_handler, ble_handle);
244             break;
245         default:
246             return 0;
247     }
248 
249     data += offset;
250     size -= offset;
251 
252     // send test response
253     gatt_client_att_packet_handler_fuzz(ATT_DATA_PACKET, ble_handle, (uint8_t *) data, size);
254     return 0;
255 }
256