Commit a73d990e authored by Dr. Matthias St. Pierre's avatar Dr. Matthias St. Pierre
Browse files

Add documentation for the RAND_DRBG API



The RAND_DRBG API was added in PR #5462 and modified by PR #5547.
This commit adds the corresponding documention.

Reviewed-by: default avatarKurt Roeckx <kurt@roeckx.be>
Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5461)
parent 3484236d
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -9,6 +9,10 @@
 Changes between 1.1.0g and 1.1.1 [xx XXX xxxx]
  *) Added new public header file <openssl/rand_drbg.h> and documentation
     for the RAND_DRBG API. See manual page RAND_DRBG(7) for an overview.
     [Matthias St. Pierre]
  *) QNX support removed (cannot find contributors to get their approval
     for the license change).
     [Rich Salz]
+48 −9
Original line number Diff line number Diff line

 OPENSSL INSTALLATION
 --------------------

@@ -215,6 +214,34 @@
                   then "GNV$LIBZSHR", "GNV$LIBZSHR32" or "GNV$LIBZSHR64" is
                   used by default depending on the pointer size chosen.


  --with-rand-seed=seed1[,seed2,...]
                   A comma separated list of seeding methods which will be tried
                   by OpenSSL in order to obtain random input (a.k.a "entropy")
                   for seeding its cryptographically secure random number
                   generator (CSPRNG). The current seeding methods are:

                   os:         Use a trusted operating system entropy source.
                               This is the default method if such an entropy
                               source exists.
                   getrandom:  Use the L<getrandom(2)> system call if available.
                   devrandom:  Use the the first device from the DEVRANDOM list
                               which can be opened to read random bytes. The
                               DEVRANDOM preprocessor constant expands to
                               "/dev/urandom","/dev/random","/dev/srandom" on
                               most unix-ish operating systems.
                   egd:        Check for an entropy generating daemon.
                   rdcpu:      Use the RDSEED or RDRAND command if provided by
                               the CPU.
                   librandom:  Use librandom (not implemented yet).
                   none:       Disable automatic seeding. This is the default
                               on some operating systems where no suitable
                               entropy source exists, or no support for it is
                               implemented yet.

                   For more information, see the section 'Note on random number
                   generation' at the end of this document.

  no-afalgeng
                   Don't build the AFALG engine. This option will be forced if
                   on a platform that does not support AFALG.
@@ -1164,10 +1191,22 @@

 Availability of cryptographically secure random numbers is required for
 secret key generation. OpenSSL provides several options to seed the
 internal PRNG. If not properly seeded, the internal PRNG will refuse
 internal CSPRNG. If not properly seeded, the internal CSPRNG will refuse
 to deliver random bytes and a "PRNG not seeded error" will occur.
 On systems without /dev/urandom (or similar) device, it may be necessary
 to install additional support software to obtain a random seed.
 Please check out the manual pages for RAND_add(), RAND_bytes(), RAND_egd(),
 and the FAQ for more information.

 The seeding method can be configured using the --with-rand-seed option,
 which can be used to specify a comma separated list of seed methods.
 However in most cases OpenSSL will choose a suitable default method,
 so it is not necessary to explicitely provide this option. Note also
 that not all methods are available on all platforms.

 I) On operating systems which provide a suitable randomness source (in
 form  of a system call or system device), OpenSSL will use the optimal
 available  method to seed the CSPRNG from the operating system's
 randomness sources. This corresponds to the option --with-rand-seed=os.

 II) On systems without such a suitable randomness source, automatic seeding
 and reseeding is disabled (--with-rand-seed=none) and it may be necessary
 to install additional support software to obtain a random seed and reseed
 the CSPRNG manually.  Please check out the manual pages for RAND_add(),
 RAND_bytes(), RAND_egd(), and the FAQ for more information.
+47 −110
Original line number Diff line number Diff line
@@ -17,8 +17,9 @@
#include "internal/cryptlib_int.h"

/*
 * Support framework for NIST SP 800-90A DRBG, AES-CTR mode.
 * The RAND_DRBG is OpenSSL's pointer to an instance of the DRBG.
 * Support framework for NIST SP 800-90A DRBG
 *
 * See manual page RAND_DRBG(7) for a general overview.
 *
 * The OpenSSL model is to have new and free functions, and that new
 * does all initialization.  That is not the NIST model, which has
@@ -29,80 +30,46 @@
 */

/*
 * THE THREE SHARED DRBGs
 *
 * There are three shared DRBGs (master, public and private), which are
 * accessed concurrently by all threads.
 * The three shared DRBG instances
 *
 * THE MASTER DRBG
 * There are three shared DRBG instances: <master>, <public>, and <private>.
 */

/*
 * 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()
 */
