drbg_lib.c 25.3 KB
Newer Older
R
Rich Salz 已提交
1
/*
2
 * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
R
Rich Salz 已提交
3 4 5 6 7 8 9 10 11 12 13 14
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <string.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include "rand_lcl.h"
15 16
#include "internal/thread_once.h"
#include "internal/rand_int.h"
R
Rich Salz 已提交
17 18 19

/*
 * Support framework for NIST SP 800-90A DRBG, AES-CTR mode.
R
Rich Salz 已提交
20 21
 * The RAND_DRBG is OpenSSL's pointer to an instance of the DRBG.
 *
R
Rich Salz 已提交
22 23 24 25 26 27 28 29
 * The OpenSSL model is to have new and free functions, and that new
 * does all initialization.  That is not the NIST model, which has
 * instantiation and un-instantiate, and re-use within a new/free
 * lifecycle.  (No doubt this comes from the desire to support hardware
 * DRBG, where allocation of resources on something like an HSM is
 * a much bigger deal than just re-setting an allocated resource.)
 */

30 31 32 33 34 35 36 37 38 39 40 41
/*
 * THE THREE SHARED DRBGs
 *
 * There are three shared DRBGs (master, public and private), which are
 * accessed concurrently by all threads.
 *
 * THE MASTER DRBG
 *
 * Not used directly by the application, only for reseeding the two other
 * DRBGs. It reseeds itself by pulling either randomness from os entropy
 * sources or by consuming randomnes which was added by RAND_add()
 */
42
static RAND_DRBG *drbg_master;
43 44 45 46 47
/*
 * THE PUBLIC DRBG
 *
 * Used by default for generating random bytes using RAND_bytes().
 */
48
static RAND_DRBG *drbg_public;
49 50 51 52 53
/*
 * THE PRIVATE DRBG
 *
 * Used by default for generating private keys using RAND_priv_bytes()
 */
54
static RAND_DRBG *drbg_private;
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/*+
 * DRBG HIERARCHY
 *
 * In addition there are DRBGs, which are not shared, but used only by a
 * single thread at every time, for example the DRBGs which are owned by
 * an SSL context. All DRBGs are organized in a hierarchical fashion
 * with the <master> DRBG as root.
 *
 * This gives the following overall picture:
 *
 *                  <os entropy sources>
 *                         |
 *    RAND_add() ==>    <master>          \
 *                       /   \            | shared DRBGs (with locking)
 *                 <public>  <private>    /
 *                     |
 *                   <ssl>  owned by an SSL context
 *
 * AUTOMATIC RESEEDING
 *
75 76 77 78 79 80 81 82 83 84
 * Before satisfying a generate request, a DRBG reseeds itself automatically,
 * if one of the following two conditions holds:
 *
 * - the number of generate requests since the last reseeding exceeds a
 *   certain threshold, the so called |reseed_interval|. This behaviour
 *   can be disabled by setting the |reseed_interval| to 0.
 *
 * - the time elapsed since the last reseeding exceeds a certain time
 *   interval, the so called |reseed_time_interval|. This behaviour
 *   can be disabled by setting the |reseed_time_interval| to 0.
85 86 87
 *
 * MANUAL RESEEDING
 *
88 89
 * For the three shared DRBGs (and only for these) there is another way to
 * reseed them manually by calling RAND_seed() (or RAND_add() with a positive
90
 * |randomness| argument). This will immediately reseed the <master> DRBG.
91 92
 * The <public> and <private> DRBG will detect this on their next generate
 * call and reseed, pulling randomness from <master>.
93 94 95 96 97 98
 */


/* NIST SP 800-90A DRBG recommends the use of a personalization string. */
static const char ossl_pers_string[] = "OpenSSL NIST SP 800-90A DRBG";

99 100
static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT;

101 102
static RAND_DRBG *drbg_setup(const char *name, RAND_DRBG *parent);
static void drbg_cleanup(RAND_DRBG *drbg);
103

R
Rich Salz 已提交
104
/*
R
Rich Salz 已提交
105
 * Set/initialize |drbg| to be of type |nid|, with optional |flags|.
106 107
 *
 * Returns 1 on success, 0 on failure.
R
Rich Salz 已提交
108
 */
