godot/thirdparty/mbedtls/library/entropy.c

/*
 *  Entropy accumulator implementation
 *
 *  Copyright The Mbed TLS Contributors
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 */

#include "common.h"

#if defined(MBEDTLS_ENTROPY_C)

#include "mbedtls/entropy.h"
#include "entropy_poll.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"

#include <string.h>

#if defined(MBEDTLS_FS_IO)
#include <stdio.h>
#endif

#include "mbedtls/platform.h"

#define ENTROPY_MAX_LOOP

void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
{}

void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
{}

int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,
                               mbedtls_entropy_f_source_ptr f_source, void *p_source,
                               size_t threshold, int strong)
{}

/*
 * Entropy accumulator update
 */
static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,
                          const unsigned char *data, size_t len)
{}

int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,
                                  const unsigned char *data, size_t len)
{}

/*
 * Run through the different sources to add entropy to our accumulator
 */
static int entropy_gather_internal(mbedtls_entropy_context *ctx)
{}

/*
 * Thread-safe wrapper for entropy_gather_internal()
 */
int mbedtls_entropy_gather(mbedtls_entropy_context *ctx)
{}

int mbedtls_entropy_func(void *data, unsigned char *output, size_t len)
{}

#if defined(MBEDTLS_ENTROPY_NV_SEED)
int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx)
{
    int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
    unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];

    /* Read new seed  and write it to NV */
    if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
        return ret;
    }

    if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {
        return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
    }

    /* Manually update the remaining stream with a separator value to diverge */
    memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
    ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);

    return ret;
}
#endif /* MBEDTLS_ENTROPY_NV_SEED */

#if defined(MBEDTLS_FS_IO)
int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path)
{}

int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path)
{}
#endif /* MBEDTLS_FS_IO */

#if defined(MBEDTLS_SELF_TEST)
/*
 * Dummy source function
 */
static int entropy_dummy_source(void *data, unsigned char *output,
                                size_t len, size_t *olen)
{}

#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)

static int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len)
{
    int ret = 0;
    size_t entropy_len = 0;
    size_t olen = 0;
    size_t attempts = buf_len;

    while (attempts > 0 && entropy_len < buf_len) {
        if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len,
                                         buf_len - entropy_len, &olen)) != 0) {
            return ret;
        }

        entropy_len += olen;
        attempts--;
    }

    if (entropy_len < buf_len) {
        ret = 1;
    }

    return ret;
}


static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf,
                                                       size_t buf_len)
{
    unsigned char set = 0xFF;
    unsigned char unset = 0x00;
    size_t i;

    for (i = 0; i < buf_len; i++) {
        set &= buf[i];
        unset |= buf[i];
    }

    return set == 0xFF || unset == 0x00;
}

/*
 * A test to ensure that the entropy sources are functioning correctly
 * and there is no obvious failure. The test performs the following checks:
 *  - The entropy source is not providing only 0s (all bits unset) or 1s (all
 *    bits set).
 *  - The entropy source is not providing values in a pattern. Because the
 *    hardware could be providing data in an arbitrary length, this check polls
 *    the hardware entropy source twice and compares the result to ensure they
 *    are not equal.
 *  - The error code returned by the entropy source is not an error.
 */
int mbedtls_entropy_source_self_test(int verbose)
{
    int ret = 0;
    unsigned char buf0[2 * sizeof(unsigned long long int)];
    unsigned char buf1[2 * sizeof(unsigned long long int)];

    if (verbose != 0) {
        mbedtls_printf("  ENTROPY_BIAS test: ");
    }

    memset(buf0, 0x00, sizeof(buf0));
    memset(buf1, 0x00, sizeof(buf1));

    if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) {
        goto cleanup;
    }
    if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) {
        goto cleanup;
    }

    /* Make sure that the returned values are not all 0 or 1 */
    if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0, sizeof(buf0))) != 0) {
        goto cleanup;
    }
    if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) {
        goto cleanup;
    }

    /* Make sure that the entropy source is not returning values in a
     * pattern */
    ret = memcmp(buf0, buf1, sizeof(buf0)) == 0;

cleanup:
    if (verbose != 0) {
        if (ret != 0) {
            mbedtls_printf("failed\n");
        } else {
            mbedtls_printf("passed\n");
        }

        mbedtls_printf("\n");
    }

    return ret != 0;
}

#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */

/*
 * The actual entropy quality is hard to test, but we can at least
 * test that the functions don't cause errors and write the correct
 * amount of data to buffers.
 */
int mbedtls_entropy_self_test(int verbose)
{}
#endif /* MBEDTLS_SELF_TEST */

#endif /* MBEDTLS_ENTROPY_C */