s4:torture: Adapt KDC canon test to Heimdal upstream changes
[samba.git] / third_party / heimdal / lib / krb5 / crypto-rand.c
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 #undef HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE
37 #define HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE
38
39 #define ENTROPY_NEEDED 128
40
41 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
42
43 static int
44 seed_something(void)
45 {
46 #ifndef NO_RANDFILE
47     char buf[1024], seedfile[256];
48
49     /* If there is a seed file, load it. But such a file cannot be trusted,
50        so use 0 for the entropy estimate */
51     if (RAND_file_name(seedfile, sizeof(seedfile))) {
52         int fd;
53         fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
54         if (fd >= 0) {
55             ssize_t ret;
56             rk_cloexec(fd);
57             ret = read(fd, buf, sizeof(buf));
58             if (ret > 0)
59                 RAND_add(buf, ret, 0.0);
60             close(fd);
61         } else
62             seedfile[0] = '\0';
63     } else
64         seedfile[0] = '\0';
65 #endif
66
67     /* Calling RAND_status() will try to use /dev/urandom if it exists so
68        we do not have to deal with it. */
69     if (RAND_status() != 1) {
70         /* TODO: Once a Windows CryptoAPI RAND method is defined, we
71            can use that and failover to another method. */
72     }
73
74     if (RAND_status() == 1)     {
75 #ifndef NO_RANDFILE
76         /* Update the seed file */
77         if (seedfile[0])
78             RAND_write_file(seedfile);
79 #endif
80
81         return 0;
82     } else
83         return -1;
84 }
85
86 /**
87  * Fill buffer buf with len bytes of PRNG randomness that is ok to use
88  * for key generation, padding and public diclosing the randomness w/o
89  * disclosing the randomness source.
90  *
91  * This function can fail, and callers must check the return value.
92  *
93  * @param buf a buffer to fill with randomness
94  * @param len length of memory that buf points to.
95  *
96  * @return return 0 on success or HEIM_ERR_RANDOM_OFFLINE if the
97  * funcation failed to initialize the randomness source.
98  *
99  * @ingroup krb5_crypto
100  */
101
102 HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE
103 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
104 krb5_generate_random(void *buf, size_t len)
105 {
106     static int rng_initialized = 0;
107     int ret;
108
109     HEIMDAL_MUTEX_lock(&crypto_mutex);
110     if (!rng_initialized) {
111         if (seed_something()) {
112             HEIMDAL_MUTEX_unlock(&crypto_mutex);
113             return HEIM_ERR_RANDOM_OFFLINE;
114         }
115         rng_initialized = 1;
116     }
117     if (RAND_bytes(buf, len) <= 0)
118         ret = HEIM_ERR_RANDOM_OFFLINE;
119     else
120         ret = 0;
121     HEIMDAL_MUTEX_unlock(&crypto_mutex);
122
123     return ret;
124 }
125
126 /**
127  * Fill buffer buf with len bytes of PRNG randomness that is ok to use
128  * for key generation, padding and public diclosing the randomness w/o
129  * disclosing the randomness source.
130  *
131  * This function can NOT fail, instead it will abort() and program will crash.
132  *
133  * If this function is called after a successful krb5_init_context(),
134  * the chance of it failing is low due to that krb5_init_context()
135  * pulls out some random, and quite commonly the randomness sources
136  * will not fail once it have started to produce good output,
137  * /dev/urandom behavies that way.
138  *
139  * @param buf a buffer to fill with randomness
140  * @param len length of memory that buf points to.
141  *
142  * @ingroup krb5_crypto
143  */
144
145
146 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
147 krb5_generate_random_block(void *buf, size_t len)
148 {
149     int ret = krb5_generate_random(buf, len);
150     if (ret)
151         krb5_abortx(NULL, "Failed to generate random block");
152 }