drbg_lib.c 11.9 KB
Newer Older
R
Rich Salz 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright 2011-2017 The OpenSSL Project Authors. All Rights Reserved.
 *
 * 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"

/*
 * Support framework for NIST SP 800-90A DRBG, AES-CTR mode.
R
Rich Salz 已提交
18 19
 * The RAND_DRBG is OpenSSL's pointer to an instance of the DRBG.
 *
R
Rich Salz 已提交
20 21 22 23 24 25 26 27 28
 * 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.)
 */

/*
R
Rich Salz 已提交
29
 * Set/initialize |drbg| to be of type |nid|, with optional |flags|.
R
Rich Salz 已提交
30 31 32
 * Return -2 if the type is not supported, 1 on success and -1 on
 * failure.
 */
R
Rich Salz 已提交
33
int RAND_DRBG_set(RAND_DRBG *drbg, int nid, unsigned int flags)
R
Rich Salz 已提交
34 35 36
{
    int ret = 1;

R
Rich Salz 已提交
37 38 39
    drbg->state = DRBG_UNINITIALISED;
    drbg->flags = flags;
    drbg->nid = nid;
R
Rich Salz 已提交
40 41 42 43 44 45 46 47 48 49 50

    switch (nid) {
    default:
        RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_UNSUPPORTED_DRBG_TYPE);
        return -2;
    case 0:
        /* Uninitialized; that's okay. */
        return 1;
    case NID_aes_128_ctr:
    case NID_aes_192_ctr:
    case NID_aes_256_ctr:
R
Rich Salz 已提交
51
        ret = ctr_init(drbg);
R
Rich Salz 已提交
52 53 54 55 56 57 58 59 60 61
        break;
    }

    if (ret < 0)
        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 已提交
62
 * NULL, will be used to auto-seed this RAND_DRBG as needed.
R
Rich Salz 已提交
63
 */
R
Rich Salz 已提交
64
RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent)
R
Rich Salz 已提交
65
{
R
Rich Salz 已提交
66 67
    RAND_DRBG *drbg = OPENSSL_zalloc(sizeof(*drbg));
    unsigned char *ucp = OPENSSL_zalloc(RANDOMNESS_NEEDED);
R
Rich Salz 已提交
68

R
Rich Salz 已提交
69
    if (drbg == NULL || ucp == NULL) {
R
Rich Salz 已提交
70
        RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE);
R
Rich Salz 已提交
71
        goto err;
R
Rich Salz 已提交
72
    }
R
Rich Salz 已提交
73 74
    drbg->size = RANDOMNESS_NEEDED;
    drbg->randomness = ucp;
R
Rich Salz 已提交
75
    drbg->fork_count = rand_fork_count;
R
Rich Salz 已提交
76 77 78 79 80
    drbg->parent = parent;
    if (RAND_DRBG_set(drbg, type, flags) < 0)
        goto err;

    if (parent != NULL) {
R
Rich Salz 已提交
81 82 83
        if (parent->state == DRBG_UNINITIALISED
                && RAND_DRBG_instantiate(parent, NULL, 0) == 0)
            goto err;
R
Rich Salz 已提交
84 85 86 87 88 89 90 91 92 93
        if (!RAND_DRBG_set_callbacks(drbg, drbg_entropy_from_parent,
                                     drbg_release_entropy,
                                     NULL, NULL)
                /*
                 * Add in our address.  Note we are adding the pointer
                 * itself, not its contents!
                 */
                || !RAND_DRBG_instantiate(drbg,
                                          (unsigned char*)&drbg, sizeof(drbg)))
            goto err;
R
Rich Salz 已提交
94
    }
R
Rich Salz 已提交
95 96 97 98 99 100 101

    return drbg;

err:
    OPENSSL_free(ucp);
    OPENSSL_free(drbg);
    return NULL;
R
Rich Salz 已提交
102 103
}

R
Rich Salz 已提交
104 105 106 107 108
RAND_DRBG *RAND_DRBG_get0_global(void)
{
    return &rand_drbg;
}

R
Rich Salz 已提交
109
/*
R
Rich Salz 已提交
110
 * Uninstantiate |drbg| and free all memory.
R
Rich Salz 已提交
111
 */
