xref: /freebsd/contrib/libfido2/fuzz/fuzz_bio.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
10afa8e06SEd Maste /*
20afa8e06SEd Maste  * Copyright (c) 2019 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 
200afa8e06SEd Maste /* Parameter set defining a FIDO2 credential management operation. */
210afa8e06SEd Maste struct param {
220afa8e06SEd Maste 	char pin[MAXSTR];
230afa8e06SEd Maste 	char name[MAXSTR];
240afa8e06SEd Maste 	int seed;
250afa8e06SEd Maste 	struct blob id;
260afa8e06SEd Maste 	struct blob info_wire_data;
270afa8e06SEd Maste 	struct blob enroll_wire_data;
280afa8e06SEd Maste 	struct blob list_wire_data;
290afa8e06SEd Maste 	struct blob set_name_wire_data;
300afa8e06SEd Maste 	struct blob remove_wire_data;
310afa8e06SEd Maste };
320afa8e06SEd Maste 
330afa8e06SEd Maste /*
340afa8e06SEd Maste  * Collection of HID reports from an authenticator issued with a FIDO2
350afa8e06SEd Maste  * 'getFingerprintSensorInfo' bio enrollment command.
360afa8e06SEd Maste  */
370afa8e06SEd Maste static const uint8_t dummy_info_wire_data[] = {
380afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
390afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
400afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_BIO_INFO,
410afa8e06SEd Maste };
420afa8e06SEd Maste 
430afa8e06SEd Maste /*
440afa8e06SEd Maste  * Collection of HID reports from an authenticator issued with FIDO2
450afa8e06SEd Maste  * 'enrollBegin' + 'enrollCaptureNextSample' bio enrollment commands.
460afa8e06SEd Maste  */
470afa8e06SEd Maste static const uint8_t dummy_enroll_wire_data[] = {
480afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
490afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
500afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_AUTHKEY,
510afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_PINTOKEN,
520afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_BIO_ENROLL,
530afa8e06SEd Maste };
540afa8e06SEd Maste 
550afa8e06SEd Maste /*
560afa8e06SEd Maste  * Collection of HID reports from an authenticator issued with a FIDO2
570afa8e06SEd Maste  * 'enumerateEnrollments' bio enrollment command.
580afa8e06SEd Maste  */
590afa8e06SEd Maste static const uint8_t dummy_list_wire_data[] = {
600afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
610afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
620afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_AUTHKEY,
630afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_PINTOKEN,
640afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_BIO_ENUM,
650afa8e06SEd Maste };
660afa8e06SEd Maste 
670afa8e06SEd Maste /*
680afa8e06SEd Maste  * Collection of HID reports from an authenticator issued with a FIDO2
690afa8e06SEd Maste  * 'setFriendlyName' bio enrollment command.
700afa8e06SEd Maste  */
710afa8e06SEd Maste static const uint8_t dummy_set_name_wire_data[] = {
720afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
730afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
740afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_AUTHKEY,
750afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_PINTOKEN,
760afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_STATUS,
770afa8e06SEd Maste };
780afa8e06SEd Maste 
790afa8e06SEd Maste /*
800afa8e06SEd Maste  * Collection of HID reports from an authenticator issued with a FIDO2
810afa8e06SEd Maste  * 'removeEnrollment' bio enrollment command.
820afa8e06SEd Maste  */
830afa8e06SEd Maste static const uint8_t dummy_remove_wire_data[] = {
840afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
850afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
860afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_AUTHKEY,
870afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_PINTOKEN,
880afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_STATUS,
890afa8e06SEd Maste };
900afa8e06SEd Maste 
910afa8e06SEd Maste struct param *
unpack(const uint8_t * ptr,size_t len)920afa8e06SEd Maste unpack(const uint8_t *ptr, size_t len)
930afa8e06SEd Maste {
940afa8e06SEd Maste 	cbor_item_t *item = NULL, **v;
950afa8e06SEd Maste 	struct cbor_load_result cbor;
960afa8e06SEd Maste 	struct param *p;
970afa8e06SEd Maste 	int ok = -1;
980afa8e06SEd Maste 
990afa8e06SEd Maste 	if ((p = calloc(1, sizeof(*p))) == NULL ||
1000afa8e06SEd Maste 	    (item = cbor_load(ptr, len, &cbor)) == NULL ||
1010afa8e06SEd Maste 	    cbor.read != len ||
1020afa8e06SEd Maste 	    cbor_isa_array(item) == false ||
1030afa8e06SEd Maste 	    cbor_array_is_definite(item) == false ||
1040afa8e06SEd Maste 	    cbor_array_size(item) != 9 ||
1050afa8e06SEd Maste 	    (v = cbor_array_handle(item)) == NULL)
1060afa8e06SEd Maste 		goto fail;
1070afa8e06SEd Maste 
1080afa8e06SEd Maste 	if (unpack_int(v[0], &p->seed) < 0 ||
1090afa8e06SEd Maste 	    unpack_string(v[1], p->pin) < 0 ||
1100afa8e06SEd Maste 	    unpack_string(v[2], p->name) < 0 ||
1110afa8e06SEd Maste 	    unpack_blob(v[3], &p->id) < 0 ||
1120afa8e06SEd Maste 	    unpack_blob(v[4], &p->info_wire_data) < 0 ||
1130afa8e06SEd Maste 	    unpack_blob(v[5], &p->enroll_wire_data) < 0 ||
1140afa8e06SEd Maste 	    unpack_blob(v[6], &p->list_wire_data) < 0 ||
1150afa8e06SEd Maste 	    unpack_blob(v[7], &p->set_name_wire_data) < 0 ||
1160afa8e06SEd Maste 	    unpack_blob(v[8], &p->remove_wire_data) < 0)
1170afa8e06SEd Maste 		goto fail;
1180afa8e06SEd Maste 
1190afa8e06SEd Maste 	ok = 0;
1200afa8e06SEd Maste fail:
1210afa8e06SEd Maste 	if (ok < 0) {
1220afa8e06SEd Maste 		free(p);
1230afa8e06SEd Maste 		p = NULL;
1240afa8e06SEd Maste 	}
1250afa8e06SEd Maste 
1260afa8e06SEd Maste 	if (item)
1270afa8e06SEd Maste 		cbor_decref(&item);
1280afa8e06SEd Maste 
1290afa8e06SEd Maste 	return p;
1300afa8e06SEd Maste }
1310afa8e06SEd Maste 
1320afa8e06SEd Maste size_t
pack(uint8_t * ptr,size_t len,const struct param * p)1330afa8e06SEd Maste pack(uint8_t *ptr, size_t len, const struct param *p)
1340afa8e06SEd Maste {
1350afa8e06SEd Maste 	cbor_item_t *argv[9], *array = NULL;
1360afa8e06SEd Maste 	size_t cbor_alloc_len, cbor_len = 0;
1370afa8e06SEd Maste 	unsigned char *cbor = NULL;
1380afa8e06SEd Maste 
1390afa8e06SEd Maste 	memset(argv, 0, sizeof(argv));
1400afa8e06SEd Maste 
1410afa8e06SEd Maste 	if ((array = cbor_new_definite_array(9)) == NULL ||
1420afa8e06SEd Maste 	    (argv[0] = pack_int(p->seed)) == NULL ||
1430afa8e06SEd Maste 	    (argv[1] = pack_string(p->pin)) == NULL ||
1440afa8e06SEd Maste 	    (argv[2] = pack_string(p->name)) == NULL ||
1450afa8e06SEd Maste 	    (argv[3] = pack_blob(&p->id)) == NULL ||
1460afa8e06SEd Maste 	    (argv[4] = pack_blob(&p->info_wire_data)) == NULL ||
1470afa8e06SEd Maste 	    (argv[5] = pack_blob(&p->enroll_wire_data)) == NULL ||
1480afa8e06SEd Maste 	    (argv[6] = pack_blob(&p->list_wire_data)) == NULL ||
1490afa8e06SEd Maste 	    (argv[7] = pack_blob(&p->set_name_wire_data)) == NULL ||
1500afa8e06SEd Maste 	    (argv[8] = pack_blob(&p->remove_wire_data)) == NULL)
1510afa8e06SEd Maste 		goto fail;
1520afa8e06SEd Maste 
1530afa8e06SEd Maste 	for (size_t i = 0; i < 9; i++)
1540afa8e06SEd Maste 		if (cbor_array_push(array, argv[i]) == false)
1550afa8e06SEd Maste 			goto fail;
1560afa8e06SEd Maste 
1570afa8e06SEd Maste 	if ((cbor_len = cbor_serialize_alloc(array, &cbor,
158*2ccfa855SEd Maste 	    &cbor_alloc_len)) == 0 || cbor_len > len) {
1590afa8e06SEd Maste 		cbor_len = 0;
1600afa8e06SEd Maste 		goto fail;
1610afa8e06SEd Maste 	}
1620afa8e06SEd Maste 
1630afa8e06SEd Maste 	memcpy(ptr, cbor, cbor_len);
1640afa8e06SEd Maste fail:
1650afa8e06SEd Maste 	for (size_t i = 0; i < 9; i++)
1660afa8e06SEd Maste 		if (argv[i])
1670afa8e06SEd Maste 			cbor_decref(&argv[i]);
1680afa8e06SEd Maste 
1690afa8e06SEd Maste 	if (array)
1700afa8e06SEd Maste 		cbor_decref(&array);
1710afa8e06SEd Maste 
1720afa8e06SEd Maste 	free(cbor);
1730afa8e06SEd Maste 
1740afa8e06SEd Maste 	return cbor_len;
1750afa8e06SEd Maste }
1760afa8e06SEd Maste 
1770afa8e06SEd Maste size_t
pack_dummy(uint8_t * ptr,size_t len)1780afa8e06SEd Maste pack_dummy(uint8_t *ptr, size_t len)
1790afa8e06SEd Maste {
1800afa8e06SEd Maste 	struct param dummy;
181*2ccfa855SEd Maste 	uint8_t	blob[MAXCORPUS];
1820afa8e06SEd Maste 	size_t blob_len;
1830afa8e06SEd Maste 
1840afa8e06SEd Maste 	memset(&dummy, 0, sizeof(dummy));
1850afa8e06SEd Maste 
1860afa8e06SEd Maste 	strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
1870afa8e06SEd Maste 	strlcpy(dummy.name, dummy_name, sizeof(dummy.name));
1880afa8e06SEd Maste 
1890afa8e06SEd Maste 	dummy.info_wire_data.len = sizeof(dummy_info_wire_data);
1900afa8e06SEd Maste 	dummy.enroll_wire_data.len = sizeof(dummy_enroll_wire_data);
1910afa8e06SEd Maste 	dummy.list_wire_data.len = sizeof(dummy_list_wire_data);
1920afa8e06SEd Maste 	dummy.set_name_wire_data.len = sizeof(dummy_set_name_wire_data);
1930afa8e06SEd Maste 	dummy.remove_wire_data.len = sizeof(dummy_remove_wire_data);
1940afa8e06SEd Maste 	dummy.id.len = sizeof(dummy_id);
1950afa8e06SEd Maste 
1960afa8e06SEd Maste 	memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data,
1970afa8e06SEd Maste 	    dummy.info_wire_data.len);
1980afa8e06SEd Maste 	memcpy(&dummy.enroll_wire_data.body, &dummy_enroll_wire_data,
1990afa8e06SEd Maste 	    dummy.enroll_wire_data.len);
2000afa8e06SEd Maste 	memcpy(&dummy.list_wire_data.body, &dummy_list_wire_data,
2010afa8e06SEd Maste 	    dummy.list_wire_data.len);
2020afa8e06SEd Maste 	memcpy(&dummy.set_name_wire_data.body, &dummy_set_name_wire_data,
2030afa8e06SEd Maste 	    dummy.set_name_wire_data.len);
2040afa8e06SEd Maste 	memcpy(&dummy.remove_wire_data.body, &dummy_remove_wire_data,
2050afa8e06SEd Maste 	    dummy.remove_wire_data.len);
2060afa8e06SEd Maste 	memcpy(&dummy.id.body, &dummy_id, dummy.id.len);
2070afa8e06SEd Maste 
2080afa8e06SEd Maste 	assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
2090afa8e06SEd Maste 
2100afa8e06SEd Maste 	if (blob_len > len) {
2110afa8e06SEd Maste 		memcpy(ptr, blob, len);
2120afa8e06SEd Maste 		return len;
2130afa8e06SEd Maste 	}
2140afa8e06SEd Maste 
2150afa8e06SEd Maste 	memcpy(ptr, blob, blob_len);
2160afa8e06SEd Maste 
2170afa8e06SEd Maste 	return blob_len;
2180afa8e06SEd Maste }
2190afa8e06SEd Maste 
2200afa8e06SEd Maste static fido_dev_t *
prepare_dev(void)2210afa8e06SEd Maste prepare_dev(void)
2220afa8e06SEd Maste {
2230afa8e06SEd Maste 	fido_dev_t *dev;
2240afa8e06SEd Maste 	bool x;
2250afa8e06SEd Maste 
2260afa8e06SEd Maste 	if ((dev = open_dev(0)) == NULL)
2270afa8e06SEd Maste 		return NULL;
2280afa8e06SEd Maste 
2290afa8e06SEd Maste 	x = fido_dev_is_fido2(dev);
2300afa8e06SEd Maste 	consume(&x, sizeof(x));
2310afa8e06SEd Maste 	x = fido_dev_supports_pin(dev);
2320afa8e06SEd Maste 	consume(&x, sizeof(x));
2330afa8e06SEd Maste 	x = fido_dev_has_pin(dev);
2340afa8e06SEd Maste 	consume(&x, sizeof(x));
2350afa8e06SEd Maste 	x = fido_dev_supports_uv(dev);
2360afa8e06SEd Maste 	consume(&x, sizeof(x));
2370afa8e06SEd Maste 	x = fido_dev_has_uv(dev);
2380afa8e06SEd Maste 	consume(&x, sizeof(x));
2390afa8e06SEd Maste 
2400afa8e06SEd Maste 	return dev;
2410afa8e06SEd Maste }
2420afa8e06SEd Maste 
2430afa8e06SEd Maste static void
get_info(const struct param * p)2440afa8e06SEd Maste get_info(const struct param *p)
2450afa8e06SEd Maste {
2460afa8e06SEd Maste 	fido_dev_t *dev = NULL;
2470afa8e06SEd Maste 	fido_bio_info_t *i = NULL;
2480afa8e06SEd Maste 	uint8_t type;
2490afa8e06SEd Maste 	uint8_t max_samples;
2500afa8e06SEd Maste 	int r;
2510afa8e06SEd Maste 
2520afa8e06SEd Maste 	set_wire_data(p->info_wire_data.body, p->info_wire_data.len);
2530afa8e06SEd Maste 
2540afa8e06SEd Maste 	if ((dev = prepare_dev()) == NULL || (i = fido_bio_info_new()) == NULL)
2550afa8e06SEd Maste 		goto done;
2560afa8e06SEd Maste 
2570afa8e06SEd Maste 	r = fido_bio_dev_get_info(dev, i);
2580afa8e06SEd Maste 	consume_str(fido_strerr(r));
2590afa8e06SEd Maste 
2600afa8e06SEd Maste 	type = fido_bio_info_type(i);
2610afa8e06SEd Maste 	max_samples = fido_bio_info_max_samples(i);
2620afa8e06SEd Maste 	consume(&type, sizeof(type));
2630afa8e06SEd Maste 	consume(&max_samples, sizeof(max_samples));
2640afa8e06SEd Maste 
2650afa8e06SEd Maste done:
2660afa8e06SEd Maste 	if (dev)
2670afa8e06SEd Maste 		fido_dev_close(dev);
2680afa8e06SEd Maste 
2690afa8e06SEd Maste 	fido_dev_free(&dev);
2700afa8e06SEd Maste 	fido_bio_info_free(&i);
2710afa8e06SEd Maste }
2720afa8e06SEd Maste 
2730afa8e06SEd Maste static void
consume_template(const fido_bio_template_t * t)2740afa8e06SEd Maste consume_template(const fido_bio_template_t *t)
2750afa8e06SEd Maste {
2760afa8e06SEd Maste 	consume_str(fido_bio_template_name(t));
2770afa8e06SEd Maste 	consume(fido_bio_template_id_ptr(t), fido_bio_template_id_len(t));
2780afa8e06SEd Maste }
2790afa8e06SEd Maste 
2800afa8e06SEd Maste static void
consume_enroll(fido_bio_enroll_t * e)2810afa8e06SEd Maste consume_enroll(fido_bio_enroll_t *e)
2820afa8e06SEd Maste {
2830afa8e06SEd Maste 	uint8_t last_status;
2840afa8e06SEd Maste 	uint8_t remaining_samples;
2850afa8e06SEd Maste 
2860afa8e06SEd Maste 	last_status = fido_bio_enroll_last_status(e);
2870afa8e06SEd Maste 	remaining_samples = fido_bio_enroll_remaining_samples(e);
2880afa8e06SEd Maste 	consume(&last_status, sizeof(last_status));
2890afa8e06SEd Maste 	consume(&remaining_samples, sizeof(remaining_samples));
2900afa8e06SEd Maste }
2910afa8e06SEd Maste 
2920afa8e06SEd Maste static void
enroll(const struct param * p)2930afa8e06SEd Maste enroll(const struct param *p)
2940afa8e06SEd Maste {
2950afa8e06SEd Maste 	fido_dev_t *dev = NULL;
2960afa8e06SEd Maste 	fido_bio_template_t *t = NULL;
2970afa8e06SEd Maste 	fido_bio_enroll_t *e = NULL;
2980afa8e06SEd Maste 	size_t cnt = 0;
2990afa8e06SEd Maste 
3000afa8e06SEd Maste 	set_wire_data(p->enroll_wire_data.body, p->enroll_wire_data.len);
3010afa8e06SEd Maste 
3020afa8e06SEd Maste 	if ((dev = prepare_dev()) == NULL ||
3030afa8e06SEd Maste 	    (t = fido_bio_template_new()) == NULL ||
3040afa8e06SEd Maste 	    (e = fido_bio_enroll_new()) == NULL)
3050afa8e06SEd Maste 		goto done;
3060afa8e06SEd Maste 
3070afa8e06SEd Maste 	fido_bio_dev_enroll_begin(dev, t, e, (uint32_t)p->seed, p->pin);
3080afa8e06SEd Maste 
3090afa8e06SEd Maste 	consume_template(t);
3100afa8e06SEd Maste 	consume_enroll(e);
3110afa8e06SEd Maste 
3120afa8e06SEd Maste 	while (fido_bio_enroll_remaining_samples(e) > 0 && cnt++ < 5) {
3130afa8e06SEd Maste 		fido_bio_dev_enroll_continue(dev, t, e, p->seed);
3140afa8e06SEd Maste 		consume_template(t);
3150afa8e06SEd Maste 		consume_enroll(e);
3160afa8e06SEd Maste 	}
3170afa8e06SEd Maste 
3180afa8e06SEd Maste done:
3190afa8e06SEd Maste 	if (dev)
3200afa8e06SEd Maste 		fido_dev_close(dev);
3210afa8e06SEd Maste 
3220afa8e06SEd Maste 	fido_dev_free(&dev);
3230afa8e06SEd Maste 	fido_bio_template_free(&t);
3240afa8e06SEd Maste 	fido_bio_enroll_free(&e);
3250afa8e06SEd Maste }
3260afa8e06SEd Maste 
3270afa8e06SEd Maste static void
list(const struct param * p)3280afa8e06SEd Maste list(const struct param *p)
3290afa8e06SEd Maste {
3300afa8e06SEd Maste 	fido_dev_t *dev = NULL;
3310afa8e06SEd Maste 	fido_bio_template_array_t *ta = NULL;
3320afa8e06SEd Maste 	const fido_bio_template_t *t = NULL;
3330afa8e06SEd Maste 
3340afa8e06SEd Maste 	set_wire_data(p->list_wire_data.body, p->list_wire_data.len);
3350afa8e06SEd Maste 
3360afa8e06SEd Maste 	if ((dev = prepare_dev()) == NULL ||
3370afa8e06SEd Maste 	    (ta = fido_bio_template_array_new()) == NULL)
3380afa8e06SEd Maste 		goto done;
3390afa8e06SEd Maste 
3400afa8e06SEd Maste 	fido_bio_dev_get_template_array(dev, ta, p->pin);
3410afa8e06SEd Maste 
3420afa8e06SEd Maste 	/* +1 on purpose */
3430afa8e06SEd Maste 	for (size_t i = 0; i < fido_bio_template_array_count(ta) + 1; i++)
3440afa8e06SEd Maste 		if ((t = fido_bio_template(ta, i)) != NULL)
3450afa8e06SEd Maste 			consume_template(t);
3460afa8e06SEd Maste 
3470afa8e06SEd Maste done:
3480afa8e06SEd Maste 	if (dev)
3490afa8e06SEd Maste 		fido_dev_close(dev);
3500afa8e06SEd Maste 
3510afa8e06SEd Maste 	fido_dev_free(&dev);
3520afa8e06SEd Maste 	fido_bio_template_array_free(&ta);
3530afa8e06SEd Maste }
3540afa8e06SEd Maste 
3550afa8e06SEd Maste static void
set_name(const struct param * p)3560afa8e06SEd Maste set_name(const struct param *p)
3570afa8e06SEd Maste {
3580afa8e06SEd Maste 	fido_dev_t *dev = NULL;
3590afa8e06SEd Maste 	fido_bio_template_t *t = NULL;
3600afa8e06SEd Maste 
3610afa8e06SEd Maste 	set_wire_data(p->set_name_wire_data.body, p->set_name_wire_data.len);
3620afa8e06SEd Maste 
3630afa8e06SEd Maste 	if ((dev = prepare_dev()) == NULL ||
3640afa8e06SEd Maste 	    (t = fido_bio_template_new()) == NULL)
3650afa8e06SEd Maste 		goto done;
3660afa8e06SEd Maste 
3670afa8e06SEd Maste 	fido_bio_template_set_name(t, p->name);
3680afa8e06SEd Maste 	fido_bio_template_set_id(t, p->id.body, p->id.len);
3690afa8e06SEd Maste 	consume_template(t);
3700afa8e06SEd Maste 
3710afa8e06SEd Maste 	fido_bio_dev_set_template_name(dev, t, p->pin);
3720afa8e06SEd Maste 
3730afa8e06SEd Maste done:
3740afa8e06SEd Maste 	if (dev)
3750afa8e06SEd Maste 		fido_dev_close(dev);
3760afa8e06SEd Maste 
3770afa8e06SEd Maste 	fido_dev_free(&dev);
3780afa8e06SEd Maste 	fido_bio_template_free(&t);
3790afa8e06SEd Maste }
3800afa8e06SEd Maste 
3810afa8e06SEd Maste static void
del(const struct param * p)3820afa8e06SEd Maste del(const struct param *p)
3830afa8e06SEd Maste {
3840afa8e06SEd Maste 	fido_dev_t *dev = NULL;
3850afa8e06SEd Maste 	fido_bio_template_t *t = NULL;
3860afa8e06SEd Maste 	int r;
3870afa8e06SEd Maste 
3880afa8e06SEd Maste 	set_wire_data(p->remove_wire_data.body, p->remove_wire_data.len);
3890afa8e06SEd Maste 
3900afa8e06SEd Maste 	if ((dev = prepare_dev()) == NULL ||
3910afa8e06SEd Maste 	    (t = fido_bio_template_new()) == NULL)
3920afa8e06SEd Maste 		goto done;
3930afa8e06SEd Maste 
3940afa8e06SEd Maste 	r = fido_bio_template_set_id(t, p->id.body, p->id.len);
3950afa8e06SEd Maste 	consume_template(t);
3960afa8e06SEd Maste 	consume_str(fido_strerr(r));
3970afa8e06SEd Maste 
3980afa8e06SEd Maste 	fido_bio_dev_enroll_remove(dev, t, p->pin);
3990afa8e06SEd Maste 
4000afa8e06SEd Maste done:
4010afa8e06SEd Maste 	if (dev)
4020afa8e06SEd Maste 		fido_dev_close(dev);
4030afa8e06SEd Maste 
4040afa8e06SEd Maste 	fido_dev_free(&dev);
4050afa8e06SEd Maste 	fido_bio_template_free(&t);
4060afa8e06SEd Maste }
4070afa8e06SEd Maste 
4080afa8e06SEd Maste void
test(const struct param * p)4090afa8e06SEd Maste test(const struct param *p)
4100afa8e06SEd Maste {
4110afa8e06SEd Maste 	prng_init((unsigned int)p->seed);
412f540a430SEd Maste 	fuzz_clock_reset();
4130afa8e06SEd Maste 	fido_init(FIDO_DEBUG);
4140afa8e06SEd Maste 	fido_set_log_handler(consume_str);
4150afa8e06SEd Maste 
4160afa8e06SEd Maste 	get_info(p);
4170afa8e06SEd Maste 	enroll(p);
4180afa8e06SEd Maste 	list(p);
4190afa8e06SEd Maste 	set_name(p);
4200afa8e06SEd Maste 	del(p);
4210afa8e06SEd Maste }
4220afa8e06SEd Maste 
4230afa8e06SEd Maste void
mutate(struct param * p,unsigned int seed,unsigned int flags)4240afa8e06SEd Maste mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
4250afa8e06SEd Maste {
4260afa8e06SEd Maste 	if (flags & MUTATE_SEED)
4270afa8e06SEd Maste 		p->seed = (int)seed;
4280afa8e06SEd Maste 
4290afa8e06SEd Maste 	if (flags & MUTATE_PARAM) {
4300afa8e06SEd Maste 		mutate_blob(&p->id);
4310afa8e06SEd Maste 		mutate_string(p->pin);
4320afa8e06SEd Maste 		mutate_string(p->name);
4330afa8e06SEd Maste 	}
4340afa8e06SEd Maste 
4350afa8e06SEd Maste 	if (flags & MUTATE_WIREDATA) {
4360afa8e06SEd Maste 		mutate_blob(&p->info_wire_data);
4370afa8e06SEd Maste 		mutate_blob(&p->enroll_wire_data);
4380afa8e06SEd Maste 		mutate_blob(&p->list_wire_data);
4390afa8e06SEd Maste 		mutate_blob(&p->set_name_wire_data);
4400afa8e06SEd Maste 		mutate_blob(&p->remove_wire_data);
4410afa8e06SEd Maste 	}
4420afa8e06SEd Maste }
443