R
Rich Salz 已提交
109
int RAND_DRBG_set(RAND_DRBG *drbg, int nid, unsigned int flags)
R
Rich Salz 已提交
110 111 112
{
    int ret = 1;

R
Rich Salz 已提交
113 114 115
    drbg->state = DRBG_UNINITIALISED;
    drbg->flags = flags;
    drbg->nid = nid;
R
Rich Salz 已提交
116 117 118 119

    switch (nid) {
    default:
        RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_UNSUPPORTED_DRBG_TYPE);
120
        return 0;
R
Rich Salz 已提交
121 122 123 124 125 126
    case 0:
        /* Uninitialized; that's okay. */
        return 1;
    case NID_aes_128_ctr:
    case NID_aes_192_ctr:
    case NID_aes_256_ctr:
127
        ret = drbg_ctr_init(drbg);
R
Rich Salz 已提交
128 129 130
        break;
    }

131
    if (ret == 0)
R
Rich Salz 已提交
132 133 134 135 136 137
        RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_ERROR_INITIALISING_DRBG);
    return ret;
}

/*
 * Allocate memory and initialize a new DRBG.  The |parent|, if not
R
Rich Salz 已提交
138
 * NULL, will be used to auto-seed this RAND_DRBG as needed.
139 140
 *
 * Returns a pointer to the new DRBG instance on success, NULL on failure.
R
Rich Salz 已提交
141
 */
R
Rich Salz 已提交
142
RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent)
R
Rich Salz 已提交
143
{
R
Rich Salz 已提交
144
    RAND_DRBG *drbg = OPENSSL_zalloc(sizeof(*drbg));
R
Rich Salz 已提交
145

R
Rich Salz 已提交
146
    if (drbg == NULL) {
R
Rich Salz 已提交
147
        RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE);
R
Rich Salz 已提交
148
        goto err;
R
Rich Salz 已提交
149
    }
R
Rich Salz 已提交
150
    drbg->fork_count = rand_fork_count;
R
Rich Salz 已提交
151
    drbg->parent = parent;
152
    if (RAND_DRBG_set(drbg, type, flags) == 0)
R
Rich Salz 已提交
153 154
        goto err;

155 156 157 158
    if (!RAND_DRBG_set_callbacks(drbg, rand_drbg_get_entropy,
                                 rand_drbg_cleanup_entropy,
                                 NULL, NULL))
        goto err;
R
Rich Salz 已提交
159 160 161 162 163 164

    return drbg;

err:
    OPENSSL_free(drbg);
    return NULL;
R
Rich Salz 已提交
165 166 167
}

/*
R
Rich Salz 已提交
168
 * Uninstantiate |drbg| and free all memory.
R
Rich Salz 已提交
169
 */
R
Rich Salz 已提交
170
void RAND_DRBG_free(RAND_DRBG *drbg)
R
Rich Salz 已提交
171
{
172
    if (drbg == NULL)
R
Rich Salz 已提交
173 174
        return;

175 176
    if (drbg->meth != NULL)
        drbg->meth->uninstantiate(drbg);
R
Rich Salz 已提交
177 178
    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data);
    OPENSSL_clear_free(drbg, sizeof(*drbg));
R
Rich Salz 已提交
179 180 181
}

/*
R
Rich Salz 已提交
182
 * Instantiate |drbg|, after it has been initialized.  Use |pers| and
R
Rich Salz 已提交
183
 * |perslen| as prediction-resistance input.
B
Benjamin Kaduk 已提交
184 185
 *
 * Requires that drbg->lock is already locked for write, if non-null.
186 187
 *
 * Returns 1 on success, 0 on failure.
R
Rich Salz 已提交
188
 */
R
Rich Salz 已提交
189
int RAND_DRBG_instantiate(RAND_DRBG *drbg,
R
Rich Salz 已提交
190 191 192
                          const unsigned char *pers, size_t perslen)
{
    unsigned char *nonce = NULL, *entropy = NULL;
193
    size_t noncelen = 0, entropylen = 0;
R
Rich Salz 已提交
194

195
    if (perslen > drbg->max_perslen) {
R
Rich Salz 已提交
196 197
        RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
                RAND_R_PERSONALISATION_STRING_TOO_LONG);
R
Rich Salz 已提交
198 199
        goto end;
    }
200 201 202 203 204 205 206 207

    if (drbg->meth == NULL)
    {
        RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
                RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
        goto end;
    }

