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

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

DEFINITIONS

This source file includes following definitions.
  1. init_method
  2. RAND_seed
  3. RAND_bytes
  4. RAND_cleanup
  5. RAND_add
  6. RAND_pseudo_bytes
  7. RAND_status
  8. RAND_set_rand_method
  9. RAND_get_rand_method
  10. RAND_set_rand_engine
  11. RAND_load_file
  12. RAND_write_file
  13. RAND_file_name

   1 /*
   2  * Copyright (c) 2006 - 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 <stdio.h>
  41 #include <stdlib.h>
  42 #include <rand.h>
  43 #include <randi.h>
  44 
  45 #include <roken.h>
  46 
  47 #ifndef O_BINARY
  48 #define O_BINARY 0
  49 #endif
  50 
  51 /**
  52  * @page page_rand RAND - random number
  53  *
  54  * See the library functions here: @ref hcrypto_rand
  55  */
  56 
  57 const static RAND_METHOD *selected_meth = NULL;
  58 static ENGINE *selected_engine = NULL;
  59 
  60 static void
  61 init_method(void)
     /* [<][>][^][v][top][bottom][index][help] */
  62 {
  63     if (selected_meth != NULL)
  64         return;
  65     selected_meth = &hc_rand_fortuna_method;
  66 }
  67 
  68 /**
  69  * Seed that random number generator. Secret material can securely be
  70  * feed into the function, they will never be returned.
  71  *
  72  * @param indata seed data
  73  * @param size length seed data
  74  *
  75  * @ingroup hcrypto_rand
  76  */
  77 
  78 void
  79 RAND_seed(const void *indata, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
  80 {
  81     init_method();
  82     (*selected_meth->seed)(indata, size);
  83 }
  84 
  85 /**
  86  * Get a random block from the random generator, can be used for key material.
  87  *
  88  * @param outdata random data
  89  * @param size length random data
  90  *
  91  * @return 1 on success, 0 on failure.
  92  *
  93  * @ingroup hcrypto_rand
  94  */
  95 int
  96 RAND_bytes(void *outdata, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
  97 {
  98     init_method();
  99     return (*selected_meth->bytes)(outdata, size);
 100 }
 101 
 102 /**
 103  * Reset and free memory used by the random generator.
 104  *
 105  * @ingroup hcrypto_rand
 106  */
 107 
 108 void
 109 RAND_cleanup(void)
     /* [<][>][^][v][top][bottom][index][help] */
 110 {
 111     const RAND_METHOD *meth = selected_meth;
 112     ENGINE *engine = selected_engine;
 113 
 114     selected_meth = NULL;
 115     selected_engine = NULL;
 116 
 117     if (meth)
 118         (*meth->cleanup)();
 119     if (engine)
 120         ENGINE_finish(engine);
 121 }
 122 
 123 /**
 124  * Seed that random number generator. Secret material can securely be
 125  * feed into the function, they will never be returned.
 126  *
 127  * @param indata the input data.
 128  * @param size size of in data.
 129  * @param entropi entropi in data.
 130  *
 131  *
 132  * @ingroup hcrypto_rand
 133  */
 134 
 135 void
 136 RAND_add(const void *indata, size_t size, double entropi)
     /* [<][>][^][v][top][bottom][index][help] */
 137 {
 138     init_method();
 139     (*selected_meth->add)(indata, size, entropi);
 140 }
 141 
 142 /**
 143  * Get a random block from the random generator, should NOT be used for key material.
 144  *
 145  * @param outdata random data
 146  * @param size length random data
 147  *
 148  * @return 1 on success, 0 on failure.
 149  *
 150  * @ingroup hcrypto_rand
 151  */
 152 
 153 int
 154 RAND_pseudo_bytes(void *outdata, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
 155 {
 156     init_method();
 157     return (*selected_meth->pseudorand)(outdata, size);
 158 }
 159 
 160 /**
 161  * Return status of the random generator
 162  *
 163  * @return 1 if the random generator can deliver random data.
 164  *
 165  * @ingroup hcrypto_rand
 166  */
 167 
 168 int
 169 RAND_status(void)
     /* [<][>][^][v][top][bottom][index][help] */
 170 {
 171     init_method();
 172     return (*selected_meth->status)();
 173 }
 174 
 175 /**
 176  * Set the default random method.
 177  *
 178  * @param meth set the new default method.
 179  *
 180  * @return 1 on success.
 181  *
 182  * @ingroup hcrypto_rand
 183  */
 184 
 185 int
 186 RAND_set_rand_method(const RAND_METHOD *meth)
     /* [<][>][^][v][top][bottom][index][help] */
 187 {
 188     const RAND_METHOD *old = selected_meth;
 189     selected_meth = meth;
 190     if (old)
 191         (*old->cleanup)();
 192     if (selected_engine) {
 193         ENGINE_finish(selected_engine);
 194         selected_engine = NULL;
 195     }
 196     return 1;
 197 }
 198 
 199 /**
 200  * Get the default random method.
 201  *
 202  * @ingroup hcrypto_rand
 203  */
 204 
 205 const RAND_METHOD *
 206 RAND_get_rand_method(void)
     /* [<][>][^][v][top][bottom][index][help] */
 207 {
 208     init_method();
 209     return selected_meth;
 210 }
 211 
 212 /**
 213  * Set the default random method from engine.
 214  *
 215  * @param engine use engine, if NULL is passed it, old method and engine is cleared.
 216  *
 217  * @return 1 on success, 0 on failure.
 218  *
 219  * @ingroup hcrypto_rand
 220  */
 221 
 222 int
 223 RAND_set_rand_engine(ENGINE *engine)
     /* [<][>][^][v][top][bottom][index][help] */
 224 {
 225     const RAND_METHOD *meth, *old = selected_meth;
 226 
 227     if (engine) {
 228         ENGINE_up_ref(engine);
 229         meth = ENGINE_get_RAND(engine);
 230         if (meth == NULL) {
 231             ENGINE_finish(engine);
 232             return 0;
 233         }
 234     } else {
 235         meth = NULL;
 236     }
 237 
 238     if (old)
 239         (*old->cleanup)();
 240 
 241     if (selected_engine)
 242         ENGINE_finish(selected_engine);
 243 
 244     selected_engine = engine;
 245     selected_meth = meth;
 246 
 247     return 1;
 248 }
 249 
 250 #define RAND_FILE_SIZE 1024
 251 
 252 /**
 253  * Load a a file and feed it into RAND_seed().
 254  *
 255  * @param filename name of file to read.
 256  * @param size minimum size to read.
 257  *
 258  * @ingroup hcrypto_rand
 259  */
 260 
 261 int
 262 RAND_load_file(const char *filename, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
 263 {
 264     unsigned char buf[128];
 265     size_t len;
 266     ssize_t slen;
 267     int fd;
 268 
 269     fd = open(filename, O_RDONLY | O_BINARY, 0600);
 270     if (fd < 0)
 271         return 0;
 272     rk_cloexec(fd);
 273     len = 0;
 274     while(len < size) {
 275         slen = read(fd, buf, sizeof(buf));
 276         if (slen <= 0)
 277             break;
 278         RAND_seed(buf, slen);
 279         len += slen;
 280     }
 281     close(fd);
 282 
 283     return len ? 1 : 0;
 284 }
 285 
 286 /**
 287  * Write of random numbers to a file to store for later initiation with RAND_load_file().
 288  *
 289  * @param filename name of file to write.
 290  *
 291  * @return 1 on success and non-one on failure.
 292  * @ingroup hcrypto_rand
 293  */
 294 
 295 int
 296 RAND_write_file(const char *filename)
     /* [<][>][^][v][top][bottom][index][help] */
 297 {
 298     unsigned char buf[128];
 299     size_t len;
 300     int res = 0, fd;
 301 
 302     fd = open(filename, O_WRONLY | O_CREAT | O_BINARY, 0600);
 303     if (fd < 0)
 304         return 0;
 305     rk_cloexec(fd);
 306 
 307     len = 0;
 308     while(len < RAND_FILE_SIZE) {
 309         res = RAND_bytes(buf, sizeof(buf));
 310         if (res != 1)
 311             break;
 312         if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
 313             res = 0;
 314             break;
 315         }
 316         len += sizeof(buf);
 317     }
 318 
 319     close(fd);
 320 
 321     return res;
 322 }
 323 
 324 /**
 325  * Return the default random state filename for a user to use for
 326  * RAND_load_file(), and RAND_write_file().
 327  *
 328  * @param filename buffer to hold file name.
 329  * @param size size of buffer filename.
 330  *
 331  * @return the buffer filename or NULL on failure.
 332  *
 333  * @ingroup hcrypto_rand
 334  */
 335 
 336 const char *
 337 RAND_file_name(char *filename, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
 338 {
 339     const char *e = NULL;
 340     int pathp = 0, ret;
 341 
 342     if (!issuid()) {
 343         e = getenv("RANDFILE");
 344         if (e == NULL) {
 345             e = getenv("HOME");
 346             if (e)
 347                 pathp = 1;
 348         }
 349     }
 350     /*
 351      * Here we really want to call getpwuid(getuid()) but this will
 352      * cause recursive lookups if the nss library uses
 353      * gssapi/krb5/hcrypto to authenticate to the ldap servers.
 354      */
 355 
 356     if (e == NULL)
 357         return NULL;
 358 
 359     if (pathp)
 360         ret = snprintf(filename, size, "%s/.rnd", e);
 361     else
 362         ret = snprintf(filename, size, "%s", e);
 363 
 364     if (ret <= 0 || ret >= size)
 365         return NULL;
 366 
 367     return filename;
 368 }

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