xref: /freebsd/contrib/libfido2/fuzz/fuzz_netlink.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
10afa8e06SEd Maste /*
20afa8e06SEd Maste  * Copyright (c) 2020 Yubico AB. All rights reserved.
30afa8e06SEd Maste  * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste  * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste  */
70afa8e06SEd Maste 
80afa8e06SEd Maste #include <assert.h>
90afa8e06SEd Maste #include <stdint.h>
100afa8e06SEd Maste #include <stdlib.h>
110afa8e06SEd Maste #include <string.h>
120afa8e06SEd Maste #include <stdio.h>
130afa8e06SEd Maste 
140afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h"
150afa8e06SEd Maste #include "mutator_aux.h"
16f540a430SEd Maste #include "dummy.h"
170afa8e06SEd Maste 
180afa8e06SEd Maste struct param {
190afa8e06SEd Maste 	int seed;
200afa8e06SEd Maste 	int dev;
210afa8e06SEd Maste 	struct blob wiredata;
220afa8e06SEd Maste };
230afa8e06SEd Maste 
240afa8e06SEd Maste struct param *
unpack(const uint8_t * ptr,size_t len)250afa8e06SEd Maste unpack(const uint8_t *ptr, size_t len)
260afa8e06SEd Maste {
270afa8e06SEd Maste 	cbor_item_t *item = NULL, **v;
280afa8e06SEd Maste 	struct cbor_load_result cbor;
290afa8e06SEd Maste 	struct param *p;
300afa8e06SEd Maste 	int ok = -1;
310afa8e06SEd Maste 
320afa8e06SEd Maste 	if ((p = calloc(1, sizeof(*p))) == NULL ||
330afa8e06SEd Maste 	    (item = cbor_load(ptr, len, &cbor)) == NULL ||
340afa8e06SEd Maste 	    cbor.read != len ||
350afa8e06SEd Maste 	    cbor_isa_array(item) == false ||
360afa8e06SEd Maste 	    cbor_array_is_definite(item) == false ||
370afa8e06SEd Maste 	    cbor_array_size(item) != 3 ||
380afa8e06SEd Maste 	    (v = cbor_array_handle(item)) == NULL)
390afa8e06SEd Maste 		goto fail;
400afa8e06SEd Maste 
410afa8e06SEd Maste 	if (unpack_int(v[0], &p->seed) < 0 ||
420afa8e06SEd Maste 	    unpack_int(v[1], &p->dev) < 0 ||
430afa8e06SEd Maste 	    unpack_blob(v[2], &p->wiredata) < 0)
440afa8e06SEd Maste 		goto fail;
450afa8e06SEd Maste 
460afa8e06SEd Maste 	ok = 0;
470afa8e06SEd Maste fail:
480afa8e06SEd Maste 	if (ok < 0) {
490afa8e06SEd Maste 		free(p);
500afa8e06SEd Maste 		p = NULL;
510afa8e06SEd Maste 	}
520afa8e06SEd Maste 
530afa8e06SEd Maste 	if (item)
540afa8e06SEd Maste 		cbor_decref(&item);
550afa8e06SEd Maste 
560afa8e06SEd Maste 	return p;
570afa8e06SEd Maste }
580afa8e06SEd Maste 
590afa8e06SEd Maste size_t
pack(uint8_t * ptr,size_t len,const struct param * p)600afa8e06SEd Maste pack(uint8_t *ptr, size_t len, const struct param *p)
610afa8e06SEd Maste {
620afa8e06SEd Maste 	cbor_item_t *argv[3], *array = NULL;
630afa8e06SEd Maste 	size_t cbor_alloc_len, cbor_len = 0;
640afa8e06SEd Maste 	unsigned char *cbor = NULL;
650afa8e06SEd Maste 
660afa8e06SEd Maste 	memset(argv, 0, sizeof(argv));
670afa8e06SEd Maste 
680afa8e06SEd Maste 	if ((array = cbor_new_definite_array(3)) == NULL ||
690afa8e06SEd Maste 	    (argv[0] = pack_int(p->seed)) == NULL ||
700afa8e06SEd Maste 	    (argv[1] = pack_int(p->dev)) == NULL ||
710afa8e06SEd Maste 	    (argv[2] = pack_blob(&p->wiredata)) == NULL)
720afa8e06SEd Maste 		goto fail;
730afa8e06SEd Maste 
740afa8e06SEd Maste 	for (size_t i = 0; i < 3; i++)
750afa8e06SEd Maste 		if (cbor_array_push(array, argv[i]) == false)
760afa8e06SEd Maste 			goto fail;
770afa8e06SEd Maste 
780afa8e06SEd Maste 	if ((cbor_len = cbor_serialize_alloc(array, &cbor,
79*2ccfa855SEd Maste 	    &cbor_alloc_len)) == 0 || cbor_len > len) {
800afa8e06SEd Maste 		cbor_len = 0;
810afa8e06SEd Maste 		goto fail;
820afa8e06SEd Maste 	}
830afa8e06SEd Maste 
840afa8e06SEd Maste 	memcpy(ptr, cbor, cbor_len);
850afa8e06SEd Maste fail:
860afa8e06SEd Maste 	for (size_t i = 0; i < 3; i++)
870afa8e06SEd Maste 		if (argv[i])
880afa8e06SEd Maste 			cbor_decref(&argv[i]);
890afa8e06SEd Maste 
900afa8e06SEd Maste 	if (array)
910afa8e06SEd Maste 		cbor_decref(&array);
920afa8e06SEd Maste 
930afa8e06SEd Maste 	free(cbor);
940afa8e06SEd Maste 
950afa8e06SEd Maste 	return cbor_len;
960afa8e06SEd Maste }
970afa8e06SEd Maste 
980afa8e06SEd Maste size_t
pack_dummy(uint8_t * ptr,size_t len)990afa8e06SEd Maste pack_dummy(uint8_t *ptr, size_t len)
1000afa8e06SEd Maste {
1010afa8e06SEd Maste 	struct param dummy;
102*2ccfa855SEd Maste 	uint8_t	blob[MAXCORPUS];
1030afa8e06SEd Maste 	size_t blob_len;
1040afa8e06SEd Maste 
1050afa8e06SEd Maste 	memset(&dummy, 0, sizeof(dummy));
1060afa8e06SEd Maste 
107f540a430SEd Maste 	dummy.wiredata.len = sizeof(dummy_netlink_wiredata);
108f540a430SEd Maste 	memcpy(&dummy.wiredata.body, &dummy_netlink_wiredata,
1090afa8e06SEd Maste 	    dummy.wiredata.len);
1100afa8e06SEd Maste 
1110afa8e06SEd Maste 	assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
1120afa8e06SEd Maste 
1130afa8e06SEd Maste 	if (blob_len > len) {
1140afa8e06SEd Maste 		memcpy(ptr, blob, len);
1150afa8e06SEd Maste 		return len;
1160afa8e06SEd Maste 	}
1170afa8e06SEd Maste 
1180afa8e06SEd Maste 	memcpy(ptr, blob, blob_len);
1190afa8e06SEd Maste 
1200afa8e06SEd Maste 	return blob_len;
1210afa8e06SEd Maste }
1220afa8e06SEd Maste 
1230afa8e06SEd Maste void
test(const struct param * p)1240afa8e06SEd Maste test(const struct param *p)
1250afa8e06SEd Maste {
1260afa8e06SEd Maste 	fido_nl_t *nl;
1270afa8e06SEd Maste 	uint32_t target;
1280afa8e06SEd Maste 
1290afa8e06SEd Maste 	prng_init((unsigned int)p->seed);
130f540a430SEd Maste 	fuzz_clock_reset();
1310afa8e06SEd Maste 	fido_init(FIDO_DEBUG);
1320afa8e06SEd Maste 	fido_set_log_handler(consume_str);
1330afa8e06SEd Maste 
1340afa8e06SEd Maste 	set_netlink_io_functions(fd_read, fd_write);
1350afa8e06SEd Maste 	set_wire_data(p->wiredata.body, p->wiredata.len);
1360afa8e06SEd Maste 
1370afa8e06SEd Maste 	if ((nl = fido_nl_new()) == NULL)
1380afa8e06SEd Maste 		return;
1390afa8e06SEd Maste 
1400afa8e06SEd Maste 	consume(&nl->fd, sizeof(nl->fd));
1410afa8e06SEd Maste 	consume(&nl->nfc_type, sizeof(nl->nfc_type));
1420afa8e06SEd Maste 	consume(&nl->nfc_mcastgrp, sizeof(nl->nfc_mcastgrp));
1430afa8e06SEd Maste 	consume(&nl->saddr, sizeof(nl->saddr));
1440afa8e06SEd Maste 
1450afa8e06SEd Maste 	fido_nl_power_nfc(nl, (uint32_t)p->dev);
1460afa8e06SEd Maste 
1470afa8e06SEd Maste 	if (fido_nl_get_nfc_target(nl, (uint32_t)p->dev, &target) == 0)
1480afa8e06SEd Maste 		consume(&target, sizeof(target));
1490afa8e06SEd Maste 
1500afa8e06SEd Maste 	fido_nl_free(&nl);
1510afa8e06SEd Maste }
1520afa8e06SEd Maste 
1530afa8e06SEd Maste void
mutate(struct param * p,unsigned int seed,unsigned int flags)1540afa8e06SEd Maste mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
1550afa8e06SEd Maste {
1560afa8e06SEd Maste 	if (flags & MUTATE_SEED)
1570afa8e06SEd Maste 		p->seed = (int)seed;
1580afa8e06SEd Maste 
1590afa8e06SEd Maste 	if (flags & MUTATE_PARAM)
1600afa8e06SEd Maste 		mutate_int(&p->dev);
1610afa8e06SEd Maste 
1620afa8e06SEd Maste 	if (flags & MUTATE_WIREDATA)
1630afa8e06SEd Maste 		mutate_blob(&p->wiredata);
1640afa8e06SEd Maste }
165