R
Rich Salz 已提交
208 209 210 211
    if (drbg->state != DRBG_UNINITIALISED) {
        RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
                drbg->state == DRBG_ERROR ? RAND_R_IN_ERROR_STATE
                                          : RAND_R_ALREADY_INSTANTIATED);
R
Rich Salz 已提交
212 213 214
        goto end;
    }

R
Rich Salz 已提交
215 216
    drbg->state = DRBG_ERROR;
    if (drbg->get_entropy != NULL)
217 218
        entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
                                   drbg->min_entropylen, drbg->max_entropylen);
219 220
    if (entropylen < drbg->min_entropylen
        || entropylen > drbg->max_entropylen) {
R
Rich Salz 已提交
221
        RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_ENTROPY);
R
Rich Salz 已提交
222 223 224
        goto end;
    }

225
    if (drbg->max_noncelen > 0 && drbg->get_nonce != NULL) {
R
Rich Salz 已提交
226
        noncelen = drbg->get_nonce(drbg, &nonce, drbg->strength / 2,
227 228
                                   drbg->min_noncelen, drbg->max_noncelen);
        if (noncelen < drbg->min_noncelen || noncelen > drbg->max_noncelen) {
229 230
            RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
                    RAND_R_ERROR_RETRIEVING_NONCE);
R
Rich Salz 已提交
231 232 233 234
            goto end;
        }
    }

235
    if (!drbg->meth->instantiate(drbg, entropy, entropylen,
R
Rich Salz 已提交
236
                         nonce, noncelen, pers, perslen)) {
R
Rich Salz 已提交
237
        RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_INSTANTIATING_DRBG);
R
Rich Salz 已提交
238 239 240
        goto end;
    }

R
Rich Salz 已提交
241
    drbg->state = DRBG_READY;
242
    drbg->generate_counter = 0;
243
    drbg->reseed_time = time(NULL);
244 245 246 247 248 249
    if (drbg->reseed_counter > 0) {
        if (drbg->parent == NULL)
            drbg->reseed_counter++;
        else
            drbg->reseed_counter = drbg->parent->reseed_counter;
    }
R
Rich Salz 已提交
250 251

end:
R
Rich Salz 已提交
252
    if (entropy != NULL && drbg->cleanup_entropy != NULL)
253
        drbg->cleanup_entropy(drbg, entropy, entropylen);
R
Rich Salz 已提交
254
    if (nonce != NULL && drbg->cleanup_nonce!= NULL )
255
        drbg->cleanup_nonce(drbg, nonce, noncelen);
256 257 258 259 260 261 262 263 264
    if (drbg->pool != NULL) {
        if (drbg->state == DRBG_READY) {
            RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
                    RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED);
            drbg->state = DRBG_ERROR;
        }
        RAND_POOL_free(drbg->pool);
        drbg->pool = NULL;
    }
R
Rich Salz 已提交
265
    if (drbg->state == DRBG_READY)
R
Rich Salz 已提交
266 267 268 269 270
        return 1;
    return 0;
}

/*
R
Rich Salz 已提交
271
 * Uninstantiate |drbg|. Must be instantiated before it can be used.
B
Benjamin Kaduk 已提交
272 273
 *
 * Requires that drbg->lock is already locked for write, if non-null.
274 275
 *
 * Returns 1 on success, 0 on failure.
R
Rich Salz 已提交
276
 */
R
Rich Salz 已提交
277
int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
R
Rich Salz 已提交
278
{
279 280 281 282 283 284 285
    if (drbg->meth == NULL)
    {
        RANDerr(RAND_F_RAND_DRBG_UNINSTANTIATE,
                RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
        return 0;
    }

286 287 288 289
    /* Clear the entire drbg->ctr struct, then reset some important
     * members of the drbg->ctr struct (e.g. keysize, df_ks) to their
     * initial values.
     */
290
    drbg->meth->uninstantiate(drbg);
291
    return RAND_DRBG_set(drbg, drbg->nid, drbg->flags);
R
Rich Salz 已提交
292 293 294
}

/*
295
 * Reseed |drbg|, mixing in the specified data
B
Benjamin Kaduk 已提交
296 297
 *
 * Requires that drbg->lock is already locked for write, if non-null.
298 299
 *
 * Returns 1 on success, 0 on failure.
R
Rich Salz 已提交
300
 */
R
Rich Salz 已提交
301
int RAND_DRBG_reseed(RAND_DRBG *drbg,
R
Rich Salz 已提交
302 303 304
                     const unsigned char *adin, size_t adinlen)
{
    unsigned char *entropy = NULL;
305
    size_t entropylen = 0;
R
Rich Salz 已提交
306 307 308 309 310 311 312 313

    if (drbg->state == DRBG_ERROR) {
        RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_IN_ERROR_STATE);
        return 0;
    }
    if (drbg->state == DRBG_UNINITIALISED) {
        RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_NOT_INSTANTIATED);
        return 0;
R
Rich Salz 已提交
314 315 316 317
    }

    if (adin == NULL)
        adinlen = 0;