R
Rich Salz 已提交
112
void RAND_DRBG_free(RAND_DRBG *drbg)
R
Rich Salz 已提交
113
{
R
Rich Salz 已提交
114 115
    /* The global DRBG is free'd by rand_cleanup_int() */
    if (drbg == NULL || drbg == &rand_drbg)
R
Rich Salz 已提交
116 117
        return;

R
Rich Salz 已提交
118 119 120 121 122
    ctr_uninstantiate(drbg);
    OPENSSL_cleanse(drbg->randomness, drbg->size);
    OPENSSL_free(drbg->randomness);
    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data);
    OPENSSL_clear_free(drbg, sizeof(*drbg));
R
Rich Salz 已提交
123 124 125
}

/*
R
Rich Salz 已提交
126
 * Instantiate |drbg|, after it has been initialized.  Use |pers| and
R
Rich Salz 已提交
127 128
 * |perslen| as prediction-resistance input.
 */
R
Rich Salz 已提交
129
int RAND_DRBG_instantiate(RAND_DRBG *drbg,
R
Rich Salz 已提交
130 131 132
                          const unsigned char *pers, size_t perslen)
{
    unsigned char *nonce = NULL, *entropy = NULL;
R
Rich Salz 已提交
133
    size_t noncelen = 0, entlen = 0;
R
Rich Salz 已提交
134

R
Rich Salz 已提交
135 136 137
    if (perslen > drbg->max_pers) {
        RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
                RAND_R_PERSONALISATION_STRING_TOO_LONG);
R
Rich Salz 已提交
138 139
        goto end;
    }
R
Rich Salz 已提交
140 141 142 143
    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 已提交
144 145 146
        goto end;
    }

R
Rich Salz 已提交
147 148 149 150 151 152
    drbg->state = DRBG_ERROR;
    if (drbg->get_entropy != NULL)
        entlen = drbg->get_entropy(drbg, &entropy, drbg->strength,
                                   drbg->min_entropy, drbg->max_entropy);
    if (entlen < drbg->min_entropy || entlen > drbg->max_entropy) {
        RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_ENTROPY);
R
Rich Salz 已提交
153 154 155
        goto end;
    }

R
Rich Salz 已提交
156 157 158 159 160
    if (drbg->max_nonce > 0 && drbg->get_nonce != NULL) {
        noncelen = drbg->get_nonce(drbg, &nonce, drbg->strength / 2,
                                   drbg->min_nonce, drbg->max_nonce);
        if (noncelen < drbg->min_nonce || noncelen > drbg->max_nonce) {
            RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_NONCE);
R
Rich Salz 已提交
161 162 163 164
            goto end;
        }
    }

R
Rich Salz 已提交
165
    if (!ctr_instantiate(drbg, entropy, entlen,
R
Rich Salz 已提交
166
                         nonce, noncelen, pers, perslen)) {
R
Rich Salz 已提交
167
        RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_INSTANTIATING_DRBG);
R
Rich Salz 已提交
168 169 170
        goto end;
    }

R
Rich Salz 已提交
171 172
    drbg->state = DRBG_READY;
    drbg->reseed_counter = 1;
R
Rich Salz 已提交
173 174

end:
R
Rich Salz 已提交
175 176 177 178 179
    if (entropy != NULL && drbg->cleanup_entropy != NULL)
        drbg->cleanup_entropy(drbg, entropy);
    if (nonce != NULL && drbg->cleanup_nonce!= NULL )
        drbg->cleanup_nonce(drbg, nonce);
    if (drbg->state == DRBG_READY)
R
Rich Salz 已提交
180 181 182 183 184
        return 1;
    return 0;
}

/*
R
Rich Salz 已提交
185
 * Uninstantiate |drbg|. Must be instantiated before it can be used.
R
Rich Salz 已提交
186
 */
R
Rich Salz 已提交
187
int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
R
Rich Salz 已提交
188
{
R
Rich Salz 已提交
189
    int ret = ctr_uninstantiate(drbg);
R
Rich Salz 已提交
190

R
Rich Salz 已提交
191 192
    OPENSSL_cleanse(&drbg->ctr, sizeof(drbg->ctr));
    drbg->state = DRBG_UNINITIALISED;
R
Rich Salz 已提交
193 194 195 196
    return ret;
}

/*
R
Rich Salz 已提交
197
 * Mix in the specified data to reseed |drbg|.
R
Rich Salz 已提交
198
 */
