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 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