Path: blob/main/contrib/libfido2/fuzz/fuzz_mgmt.c
101206 views
/*1* Copyright (c) 2019-2022 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#define MAXRPID 642021struct param {22char pin1[MAXSTR];23char pin2[MAXSTR];24struct blob reset_wire_data;25struct blob info_wire_data;26struct blob set_pin_wire_data;27struct blob change_pin_wire_data;28struct blob retry_wire_data;29struct blob config_wire_data;30int seed;31};3233static const uint8_t dummy_reset_wire_data[] = {34WIREDATA_CTAP_INIT,35WIREDATA_CTAP_CBOR_INFO,36WIREDATA_CTAP_KEEPALIVE,37WIREDATA_CTAP_KEEPALIVE,38WIREDATA_CTAP_KEEPALIVE,39WIREDATA_CTAP_CBOR_STATUS,40};4142static const uint8_t dummy_info_wire_data[] = {43WIREDATA_CTAP_INIT,44WIREDATA_CTAP_CBOR_INFO,45WIREDATA_CTAP_CBOR_INFO,46};4748static const uint8_t dummy_set_pin_wire_data[] = {49WIREDATA_CTAP_INIT,50WIREDATA_CTAP_CBOR_INFO,51WIREDATA_CTAP_CBOR_AUTHKEY,52WIREDATA_CTAP_CBOR_STATUS,53};5455static const uint8_t dummy_change_pin_wire_data[] = {56WIREDATA_CTAP_INIT,57WIREDATA_CTAP_CBOR_INFO,58WIREDATA_CTAP_CBOR_AUTHKEY,59WIREDATA_CTAP_CBOR_STATUS,60};6162static const uint8_t dummy_retry_wire_data[] = {63WIREDATA_CTAP_INIT,64WIREDATA_CTAP_CBOR_INFO,65WIREDATA_CTAP_CBOR_RETRIES,66};6768static const uint8_t dummy_config_wire_data[] = {69WIREDATA_CTAP_INIT,70WIREDATA_CTAP_CBOR_INFO,71WIREDATA_CTAP_CBOR_STATUS,72};7374struct param *75unpack(const uint8_t *ptr, size_t len)76{77cbor_item_t *item = NULL, **v;78struct cbor_load_result cbor;79struct param *p;80int ok = -1;8182if ((p = calloc(1, sizeof(*p))) == NULL ||83(item = cbor_load(ptr, len, &cbor)) == NULL ||84cbor.read != len ||85cbor_isa_array(item) == false ||86cbor_array_is_definite(item) == false ||87cbor_array_size(item) != 9 ||88(v = cbor_array_handle(item)) == NULL)89goto fail;9091if (unpack_int(v[0], &p->seed) < 0 ||92unpack_string(v[1], p->pin1) < 0 ||93unpack_string(v[2], p->pin2) < 0 ||94unpack_blob(v[3], &p->reset_wire_data) < 0 ||95unpack_blob(v[4], &p->info_wire_data) < 0 ||96unpack_blob(v[5], &p->set_pin_wire_data) < 0 ||97unpack_blob(v[6], &p->change_pin_wire_data) < 0 ||98unpack_blob(v[7], &p->retry_wire_data) < 0 ||99unpack_blob(v[8], &p->config_wire_data) < 0)100goto fail;101102ok = 0;103fail:104if (ok < 0) {105free(p);106p = NULL;107}108109if (item)110cbor_decref(&item);111112return p;113}114115size_t116pack(uint8_t *ptr, size_t len, const struct param *p)117{118cbor_item_t *argv[9], *array = NULL;119size_t cbor_alloc_len, cbor_len = 0;120unsigned char *cbor = NULL;121122memset(argv, 0, sizeof(argv));123124if ((array = cbor_new_definite_array(9)) == NULL ||125(argv[0] = pack_int(p->seed)) == NULL ||126(argv[1] = pack_string(p->pin1)) == NULL ||127(argv[2] = pack_string(p->pin2)) == NULL ||128(argv[3] = pack_blob(&p->reset_wire_data)) == NULL ||129(argv[4] = pack_blob(&p->info_wire_data)) == NULL ||130(argv[5] = pack_blob(&p->set_pin_wire_data)) == NULL ||131(argv[6] = pack_blob(&p->change_pin_wire_data)) == NULL ||132(argv[7] = pack_blob(&p->retry_wire_data)) == NULL ||133(argv[8] = pack_blob(&p->config_wire_data)) == NULL)134goto fail;135136for (size_t i = 0; i < 9; i++)137if (cbor_array_push(array, argv[i]) == false)138goto fail;139140if ((cbor_len = cbor_serialize_alloc(array, &cbor,141&cbor_alloc_len)) == 0 || cbor_len > len) {142cbor_len = 0;143goto fail;144}145146memcpy(ptr, cbor, cbor_len);147fail:148for (size_t i = 0; i < 9; i++)149if (argv[i])150cbor_decref(&argv[i]);151152if (array)153cbor_decref(&array);154155free(cbor);156157return cbor_len;158}159160size_t161pack_dummy(uint8_t *ptr, size_t len)162{163struct param dummy;164uint8_t blob[MAXCORPUS];165size_t blob_len;166167memset(&dummy, 0, sizeof(dummy));168169strlcpy(dummy.pin1, dummy_pin1, sizeof(dummy.pin1));170strlcpy(dummy.pin2, dummy_pin2, sizeof(dummy.pin2));171172dummy.reset_wire_data.len = sizeof(dummy_reset_wire_data);173dummy.info_wire_data.len = sizeof(dummy_info_wire_data);174dummy.set_pin_wire_data.len = sizeof(dummy_set_pin_wire_data);175dummy.change_pin_wire_data.len = sizeof(dummy_change_pin_wire_data);176dummy.retry_wire_data.len = sizeof(dummy_retry_wire_data);177dummy.config_wire_data.len = sizeof(dummy_config_wire_data);178179memcpy(&dummy.reset_wire_data.body, &dummy_reset_wire_data,180dummy.reset_wire_data.len);181memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data,182dummy.info_wire_data.len);183memcpy(&dummy.set_pin_wire_data.body, &dummy_set_pin_wire_data,184dummy.set_pin_wire_data.len);185memcpy(&dummy.change_pin_wire_data.body, &dummy_change_pin_wire_data,186dummy.change_pin_wire_data.len);187memcpy(&dummy.retry_wire_data.body, &dummy_retry_wire_data,188dummy.retry_wire_data.len);189memcpy(&dummy.config_wire_data.body, &dummy_config_wire_data,190dummy.config_wire_data.len);191192assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);193194if (blob_len > len) {195memcpy(ptr, blob, len);196return len;197}198199memcpy(ptr, blob, blob_len);200201return blob_len;202}203204static void205dev_reset(const struct param *p)206{207fido_dev_t *dev;208209set_wire_data(p->reset_wire_data.body, p->reset_wire_data.len);210211if ((dev = open_dev(0)) == NULL)212return;213214fido_dev_reset(dev);215fido_dev_close(dev);216fido_dev_free(&dev);217}218219static void220dev_get_cbor_info(const struct param *p)221{222fido_dev_t *dev;223fido_cbor_info_t *ci;224uint64_t n;225uint8_t proto, major, minor, build, flags;226bool v;227228set_wire_data(p->info_wire_data.body, p->info_wire_data.len);229230if ((dev = open_dev(0)) == NULL)231return;232233proto = fido_dev_protocol(dev);234major = fido_dev_major(dev);235minor = fido_dev_minor(dev);236build = fido_dev_build(dev);237flags = fido_dev_flags(dev);238239consume(&proto, sizeof(proto));240consume(&major, sizeof(major));241consume(&minor, sizeof(minor));242consume(&build, sizeof(build));243consume(&flags, sizeof(flags));244245if ((ci = fido_cbor_info_new()) == NULL)246goto out;247248fido_dev_get_cbor_info(dev, ci);249250for (size_t i = 0; i < fido_cbor_info_versions_len(ci); i++) {251char * const *sa = fido_cbor_info_versions_ptr(ci);252consume(sa[i], strlen(sa[i]));253}254255for (size_t i = 0; i < fido_cbor_info_extensions_len(ci); i++) {256char * const *sa = fido_cbor_info_extensions_ptr(ci);257consume(sa[i], strlen(sa[i]));258}259260for (size_t i = 0; i < fido_cbor_info_transports_len(ci); i++) {261char * const *sa = fido_cbor_info_transports_ptr(ci);262consume(sa[i], strlen(sa[i]));263}264265for (size_t i = 0; i < fido_cbor_info_options_len(ci); i++) {266char * const *sa = fido_cbor_info_options_name_ptr(ci);267const bool *va = fido_cbor_info_options_value_ptr(ci);268consume(sa[i], strlen(sa[i]));269consume(&va[i], sizeof(va[i]));270}271272/* +1 on purpose */273for (size_t i = 0; i <= fido_cbor_info_algorithm_count(ci); i++) {274const char *type = fido_cbor_info_algorithm_type(ci, i);275int cose = fido_cbor_info_algorithm_cose(ci, i);276consume_str(type);277consume(&cose, sizeof(cose));278}279280for (size_t i = 0; i < fido_cbor_info_certs_len(ci); i++) {281char * const *na = fido_cbor_info_certs_name_ptr(ci);282const uint64_t *va = fido_cbor_info_certs_value_ptr(ci);283consume(na[i], strlen(na[i]));284consume(&va[i], sizeof(va[i]));285}286287n = fido_cbor_info_maxmsgsiz(ci);288consume(&n, sizeof(n));289n = fido_cbor_info_maxcredbloblen(ci);290consume(&n, sizeof(n));291n = fido_cbor_info_maxcredcntlst(ci);292consume(&n, sizeof(n));293n = fido_cbor_info_maxcredidlen(ci);294consume(&n, sizeof(n));295n = fido_cbor_info_maxlargeblob(ci);296consume(&n, sizeof(n));297n = fido_cbor_info_fwversion(ci);298consume(&n, sizeof(n));299n = fido_cbor_info_minpinlen(ci);300consume(&n, sizeof(n));301n = fido_cbor_info_maxrpid_minpinlen(ci);302consume(&n, sizeof(n));303n = fido_cbor_info_uv_attempts(ci);304consume(&n, sizeof(n));305n = fido_cbor_info_uv_modality(ci);306consume(&n, sizeof(n));307n = (uint64_t)fido_cbor_info_rk_remaining(ci);308consume(&n, sizeof(n));309310consume(fido_cbor_info_aaguid_ptr(ci), fido_cbor_info_aaguid_len(ci));311consume(fido_cbor_info_protocols_ptr(ci),312fido_cbor_info_protocols_len(ci));313314v = fido_cbor_info_new_pin_required(ci);315consume(&v, sizeof(v));316317out:318fido_dev_close(dev);319fido_dev_free(&dev);320321fido_cbor_info_free(&ci);322}323324static void325dev_set_pin(const struct param *p)326{327fido_dev_t *dev;328329set_wire_data(p->set_pin_wire_data.body, p->set_pin_wire_data.len);330331if ((dev = open_dev(0)) == NULL)332return;333334fido_dev_set_pin(dev, p->pin1, NULL);335fido_dev_close(dev);336fido_dev_free(&dev);337}338339static void340dev_change_pin(const struct param *p)341{342fido_dev_t *dev;343344set_wire_data(p->change_pin_wire_data.body, p->change_pin_wire_data.len);345346if ((dev = open_dev(0)) == NULL)347return;348349fido_dev_set_pin(dev, p->pin2, p->pin1);350fido_dev_close(dev);351fido_dev_free(&dev);352}353354static void355dev_get_retry_count(const struct param *p)356{357fido_dev_t *dev;358int n = 0;359360set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len);361362if ((dev = open_dev(0)) == NULL)363return;364365fido_dev_get_retry_count(dev, &n);366consume(&n, sizeof(n));367fido_dev_close(dev);368fido_dev_free(&dev);369}370371static void372dev_get_uv_retry_count(const struct param *p)373{374fido_dev_t *dev;375int n = 0;376377set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len);378379if ((dev = open_dev(0)) == NULL)380return;381382fido_dev_get_uv_retry_count(dev, &n);383consume(&n, sizeof(n));384fido_dev_close(dev);385fido_dev_free(&dev);386}387388static void389dev_enable_entattest(const struct param *p)390{391fido_dev_t *dev;392const char *pin;393int r;394395set_wire_data(p->config_wire_data.body, p->config_wire_data.len);396if ((dev = open_dev(0)) == NULL)397return;398pin = p->pin1;399if (strlen(pin) == 0)400pin = NULL;401r = fido_dev_enable_entattest(dev, pin);402consume_str(fido_strerr(r));403fido_dev_close(dev);404fido_dev_free(&dev);405}406407static void408dev_toggle_always_uv(const struct param *p)409{410fido_dev_t *dev;411const char *pin;412int r;413414set_wire_data(p->config_wire_data.body, p->config_wire_data.len);415if ((dev = open_dev(0)) == NULL)416return;417pin = p->pin1;418if (strlen(pin) == 0)419pin = NULL;420r = fido_dev_toggle_always_uv(dev, pin);421consume_str(fido_strerr(r));422fido_dev_close(dev);423fido_dev_free(&dev);424}425426static void427dev_force_pin_change(const struct param *p)428{429fido_dev_t *dev;430const char *pin;431int r;432433set_wire_data(p->config_wire_data.body, p->config_wire_data.len);434if ((dev = open_dev(0)) == NULL)435return;436pin = p->pin1;437if (strlen(pin) == 0)438pin = NULL;439r = fido_dev_force_pin_change(dev, pin);440consume_str(fido_strerr(r));441fido_dev_close(dev);442fido_dev_free(&dev);443}444445static void446dev_set_pin_minlen(const struct param *p)447{448fido_dev_t *dev;449const char *pin;450int r;451452set_wire_data(p->config_wire_data.body, p->config_wire_data.len);453if ((dev = open_dev(0)) == NULL)454return;455pin = p->pin1;456if (strlen(pin) == 0)457pin = NULL;458r = fido_dev_set_pin_minlen(dev, strlen(p->pin2), pin);459consume_str(fido_strerr(r));460fido_dev_close(dev);461fido_dev_free(&dev);462}463464static void465dev_set_pin_minlen_rpid(const struct param *p)466{467fido_dev_t *dev;468const char *rpid[MAXRPID];469const char *pin;470size_t n;471int r;472473set_wire_data(p->config_wire_data.body, p->config_wire_data.len);474if ((dev = open_dev(0)) == NULL)475return;476n = uniform_random(MAXRPID);477for (size_t i = 0; i < n; i++)478rpid[i] = dummy_rp_id;479pin = p->pin1;480if (strlen(pin) == 0)481pin = NULL;482r = fido_dev_set_pin_minlen_rpid(dev, rpid, n, pin);483consume_str(fido_strerr(r));484fido_dev_close(dev);485fido_dev_free(&dev);486}487488void489test(const struct param *p)490{491prng_init((unsigned int)p->seed);492fuzz_clock_reset();493fido_init(FIDO_DEBUG);494fido_set_log_handler(consume_str);495496dev_reset(p);497dev_get_cbor_info(p);498dev_set_pin(p);499dev_change_pin(p);500dev_get_retry_count(p);501dev_get_uv_retry_count(p);502dev_enable_entattest(p);503dev_toggle_always_uv(p);504dev_force_pin_change(p);505dev_set_pin_minlen(p);506dev_set_pin_minlen_rpid(p);507}508509void510mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN511{512if (flags & MUTATE_SEED)513p->seed = (int)seed;514515if (flags & MUTATE_PARAM) {516mutate_string(p->pin1);517mutate_string(p->pin2);518}519520if (flags & MUTATE_WIREDATA) {521mutate_blob(&p->reset_wire_data);522mutate_blob(&p->info_wire_data);523mutate_blob(&p->set_pin_wire_data);524mutate_blob(&p->change_pin_wire_data);525mutate_blob(&p->retry_wire_data);526}527}528529530