1/* srm */ 2/* Copyright (c) 2000 Matthew D. Gauthier 3 * Portions copyright (c) 2007 Apple Inc. All rights reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Except as contained in this notice, the name of the contributors shall 25 * not be used in advertising or otherwise to promote the sale, use or 26 * other dealings in this Software without prior written authorization. 27 */ 28 29#include <fcntl.h> 30#include <stdlib.h> 31#include <sys/stat.h> 32#include <sys/types.h> 33#include <sys/time.h> 34#include <unistd.h> 35 36#include "removefile.h" 37#include "removefile_priv.h" 38 39static void 40seed_random(removefile_state_t state) { 41#ifdef USE_ARC4RANDOM 42 arc4random_stir(); 43#else 44 unsigned int rseed; 45 struct timeval tv; 46 struct timezone tz; 47 48 if (state->urand_file != -1) { 49 read(state->urand_file, &rseed, sizeof(rseed)); 50 } else { 51 rseed = rand(); 52 } 53 (void)gettimeofday(&tv, &tz); 54 rseed ^= tv.tv_sec + tv.tv_usec + getpid(); 55 srand(rseed); 56#endif 57} 58 59void 60__removefile_init_random(const unsigned int seed, removefile_state_t state) { 61#ifdef USE_ARC4RANDOM 62 arc4random_addrandom((unsigned char *)&seed, sizeof(seed)); 63#else 64 struct stat statbuf; 65 66 if (stat("/dev/urandom", &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) { 67 state->urand_file = open("/dev/urandom", O_RDONLY); 68 } else { 69 srand(seed); 70 } 71 seed_random(state); 72#endif 73} 74 75char 76__removefile_random_char(removefile_state_t state) { 77#ifdef USE_ARC4RANDOM 78 random_bytes_read += 4; 79 return arc4random(); 80#else 81 char buf[4]; 82 83 if (state->urand_file != -1) { 84 read(state->urand_file, &buf, 1); 85 return buf[0]; 86 } 87 return rand(); 88#endif 89} 90 91void 92__removefile_randomize_buffer(unsigned char *buffer, size_t length, removefile_state_t state) { 93 size_t i; 94 95#ifdef USE_ARC4RANDOM 96 u_int32_t *p = (u_int32_t *)buffer; 97 u_int32_t mod4length = length - (length % 4); 98 99 for (i = 0; i < mod4length; i += 4) { 100 *p++ = arc4random(); 101 } 102 103 while (i < length) { 104 buffer[i++] = arc4random(); 105 } 106 state->random_bytes_read += (mod4length + ((length - mod4length) * 4)); 107 if (state->random_bytes_read > 512*1024*1024 /* RESEED_BYTES */) { 108 state->random_bytes_read = 0; 109 seed_random(state); 110 } 111#else 112 if (state->urand_file != -1) { 113 read(state->urand_file, buffer, length); 114 } else { 115 for (i = 0; i < length; i++) 116 buffer[i] = rand(); 117 } 118#endif 119} 120