2017-06-27 16:04:37 +00:00
|
|
|
/*
|
|
|
|
* 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"
|
2017-08-27 15:46:33 +00:00
|
|
|
#include "internal/thread_once.h"
|
|
|
|
#include "internal/rand_int.h"
|
2017-06-27 16:04:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Support framework for NIST SP 800-90A DRBG, AES-CTR mode.
|
2017-08-03 13:23:28 +00:00
|
|
|
* The RAND_DRBG is OpenSSL's pointer to an instance of the DRBG.
|
|
|
|
*
|
2017-06-27 16:04:37 +00:00
|
|
|
* 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.)
|
|
|
|
*/
|
|
|
|
|
2017-08-27 15:46:33 +00:00
|
|
|
static CRYPTO_ONCE rand_init_drbg = CRYPTO_ONCE_STATIC_INIT;
|
|
|
|
|
2017-06-27 16:04:37 +00:00
|
|
|
/*
|
2017-08-03 13:23:28 +00:00
|
|
|
* Set/initialize |drbg| to be of type |nid|, with optional |flags|.
|
2017-06-27 16:04:37 +00:00
|
|
|
* Return -2 if the type is not supported, 1 on success and -1 on
|
|
|
|
* failure.
|
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
int RAND_DRBG_set(RAND_DRBG *drbg, int nid, unsigned int flags)
|
2017-06-27 16:04:37 +00:00
|
|
|
{
|
|
|
|
int ret = 1;
|
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->state = DRBG_UNINITIALISED;
|
|
|
|
drbg->flags = flags;
|
|
|
|
drbg->nid = nid;
|
2017-06-27 16:04:37 +00:00
|
|
|
|
|
|
|
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:
|
2017-08-03 13:23:28 +00:00
|
|
|
ret = ctr_init(drbg);
|
2017-06-27 16:04:37 +00:00
|
|
|
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
|
2017-08-03 13:23:28 +00:00
|
|
|
* NULL, will be used to auto-seed this RAND_DRBG as needed.
|
2017-06-27 16:04:37 +00:00
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent)
|
2017-06-27 16:04:37 +00:00
|
|
|
{
|
2017-08-03 13:23:28 +00:00
|
|
|
RAND_DRBG *drbg = OPENSSL_zalloc(sizeof(*drbg));
|
2017-06-27 16:04:37 +00:00
|
|
|
|
2017-08-22 22:24:23 +00:00
|
|
|
if (drbg == NULL) {
|
2017-06-27 16:04:37 +00:00
|
|
|
RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE);
|
2017-08-03 13:23:28 +00:00
|
|
|
goto err;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->size = RANDOMNESS_NEEDED;
|
2017-08-06 22:12:28 +00:00
|
|
|
drbg->fork_count = rand_fork_count;
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->parent = parent;
|
|
|
|
if (RAND_DRBG_set(drbg, type, flags) < 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (parent != NULL) {
|
|
|
|
if (!RAND_DRBG_set_callbacks(drbg, drbg_entropy_from_parent,
|
|
|
|
drbg_release_entropy,
|
2017-08-27 15:46:33 +00:00
|
|
|
NULL, NULL))
|
2017-08-03 13:23:28 +00:00
|
|
|
goto err;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
2017-08-03 13:23:28 +00:00
|
|
|
|
|
|
|
return drbg;
|
|
|
|
|
|
|
|
err:
|
|
|
|
OPENSSL_free(drbg);
|
|
|
|
return NULL;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-08-03 13:23:28 +00:00
|
|
|
* Uninstantiate |drbg| and free all memory.
|
2017-06-27 16:04:37 +00:00
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
void RAND_DRBG_free(RAND_DRBG *drbg)
|
2017-06-27 16:04:37 +00:00
|
|
|
{
|
2017-08-27 15:46:33 +00:00
|
|
|
/* The global DRBG is free'd by rand_cleanup_drbg_int() */
|
2017-08-03 13:23:28 +00:00
|
|
|
if (drbg == NULL || drbg == &rand_drbg)
|
2017-06-27 16:04:37 +00:00
|
|
|
return;
|
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
ctr_uninstantiate(drbg);
|
|
|
|
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data);
|
|
|
|
OPENSSL_clear_free(drbg, sizeof(*drbg));
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-08-03 13:23:28 +00:00
|
|
|
* Instantiate |drbg|, after it has been initialized. Use |pers| and
|
2017-06-27 16:04:37 +00:00
|
|
|
* |perslen| as prediction-resistance input.
|
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
int RAND_DRBG_instantiate(RAND_DRBG *drbg,
|
2017-06-27 16:04:37 +00:00
|
|
|
const unsigned char *pers, size_t perslen)
|
|
|
|
{
|
|
|
|
unsigned char *nonce = NULL, *entropy = NULL;
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
size_t noncelen = 0, entropylen = 0;
|
2017-06-27 16:04:37 +00:00
|
|
|
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
if (perslen > drbg->max_perslen) {
|
2017-08-03 13:23:28 +00:00
|
|
|
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
|
|
|
|
RAND_R_PERSONALISATION_STRING_TOO_LONG);
|
2017-06-27 16:04:37 +00:00
|
|
|
goto end;
|
|
|
|
}
|
2017-08-03 13:23:28 +00:00
|
|
|
if (drbg->state != DRBG_UNINITIALISED) {
|
|
|
|
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
|
|
|
|
drbg->state == DRBG_ERROR ? RAND_R_IN_ERROR_STATE
|
|
|
|
: RAND_R_ALREADY_INSTANTIATED);
|
2017-06-27 16:04:37 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->state = DRBG_ERROR;
|
|
|
|
if (drbg->get_entropy != NULL)
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
|
|
|
|
drbg->min_entropylen, drbg->max_entropylen);
|
|
|
|
if (entropylen < drbg->min_entropylen || entropylen > drbg->max_entropylen) {
|
2017-08-03 13:23:28 +00:00
|
|
|
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_ENTROPY);
|
2017-06-27 16:04:37 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
if (drbg->max_noncelen > 0 && drbg->get_nonce != NULL) {
|
2017-08-03 13:23:28 +00:00
|
|
|
noncelen = drbg->get_nonce(drbg, &nonce, drbg->strength / 2,
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
drbg->min_noncelen, drbg->max_noncelen);
|
|
|
|
if (noncelen < drbg->min_noncelen || noncelen > drbg->max_noncelen) {
|
2017-08-03 13:23:28 +00:00
|
|
|
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_NONCE);
|
2017-06-27 16:04:37 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
if (!ctr_instantiate(drbg, entropy, entropylen,
|
2017-06-27 16:04:37 +00:00
|
|
|
nonce, noncelen, pers, perslen)) {
|
2017-08-03 13:23:28 +00:00
|
|
|
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_INSTANTIATING_DRBG);
|
2017-06-27 16:04:37 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->state = DRBG_READY;
|
|
|
|
drbg->reseed_counter = 1;
|
2017-06-27 16:04:37 +00:00
|
|
|
|
|
|
|
end:
|
2017-08-03 13:23:28 +00:00
|
|
|
if (entropy != NULL && drbg->cleanup_entropy != NULL)
|
2017-08-25 21:26:53 +00:00
|
|
|
drbg->cleanup_entropy(drbg, entropy, entropylen);
|
2017-08-03 13:23:28 +00:00
|
|
|
if (nonce != NULL && drbg->cleanup_nonce!= NULL )
|
2017-08-25 21:26:53 +00:00
|
|
|
drbg->cleanup_nonce(drbg, nonce, noncelen);
|
2017-08-03 13:23:28 +00:00
|
|
|
if (drbg->state == DRBG_READY)
|
2017-06-27 16:04:37 +00:00
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-08-03 13:23:28 +00:00
|
|
|
* Uninstantiate |drbg|. Must be instantiated before it can be used.
|
2017-06-27 16:04:37 +00:00
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
|
2017-06-27 16:04:37 +00:00
|
|
|
{
|
2017-08-03 13:23:28 +00:00
|
|
|
int ret = ctr_uninstantiate(drbg);
|
2017-06-27 16:04:37 +00:00
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
OPENSSL_cleanse(&drbg->ctr, sizeof(drbg->ctr));
|
|
|
|
drbg->state = DRBG_UNINITIALISED;
|
2017-06-27 16:04:37 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-08-03 13:23:28 +00:00
|
|
|
* Mix in the specified data to reseed |drbg|.
|
2017-06-27 16:04:37 +00:00
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
int RAND_DRBG_reseed(RAND_DRBG *drbg,
|
2017-06-27 16:04:37 +00:00
|
|
|
const unsigned char *adin, size_t adinlen)
|
|
|
|
{
|
|
|
|
unsigned char *entropy = NULL;
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
size_t entropylen = 0;
|
2017-08-03 13:23:28 +00:00
|
|
|
|
|
|
|
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;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (adin == NULL)
|
|
|
|
adinlen = 0;
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
else if (adinlen > drbg->max_adinlen) {
|
2017-08-03 13:23:28 +00:00
|
|
|
RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
|
|
|
|
return 0;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->state = DRBG_ERROR;
|
|
|
|
if (drbg->get_entropy != NULL)
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
|
|
|
|
drbg->min_entropylen, drbg->max_entropylen);
|
|
|
|
if (entropylen < drbg->min_entropylen || entropylen > drbg->max_entropylen) {
|
2017-08-03 13:23:28 +00:00
|
|
|
RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ERROR_RETRIEVING_ENTROPY);
|
2017-06-27 16:04:37 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
if (!ctr_reseed(drbg, entropy, entropylen, adin, adinlen))
|
2017-06-27 16:04:37 +00:00
|
|
|
goto end;
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->state = DRBG_READY;
|
|
|
|
drbg->reseed_counter = 1;
|
2017-06-27 16:04:37 +00:00
|
|
|
|
|
|
|
end:
|
2017-08-03 13:23:28 +00:00
|
|
|
if (entropy != NULL && drbg->cleanup_entropy != NULL)
|
2017-08-25 21:26:53 +00:00
|
|
|
drbg->cleanup_entropy(drbg, entropy, entropylen);
|
2017-08-03 13:23:28 +00:00
|
|
|
if (drbg->state == DRBG_READY)
|
2017-06-27 16:04:37 +00:00
|
|
|
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|.
|
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
|
2017-06-27 16:04:37 +00:00
|
|
|
int prediction_resistance,
|
|
|
|
const unsigned char *adin, size_t adinlen)
|
|
|
|
{
|
2017-08-03 13:23:28 +00:00
|
|
|
if (drbg->state == DRBG_ERROR) {
|
|
|
|
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_IN_ERROR_STATE);
|
|
|
|
return 0;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
2017-08-03 13:23:28 +00:00
|
|
|
if (drbg->state == DRBG_UNINITIALISED) {
|
|
|
|
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_NOT_INSTANTIATED);
|
2017-06-27 16:04:37 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-08-03 13:23:28 +00:00
|
|
|
if (outlen > drbg->max_request) {
|
|
|
|
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG);
|
|
|
|
return 0;
|
|
|
|
}
|
DRBG: clarify difference between entropy counts and buffer lengths
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
2017-08-20 21:02:46 +00:00
|
|
|
if (adinlen > drbg->max_adinlen) {
|
2017-08-03 13:23:28 +00:00
|
|
|
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
|
|
|
|
return 0;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
|
|
|
|
2017-08-06 22:12:28 +00:00
|
|
|
if (drbg->fork_count != rand_fork_count) {
|
|
|
|
drbg->fork_count = rand_fork_count;
|
|
|
|
drbg->state = DRBG_RESEED;
|
|
|
|
}
|
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
if (drbg->reseed_counter >= drbg->reseed_interval)
|
|
|
|
drbg->state = DRBG_RESEED;
|
2017-06-27 16:04:37 +00:00
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
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;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
|
|
|
adin = NULL;
|
|
|
|
adinlen = 0;
|
|
|
|
}
|
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
if (!ctr_generate(drbg, out, outlen, adin, adinlen)) {
|
|
|
|
drbg->state = DRBG_ERROR;
|
|
|
|
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_GENERATE_ERROR);
|
|
|
|
return 0;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
2017-08-03 13:23:28 +00:00
|
|
|
|
|
|
|
if (drbg->reseed_counter >= drbg->reseed_interval)
|
|
|
|
drbg->state = DRBG_RESEED;
|
2017-06-27 16:04:37 +00:00
|
|
|
else
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->reseed_counter++;
|
2017-06-27 16:04:37 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-08-03 13:23:28 +00:00
|
|
|
* Set the callbacks for entropy and nonce. We currently don't use
|
|
|
|
* the nonce; that's mainly for the KATs
|
2017-06-27 16:04:37 +00:00
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
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)
|
2017-06-27 16:04:37 +00:00
|
|
|
{
|
2017-08-03 13:23:28 +00:00
|
|
|
if (drbg->state != DRBG_UNINITIALISED)
|
2017-06-27 16:04:37 +00:00
|
|
|
return 0;
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->get_entropy = cb_get_entropy;
|
|
|
|
drbg->cleanup_entropy = cb_cleanup_entropy;
|
|
|
|
drbg->get_nonce = cb_get_nonce;
|
|
|
|
drbg->cleanup_nonce = cb_cleanup_nonce;
|
2017-06-27 16:04:37 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-08-03 13:23:28 +00:00
|
|
|
* Set the reseed interval.
|
2017-06-27 16:04:37 +00:00
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, int interval)
|
2017-06-27 16:04:37 +00:00
|
|
|
{
|
2017-07-19 21:41:26 +00:00
|
|
|
if (interval < 0 || interval > MAX_RESEED)
|
|
|
|
return 0;
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg->reseed_interval = interval;
|
2017-07-19 21:41:26 +00:00
|
|
|
return 1;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get and set the EXDATA
|
|
|
|
*/
|
2017-08-03 13:23:28 +00:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2017-08-27 15:46:33 +00:00
|
|
|
/*
|
|
|
|
* Creates a global DRBG with default settings.
|
|
|
|
* Returns 1 on success, 0 on failure
|
|
|
|
*/
|
|
|
|
static int setup_drbg(RAND_DRBG *drbg)
|
|
|
|
{
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
drbg->lock = CRYPTO_THREAD_lock_new();
|
|
|
|
ret &= drbg->lock != NULL;
|
|
|
|
drbg->size = RANDOMNESS_NEEDED;
|
|
|
|
drbg->secure = CRYPTO_secure_malloc_initialized();
|
|
|
|
/* If you change these parameters, see RANDOMNESS_NEEDED */
|
|
|
|
ret &= RAND_DRBG_set(drbg,
|
|
|
|
NID_aes_128_ctr, RAND_DRBG_FLAG_CTR_USE_DF) == 1;
|
|
|
|
ret &= RAND_DRBG_set_callbacks(drbg, drbg_entropy_from_system,
|
|
|
|
drbg_release_entropy, NULL, NULL) == 1;
|
|
|
|
ret &= RAND_DRBG_instantiate(drbg, NULL, 0) == 1;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize the global DRBGs on first use.
|
|
|
|
* Returns 1 on success, 0 on failure.
|
|
|
|
*/
|
|
|
|
DEFINE_RUN_ONCE_STATIC(do_rand_init_drbg)
|
|
|
|
{
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
ret &= setup_drbg(&rand_drbg);
|
|
|
|
ret &= setup_drbg(&priv_drbg);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean up a DRBG and free it */
|
|
|
|
static void free_drbg(RAND_DRBG *drbg)
|
|
|
|
{
|
|
|
|
CRYPTO_THREAD_lock_free(drbg->lock);
|
|
|
|
RAND_DRBG_uninstantiate(drbg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean up the global DRBGs before exit */
|
|
|
|
void rand_cleanup_drbg_int(void)
|
|
|
|
{
|
|
|
|
free_drbg(&rand_drbg);
|
|
|
|
free_drbg(&priv_drbg);
|
|
|
|
}
|
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
static int drbg_bytes(unsigned char *out, int count)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
size_t chunk;
|
2017-08-27 15:46:33 +00:00
|
|
|
RAND_DRBG *drbg = RAND_DRBG_get0_global();
|
2017-08-03 13:23:28 +00:00
|
|
|
|
2017-08-27 15:46:33 +00:00
|
|
|
if (drbg == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
CRYPTO_THREAD_write_lock(drbg->lock);
|
|
|
|
if (drbg->state == DRBG_UNINITIALISED)
|
2017-08-03 13:23:28 +00:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
for ( ; count > 0; count -= chunk, out += chunk) {
|
|
|
|
chunk = count;
|
2017-08-27 15:46:33 +00:00
|
|
|
if (chunk > drbg->max_request)
|
|
|
|
chunk = drbg->max_request;
|
|
|
|
ret = RAND_DRBG_generate(drbg, out, chunk, 0, NULL, 0);
|
2017-08-03 13:23:28 +00:00
|
|
|
if (!ret)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
err:
|
2017-08-27 15:46:33 +00:00
|
|
|
CRYPTO_THREAD_unlock(drbg->lock);
|
2017-08-03 13:23:28 +00:00
|
|
|
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)
|
2017-06-27 16:04:37 +00:00
|
|
|
{
|
2017-08-03 13:23:28 +00:00
|
|
|
int ret;
|
2017-08-27 15:46:33 +00:00
|
|
|
RAND_DRBG *drbg = RAND_DRBG_get0_global();
|
|
|
|
|
|
|
|
if (drbg == NULL)
|
|
|
|
return 0;
|
2017-08-03 13:23:28 +00:00
|
|
|
|
2017-08-27 15:46:33 +00:00
|
|
|
CRYPTO_THREAD_write_lock(drbg->lock);
|
|
|
|
ret = drbg->state == DRBG_READY ? 1 : 0;
|
|
|
|
CRYPTO_THREAD_unlock(drbg->lock);
|
2017-08-03 13:23:28 +00:00
|
|
|
return ret;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|
|
|
|
|
2017-08-27 15:46:33 +00:00
|
|
|
/*
|
|
|
|
* Get the global public DRBG.
|
|
|
|
* Returns pointer to the DRBG on success, NULL on failure.
|
|
|
|
*/
|
|
|
|
RAND_DRBG *RAND_DRBG_get0_global(void)
|
|
|
|
{
|
|
|
|
if (!RUN_ONCE(&rand_init_drbg, do_rand_init_drbg))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return &rand_drbg;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the global private DRBG.
|
|
|
|
* Returns pointer to the DRBG on success, NULL on failure.
|
|
|
|
*/
|
|
|
|
RAND_DRBG *RAND_DRBG_get0_priv_global(void)
|
|
|
|
{
|
|
|
|
if (!RUN_ONCE(&rand_init_drbg, do_rand_init_drbg))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return &priv_drbg;
|
|
|
|
}
|
|
|
|
|
2017-08-03 13:23:28 +00:00
|
|
|
RAND_DRBG rand_drbg; /* The default global DRBG. */
|
2017-08-02 18:00:52 +00:00
|
|
|
RAND_DRBG priv_drbg; /* The global private-key DRBG. */
|
2017-08-03 13:23:28 +00:00
|
|
|
|
|
|
|
RAND_METHOD rand_meth = {
|
|
|
|
drbg_seed,
|
|
|
|
drbg_bytes,
|
2017-08-02 18:00:52 +00:00
|
|
|
NULL,
|
2017-08-03 13:23:28 +00:00
|
|
|
drbg_add,
|
|
|
|
drbg_bytes,
|
|
|
|
drbg_status
|
|
|
|
};
|
|
|
|
|
|
|
|
RAND_METHOD *RAND_OpenSSL(void)
|
2017-06-27 16:04:37 +00:00
|
|
|
{
|
2017-08-03 13:23:28 +00:00
|
|
|
return &rand_meth;
|
2017-06-27 16:04:37 +00:00
|
|
|
}
|