13ff1169cSchristos /* 2*540ca271Schristos * Copyright (C) 2020-2022 Yubico AB - See COPYING 33ff1169cSchristos */ 43ff1169cSchristos #include <sys/types.h> 53ff1169cSchristos #include <sys/stat.h> 6*540ca271Schristos #include <errno.h> 7*540ca271Schristos #include <stdint.h> 8*540ca271Schristos #include <stdio.h> 9*540ca271Schristos #include <stdlib.h> 10*540ca271Schristos #include <string.h> 113ff1169cSchristos #include <unistd.h> 123ff1169cSchristos 133ff1169cSchristos #include "fuzz/fuzz.h" 14*540ca271Schristos #include "util.h" 153ff1169cSchristos 163ff1169cSchristos static void cleanup(device_t *devs, unsigned int n_devs) { 173ff1169cSchristos for (unsigned int i = 0; i < n_devs; i++) { 183ff1169cSchristos free(devs[i].keyHandle); 193ff1169cSchristos free(devs[i].publicKey); 203ff1169cSchristos free(devs[i].coseType); 213ff1169cSchristos free(devs[i].attributes); 223ff1169cSchristos devs[i].keyHandle = NULL; 233ff1169cSchristos devs[i].publicKey = NULL; 243ff1169cSchristos devs[i].coseType = NULL; 253ff1169cSchristos devs[i].attributes = NULL; 263ff1169cSchristos } 273ff1169cSchristos } 283ff1169cSchristos 293ff1169cSchristos #define DEV_MAX_SIZE 10 303ff1169cSchristos 313ff1169cSchristos int LLVMFuzzerTestOneInput(const uint8_t *, size_t); 323ff1169cSchristos int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 333ff1169cSchristos device_t devs[12] = {0}; 343ff1169cSchristos unsigned int n_devs = 12; 353ff1169cSchristos FILE *fp = NULL; 363ff1169cSchristos size_t fp_len = 0; 373ff1169cSchristos size_t offset = 0; 38*540ca271Schristos char username[256] = "user"; 393ff1169cSchristos size_t username_len = 0; 403ff1169cSchristos cfg_t cfg = {0}; 41*540ca271Schristos 423ff1169cSchristos cfg.max_devs = DEV_MAX_SIZE; 43*540ca271Schristos cfg.auth_file = "/path/to/authfile"; /* XXX: any path works, file mocked */ 44*540ca271Schristos cfg.sshformat = 1; 453ff1169cSchristos 463ff1169cSchristos /* first 6 byte decides which parser we should call, if 473ff1169cSchristos * we want to run with debug and also sets the initial seed */ 483ff1169cSchristos if (size < 6) { 493ff1169cSchristos return -1; 503ff1169cSchristos } 513ff1169cSchristos /* do not always run with debug, only 8/255 times */ 523ff1169cSchristos if (data[offset++] < 9) { 533ff1169cSchristos cfg.debug = 1; 543ff1169cSchristos } 553ff1169cSchristos 563ff1169cSchristos /* predictable random for this seed */ 573ff1169cSchristos prng_init((uint32_t) data[offset] << 24 | (uint32_t) data[offset + 1] << 16 | 583ff1169cSchristos (uint32_t) data[offset + 2] << 8 | (uint32_t) data[offset + 3]); 593ff1169cSchristos offset += 4; 603ff1169cSchristos 613ff1169cSchristos /* choose which format parser to run, even == native, odd == ssh */ 623ff1169cSchristos if (data[offset++] % 2) { 63*540ca271Schristos cfg.sshformat = 0; 643ff1169cSchristos /* native format, get a random username first */ 653ff1169cSchristos if (size < 7) { 663ff1169cSchristos return -1; 673ff1169cSchristos } 683ff1169cSchristos username_len = data[offset++]; 693ff1169cSchristos if (username_len > (size - offset)) { 703ff1169cSchristos username_len = (size - offset); 713ff1169cSchristos } 72*540ca271Schristos memset(username, 0, sizeof(username)); 733ff1169cSchristos memcpy(username, &data[offset], username_len); 743ff1169cSchristos offset += username_len; 753ff1169cSchristos } 763ff1169cSchristos 773ff1169cSchristos fp_len = size - offset; 783ff1169cSchristos fp = tmpfile(); 793ff1169cSchristos if (fp == NULL || (fwrite(&data[offset], 1, fp_len, fp)) != fp_len) { 803ff1169cSchristos fprintf(stderr, "failed to create file for parser: %s\n", strerror(errno)); 813ff1169cSchristos if (fp != NULL) { 823ff1169cSchristos fclose(fp); 833ff1169cSchristos } 843ff1169cSchristos return -1; 853ff1169cSchristos } 863ff1169cSchristos (void) fseek(fp, 0L, SEEK_SET); 873ff1169cSchristos 88*540ca271Schristos set_user(username); 89*540ca271Schristos set_authfile(fileno(fp)); 90*540ca271Schristos 91*540ca271Schristos get_devices_from_authfile(&cfg, username, devs, &n_devs); 923ff1169cSchristos 933ff1169cSchristos cleanup(devs, n_devs); 943ff1169cSchristos fclose(fp); 953ff1169cSchristos 963ff1169cSchristos return 0; 973ff1169cSchristos } 98