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.
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 "large blob" operation. */
210afa8e06SEd Maste struct param {
220afa8e06SEd Maste char pin[MAXSTR];
230afa8e06SEd Maste int seed;
240afa8e06SEd Maste struct blob key;
250afa8e06SEd Maste struct blob get_wiredata;
260afa8e06SEd Maste struct blob set_wiredata;
270afa8e06SEd Maste };
280afa8e06SEd Maste
290afa8e06SEd Maste /*
300afa8e06SEd Maste * Collection of HID reports from an authenticator issued with a FIDO2
310afa8e06SEd Maste * 'authenticatorLargeBlobs' 'get' command.
320afa8e06SEd Maste */
330afa8e06SEd Maste static const uint8_t dummy_get_wiredata[] = {
340afa8e06SEd Maste WIREDATA_CTAP_INIT,
350afa8e06SEd Maste WIREDATA_CTAP_CBOR_INFO,
360afa8e06SEd Maste WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY
370afa8e06SEd Maste };
380afa8e06SEd Maste
390afa8e06SEd Maste /*
400afa8e06SEd Maste * Collection of HID reports from an authenticator issued with a FIDO2
410afa8e06SEd Maste * 'authenticatorLargeBlobs' 'set' command.
420afa8e06SEd Maste */
430afa8e06SEd Maste static const uint8_t dummy_set_wiredata[] = {
440afa8e06SEd Maste WIREDATA_CTAP_INIT,
450afa8e06SEd Maste WIREDATA_CTAP_CBOR_INFO,
460afa8e06SEd Maste WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY,
470afa8e06SEd Maste WIREDATA_CTAP_CBOR_AUTHKEY,
480afa8e06SEd Maste WIREDATA_CTAP_CBOR_PINTOKEN,
490afa8e06SEd Maste WIREDATA_CTAP_CBOR_STATUS
500afa8e06SEd Maste };
510afa8e06SEd Maste
520afa8e06SEd Maste /*
530afa8e06SEd Maste * XXX this needs to match the encrypted blob embedded in
540afa8e06SEd Maste * WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY.
550afa8e06SEd Maste */
560afa8e06SEd Maste static const uint8_t dummy_key[] = {
570afa8e06SEd Maste 0xa9, 0x1b, 0xc4, 0xdd, 0xfc, 0x9a, 0x93, 0x79,
580afa8e06SEd Maste 0x75, 0xba, 0xf7, 0x7f, 0x4d, 0x57, 0xfc, 0xa6,
590afa8e06SEd Maste 0xe1, 0xf8, 0x06, 0x43, 0x23, 0x99, 0x51, 0x32,
600afa8e06SEd Maste 0xce, 0x6e, 0x19, 0x84, 0x50, 0x13, 0x2d, 0x7b
610afa8e06SEd Maste };
620afa8e06SEd Maste
630afa8e06SEd Maste struct param *
unpack(const uint8_t * ptr,size_t len)640afa8e06SEd Maste unpack(const uint8_t *ptr, size_t len)
650afa8e06SEd Maste {
660afa8e06SEd Maste cbor_item_t *item = NULL, **v;
670afa8e06SEd Maste struct cbor_load_result cbor;
680afa8e06SEd Maste struct param *p;
690afa8e06SEd Maste int ok = -1;
700afa8e06SEd Maste
710afa8e06SEd Maste if ((p = calloc(1, sizeof(*p))) == NULL ||
720afa8e06SEd Maste (item = cbor_load(ptr, len, &cbor)) == NULL ||
730afa8e06SEd Maste cbor.read != len ||
740afa8e06SEd Maste cbor_isa_array(item) == false ||
750afa8e06SEd Maste cbor_array_is_definite(item) == false ||
760afa8e06SEd Maste cbor_array_size(item) != 5 ||
770afa8e06SEd Maste (v = cbor_array_handle(item)) == NULL)
780afa8e06SEd Maste goto fail;
790afa8e06SEd Maste
800afa8e06SEd Maste if (unpack_int(v[0], &p->seed) < 0 ||
810afa8e06SEd Maste unpack_string(v[1], p->pin) < 0 ||
820afa8e06SEd Maste unpack_blob(v[2], &p->key) < 0 ||
830afa8e06SEd Maste unpack_blob(v[3], &p->get_wiredata) < 0 ||
840afa8e06SEd Maste unpack_blob(v[4], &p->set_wiredata) < 0)
850afa8e06SEd Maste goto fail;
860afa8e06SEd Maste
870afa8e06SEd Maste ok = 0;
880afa8e06SEd Maste fail:
890afa8e06SEd Maste if (ok < 0) {
900afa8e06SEd Maste free(p);
910afa8e06SEd Maste p = NULL;
920afa8e06SEd Maste }
930afa8e06SEd Maste
940afa8e06SEd Maste if (item)
950afa8e06SEd Maste cbor_decref(&item);
960afa8e06SEd Maste
970afa8e06SEd Maste return p;
980afa8e06SEd Maste }
990afa8e06SEd Maste
1000afa8e06SEd Maste size_t
pack(uint8_t * ptr,size_t len,const struct param * p)1010afa8e06SEd Maste pack(uint8_t *ptr, size_t len, const struct param *p)
1020afa8e06SEd Maste {
1030afa8e06SEd Maste cbor_item_t *argv[5], *array = NULL;
1040afa8e06SEd Maste size_t cbor_alloc_len, cbor_len = 0;
1050afa8e06SEd Maste unsigned char *cbor = NULL;
1060afa8e06SEd Maste
1070afa8e06SEd Maste memset(argv, 0, sizeof(argv));
1080afa8e06SEd Maste
1090afa8e06SEd Maste if ((array = cbor_new_definite_array(5)) == NULL ||
1100afa8e06SEd Maste (argv[0] = pack_int(p->seed)) == NULL ||
1110afa8e06SEd Maste (argv[1] = pack_string(p->pin)) == NULL ||
1120afa8e06SEd Maste (argv[2] = pack_blob(&p->key)) == NULL ||
1130afa8e06SEd Maste (argv[3] = pack_blob(&p->get_wiredata)) == NULL ||
1140afa8e06SEd Maste (argv[4] = pack_blob(&p->set_wiredata)) == NULL)
1150afa8e06SEd Maste goto fail;
1160afa8e06SEd Maste
1170afa8e06SEd Maste for (size_t i = 0; i < 5; i++)
1180afa8e06SEd Maste if (cbor_array_push(array, argv[i]) == false)
1190afa8e06SEd Maste goto fail;
1200afa8e06SEd Maste
1210afa8e06SEd Maste if ((cbor_len = cbor_serialize_alloc(array, &cbor,
122*2ccfa855SEd Maste &cbor_alloc_len)) == 0 || cbor_len > len) {
1230afa8e06SEd Maste cbor_len = 0;
1240afa8e06SEd Maste goto fail;
1250afa8e06SEd Maste }
1260afa8e06SEd Maste
1270afa8e06SEd Maste memcpy(ptr, cbor, cbor_len);
1280afa8e06SEd Maste fail:
1290afa8e06SEd Maste for (size_t i = 0; i < 5; i++)
1300afa8e06SEd Maste if (argv[i])
1310afa8e06SEd Maste cbor_decref(&argv[i]);
1320afa8e06SEd Maste
1330afa8e06SEd Maste if (array)
1340afa8e06SEd Maste cbor_decref(&array);
1350afa8e06SEd Maste
1360afa8e06SEd Maste free(cbor);
1370afa8e06SEd Maste
1380afa8e06SEd Maste return cbor_len;
1390afa8e06SEd Maste }
1400afa8e06SEd Maste
1410afa8e06SEd Maste size_t
pack_dummy(uint8_t * ptr,size_t len)1420afa8e06SEd Maste pack_dummy(uint8_t *ptr, size_t len)
1430afa8e06SEd Maste {
1440afa8e06SEd Maste struct param dummy;
145*2ccfa855SEd Maste uint8_t blob[MAXCORPUS];
1460afa8e06SEd Maste size_t blob_len;
1470afa8e06SEd Maste
1480afa8e06SEd Maste memset(&dummy, 0, sizeof(dummy));
1490afa8e06SEd Maste
1500afa8e06SEd Maste strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
1510afa8e06SEd Maste
1520afa8e06SEd Maste dummy.get_wiredata.len = sizeof(dummy_get_wiredata);
1530afa8e06SEd Maste dummy.set_wiredata.len = sizeof(dummy_set_wiredata);
1540afa8e06SEd Maste dummy.key.len = sizeof(dummy_key);
1550afa8e06SEd Maste
1560afa8e06SEd Maste memcpy(&dummy.get_wiredata.body, &dummy_get_wiredata,
1570afa8e06SEd Maste dummy.get_wiredata.len);
1580afa8e06SEd Maste memcpy(&dummy.set_wiredata.body, &dummy_set_wiredata,
1590afa8e06SEd Maste dummy.set_wiredata.len);
1600afa8e06SEd Maste memcpy(&dummy.key.body, &dummy_key, dummy.key.len);
1610afa8e06SEd Maste
1620afa8e06SEd Maste assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
1630afa8e06SEd Maste
1640afa8e06SEd Maste if (blob_len > len) {
1650afa8e06SEd Maste memcpy(ptr, blob, len);
1660afa8e06SEd Maste return len;
1670afa8e06SEd Maste }
1680afa8e06SEd Maste
1690afa8e06SEd Maste memcpy(ptr, blob, blob_len);
1700afa8e06SEd Maste
1710afa8e06SEd Maste return blob_len;
1720afa8e06SEd Maste }
1730afa8e06SEd Maste
1740afa8e06SEd Maste static fido_dev_t *
prepare_dev(void)1750afa8e06SEd Maste prepare_dev(void)
1760afa8e06SEd Maste {
1770afa8e06SEd Maste fido_dev_t *dev;
1780afa8e06SEd Maste
1790afa8e06SEd Maste if ((dev = open_dev(0)) == NULL)
1800afa8e06SEd Maste return NULL;
1810afa8e06SEd Maste
1820afa8e06SEd Maste return dev;
1830afa8e06SEd Maste }
1840afa8e06SEd Maste
1850afa8e06SEd Maste static void
get_blob(const struct param * p,int array)1860afa8e06SEd Maste get_blob(const struct param *p, int array)
1870afa8e06SEd Maste {
1880afa8e06SEd Maste fido_dev_t *dev;
1890afa8e06SEd Maste u_char *ptr = NULL;
1900afa8e06SEd Maste size_t len = 0;
1910afa8e06SEd Maste
1920afa8e06SEd Maste set_wire_data(p->get_wiredata.body, p->get_wiredata.len);
1930afa8e06SEd Maste
1940afa8e06SEd Maste if ((dev = prepare_dev()) == NULL)
1950afa8e06SEd Maste return;
1960afa8e06SEd Maste
1970afa8e06SEd Maste if (array)
1980afa8e06SEd Maste fido_dev_largeblob_get_array(dev, &ptr, &len);
1990afa8e06SEd Maste else
2000afa8e06SEd Maste fido_dev_largeblob_get(dev, p->key.body, p->key.len, &ptr, &len);
2010afa8e06SEd Maste consume(ptr, len);
2020afa8e06SEd Maste free(ptr);
2030afa8e06SEd Maste
2040afa8e06SEd Maste fido_dev_close(dev);
2050afa8e06SEd Maste fido_dev_free(&dev);
2060afa8e06SEd Maste }
2070afa8e06SEd Maste
2080afa8e06SEd Maste
2090afa8e06SEd Maste static void
set_blob(const struct param * p,int op)2100afa8e06SEd Maste set_blob(const struct param *p, int op)
2110afa8e06SEd Maste {
2120afa8e06SEd Maste fido_dev_t *dev;
2130afa8e06SEd Maste const char *pin;
2140afa8e06SEd Maste
2150afa8e06SEd Maste set_wire_data(p->set_wiredata.body, p->set_wiredata.len);
2160afa8e06SEd Maste
2170afa8e06SEd Maste if ((dev = prepare_dev()) == NULL)
2180afa8e06SEd Maste return;
2190afa8e06SEd Maste pin = p->pin;
2200afa8e06SEd Maste if (strlen(pin) == 0)
2210afa8e06SEd Maste pin = NULL;
2220afa8e06SEd Maste
2230afa8e06SEd Maste switch (op) {
2240afa8e06SEd Maste case 0:
2250afa8e06SEd Maste fido_dev_largeblob_remove(dev, p->key.body, p->key.len, pin);
2260afa8e06SEd Maste break;
2270afa8e06SEd Maste case 1:
2280afa8e06SEd Maste /* XXX reuse p->get_wiredata as the blob to be set */
2290afa8e06SEd Maste fido_dev_largeblob_set(dev, p->key.body, p->key.len,
2300afa8e06SEd Maste p->get_wiredata.body, p->get_wiredata.len, pin);
2310afa8e06SEd Maste break;
2320afa8e06SEd Maste case 2:
2330afa8e06SEd Maste /* XXX reuse p->get_wiredata as the body of the cbor array */
2340afa8e06SEd Maste fido_dev_largeblob_set_array(dev, p->get_wiredata.body,
2350afa8e06SEd Maste p->get_wiredata.len, pin);
2360afa8e06SEd Maste }
2370afa8e06SEd Maste
2380afa8e06SEd Maste fido_dev_close(dev);
2390afa8e06SEd Maste fido_dev_free(&dev);
2400afa8e06SEd Maste }
2410afa8e06SEd Maste
2420afa8e06SEd Maste void
test(const struct param * p)2430afa8e06SEd Maste test(const struct param *p)
2440afa8e06SEd Maste {
2450afa8e06SEd Maste prng_init((unsigned int)p->seed);
246f540a430SEd Maste fuzz_clock_reset();
2470afa8e06SEd Maste fido_init(FIDO_DEBUG);
2480afa8e06SEd Maste fido_set_log_handler(consume_str);
2490afa8e06SEd Maste
2500afa8e06SEd Maste get_blob(p, 0);
2510afa8e06SEd Maste get_blob(p, 1);
2520afa8e06SEd Maste set_blob(p, 0);
2530afa8e06SEd Maste set_blob(p, 1);
2540afa8e06SEd Maste set_blob(p, 2);
2550afa8e06SEd Maste }
2560afa8e06SEd Maste
2570afa8e06SEd Maste void
mutate(struct param * p,unsigned int seed,unsigned int flags)2580afa8e06SEd Maste mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
2590afa8e06SEd Maste {
2600afa8e06SEd Maste if (flags & MUTATE_SEED)
2610afa8e06SEd Maste p->seed = (int)seed;
2620afa8e06SEd Maste
2630afa8e06SEd Maste if (flags & MUTATE_PARAM) {
2640afa8e06SEd Maste mutate_blob(&p->key);
2650afa8e06SEd Maste mutate_string(p->pin);
2660afa8e06SEd Maste }
2670afa8e06SEd Maste
2680afa8e06SEd Maste if (flags & MUTATE_WIREDATA) {
2690afa8e06SEd Maste mutate_blob(&p->get_wiredata);
2700afa8e06SEd Maste mutate_blob(&p->set_wiredata);
2710afa8e06SEd Maste }
2720afa8e06SEd Maste }
273