318
    else if (adinlen > drbg->max_adinlen) {
R
Rich Salz 已提交
319 320
        RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
        return 0;
R
Rich Salz 已提交
321 322
    }

R
Rich Salz 已提交
323 324
    drbg->state = DRBG_ERROR;
    if (drbg->get_entropy != NULL)
325 326
        entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
                                   drbg->min_entropylen, drbg->max_entropylen);
327 328
    if (entropylen < drbg->min_entropylen
        || entropylen > drbg->max_entropylen) {
R
Rich Salz 已提交
329
        RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ERROR_RETRIEVING_ENTROPY);
R
Rich Salz 已提交
330 331 332
        goto end;
    }

333
    if (!drbg->meth->reseed(drbg, entropy, entropylen, adin, adinlen))
R
Rich Salz 已提交
334
        goto end;
335

R
Rich Salz 已提交
336
    drbg->state = DRBG_READY;
337
    drbg->generate_counter = 0;
338
    drbg->reseed_time = time(NULL);
339 340 341 342 343 344
    if (drbg->reseed_counter > 0) {
        if (drbg->parent == NULL)
            drbg->reseed_counter++;
        else
            drbg->reseed_counter = drbg->parent->reseed_counter;
    }
R
Rich Salz 已提交
345 346

end:
R
Rich Salz 已提交
347
    if (entropy != NULL && drbg->cleanup_entropy != NULL)
348
        drbg->cleanup_entropy(drbg, entropy, entropylen);
R
Rich Salz 已提交
349
    if (drbg->state == DRBG_READY)
R
Rich Salz 已提交
350 351 352 353
        return 1;
    return 0;
}

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
/*
 * Restart |drbg|, using the specified entropy or additional input
 *
 * Tries its best to get the drbg instantiated by all means,
 * regardless of its current state.
 *
 * Optionally, a |buffer| of |len| random bytes can be passed,
 * which is assumed to contain at least |entropy| bits of entropy.
 *
 * If |entropy| > 0, the buffer content is used as entropy input.
 *
 * If |entropy| == 0, the buffer content is used as additional input
 *
 * Returns 1 on success, 0 on failure.
 *
 * This function is used internally only.
 */
int rand_drbg_restart(RAND_DRBG *drbg,
                      const unsigned char *buffer, size_t len, size_t entropy)
{
    int reseeded = 0;
    const unsigned char *adin = NULL;
    size_t adinlen = 0;

    if (drbg->pool != NULL) {
        RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
        RAND_POOL_free(drbg->pool);
        drbg->pool = NULL;
    }

    if (buffer != NULL) {
        if (entropy > 0) {
            if (drbg->max_entropylen < len) {
                RANDerr(RAND_F_RAND_DRBG_RESTART,
                    RAND_R_ENTROPY_INPUT_TOO_LONG);
                return 0;
            }

            if (entropy > 8 * len) {
                RANDerr(RAND_F_RAND_DRBG_RESTART, RAND_R_ENTROPY_OUT_OF_RANGE);
                return 0;
            }

            /* will be picked up by the rand_drbg_get_entropy() callback */
            drbg->pool = RAND_POOL_new(entropy, len, len);
            if (drbg->pool == NULL)
                return 0;

            RAND_POOL_add(drbg->pool, buffer, len, entropy);
        } else {
            if (drbg->max_adinlen < len) {
                RANDerr(RAND_F_RAND_DRBG_RESTART,
                        RAND_R_ADDITIONAL_INPUT_TOO_LONG);
                return 0;
            }
            adin = buffer;
            adinlen = len;
        }
    }

    /* repair error state */
415
    if (drbg->state == DRBG_ERROR)
416 417 418 419
        RAND_DRBG_uninstantiate(drbg);

    /* repair uninitialized state */
    if (drbg->state == DRBG_UNINITIALISED) {
420 421 422 423
        /* reinstantiate drbg */
        RAND_DRBG_instantiate(drbg,
                              (const unsigned char *) ossl_pers_string,
                              sizeof(ossl_pers_string) - 1);
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
        /* already reseeded. prevent second reseeding below */
        reseeded = (drbg->state == DRBG_READY);
    }

    /* refresh current state if entropy or additional input has been provided */
    if (drbg->state == DRBG_READY) {
        if (adin != NULL) {
            /*
             * mix in additional input without reseeding
             *
             * Similar to RAND_DRBG_reseed(), but the provided additional
             * data |adin| is mixed into the current state without pulling
             * entropy from the trusted entropy source using get_entropy().
             * This is not a reseeding in the strict sense of NIST SP 800-90A.
             */
439
            drbg->meth->reseed(drbg, adin, adinlen, NULL, 0);
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
        } else if (reseeded == 0) {
            /* do a full reseeding if it has not been done yet above */
            RAND_DRBG_reseed(drbg, NULL, 0);
        }
    }

    /* check whether a given entropy pool was cleared properly during reseed */
    if (drbg->pool != NULL) {
        drbg->state = DRBG_ERROR;
        RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
        RAND_POOL_free(drbg->pool);
        drbg->pool = NULL;
        return 0;
    }

    return drbg->state == DRBG_READY;
}