static RAND_DRBG *drbg_master;
/*+
 * 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.
 * sources or by consuming randomness which was added by RAND_add().
 *
 * 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
 *
 * 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.
 *
 * MANUAL RESEEDING
 * The <master> DRBG is a global instance which is accessed concurrently by
 * all threads. The necessary locking is managed automatically by its child
 * DRBG instances during reseeding.
 */
static RAND_DRBG *master_drbg;
/*
 * The <public> DRBG
 *
 * 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
 * |randomness| argument). This will immediately reseed the <master> DRBG.
 * The <public> and <private> DRBG will detect this on their next generate
 * call and reseed, pulling randomness from <master>.
 * Used by default for generating random bytes using RAND_bytes().
 *
 * LOCKING
 * The <public> DRBG is thread-local, i.e., there is one instance per thread.
 */
static CRYPTO_THREAD_LOCAL public_drbg;
/*
 * The <private> DRBG
 *
 * The three shared DRBGs are intended to be used concurrently, so they
 * support locking. The RAND methods take the locks automatically, so using
 * the RAND api (in particular RAND_bytes() and RAND_priv_bytes()) is
 * thread-safe. Note however that accessing the shared DRBGs directly via
 * the RAND_DRBG interface is *not* thread-safe.
 * Used by default for generating private keys using RAND_priv_bytes()
 *
 * All other DRBG instances don't support locking, because they are
 * intendended to be used by a single thread. Instead of accessing a single
 * DRBG instance concurrently from different threads, it is recommended to
 * instantiate a separate DRBG instance per thread. Using the same shared
 * DRBG (preferrably the public DRBG) as parent of DRBG instances on
 * different threads is safe.
 * The <private> DRBG is thread-local, i.e., there is one instance per thread.
 */
static CRYPTO_THREAD_LOCAL private_drbg;



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

static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT;
static CRYPTO_THREAD_LOCAL private_drbg_thread_local_key;
static CRYPTO_THREAD_LOCAL public_drbg_thread_local_key;



@@ -683,40 +650,10 @@ err:
/*
 * 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.
 * Setting the callbacks is allowed only if the drbg has not been
 * initialized yet. Otherwise, the operation will fail.
 *
 * 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.
 * Returns 1 on success, 0 on failure.
 */
int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
                            RAND_DRBG_get_entropy_fn get_entropy,
@@ -936,12 +873,12 @@ DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init)

    ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND);

    drbg_master = drbg_setup(NULL);
    master_drbg = drbg_setup(NULL);

    ret &= CRYPTO_THREAD_init_local(&private_drbg_thread_local_key, NULL);
    ret &= CRYPTO_THREAD_init_local(&public_drbg_thread_local_key, NULL);
    ret &= CRYPTO_THREAD_init_local(&private_drbg, NULL);
    ret &= CRYPTO_THREAD_init_local(&public_drbg, NULL);

    if (drbg_master == NULL || ret == 0)
    if (master_drbg == NULL || ret == 0)
        return 0;

    return 1;
@@ -950,21 +887,21 @@ DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init)
/* Clean up the global DRBGs before exit */
void rand_drbg_cleanup_int(void)
{
    RAND_DRBG_free(drbg_master);
    drbg_master = NULL;
    RAND_DRBG_free(master_drbg);
    master_drbg = NULL;

    CRYPTO_THREAD_cleanup_local(&private_drbg_thread_local_key);
    CRYPTO_THREAD_cleanup_local(&public_drbg_thread_local_key);
    CRYPTO_THREAD_cleanup_local(&private_drbg);
    CRYPTO_THREAD_cleanup_local(&public_drbg);
}

void drbg_delete_thread_state()
{
    RAND_DRBG *drbg;

    drbg = CRYPTO_THREAD_get_local(&public_drbg_thread_local_key);
    drbg = CRYPTO_THREAD_get_local(&public_drbg);
    RAND_DRBG_free(drbg);

    drbg = CRYPTO_THREAD_get_local(&private_drbg_thread_local_key);
    drbg = CRYPTO_THREAD_get_local(&private_drbg);
    RAND_DRBG_free(drbg);
}

@@ -1044,7 +981,7 @@ RAND_DRBG *RAND_DRBG_get0_master(void)
    if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
        return NULL;

    return drbg_master;
    return master_drbg;
}

