Beispiel #1
0
/*
 * Implements the get_entropy() callback (see RAND_DRBG_set_callbacks())
 *
 * If the DRBG has a parent, then the required amount of entropy input
 * is fetched using the parent's RAND_DRBG_generate().
 *
 * Otherwise, the entropy is polled from the system entropy sources
 * using RAND_POOL_acquire_entropy().
 *
 * If a random pool has been added to the DRBG using RAND_add(), then
 * its entropy will be used up first.
 */
size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
                        unsigned char **pout,
                        int entropy, size_t min_len, size_t max_len)
{
    size_t ret = 0;
    size_t entropy_available = 0;
    RAND_POOL *pool = RAND_POOL_new(entropy, min_len, max_len);

    if (pool == NULL)
        return 0;

    if (drbg->pool) {
        RAND_POOL_add(pool,
                      RAND_POOL_buffer(drbg->pool),
                      RAND_POOL_length(drbg->pool),
                      RAND_POOL_entropy(drbg->pool));
        RAND_POOL_free(drbg->pool);
        drbg->pool = NULL;
    }

    if (drbg->parent) {
        size_t bytes_needed = RAND_POOL_bytes_needed(pool, 8);
        unsigned char *buffer = RAND_POOL_add_begin(pool, bytes_needed);

        if (buffer != NULL) {
            size_t bytes = 0;

            /*
             * Get random from parent, include our state as additional input.
             * Our lock is already held, but we need to lock our parent before
             * generating bits from it.
             */
            if (drbg->parent->lock)
                CRYPTO_THREAD_write_lock(drbg->parent->lock);
            if (RAND_DRBG_generate(drbg->parent,
                                   buffer, bytes_needed,
                                   0,
                                   (unsigned char *)drbg, sizeof(*drbg)) != 0)
                bytes = bytes_needed;
            if (drbg->parent->lock)
                CRYPTO_THREAD_unlock(drbg->parent->lock);

            entropy_available = RAND_POOL_add_end(pool, bytes, 8 * bytes);
        }

    } else {
        /* Get entropy by polling system entropy sources. */
        entropy_available = RAND_POOL_acquire_entropy(pool);
    }

    if (entropy_available > 0) {
        ret   = RAND_POOL_length(pool);
        *pout = RAND_POOL_detach(pool);
    }

    RAND_POOL_free(pool);
    return ret;
}
Beispiel #2
0
/*
 * Generate additional data that can be used for the drbg. The data does
 * not need to contain entropy, but it's useful if it contains at least
 * some bits that are unpredictable.
 *
 * Returns 0 on failure.
 *
 * On success it allocates a buffer at |*pout| and returns the length of
 * the data. The buffer should get freed using OPENSSL_secure_clear_free().
 */
size_t rand_drbg_get_additional_data(unsigned char **pout, size_t max_len)
{
    RAND_POOL *pool;
    CRYPTO_THREAD_ID thread_id;
    size_t len;
#ifdef OPENSSL_SYS_UNIX
    pid_t pid;
#elif defined(OPENSSL_SYS_WIN32)
    DWORD pid;
#endif
    uint64_t tbits;

    pool = RAND_POOL_new(0, 0, max_len);
    if (pool == NULL)
        return 0;

#ifdef OPENSSL_SYS_UNIX
    pid = getpid();
    RAND_POOL_add(pool, (unsigned char *)&pid, sizeof(pid), 0);
#elif defined(OPENSSL_SYS_WIN32)
    pid = GetCurrentProcessId();
    RAND_POOL_add(pool, (unsigned char *)&pid, sizeof(pid), 0);
#endif

    thread_id = CRYPTO_THREAD_get_current_id();
    if (thread_id != 0)
        RAND_POOL_add(pool, (unsigned char *)&thread_id, sizeof(thread_id), 0);

    tbits = get_timer_bits();
    if (tbits != 0)
        RAND_POOL_add(pool, (unsigned char *)&tbits, sizeof(tbits), 0);

    /* TODO: Use RDSEED? */

    len = RAND_POOL_length(pool);
    if (len != 0)
        *pout = RAND_POOL_detach(pool);
    RAND_POOL_free(pool);

    return len;
}