R
Rich Salz 已提交
458 459 460 461
/*
 * Generate |outlen| bytes into the buffer at |out|.  Reseed if we need
 * to or if |prediction_resistance| is set.  Additional input can be
 * sent in |adin| and |adinlen|.
462
 *
B
Benjamin Kaduk 已提交
463 464
 * Requires that drbg->lock is already locked for write, if non-null.
 *
465 466
 * Returns 1 on success, 0 on failure.
 *
R
Rich Salz 已提交
467
 */
R
Rich Salz 已提交
468
int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
R
Rich Salz 已提交
469 470 471
                       int prediction_resistance,
                       const unsigned char *adin, size_t adinlen)
{
472 473
    int reseed_required = 0;

474 475 476 477 478 479 480 481 482 483 484 485
    if (drbg->state != DRBG_READY) {
        /* try to recover from previous errors */
        rand_drbg_restart(drbg, NULL, 0, 0);

        if (drbg->state == DRBG_ERROR) {
            RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_IN_ERROR_STATE);
            return 0;
        }
        if (drbg->state == DRBG_UNINITIALISED) {
            RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_NOT_INSTANTIATED);
            return 0;
        }
R
Rich Salz 已提交
486
    }
487

R
Rich Salz 已提交
488 489 490 491
    if (outlen > drbg->max_request) {
        RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG);
        return 0;
    }
492
    if (adinlen > drbg->max_adinlen) {
R
Rich Salz 已提交
493 494
        RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
        return 0;
R
Rich Salz 已提交
495 496
    }

R
Rich Salz 已提交
497 498
    if (drbg->fork_count != rand_fork_count) {
        drbg->fork_count = rand_fork_count;
499
        reseed_required = 1;
R
Rich Salz 已提交
500 501
    }

502 503 504 505
    if (drbg->reseed_interval > 0) {
        if (drbg->generate_counter >= drbg->reseed_interval)
            reseed_required = 1;
    }
506 507 508 509 510 511
    if (drbg->reseed_time_interval > 0) {
        time_t now = time(NULL);
        if (now < drbg->reseed_time
            || now - drbg->reseed_time >= drbg->reseed_time_interval)
            reseed_required = 1;
    }
512 513 514 515
    if (drbg->reseed_counter > 0 && drbg->parent != NULL) {
        if (drbg->reseed_counter != drbg->parent->reseed_counter)
            reseed_required = 1;
    }
R
Rich Salz 已提交
516

517
    if (reseed_required || prediction_resistance) {
R
Rich Salz 已提交
518 519 520
        if (!RAND_DRBG_reseed(drbg, adin, adinlen)) {
            RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_RESEED_ERROR);
            return 0;
R
Rich Salz 已提交
521 522 523 524 525
        }
        adin = NULL;
        adinlen = 0;
    }

