summaryrefslogtreecommitdiff
path: root/fuzz/fuzz_cred.c
diff options
context:
space:
mode:
Diffstat (limited to 'fuzz/fuzz_cred.c')
-rw-r--r--fuzz/fuzz_cred.c458
1 files changed, 256 insertions, 202 deletions
diff --git a/fuzz/fuzz_cred.c b/fuzz/fuzz_cred.c
index cc37903..87a877a 100644
--- a/fuzz/fuzz_cred.c
+++ b/fuzz/fuzz_cred.c
@@ -18,43 +18,25 @@
18 18
19#include "../openbsd-compat/openbsd-compat.h" 19#include "../openbsd-compat/openbsd-compat.h"
20 20
21#define TAG_U2F 0x01
22#define TAG_TYPE 0x02
23#define TAG_CDH 0x03
24#define TAG_RP_ID 0x04
25#define TAG_RP_NAME 0x05
26#define TAG_USER_ID 0x06
27#define TAG_USER_NAME 0x07
28#define TAG_USER_NICK 0x08
29#define TAG_USER_ICON 0x09
30#define TAG_EXT 0x0a
31#define TAG_SEED 0x0b
32#define TAG_RK 0x0c
33#define TAG_UV 0x0d
34#define TAG_PIN 0x0e
35#define TAG_WIRE_DATA 0x0f
36#define TAG_EXCL_COUNT 0x10
37#define TAG_EXCL_CRED 0x11
38
39/* Parameter set defining a FIDO2 make credential operation. */ 21/* Parameter set defining a FIDO2 make credential operation. */
40struct param { 22struct param {
41 char pin[MAXSTR]; 23 char pin[MAXSTR];
42 char rp_id[MAXSTR]; 24 char rp_id[MAXSTR];
43 char rp_name[MAXSTR]; 25 char rp_name[MAXSTR];
44 char user_icon[MAXSTR]; 26 char user_icon[MAXSTR];
45 char user_name[MAXSTR]; 27 char user_name[MAXSTR];
46 char user_nick[MAXSTR]; 28 char user_nick[MAXSTR];
47 int ext; 29 int ext;
48 int seed; 30 int seed;
49 struct blob cdh; 31 struct blob cdh;
50 struct blob excl_cred; 32 struct blob excl_cred;
51 struct blob user_id; 33 struct blob user_id;
52 struct blob wire_data; 34 struct blob wire_data;
53 uint8_t excl_count; 35 uint8_t excl_count;
54 uint8_t rk; 36 uint8_t rk;
55 uint8_t type; 37 uint8_t type;
56 uint8_t u2f; 38 uint8_t u2f;
57 uint8_t uv; 39 uint8_t uv;
58}; 40};
59 41
60/* 42/*
@@ -86,79 +68,157 @@ static const uint8_t dummy_wire_data_u2f[] = {
86 WIREDATA_CTAP_U2F_REGISTER, 68 WIREDATA_CTAP_U2F_REGISTER,
87}; 69};
88 70
89int LLVMFuzzerTestOneInput(const uint8_t *, size_t); 71struct param *
90size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int); 72unpack(const uint8_t *ptr, size_t len)
91
92static int
93unpack(const uint8_t *ptr, size_t len, struct param *p) NO_MSAN
94{ 73{
95 uint8_t **pp = (void *)&ptr; 74 cbor_item_t *item = NULL, **v;
96 75 struct cbor_load_result cbor;
97 if (unpack_byte(TAG_RK, pp, &len, &p->rk) < 0 || 76 struct param *p;
98 unpack_byte(TAG_TYPE, pp, &len, &p->type) < 0 || 77 int ok = -1;
99 unpack_byte(TAG_U2F, pp, &len, &p->u2f) < 0 || 78
100 unpack_byte(TAG_UV, pp, &len, &p->uv) < 0 || 79 if ((p = calloc(1, sizeof(*p))) == NULL ||
101 unpack_byte(TAG_EXCL_COUNT, pp, &len, &p->excl_count) < 0 || 80 (item = cbor_load(ptr, len, &cbor)) == NULL ||
102 unpack_string(TAG_PIN, pp, &len, p->pin) < 0 || 81 cbor.read != len ||
103 unpack_string(TAG_RP_ID, pp, &len, p->rp_id) < 0 || 82 cbor_isa_array(item) == false ||
104 unpack_string(TAG_RP_NAME, pp, &len, p->rp_name) < 0 || 83 cbor_array_is_definite(item) == false ||
105 unpack_string(TAG_USER_ICON, pp, &len, p->user_icon) < 0 || 84 cbor_array_size(item) != 17 ||
106 unpack_string(TAG_USER_NAME, pp, &len, p->user_name) < 0 || 85 (v = cbor_array_handle(item)) == NULL)
107 unpack_string(TAG_USER_NICK, pp, &len, p->user_nick) < 0 || 86 goto fail;
108 unpack_int(TAG_EXT, pp, &len, &p->ext) < 0 || 87
109 unpack_int(TAG_SEED, pp, &len, &p->seed) < 0 || 88 if (unpack_byte(v[0], &p->rk) < 0 ||
110 unpack_blob(TAG_CDH, pp, &len, &p->cdh) < 0 || 89 unpack_byte(v[1], &p->type) < 0 ||
111 unpack_blob(TAG_USER_ID, pp, &len, &p->user_id) < 0 || 90 unpack_byte(v[2], &p->u2f) < 0 ||
112 unpack_blob(TAG_WIRE_DATA, pp, &len, &p->wire_data) < 0 || 91 unpack_byte(v[3], &p->uv) < 0 ||
113 unpack_blob(TAG_EXCL_CRED, pp, &len, &p->excl_cred) < 0) 92 unpack_byte(v[4], &p->excl_count) < 0 ||
114 return (-1); 93 unpack_int(v[5], &p->ext) < 0 ||
115 94 unpack_int(v[6], &p->seed) < 0 ||
116 return (0); 95 unpack_string(v[7], p->pin) < 0 ||
96 unpack_string(v[8], p->rp_id) < 0 ||
97 unpack_string(v[9], p->rp_name) < 0 ||
98 unpack_string(v[10], p->user_icon) < 0 ||
99 unpack_string(v[11], p->user_name) < 0 ||
100 unpack_string(v[12], p->user_nick) < 0 ||
101 unpack_blob(v[13], &p->cdh) < 0 ||
102 unpack_blob(v[14], &p->user_id) < 0 ||
103 unpack_blob(v[15], &p->wire_data) < 0 ||
104 unpack_blob(v[16], &p->excl_cred) < 0)
105 goto fail;
106
107 ok = 0;
108fail:
109 if (ok < 0) {
110 free(p);
111 p = NULL;
112 }
113
114 if (item)
115 cbor_decref(&item);
116
117 return p;
117} 118}
118 119
119static size_t 120size_t
120pack(uint8_t *ptr, size_t len, const struct param *p) 121pack(uint8_t *ptr, size_t len, const struct param *p)
121{ 122{
122 const size_t max = len; 123 cbor_item_t *argv[17], *array = NULL;
123 124 size_t cbor_alloc_len, cbor_len = 0;
124 if (pack_byte(TAG_RK, &ptr, &len, p->rk) < 0 || 125 unsigned char *cbor = NULL;
125 pack_byte(TAG_TYPE, &ptr, &len, p->type) < 0 || 126
126 pack_byte(TAG_U2F, &ptr, &len, p->u2f) < 0 || 127 memset(argv, 0, sizeof(argv));
127 pack_byte(TAG_UV, &ptr, &len, p->uv) < 0 || 128
128 pack_byte(TAG_EXCL_COUNT, &ptr, &len, p->excl_count) < 0 || 129 if ((array = cbor_new_definite_array(17)) == NULL ||
129 pack_string(TAG_PIN, &ptr, &len, p->pin) < 0 || 130 (argv[0] = pack_byte(p->rk)) == NULL ||
130 pack_string(TAG_RP_ID, &ptr, &len, p->rp_id) < 0 || 131 (argv[1] = pack_byte(p->type)) == NULL ||
131 pack_string(TAG_RP_NAME, &ptr, &len, p->rp_name) < 0 || 132 (argv[2] = pack_byte(p->u2f)) == NULL ||
132 pack_string(TAG_USER_ICON, &ptr, &len, p->user_icon) < 0 || 133 (argv[3] = pack_byte(p->uv)) == NULL ||
133 pack_string(TAG_USER_NAME, &ptr, &len, p->user_name) < 0 || 134 (argv[4] = pack_byte(p->excl_count)) == NULL ||
134 pack_string(TAG_USER_NICK, &ptr, &len, p->user_nick) < 0 || 135 (argv[5] = pack_int(p->ext)) == NULL ||
135 pack_int(TAG_EXT, &ptr, &len, p->ext) < 0 || 136 (argv[6] = pack_int(p->seed)) == NULL ||
136 pack_int(TAG_SEED, &ptr, &len, p->seed) < 0 || 137 (argv[7] = pack_string(p->pin)) == NULL ||
137 pack_blob(TAG_CDH, &ptr, &len, &p->cdh) < 0 || 138 (argv[8] = pack_string(p->rp_id)) == NULL ||
138 pack_blob(TAG_USER_ID, &ptr, &len, &p->user_id) < 0 || 139 (argv[9] = pack_string(p->rp_name)) == NULL ||
139 pack_blob(TAG_WIRE_DATA, &ptr, &len, &p->wire_data) < 0 || 140 (argv[10] = pack_string(p->user_icon)) == NULL ||
140 pack_blob(TAG_EXCL_CRED, &ptr, &len, &p->excl_cred) < 0) 141 (argv[11] = pack_string(p->user_name)) == NULL ||
141 return (0); 142 (argv[12] = pack_string(p->user_nick)) == NULL ||
142 143 (argv[13] = pack_blob(&p->cdh)) == NULL ||
143 return (max - len); 144 (argv[14] = pack_blob(&p->user_id)) == NULL ||
145 (argv[15] = pack_blob(&p->wire_data)) == NULL ||
146 (argv[16] = pack_blob(&p->excl_cred)) == NULL)
147 goto fail;
148
149 for (size_t i = 0; i < 17; i++)
150 if (cbor_array_push(array, argv[i]) == false)
151 goto fail;
152
153 if ((cbor_len = cbor_serialize_alloc(array, &cbor,
154 &cbor_alloc_len)) > len) {
155 cbor_len = 0;
156 goto fail;
157 }
158
159 memcpy(ptr, cbor, cbor_len);
160fail:
161 for (size_t i = 0; i < 17; i++)
162 if (argv[i])
163 cbor_decref(&argv[i]);
164
165 if (array)
166 cbor_decref(&array);
167
168 free(cbor);
169
170 return cbor_len;
144} 171}
145 172
146static size_t 173size_t
147input_len(int max) 174pack_dummy(uint8_t *ptr, size_t len)
148{ 175{
149 return (5 * len_byte() + 6 * len_string(max) + 2 * len_int() + 176 struct param dummy;
150 4 * len_blob(max)); 177 uint8_t blob[4096];
178 size_t blob_len;
179
180 memset(&dummy, 0, sizeof(dummy));
181
182 dummy.type = 1;
183 dummy.ext = FIDO_EXT_HMAC_SECRET;
184
185 strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
186 strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
187 strlcpy(dummy.rp_name, dummy_rp_name, sizeof(dummy.rp_name));
188 strlcpy(dummy.user_icon, dummy_user_icon, sizeof(dummy.user_icon));
189 strlcpy(dummy.user_name, dummy_user_name, sizeof(dummy.user_name));
190 strlcpy(dummy.user_nick, dummy_user_nick, sizeof(dummy.user_nick));
191
192 dummy.cdh.len = sizeof(dummy_cdh);
193 dummy.user_id.len = sizeof(dummy_user_id);
194 dummy.wire_data.len = sizeof(dummy_wire_data_fido);
195
196 memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len);
197 memcpy(&dummy.user_id.body, &dummy_user_id, dummy.user_id.len);
198 memcpy(&dummy.wire_data.body, &dummy_wire_data_fido,
199 dummy.wire_data.len);
200
201 assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
202
203 if (blob_len > len) {
204 memcpy(ptr, blob, len);
205 return len;
206 }
207
208 memcpy(ptr, blob, blob_len);
209
210 return blob_len;
151} 211}
152 212
153static void 213static void
154make_cred(fido_cred_t *cred, uint8_t u2f, int type, const struct blob *cdh, 214make_cred(fido_cred_t *cred, uint8_t u2f, int type, const struct blob *cdh,
155 const char *rp_id, const char *rp_name, struct blob *user_id, 215 const char *rp_id, const char *rp_name, const struct blob *user_id,
156 const char *user_name, const char *user_nick, const char *user_icon, 216 const char *user_name, const char *user_nick, const char *user_icon,
157 int ext, uint8_t rk, uint8_t uv, const char *pin, uint8_t excl_count, 217 int ext, uint8_t rk, uint8_t uv, const char *pin, uint8_t excl_count,
158 struct blob *excl_cred) 218 const struct blob *excl_cred)
159{ 219{
160 fido_dev_t *dev; 220 fido_dev_t *dev;
161 fido_dev_io_t io; 221 fido_dev_io_t io;
162 222
163 memset(&io, 0, sizeof(io)); 223 memset(&io, 0, sizeof(io));
164 224
@@ -185,6 +245,7 @@ make_cred(fido_cred_t *cred, uint8_t u2f, int type, const struct blob *cdh,
185 fido_cred_set_user(cred, user_id->body, user_id->len, user_name, 245 fido_cred_set_user(cred, user_id->body, user_id->len, user_name,
186 user_nick, user_icon); 246 user_nick, user_icon);
187 fido_cred_set_extensions(cred, ext); 247 fido_cred_set_extensions(cred, ext);
248
188 if (rk & 1) 249 if (rk & 1)
189 fido_cred_set_rk(cred, FIDO_OPT_TRUE); 250 fido_cred_set_rk(cred, FIDO_OPT_TRUE);
190 if (uv & 1) 251 if (uv & 1)
@@ -192,6 +253,16 @@ make_cred(fido_cred_t *cred, uint8_t u2f, int type, const struct blob *cdh,
192 if (user_id->len) 253 if (user_id->len)
193 fido_cred_set_prot(cred, user_id->body[0] & 0x03); 254 fido_cred_set_prot(cred, user_id->body[0] & 0x03);
194 255
256 /* repeat memory operations to trigger reallocation paths */
257 fido_cred_set_type(cred, type);
258 fido_cred_set_clientdata_hash(cred, cdh->body, cdh->len);
259 fido_cred_set_rp(cred, rp_id, rp_name);
260 fido_cred_set_user(cred, user_id->body, user_id->len, user_name,
261 user_nick, user_icon);
262
263 if (strlen(pin) == 0)
264 pin = NULL;
265
195 fido_dev_make_cred(dev, cred, u2f & 1 ? NULL : pin); 266 fido_dev_make_cred(dev, cred, u2f & 1 ? NULL : pin);
196 267
197 fido_dev_cancel(dev); 268 fido_dev_cancel(dev);
@@ -206,8 +277,8 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
206 const unsigned char *x5c_ptr, size_t x5c_len, const unsigned char *sig_ptr, 277 const unsigned char *x5c_ptr, size_t x5c_len, const unsigned char *sig_ptr,
207 size_t sig_len, const char *fmt, int prot) 278 size_t sig_len, const char *fmt, int prot)
208{ 279{
209 fido_cred_t *cred; 280 fido_cred_t *cred;
210 uint8_t flags; 281 uint8_t flags;
211 282
212 if ((cred = fido_cred_new()) == NULL) 283 if ((cred = fido_cred_new()) == NULL)
213 return; 284 return;
@@ -229,11 +300,18 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
229 if (fmt) 300 if (fmt)
230 fido_cred_set_fmt(cred, fmt); 301 fido_cred_set_fmt(cred, fmt);
231 302
232 fido_cred_verify(cred); 303 /* repeat memory operations to trigger reallocation paths */
233 fido_cred_verify_self(cred); 304 if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK)
305 fido_cred_set_authdata_raw(cred, authdata_ptr, authdata_len);
306 fido_cred_set_x509(cred, x5c_ptr, x5c_len);
307 fido_cred_set_sig(cred, sig_ptr, sig_len);
308
309 assert(fido_cred_verify(cred) != FIDO_OK);
310 assert(fido_cred_verify_self(cred) != FIDO_OK);
234 311
235 consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred)); 312 consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred));
236 consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred)); 313 consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred));
314 consume(fido_cred_aaguid_ptr(cred), fido_cred_aaguid_len(cred));
237 consume(fido_cred_user_id_ptr(cred), fido_cred_user_id_len(cred)); 315 consume(fido_cred_user_id_ptr(cred), fido_cred_user_id_len(cred));
238 consume(fido_cred_user_name(cred), xstrlen(fido_cred_user_name(cred))); 316 consume(fido_cred_user_name(cred), xstrlen(fido_cred_user_name(cred)));
239 consume(fido_cred_display_name(cred), 317 consume(fido_cred_display_name(cred),
@@ -247,30 +325,16 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
247 fido_cred_free(&cred); 325 fido_cred_free(&cred);
248} 326}
249 327
250int 328static void
251LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) 329test_cred(const struct param *p)
252{ 330{
253 struct param p; 331 fido_cred_t *cred = NULL;
254 fido_cred_t *cred = NULL; 332 int cose_alg = 0;
255 int cose_alg = 0;
256
257 memset(&p, 0, sizeof(p));
258
259 if (size < input_len(GETLEN_MIN) || size > input_len(GETLEN_MAX) ||
260 unpack(data, size, &p) < 0)
261 return (0);
262
263 prng_init((unsigned int)p.seed);
264
265 fido_init(FIDO_DEBUG);
266 fido_set_log_handler(consume_str);
267 333
268 if ((cred = fido_cred_new()) == NULL) 334 if ((cred = fido_cred_new()) == NULL)
269 return (0); 335 return;
270
271 set_wire_data(p.wire_data.body, p.wire_data.len);
272 336
273 switch (p.type & 3) { 337 switch (p->type & 3) {
274 case 0: 338 case 0:
275 cose_alg = COSE_ES256; 339 cose_alg = COSE_ES256;
276 break; 340 break;
@@ -282,116 +346,106 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
282 break; 346 break;
283 } 347 }
284 348
285 make_cred(cred, p.u2f, cose_alg, &p.cdh, p.rp_id, p.rp_name, 349 set_wire_data(p->wire_data.body, p->wire_data.len);
286 &p.user_id, p.user_name, p.user_nick, p.user_icon, p.ext, p.rk, 350
287 p.uv, p.pin, p.excl_count, &p.excl_cred); 351 make_cred(cred, p->u2f, cose_alg, &p->cdh, p->rp_id, p->rp_name,
352 &p->user_id, p->user_name, p->user_nick, p->user_icon, p->ext,
353 p->rk, p->uv, p->pin, p->excl_count, &p->excl_cred);
288 354
289 verify_cred(cose_alg, 355 verify_cred(cose_alg,
290 fido_cred_clientdata_hash_ptr(cred), 356 fido_cred_clientdata_hash_ptr(cred),
291 fido_cred_clientdata_hash_len(cred), fido_cred_rp_id(cred), 357 fido_cred_clientdata_hash_len(cred), fido_cred_rp_id(cred),
292 fido_cred_rp_name(cred), fido_cred_authdata_ptr(cred), 358 fido_cred_rp_name(cred), fido_cred_authdata_ptr(cred),
293 fido_cred_authdata_len(cred), p.ext, p.rk, p.uv, 359 fido_cred_authdata_len(cred), p->ext, p->rk, p->uv,
294 fido_cred_x5c_ptr(cred), fido_cred_x5c_len(cred), 360 fido_cred_x5c_ptr(cred), fido_cred_x5c_len(cred),
295 fido_cred_sig_ptr(cred), fido_cred_sig_len(cred), 361 fido_cred_sig_ptr(cred), fido_cred_sig_len(cred),
296 fido_cred_fmt(cred), fido_cred_prot(cred)); 362 fido_cred_fmt(cred), fido_cred_prot(cred));
297 363
298 fido_cred_free(&cred); 364 fido_cred_free(&cred);
299
300 return (0);
301} 365}
302 366
303static size_t 367static void
304pack_dummy(uint8_t *ptr, size_t len) 368test_touch(const struct param *p)
305{ 369{
306 struct param dummy; 370 fido_dev_t *dev;
307 uint8_t blob[16384]; 371 fido_dev_io_t io;
308 size_t blob_len; 372 int r;
373 int touched;
309 374
310 memset(&dummy, 0, sizeof(dummy)); 375 memset(&io, 0, sizeof(io));
311 376
312 dummy.type = 1; 377 io.open = dev_open;
313 dummy.ext = FIDO_EXT_HMAC_SECRET; 378 io.close = dev_close;
379 io.read = dev_read;
380 io.write = dev_write;
314 381
315 strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); 382 set_wire_data(p->wire_data.body, p->wire_data.len);
316 strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
317 strlcpy(dummy.rp_name, dummy_rp_name, sizeof(dummy.rp_name));
318 strlcpy(dummy.user_icon, dummy_user_icon, sizeof(dummy.user_icon));
319 strlcpy(dummy.user_name, dummy_user_name, sizeof(dummy.user_name));
320 strlcpy(dummy.user_nick, dummy_user_nick, sizeof(dummy.user_nick));
321 383
322 dummy.cdh.len = sizeof(dummy_cdh); 384 if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev,
323 dummy.user_id.len = sizeof(dummy_user_id); 385 &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) {
324 dummy.wire_data.len = sizeof(dummy_wire_data_fido); 386 fido_dev_free(&dev);
387 return;
388 }
325 389
326 memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len); 390 if (p->u2f & 1)
327 memcpy(&dummy.user_id.body, &dummy_user_id, dummy.user_id.len); 391 fido_dev_force_u2f(dev);
328 memcpy(&dummy.wire_data.body, &dummy_wire_data_fido,
329 dummy.wire_data.len);
330 392
331 blob_len = pack(blob, sizeof(blob), &dummy); 393 r = fido_dev_get_touch_begin(dev);
332 assert(blob_len != 0); 394 consume_str(fido_strerr(r));
395 r = fido_dev_get_touch_status(dev, &touched, -1);
396 consume_str(fido_strerr(r));
397 consume(&touched, sizeof(touched));
333 398
334 if (blob_len > len) { 399 fido_dev_cancel(dev);
335 memcpy(ptr, blob, len); 400 fido_dev_close(dev);
336 return (len); 401 fido_dev_free(&dev);
337 } 402}
338 403
339 memcpy(ptr, blob, blob_len); 404void
405test(const struct param *p)
406{
407 prng_init((unsigned int)p->seed);
408 fido_init(FIDO_DEBUG);
409 fido_set_log_handler(consume_str);
340 410
341 return (blob_len); 411 test_cred(p);
412 test_touch(p);
342} 413}
343 414
344size_t 415void
345LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize, 416mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
346 unsigned int seed) NO_MSAN
347{ 417{
348 struct param p; 418 if (flags & MUTATE_SEED)
349 uint8_t blob[16384]; 419 p->seed = (int)seed;
350 size_t blob_len; 420
351 421 if (flags & MUTATE_PARAM) {
352 memset(&p, 0, sizeof(p)); 422 mutate_byte(&p->rk);
353 423 mutate_byte(&p->type);
354 if (unpack(data, size, &p) < 0) 424 mutate_byte(&p->u2f);
355 return (pack_dummy(data, maxsize)); 425 mutate_byte(&p->uv);
356 426 mutate_byte(&p->excl_count);
357 mutate_byte(&p.rk); 427 mutate_int(&p->ext);
358 mutate_byte(&p.type); 428 mutate_blob(&p->cdh);
359 mutate_byte(&p.u2f); 429 mutate_blob(&p->user_id);
360 mutate_byte(&p.uv); 430 mutate_blob(&p->excl_cred);
361 mutate_byte(&p.excl_count); 431 mutate_string(p->pin);
362 432 mutate_string(p->user_icon);
363 mutate_int(&p.ext); 433 mutate_string(p->user_name);
364 p.seed = (int)seed; 434 mutate_string(p->user_nick);
365 435 mutate_string(p->rp_id);
366 mutate_blob(&p.cdh); 436 mutate_string(p->rp_name);
367 mutate_blob(&p.user_id);
368
369 if (p.u2f & 1) {
370 p.wire_data.len = sizeof(dummy_wire_data_u2f);
371 memcpy(&p.wire_data.body, &dummy_wire_data_u2f,
372 p.wire_data.len);
373 } else {
374 p.wire_data.len = sizeof(dummy_wire_data_fido);
375 memcpy(&p.wire_data.body, &dummy_wire_data_fido,
376 p.wire_data.len);
377 } 437 }
378 438
379 mutate_blob(&p.wire_data); 439 if (flags & MUTATE_WIREDATA) {
380 mutate_blob(&p.excl_cred); 440 if (p->u2f & 1) {
381 441 p->wire_data.len = sizeof(dummy_wire_data_u2f);
382 mutate_string(p.pin); 442 memcpy(&p->wire_data.body, &dummy_wire_data_u2f,
383 mutate_string(p.user_icon); 443 p->wire_data.len);
384 mutate_string(p.user_name); 444 } else {
385 mutate_string(p.user_nick); 445 p->wire_data.len = sizeof(dummy_wire_data_fido);
386 mutate_string(p.rp_id); 446 memcpy(&p->wire_data.body, &dummy_wire_data_fido,
387 mutate_string(p.rp_name); 447 p->wire_data.len);
388 448 }
389 blob_len = pack(blob, sizeof(blob), &p); 449 mutate_blob(&p->wire_data);
390 450 }
391 if (blob_len == 0 || blob_len > maxsize)
392 return (0);
393
394 memcpy(data, blob, blob_len);
395
396 return (blob_len);
397} 451}