1/* 2 * Copyright (c) 1997 - 2008 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#include "krb5_locl.h" 35 36#ifdef __APPLE__ 37KRB5_LIB_FUNCTION void KRB5_LIB_CALL 38krb5_generate_random_block(void *buf, size_t len) 39{ 40 CCRandomCopyBytes(kCCRandomDefault, buf, len); 41} 42#else 43 44#define ENTROPY_NEEDED 128 45 46static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; 47 48static int 49seed_something(void) 50{ 51 char buf[1024], seedfile[256]; 52 53 /* If there is a seed file, load it. But such a file cannot be trusted, 54 so use 0 for the entropy estimate */ 55 56 if (krb5_homedir_access(NULL) && RAND_file_name(seedfile, sizeof(seedfile))) { 57 int fd; 58 fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC); 59 if (fd >= 0) { 60 ssize_t ret; 61 rk_cloexec(fd); 62 ret = read(fd, buf, sizeof(buf)); 63 if (ret > 0) 64 RAND_add(buf, ret, 0.0); 65 close(fd); 66 } else 67 seedfile[0] = '\0'; 68 } else 69 seedfile[0] = '\0'; 70 71 /* Calling RAND_status() will try to use /dev/urandom if it exists so 72 we do not have to deal with it. */ 73 if (RAND_status() != 1) { 74#ifndef _WIN32 75 krb5_context context; 76 const char *p; 77 78 /* Try using egd */ 79 if (!krb5_init_context(&context)) { 80 p = krb5_config_get_string(context, NULL, "libdefaults", 81 "egd_socket", NULL); 82 if (p != NULL) 83 RAND_egd_bytes(p, ENTROPY_NEEDED); 84 krb5_free_context(context); 85 } 86#else 87 /* TODO: Once a Windows CryptoAPI RAND method is defined, we 88 can use that and failover to another method. */ 89#endif 90 } 91 92 if (RAND_status() == 1) { 93 /* Update the seed file */ 94 if (seedfile[0]) 95 RAND_write_file(seedfile); 96 97 return 0; 98 } else 99 return -1; 100} 101 102KRB5_LIB_FUNCTION void KRB5_LIB_CALL 103krb5_generate_random_block(void *buf, size_t len) 104{ 105 static int rng_initialized = 0; 106 107 HEIMDAL_MUTEX_lock(&crypto_mutex); 108 if (!rng_initialized) { 109 if (seed_something()) 110 krb5_abortx(NULL, "Fatal: could not seed the " 111 "random number generator"); 112 113 rng_initialized = 1; 114 } 115 HEIMDAL_MUTEX_unlock(&crypto_mutex); 116 if (RAND_bytes(buf, len) <= 0) 117 krb5_abortx(NULL, "Failed to generate random block"); 118} 119 120#endif /* __APPLE__ */ 121