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 #include "dummy.h" 16 17 struct param { 18 int seed; 19 int dev; 20 struct blob wiredata; 21 }; 22 23 struct param * 24 unpack(const uint8_t *ptr, size_t len) 25 { 26 cbor_item_t *item = NULL, **v; 27 struct cbor_load_result cbor; 28 struct param *p; 29 int ok = -1; 30 31 if ((p = calloc(1, sizeof(*p))) == NULL || 32 (item = cbor_load(ptr, len, &cbor)) == NULL || 33 cbor.read != len || 34 cbor_isa_array(item) == false || 35 cbor_array_is_definite(item) == false || 36 cbor_array_size(item) != 3 || 37 (v = cbor_array_handle(item)) == NULL) 38 goto fail; 39 40 if (unpack_int(v[0], &p->seed) < 0 || 41 unpack_int(v[1], &p->dev) < 0 || 42 unpack_blob(v[2], &p->wiredata) < 0) 43 goto fail; 44 45 ok = 0; 46 fail: 47 if (ok < 0) { 48 free(p); 49 p = NULL; 50 } 51 52 if (item) 53 cbor_decref(&item); 54 55 return p; 56 } 57 58 size_t 59 pack(uint8_t *ptr, size_t len, const struct param *p) 60 { 61 cbor_item_t *argv[3], *array = NULL; 62 size_t cbor_alloc_len, cbor_len = 0; 63 unsigned char *cbor = NULL; 64 65 memset(argv, 0, sizeof(argv)); 66 67 if ((array = cbor_new_definite_array(3)) == NULL || 68 (argv[0] = pack_int(p->seed)) == NULL || 69 (argv[1] = pack_int(p->dev)) == NULL || 70 (argv[2] = pack_blob(&p->wiredata)) == NULL) 71 goto fail; 72 73 for (size_t i = 0; i < 3; i++) 74 if (cbor_array_push(array, argv[i]) == false) 75 goto fail; 76 77 if ((cbor_len = cbor_serialize_alloc(array, &cbor, 78 &cbor_alloc_len)) > len) { 79 cbor_len = 0; 80 goto fail; 81 } 82 83 memcpy(ptr, cbor, cbor_len); 84 fail: 85 for (size_t i = 0; i < 3; i++) 86 if (argv[i]) 87 cbor_decref(&argv[i]); 88 89 if (array) 90 cbor_decref(&array); 91 92 free(cbor); 93 94 return cbor_len; 95 } 96 97 size_t 98 pack_dummy(uint8_t *ptr, size_t len) 99 { 100 struct param dummy; 101 uint8_t blob[4096]; 102 size_t blob_len; 103 104 memset(&dummy, 0, sizeof(dummy)); 105 106 dummy.wiredata.len = sizeof(dummy_netlink_wiredata); 107 memcpy(&dummy.wiredata.body, &dummy_netlink_wiredata, 108 dummy.wiredata.len); 109 110 assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); 111 112 if (blob_len > len) { 113 memcpy(ptr, blob, len); 114 return len; 115 } 116 117 memcpy(ptr, blob, blob_len); 118 119 return blob_len; 120 } 121 122 void 123 test(const struct param *p) 124 { 125 fido_nl_t *nl; 126 uint32_t target; 127 128 prng_init((unsigned int)p->seed); 129 fuzz_clock_reset(); 130 fido_init(FIDO_DEBUG); 131 fido_set_log_handler(consume_str); 132 133 set_netlink_io_functions(fd_read, fd_write); 134 set_wire_data(p->wiredata.body, p->wiredata.len); 135 136 if ((nl = fido_nl_new()) == NULL) 137 return; 138 139 consume(&nl->fd, sizeof(nl->fd)); 140 consume(&nl->nfc_type, sizeof(nl->nfc_type)); 141 consume(&nl->nfc_mcastgrp, sizeof(nl->nfc_mcastgrp)); 142 consume(&nl->saddr, sizeof(nl->saddr)); 143 144 fido_nl_power_nfc(nl, (uint32_t)p->dev); 145 146 if (fido_nl_get_nfc_target(nl, (uint32_t)p->dev, &target) == 0) 147 consume(&target, sizeof(target)); 148 149 fido_nl_free(&nl); 150 } 151 152 void 153 mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN 154 { 155 if (flags & MUTATE_SEED) 156 p->seed = (int)seed; 157 158 if (flags & MUTATE_PARAM) 159 mutate_int(&p->dev); 160 161 if (flags & MUTATE_WIREDATA) 162 mutate_blob(&p->wiredata); 163 } 164