526
    if (!drbg->meth->generate(drbg, out, outlen, adin, adinlen)) {
R
Rich Salz 已提交
527 528 529
        drbg->state = DRBG_ERROR;
        RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_GENERATE_ERROR);
        return 0;
R
Rich Salz 已提交
530
    }
R
Rich Salz 已提交
531

532
    drbg->generate_counter++;
533

R
Rich Salz 已提交
534 535 536 537
    return 1;
}

/*
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
 * Set the RAND_DRBG callbacks for obtaining entropy and nonce.
 *
 * In the following, the signature and the semantics of the
 * get_entropy() and cleanup_entropy() callbacks are explained.
 *
 * GET_ENTROPY
 *
 *     size_t get_entropy(RAND_DRBG *ctx,
 *                        unsigned char **pout,
 *                        int entropy,
 *                        size_t min_len, size_t max_len);
 *
 * This is a request to allocate and fill a buffer of size
 * |min_len| <= size <= |max_len| (in bytes) which contains
 * at least |entropy| bits of randomness. The buffer's address is
 * to be returned in |*pout| and the number of collected
 * randomness bytes (which may be less than the allocated size
 * of the buffer) as return value.
 *
 * If the callback fails to acquire at least |entropy| bits of
 * randomness, it shall return a buffer length of 0.
 *
 * CLEANUP_ENTROPY
 *
 *     void cleanup_entropy(RAND_DRBG *ctx,
 *                          unsigned char *out, size_t outlen);
 *
 * A request to clear and free the buffer allocated by get_entropy().
 * The values |out| and |outlen| are expected to be the random buffer's
 * address and length, as returned by the get_entropy() callback.
 *
 * GET_NONCE, CLEANUP_NONCE
 *
 * Signature and semantics of the get_nonce() and cleanup_nonce()
 * callbacks are analogous to get_entropy() and cleanup_entropy().
 * Currently, the nonce is used only for the known answer tests.
R
Rich Salz 已提交
574
 */
R
Rich Salz 已提交
575
int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
576 577 578 579
                            RAND_DRBG_get_entropy_fn get_entropy,
                            RAND_DRBG_cleanup_entropy_fn cleanup_entropy,
                            RAND_DRBG_get_nonce_fn get_nonce,
                            RAND_DRBG_cleanup_nonce_fn cleanup_nonce)
R
Rich Salz 已提交
580
{
R
Rich Salz 已提交
581
    if (drbg->state != DRBG_UNINITIALISED)
R
Rich Salz 已提交
582
        return 0;
583 584 585 586
    drbg->get_entropy = get_entropy;
    drbg->cleanup_entropy = cleanup_entropy;
    drbg->get_nonce = get_nonce;
    drbg->cleanup_nonce = cleanup_nonce;
R
Rich Salz 已提交
587 588 589 590
    return 1;
}

/*
R
Rich Salz 已提交
591
 * Set the reseed interval.
592 593 594
 *
 * The drbg will reseed automatically whenever the number of generate
 * requests exceeds the given reseed interval. If the reseed interval
595
 * is 0, then this feature is disabled.
596 597
 *
 * Returns 1 on success, 0 on failure.
R
Rich Salz 已提交
598
 */
599
int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval)
R
Rich Salz 已提交
600
{
601
    if (interval > MAX_RESEED_INTERVAL)
602
        return 0;
R
Rich Salz 已提交
603
    drbg->reseed_interval = interval;
604
    return 1;
R
Rich Salz 已提交
605 606
}

607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
/*
 * Set the reseed time interval.
 *
 * The drbg will reseed automatically whenever the time elapsed since
 * the last reseeding exceeds the given reseed time interval. For safety,
 * a reseeding will also occur if the clock has been reset to a smaller
 * value.
 *
 * Returns 1 on success, 0 on failure.
 */
int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval)
{
    if (interval > MAX_RESEED_TIME_INTERVAL)
        return 0;
    drbg->reseed_time_interval = interval;
    return 1;
}

R
Rich Salz 已提交
625 626 627
/*
 * Get and set the EXDATA
 */
R
Rich Salz 已提交
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg)
{
    return CRYPTO_set_ex_data(&drbg->ex_data, idx, arg);
}

void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx)
{
    return CRYPTO_get_ex_data(&drbg->ex_data, idx);
}


/*
 * The following functions provide a RAND_METHOD that works on the
 * global DRBG.  They lock.
 */

