1 /* 2 * Copyright (c) 2020 Yubico AB. All rights reserved. 3 * Use of this source code is governed by a BSD-style 4 * license that can be found in the LICENSE file. 5 */ 6 7 #include <assert.h> 8 #include <stdint.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <stdio.h> 12 13 #include "../openbsd-compat/openbsd-compat.h" 14 #include "mutator_aux.h" 15 16 struct param { 17 int seed; 18 int dev; 19 struct blob wiredata; 20 }; 21 22 /* 23 * Sample netlink messages. These are unlikely to get the harness very far in 24 * terms of coverage, but serve to give libFuzzer a sense of the underlying 25 * structure. 26 */ 27 static const uint8_t sample_netlink_wiredata[] = { 28 0xd8, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 29 0x00, 0x00, 0x00, 0x00, 0x9d, 0x2e, 0x00, 0x00, 30 0x01, 0x02, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 31 0x6e, 0x66, 0x63, 0x00, 0x06, 0x00, 0x01, 0x00, 32 0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 33 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 34 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00, 35 0x1f, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x00, 36 0x14, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 37 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 38 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 39 0x08, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 40 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 41 0x14, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 42 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 43 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 44 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 45 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 46 0x14, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00, 47 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 48 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x06, 0x00, 49 0x08, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 50 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 51 0x14, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00, 52 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 53 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00, 54 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 55 0x08, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00, 56 0x14, 0x00, 0x09, 0x00, 0x08, 0x00, 0x01, 0x00, 57 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 58 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x00, 59 0x08, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 60 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 61 0x14, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00, 62 0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 63 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0c, 0x00, 64 0x08, 0x00, 0x01, 0x00, 0x15, 0x00, 0x00, 0x00, 65 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 66 0x14, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x01, 0x00, 67 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 68 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0e, 0x00, 69 0x08, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 70 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 71 0x14, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x01, 0x00, 72 0x1a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 73 0x0c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x10, 0x00, 74 0x08, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x00, 75 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 76 0x14, 0x00, 0x11, 0x00, 0x08, 0x00, 0x01, 0x00, 77 0x1c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 78 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 79 0x08, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x00, 0x00, 80 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 81 0x14, 0x00, 0x13, 0x00, 0x08, 0x00, 0x01, 0x00, 82 0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 83 0x0a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x07, 0x00, 84 0x18, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 85 0x05, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 86 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x00, 87 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 88 0x00, 0x00, 0x00, 0x00, 0x9d, 0x2e, 0x00, 0x00, 89 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 90 0x1e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 91 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 92 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 93 0x9d, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 94 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00, 95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 96 0x1c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 0x09, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 99 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 100 0x1e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 101 0x9d, 0x2e, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 102 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 103 0x08, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 104 0x06, 0x00, 0x05, 0x00, 0x44, 0x00, 0x00, 0x00, 105 0x05, 0x00, 0x06, 0x00, 0x20, 0x00, 0x00, 0x00, 106 0x0b, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00, 107 0x93, 0xb9, 0x25, 0x00 108 }; 109 110 struct param * 111 unpack(const uint8_t *ptr, size_t len) 112 { 113 cbor_item_t *item = NULL, **v; 114 struct cbor_load_result cbor; 115 struct param *p; 116 int ok = -1; 117 118 if ((p = calloc(1, sizeof(*p))) == NULL || 119 (item = cbor_load(ptr, len, &cbor)) == NULL || 120 cbor.read != len || 121 cbor_isa_array(item) == false || 122 cbor_array_is_definite(item) == false || 123 cbor_array_size(item) != 3 || 124 (v = cbor_array_handle(item)) == NULL) 125 goto fail; 126 127 if (unpack_int(v[0], &p->seed) < 0 || 128 unpack_int(v[1], &p->dev) < 0 || 129 unpack_blob(v[2], &p->wiredata) < 0) 130 goto fail; 131 132 ok = 0; 133 fail: 134 if (ok < 0) { 135 free(p); 136 p = NULL; 137 } 138 139 if (item) 140 cbor_decref(&item); 141 142 return p; 143 } 144 145 size_t 146 pack(uint8_t *ptr, size_t len, const struct param *p) 147 { 148 cbor_item_t *argv[3], *array = NULL; 149 size_t cbor_alloc_len, cbor_len = 0; 150 unsigned char *cbor = NULL; 151 152 memset(argv, 0, sizeof(argv)); 153 154 if ((array = cbor_new_definite_array(3)) == NULL || 155 (argv[0] = pack_int(p->seed)) == NULL || 156 (argv[1] = pack_int(p->dev)) == NULL || 157 (argv[2] = pack_blob(&p->wiredata)) == NULL) 158 goto fail; 159 160 for (size_t i = 0; i < 3; i++) 161 if (cbor_array_push(array, argv[i]) == false) 162 goto fail; 163 164 if ((cbor_len = cbor_serialize_alloc(array, &cbor, 165 &cbor_alloc_len)) > len) { 166 cbor_len = 0; 167 goto fail; 168 } 169 170 memcpy(ptr, cbor, cbor_len); 171 fail: 172 for (size_t i = 0; i < 3; i++) 173 if (argv[i]) 174 cbor_decref(&argv[i]); 175 176 if (array) 177 cbor_decref(&array); 178 179 free(cbor); 180 181 return cbor_len; 182 } 183 184 size_t 185 pack_dummy(uint8_t *ptr, size_t len) 186 { 187 struct param dummy; 188 uint8_t blob[4096]; 189 size_t blob_len; 190 191 memset(&dummy, 0, sizeof(dummy)); 192 193 dummy.wiredata.len = sizeof(sample_netlink_wiredata); 194 memcpy(&dummy.wiredata.body, &sample_netlink_wiredata, 195 dummy.wiredata.len); 196 197 assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); 198 199 if (blob_len > len) { 200 memcpy(ptr, blob, len); 201 return len; 202 } 203 204 memcpy(ptr, blob, blob_len); 205 206 return blob_len; 207 } 208 209 void 210 test(const struct param *p) 211 { 212 fido_nl_t *nl; 213 uint32_t target; 214 215 prng_init((unsigned int)p->seed); 216 fido_init(FIDO_DEBUG); 217 fido_set_log_handler(consume_str); 218 219 set_netlink_io_functions(fd_read, fd_write); 220 set_wire_data(p->wiredata.body, p->wiredata.len); 221 222 if ((nl = fido_nl_new()) == NULL) 223 return; 224 225 consume(&nl->fd, sizeof(nl->fd)); 226 consume(&nl->nfc_type, sizeof(nl->nfc_type)); 227 consume(&nl->nfc_mcastgrp, sizeof(nl->nfc_mcastgrp)); 228 consume(&nl->saddr, sizeof(nl->saddr)); 229 230 fido_nl_power_nfc(nl, (uint32_t)p->dev); 231 232 if (fido_nl_get_nfc_target(nl, (uint32_t)p->dev, &target) == 0) 233 consume(&target, sizeof(target)); 234 235 fido_nl_free(&nl); 236 } 237 238 void 239 mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN 240 { 241 if (flags & MUTATE_SEED) 242 p->seed = (int)seed; 243 244 if (flags & MUTATE_PARAM) 245 mutate_int(&p->dev); 246 247 if (flags & MUTATE_WIREDATA) 248 mutate_blob(&p->wiredata); 249 } 250