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