1 /* 2 * Copyright (C) 2020-2022 Yubico AB - See COPYING 3 */ 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 #include <errno.h> 7 #include <stdint.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 13 #include "fuzz/fuzz.h" 14 #include "util.h" 15 16 static void cleanup(device_t *devs, unsigned int n_devs) { 17 for (unsigned int i = 0; i < n_devs; i++) { 18 free(devs[i].keyHandle); 19 free(devs[i].publicKey); 20 free(devs[i].coseType); 21 free(devs[i].attributes); 22 devs[i].keyHandle = NULL; 23 devs[i].publicKey = NULL; 24 devs[i].coseType = NULL; 25 devs[i].attributes = NULL; 26 } 27 } 28 29 #define DEV_MAX_SIZE 10 30 31 int LLVMFuzzerTestOneInput(const uint8_t *, size_t); 32 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 33 device_t devs[12] = {0}; 34 unsigned int n_devs = 12; 35 FILE *fp = NULL; 36 size_t fp_len = 0; 37 size_t offset = 0; 38 char username[256] = "user"; 39 size_t username_len = 0; 40 cfg_t cfg = {0}; 41 42 cfg.max_devs = DEV_MAX_SIZE; 43 cfg.auth_file = "/path/to/authfile"; /* XXX: any path works, file mocked */ 44 cfg.sshformat = 1; 45 46 /* first 6 byte decides which parser we should call, if 47 * we want to run with debug and also sets the initial seed */ 48 if (size < 6) { 49 return -1; 50 } 51 /* do not always run with debug, only 8/255 times */ 52 if (data[offset++] < 9) { 53 cfg.debug = 1; 54 } 55 56 /* predictable random for this seed */ 57 prng_init((uint32_t) data[offset] << 24 | (uint32_t) data[offset + 1] << 16 | 58 (uint32_t) data[offset + 2] << 8 | (uint32_t) data[offset + 3]); 59 offset += 4; 60 61 /* choose which format parser to run, even == native, odd == ssh */ 62 if (data[offset++] % 2) { 63 cfg.sshformat = 0; 64 /* native format, get a random username first */ 65 if (size < 7) { 66 return -1; 67 } 68 username_len = data[offset++]; 69 if (username_len > (size - offset)) { 70 username_len = (size - offset); 71 } 72 memset(username, 0, sizeof(username)); 73 memcpy(username, &data[offset], username_len); 74 offset += username_len; 75 } 76 77 fp_len = size - offset; 78 fp = tmpfile(); 79 if (fp == NULL || (fwrite(&data[offset], 1, fp_len, fp)) != fp_len) { 80 fprintf(stderr, "failed to create file for parser: %s\n", strerror(errno)); 81 if (fp != NULL) { 82 fclose(fp); 83 } 84 return -1; 85 } 86 (void) fseek(fp, 0L, SEEK_SET); 87 88 set_user(username); 89 set_authfile(fileno(fp)); 90 91 get_devices_from_authfile(&cfg, username, devs, &n_devs); 92 93 cleanup(devs, n_devs); 94 fclose(fp); 95 96 return 0; 97 } 98