R
Rich Salz 已提交
199
int RAND_DRBG_reseed(RAND_DRBG *drbg,
R
Rich Salz 已提交
200 201 202 203
                     const unsigned char *adin, size_t adinlen)
{
    unsigned char *entropy = NULL;
    size_t entlen = 0;
R
Rich Salz 已提交
204 205 206 207 208 209 210 211

    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 已提交
212 213 214 215
    }

    if (adin == NULL)
        adinlen = 0;
R
Rich Salz 已提交
216 217 218
    else if (adinlen > drbg->max_adin) {
        RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
        return 0;
R
Rich Salz 已提交
219 220
    }

R
Rich Salz 已提交
221 222 223 224 225 226
    drbg->state = DRBG_ERROR;
    if (drbg->get_entropy != NULL)
        entlen = drbg->get_entropy(drbg, &entropy, drbg->strength,
                                   drbg->min_entropy, drbg->max_entropy);
    if (entlen < drbg->min_entropy || entlen > drbg->max_entropy) {
        RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ERROR_RETRIEVING_ENTROPY);
R
Rich Salz 已提交
227 228 229
        goto end;
    }

R
Rich Salz 已提交
230
    if (!ctr_reseed(drbg, entropy, entlen, adin, adinlen))
R
Rich Salz 已提交
231
        goto end;
R
Rich Salz 已提交
232 233
    drbg->state = DRBG_READY;
    drbg->reseed_counter = 1;
R
Rich Salz 已提交
234 235

end:
R
Rich Salz 已提交
236 237 238
    if (entropy != NULL && drbg->cleanup_entropy != NULL)
        drbg->cleanup_entropy(drbg, entropy);
    if (drbg->state == DRBG_READY)
R
Rich Salz 已提交
239 240 241 242 243 244 245 246 247
        return 1;
    return 0;
}

/*
 * 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|.
 */
R
Rich Salz 已提交
248
int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
R
Rich Salz 已提交
249 250 251
                       int prediction_resistance,
                       const unsigned char *adin, size_t adinlen)
{
R
Rich Salz 已提交
252 253 254
    if (drbg->state == DRBG_ERROR) {
        RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_IN_ERROR_STATE);
        return 0;
R
Rich Salz 已提交
255
    }
R
Rich Salz 已提交
256 257
    if (drbg->state == DRBG_UNINITIALISED) {
        RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_NOT_INSTANTIATED);
R
Rich Salz 已提交
258 259
        return 0;
    }
R
Rich Salz 已提交
260 261 262 263 264 265 266
    if (outlen > drbg->max_request) {
        RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG);
        return 0;
    }
    if (adinlen > drbg->max_adin) {
        RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
        return 0;
R
Rich Salz 已提交
267 268
    }

R
Rich Salz 已提交
269 270 271 272 273
    if (drbg->fork_count != rand_fork_count) {
        drbg->fork_count = rand_fork_count;
        drbg->state = DRBG_RESEED;
    }

R
Rich Salz 已提交
274 275
    if (drbg->reseed_counter >= drbg->reseed_interval)
        drbg->state = DRBG_RESEED;
R
Rich Salz 已提交
276

R
Rich Salz 已提交
277 278 279 280
    if (drbg->state == DRBG_RESEED || prediction_resistance) {
        if (!RAND_DRBG_reseed(drbg, adin, adinlen)) {
            RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_RESEED_ERROR);
            return 0;
R
Rich Salz 已提交
281 282 283 284 285
        }
        adin = NULL;
        adinlen = 0;
    }

R
Rich Salz 已提交
286 287 288 289
    if (!ctr_generate(drbg, out, outlen, adin, adinlen)) {
        drbg->state = DRBG_ERROR;
        RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_GENERATE_ERROR);
        return 0;
R
Rich Salz 已提交
290
    }
R
Rich Salz 已提交
291 292 293

    if (drbg->reseed_counter >= drbg->reseed_interval)
        drbg->state = DRBG_RESEED;
R
Rich Salz 已提交
294
    else
R
Rich Salz 已提交
295
        drbg->reseed_counter++;
R
Rich Salz 已提交
296 297 298 299
    return 1;
}

/*
R
Rich Salz 已提交
300 301
 * Set the callbacks for entropy and nonce.  We currently don't use
 * the nonce; that's mainly for the KATs
R
Rich Salz 已提交
302
 */
