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