1226031Sstas/* 2226031Sstas * Copyright (c) 1997 - 2008 Kungliga Tekniska H��gskolan 3226031Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4226031Sstas * All rights reserved. 5226031Sstas * 6226031Sstas * Redistribution and use in source and binary forms, with or without 7226031Sstas * modification, are permitted provided that the following conditions 8226031Sstas * are met: 9226031Sstas * 10226031Sstas * 1. Redistributions of source code must retain the above copyright 11226031Sstas * notice, this list of conditions and the following disclaimer. 12226031Sstas * 13226031Sstas * 2. Redistributions in binary form must reproduce the above copyright 14226031Sstas * notice, this list of conditions and the following disclaimer in the 15226031Sstas * documentation and/or other materials provided with the distribution. 16226031Sstas * 17226031Sstas * 3. Neither the name of the Institute nor the names of its contributors 18226031Sstas * may be used to endorse or promote products derived from this software 19226031Sstas * without specific prior written permission. 20226031Sstas * 21226031Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24226031Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31226031Sstas * SUCH DAMAGE. 32226031Sstas */ 33226031Sstas 34226031Sstas#include "krb5_locl.h" 35226031Sstas 36226031Sstas#define ENTROPY_NEEDED 128 37226031Sstas 38226031Sstasstatic HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; 39226031Sstas 40226031Sstasstatic int 41226031Sstasseed_something(void) 42226031Sstas{ 43226031Sstas char buf[1024], seedfile[256]; 44226031Sstas 45226031Sstas /* If there is a seed file, load it. But such a file cannot be trusted, 46226031Sstas so use 0 for the entropy estimate */ 47226031Sstas if (RAND_file_name(seedfile, sizeof(seedfile))) { 48226031Sstas int fd; 49226031Sstas fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC); 50226031Sstas if (fd >= 0) { 51226031Sstas ssize_t ret; 52226031Sstas rk_cloexec(fd); 53226031Sstas ret = read(fd, buf, sizeof(buf)); 54226031Sstas if (ret > 0) 55226031Sstas RAND_add(buf, ret, 0.0); 56226031Sstas close(fd); 57226031Sstas } else 58226031Sstas seedfile[0] = '\0'; 59226031Sstas } else 60226031Sstas seedfile[0] = '\0'; 61226031Sstas 62226031Sstas /* Calling RAND_status() will try to use /dev/urandom if it exists so 63226031Sstas we do not have to deal with it. */ 64226031Sstas if (RAND_status() != 1) { 65226031Sstas#ifndef _WIN32 66226031Sstas krb5_context context; 67226031Sstas const char *p; 68226031Sstas 69226031Sstas /* Try using egd */ 70226031Sstas if (!krb5_init_context(&context)) { 71226031Sstas p = krb5_config_get_string(context, NULL, "libdefaults", 72226031Sstas "egd_socket", NULL); 73226031Sstas if (p != NULL) 74226031Sstas RAND_egd_bytes(p, ENTROPY_NEEDED); 75226031Sstas krb5_free_context(context); 76226031Sstas } 77226031Sstas#else 78226031Sstas /* TODO: Once a Windows CryptoAPI RAND method is defined, we 79226031Sstas can use that and failover to another method. */ 80226031Sstas#endif 81226031Sstas } 82226031Sstas 83226031Sstas if (RAND_status() == 1) { 84226031Sstas /* Update the seed file */ 85226031Sstas if (seedfile[0]) 86226031Sstas RAND_write_file(seedfile); 87226031Sstas 88226031Sstas return 0; 89226031Sstas } else 90226031Sstas return -1; 91226031Sstas} 92226031Sstas 93226031SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 94226031Sstaskrb5_generate_random_block(void *buf, size_t len) 95226031Sstas{ 96226031Sstas static int rng_initialized = 0; 97226031Sstas 98226031Sstas HEIMDAL_MUTEX_lock(&crypto_mutex); 99226031Sstas if (!rng_initialized) { 100226031Sstas if (seed_something()) 101226031Sstas krb5_abortx(NULL, "Fatal: could not seed the " 102226031Sstas "random number generator"); 103226031Sstas 104226031Sstas rng_initialized = 1; 105226031Sstas } 106226031Sstas HEIMDAL_MUTEX_unlock(&crypto_mutex); 107226031Sstas if (RAND_bytes(buf, len) <= 0) 108226031Sstas krb5_abortx(NULL, "Failed to generate random block"); 109226031Sstas} 110