xref: /freebsd/contrib/libfido2/fuzz/fuzz_cred.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 "wiredata_u2f.h"
170afa8e06SEd Maste #include "dummy.h"
180afa8e06SEd Maste 
190afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h"
200afa8e06SEd Maste 
210afa8e06SEd Maste /* Parameter set defining a FIDO2 make credential operation. */
220afa8e06SEd Maste struct param {
230afa8e06SEd Maste 	char pin[MAXSTR];
240afa8e06SEd Maste 	char rp_id[MAXSTR];
250afa8e06SEd Maste 	char rp_name[MAXSTR];
260afa8e06SEd Maste 	char user_icon[MAXSTR];
270afa8e06SEd Maste 	char user_name[MAXSTR];
280afa8e06SEd Maste 	char user_nick[MAXSTR];
290afa8e06SEd Maste 	int ext;
300afa8e06SEd Maste 	int seed;
310afa8e06SEd Maste 	struct blob cdh;
320afa8e06SEd Maste 	struct blob excl_cred;
330afa8e06SEd Maste 	struct blob user_id;
340afa8e06SEd Maste 	struct blob wire_data;
350afa8e06SEd Maste 	uint8_t excl_count;
360afa8e06SEd Maste 	uint8_t rk;
370afa8e06SEd Maste 	uint8_t type;
380afa8e06SEd Maste 	uint8_t opt;
390afa8e06SEd Maste 	uint8_t uv;
400afa8e06SEd Maste };
410afa8e06SEd Maste 
420afa8e06SEd Maste /*
430afa8e06SEd Maste  * Collection of HID reports from an authenticator issued with a FIDO2
440afa8e06SEd Maste  * make credential using the example parameters above.
450afa8e06SEd Maste  */
460afa8e06SEd Maste static const uint8_t dummy_wire_data_fido[] = {
470afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
480afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_INFO,
490afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_AUTHKEY,
500afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_PINTOKEN,
510afa8e06SEd Maste 	WIREDATA_CTAP_KEEPALIVE,
520afa8e06SEd Maste 	WIREDATA_CTAP_KEEPALIVE,
530afa8e06SEd Maste 	WIREDATA_CTAP_KEEPALIVE,
540afa8e06SEd Maste 	WIREDATA_CTAP_CBOR_CRED,
550afa8e06SEd Maste };
560afa8e06SEd Maste 
570afa8e06SEd Maste /*
580afa8e06SEd Maste  * Collection of HID reports from an authenticator issued with a U2F
590afa8e06SEd Maste  * registration using the example parameters above.
600afa8e06SEd Maste  */
610afa8e06SEd Maste static const uint8_t dummy_wire_data_u2f[] = {
620afa8e06SEd Maste 	WIREDATA_CTAP_INIT,
630afa8e06SEd Maste 	WIREDATA_CTAP_U2F_6985,
640afa8e06SEd Maste 	WIREDATA_CTAP_U2F_6985,
650afa8e06SEd Maste 	WIREDATA_CTAP_U2F_6985,
660afa8e06SEd Maste 	WIREDATA_CTAP_U2F_6985,
670afa8e06SEd Maste 	WIREDATA_CTAP_U2F_6985,
680afa8e06SEd Maste 	WIREDATA_CTAP_U2F_REGISTER,
690afa8e06SEd Maste };
700afa8e06SEd Maste 
710afa8e06SEd Maste struct param *
unpack(const uint8_t * ptr,size_t len)720afa8e06SEd Maste unpack(const uint8_t *ptr, size_t len)
730afa8e06SEd Maste {
740afa8e06SEd Maste 	cbor_item_t *item = NULL, **v;
750afa8e06SEd Maste 	struct cbor_load_result cbor;
760afa8e06SEd Maste 	struct param *p;
770afa8e06SEd Maste 	int ok = -1;
780afa8e06SEd Maste 
790afa8e06SEd Maste 	if ((p = calloc(1, sizeof(*p))) == NULL ||
800afa8e06SEd Maste 	    (item = cbor_load(ptr, len, &cbor)) == NULL ||
810afa8e06SEd Maste 	    cbor.read != len ||
820afa8e06SEd Maste 	    cbor_isa_array(item) == false ||
830afa8e06SEd Maste 	    cbor_array_is_definite(item) == false ||
840afa8e06SEd Maste 	    cbor_array_size(item) != 17 ||
850afa8e06SEd Maste 	    (v = cbor_array_handle(item)) == NULL)
860afa8e06SEd Maste 		goto fail;
870afa8e06SEd Maste 
880afa8e06SEd Maste 	if (unpack_byte(v[0], &p->rk) < 0 ||
890afa8e06SEd Maste 	    unpack_byte(v[1], &p->type) < 0 ||
900afa8e06SEd Maste 	    unpack_byte(v[2], &p->opt) < 0 ||
910afa8e06SEd Maste 	    unpack_byte(v[3], &p->uv) < 0 ||
920afa8e06SEd Maste 	    unpack_byte(v[4], &p->excl_count) < 0 ||
930afa8e06SEd Maste 	    unpack_int(v[5], &p->ext) < 0 ||
940afa8e06SEd Maste 	    unpack_int(v[6], &p->seed) < 0 ||
950afa8e06SEd Maste 	    unpack_string(v[7], p->pin) < 0 ||
960afa8e06SEd Maste 	    unpack_string(v[8], p->rp_id) < 0 ||
970afa8e06SEd Maste 	    unpack_string(v[9], p->rp_name) < 0 ||
980afa8e06SEd Maste 	    unpack_string(v[10], p->user_icon) < 0 ||
990afa8e06SEd Maste 	    unpack_string(v[11], p->user_name) < 0 ||
1000afa8e06SEd Maste 	    unpack_string(v[12], p->user_nick) < 0 ||
1010afa8e06SEd Maste 	    unpack_blob(v[13], &p->cdh) < 0 ||
1020afa8e06SEd Maste 	    unpack_blob(v[14], &p->user_id) < 0 ||
1030afa8e06SEd Maste 	    unpack_blob(v[15], &p->wire_data) < 0 ||
1040afa8e06SEd Maste 	    unpack_blob(v[16], &p->excl_cred) < 0)
1050afa8e06SEd Maste 		goto fail;
1060afa8e06SEd Maste 
1070afa8e06SEd Maste 	ok = 0;
1080afa8e06SEd Maste fail:
1090afa8e06SEd Maste 	if (ok < 0) {
1100afa8e06SEd Maste 		free(p);
1110afa8e06SEd Maste 		p = NULL;
1120afa8e06SEd Maste 	}
1130afa8e06SEd Maste 
1140afa8e06SEd Maste 	if (item)
1150afa8e06SEd Maste 		cbor_decref(&item);
1160afa8e06SEd Maste 
1170afa8e06SEd Maste 	return p;
1180afa8e06SEd Maste }
1190afa8e06SEd Maste 
1200afa8e06SEd Maste size_t
pack(uint8_t * ptr,size_t len,const struct param * p)1210afa8e06SEd Maste pack(uint8_t *ptr, size_t len, const struct param *p)
1220afa8e06SEd Maste {
1230afa8e06SEd Maste 	cbor_item_t *argv[17], *array = NULL;
1240afa8e06SEd Maste 	size_t cbor_alloc_len, cbor_len = 0;
1250afa8e06SEd Maste 	unsigned char *cbor = NULL;
1260afa8e06SEd Maste 
1270afa8e06SEd Maste 	memset(argv, 0, sizeof(argv));
1280afa8e06SEd Maste 
1290afa8e06SEd Maste 	if ((array = cbor_new_definite_array(17)) == NULL ||
1300afa8e06SEd Maste 	    (argv[0] = pack_byte(p->rk)) == NULL ||
1310afa8e06SEd Maste 	    (argv[1] = pack_byte(p->type)) == NULL ||
1320afa8e06SEd Maste 	    (argv[2] = pack_byte(p->opt)) == NULL ||
1330afa8e06SEd Maste 	    (argv[3] = pack_byte(p->uv)) == NULL ||
1340afa8e06SEd Maste 	    (argv[4] = pack_byte(p->excl_count)) == NULL ||
1350afa8e06SEd Maste 	    (argv[5] = pack_int(p->ext)) == NULL ||
1360afa8e06SEd Maste 	    (argv[6] = pack_int(p->seed)) == NULL ||
1370afa8e06SEd Maste 	    (argv[7] = pack_string(p->pin)) == NULL ||
1380afa8e06SEd Maste 	    (argv[8] = pack_string(p->rp_id)) == NULL ||
1390afa8e06SEd Maste 	    (argv[9] = pack_string(p->rp_name)) == NULL ||
1400afa8e06SEd Maste 	    (argv[10] = pack_string(p->user_icon)) == NULL ||
1410afa8e06SEd Maste 	    (argv[11] = pack_string(p->user_name)) == NULL ||
1420afa8e06SEd Maste 	    (argv[12] = pack_string(p->user_nick)) == NULL ||
1430afa8e06SEd Maste 	    (argv[13] = pack_blob(&p->cdh)) == NULL ||
1440afa8e06SEd Maste 	    (argv[14] = pack_blob(&p->user_id)) == NULL ||
1450afa8e06SEd Maste 	    (argv[15] = pack_blob(&p->wire_data)) == NULL ||
1460afa8e06SEd Maste 	    (argv[16] = pack_blob(&p->excl_cred)) == NULL)
1470afa8e06SEd Maste 		goto fail;
1480afa8e06SEd Maste 
1490afa8e06SEd Maste 	for (size_t i = 0; i < 17; i++)
1500afa8e06SEd Maste 		if (cbor_array_push(array, argv[i]) == false)
1510afa8e06SEd Maste 			goto fail;
1520afa8e06SEd Maste 
1530afa8e06SEd Maste 	if ((cbor_len = cbor_serialize_alloc(array, &cbor,
154*2ccfa855SEd Maste 	    &cbor_alloc_len)) == 0 || cbor_len > len) {
1550afa8e06SEd Maste 		cbor_len = 0;
1560afa8e06SEd Maste 		goto fail;
1570afa8e06SEd Maste 	}
1580afa8e06SEd Maste 
1590afa8e06SEd Maste 	memcpy(ptr, cbor, cbor_len);
1600afa8e06SEd Maste fail:
1610afa8e06SEd Maste 	for (size_t i = 0; i < 17; i++)
1620afa8e06SEd Maste 		if (argv[i])
1630afa8e06SEd Maste 			cbor_decref(&argv[i]);
1640afa8e06SEd Maste 
1650afa8e06SEd Maste 	if (array)
1660afa8e06SEd Maste 		cbor_decref(&array);
1670afa8e06SEd Maste 
1680afa8e06SEd Maste 	free(cbor);
1690afa8e06SEd Maste 
1700afa8e06SEd Maste 	return cbor_len;
1710afa8e06SEd Maste }
1720afa8e06SEd Maste 
1730afa8e06SEd Maste size_t
pack_dummy(uint8_t * ptr,size_t len)1740afa8e06SEd Maste pack_dummy(uint8_t *ptr, size_t len)
1750afa8e06SEd Maste {
1760afa8e06SEd Maste 	struct param dummy;
177*2ccfa855SEd Maste 	uint8_t blob[MAXCORPUS];
1780afa8e06SEd Maste 	size_t blob_len;
1790afa8e06SEd Maste 
1800afa8e06SEd Maste 	memset(&dummy, 0, sizeof(dummy));
1810afa8e06SEd Maste 
1820afa8e06SEd Maste 	dummy.type = 1;
1830afa8e06SEd Maste 	dummy.ext = FIDO_EXT_HMAC_SECRET;
1840afa8e06SEd Maste 
1850afa8e06SEd Maste 	strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
1860afa8e06SEd Maste 	strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
1870afa8e06SEd Maste 	strlcpy(dummy.rp_name, dummy_rp_name, sizeof(dummy.rp_name));
1880afa8e06SEd Maste 	strlcpy(dummy.user_icon, dummy_user_icon, sizeof(dummy.user_icon));
1890afa8e06SEd Maste 	strlcpy(dummy.user_name, dummy_user_name, sizeof(dummy.user_name));
1900afa8e06SEd Maste 	strlcpy(dummy.user_nick, dummy_user_nick, sizeof(dummy.user_nick));
1910afa8e06SEd Maste 
1920afa8e06SEd Maste 	dummy.cdh.len = sizeof(dummy_cdh);
1930afa8e06SEd Maste 	dummy.user_id.len = sizeof(dummy_user_id);
1940afa8e06SEd Maste 	dummy.wire_data.len = sizeof(dummy_wire_data_fido);
1950afa8e06SEd Maste 
1960afa8e06SEd Maste 	memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len);
1970afa8e06SEd Maste 	memcpy(&dummy.user_id.body, &dummy_user_id, dummy.user_id.len);
1980afa8e06SEd Maste 	memcpy(&dummy.wire_data.body, &dummy_wire_data_fido,
1990afa8e06SEd Maste 	    dummy.wire_data.len);
2000afa8e06SEd Maste 
2010afa8e06SEd Maste 	assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
2020afa8e06SEd Maste 
2030afa8e06SEd Maste 	if (blob_len > len) {
2040afa8e06SEd Maste 		memcpy(ptr, blob, len);
2050afa8e06SEd Maste 		return len;
2060afa8e06SEd Maste 	}
2070afa8e06SEd Maste 
2080afa8e06SEd Maste 	memcpy(ptr, blob, blob_len);
2090afa8e06SEd Maste 
2100afa8e06SEd Maste 	return blob_len;
2110afa8e06SEd Maste }
2120afa8e06SEd Maste 
2130afa8e06SEd Maste static void
make_cred(fido_cred_t * cred,uint8_t opt,int type,const struct blob * cdh,const char * rp_id,const char * rp_name,const struct blob * user_id,const char * user_name,const char * user_nick,const char * user_icon,int ext,uint8_t rk,uint8_t uv,const char * pin,uint8_t excl_count,const struct blob * excl_cred)2140afa8e06SEd Maste make_cred(fido_cred_t *cred, uint8_t opt, int type, const struct blob *cdh,
2150afa8e06SEd Maste     const char *rp_id, const char *rp_name, const struct blob *user_id,
2160afa8e06SEd Maste     const char *user_name, const char *user_nick, const char *user_icon,
2170afa8e06SEd Maste     int ext, uint8_t rk, uint8_t uv, const char *pin, uint8_t excl_count,
2180afa8e06SEd Maste     const struct blob *excl_cred)
2190afa8e06SEd Maste {
2200afa8e06SEd Maste 	fido_dev_t *dev;
2210afa8e06SEd Maste 
2220afa8e06SEd Maste 	if ((dev = open_dev(opt & 2)) == NULL)
2230afa8e06SEd Maste 		return;
2240afa8e06SEd Maste 	if (opt & 1)
2250afa8e06SEd Maste 		fido_dev_force_u2f(dev);
2260afa8e06SEd Maste 
2270afa8e06SEd Maste 	for (uint8_t i = 0; i < excl_count; i++)
2280afa8e06SEd Maste 		fido_cred_exclude(cred, excl_cred->body, excl_cred->len);
2290afa8e06SEd Maste 
2300afa8e06SEd Maste 	fido_cred_set_type(cred, type);
2310afa8e06SEd Maste 	fido_cred_set_clientdata_hash(cred, cdh->body, cdh->len);
2320afa8e06SEd Maste 	fido_cred_set_rp(cred, rp_id, rp_name);
2330afa8e06SEd Maste 	fido_cred_set_user(cred, user_id->body, user_id->len, user_name,
2340afa8e06SEd Maste 	    user_nick, user_icon);
235f540a430SEd Maste 
2360afa8e06SEd Maste 	if (ext & FIDO_EXT_HMAC_SECRET)
2370afa8e06SEd Maste 		fido_cred_set_extensions(cred, FIDO_EXT_HMAC_SECRET);
2380afa8e06SEd Maste 	if (ext & FIDO_EXT_CRED_BLOB)
2390afa8e06SEd Maste 		fido_cred_set_blob(cred, user_id->body, user_id->len);
2400afa8e06SEd Maste 	if (ext & FIDO_EXT_LARGEBLOB_KEY)
2410afa8e06SEd Maste 		fido_cred_set_extensions(cred, FIDO_EXT_LARGEBLOB_KEY);
242f540a430SEd Maste 	if (ext & FIDO_EXT_MINPINLEN)
243f540a430SEd Maste 		fido_cred_set_pin_minlen(cred, strlen(pin));
2440afa8e06SEd Maste 
2450afa8e06SEd Maste 	if (rk & 1)
2460afa8e06SEd Maste 		fido_cred_set_rk(cred, FIDO_OPT_TRUE);
2470afa8e06SEd Maste 	if (uv & 1)
2480afa8e06SEd Maste 		fido_cred_set_uv(cred, FIDO_OPT_TRUE);
2490afa8e06SEd Maste 	if (user_id->len)
2500afa8e06SEd Maste 		fido_cred_set_prot(cred, user_id->body[0] & 0x03);
2510afa8e06SEd Maste 
2520afa8e06SEd Maste 	/* repeat memory operations to trigger reallocation paths */
2530afa8e06SEd Maste 	fido_cred_set_type(cred, type);
2540afa8e06SEd Maste 	fido_cred_set_clientdata_hash(cred, cdh->body, cdh->len);
2550afa8e06SEd Maste 	fido_cred_set_rp(cred, rp_id, rp_name);
2560afa8e06SEd Maste 	fido_cred_set_user(cred, user_id->body, user_id->len, user_name,
2570afa8e06SEd Maste 	    user_nick, user_icon);
2580afa8e06SEd Maste 
2590afa8e06SEd Maste 	if (strlen(pin) == 0)
2600afa8e06SEd Maste 		pin = NULL;
2610afa8e06SEd Maste 
2620afa8e06SEd Maste 	fido_dev_make_cred(dev, cred, (opt & 1) ? NULL : pin);
2630afa8e06SEd Maste 
2640afa8e06SEd Maste 	fido_dev_cancel(dev);
2650afa8e06SEd Maste 	fido_dev_close(dev);
2660afa8e06SEd Maste 	fido_dev_free(&dev);
2670afa8e06SEd Maste }
2680afa8e06SEd Maste 
2690afa8e06SEd Maste static void
verify_cred(int type,const unsigned char * cdh_ptr,size_t cdh_len,const char * rp_id,const char * rp_name,const unsigned char * authdata_ptr,size_t authdata_len,const unsigned char * authdata_raw_ptr,size_t authdata_raw_len,int ext,uint8_t rk,uint8_t uv,const unsigned char * x5c_ptr,size_t x5c_len,const unsigned char * sig_ptr,size_t sig_len,const unsigned char * attstmt_ptr,size_t attstmt_len,const char * fmt,int prot,size_t minpinlen)2700afa8e06SEd Maste verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
2710afa8e06SEd Maste     const char *rp_id, const char *rp_name, const unsigned char *authdata_ptr,
2720afa8e06SEd Maste     size_t authdata_len, const unsigned char *authdata_raw_ptr,
2730afa8e06SEd Maste     size_t authdata_raw_len, int ext, uint8_t rk, uint8_t uv,
2740afa8e06SEd Maste     const unsigned char *x5c_ptr, size_t x5c_len, const unsigned char *sig_ptr,
275f540a430SEd Maste     size_t sig_len, const unsigned char *attstmt_ptr, size_t attstmt_len,
276f540a430SEd Maste     const char *fmt, int prot, size_t minpinlen)
2770afa8e06SEd Maste {
2780afa8e06SEd Maste 	fido_cred_t *cred;
2790afa8e06SEd Maste 	uint8_t flags;
2800afa8e06SEd Maste 	uint32_t sigcount;
281f540a430SEd Maste 	int r;
2820afa8e06SEd Maste 
2830afa8e06SEd Maste 	if ((cred = fido_cred_new()) == NULL)
2840afa8e06SEd Maste 		return;
2850afa8e06SEd Maste 
2860afa8e06SEd Maste 	fido_cred_set_type(cred, type);
2870afa8e06SEd Maste 	fido_cred_set_clientdata_hash(cred, cdh_ptr, cdh_len);
2880afa8e06SEd Maste 	fido_cred_set_rp(cred, rp_id, rp_name);
2890afa8e06SEd Maste 	consume(authdata_ptr, authdata_len);
2900afa8e06SEd Maste 	consume(authdata_raw_ptr, authdata_raw_len);
291f540a430SEd Maste 	consume(x5c_ptr, x5c_len);
292f540a430SEd Maste 	consume(sig_ptr, sig_len);
293f540a430SEd Maste 	consume(attstmt_ptr, attstmt_len);
2940afa8e06SEd Maste 	if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK)
2950afa8e06SEd Maste 		fido_cred_set_authdata_raw(cred, authdata_raw_ptr,
2960afa8e06SEd Maste 		    authdata_raw_len);
2970afa8e06SEd Maste 	fido_cred_set_extensions(cred, ext);
298f540a430SEd Maste 	if (fido_cred_set_attstmt(cred, attstmt_ptr, attstmt_len) != FIDO_OK) {
2990afa8e06SEd Maste 		fido_cred_set_x509(cred, x5c_ptr, x5c_len);
3000afa8e06SEd Maste 		fido_cred_set_sig(cred, sig_ptr, sig_len);
301f540a430SEd Maste 	}
3020afa8e06SEd Maste 	fido_cred_set_prot(cred, prot);
303f540a430SEd Maste 	fido_cred_set_pin_minlen(cred, minpinlen);
3040afa8e06SEd Maste 
3050afa8e06SEd Maste 	if (rk & 1)
3060afa8e06SEd Maste 		fido_cred_set_rk(cred, FIDO_OPT_TRUE);
3070afa8e06SEd Maste 	if (uv & 1)
3080afa8e06SEd Maste 		fido_cred_set_uv(cred, FIDO_OPT_TRUE);
3090afa8e06SEd Maste 	if (fmt)
3100afa8e06SEd Maste 		fido_cred_set_fmt(cred, fmt);
3110afa8e06SEd Maste 
3120afa8e06SEd Maste 	/* repeat memory operations to trigger reallocation paths */
3130afa8e06SEd Maste 	if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK)
314f540a430SEd Maste 		fido_cred_set_authdata_raw(cred, authdata_raw_ptr,
315f540a430SEd Maste 		    authdata_raw_len);
316f540a430SEd Maste 	if (fido_cred_set_attstmt(cred, attstmt_ptr, attstmt_len) != FIDO_OK) {
317f540a430SEd Maste 		fido_cred_set_x509(cred, x5c_ptr, x5c_len);
318f540a430SEd Maste 		fido_cred_set_sig(cred, sig_ptr, sig_len);
319f540a430SEd Maste 	}
3200afa8e06SEd Maste 	fido_cred_set_x509(cred, x5c_ptr, x5c_len);
3210afa8e06SEd Maste 	fido_cred_set_sig(cred, sig_ptr, sig_len);
3220afa8e06SEd Maste 
323f540a430SEd Maste 	r = fido_cred_verify(cred);
324f540a430SEd Maste 	consume(&r, sizeof(r));
325f540a430SEd Maste 	r = fido_cred_verify_self(cred);
326f540a430SEd Maste 	consume(&r, sizeof(r));
3270afa8e06SEd Maste 
3280afa8e06SEd Maste 	consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred));
3290afa8e06SEd Maste 	consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred));
3300afa8e06SEd Maste 	consume(fido_cred_aaguid_ptr(cred), fido_cred_aaguid_len(cred));
3310afa8e06SEd Maste 	consume(fido_cred_user_id_ptr(cred), fido_cred_user_id_len(cred));
3320afa8e06SEd Maste 	consume_str(fido_cred_user_name(cred));
3330afa8e06SEd Maste 	consume_str(fido_cred_display_name(cred));
3340afa8e06SEd Maste 	consume(fido_cred_largeblob_key_ptr(cred),
3350afa8e06SEd Maste 	    fido_cred_largeblob_key_len(cred));
3360afa8e06SEd Maste 
3370afa8e06SEd Maste 	flags = fido_cred_flags(cred);
3380afa8e06SEd Maste 	consume(&flags, sizeof(flags));
3390afa8e06SEd Maste 	sigcount = fido_cred_sigcount(cred);
3400afa8e06SEd Maste 	consume(&sigcount, sizeof(sigcount));
3410afa8e06SEd Maste 	type = fido_cred_type(cred);
3420afa8e06SEd Maste 	consume(&type, sizeof(type));
343f540a430SEd Maste 	minpinlen = fido_cred_pin_minlen(cred);
344f540a430SEd Maste 	consume(&minpinlen, sizeof(minpinlen));
3450afa8e06SEd Maste 
3460afa8e06SEd Maste 	fido_cred_free(&cred);
3470afa8e06SEd Maste }
3480afa8e06SEd Maste 
3490afa8e06SEd Maste static void
test_cred(const struct param * p)3500afa8e06SEd Maste test_cred(const struct param *p)
3510afa8e06SEd Maste {
3520afa8e06SEd Maste 	fido_cred_t *cred = NULL;
3530afa8e06SEd Maste 	int cose_alg = 0;
3540afa8e06SEd Maste 
3550afa8e06SEd Maste 	if ((cred = fido_cred_new()) == NULL)
3560afa8e06SEd Maste 		return;
3570afa8e06SEd Maste 
3580afa8e06SEd Maste 	switch (p->type & 3) {
3590afa8e06SEd Maste 	case 0:
3600afa8e06SEd Maste 		cose_alg = COSE_ES256;
3610afa8e06SEd Maste 		break;
3620afa8e06SEd Maste 	case 1:
3630afa8e06SEd Maste 		cose_alg = COSE_RS256;
3640afa8e06SEd Maste 		break;
365*2ccfa855SEd Maste 	case 2:
366*2ccfa855SEd Maste 		cose_alg = COSE_ES384;
367*2ccfa855SEd Maste 		break;
3680afa8e06SEd Maste 	default:
3690afa8e06SEd Maste 		cose_alg = COSE_EDDSA;
3700afa8e06SEd Maste 		break;
3710afa8e06SEd Maste 	}
3720afa8e06SEd Maste 
3730afa8e06SEd Maste 	set_wire_data(p->wire_data.body, p->wire_data.len);
3740afa8e06SEd Maste 
3750afa8e06SEd Maste 	make_cred(cred, p->opt, cose_alg, &p->cdh, p->rp_id, p->rp_name,
3760afa8e06SEd Maste 	    &p->user_id, p->user_name, p->user_nick, p->user_icon, p->ext,
3770afa8e06SEd Maste 	    p->rk, p->uv, p->pin, p->excl_count, &p->excl_cred);
3780afa8e06SEd Maste 
3790afa8e06SEd Maste 	verify_cred(cose_alg,
3800afa8e06SEd Maste 	    fido_cred_clientdata_hash_ptr(cred),
3810afa8e06SEd Maste 	    fido_cred_clientdata_hash_len(cred), fido_cred_rp_id(cred),
3820afa8e06SEd Maste 	    fido_cred_rp_name(cred), fido_cred_authdata_ptr(cred),
3830afa8e06SEd Maste 	    fido_cred_authdata_len(cred), fido_cred_authdata_raw_ptr(cred),
3840afa8e06SEd Maste 	    fido_cred_authdata_raw_len(cred), p->ext, p->rk, p->uv,
3850afa8e06SEd Maste 	    fido_cred_x5c_ptr(cred), fido_cred_x5c_len(cred),
3860afa8e06SEd Maste 	    fido_cred_sig_ptr(cred), fido_cred_sig_len(cred),
387f540a430SEd Maste 	    fido_cred_attstmt_ptr(cred), fido_cred_attstmt_len(cred),
388f540a430SEd Maste 	    fido_cred_fmt(cred), fido_cred_prot(cred),
389f540a430SEd Maste 	    fido_cred_pin_minlen(cred));
3900afa8e06SEd Maste 
3910afa8e06SEd Maste 	fido_cred_free(&cred);
3920afa8e06SEd Maste }
3930afa8e06SEd Maste 
3940afa8e06SEd Maste static void
test_touch(const struct param * p)3950afa8e06SEd Maste test_touch(const struct param *p)
3960afa8e06SEd Maste {
3970afa8e06SEd Maste 	fido_dev_t *dev;
3980afa8e06SEd Maste 	int r;
3990afa8e06SEd Maste 	int touched;
4000afa8e06SEd Maste 
4010afa8e06SEd Maste 	set_wire_data(p->wire_data.body, p->wire_data.len);
4020afa8e06SEd Maste 
4030afa8e06SEd Maste 	if ((dev = open_dev(p->opt & 2)) == NULL)
4040afa8e06SEd Maste 		return;
4050afa8e06SEd Maste 	if (p->opt & 1)
4060afa8e06SEd Maste 		fido_dev_force_u2f(dev);
4070afa8e06SEd Maste 
4080afa8e06SEd Maste 	r = fido_dev_get_touch_begin(dev);
4090afa8e06SEd Maste 	consume_str(fido_strerr(r));
4100afa8e06SEd Maste 	r = fido_dev_get_touch_status(dev, &touched, -1);
4110afa8e06SEd Maste 	consume_str(fido_strerr(r));
4120afa8e06SEd Maste 	consume(&touched, sizeof(touched));
4130afa8e06SEd Maste 
4140afa8e06SEd Maste 	fido_dev_cancel(dev);
4150afa8e06SEd Maste 	fido_dev_close(dev);
4160afa8e06SEd Maste 	fido_dev_free(&dev);
4170afa8e06SEd Maste }
4180afa8e06SEd Maste 
4190afa8e06SEd Maste static void
test_misc(const struct param * p)4200afa8e06SEd Maste test_misc(const struct param *p)
4210afa8e06SEd Maste {
4220afa8e06SEd Maste 	fido_cred_t *cred = NULL;
4230afa8e06SEd Maste 
4240afa8e06SEd Maste 	if ((cred = fido_cred_new()) == NULL)
4250afa8e06SEd Maste 		return;
4260afa8e06SEd Maste 
4270afa8e06SEd Maste 	/* reuse user id as credential id */
4280afa8e06SEd Maste 	fido_cred_set_id(cred, p->user_id.body, p->user_id.len);
4290afa8e06SEd Maste 	consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred));
4300afa8e06SEd Maste 	fido_cred_free(&cred);
4310afa8e06SEd Maste }
4320afa8e06SEd Maste 
4330afa8e06SEd Maste void
test(const struct param * p)4340afa8e06SEd Maste test(const struct param *p)
4350afa8e06SEd Maste {
4360afa8e06SEd Maste 	prng_init((unsigned int)p->seed);
437f540a430SEd Maste 	fuzz_clock_reset();
4380afa8e06SEd Maste 	fido_init(FIDO_DEBUG);
4390afa8e06SEd Maste 	fido_set_log_handler(consume_str);
4400afa8e06SEd Maste 
4410afa8e06SEd Maste 	test_cred(p);
4420afa8e06SEd Maste 	test_touch(p);
4430afa8e06SEd Maste 	test_misc(p);
4440afa8e06SEd Maste }
4450afa8e06SEd Maste 
4460afa8e06SEd Maste void
mutate(struct param * p,unsigned int seed,unsigned int flags)4470afa8e06SEd Maste mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
4480afa8e06SEd Maste {
4490afa8e06SEd Maste 	if (flags & MUTATE_SEED)
4500afa8e06SEd Maste 		p->seed = (int)seed;
4510afa8e06SEd Maste 
4520afa8e06SEd Maste 	if (flags & MUTATE_PARAM) {
4530afa8e06SEd Maste 		mutate_byte(&p->rk);
4540afa8e06SEd Maste 		mutate_byte(&p->type);
4550afa8e06SEd Maste 		mutate_byte(&p->opt);
4560afa8e06SEd Maste 		mutate_byte(&p->uv);
4570afa8e06SEd Maste 		mutate_byte(&p->excl_count);
4580afa8e06SEd Maste 		mutate_int(&p->ext);
4590afa8e06SEd Maste 		mutate_blob(&p->cdh);
4600afa8e06SEd Maste 		mutate_blob(&p->user_id);
4610afa8e06SEd Maste 		mutate_blob(&p->excl_cred);
4620afa8e06SEd Maste 		mutate_string(p->pin);
4630afa8e06SEd Maste 		mutate_string(p->user_icon);
4640afa8e06SEd Maste 		mutate_string(p->user_name);
4650afa8e06SEd Maste 		mutate_string(p->user_nick);
4660afa8e06SEd Maste 		mutate_string(p->rp_id);
4670afa8e06SEd Maste 		mutate_string(p->rp_name);
4680afa8e06SEd Maste 	}
4690afa8e06SEd Maste 
4700afa8e06SEd Maste 	if (flags & MUTATE_WIREDATA) {
4710afa8e06SEd Maste 		if (p->opt & 1) {
4720afa8e06SEd Maste 			p->wire_data.len = sizeof(dummy_wire_data_u2f);
4730afa8e06SEd Maste 			memcpy(&p->wire_data.body, &dummy_wire_data_u2f,
4740afa8e06SEd Maste 			    p->wire_data.len);
4750afa8e06SEd Maste 		} else {
4760afa8e06SEd Maste 			p->wire_data.len = sizeof(dummy_wire_data_fido);
4770afa8e06SEd Maste 			memcpy(&p->wire_data.body, &dummy_wire_data_fido,
4780afa8e06SEd Maste 			    p->wire_data.len);
4790afa8e06SEd Maste 		}
4800afa8e06SEd Maste 		mutate_blob(&p->wire_data);
4810afa8e06SEd Maste 	}
4820afa8e06SEd Maste }
483