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 259 if ((assert = fido_assert_new()) == NULL) 260 return; 261 262 fido_assert_set_clientdata_hash(assert, cdh_ptr, cdh_len); 263 fido_assert_set_rp(assert, rp_id); 264 fido_assert_set_count(assert, 1); 265 266 if (fido_assert_set_authdata(assert, 0, authdata_ptr, 267 authdata_len) != FIDO_OK) { 268 fido_assert_set_authdata_raw(assert, 0, authdata_ptr, 269 authdata_len); 270 } 271 272 if (up & 1) 273 fido_assert_set_up(assert, FIDO_OPT_TRUE); 274 if (uv & 1) 275 fido_assert_set_uv(assert, FIDO_OPT_TRUE); 276 277 fido_assert_set_extensions(assert, ext); 278 fido_assert_set_sig(assert, 0, sig_ptr, sig_len); 279 280 /* repeat memory operations to trigger reallocation paths */ 281 if (fido_assert_set_authdata(assert, 0, authdata_ptr, 282 authdata_len) != FIDO_OK) { 283 fido_assert_set_authdata_raw(assert, 0, authdata_ptr, 284 authdata_len); 285 } 286 fido_assert_set_sig(assert, 0, sig_ptr, sig_len); 287 288 assert(fido_assert_verify(assert, 0, type, pk) != FIDO_OK); 289 290 fido_assert_free(&assert); 291 } 292 293 /* 294 * Do a dummy conversion to exercise rs256_pk_from_RSA(). 295 */ 296 static void 297 rs256_convert(const rs256_pk_t *k) 298 { 299 EVP_PKEY *pkey = NULL; 300 rs256_pk_t *pk = NULL; 301 RSA *rsa = NULL; 302 volatile int r; 303 304 if ((pkey = rs256_pk_to_EVP_PKEY(k)) == NULL || 305 (pk = rs256_pk_new()) == NULL || 306 (rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) 307 goto out; 308 309 r = rs256_pk_from_RSA(pk, rsa); 310 out: 311 if (pk) 312 rs256_pk_free(&pk); 313 if (pkey) 314 EVP_PKEY_free(pkey); 315 } 316 317 /* 318 * Do a dummy conversion to exercise eddsa_pk_from_EVP_PKEY(). 319 */ 320 static void 321 eddsa_convert(const eddsa_pk_t *k) 322 { 323 EVP_PKEY *pkey = NULL; 324 eddsa_pk_t *pk = NULL; 325 volatile int r; 326 327 if ((pkey = eddsa_pk_to_EVP_PKEY(k)) == NULL || 328 (pk = eddsa_pk_new()) == NULL) 329 goto out; 330 331 r = eddsa_pk_from_EVP_PKEY(pk, pkey); 332 out: 333 if (pk) 334 eddsa_pk_free(&pk); 335 if (pkey) 336 EVP_PKEY_free(pkey); 337 } 338 339 void 340 test(const struct param *p) 341 { 342 fido_assert_t *assert = NULL; 343 es256_pk_t *es256_pk = NULL; 344 rs256_pk_t *rs256_pk = NULL; 345 eddsa_pk_t *eddsa_pk = NULL; 346 uint8_t flags; 347 uint32_t sigcount; 348 int cose_alg = 0; 349 void *pk; 350 351 prng_init((unsigned int)p->seed); 352 fido_init(FIDO_DEBUG); 353 fido_set_log_handler(consume_str); 354 355 switch (p->type & 3) { 356 case 0: 357 cose_alg = COSE_ES256; 358 359 if ((es256_pk = es256_pk_new()) == NULL) 360 return; 361 362 es256_pk_from_ptr(es256_pk, p->es256.body, p->es256.len); 363 pk = es256_pk; 364 365 break; 366 case 1: 367 cose_alg = COSE_RS256; 368 369 if ((rs256_pk = rs256_pk_new()) == NULL) 370 return; 371 372 rs256_pk_from_ptr(rs256_pk, p->rs256.body, p->rs256.len); 373 pk = rs256_pk; 374 375 rs256_convert(pk); 376 377 break; 378 default: 379 cose_alg = COSE_EDDSA; 380 381 if ((eddsa_pk = eddsa_pk_new()) == NULL) 382 return; 383 384 eddsa_pk_from_ptr(eddsa_pk, p->eddsa.body, p->eddsa.len); 385 pk = eddsa_pk; 386 387 eddsa_convert(pk); 388 389 break; 390 } 391 392 if ((assert = fido_assert_new()) == NULL) 393 goto out; 394 395 set_wire_data(p->wire_data.body, p->wire_data.len); 396 397 get_assert(assert, p->opt, &p->cdh, p->rp_id, p->ext, p->up, p->uv, 398 p->pin, p->cred_count, &p->cred); 399 400 /* XXX +1 on purpose */ 401 for (size_t i = 0; i <= fido_assert_count(assert); i++) { 402 verify_assert(cose_alg, 403 fido_assert_clientdata_hash_ptr(assert), 404 fido_assert_clientdata_hash_len(assert), 405 fido_assert_rp_id(assert), 406 fido_assert_authdata_ptr(assert, i), 407 fido_assert_authdata_len(assert, i), 408 fido_assert_sig_ptr(assert, i), 409 fido_assert_sig_len(assert, i), p->up, p->uv, p->ext, pk); 410 consume(fido_assert_id_ptr(assert, i), 411 fido_assert_id_len(assert, i)); 412 consume(fido_assert_user_id_ptr(assert, i), 413 fido_assert_user_id_len(assert, i)); 414 consume(fido_assert_hmac_secret_ptr(assert, i), 415 fido_assert_hmac_secret_len(assert, i)); 416 consume_str(fido_assert_user_icon(assert, i)); 417 consume_str(fido_assert_user_name(assert, i)); 418 consume_str(fido_assert_user_display_name(assert, i)); 419 consume(fido_assert_blob_ptr(assert, i), 420 fido_assert_blob_len(assert, i)); 421 consume(fido_assert_largeblob_key_ptr(assert, i), 422 fido_assert_largeblob_key_len(assert, i)); 423 flags = fido_assert_flags(assert, i); 424 consume(&flags, sizeof(flags)); 425 sigcount = fido_assert_sigcount(assert, i); 426 consume(&sigcount, sizeof(sigcount)); 427 } 428 429 out: 430 es256_pk_free(&es256_pk); 431 rs256_pk_free(&rs256_pk); 432 eddsa_pk_free(&eddsa_pk); 433 434 fido_assert_free(&assert); 435 } 436 437 void 438 mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN 439 { 440 if (flags & MUTATE_SEED) 441 p->seed = (int)seed; 442 443 if (flags & MUTATE_PARAM) { 444 mutate_byte(&p->uv); 445 mutate_byte(&p->up); 446 mutate_byte(&p->opt); 447 mutate_byte(&p->type); 448 mutate_byte(&p->cred_count); 449 mutate_int(&p->ext); 450 mutate_blob(&p->rs256); 451 mutate_blob(&p->es256); 452 mutate_blob(&p->eddsa); 453 mutate_blob(&p->cred); 454 mutate_blob(&p->cdh); 455 mutate_string(p->rp_id); 456 mutate_string(p->pin); 457 } 458 459 if (flags & MUTATE_WIREDATA) { 460 if (p->opt & 1) { 461 p->wire_data.len = sizeof(dummy_wire_data_u2f); 462 memcpy(&p->wire_data.body, &dummy_wire_data_u2f, 463 p->wire_data.len); 464 } else { 465 p->wire_data.len = sizeof(dummy_wire_data_fido); 466 memcpy(&p->wire_data.body, &dummy_wire_data_fido, 467 p->wire_data.len); 468 } 469 mutate_blob(&p->wire_data); 470 } 471 } 472