/*
@@ -1058,11 +995,11 @@ RAND_DRBG *RAND_DRBG_get0_public(void)
    if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
        return NULL;

    drbg = CRYPTO_THREAD_get_local(&public_drbg_thread_local_key);
    drbg = CRYPTO_THREAD_get_local(&public_drbg);
    if (drbg == NULL) {
        ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND);
        drbg = drbg_setup(drbg_master);
        CRYPTO_THREAD_set_local(&public_drbg_thread_local_key, drbg);
        drbg = drbg_setup(master_drbg);
        CRYPTO_THREAD_set_local(&public_drbg, drbg);
    }
    return drbg;
}
@@ -1078,11 +1015,11 @@ RAND_DRBG *RAND_DRBG_get0_private(void)
    if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
        return NULL;

    drbg = CRYPTO_THREAD_get_local(&private_drbg_thread_local_key);
    drbg = CRYPTO_THREAD_get_local(&private_drbg);
    if (drbg == NULL) {
        ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND);
        drbg = drbg_setup(drbg_master);
        CRYPTO_THREAD_set_local(&private_drbg_thread_local_key, drbg);
        drbg = drbg_setup(master_drbg);
        CRYPTO_THREAD_set_local(&private_drbg, drbg);
    }
    return drbg;
}
+11 −9
Original line number Diff line number Diff line
@@ -40,20 +40,22 @@ Several OpenSSL structures can have application-specific data attached to them,
known as "exdata."
The specific structures are:

    SSL
    SSL_CTX
    SSL_SESSION
    X509
    X509_STORE
    X509_STORE_CTX
    APP
    BIO
    DH
    DRBG
    DSA
    EC_KEY
    RSA
    ENGINE
    RSA
    SSL
    SSL_CTX
    SSL_SESSION
    UI
    UI_METHOD
    BIO
    X509
    X509_STORE
    X509_STORE_CTX

Each is identified by an B<CRYPTO_EX_INDEX_xxx> define in the B<crypto.h>
header file.  In addition, B<CRYPTO_EX_INDEX_APP> is reserved for
@@ -155,7 +157,7 @@ dup_func() should return 0 for failure and 1 for success.

=head1 COPYRIGHT

Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2015-2018 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
+88 −0
Original line number Diff line number Diff line
=pod

=head1 NAME

RAND_DRBG_generate,
RAND_DRBG_bytes
- generate random bytes using the given drbg instance

=head1 SYNOPSIS

 #include <openssl/rand_drbg.h>

 int RAND_DRBG_generate(RAND_DRBG *drbg,
                        unsigned char *out, size_t outlen,
                        int prediction_resistance,
                        const unsigned char *adin, size_t adinlen);

 int RAND_DRBG_bytes(RAND_DRBG *drbg,
                     unsigned char *out, size_t outlen);


=head1 DESCRIPTION

RAND_DRBG_generate() generates B<outlen> random bytes using the given
DRBG instance B<drbg> and stores them in the buffer at B<out>.

Before generating the output, the DRBG instance checks whether the maximum
number of generate requests (I<reseed interval>) or the maximum timespan
(I<reseed time interval>) since its last seeding have been reached.
If this is the case, the DRBG reseeds automatically.
Additionally, an immediate reseeding can be requested by setting the
B<prediction_resistance> flag to 1. See NOTES section for more details.

The caller can optionally provide additional data to be used for reseeding
by passing a pointer B<adin> to a buffer of length B<adinlen>.
This additional data is mixed into the internal state of the random
generator but does not contribute to the entropy count.
The additional data can be omitted by setting B<adin> to NULL and
B<adinlen> to 0;

RAND_DRBG_bytes() generates B<outlen> random bytes using the given
DRBG instance B<drbg> and stores them in the buffer at B<out>.
This function is a wrapper around the RAND_DRBG_generate() call,
which collects some additional data from low entropy sources
(e.g., a high resolution timer) and calls
RAND_DRBG_generate(drbg, out, outlen, 0, adin, adinlen).


=head1 RETURN VALUES

RAND_DRBG_generate() and RAND_DRBG_bytes() return 1 on success,
and 0 on failure.

=head1 NOTES

The I<reseed interval> and I<reseed time interval> of the B<drbg> are set to
reasonable default values, which in general do not have to be adjusted.
If necessary, they can be changed using L<RAND_DRBG_set_reseed_interval(3)>
and L<RAND_DRBG_set_reseed_time_interval(3)>, respectively.

A request for prediction resistance can only be satisfied by pulling fresh
entropy from one of the approved entropy sources listed in section 5.5.2 of
[NIST SP 800-90C].
Since the default DRBG implementation does not have access to such an approved
entropy source, a request for prediction resistance will always fail.
In other words, prediction resistance is currently not supported yet by the DRBG.

=head1 HISTORY

The RAND_DRBG functions were added in OpenSSL 1.1.1.

=head1 SEE ALSO

L<RAND_bytes(3)>,
L<RAND_DRBG_set_reseed_interval(3)>,
L<RAND_DRBG_set_reseed_time_interval(3)>,
L<RAND_DRBG(7)>

=head1 COPYRIGHT

Copyright 2017-2018 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
L<https://www.openssl.org/source/license.html>.

=cut
Loading