1*0afa8e06SEd Maste /* 2*0afa8e06SEd Maste * Copyright (c) 2020 Yubico AB. All rights reserved. 3*0afa8e06SEd Maste * Use of this source code is governed by a BSD-style 4*0afa8e06SEd Maste * license that can be found in the LICENSE file. 5*0afa8e06SEd Maste */ 6*0afa8e06SEd Maste 7*0afa8e06SEd Maste #include <assert.h> 8*0afa8e06SEd Maste #include <stdint.h> 9*0afa8e06SEd Maste #include <stdio.h> 10*0afa8e06SEd Maste #include <stdlib.h> 11*0afa8e06SEd Maste #include <string.h> 12*0afa8e06SEd Maste 13*0afa8e06SEd Maste #include "mutator_aux.h" 14*0afa8e06SEd Maste #include "wiredata_fido2.h" 15*0afa8e06SEd Maste #include "dummy.h" 16*0afa8e06SEd Maste 17*0afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h" 18*0afa8e06SEd Maste 19*0afa8e06SEd Maste /* Parameter set defining a FIDO2 "large blob" operation. */ 20*0afa8e06SEd Maste struct param { 21*0afa8e06SEd Maste char pin[MAXSTR]; 22*0afa8e06SEd Maste int seed; 23*0afa8e06SEd Maste struct blob key; 24*0afa8e06SEd Maste struct blob get_wiredata; 25*0afa8e06SEd Maste struct blob set_wiredata; 26*0afa8e06SEd Maste }; 27*0afa8e06SEd Maste 28*0afa8e06SEd Maste /* 29*0afa8e06SEd Maste * Collection of HID reports from an authenticator issued with a FIDO2 30*0afa8e06SEd Maste * 'authenticatorLargeBlobs' 'get' command. 31*0afa8e06SEd Maste */ 32*0afa8e06SEd Maste static const uint8_t dummy_get_wiredata[] = { 33*0afa8e06SEd Maste WIREDATA_CTAP_INIT, 34*0afa8e06SEd Maste WIREDATA_CTAP_CBOR_INFO, 35*0afa8e06SEd Maste WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY 36*0afa8e06SEd Maste }; 37*0afa8e06SEd Maste 38*0afa8e06SEd Maste /* 39*0afa8e06SEd Maste * Collection of HID reports from an authenticator issued with a FIDO2 40*0afa8e06SEd Maste * 'authenticatorLargeBlobs' 'set' command. 41*0afa8e06SEd Maste */ 42*0afa8e06SEd Maste static const uint8_t dummy_set_wiredata[] = { 43*0afa8e06SEd Maste WIREDATA_CTAP_INIT, 44*0afa8e06SEd Maste WIREDATA_CTAP_CBOR_INFO, 45*0afa8e06SEd Maste WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY, 46*0afa8e06SEd Maste WIREDATA_CTAP_CBOR_AUTHKEY, 47*0afa8e06SEd Maste WIREDATA_CTAP_CBOR_PINTOKEN, 48*0afa8e06SEd Maste WIREDATA_CTAP_CBOR_STATUS 49*0afa8e06SEd Maste }; 50*0afa8e06SEd Maste 51*0afa8e06SEd Maste /* 52*0afa8e06SEd Maste * XXX this needs to match the encrypted blob embedded in 53*0afa8e06SEd Maste * WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY. 54*0afa8e06SEd Maste */ 55*0afa8e06SEd Maste static const uint8_t dummy_key[] = { 56*0afa8e06SEd Maste 0xa9, 0x1b, 0xc4, 0xdd, 0xfc, 0x9a, 0x93, 0x79, 57*0afa8e06SEd Maste 0x75, 0xba, 0xf7, 0x7f, 0x4d, 0x57, 0xfc, 0xa6, 58*0afa8e06SEd Maste 0xe1, 0xf8, 0x06, 0x43, 0x23, 0x99, 0x51, 0x32, 59*0afa8e06SEd Maste 0xce, 0x6e, 0x19, 0x84, 0x50, 0x13, 0x2d, 0x7b 60*0afa8e06SEd Maste }; 61*0afa8e06SEd Maste 62*0afa8e06SEd Maste struct param * 63*0afa8e06SEd Maste unpack(const uint8_t *ptr, size_t len) 64*0afa8e06SEd Maste { 65*0afa8e06SEd Maste cbor_item_t *item = NULL, **v; 66*0afa8e06SEd Maste struct cbor_load_result cbor; 67*0afa8e06SEd Maste struct param *p; 68*0afa8e06SEd Maste int ok = -1; 69*0afa8e06SEd Maste 70*0afa8e06SEd Maste if ((p = calloc(1, sizeof(*p))) == NULL || 71*0afa8e06SEd Maste (item = cbor_load(ptr, len, &cbor)) == NULL || 72*0afa8e06SEd Maste cbor.read != len || 73*0afa8e06SEd Maste cbor_isa_array(item) == false || 74*0afa8e06SEd Maste cbor_array_is_definite(item) == false || 75*0afa8e06SEd Maste cbor_array_size(item) != 5 || 76*0afa8e06SEd Maste (v = cbor_array_handle(item)) == NULL) 77*0afa8e06SEd Maste goto fail; 78*0afa8e06SEd Maste 79*0afa8e06SEd Maste if (unpack_int(v[0], &p->seed) < 0 || 80*0afa8e06SEd Maste unpack_string(v[1], p->pin) < 0 || 81*0afa8e06SEd Maste unpack_blob(v[2], &p->key) < 0 || 82*0afa8e06SEd Maste unpack_blob(v[3], &p->get_wiredata) < 0 || 83*0afa8e06SEd Maste unpack_blob(v[4], &p->set_wiredata) < 0) 84*0afa8e06SEd Maste goto fail; 85*0afa8e06SEd Maste 86*0afa8e06SEd Maste ok = 0; 87*0afa8e06SEd Maste fail: 88*0afa8e06SEd Maste if (ok < 0) { 89*0afa8e06SEd Maste free(p); 90*0afa8e06SEd Maste p = NULL; 91*0afa8e06SEd Maste } 92*0afa8e06SEd Maste 93*0afa8e06SEd Maste if (item) 94*0afa8e06SEd Maste cbor_decref(&item); 95*0afa8e06SEd Maste 96*0afa8e06SEd Maste return p; 97*0afa8e06SEd Maste } 98*0afa8e06SEd Maste 99*0afa8e06SEd Maste size_t 100*0afa8e06SEd Maste pack(uint8_t *ptr, size_t len, const struct param *p) 101*0afa8e06SEd Maste { 102*0afa8e06SEd Maste cbor_item_t *argv[5], *array = NULL; 103*0afa8e06SEd Maste size_t cbor_alloc_len, cbor_len = 0; 104*0afa8e06SEd Maste unsigned char *cbor = NULL; 105*0afa8e06SEd Maste 106*0afa8e06SEd Maste memset(argv, 0, sizeof(argv)); 107*0afa8e06SEd Maste 108*0afa8e06SEd Maste if ((array = cbor_new_definite_array(5)) == NULL || 109*0afa8e06SEd Maste (argv[0] = pack_int(p->seed)) == NULL || 110*0afa8e06SEd Maste (argv[1] = pack_string(p->pin)) == NULL || 111*0afa8e06SEd Maste (argv[2] = pack_blob(&p->key)) == NULL || 112*0afa8e06SEd Maste (argv[3] = pack_blob(&p->get_wiredata)) == NULL || 113*0afa8e06SEd Maste (argv[4] = pack_blob(&p->set_wiredata)) == NULL) 114*0afa8e06SEd Maste goto fail; 115*0afa8e06SEd Maste 116*0afa8e06SEd Maste for (size_t i = 0; i < 5; i++) 117*0afa8e06SEd Maste if (cbor_array_push(array, argv[i]) == false) 118*0afa8e06SEd Maste goto fail; 119*0afa8e06SEd Maste 120*0afa8e06SEd Maste if ((cbor_len = cbor_serialize_alloc(array, &cbor, 121*0afa8e06SEd Maste &cbor_alloc_len)) > len) { 122*0afa8e06SEd Maste cbor_len = 0; 123*0afa8e06SEd Maste goto fail; 124*0afa8e06SEd Maste } 125*0afa8e06SEd Maste 126*0afa8e06SEd Maste memcpy(ptr, cbor, cbor_len); 127*0afa8e06SEd Maste fail: 128*0afa8e06SEd Maste for (size_t i = 0; i < 5; i++) 129*0afa8e06SEd Maste if (argv[i]) 130*0afa8e06SEd Maste cbor_decref(&argv[i]); 131*0afa8e06SEd Maste 132*0afa8e06SEd Maste if (array) 133*0afa8e06SEd Maste cbor_decref(&array); 134*0afa8e06SEd Maste 135*0afa8e06SEd Maste free(cbor); 136*0afa8e06SEd Maste 137*0afa8e06SEd Maste return cbor_len; 138*0afa8e06SEd Maste } 139*0afa8e06SEd Maste 140*0afa8e06SEd Maste size_t 141*0afa8e06SEd Maste pack_dummy(uint8_t *ptr, size_t len) 142*0afa8e06SEd Maste { 143*0afa8e06SEd Maste struct param dummy; 144*0afa8e06SEd Maste uint8_t blob[4096]; 145*0afa8e06SEd Maste size_t blob_len; 146*0afa8e06SEd Maste 147*0afa8e06SEd Maste memset(&dummy, 0, sizeof(dummy)); 148*0afa8e06SEd Maste 149*0afa8e06SEd Maste strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); 150*0afa8e06SEd Maste 151*0afa8e06SEd Maste dummy.get_wiredata.len = sizeof(dummy_get_wiredata); 152*0afa8e06SEd Maste dummy.set_wiredata.len = sizeof(dummy_set_wiredata); 153*0afa8e06SEd Maste dummy.key.len = sizeof(dummy_key); 154*0afa8e06SEd Maste 155*0afa8e06SEd Maste memcpy(&dummy.get_wiredata.body, &dummy_get_wiredata, 156*0afa8e06SEd Maste dummy.get_wiredata.len); 157*0afa8e06SEd Maste memcpy(&dummy.set_wiredata.body, &dummy_set_wiredata, 158*0afa8e06SEd Maste dummy.set_wiredata.len); 159*0afa8e06SEd Maste memcpy(&dummy.key.body, &dummy_key, dummy.key.len); 160*0afa8e06SEd Maste 161*0afa8e06SEd Maste assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); 162*0afa8e06SEd Maste 163*0afa8e06SEd Maste if (blob_len > len) { 164*0afa8e06SEd Maste memcpy(ptr, blob, len); 165*0afa8e06SEd Maste return len; 166*0afa8e06SEd Maste } 167*0afa8e06SEd Maste 168*0afa8e06SEd Maste memcpy(ptr, blob, blob_len); 169*0afa8e06SEd Maste 170*0afa8e06SEd Maste return blob_len; 171*0afa8e06SEd Maste } 172*0afa8e06SEd Maste 173*0afa8e06SEd Maste static fido_dev_t * 174*0afa8e06SEd Maste prepare_dev(void) 175*0afa8e06SEd Maste { 176*0afa8e06SEd Maste fido_dev_t *dev; 177*0afa8e06SEd Maste 178*0afa8e06SEd Maste if ((dev = open_dev(0)) == NULL) 179*0afa8e06SEd Maste return NULL; 180*0afa8e06SEd Maste 181*0afa8e06SEd Maste return dev; 182*0afa8e06SEd Maste } 183*0afa8e06SEd Maste 184*0afa8e06SEd Maste static void 185*0afa8e06SEd Maste get_blob(const struct param *p, int array) 186*0afa8e06SEd Maste { 187*0afa8e06SEd Maste fido_dev_t *dev; 188*0afa8e06SEd Maste u_char *ptr = NULL; 189*0afa8e06SEd Maste size_t len = 0; 190*0afa8e06SEd Maste 191*0afa8e06SEd Maste set_wire_data(p->get_wiredata.body, p->get_wiredata.len); 192*0afa8e06SEd Maste 193*0afa8e06SEd Maste if ((dev = prepare_dev()) == NULL) 194*0afa8e06SEd Maste return; 195*0afa8e06SEd Maste 196*0afa8e06SEd Maste if (array) 197*0afa8e06SEd Maste fido_dev_largeblob_get_array(dev, &ptr, &len); 198*0afa8e06SEd Maste else 199*0afa8e06SEd Maste fido_dev_largeblob_get(dev, p->key.body, p->key.len, &ptr, &len); 200*0afa8e06SEd Maste consume(ptr, len); 201*0afa8e06SEd Maste free(ptr); 202*0afa8e06SEd Maste 203*0afa8e06SEd Maste fido_dev_close(dev); 204*0afa8e06SEd Maste fido_dev_free(&dev); 205*0afa8e06SEd Maste } 206*0afa8e06SEd Maste 207*0afa8e06SEd Maste 208*0afa8e06SEd Maste static void 209*0afa8e06SEd Maste set_blob(const struct param *p, int op) 210*0afa8e06SEd Maste { 211*0afa8e06SEd Maste fido_dev_t *dev; 212*0afa8e06SEd Maste const char *pin; 213*0afa8e06SEd Maste 214*0afa8e06SEd Maste set_wire_data(p->set_wiredata.body, p->set_wiredata.len); 215*0afa8e06SEd Maste 216*0afa8e06SEd Maste if ((dev = prepare_dev()) == NULL) 217*0afa8e06SEd Maste return; 218*0afa8e06SEd Maste pin = p->pin; 219*0afa8e06SEd Maste if (strlen(pin) == 0) 220*0afa8e06SEd Maste pin = NULL; 221*0afa8e06SEd Maste 222*0afa8e06SEd Maste switch (op) { 223*0afa8e06SEd Maste case 0: 224*0afa8e06SEd Maste fido_dev_largeblob_remove(dev, p->key.body, p->key.len, pin); 225*0afa8e06SEd Maste break; 226*0afa8e06SEd Maste case 1: 227*0afa8e06SEd Maste /* XXX reuse p->get_wiredata as the blob to be set */ 228*0afa8e06SEd Maste fido_dev_largeblob_set(dev, p->key.body, p->key.len, 229*0afa8e06SEd Maste p->get_wiredata.body, p->get_wiredata.len, pin); 230*0afa8e06SEd Maste break; 231*0afa8e06SEd Maste case 2: 232*0afa8e06SEd Maste /* XXX reuse p->get_wiredata as the body of the cbor array */ 233*0afa8e06SEd Maste fido_dev_largeblob_set_array(dev, p->get_wiredata.body, 234*0afa8e06SEd Maste p->get_wiredata.len, pin); 235*0afa8e06SEd Maste } 236*0afa8e06SEd Maste 237*0afa8e06SEd Maste fido_dev_close(dev); 238*0afa8e06SEd Maste fido_dev_free(&dev); 239*0afa8e06SEd Maste } 240*0afa8e06SEd Maste 241*0afa8e06SEd Maste void 242*0afa8e06SEd Maste test(const struct param *p) 243*0afa8e06SEd Maste { 244*0afa8e06SEd Maste prng_init((unsigned int)p->seed); 245*0afa8e06SEd Maste fido_init(FIDO_DEBUG); 246*0afa8e06SEd Maste fido_set_log_handler(consume_str); 247*0afa8e06SEd Maste 248*0afa8e06SEd Maste get_blob(p, 0); 249*0afa8e06SEd Maste get_blob(p, 1); 250*0afa8e06SEd Maste set_blob(p, 0); 251*0afa8e06SEd Maste set_blob(p, 1); 252*0afa8e06SEd Maste set_blob(p, 2); 253*0afa8e06SEd Maste } 254*0afa8e06SEd Maste 255*0afa8e06SEd Maste void 256*0afa8e06SEd Maste mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN 257*0afa8e06SEd Maste { 258*0afa8e06SEd Maste if (flags & MUTATE_SEED) 259*0afa8e06SEd Maste p->seed = (int)seed; 260*0afa8e06SEd Maste 261*0afa8e06SEd Maste if (flags & MUTATE_PARAM) { 262*0afa8e06SEd Maste mutate_blob(&p->key); 263*0afa8e06SEd Maste mutate_string(p->pin); 264*0afa8e06SEd Maste } 265*0afa8e06SEd Maste 266*0afa8e06SEd Maste if (flags & MUTATE_WIREDATA) { 267*0afa8e06SEd Maste mutate_blob(&p->get_wiredata); 268*0afa8e06SEd Maste mutate_blob(&p->set_wiredata); 269*0afa8e06SEd Maste } 270*0afa8e06SEd Maste } 271