644
/*
645 646
 * Allocates a new global DRBG on the secure heap (if enabled) and
 * initializes it with default settings.
647 648 649
 * A global lock for the DRBG is created with the given name.
 *
 * Returns a pointer to the new DRBG instance on success, NULL on failure.
650
 */
651
static RAND_DRBG *drbg_setup(const char *name, RAND_DRBG *parent)
652
{
653
    RAND_DRBG *drbg;
654

655
    if (name == NULL) {
656
        RANDerr(RAND_F_DRBG_SETUP, ERR_R_INTERNAL_ERROR);
657
        return NULL;
658
    }
659

660 661 662 663
    drbg = OPENSSL_secure_zalloc(sizeof(RAND_DRBG));
    if (drbg == NULL)
        return NULL;

664 665 666
    drbg->lock = CRYPTO_THREAD_glock_new(name);
    if (drbg->lock == NULL) {
        RANDerr(RAND_F_DRBG_SETUP, RAND_R_FAILED_TO_CREATE_LOCK);
667
        goto err;
668 669
    }

670 671 672 673 674 675
    if (RAND_DRBG_set(drbg,
                      RAND_DRBG_NID, RAND_DRBG_FLAG_CTR_USE_DF) != 1)
        goto err;
    if (RAND_DRBG_set_callbacks(drbg, rand_drbg_get_entropy,
                                rand_drbg_cleanup_entropy, NULL, NULL) != 1)
        goto err;
676

677
    if (parent == NULL) {
678
        drbg->reseed_interval = MASTER_RESEED_INTERVAL;
679 680
        drbg->reseed_time_interval = MASTER_RESEED_TIME_INTERVAL;
    } else {
681 682
        drbg->parent = parent;
        drbg->reseed_interval = SLAVE_RESEED_INTERVAL;
683
        drbg->reseed_time_interval = SLAVE_RESEED_TIME_INTERVAL;
684 685 686 687 688
    }

    /* enable seed propagation */
    drbg->reseed_counter = 1;

689 690 691 692 693 694 695 696 697
    /*
     * Ignore instantiation error so support just-in-time instantiation.
     *
     * The state of the drbg will be checked in RAND_DRBG_generate() and
     * an automatic recovery is attempted.
     */
    RAND_DRBG_instantiate(drbg,
                          (const unsigned char *) ossl_pers_string,
                          sizeof(ossl_pers_string) - 1);
698 699 700 701 702
    return drbg;

err:
    drbg_cleanup(drbg);
    return NULL;
703 704 705 706 707 708
}

/*
 * Initialize the global DRBGs on first use.
 * Returns 1 on success, 0 on failure.
 */
709
DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init)
710
{
711 712 713 714 715 716 717
    /*
     * ensure that libcrypto is initialized, otherwise the
     * DRBG locks are not cleaned up properly
     */
    if (!OPENSSL_init_crypto(0, NULL))
        return 0;

718 719 720
    drbg_master = drbg_setup("drbg_master", NULL);
    drbg_public = drbg_setup("drbg_public", drbg_master);
    drbg_private = drbg_setup("drbg_private", drbg_master);
721

722 723
    if (drbg_master == NULL || drbg_public == NULL || drbg_private == NULL)
        return 0;
724

725
    return 1;
726 727
}

728 729
/* Cleans up the given global DRBG  */
static void drbg_cleanup(RAND_DRBG *drbg)
730
{
731 732 733 734 735
    if (drbg != NULL) {
        RAND_DRBG_uninstantiate(drbg);
        CRYPTO_THREAD_lock_free(drbg->lock);
        OPENSSL_secure_clear_free(drbg, sizeof(RAND_DRBG));
    }
736 737 738
}

/* Clean up the global DRBGs before exit */
739
void rand_drbg_cleanup_int(void)
740
{
741 742 743 744 745
    drbg_cleanup(drbg_private);
    drbg_cleanup(drbg_public);
    drbg_cleanup(drbg_master);

    drbg_private = drbg_public = drbg_master = NULL;
746 747
}

