1/* 2 * Copyright (c) 2011 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2011 - 2013 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <sys/types.h> 37#include <inttypes.h> 38#include <roken.h> 39#define HEIM_FUZZER_INTERNALS 1 40#include "fuzzer.h" 41 42#define SIZE(_array) (sizeof(_array) / sizeof((_array)[0])) 43 44/* 45 * 46 */ 47 48static void 49null_free(void *ctx) 50{ 51 if (ctx != NULL) 52 abort(); 53} 54 55/* 56 * 57 */ 58 59#define MIN_RANDOM_TRIES 30000 60 61static unsigned long 62random_tries(size_t length) 63{ 64 length = length * 12; 65 if (length < MIN_RANDOM_TRIES) 66 length = MIN_RANDOM_TRIES; 67 return (unsigned long)length; 68} 69 70static int 71random_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length) 72{ 73 *ctx = NULL; 74 75 if (iteration > MIN_RANDOM_TRIES && iteration > length * 12) 76 return 1; 77 78 data[rk_random() % length] = rk_random(); 79 80 return 0; 81} 82 83 84const struct heim_fuzz_type_data __heim_fuzz_random = { 85 "random", 86 random_tries, 87 random_fuzz, 88 null_free 89}; 90 91/* 92 * 93 */ 94 95static unsigned long 96bitflip_tries(size_t length) 97{ 98 return length << 3; 99} 100 101static int 102bitflip_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length) 103{ 104 *ctx = NULL; 105 if ((iteration >> 3) >= length) 106 return 1; 107 data[iteration >> 3] ^= (1 << (iteration & 7)); 108 109 return 0; 110} 111 112const struct heim_fuzz_type_data __heim_fuzz_bitflip = { 113 "bitflip", 114 bitflip_tries, 115 bitflip_fuzz, 116 null_free 117}; 118 119/* 120 * 121 */ 122 123static unsigned long 124byteflip_tries(size_t length) 125{ 126 return length; 127} 128 129static int 130byteflip_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length) 131{ 132 *ctx = NULL; 133 if (iteration >= length) 134 return 1; 135 data[iteration] ^= 0xff; 136 137 return 0; 138} 139 140const struct heim_fuzz_type_data __heim_fuzz_byteflip = { 141 "byteflip", 142 byteflip_tries, 143 byteflip_fuzz, 144 null_free 145}; 146 147/* 148 * 149 */ 150 151static unsigned long 152shortflip_tries(size_t length) 153{ 154 return length / 2; 155} 156 157static int 158shortflip_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length) 159{ 160 *ctx = NULL; 161 if (iteration + 1 >= length / 2) 162 return 1; 163 data[iteration + 0] ^= 0xff; 164 data[iteration + 1] ^= 0xff; 165 166 return 0; 167} 168 169const struct heim_fuzz_type_data __heim_fuzz_shortflip = { 170 "shortflip", 171 shortflip_tries, 172 shortflip_fuzz, 173 null_free 174}; 175 176/* 177 * 178 */ 179 180static unsigned long 181wordflip_tries(size_t length) 182{ 183 return length / 4; 184} 185 186static int 187wordflip_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length) 188{ 189 if (ctx) 190 *ctx = NULL; 191 if (iteration + 3 >= length / 4) 192 return 1; 193 data[iteration + 0] ^= 0xff; 194 data[iteration + 1] ^= 0xff; 195 data[iteration + 2] ^= 0xff; 196 data[iteration + 3] ^= 0xff; 197 198 return 0; 199} 200 201const struct heim_fuzz_type_data __heim_fuzz_wordflip = { 202 "wordflip", 203 wordflip_tries, 204 wordflip_fuzz, 205 null_free 206}; 207 208/* 209 * interesting values picked from AFL 210 */ 211 212static uint8_t interesting_u8[] = { 213 -128, 214 -1, 215 0, 216 1, 217 16, 218 32, 219 64, 220 100, 221 127 222}; 223 224static uint16_t interesting_u16[] = { 225 (uint16_t)-32768, 226 (uint16_t)-129, 227 128, 228 255, 229 256, 230 512, 231 1000, 232 1024, 233 4096, 234 32767 235}; 236 237static uint32_t interesting_u32[] = { 238 (uint32_t)-2147483648LL, 239 (uint32_t)-100000000, 240 (uint32_t)-32769, 241 32768, 242 65535, 243 65536, 244 100000000, 245 2147483647 246}; 247 248 249static unsigned long 250interesting_tries(size_t length) 251{ 252 return length; 253} 254 255static int 256interesting8_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length) 257{ 258 if (length < iteration / SIZE(interesting_u8)) 259 return 1; 260 261 memcpy(&data[iteration % SIZE(interesting_u8)], &interesting_u8[iteration / SIZE(interesting_u8)], 1); 262 return 0; 263} 264 265const struct heim_fuzz_type_data __heim_fuzz_interesting8 = { 266 "interesting uint8", 267 interesting_tries, 268 interesting8_fuzz, 269 null_free 270}; 271 272static int 273interesting16_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length) 274{ 275 if (length < 1 + (iteration / SIZE(interesting_u16))) 276 return 1; 277 278 memcpy(&data[iteration % SIZE(interesting_u16)], &interesting_u16[iteration / SIZE(interesting_u16)], 2); 279 return 0; 280} 281 282const struct heim_fuzz_type_data __heim_fuzz_interesting16 = { 283 "interesting uint16", 284 interesting_tries, 285 interesting16_fuzz, 286 null_free 287}; 288 289static int 290interesting32_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length) 291{ 292 if (length < 3 + (iteration / SIZE(interesting_u32))) 293 return 1; 294 295 memcpy(&data[iteration % SIZE(interesting_u32)], &interesting_u32[iteration / SIZE(interesting_u32)], 4); 296 return 0; 297} 298 299const struct heim_fuzz_type_data __heim_fuzz_interesting32 = { 300 "interesting uint32", 301 interesting_tries, 302 interesting32_fuzz, 303 null_free 304}; 305 306/* 307 * 308 */ 309 310const char * 311heim_fuzzer_name(heim_fuzz_type_t type) 312{ 313 return type->name; 314} 315 316unsigned long 317heim_fuzzer_tries(heim_fuzz_type_t type, size_t length) 318{ 319 return type->tries(length); 320} 321 322int 323heim_fuzzer(heim_fuzz_type_t type, 324 void **ctx, 325 unsigned long iteration, 326 uint8_t *data, 327 size_t length) 328{ 329 if (length == 0) 330 return 1; 331 return type->fuzz(ctx, iteration, data, length); 332} 333 334void 335heim_fuzzer_free(heim_fuzz_type_t type, 336 void *ctx) 337{ 338 if (ctx != NULL) 339 type->freectx(ctx); 340} 341