root/source4/heimdal/lib/hcrypto/rand-egd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. connect_egd
  2. get_entropy
  3. put_entropy
  4. egd_seed
  5. get_bytes
  6. egd_bytes
  7. egd_cleanup
  8. egd_add
  9. egd_pseudorand
  10. egd_status
  11. RAND_egd_method
  12. RAND_egd
  13. RAND_egd_bytes

   1 /*
   2  * Copyright (c) 2007 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #ifdef HAVE_CONFIG_H
  35 #include <config.h>
  36 #endif
  37 
  38 RCSID("$Id$");
  39 
  40 #include <sys/types.h>
  41 #ifdef HAVE_SYS_UN_H
  42 #include <sys/un.h>
  43 #endif
  44 
  45 #include <stdio.h>
  46 #include <stdlib.h>
  47 #ifdef HAVE_UNISTD_H
  48 #include <unistd.h>
  49 #endif
  50 #include <assert.h>
  51 
  52 #include <rand.h>
  53 #include <randi.h>
  54 
  55 #include <roken.h>
  56 
  57 static const char *egd_path = "/var/run/egd-pool";
  58 
  59 #define MAX_EGD_DATA 255
  60 
  61 static int
  62 connect_egd(const char *path)
     /* [<][>][^][v][top][bottom][index][help] */
  63 {
  64     struct sockaddr_un addr;
  65     int fd;
  66 
  67     memset(&addr, 0, sizeof(addr));
  68 
  69     if (strlen(path) > sizeof(addr.sun_path))
  70         return -1;
  71 
  72     addr.sun_family = AF_UNIX;
  73     strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
  74 
  75     fd = socket(AF_UNIX, SOCK_STREAM, 0);
  76     if (fd < 0)
  77         return -1;
  78 
  79     rk_cloexec(fd);
  80 
  81     if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
  82         close(fd);
  83         return -1;
  84     }
  85 
  86     return fd;
  87 }
  88 
  89 static int
  90 get_entropy(int fd, void *data, size_t len)
     /* [<][>][^][v][top][bottom][index][help] */
  91 {
  92     unsigned char msg[2];
  93 
  94     assert(len <= MAX_EGD_DATA);
  95 
  96     msg[0] = 0x02; /* read blocking data */
  97     msg[1] = len; /* wanted length */
  98 
  99     if (net_write(fd, msg, sizeof(msg)) != sizeof(msg))
 100         return 0;
 101 
 102     if (net_read(fd, data, len) != len)
 103         return 0;
 104 
 105     return 1;
 106 }
 107 
 108 static int
 109 put_entropy(int fd, const void *data, size_t len)
     /* [<][>][^][v][top][bottom][index][help] */
 110 {
 111     unsigned char msg[4];
 112 
 113     assert (len <= MAX_EGD_DATA);
 114 
 115     msg[0] = 0x03; /* write data */
 116     msg[1] = 0; /* dummy */
 117     msg[2] = 0; /* entropy */
 118     msg[3] = len; /* length */
 119 
 120     if (net_write(fd, msg, sizeof(msg)) != sizeof(msg))
 121         return 0;
 122     if (net_write(fd, data, len) != len)
 123         return 0;
 124 
 125     return 1;
 126 }
 127 
 128 /*
 129  *
 130  */
 131 
 132 static void
 133 egd_seed(const void *indata, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 134 {
 135     size_t len;
 136     int fd, ret = 1;
 137 
 138     fd = connect_egd(egd_path);
 139     if (fd < 0)
 140         return;
 141 
 142     while(size) {
 143         len = size;
 144         if (len > MAX_EGD_DATA)
 145             len = MAX_EGD_DATA;
 146         ret = put_entropy(fd, indata, len);
 147         if (ret != 1)
 148             break;
 149         indata = ((unsigned char *)indata) + len;
 150         size -= len;
 151     }   
 152     close(fd);
 153 }
 154 
 155 static int
 156 get_bytes(const char *path, unsigned char *outdata, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 157 {
 158     size_t len;
 159     int fd, ret = 1;
 160 
 161     if (path == NULL)
 162         path = egd_path;
 163 
 164     fd = connect_egd(path);
 165     if (fd < 0)
 166         return 0;
 167 
 168     while(size) {
 169         len = size;
 170         if (len > MAX_EGD_DATA)
 171             len = MAX_EGD_DATA;
 172         ret = get_entropy(fd, outdata, len);
 173         if (ret != 1)
 174             break;
 175         outdata += len;
 176         size -= len;
 177     }   
 178     close(fd);
 179 
 180     return ret;
 181 }
 182 
 183 static int
 184 egd_bytes(unsigned char *outdata, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 185 {
 186     return get_bytes(NULL, outdata, size);
 187 }
 188 
 189 static void
 190 egd_cleanup(void)
     /* [<][>][^][v][top][bottom][index][help] */
 191 {
 192 }
 193 
 194 static void
 195 egd_add(const void *indata, int size, double entropi)
     /* [<][>][^][v][top][bottom][index][help] */
 196 {
 197     egd_seed(indata, size);
 198 }
 199 
 200 static int
 201 egd_pseudorand(unsigned char *outdata, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 202 {
 203     return get_bytes(NULL, outdata, size);
 204 }
 205 
 206 static int
 207 egd_status(void)
     /* [<][>][^][v][top][bottom][index][help] */
 208 {
 209     int fd;
 210     fd = connect_egd(egd_path);
 211     if (fd < 0)
 212         return 0;
 213     close(fd);
 214     return 1;
 215 }
 216 
 217 const RAND_METHOD hc_rand_egd_method = {
 218     egd_seed,
 219     egd_bytes,
 220     egd_cleanup,
 221     egd_add,
 222     egd_pseudorand,
 223     egd_status
 224 };
 225 
 226 const RAND_METHOD *
 227 RAND_egd_method(void)
     /* [<][>][^][v][top][bottom][index][help] */
 228 {
 229     return &hc_rand_egd_method;
 230 }
 231 
 232 
 233 int
 234 RAND_egd(const char *filename)
     /* [<][>][^][v][top][bottom][index][help] */
 235 {
 236     return RAND_egd_bytes(filename, 128);
 237 }
 238 
 239 int
 240 RAND_egd_bytes(const char *filename, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 241 {
 242     void *data;
 243     int ret;
 244 
 245     if (size <= 0)
 246         return 0;
 247 
 248     data = malloc(size);
 249     if (data == NULL)
 250         return 0;
 251 
 252     ret = get_bytes(filename, data, size);
 253     if (ret != 1) {
 254         free(data);
 255         return ret;
 256     }
 257 
 258     RAND_seed(data, size);
 259 
 260     memset(data, 0, size);
 261     free(data);
 262 
 263     return 1;
 264 }

/* [<][>][^][v][top][bottom][index][help] */