xref: /freebsd/contrib/libfido2/fuzz/fuzz_mgmt.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
10afa8e06SEd Maste /*
2*2ccfa855SEd Maste  * Copyright (c) 2019-2022 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 <stdio.h>
110afa8e06SEd Maste #include <stdlib.h>
120afa8e06SEd Maste #include <string.h>
130afa8e06SEd Maste 
140afa8e06SEd Maste #include "mutator_aux.h"
150afa8e06SEd Maste #include "wiredata_fido2.h"
160afa8e06SEd Maste #include "dummy.h"
170afa8e06SEd Maste 
180afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h"
190afa8e06SEd Maste 
20f540a430SEd Maste #define MAXRPID	64
21f540a430SEd Maste 
220afa8e06SEd Maste struct param {
230afa8e06SEd Maste 	char pin1[MAXSTR];
240afa8e06SEd Maste 	char pin2[MAXSTR];
250afa8e06SEd Maste 	struct blob reset_wire_data;
260afa8e06SEd Maste 	struct blob info_wire_data;
270afa8e06SEd Maste 	struct blob set_pin_wire_data;
280afa8e06SEd Maste 	struct blob change_pin_wire_data;
290afa8e06SEd Maste 	struct blob retry_wire_data;
300afa8e06SEd Maste 	struct blob config_wire_data;
310afa8e06SEd Maste 	int seed;
320afa8e06SEd Maste };
330afa8e06SEd Maste 
340afa8e06SEd Maste static const uint8_t dummy_reset_wire_data[] = {
350afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
360afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
370afa8e06SEd Maste 	WIREDATA_CTAP_KEEPALIVE,
380afa8e06SEd Maste 	WIREDATA_CTAP_KEEPALIVE,
390afa8e06SEd Maste 	WIREDATA_CTAP_KEEPALIVE,
400afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_STATUS,
410afa8e06SEd Maste };
420afa8e06SEd Maste 
430afa8e06SEd Maste static const uint8_t dummy_info_wire_data[] = {
440afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
450afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
460afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
470afa8e06SEd Maste };
480afa8e06SEd Maste 
490afa8e06SEd Maste static const uint8_t dummy_set_pin_wire_data[] = {
500afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
510afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
520afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_AUTHKEY,
530afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_STATUS,
540afa8e06SEd Maste };
550afa8e06SEd Maste 
560afa8e06SEd Maste static const uint8_t dummy_change_pin_wire_data[] = {
570afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
580afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
590afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_AUTHKEY,
600afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_STATUS,
610afa8e06SEd Maste };
620afa8e06SEd Maste 
630afa8e06SEd Maste static const uint8_t dummy_retry_wire_data[] = {
640afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
650afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
660afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_RETRIES,
670afa8e06SEd Maste };
680afa8e06SEd Maste 
690afa8e06SEd Maste static const uint8_t dummy_config_wire_data[] = {
700afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
710afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
720afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_STATUS,
730afa8e06SEd Maste };
740afa8e06SEd Maste 
750afa8e06SEd Maste struct param *
unpack(const uint8_t * ptr,size_t len)760afa8e06SEd Maste unpack(const uint8_t *ptr, size_t len)
770afa8e06SEd Maste {
780afa8e06SEd Maste 	cbor_item_t *item = NULL, **v;
790afa8e06SEd Maste 	struct cbor_load_result cbor;
800afa8e06SEd Maste 	struct param *p;
810afa8e06SEd Maste 	int ok = -1;
820afa8e06SEd Maste 
830afa8e06SEd Maste 	if ((p = calloc(1, sizeof(*p))) == NULL ||
840afa8e06SEd Maste 	    (item = cbor_load(ptr, len, &cbor)) == NULL ||
850afa8e06SEd Maste 	    cbor.read != len ||
860afa8e06SEd Maste 	    cbor_isa_array(item) == false ||
870afa8e06SEd Maste 	    cbor_array_is_definite(item) == false ||
880afa8e06SEd Maste 	    cbor_array_size(item) != 9 ||
890afa8e06SEd Maste 	    (v = cbor_array_handle(item)) == NULL)
900afa8e06SEd Maste 		goto fail;
910afa8e06SEd Maste 
920afa8e06SEd Maste 	if (unpack_int(v[0], &p->seed) < 0 ||
930afa8e06SEd Maste 	    unpack_string(v[1], p->pin1) < 0 ||
940afa8e06SEd Maste 	    unpack_string(v[2], p->pin2) < 0 ||
950afa8e06SEd Maste 	    unpack_blob(v[3], &p->reset_wire_data) < 0 ||
960afa8e06SEd Maste 	    unpack_blob(v[4], &p->info_wire_data) < 0 ||
970afa8e06SEd Maste 	    unpack_blob(v[5], &p->set_pin_wire_data) < 0 ||
980afa8e06SEd Maste 	    unpack_blob(v[6], &p->change_pin_wire_data) < 0 ||
990afa8e06SEd Maste 	    unpack_blob(v[7], &p->retry_wire_data) < 0 ||
1000afa8e06SEd Maste 	    unpack_blob(v[8], &p->config_wire_data) < 0)
1010afa8e06SEd Maste 		goto fail;
1020afa8e06SEd Maste 
1030afa8e06SEd Maste 	ok = 0;
1040afa8e06SEd Maste fail:
1050afa8e06SEd Maste 	if (ok < 0) {
1060afa8e06SEd Maste 		free(p);
1070afa8e06SEd Maste 		p = NULL;
1080afa8e06SEd Maste 	}
1090afa8e06SEd Maste 
1100afa8e06SEd Maste 	if (item)
1110afa8e06SEd Maste 		cbor_decref(&item);
1120afa8e06SEd Maste 
1130afa8e06SEd Maste 	return p;
1140afa8e06SEd Maste }
1150afa8e06SEd Maste 
1160afa8e06SEd Maste size_t
pack(uint8_t * ptr,size_t len,const struct param * p)1170afa8e06SEd Maste pack(uint8_t *ptr, size_t len, const struct param *p)
1180afa8e06SEd Maste {
1190afa8e06SEd Maste 	cbor_item_t *argv[9], *array = NULL;
1200afa8e06SEd Maste 	size_t cbor_alloc_len, cbor_len = 0;
1210afa8e06SEd Maste 	unsigned char *cbor = NULL;
1220afa8e06SEd Maste 
1230afa8e06SEd Maste 	memset(argv, 0, sizeof(argv));
1240afa8e06SEd Maste 
1250afa8e06SEd Maste 	if ((array = cbor_new_definite_array(9)) == NULL ||
1260afa8e06SEd Maste 	    (argv[0] = pack_int(p->seed)) == NULL ||
1270afa8e06SEd Maste 	    (argv[1] = pack_string(p->pin1)) == NULL ||
1280afa8e06SEd Maste 	    (argv[2] = pack_string(p->pin2)) == NULL ||
1290afa8e06SEd Maste 	    (argv[3] = pack_blob(&p->reset_wire_data)) == NULL ||
1300afa8e06SEd Maste 	    (argv[4] = pack_blob(&p->info_wire_data)) == NULL ||
1310afa8e06SEd Maste 	    (argv[5] = pack_blob(&p->set_pin_wire_data)) == NULL ||
1320afa8e06SEd Maste 	    (argv[6] = pack_blob(&p->change_pin_wire_data)) == NULL ||
1330afa8e06SEd Maste 	    (argv[7] = pack_blob(&p->retry_wire_data)) == NULL ||
1340afa8e06SEd Maste 	    (argv[8] = pack_blob(&p->config_wire_data)) == NULL)
1350afa8e06SEd Maste 		goto fail;
1360afa8e06SEd Maste 
1370afa8e06SEd Maste 	for (size_t i = 0; i < 9; i++)
1380afa8e06SEd Maste 		if (cbor_array_push(array, argv[i]) == false)
1390afa8e06SEd Maste 			goto fail;
1400afa8e06SEd Maste 
1410afa8e06SEd Maste 	if ((cbor_len = cbor_serialize_alloc(array, &cbor,
142*2ccfa855SEd Maste 	    &cbor_alloc_len)) == 0 || cbor_len > len) {
1430afa8e06SEd Maste 		cbor_len = 0;
1440afa8e06SEd Maste 		goto fail;
1450afa8e06SEd Maste 	}
1460afa8e06SEd Maste 
1470afa8e06SEd Maste 	memcpy(ptr, cbor, cbor_len);
1480afa8e06SEd Maste fail:
1490afa8e06SEd Maste 	for (size_t i = 0; i < 9; i++)
1500afa8e06SEd Maste 		if (argv[i])
1510afa8e06SEd Maste 			cbor_decref(&argv[i]);
1520afa8e06SEd Maste 
1530afa8e06SEd Maste 	if (array)
1540afa8e06SEd Maste 		cbor_decref(&array);
1550afa8e06SEd Maste 
1560afa8e06SEd Maste 	free(cbor);
1570afa8e06SEd Maste 
1580afa8e06SEd Maste 	return cbor_len;
1590afa8e06SEd Maste }
1600afa8e06SEd Maste 
1610afa8e06SEd Maste size_t
pack_dummy(uint8_t * ptr,size_t len)1620afa8e06SEd Maste pack_dummy(uint8_t *ptr, size_t len)
1630afa8e06SEd Maste {
1640afa8e06SEd Maste 	struct param dummy;
165*2ccfa855SEd Maste 	uint8_t blob[MAXCORPUS];
1660afa8e06SEd Maste 	size_t blob_len;
1670afa8e06SEd Maste 
1680afa8e06SEd Maste 	memset(&dummy, 0, sizeof(dummy));
1690afa8e06SEd Maste 
1700afa8e06SEd Maste 	strlcpy(dummy.pin1, dummy_pin1, sizeof(dummy.pin1));
1710afa8e06SEd Maste 	strlcpy(dummy.pin2, dummy_pin2, sizeof(dummy.pin2));
1720afa8e06SEd Maste 
1730afa8e06SEd Maste 	dummy.reset_wire_data.len = sizeof(dummy_reset_wire_data);
1740afa8e06SEd Maste 	dummy.info_wire_data.len = sizeof(dummy_info_wire_data);
1750afa8e06SEd Maste 	dummy.set_pin_wire_data.len = sizeof(dummy_set_pin_wire_data);
1760afa8e06SEd Maste 	dummy.change_pin_wire_data.len = sizeof(dummy_change_pin_wire_data);
1770afa8e06SEd Maste 	dummy.retry_wire_data.len = sizeof(dummy_retry_wire_data);
1780afa8e06SEd Maste 	dummy.config_wire_data.len = sizeof(dummy_config_wire_data);
1790afa8e06SEd Maste 
1800afa8e06SEd Maste 	memcpy(&dummy.reset_wire_data.body, &dummy_reset_wire_data,
1810afa8e06SEd Maste 	    dummy.reset_wire_data.len);
1820afa8e06SEd Maste 	memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data,
1830afa8e06SEd Maste 	    dummy.info_wire_data.len);
1840afa8e06SEd Maste 	memcpy(&dummy.set_pin_wire_data.body, &dummy_set_pin_wire_data,
1850afa8e06SEd Maste 	    dummy.set_pin_wire_data.len);
1860afa8e06SEd Maste 	memcpy(&dummy.change_pin_wire_data.body, &dummy_change_pin_wire_data,
1870afa8e06SEd Maste 	    dummy.change_pin_wire_data.len);
1880afa8e06SEd Maste 	memcpy(&dummy.retry_wire_data.body, &dummy_retry_wire_data,
1890afa8e06SEd Maste 	    dummy.retry_wire_data.len);
1900afa8e06SEd Maste 	memcpy(&dummy.config_wire_data.body, &dummy_config_wire_data,
1910afa8e06SEd Maste 	    dummy.config_wire_data.len);
1920afa8e06SEd Maste 
1930afa8e06SEd Maste 	assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
1940afa8e06SEd Maste 
1950afa8e06SEd Maste 	if (blob_len > len) {
1960afa8e06SEd Maste 		memcpy(ptr, blob, len);
1970afa8e06SEd Maste 		return len;
1980afa8e06SEd Maste 	}
1990afa8e06SEd Maste 
2000afa8e06SEd Maste 	memcpy(ptr, blob, blob_len);
2010afa8e06SEd Maste 
2020afa8e06SEd Maste 	return blob_len;
2030afa8e06SEd Maste }
2040afa8e06SEd Maste 
2050afa8e06SEd Maste static void
dev_reset(const struct param * p)2060afa8e06SEd Maste dev_reset(const struct param *p)
2070afa8e06SEd Maste {
2080afa8e06SEd Maste 	fido_dev_t *dev;
2090afa8e06SEd Maste 
2100afa8e06SEd Maste 	set_wire_data(p->reset_wire_data.body, p->reset_wire_data.len);
2110afa8e06SEd Maste 
2120afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
2130afa8e06SEd Maste 		return;
2140afa8e06SEd Maste 
2150afa8e06SEd Maste 	fido_dev_reset(dev);
2160afa8e06SEd Maste 	fido_dev_close(dev);
2170afa8e06SEd Maste 	fido_dev_free(&dev);
2180afa8e06SEd Maste }
2190afa8e06SEd Maste 
2200afa8e06SEd Maste static void
dev_get_cbor_info(const struct param * p)2210afa8e06SEd Maste dev_get_cbor_info(const struct param *p)
2220afa8e06SEd Maste {
2230afa8e06SEd Maste 	fido_dev_t *dev;
2240afa8e06SEd Maste 	fido_cbor_info_t *ci;
2250afa8e06SEd Maste 	uint64_t n;
2260afa8e06SEd Maste 	uint8_t proto, major, minor, build, flags;
227*2ccfa855SEd Maste 	bool v;
2280afa8e06SEd Maste 
2290afa8e06SEd Maste 	set_wire_data(p->info_wire_data.body, p->info_wire_data.len);
2300afa8e06SEd Maste 
2310afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
2320afa8e06SEd Maste 		return;
2330afa8e06SEd Maste 
2340afa8e06SEd Maste 	proto = fido_dev_protocol(dev);
2350afa8e06SEd Maste 	major = fido_dev_major(dev);
2360afa8e06SEd Maste 	minor = fido_dev_minor(dev);
2370afa8e06SEd Maste 	build = fido_dev_build(dev);
2380afa8e06SEd Maste 	flags = fido_dev_flags(dev);
2390afa8e06SEd Maste 
2400afa8e06SEd Maste 	consume(&proto, sizeof(proto));
2410afa8e06SEd Maste 	consume(&major, sizeof(major));
2420afa8e06SEd Maste 	consume(&minor, sizeof(minor));
2430afa8e06SEd Maste 	consume(&build, sizeof(build));
2440afa8e06SEd Maste 	consume(&flags, sizeof(flags));
2450afa8e06SEd Maste 
2460afa8e06SEd Maste 	if ((ci = fido_cbor_info_new()) == NULL)
2470afa8e06SEd Maste 		goto out;
2480afa8e06SEd Maste 
2490afa8e06SEd Maste 	fido_dev_get_cbor_info(dev, ci);
2500afa8e06SEd Maste 
2510afa8e06SEd Maste 	for (size_t i = 0; i < fido_cbor_info_versions_len(ci); i++) {
2520afa8e06SEd Maste 		char * const *sa = fido_cbor_info_versions_ptr(ci);
2530afa8e06SEd Maste 		consume(sa[i], strlen(sa[i]));
2540afa8e06SEd Maste 	}
2550afa8e06SEd Maste 
2560afa8e06SEd Maste 	for (size_t i = 0; i < fido_cbor_info_extensions_len(ci); i++) {
2570afa8e06SEd Maste 		char * const *sa = fido_cbor_info_extensions_ptr(ci);
2580afa8e06SEd Maste 		consume(sa[i], strlen(sa[i]));
2590afa8e06SEd Maste 	}
2600afa8e06SEd Maste 
2610afa8e06SEd Maste 	for (size_t i = 0; i < fido_cbor_info_transports_len(ci); i++) {
2620afa8e06SEd Maste 		char * const *sa = fido_cbor_info_transports_ptr(ci);
2630afa8e06SEd Maste 		consume(sa[i], strlen(sa[i]));
2640afa8e06SEd Maste 	}
2650afa8e06SEd Maste 
2660afa8e06SEd Maste 	for (size_t i = 0; i < fido_cbor_info_options_len(ci); i++) {
2670afa8e06SEd Maste 		char * const *sa = fido_cbor_info_options_name_ptr(ci);
2680afa8e06SEd Maste 		const bool *va = fido_cbor_info_options_value_ptr(ci);
2690afa8e06SEd Maste 		consume(sa[i], strlen(sa[i]));
2700afa8e06SEd Maste 		consume(&va[i], sizeof(va[i]));
2710afa8e06SEd Maste 	}
2720afa8e06SEd Maste 
2730afa8e06SEd Maste 	/* +1 on purpose */
2740afa8e06SEd Maste 	for (size_t i = 0; i <= fido_cbor_info_algorithm_count(ci); i++) {
2750afa8e06SEd Maste 		const char *type = fido_cbor_info_algorithm_type(ci, i);
2760afa8e06SEd Maste 		int cose = fido_cbor_info_algorithm_cose(ci, i);
2770afa8e06SEd Maste 		consume_str(type);
2780afa8e06SEd Maste 		consume(&cose, sizeof(cose));
2790afa8e06SEd Maste 	}
2800afa8e06SEd Maste 
281*2ccfa855SEd Maste 	for (size_t i = 0; i < fido_cbor_info_certs_len(ci); i++) {
282*2ccfa855SEd Maste 		char * const *na = fido_cbor_info_certs_name_ptr(ci);
283*2ccfa855SEd Maste 		const uint64_t *va = fido_cbor_info_certs_value_ptr(ci);
284*2ccfa855SEd Maste 		consume(na[i], strlen(na[i]));
285*2ccfa855SEd Maste 		consume(&va[i], sizeof(va[i]));
286*2ccfa855SEd Maste 	}
287*2ccfa855SEd Maste 
2880afa8e06SEd Maste 	n = fido_cbor_info_maxmsgsiz(ci);
2890afa8e06SEd Maste 	consume(&n, sizeof(n));
2900afa8e06SEd Maste 	n = fido_cbor_info_maxcredbloblen(ci);
2910afa8e06SEd Maste 	consume(&n, sizeof(n));
2920afa8e06SEd Maste 	n = fido_cbor_info_maxcredcntlst(ci);
2930afa8e06SEd Maste 	consume(&n, sizeof(n));
2940afa8e06SEd Maste 	n = fido_cbor_info_maxcredidlen(ci);
2950afa8e06SEd Maste 	consume(&n, sizeof(n));
296*2ccfa855SEd Maste 	n = fido_cbor_info_maxlargeblob(ci);
297*2ccfa855SEd Maste 	consume(&n, sizeof(n));
2980afa8e06SEd Maste 	n = fido_cbor_info_fwversion(ci);
2990afa8e06SEd Maste 	consume(&n, sizeof(n));
300*2ccfa855SEd Maste 	n = fido_cbor_info_minpinlen(ci);
301*2ccfa855SEd Maste 	consume(&n, sizeof(n));
302*2ccfa855SEd Maste 	n = fido_cbor_info_maxrpid_minpinlen(ci);
303*2ccfa855SEd Maste 	consume(&n, sizeof(n));
304*2ccfa855SEd Maste 	n = fido_cbor_info_uv_attempts(ci);
305*2ccfa855SEd Maste 	consume(&n, sizeof(n));
306*2ccfa855SEd Maste 	n = fido_cbor_info_uv_modality(ci);
307*2ccfa855SEd Maste 	consume(&n, sizeof(n));
308*2ccfa855SEd Maste 	n = (uint64_t)fido_cbor_info_rk_remaining(ci);
309*2ccfa855SEd Maste 	consume(&n, sizeof(n));
3100afa8e06SEd Maste 
3110afa8e06SEd Maste 	consume(fido_cbor_info_aaguid_ptr(ci), fido_cbor_info_aaguid_len(ci));
3120afa8e06SEd Maste 	consume(fido_cbor_info_protocols_ptr(ci),
3130afa8e06SEd Maste 	    fido_cbor_info_protocols_len(ci));
3140afa8e06SEd Maste 
315*2ccfa855SEd Maste 	v = fido_cbor_info_new_pin_required(ci);
316*2ccfa855SEd Maste 	consume(&v, sizeof(v));
317*2ccfa855SEd Maste 
3180afa8e06SEd Maste out:
3190afa8e06SEd Maste 	fido_dev_close(dev);
3200afa8e06SEd Maste 	fido_dev_free(&dev);
3210afa8e06SEd Maste 
3220afa8e06SEd Maste 	fido_cbor_info_free(&ci);
3230afa8e06SEd Maste }
3240afa8e06SEd Maste 
3250afa8e06SEd Maste static void
dev_set_pin(const struct param * p)3260afa8e06SEd Maste dev_set_pin(const struct param *p)
3270afa8e06SEd Maste {
3280afa8e06SEd Maste 	fido_dev_t *dev;
3290afa8e06SEd Maste 
3300afa8e06SEd Maste 	set_wire_data(p->set_pin_wire_data.body, p->set_pin_wire_data.len);
3310afa8e06SEd Maste 
3320afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
3330afa8e06SEd Maste 		return;
3340afa8e06SEd Maste 
3350afa8e06SEd Maste 	fido_dev_set_pin(dev, p->pin1, NULL);
3360afa8e06SEd Maste 	fido_dev_close(dev);
3370afa8e06SEd Maste 	fido_dev_free(&dev);
3380afa8e06SEd Maste }
3390afa8e06SEd Maste 
3400afa8e06SEd Maste static void
dev_change_pin(const struct param * p)3410afa8e06SEd Maste dev_change_pin(const struct param *p)
3420afa8e06SEd Maste {
3430afa8e06SEd Maste 	fido_dev_t *dev;
3440afa8e06SEd Maste 
3450afa8e06SEd Maste 	set_wire_data(p->change_pin_wire_data.body, p->change_pin_wire_data.len);
3460afa8e06SEd Maste 
3470afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
3480afa8e06SEd Maste 		return;
3490afa8e06SEd Maste 
3500afa8e06SEd Maste 	fido_dev_set_pin(dev, p->pin2, p->pin1);
3510afa8e06SEd Maste 	fido_dev_close(dev);
3520afa8e06SEd Maste 	fido_dev_free(&dev);
3530afa8e06SEd Maste }
3540afa8e06SEd Maste 
3550afa8e06SEd Maste static void
dev_get_retry_count(const struct param * p)3560afa8e06SEd Maste dev_get_retry_count(const struct param *p)
3570afa8e06SEd Maste {
3580afa8e06SEd Maste 	fido_dev_t *dev;
3590afa8e06SEd Maste 	int n = 0;
3600afa8e06SEd Maste 
3610afa8e06SEd Maste 	set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len);
3620afa8e06SEd Maste 
3630afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
3640afa8e06SEd Maste 		return;
3650afa8e06SEd Maste 
3660afa8e06SEd Maste 	fido_dev_get_retry_count(dev, &n);
3670afa8e06SEd Maste 	consume(&n, sizeof(n));
3680afa8e06SEd Maste 	fido_dev_close(dev);
3690afa8e06SEd Maste 	fido_dev_free(&dev);
3700afa8e06SEd Maste }
3710afa8e06SEd Maste 
3720afa8e06SEd Maste static void
dev_get_uv_retry_count(const struct param * p)3730afa8e06SEd Maste dev_get_uv_retry_count(const struct param *p)
3740afa8e06SEd Maste {
3750afa8e06SEd Maste 	fido_dev_t *dev;
3760afa8e06SEd Maste 	int n = 0;
3770afa8e06SEd Maste 
3780afa8e06SEd Maste 	set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len);
3790afa8e06SEd Maste 
3800afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
3810afa8e06SEd Maste 		return;
3820afa8e06SEd Maste 
3830afa8e06SEd Maste 	fido_dev_get_uv_retry_count(dev, &n);
3840afa8e06SEd Maste 	consume(&n, sizeof(n));
3850afa8e06SEd Maste 	fido_dev_close(dev);
3860afa8e06SEd Maste 	fido_dev_free(&dev);
3870afa8e06SEd Maste }
3880afa8e06SEd Maste 
3890afa8e06SEd Maste static void
dev_enable_entattest(const struct param * p)3900afa8e06SEd Maste dev_enable_entattest(const struct param *p)
3910afa8e06SEd Maste {
3920afa8e06SEd Maste 	fido_dev_t *dev;
3930afa8e06SEd Maste 	const char *pin;
3940afa8e06SEd Maste 	int r;
3950afa8e06SEd Maste 
3960afa8e06SEd Maste 	set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
3970afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
3980afa8e06SEd Maste 		return;
3990afa8e06SEd Maste 	pin = p->pin1;
4000afa8e06SEd Maste 	if (strlen(pin) == 0)
4010afa8e06SEd Maste 		pin = NULL;
4020afa8e06SEd Maste 	r = fido_dev_enable_entattest(dev, pin);
4030afa8e06SEd Maste 	consume_str(fido_strerr(r));
4040afa8e06SEd Maste 	fido_dev_close(dev);
4050afa8e06SEd Maste 	fido_dev_free(&dev);
4060afa8e06SEd Maste }
4070afa8e06SEd Maste 
4080afa8e06SEd Maste static void
dev_toggle_always_uv(const struct param * p)4090afa8e06SEd Maste dev_toggle_always_uv(const struct param *p)
4100afa8e06SEd Maste {
4110afa8e06SEd Maste 	fido_dev_t *dev;
4120afa8e06SEd Maste 	const char *pin;
4130afa8e06SEd Maste 	int r;
4140afa8e06SEd Maste 
4150afa8e06SEd Maste 	set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
4160afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
4170afa8e06SEd Maste 		return;
4180afa8e06SEd Maste 	pin = p->pin1;
4190afa8e06SEd Maste 	if (strlen(pin) == 0)
4200afa8e06SEd Maste 		pin = NULL;
4210afa8e06SEd Maste 	r = fido_dev_toggle_always_uv(dev, pin);
4220afa8e06SEd Maste 	consume_str(fido_strerr(r));
4230afa8e06SEd Maste 	fido_dev_close(dev);
4240afa8e06SEd Maste 	fido_dev_free(&dev);
4250afa8e06SEd Maste }
4260afa8e06SEd Maste 
4270afa8e06SEd Maste static void
dev_force_pin_change(const struct param * p)4280afa8e06SEd Maste dev_force_pin_change(const struct param *p)
4290afa8e06SEd Maste {
4300afa8e06SEd Maste 	fido_dev_t *dev;
4310afa8e06SEd Maste 	const char *pin;
4320afa8e06SEd Maste 	int r;
4330afa8e06SEd Maste 
4340afa8e06SEd Maste 	set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
4350afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
4360afa8e06SEd Maste 		return;
4370afa8e06SEd Maste 	pin = p->pin1;
4380afa8e06SEd Maste 	if (strlen(pin) == 0)
4390afa8e06SEd Maste 		pin = NULL;
4400afa8e06SEd Maste 	r = fido_dev_force_pin_change(dev, pin);
4410afa8e06SEd Maste 	consume_str(fido_strerr(r));
4420afa8e06SEd Maste 	fido_dev_close(dev);
4430afa8e06SEd Maste 	fido_dev_free(&dev);
4440afa8e06SEd Maste }
4450afa8e06SEd Maste 
4460afa8e06SEd Maste static void
dev_set_pin_minlen(const struct param * p)4470afa8e06SEd Maste dev_set_pin_minlen(const struct param *p)
4480afa8e06SEd Maste {
4490afa8e06SEd Maste 	fido_dev_t *dev;
4500afa8e06SEd Maste 	const char *pin;
4510afa8e06SEd Maste 	int r;
4520afa8e06SEd Maste 
4530afa8e06SEd Maste 	set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
4540afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
4550afa8e06SEd Maste 		return;
4560afa8e06SEd Maste 	pin = p->pin1;
4570afa8e06SEd Maste 	if (strlen(pin) == 0)
4580afa8e06SEd Maste 		pin = NULL;
4590afa8e06SEd Maste 	r = fido_dev_set_pin_minlen(dev, strlen(p->pin2), pin);
4600afa8e06SEd Maste 	consume_str(fido_strerr(r));
4610afa8e06SEd Maste 	fido_dev_close(dev);
4620afa8e06SEd Maste 	fido_dev_free(&dev);
4630afa8e06SEd Maste }
4640afa8e06SEd Maste 
465f540a430SEd Maste static void
dev_set_pin_minlen_rpid(const struct param * p)466f540a430SEd Maste dev_set_pin_minlen_rpid(const struct param *p)
467f540a430SEd Maste {
468f540a430SEd Maste 	fido_dev_t *dev;
469f540a430SEd Maste 	const char *rpid[MAXRPID];
470f540a430SEd Maste 	const char *pin;
471f540a430SEd Maste 	size_t n;
472f540a430SEd Maste 	int r;
473f540a430SEd Maste 
474f540a430SEd Maste 	set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
475f540a430SEd Maste 	if ((dev = open_dev(0)) == NULL)
476f540a430SEd Maste 		return;
477f540a430SEd Maste 	n = uniform_random(MAXRPID);
478f540a430SEd Maste 	for (size_t i = 0; i < n; i++)
479f540a430SEd Maste 		rpid[i] = dummy_rp_id;
480f540a430SEd Maste 	pin = p->pin1;
481f540a430SEd Maste 	if (strlen(pin) == 0)
482f540a430SEd Maste 		pin = NULL;
483f540a430SEd Maste 	r = fido_dev_set_pin_minlen_rpid(dev, rpid, n, pin);
484f540a430SEd Maste 	consume_str(fido_strerr(r));
485f540a430SEd Maste 	fido_dev_close(dev);
486f540a430SEd Maste 	fido_dev_free(&dev);
487f540a430SEd Maste }
488f540a430SEd Maste 
4890afa8e06SEd Maste void
test(const struct param * p)4900afa8e06SEd Maste test(const struct param *p)
4910afa8e06SEd Maste {
4920afa8e06SEd Maste 	prng_init((unsigned int)p->seed);
493f540a430SEd Maste 	fuzz_clock_reset();
4940afa8e06SEd Maste 	fido_init(FIDO_DEBUG);
4950afa8e06SEd Maste 	fido_set_log_handler(consume_str);
4960afa8e06SEd Maste 
4970afa8e06SEd Maste 	dev_reset(p);
4980afa8e06SEd Maste 	dev_get_cbor_info(p);
4990afa8e06SEd Maste 	dev_set_pin(p);
5000afa8e06SEd Maste 	dev_change_pin(p);
5010afa8e06SEd Maste 	dev_get_retry_count(p);
5020afa8e06SEd Maste 	dev_get_uv_retry_count(p);
5030afa8e06SEd Maste 	dev_enable_entattest(p);
5040afa8e06SEd Maste 	dev_toggle_always_uv(p);
5050afa8e06SEd Maste 	dev_force_pin_change(p);
5060afa8e06SEd Maste 	dev_set_pin_minlen(p);
507f540a430SEd Maste 	dev_set_pin_minlen_rpid(p);
5080afa8e06SEd Maste }
5090afa8e06SEd Maste 
5100afa8e06SEd Maste void
mutate(struct param * p,unsigned int seed,unsigned int flags)5110afa8e06SEd Maste mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
5120afa8e06SEd Maste {
5130afa8e06SEd Maste 	if (flags & MUTATE_SEED)
5140afa8e06SEd Maste 		p->seed = (int)seed;
5150afa8e06SEd Maste 
5160afa8e06SEd Maste 	if (flags & MUTATE_PARAM) {
5170afa8e06SEd Maste 		mutate_string(p->pin1);
5180afa8e06SEd Maste 		mutate_string(p->pin2);
5190afa8e06SEd Maste 	}
5200afa8e06SEd Maste 
5210afa8e06SEd Maste 	if (flags & MUTATE_WIREDATA) {
5220afa8e06SEd Maste 		mutate_blob(&p->reset_wire_data);
5230afa8e06SEd Maste 		mutate_blob(&p->info_wire_data);
5240afa8e06SEd Maste 		mutate_blob(&p->set_pin_wire_data);
5250afa8e06SEd Maste 		mutate_blob(&p->change_pin_wire_data);
5260afa8e06SEd Maste 		mutate_blob(&p->retry_wire_data);
5270afa8e06SEd Maste 	}
5280afa8e06SEd Maste }
529