748
/* Implements the default OpenSSL RAND_bytes() method */
R
Rich Salz 已提交
749 750 751 752
static int drbg_bytes(unsigned char *out, int count)
{
    int ret = 0;
    size_t chunk;
753
    RAND_DRBG *drbg = RAND_DRBG_get0_public();
R
Rich Salz 已提交
754

755 756 757 758 759
    if (drbg == NULL)
        return 0;

    CRYPTO_THREAD_write_lock(drbg->lock);
    if (drbg->state == DRBG_UNINITIALISED)
R
Rich Salz 已提交
760 761 762 763
        goto err;

    for ( ; count > 0; count -= chunk, out += chunk) {
        chunk = count;
764 765 766
        if (chunk > drbg->max_request)
            chunk = drbg->max_request;
        ret = RAND_DRBG_generate(drbg, out, chunk, 0, NULL, 0);
R
Rich Salz 已提交
767 768 769 770 771 772
        if (!ret)
            goto err;
    }
    ret = 1;

err:
773
    CRYPTO_THREAD_unlock(drbg->lock);
R
Rich Salz 已提交
774 775 776
    return ret;
}

777
/* Implements the default OpenSSL RAND_add() method */
R
Rich Salz 已提交
778 779
static int drbg_add(const void *buf, int num, double randomness)
{
780
    int ret = 0;
781
    RAND_DRBG *drbg = RAND_DRBG_get0_master();
R
Rich Salz 已提交
782

783 784
    if (drbg == NULL)
        return 0;
R
Rich Salz 已提交
785

786 787
    if (num < 0 || randomness < 0.0)
        return 0;
R
Rich Salz 已提交
788

789 790 791 792 793 794 795 796
    if (randomness > (double)drbg->max_entropylen) {
        /*
         * The purpose of this check is to bound |randomness| by a
         * relatively small value in order to prevent an integer
         * overflow when multiplying by 8 in the rand_drbg_restart()
         * call below.
         */
        return 0;
R
Rich Salz 已提交
797 798
    }

799 800 801 802 803 804 805
    CRYPTO_THREAD_write_lock(drbg->lock);
    ret = rand_drbg_restart(drbg, buf,
                            (size_t)(unsigned int)num,
                            (size_t)(8*randomness));
    CRYPTO_THREAD_unlock(drbg->lock);

    return ret;
R
Rich Salz 已提交
806 807
}

808
/* Implements the default OpenSSL RAND_seed() method */
R
Rich Salz 已提交
809 810 811 812 813
static int drbg_seed(const void *buf, int num)
{
    return drbg_add(buf, num, num);
}

814
/* Implements the default OpenSSL RAND_status() method */
R
Rich Salz 已提交
815
static int drbg_status(void)
R
Rich Salz 已提交
816
{
R
Rich Salz 已提交
817
    int ret;
818
    RAND_DRBG *drbg = RAND_DRBG_get0_master();
819 820 821

    if (drbg == NULL)
        return 0;
R
Rich Salz 已提交
822

823 824 825
    CRYPTO_THREAD_write_lock(drbg->lock);
    ret = drbg->state == DRBG_READY ? 1 : 0;
    CRYPTO_THREAD_unlock(drbg->lock);
R
Rich Salz 已提交
826
    return ret;
R
Rich Salz 已提交
827 828
}

829
/*
830 831 832 833 834 835 836 837 838
 * Get the master DRBG.
 * Returns pointer to the DRBG on success, NULL on failure.
 *
 */
RAND_DRBG *RAND_DRBG_get0_master(void)
{
    if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
        return NULL;

839
    return drbg_master;
840 841 842 843
}

/*
 * Get the public DRBG.
844 845
 * Returns pointer to the DRBG on success, NULL on failure.
 */
846
RAND_DRBG *RAND_DRBG_get0_public(void)
847
{
848
    if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
849 850
        return NULL;

851
    return drbg_public;
852 853 854
}

/*
855
 * Get the private DRBG.
856 857
 * Returns pointer to the DRBG on success, NULL on failure.
 */
858
RAND_DRBG *RAND_DRBG_get0_private(void)
859
{
860
    if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
861 862
        return NULL;

863
    return drbg_private;
864 865
}

R
Rich Salz 已提交
866 867 868
RAND_METHOD rand_meth = {
    drbg_seed,
    drbg_bytes,
869
    NULL,
R
Rich Salz 已提交
870 871 872 873 874 875
    drbg_add,
    drbg_bytes,
    drbg_status
};

RAND_METHOD *RAND_OpenSSL(void)
R
Rich Salz 已提交
876
{
R
Rich Salz 已提交
877
    return &rand_meth;
R
Rich Salz 已提交
878
}