1 /* 2 * Copyright (c) 2019 Yubico AB. All rights reserved. 3 * Use of this source code is governed by a BSD-style 4 * license that can be found in the LICENSE file. 5 */ 6 7 #include <assert.h> 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 13 #include "mutator_aux.h" 14 #include "wiredata_fido2.h" 15 #include "wiredata_u2f.h" 16 #include "dummy.h" 17 18 #include "../openbsd-compat/openbsd-compat.h" 19 20 /* Parameter set defining a FIDO2 get assertion operation. */ 21 struct param { 22 char pin[MAXSTR]; 23 char rp_id[MAXSTR]; 24 int ext; 25 int seed; 26 struct blob cdh; 27 struct blob cred; 28 struct blob es256; 29 struct blob rs256; 30 struct blob eddsa; 31 struct blob wire_data; 32 uint8_t cred_count; 33 uint8_t type; 34 uint8_t opt; 35 uint8_t up; 36 uint8_t uv; 37 }; 38 39 /* 40 * Collection of HID reports from an authenticator issued with a FIDO2 41 * get assertion using the example parameters above. 42 */ 43 static const uint8_t dummy_wire_data_fido[] = { 44 WIREDATA_CTAP_INIT, 45 WIREDATA_CTAP_CBOR_INFO, 46 WIREDATA_CTAP_CBOR_AUTHKEY, 47 WIREDATA_CTAP_CBOR_PINTOKEN, 48 WIREDATA_CTAP_CBOR_ASSERT, 49 }; 50 51 /* 52 * Collection of HID reports from an authenticator issued with a U2F 53 * authentication using the example parameters above. 54 */ 55 static const uint8_t dummy_wire_data_u2f[] = { 56 WIREDATA_CTAP_INIT, 57 WIREDATA_CTAP_U2F_6985, 58 WIREDATA_CTAP_U2F_6985, 59 WIREDATA_CTAP_U2F_6985, 60 WIREDATA_CTAP_U2F_6985, 61 WIREDATA_CTAP_U2F_AUTH, 62 }; 63 64 struct param * 65 unpack(const uint8_t *ptr, size_t len) 66 { 67 cbor_item_t *item = NULL, **v; 68 struct cbor_load_result cbor; 69 struct param *p; 70 int ok = -1; 71 72 if ((p = calloc(1, sizeof(*p))) == NULL || 73 (item = cbor_load(ptr, len, &cbor)) == NULL || 74 cbor.read != len || 75 cbor_isa_array(item) == false || 76 cbor_array_is_definite(item) == false || 77 cbor_array_size(item) != 15 || 78 (v = cbor_array_handle(item)) == NULL) 79 goto fail; 80 81 if (unpack_byte(v[0], &p->uv) < 0 || 82 unpack_byte(v[1], &p->up) < 0 || 83 unpack_byte(v[2], &p->opt) < 0 || 84 unpack_byte(v[3], &p->type) < 0 || 85 unpack_byte(v[4], &p->cred_count) < 0 || 86 unpack_int(v[5], &p->ext) < 0 || 87 unpack_int(v[6], &p->seed) < 0 || 88 unpack_string(v[7], p->rp_id) < 0 || 89 unpack_string(v[8], p->pin) < 0 || 90 unpack_blob(v[9], &p->wire_data) < 0 || 91 unpack_blob(v[10], &p->rs256) < 0 || 92 unpack_blob(v[11], &p->es256) < 0 || 93 unpack_blob(v[12], &p->eddsa) < 0 || 94 unpack_blob(v[13], &p->cred) < 0 || 95 unpack_blob(v[14], &p->cdh) < 0) 96 goto fail; 97 98 ok = 0; 99 fail: 100 if (ok < 0) { 101 free(p); 102 p = NULL; 103 } 104 105 if (item) 106 cbor_decref(&item); 107 108 return p; 109 } 110 111 size_t 112 pack(uint8_t *ptr, size_t len, const struct param *p) 113 { 114 cbor_item_t *argv[15], *array = NULL; 115 size_t cbor_alloc_len, cbor_len = 0; 116 unsigned char *cbor = NULL; 117 118 memset(argv, 0, sizeof(argv)); 119 120 if ((array = cbor_new_definite_array(15)) == NULL || 121 (argv[0] = pack_byte(p->uv)) == NULL || 122 (argv[1] = pack_byte(p->up)) == NULL || 123 (argv[2] = pack_byte(p->opt)) == NULL || 124 (argv[3] = pack_byte(p->type)) == NULL || 125 (argv[4] = pack_byte(p->cred_count)) == NULL || 126 (argv[5] = pack_int(p->ext)) == NULL || 127 (argv[6] = pack_int(p->seed)) == NULL || 128 (argv[7] = pack_string(p->rp_id)) == NULL || 129 (argv[8] = pack_string(p->pin)) == NULL || 130 (argv[9] = pack_blob(&p->wire_data)) == NULL || 131 (argv[10] = pack_blob(&p->rs256)) == NULL || 132 (argv[11] = pack_blob(&p->es256)) == NULL || 133 (argv[12] = pack_blob(&p->eddsa)) == NULL || 134 (argv[13] = pack_blob(&p->cred)) == NULL || 135 (argv[14] = pack_blob(&p->cdh)) == NULL) 136 goto fail; 137 138 for (size_t i = 0; i < 15; i++) 139 if (cbor_array_push(array, argv[i]) == false) 140 goto fail; 141 142 if ((cbor_len = cbor_serialize_alloc(array, &cbor, 143 &cbor_alloc_len)) > len) { 144 cbor_len = 0; 145 goto fail; 146 } 147 148 memcpy(ptr, cbor, cbor_len); 149 fail: 150 for (size_t i = 0; i < 15; i++) 151 if (argv[i]) 152 cbor_decref(&argv[i]); 153 154 if (array) 155 cbor_decref(&array); 156 157 free(cbor); 158 159 return cbor_len; 160 } 161 162 size_t 163 pack_dummy(uint8_t *ptr, size_t len) 164 { 165 struct param dummy; 166 uint8_t blob[4096]; 167 size_t blob_len; 168 169 memset(&dummy, 0, sizeof(dummy)); 170 171 dummy.type = 1; /* rsa */ 172 dummy.ext = FIDO_EXT_HMAC_SECRET; 173 174 strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); 175 strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id)); 176 177 dummy.cred.len = sizeof(dummy_cdh); /* XXX */ 178 dummy.cdh.len = sizeof(dummy_cdh); 179 dummy.es256.len = sizeof(dummy_es256); 180 dummy.rs256.len = sizeof(dummy_rs256); 181 dummy.eddsa.len = sizeof(dummy_eddsa); 182 dummy.wire_data.len = sizeof(dummy_wire_data_fido); 183 184 memcpy(&dummy.cred.body, &dummy_cdh, dummy.cred.len); /* XXX */ 185 memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len); 186 memcpy(&dummy.wire_data.body, &dummy_wire_data_fido, 187 dummy.wire_data.len); 188 memcpy(&dummy.es256.body, &dummy_es256, dummy.es256.len); 189 memcpy(&dummy.rs256.body, &dummy_rs256, dummy.rs256.len); 190 memcpy(&dummy.eddsa.body, &dummy_eddsa, dummy.eddsa.len); 191 192 assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); 193 194 if (blob_len > len) { 195 memcpy(ptr, blob, len); 196 return len; 197 } 198 199 memcpy(ptr, blob, blob_len); 200 201 return blob_len; 202 } 203 204 static void 205 get_assert(fido_assert_t *assert, uint8_t opt, const struct blob *cdh, 206 const char *rp_id, int ext, uint8_t up, uint8_t uv, const char *pin, 207 uint8_t cred_count, const struct blob *cred) 208 { 209 fido_dev_t *dev; 210 211 if ((dev = open_dev(opt & 2)) == NULL) 212 return; 213 if (opt & 1) 214 fido_dev_force_u2f(dev); 215 if (ext & FIDO_EXT_HMAC_SECRET) 216 fido_assert_set_extensions(assert, FIDO_EXT_HMAC_SECRET); 217 if (ext & FIDO_EXT_CRED_BLOB) 218 fido_assert_set_extensions(assert, FIDO_EXT_CRED_BLOB); 219 if (ext & FIDO_EXT_LARGEBLOB_KEY) 220 fido_assert_set_extensions(assert, FIDO_EXT_LARGEBLOB_KEY); 221 if (up & 1) 222 fido_assert_set_up(assert, FIDO_OPT_TRUE); 223 else if (opt & 1) 224 fido_assert_set_up(assert, FIDO_OPT_FALSE); 225 if (uv & 1) 226 fido_assert_set_uv(assert, FIDO_OPT_TRUE); 227 228 for (uint8_t i = 0; i < cred_count; i++) 229 fido_assert_allow_cred(assert, cred->body, cred->len); 230 231 fido_assert_set_clientdata_hash(assert, cdh->body, cdh->len); 232 fido_assert_set_rp(assert, rp_id); 233 /* XXX reuse cred as hmac salt */ 234 fido_assert_set_hmac_salt(assert, cred->body, cred->len); 235 236 /* repeat memory operations to trigger reallocation paths */ 237 fido_assert_set_clientdata_hash(assert, cdh->body, cdh->len); 238 fido_assert_set_rp(assert, rp_id); 239 fido_assert_set_hmac_salt(assert, cred->body, cred->len); 240 241 if (strlen(pin) == 0) 242 pin = NULL; 243 244 fido_dev_get_assert(dev, assert, (opt & 1) ? NULL : pin); 245 246 fido_dev_cancel(dev); 247 fido_dev_close(dev); 248 fido_dev_free(&dev); 249 } 250 251 static void 252 verify_assert(int type, const unsigned char *cdh_ptr, size_t cdh_len, 253 const char *rp_id, const unsigned char *authdata_ptr, size_t authdata_len, 254 const unsigned char *sig_ptr, size_t sig_len, uint8_t up, uint8_t uv, 255 int ext, void *pk) 256 { 257 fido_assert_t *assert = NULL; 258 int r; 259 260 if ((assert = fido_assert_new()) == NULL) 261 return; 262 263 fido_assert_set_clientdata_hash(assert, cdh_ptr, cdh_len); 264 fido_assert_set_rp(assert, rp_id); 265 fido_assert_set_count(assert, 1); 266 267 if (fido_assert_set_authdata(assert, 0, authdata_ptr, 268 authdata_len) != FIDO_OK) { 269 fido_assert_set_authdata_raw(assert, 0, authdata_ptr, 270 authdata_len); 271 } 272 273 if (up & 1) 274 fido_assert_set_up(assert, FIDO_OPT_TRUE); 275 if (uv & 1) 276 fido_assert_set_uv(assert, FIDO_OPT_TRUE); 277 278 fido_assert_set_extensions(assert, ext); 279 fido_assert_set_sig(assert, 0, sig_ptr, sig_len); 280 281 /* repeat memory operations to trigger reallocation paths */ 282 if (fido_assert_set_authdata(assert, 0, authdata_ptr, 283 authdata_len) != FIDO_OK) { 284 fido_assert_set_authdata_raw(assert, 0, authdata_ptr, 285 authdata_len); 286 } 287 fido_assert_set_sig(assert, 0, sig_ptr, sig_len); 288 289 r = fido_assert_verify(assert, 0, type, pk); 290 consume(&r, sizeof(r)); 291 292 fido_assert_free(&assert); 293 } 294 295 /* 296 * Do a dummy conversion to exercise es256_pk_from_EVP_PKEY(). 297 */ 298 static void 299 es256_convert(const es256_pk_t *k) 300 { 301 EVP_PKEY *pkey = NULL; 302 es256_pk_t *pk = NULL; 303 int r; 304 305 if ((pkey = es256_pk_to_EVP_PKEY(k)) == NULL || 306 (pk = es256_pk_new()) == NULL) 307 goto out; 308 309 r = es256_pk_from_EVP_PKEY(pk, pkey); 310 consume(&r, sizeof(r)); 311 out: 312 es256_pk_free(&pk); 313 EVP_PKEY_free(pkey); 314 } 315 316 /* 317 * Do a dummy conversion to exercise rs256_pk_from_EVP_PKEY(). 318 */ 319 static void 320 rs256_convert(const rs256_pk_t *k) 321 { 322 EVP_PKEY *pkey = NULL; 323 rs256_pk_t *pk = NULL; 324 int r; 325 326 if ((pkey = rs256_pk_to_EVP_PKEY(k)) == NULL || 327 (pk = rs256_pk_new()) == NULL) 328 goto out; 329 330 r = rs256_pk_from_EVP_PKEY(pk, pkey); 331 consume(&r, sizeof(r)); 332 out: 333 rs256_pk_free(&pk); 334 EVP_PKEY_free(pkey); 335 } 336 337 /* 338 * Do a dummy conversion to exercise eddsa_pk_from_EVP_PKEY(). 339 */ 340 static void 341 eddsa_convert(const eddsa_pk_t *k) 342 { 343 EVP_PKEY *pkey = NULL; 344 eddsa_pk_t *pk = NULL; 345 int r; 346 347 if ((pkey = eddsa_pk_to_EVP_PKEY(k)) == NULL || 348 (pk = eddsa_pk_new()) == NULL) 349 goto out; 350 351 r = eddsa_pk_from_EVP_PKEY(pk, pkey); 352 consume(&r, sizeof(r)); 353 out: 354 if (pk) 355 eddsa_pk_free(&pk); 356 if (pkey) 357 EVP_PKEY_free(pkey); 358 } 359 360 void 361 test(const struct param *p) 362 { 363 fido_assert_t *assert = NULL; 364 es256_pk_t *es256_pk = NULL; 365 rs256_pk_t *rs256_pk = NULL; 366 eddsa_pk_t *eddsa_pk = NULL; 367 uint8_t flags; 368 uint32_t sigcount; 369 int cose_alg = 0; 370 void *pk; 371 372 prng_init((unsigned int)p->seed); 373 fuzz_clock_reset(); 374 fido_init(FIDO_DEBUG); 375 fido_set_log_handler(consume_str); 376 377 switch (p->type & 3) { 378 case 0: 379 cose_alg = COSE_ES256; 380 381 if ((es256_pk = es256_pk_new()) == NULL) 382 return; 383 384 es256_pk_from_ptr(es256_pk, p->es256.body, p->es256.len); 385 pk = es256_pk; 386 387 es256_convert(pk); 388 389 break; 390 case 1: 391 cose_alg = COSE_RS256; 392 393 if ((rs256_pk = rs256_pk_new()) == NULL) 394 return; 395 396 rs256_pk_from_ptr(rs256_pk, p->rs256.body, p->rs256.len); 397 pk = rs256_pk; 398 399 rs256_convert(pk); 400 401 break; 402 default: 403 cose_alg = COSE_EDDSA; 404 405 if ((eddsa_pk = eddsa_pk_new()) == NULL) 406 return; 407 408 eddsa_pk_from_ptr(eddsa_pk, p->eddsa.body, p->eddsa.len); 409 pk = eddsa_pk; 410 411 eddsa_convert(pk); 412 413 break; 414 } 415 416 if ((assert = fido_assert_new()) == NULL) 417 goto out; 418 419 set_wire_data(p->wire_data.body, p->wire_data.len); 420 421 get_assert(assert, p->opt, &p->cdh, p->rp_id, p->ext, p->up, p->uv, 422 p->pin, p->cred_count, &p->cred); 423 424 /* XXX +1 on purpose */ 425 for (size_t i = 0; i <= fido_assert_count(assert); i++) { 426 verify_assert(cose_alg, 427 fido_assert_clientdata_hash_ptr(assert), 428 fido_assert_clientdata_hash_len(assert), 429 fido_assert_rp_id(assert), 430 fido_assert_authdata_ptr(assert, i), 431 fido_assert_authdata_len(assert, i), 432 fido_assert_sig_ptr(assert, i), 433 fido_assert_sig_len(assert, i), p->up, p->uv, p->ext, pk); 434 consume(fido_assert_id_ptr(assert, i), 435 fido_assert_id_len(assert, i)); 436 consume(fido_assert_user_id_ptr(assert, i), 437 fido_assert_user_id_len(assert, i)); 438 consume(fido_assert_hmac_secret_ptr(assert, i), 439 fido_assert_hmac_secret_len(assert, i)); 440 consume_str(fido_assert_user_icon(assert, i)); 441 consume_str(fido_assert_user_name(assert, i)); 442 consume_str(fido_assert_user_display_name(assert, i)); 443 consume(fido_assert_blob_ptr(assert, i), 444 fido_assert_blob_len(assert, i)); 445 consume(fido_assert_largeblob_key_ptr(assert, i), 446 fido_assert_largeblob_key_len(assert, i)); 447 flags = fido_assert_flags(assert, i); 448 consume(&flags, sizeof(flags)); 449 sigcount = fido_assert_sigcount(assert, i); 450 consume(&sigcount, sizeof(sigcount)); 451 } 452 453 out: 454 es256_pk_free(&es256_pk); 455 rs256_pk_free(&rs256_pk); 456 eddsa_pk_free(&eddsa_pk); 457 458 fido_assert_free(&assert); 459 } 460 461 void 462 mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN 463 { 464 if (flags & MUTATE_SEED) 465 p->seed = (int)seed; 466 467 if (flags & MUTATE_PARAM) { 468 mutate_byte(&p->uv); 469 mutate_byte(&p->up); 470 mutate_byte(&p->opt); 471 mutate_byte(&p->type); 472 mutate_byte(&p->cred_count); 473 mutate_int(&p->ext); 474 mutate_blob(&p->rs256); 475 mutate_blob(&p->es256); 476 mutate_blob(&p->eddsa); 477 mutate_blob(&p->cred); 478 mutate_blob(&p->cdh); 479 mutate_string(p->rp_id); 480 mutate_string(p->pin); 481 } 482 483 if (flags & MUTATE_WIREDATA) { 484 if (p->opt & 1) { 485 p->wire_data.len = sizeof(dummy_wire_data_u2f); 486 memcpy(&p->wire_data.body, &dummy_wire_data_u2f, 487 p->wire_data.len); 488 } else { 489 p->wire_data.len = sizeof(dummy_wire_data_fido); 490 memcpy(&p->wire_data.body, &dummy_wire_data_fido, 491 p->wire_data.len); 492 } 493 mutate_blob(&p->wire_data); 494 } 495 } 496