xref: /btstack/test/fuzz/fuzz_hci.c (revision 308e35cf33f6937b53ef6c055adea9d10e215e1a)
1 #include <stdint.h>
2 #include <stddef.h>
3 #include <stdio.h>
4 
5 #include <btstack_util.h>
6 #include <btstack.h>
7 #include <btstack_run_loop_posix.h>
8 #include "hci.h"
9 
10 static  void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
11 
12 static int hci_transport_fuzz_set_baudrate(uint32_t baudrate){
13     return 0;
14 }
15 
16 static int hci_transport_fuzz_can_send_now(uint8_t packet_type){
17     return 1;
18 }
19 
20 static int hci_transport_fuzz_send_packet(uint8_t packet_type, uint8_t * packet, int size){
21     return 0;
22 }
23 
24 static void hci_transport_fuzz_init(const void * transport_config){
25 }
26 
27 static int hci_transport_fuzz_open(void){
28     return 0;
29 }
30 
31 static int hci_transport_fuzz_close(void){
32     return 0;
33 }
34 
35 static void hci_transport_fuzz_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
36     packet_handler = handler;
37 }
38 
39 static const hci_transport_t hci_transport_fuzz = {
40         /* const char * name; */                                        "FUZZ",
41         /* void   (*init) (const void *transport_config); */            &hci_transport_fuzz_init,
42         /* int    (*open)(void); */                                     &hci_transport_fuzz_open,
43         /* int    (*close)(void); */                                    &hci_transport_fuzz_close,
44         /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_fuzz_register_packet_handler,
45         /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_fuzz_can_send_now,
46         /* int    (*send_packet)(...); */                               &hci_transport_fuzz_send_packet,
47         /* int    (*set_baudrate)(uint32_t baudrate); */                &hci_transport_fuzz_set_baudrate,
48         /* void   (*reset_link)(void); */                               NULL,
49         /* void   (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
50 };
51 
52 static void l2cap_packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
53     switch (packet_type) {
54         case HCI_EVENT_PACKET:
55             break;
56         case HCI_SCO_DATA_PACKET:
57             break;
58         case HCI_ACL_DATA_PACKET:
59             break;
60         default:
61             break;
62     }
63 }
64 
65 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
66     static int initialized = 0;
67     if (initialized == 0){
68         initialized = 1;
69         btstack_memory_init();
70         btstack_run_loop_init(btstack_run_loop_posix_get_instance());
71     }
72 
73     // prepare test data
74     if (size < 3) return 0;
75     uint8_t  packet_type  = (data[0] & 3) + 1;             // only 1-4
76     uint16_t connection_handle = ((data[0] >> 2) & 0x07); // 0x0000 - 0x0007
77     uint8_t  pb_or_ps = (data[0] >> 5) & 0x003;            // 0x00-0x03
78     size--;
79     data++;
80     uint8_t packet[1000];
81     uint16_t packet_len;
82     switch (packet_type){
83         case HCI_EVENT_PACKET:
84             packet[0] = data[0];
85             size--;
86             data++;
87             if (size > 255) return 0;
88             packet[1] = size;
89             memcpy(&packet[2], data, size);
90             packet_len = size + 2;
91             // avoid assert on packet buffer reserved
92             if (packet[0] == HCI_EVENT_TRANSPORT_PACKET_SENT){
93                 return 0;
94             }
95             break;
96         case HCI_SCO_DATA_PACKET:
97             little_endian_store_16(packet, 0, (pb_or_ps << 12) | connection_handle);
98             if (size > 255) return 0;
99             packet[2] = size;
100             memcpy(&packet[3], data, size);
101             packet_len = size + 3;
102             break;
103         case HCI_ACL_DATA_PACKET:
104             little_endian_store_16(packet, 0, (pb_or_ps << 12) | connection_handle);
105             little_endian_store_16(packet, 2, size);
106             if (size > (sizeof(packet) - 4)) return 0;
107             memcpy(&packet[4], data, size);
108             packet_len = size + 4;
109             break;
110         default:
111             return 0;
112     }
113 
114     // init hci
115     hci_init(&hci_transport_fuzz, NULL);
116     hci_setup_test_connections_fuzz();
117 
118     // deliver test data
119     (*packet_handler)(packet_type, packet, packet_len);
120 
121     // teardown
122     hci_free_connections_fuzz();
123     return 0;
124 }
125