10afa8e06SEd Maste /* 20afa8e06SEd Maste * Copyright (c) 2020 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. 50afa8e06SEd Maste */ 60afa8e06SEd Maste 70afa8e06SEd Maste #include <assert.h> 80afa8e06SEd Maste #include <stdint.h> 90afa8e06SEd Maste #include <stdlib.h> 100afa8e06SEd Maste #include <string.h> 110afa8e06SEd Maste #include <stdio.h> 120afa8e06SEd Maste 130afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h" 140afa8e06SEd Maste #include "mutator_aux.h" 15*f540a430SEd Maste #include "dummy.h" 160afa8e06SEd Maste 170afa8e06SEd Maste struct param { 180afa8e06SEd Maste int seed; 190afa8e06SEd Maste int dev; 200afa8e06SEd Maste struct blob wiredata; 210afa8e06SEd Maste }; 220afa8e06SEd Maste 230afa8e06SEd Maste struct param * 240afa8e06SEd Maste unpack(const uint8_t *ptr, size_t len) 250afa8e06SEd Maste { 260afa8e06SEd Maste cbor_item_t *item = NULL, **v; 270afa8e06SEd Maste struct cbor_load_result cbor; 280afa8e06SEd Maste struct param *p; 290afa8e06SEd Maste int ok = -1; 300afa8e06SEd Maste 310afa8e06SEd Maste if ((p = calloc(1, sizeof(*p))) == NULL || 320afa8e06SEd Maste (item = cbor_load(ptr, len, &cbor)) == NULL || 330afa8e06SEd Maste cbor.read != len || 340afa8e06SEd Maste cbor_isa_array(item) == false || 350afa8e06SEd Maste cbor_array_is_definite(item) == false || 360afa8e06SEd Maste cbor_array_size(item) != 3 || 370afa8e06SEd Maste (v = cbor_array_handle(item)) == NULL) 380afa8e06SEd Maste goto fail; 390afa8e06SEd Maste 400afa8e06SEd Maste if (unpack_int(v[0], &p->seed) < 0 || 410afa8e06SEd Maste unpack_int(v[1], &p->dev) < 0 || 420afa8e06SEd Maste unpack_blob(v[2], &p->wiredata) < 0) 430afa8e06SEd Maste goto fail; 440afa8e06SEd Maste 450afa8e06SEd Maste ok = 0; 460afa8e06SEd Maste fail: 470afa8e06SEd Maste if (ok < 0) { 480afa8e06SEd Maste free(p); 490afa8e06SEd Maste p = NULL; 500afa8e06SEd Maste } 510afa8e06SEd Maste 520afa8e06SEd Maste if (item) 530afa8e06SEd Maste cbor_decref(&item); 540afa8e06SEd Maste 550afa8e06SEd Maste return p; 560afa8e06SEd Maste } 570afa8e06SEd Maste 580afa8e06SEd Maste size_t 590afa8e06SEd Maste pack(uint8_t *ptr, size_t len, const struct param *p) 600afa8e06SEd Maste { 610afa8e06SEd Maste cbor_item_t *argv[3], *array = NULL; 620afa8e06SEd Maste size_t cbor_alloc_len, cbor_len = 0; 630afa8e06SEd Maste unsigned char *cbor = NULL; 640afa8e06SEd Maste 650afa8e06SEd Maste memset(argv, 0, sizeof(argv)); 660afa8e06SEd Maste 670afa8e06SEd Maste if ((array = cbor_new_definite_array(3)) == NULL || 680afa8e06SEd Maste (argv[0] = pack_int(p->seed)) == NULL || 690afa8e06SEd Maste (argv[1] = pack_int(p->dev)) == NULL || 700afa8e06SEd Maste (argv[2] = pack_blob(&p->wiredata)) == NULL) 710afa8e06SEd Maste goto fail; 720afa8e06SEd Maste 730afa8e06SEd Maste for (size_t i = 0; i < 3; i++) 740afa8e06SEd Maste if (cbor_array_push(array, argv[i]) == false) 750afa8e06SEd Maste goto fail; 760afa8e06SEd Maste 770afa8e06SEd Maste if ((cbor_len = cbor_serialize_alloc(array, &cbor, 780afa8e06SEd Maste &cbor_alloc_len)) > len) { 790afa8e06SEd Maste cbor_len = 0; 800afa8e06SEd Maste goto fail; 810afa8e06SEd Maste } 820afa8e06SEd Maste 830afa8e06SEd Maste memcpy(ptr, cbor, cbor_len); 840afa8e06SEd Maste fail: 850afa8e06SEd Maste for (size_t i = 0; i < 3; i++) 860afa8e06SEd Maste if (argv[i]) 870afa8e06SEd Maste cbor_decref(&argv[i]); 880afa8e06SEd Maste 890afa8e06SEd Maste if (array) 900afa8e06SEd Maste cbor_decref(&array); 910afa8e06SEd Maste 920afa8e06SEd Maste free(cbor); 930afa8e06SEd Maste 940afa8e06SEd Maste return cbor_len; 950afa8e06SEd Maste } 960afa8e06SEd Maste 970afa8e06SEd Maste size_t 980afa8e06SEd Maste pack_dummy(uint8_t *ptr, size_t len) 990afa8e06SEd Maste { 1000afa8e06SEd Maste struct param dummy; 1010afa8e06SEd Maste uint8_t blob[4096]; 1020afa8e06SEd Maste size_t blob_len; 1030afa8e06SEd Maste 1040afa8e06SEd Maste memset(&dummy, 0, sizeof(dummy)); 1050afa8e06SEd Maste 106*f540a430SEd Maste dummy.wiredata.len = sizeof(dummy_netlink_wiredata); 107*f540a430SEd Maste memcpy(&dummy.wiredata.body, &dummy_netlink_wiredata, 1080afa8e06SEd Maste dummy.wiredata.len); 1090afa8e06SEd Maste 1100afa8e06SEd Maste assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); 1110afa8e06SEd Maste 1120afa8e06SEd Maste if (blob_len > len) { 1130afa8e06SEd Maste memcpy(ptr, blob, len); 1140afa8e06SEd Maste return len; 1150afa8e06SEd Maste } 1160afa8e06SEd Maste 1170afa8e06SEd Maste memcpy(ptr, blob, blob_len); 1180afa8e06SEd Maste 1190afa8e06SEd Maste return blob_len; 1200afa8e06SEd Maste } 1210afa8e06SEd Maste 1220afa8e06SEd Maste void 1230afa8e06SEd Maste test(const struct param *p) 1240afa8e06SEd Maste { 1250afa8e06SEd Maste fido_nl_t *nl; 1260afa8e06SEd Maste uint32_t target; 1270afa8e06SEd Maste 1280afa8e06SEd Maste prng_init((unsigned int)p->seed); 129*f540a430SEd Maste fuzz_clock_reset(); 1300afa8e06SEd Maste fido_init(FIDO_DEBUG); 1310afa8e06SEd Maste fido_set_log_handler(consume_str); 1320afa8e06SEd Maste 1330afa8e06SEd Maste set_netlink_io_functions(fd_read, fd_write); 1340afa8e06SEd Maste set_wire_data(p->wiredata.body, p->wiredata.len); 1350afa8e06SEd Maste 1360afa8e06SEd Maste if ((nl = fido_nl_new()) == NULL) 1370afa8e06SEd Maste return; 1380afa8e06SEd Maste 1390afa8e06SEd Maste consume(&nl->fd, sizeof(nl->fd)); 1400afa8e06SEd Maste consume(&nl->nfc_type, sizeof(nl->nfc_type)); 1410afa8e06SEd Maste consume(&nl->nfc_mcastgrp, sizeof(nl->nfc_mcastgrp)); 1420afa8e06SEd Maste consume(&nl->saddr, sizeof(nl->saddr)); 1430afa8e06SEd Maste 1440afa8e06SEd Maste fido_nl_power_nfc(nl, (uint32_t)p->dev); 1450afa8e06SEd Maste 1460afa8e06SEd Maste if (fido_nl_get_nfc_target(nl, (uint32_t)p->dev, &target) == 0) 1470afa8e06SEd Maste consume(&target, sizeof(target)); 1480afa8e06SEd Maste 1490afa8e06SEd Maste fido_nl_free(&nl); 1500afa8e06SEd Maste } 1510afa8e06SEd Maste 1520afa8e06SEd Maste void 1530afa8e06SEd Maste mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN 1540afa8e06SEd Maste { 1550afa8e06SEd Maste if (flags & MUTATE_SEED) 1560afa8e06SEd Maste p->seed = (int)seed; 1570afa8e06SEd Maste 1580afa8e06SEd Maste if (flags & MUTATE_PARAM) 1590afa8e06SEd Maste mutate_int(&p->dev); 1600afa8e06SEd Maste 1610afa8e06SEd Maste if (flags & MUTATE_WIREDATA) 1620afa8e06SEd Maste mutate_blob(&p->wiredata); 1630afa8e06SEd Maste } 164