R
Rich Salz 已提交
303 304 305 306 307
int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
                            RAND_DRBG_get_entropy_fn cb_get_entropy,
                            RAND_DRBG_cleanup_entropy_fn cb_cleanup_entropy,
                            RAND_DRBG_get_nonce_fn cb_get_nonce,
                            RAND_DRBG_cleanup_nonce_fn cb_cleanup_nonce)
R
Rich Salz 已提交
308
{
R
Rich Salz 已提交
309
    if (drbg->state != DRBG_UNINITIALISED)
R
Rich Salz 已提交
310
        return 0;
R
Rich Salz 已提交
311 312 313 314
    drbg->get_entropy = cb_get_entropy;
    drbg->cleanup_entropy = cb_cleanup_entropy;
    drbg->get_nonce = cb_get_nonce;
    drbg->cleanup_nonce = cb_cleanup_nonce;
R
Rich Salz 已提交
315 316 317 318
    return 1;
}

/*
R
Rich Salz 已提交
319
 * Set the reseed interval.
R
Rich Salz 已提交
320
 */
R
Rich Salz 已提交
321
int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, int interval)
R
Rich Salz 已提交
322
{
323 324
    if (interval < 0 || interval > MAX_RESEED)
        return 0;
R
Rich Salz 已提交
325
    drbg->reseed_interval = interval;
326
    return 1;
R
Rich Salz 已提交
327 328 329 330 331
}

/*
 * Get and set the EXDATA
 */
R
Rich Salz 已提交
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 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
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.
 */

static int drbg_bytes(unsigned char *out, int count)
{
    int ret = 0;
    size_t chunk;

    CRYPTO_THREAD_write_lock(rand_drbg.lock);
    if (rand_drbg.state == DRBG_UNINITIALISED
            && RAND_DRBG_instantiate(&rand_drbg, NULL, 0) == 0)
        goto err;

    for ( ; count > 0; count -= chunk, out += chunk) {
        chunk = count;
        if (chunk > rand_drbg.max_request)
            chunk = rand_drbg.max_request;
        ret = RAND_DRBG_generate(&rand_drbg, out, chunk, 0, NULL, 0);
        if (!ret)
            goto err;
    }
    ret = 1;

err:
    CRYPTO_THREAD_unlock(rand_drbg.lock);
    return ret;
}

static int drbg_add(const void *buf, int num, double randomness)
{
    unsigned char *in = (unsigned char *)buf;
    unsigned char *out, *end;

    CRYPTO_THREAD_write_lock(rand_bytes.lock);
    out = &rand_bytes.buff[rand_bytes.curr];
    end = &rand_bytes.buff[rand_bytes.size];

    /* Copy whatever fits into the end of the buffer. */
    for ( ; --num >= 0 && out < end; rand_bytes.curr++)
        *out++ = *in++;

    /* XOR any the leftover. */
    while (num > 0) {
        for (out = rand_bytes.buff; --num >= 0 && out < end; )
            *out++ ^= *in++;
    }

    CRYPTO_THREAD_unlock(rand_bytes.lock);
    return 1;
}

static int drbg_seed(const void *buf, int num)
{
    return drbg_add(buf, num, num);
}

static int drbg_status(void)
R
Rich Salz 已提交
402
{
R
Rich Salz 已提交
403 404 405 406 407 408
    int ret;

    CRYPTO_THREAD_write_lock(rand_drbg.lock);
    ret = rand_drbg.state == DRBG_READY ? 1 : 0;
    CRYPTO_THREAD_unlock(rand_drbg.lock);
    return ret;
R
Rich Salz 已提交
409 410
}

R
Rich Salz 已提交
411
RAND_DRBG rand_drbg; /* The default global DRBG. */
412
RAND_DRBG priv_drbg; /* The global private-key DRBG. */
R
Rich Salz 已提交
413 414 415 416

RAND_METHOD rand_meth = {
    drbg_seed,
    drbg_bytes,
417
    NULL,
R
Rich Salz 已提交
418 419 420 421 422 423
    drbg_add,
    drbg_bytes,
    drbg_status
};

RAND_METHOD *RAND_OpenSSL(void)
R
Rich Salz 已提交
424
{
R
Rich Salz 已提交
425
    return &rand_meth;
R
Rich Salz 已提交
426
}