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
hci_transport_fuzz_set_baudrate(uint32_t baudrate)10 static int hci_transport_fuzz_set_baudrate(uint32_t baudrate){
11 return 0;
12 }
13
hci_transport_fuzz_can_send_now(uint8_t packet_type)14 static int hci_transport_fuzz_can_send_now(uint8_t packet_type){
15 return 1;
16 }
17
hci_transport_fuzz_send_packet(uint8_t packet_type,uint8_t * packet,int size)18 static int hci_transport_fuzz_send_packet(uint8_t packet_type, uint8_t * packet, int size){
19 return 0;
20 }
21
hci_transport_fuzz_init(const void * transport_config)22 static void hci_transport_fuzz_init(const void * transport_config){
23 }
24
hci_transport_fuzz_open(void)25 static int hci_transport_fuzz_open(void){
26 return 0;
27 }
28
hci_transport_fuzz_close(void)29 static int hci_transport_fuzz_close(void){
30 return 0;
31 }
32
hci_transport_fuzz_register_packet_handler(void (* handler)(uint8_t packet_type,uint8_t * packet,uint16_t size))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
gatt_client_packet_handler(uint8_t packet_type,uint16_t handle,uint8_t * packet,uint16_t size)50 static void gatt_client_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
51 }
52
set_gatt_service_uuid16(gatt_client_service_t * service,const uint8_t * data,size_t size)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
set_gatt_service_uuid128(gatt_client_service_t * service,const uint8_t * data,size_t size)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
set_gatt_characteristic_uuid16(gatt_client_characteristic_t * characteristic,const uint8_t * data,size_t size)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
set_gatt_characteristic_uuid128(gatt_client_characteristic_t * characteristic,const uint8_t * data,size_t size)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
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)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 uint8_t response_type = 0;
115 switch (cmd_type){
116 case 1:
117 gatt_client_discover_primary_services(gatt_client_packet_handler, ble_handle);
118 response_type = ATT_READ_BY_GROUP_TYPE_RESPONSE;
119 break;
120 case 2:
121 offset = 2;
122 if (size < offset) return 0;
123 uuid16 = big_endian_read_16(data, 0);
124 gatt_client_discover_primary_services_by_uuid16(gatt_client_packet_handler, ble_handle, uuid16);
125 response_type = ATT_FIND_BY_TYPE_VALUE_RESPONSE;
126 break;
127 case 3:
128 offset = 16;
129 if (size < offset) return 0;
130 memcpy(uuid128, data, 16);
131 gatt_client_discover_primary_services_by_uuid128(gatt_client_packet_handler, ble_handle, uuid128);
132 response_type = ATT_FIND_BY_TYPE_VALUE_RESPONSE;
133 break;
134 case 4:
135 offset = 2;
136 if (size < offset) return 0;
137 set_gatt_service_uuid16(&service, data, size);
138 gatt_client_find_included_services_for_service(gatt_client_packet_handler, ble_handle, &service);
139 response_type = ATT_READ_BY_TYPE_RESPONSE;
140 break;
141 case 5:
142 offset = 2;
143 if (size < offset) return 0;
144 set_gatt_service_uuid16(&service, data, size);
145 gatt_client_discover_characteristics_for_service(gatt_client_packet_handler, ble_handle, &service);
146 response_type = ATT_READ_BY_TYPE_RESPONSE;
147 break;
148 case 6:
149 offset = 2;
150 if (size < offset) return 0;
151 uuid16 = big_endian_read_16(data, 0);
152 gatt_client_discover_characteristics_for_handle_range_by_uuid16(gatt_client_packet_handler, ble_handle, 0x0001, 0xffff, uuid16);
153 response_type = ATT_READ_BY_TYPE_RESPONSE;
154 break;
155 case 7:
156 offset = 16;
157 if (size < offset) return 0;
158 memcpy(uuid128, data, 16);
159 gatt_client_discover_characteristics_for_handle_range_by_uuid128(gatt_client_packet_handler, ble_handle, 0x0001, 0xffff, uuid128);
160 response_type = ATT_READ_BY_TYPE_RESPONSE;
161 break;
162 case 8:
163 offset = 4;
164 if (size < offset) return 0;
165 set_gatt_service_uuid16(&service, data, size);
166 uuid16 = big_endian_read_16(data, 2);
167 gatt_client_discover_characteristics_for_service_by_uuid16(gatt_client_packet_handler, ble_handle, &service, uuid16);
168 response_type = ATT_READ_BY_TYPE_RESPONSE;
169 break;
170 case 9:
171 offset = 18;
172 if (size < offset) return 0;
173 set_gatt_service_uuid16(&service, data, size);
174 memcpy(uuid128, data + 2, 16);
175 gatt_client_discover_characteristics_for_service_by_uuid128(gatt_client_packet_handler, ble_handle, &service, uuid128);
176 response_type = ATT_READ_BY_TYPE_RESPONSE;
177 break;
178 case 10:
179 offset = 2;
180 if (size < offset) return 0;
181 set_gatt_characteristic_uuid16(&characteristic, data, size);
182 gatt_client_discover_characteristic_descriptors(gatt_client_packet_handler, ble_handle, &characteristic);
183 response_type = ATT_FIND_INFORMATION_REPLY;
184 break;
185 case 11:
186 offset = 2;
187 if (size < offset) return 0;
188 set_gatt_characteristic_uuid16(&characteristic, data, size);
189 gatt_client_read_value_of_characteristic(gatt_client_packet_handler, ble_handle, &characteristic);
190 response_type = ATT_READ_RESPONSE;
191 break;
192 case 12:
193 offset = 2;
194 if (size < offset) return 0;
195 set_gatt_characteristic_uuid16(&characteristic, data, size);
196 gatt_client_read_value_of_characteristics_by_uuid16(gatt_client_packet_handler, ble_handle, characteristic.start_handle, characteristic.end_handle, characteristic.uuid16);
197 response_type = ATT_READ_BY_TYPE_RESPONSE;
198 break;
199 case 13:
200 offset = 16;
201 if (size < offset) return 0;
202 set_gatt_characteristic_uuid128(&characteristic, data, size);
203 gatt_client_read_value_of_characteristics_by_uuid128(gatt_client_packet_handler, ble_handle, characteristic.start_handle, characteristic.end_handle, characteristic.uuid128);
204 response_type = ATT_READ_BY_TYPE_RESPONSE;
205 break;
206 case 14:
207 offset = 2;
208 if (size < offset) return 0;
209 set_gatt_characteristic_uuid16(&characteristic, data, size);
210 gatt_client_read_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, &characteristic);
211 response_type = ATT_READ_BLOB_RESPONSE;
212 break;
213 case 15:
214 offset = 4;
215 if (size < offset) return 0;
216 set_gatt_characteristic_uuid16(&characteristic, data, size);
217 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));
218 response_type = ATT_READ_BLOB_RESPONSE;
219 break;
220 case 16:
221 gatt_client_read_multiple_characteristic_values(gatt_client_packet_handler, ble_handle, 0, NULL);
222 response_type = ATT_READ_MULTIPLE_RESPONSE;
223 break;
224 case 17:
225 gatt_client_write_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
226 response_type = ATT_WRITE_RESPONSE;
227 break;
228 case 18:
229 gatt_client_write_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
230 response_type = ATT_PREPARE_WRITE_RESPONSE;
231 break;
232 case 19:
233 gatt_client_reliable_write_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
234 response_type = ATT_PREPARE_WRITE_RESPONSE;
235 break;
236 case 20:
237 gatt_client_read_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5);
238 response_type = ATT_READ_RESPONSE;
239 break;
240 case 21:
241 gatt_client_read_long_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5);
242 response_type = ATT_READ_BLOB_RESPONSE;
243 break;
244 case 22:
245 gatt_client_write_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
246 response_type = ATT_PREPARE_WRITE_RESPONSE;
247 break;
248 case 23:
249 gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
250 response_type = ATT_PREPARE_WRITE_RESPONSE;
251 break;
252 case 24:
253 offset = 2;
254 if (size < offset) return 0;
255 set_gatt_characteristic_uuid16(&characteristic, data, size);
256 gatt_client_write_client_characteristic_configuration(gatt_client_packet_handler, ble_handle, &characteristic, 1);
257 #ifdef ENABLE_GATT_FIND_INFORMATION_FOR_CCC_DISCOVERY
258 response_type = ATT_FIND_INFORMATION_REPLY;
259 #else
260 response_type = ATT_READ_BY_TYPE_RESPONSE;
261 #endif
262 break;
263 case 25:
264 gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL);
265 response_type = ATT_PREPARE_WRITE_RESPONSE;
266 break;
267
268 #if 0
269 // TODO: won't work as only single packet is simulate
270 case 26:
271 gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL);
272 response_type = ATT_PREPARE_WRITE_RESPONSE;
273 gatt_client_execute_write(gatt_client_packet_handler, ble_handle);
274 break;
275 case 27:
276 gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL);
277 response_type = ATT_PREPARE_WRITE_RESPONSE;
278 gatt_client_cancel_write(gatt_client_packet_handler, ble_handle);
279 break;
280 #endif
281 default:
282 return 0;
283 }
284
285 data += offset;
286 size -= offset;
287
288 uint8_t response_buffer[256];
289 response_buffer[0] = response_type;
290 uint32_t bytes_to_copy = btstack_min(size, sizeof(response_buffer)-1);
291 memcpy(&response_buffer[1], data, bytes_to_copy);
292 // send test response
293 gatt_client_att_packet_handler_fuzz(ATT_DATA_PACKET, ble_handle, response_buffer, bytes_to_copy+1);
294 return 0;
295 }
296