Path: blob/main/contrib/libfido2/fuzz/fuzz_credman.c
39586 views
/*1* Copyright (c) 2019-2021 Yubico AB. All rights reserved.2* Use of this source code is governed by a BSD-style3* license that can be found in the LICENSE file.4* SPDX-License-Identifier: BSD-2-Clause5*/67#include <assert.h>8#include <stdint.h>9#include <stdio.h>10#include <stdlib.h>11#include <string.h>1213#include "mutator_aux.h"14#include "wiredata_fido2.h"15#include "dummy.h"1617#include "../openbsd-compat/openbsd-compat.h"1819/* Parameter set defining a FIDO2 credential management operation. */20struct param {21char pin[MAXSTR];22char rp_id[MAXSTR];23int seed;24struct blob cred_id;25struct blob del_wire_data;26struct blob meta_wire_data;27struct blob rk_wire_data;28struct blob rp_wire_data;29};3031/*32* Collection of HID reports from an authenticator issued with a FIDO233* 'getCredsMetadata' credential management command.34*/35static const uint8_t dummy_meta_wire_data[] = {36WIREDATA_CTAP_INIT,37WIREDATA_CTAP_CBOR_INFO,38WIREDATA_CTAP_CBOR_AUTHKEY,39WIREDATA_CTAP_CBOR_PINTOKEN,40WIREDATA_CTAP_CBOR_CREDMAN_META,41};4243/*44* Collection of HID reports from an authenticator issued with a FIDO245* 'enumerateRPsBegin' credential management command.46*/47static const uint8_t dummy_rp_wire_data[] = {48WIREDATA_CTAP_INIT,49WIREDATA_CTAP_CBOR_INFO,50WIREDATA_CTAP_CBOR_AUTHKEY,51WIREDATA_CTAP_CBOR_PINTOKEN,52WIREDATA_CTAP_CBOR_CREDMAN_RPLIST,53};5455/*56* Collection of HID reports from an authenticator issued with a FIDO257* 'enumerateCredentialsBegin' credential management command.58*/59static const uint8_t dummy_rk_wire_data[] = {60WIREDATA_CTAP_INIT,61WIREDATA_CTAP_CBOR_INFO,62WIREDATA_CTAP_CBOR_AUTHKEY,63WIREDATA_CTAP_CBOR_PINTOKEN,64WIREDATA_CTAP_CBOR_CREDMAN_RKLIST,65};6667/*68* Collection of HID reports from an authenticator issued with a FIDO269* 'deleteCredential' credential management command.70*/71static const uint8_t dummy_del_wire_data[] = {72WIREDATA_CTAP_INIT,73WIREDATA_CTAP_CBOR_INFO,74WIREDATA_CTAP_CBOR_AUTHKEY,75WIREDATA_CTAP_CBOR_PINTOKEN,76WIREDATA_CTAP_CBOR_STATUS,77};7879struct param *80unpack(const uint8_t *ptr, size_t len)81{82cbor_item_t *item = NULL, **v;83struct cbor_load_result cbor;84struct param *p;85int ok = -1;8687if ((p = calloc(1, sizeof(*p))) == NULL ||88(item = cbor_load(ptr, len, &cbor)) == NULL ||89cbor.read != len ||90cbor_isa_array(item) == false ||91cbor_array_is_definite(item) == false ||92cbor_array_size(item) != 8 ||93(v = cbor_array_handle(item)) == NULL)94goto fail;9596if (unpack_int(v[0], &p->seed) < 0 ||97unpack_string(v[1], p->pin) < 0 ||98unpack_string(v[2], p->rp_id) < 0 ||99unpack_blob(v[3], &p->cred_id) < 0 ||100unpack_blob(v[4], &p->meta_wire_data) < 0 ||101unpack_blob(v[5], &p->rp_wire_data) < 0 ||102unpack_blob(v[6], &p->rk_wire_data) < 0 ||103unpack_blob(v[7], &p->del_wire_data) < 0)104goto fail;105106ok = 0;107fail:108if (ok < 0) {109free(p);110p = NULL;111}112113if (item)114cbor_decref(&item);115116return p;117}118119size_t120pack(uint8_t *ptr, size_t len, const struct param *p)121{122cbor_item_t *argv[8], *array = NULL;123size_t cbor_alloc_len, cbor_len = 0;124unsigned char *cbor = NULL;125126memset(argv, 0, sizeof(argv));127128if ((array = cbor_new_definite_array(8)) == NULL ||129(argv[0] = pack_int(p->seed)) == NULL ||130(argv[1] = pack_string(p->pin)) == NULL ||131(argv[2] = pack_string(p->rp_id)) == NULL ||132(argv[3] = pack_blob(&p->cred_id)) == NULL ||133(argv[4] = pack_blob(&p->meta_wire_data)) == NULL ||134(argv[5] = pack_blob(&p->rp_wire_data)) == NULL ||135(argv[6] = pack_blob(&p->rk_wire_data)) == NULL ||136(argv[7] = pack_blob(&p->del_wire_data)) == NULL)137goto fail;138139for (size_t i = 0; i < 8; i++)140if (cbor_array_push(array, argv[i]) == false)141goto fail;142143if ((cbor_len = cbor_serialize_alloc(array, &cbor,144&cbor_alloc_len)) == 0 || cbor_len > len) {145cbor_len = 0;146goto fail;147}148149memcpy(ptr, cbor, cbor_len);150fail:151for (size_t i = 0; i < 8; i++)152if (argv[i])153cbor_decref(&argv[i]);154155if (array)156cbor_decref(&array);157158free(cbor);159160return cbor_len;161}162163size_t164pack_dummy(uint8_t *ptr, size_t len)165{166struct param dummy;167uint8_t blob[MAXCORPUS];168size_t blob_len;169170memset(&dummy, 0, sizeof(dummy));171172strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));173strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));174175dummy.meta_wire_data.len = sizeof(dummy_meta_wire_data);176dummy.rp_wire_data.len = sizeof(dummy_rp_wire_data);177dummy.rk_wire_data.len = sizeof(dummy_rk_wire_data);178dummy.del_wire_data.len = sizeof(dummy_del_wire_data);179dummy.cred_id.len = sizeof(dummy_cred_id);180181memcpy(&dummy.meta_wire_data.body, &dummy_meta_wire_data,182dummy.meta_wire_data.len);183memcpy(&dummy.rp_wire_data.body, &dummy_rp_wire_data,184dummy.rp_wire_data.len);185memcpy(&dummy.rk_wire_data.body, &dummy_rk_wire_data,186dummy.rk_wire_data.len);187memcpy(&dummy.del_wire_data.body, &dummy_del_wire_data,188dummy.del_wire_data.len);189memcpy(&dummy.cred_id.body, &dummy_cred_id, dummy.cred_id.len);190191assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);192193if (blob_len > len) {194memcpy(ptr, blob, len);195return len;196}197198memcpy(ptr, blob, blob_len);199200return blob_len;201}202203static fido_dev_t *204prepare_dev(void)205{206fido_dev_t *dev;207bool x;208209if ((dev = open_dev(0)) == NULL)210return NULL;211212x = fido_dev_is_fido2(dev);213consume(&x, sizeof(x));214x = fido_dev_supports_cred_prot(dev);215consume(&x, sizeof(x));216x = fido_dev_supports_credman(dev);217consume(&x, sizeof(x));218219return dev;220}221222static void223get_metadata(const struct param *p)224{225fido_dev_t *dev;226fido_credman_metadata_t *metadata;227uint64_t existing;228uint64_t remaining;229230set_wire_data(p->meta_wire_data.body, p->meta_wire_data.len);231232if ((dev = prepare_dev()) == NULL)233return;234235if ((metadata = fido_credman_metadata_new()) == NULL) {236fido_dev_close(dev);237fido_dev_free(&dev);238return;239}240241fido_credman_get_dev_metadata(dev, metadata, p->pin);242243existing = fido_credman_rk_existing(metadata);244remaining = fido_credman_rk_remaining(metadata);245consume(&existing, sizeof(existing));246consume(&remaining, sizeof(remaining));247248fido_credman_metadata_free(&metadata);249fido_dev_close(dev);250fido_dev_free(&dev);251}252253static void254get_rp_list(const struct param *p)255{256fido_dev_t *dev;257fido_credman_rp_t *rp;258259set_wire_data(p->rp_wire_data.body, p->rp_wire_data.len);260261if ((dev = prepare_dev()) == NULL)262return;263264if ((rp = fido_credman_rp_new()) == NULL) {265fido_dev_close(dev);266fido_dev_free(&dev);267return;268}269270fido_credman_get_dev_rp(dev, rp, p->pin);271272/* +1 on purpose */273for (size_t i = 0; i < fido_credman_rp_count(rp) + 1; i++) {274consume(fido_credman_rp_id_hash_ptr(rp, i),275fido_credman_rp_id_hash_len(rp, i));276consume_str(fido_credman_rp_id(rp, i));277consume_str(fido_credman_rp_name(rp, i));278}279280fido_credman_rp_free(&rp);281fido_dev_close(dev);282fido_dev_free(&dev);283}284285static void286get_rk_list(const struct param *p)287{288fido_dev_t *dev;289fido_credman_rk_t *rk;290const fido_cred_t *cred;291int val;292293set_wire_data(p->rk_wire_data.body, p->rk_wire_data.len);294295if ((dev = prepare_dev()) == NULL)296return;297298if ((rk = fido_credman_rk_new()) == NULL) {299fido_dev_close(dev);300fido_dev_free(&dev);301return;302}303304fido_credman_get_dev_rk(dev, p->rp_id, rk, p->pin);305306/* +1 on purpose */307for (size_t i = 0; i < fido_credman_rk_count(rk) + 1; i++) {308if ((cred = fido_credman_rk(rk, i)) == NULL) {309assert(i >= fido_credman_rk_count(rk));310continue;311}312val = fido_cred_type(cred);313consume(&val, sizeof(val));314consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred));315consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred));316consume(fido_cred_user_id_ptr(cred),317fido_cred_user_id_len(cred));318consume_str(fido_cred_user_name(cred));319consume_str(fido_cred_display_name(cred));320val = fido_cred_prot(cred);321consume(&val, sizeof(val));322}323324fido_credman_rk_free(&rk);325fido_dev_close(dev);326fido_dev_free(&dev);327}328329static void330del_rk(const struct param *p)331{332fido_dev_t *dev;333334set_wire_data(p->del_wire_data.body, p->del_wire_data.len);335336if ((dev = prepare_dev()) == NULL)337return;338339fido_credman_del_dev_rk(dev, p->cred_id.body, p->cred_id.len, p->pin);340fido_dev_close(dev);341fido_dev_free(&dev);342}343344static void345set_rk(const struct param *p)346{347fido_dev_t *dev = NULL;348fido_cred_t *cred = NULL;349const char *pin = p->pin;350int r0, r1, r2;351352set_wire_data(p->del_wire_data.body, p->del_wire_data.len);353354if ((dev = prepare_dev()) == NULL)355return;356if ((cred = fido_cred_new()) == NULL)357goto out;358r0 = fido_cred_set_id(cred, p->cred_id.body, p->cred_id.len);359r1 = fido_cred_set_user(cred, p->cred_id.body, p->cred_id.len, p->rp_id,360NULL, NULL);361if (strlen(pin) == 0)362pin = NULL;363r2 = fido_credman_set_dev_rk(dev, cred, pin);364consume(&r0, sizeof(r0));365consume(&r1, sizeof(r1));366consume(&r2, sizeof(r2));367out:368fido_dev_close(dev);369fido_dev_free(&dev);370fido_cred_free(&cred);371}372373void374test(const struct param *p)375{376prng_init((unsigned int)p->seed);377fuzz_clock_reset();378fido_init(FIDO_DEBUG);379fido_set_log_handler(consume_str);380381get_metadata(p);382get_rp_list(p);383get_rk_list(p);384del_rk(p);385set_rk(p);386}387388void389mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN390{391if (flags & MUTATE_SEED)392p->seed = (int)seed;393394if (flags & MUTATE_PARAM) {395mutate_blob(&p->cred_id);396mutate_string(p->pin);397mutate_string(p->rp_id);398}399400if (flags & MUTATE_WIREDATA) {401mutate_blob(&p->meta_wire_data);402mutate_blob(&p->rp_wire_data);403mutate_blob(&p->rk_wire_data);404mutate_blob(&p->del_wire_data);405}406}407408409