1 /* $NetBSD: rand-unix.c,v 1.2 2017/01/28 21:31:47 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * 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 <config.h> 37 #include <krb5/roken.h> 38 39 #include <rand.h> 40 #include <heim_threads.h> 41 42 #include "randi.h" 43 44 /* 45 * Unix /dev/random 46 */ 47 48 int 49 _hc_unix_device_fd(int flags, const char **fn) 50 { 51 static const char *rnd_devices[] = { 52 "/dev/urandom", 53 "/dev/random", 54 "/dev/srandom", 55 "/dev/arandom", 56 NULL 57 }; 58 const char **p; 59 60 for(p = rnd_devices; *p; p++) { 61 int fd = open(*p, flags | O_NDELAY); 62 if(fd >= 0) { 63 if (fn) 64 *fn = *p; 65 rk_cloexec(fd); 66 return fd; 67 } 68 } 69 return -1; 70 } 71 72 static void 73 unix_seed(const void *p, int size) 74 { 75 const unsigned char *indata = p; 76 ssize_t count; 77 int fd; 78 79 if (size < 0) 80 return; 81 else if (size == 0) 82 return; 83 84 fd = _hc_unix_device_fd(O_RDONLY, NULL); 85 if (fd < 0) 86 return; 87 88 while (size > 0) { 89 count = write(fd, indata, size); 90 if (count < 0 && errno == EINTR) 91 continue; 92 else if (count <= 0) { 93 close(fd); 94 return; 95 } 96 indata += count; 97 size -= count; 98 } 99 close(fd); 100 } 101 102 103 static int 104 unix_bytes(unsigned char *outdata, int size) 105 { 106 ssize_t count; 107 int fd; 108 109 if (size < 0) 110 return 0; 111 else if (size == 0) 112 return 1; 113 114 fd = _hc_unix_device_fd(O_RDONLY, NULL); 115 if (fd < 0) 116 return 0; 117 118 while (size > 0) { 119 count = read(fd, outdata, size); 120 if (count < 0 && errno == EINTR) 121 continue; 122 else if (count <= 0) { 123 close(fd); 124 return 0; 125 } 126 outdata += count; 127 size -= count; 128 } 129 close(fd); 130 131 return 1; 132 } 133 134 static void 135 unix_cleanup(void) 136 { 137 } 138 139 static void 140 unix_add(const void *indata, int size, double entropi) 141 { 142 unix_seed(indata, size); 143 } 144 145 static int 146 unix_pseudorand(unsigned char *outdata, int size) 147 { 148 return unix_bytes(outdata, size); 149 } 150 151 static int 152 unix_status(void) 153 { 154 int fd; 155 156 fd = _hc_unix_device_fd(O_RDONLY, NULL); 157 if (fd < 0) 158 return 0; 159 close(fd); 160 161 return 1; 162 } 163 164 const RAND_METHOD hc_rand_unix_method = { 165 unix_seed, 166 unix_bytes, 167 unix_cleanup, 168 unix_add, 169 unix_pseudorand, 170 unix_status 171 }; 172 173 const RAND_METHOD * 174 RAND_unix_method(void) 175 { 176 return &hc_rand_unix_method; 177 } 178