1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012- OpenVPN Inc.
//
// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//
// Wrap the mbed TLS Cryptographic Random API defined in <mbedtls/ctr_drbg.h>
// so that it can be used as the primary source of cryptographic entropy by
// the OpenVPN core.
#ifndef OPENVPN_MBEDTLS_UTIL_RAND_H
#define OPENVPN_MBEDTLS_UTIL_RAND_H
#include <mbedtls/entropy.h>
#if MBEDTLS_VERSION_NUMBER < 0x03000000
#include <mbedtls/entropy_poll.h>
#endif
#include <mbedtls/ctr_drbg.h>
#include <openvpn/random/randapi.hpp>
#include <openvpn/mbedtls/util/error.hpp>
namespace openvpn {
class MbedTLSRandom : public StrongRandomAPI
{
public:
OPENVPN_EXCEPTION(rand_error_mbedtls);
typedef RCPtr<MbedTLSRandom> Ptr;
MbedTLSRandom(StrongRandomAPI::Ptr entropy_source)
: entropy(std::move(entropy_source))
{
// Init RNG context
mbedtls_ctr_drbg_init(&ctx);
// Seed RNG
const int errnum = mbedtls_ctr_drbg_seed(&ctx, entropy_poll, entropy.get(), nullptr, 0);
if (errnum < 0)
throw MbedTLSException("mbedtls_ctr_drbg_seed", errnum);
}
MbedTLSRandom()
: MbedTLSRandom(StrongRandomAPI::Ptr())
{
}
virtual ~MbedTLSRandom()
{
// Free RNG context
mbedtls_ctr_drbg_free(&ctx);
}
// Random algorithm name
std::string name() const override
{
const std::string n = "mbedTLS-CTR_DRBG";
if (entropy)
return n + '+' + entropy->name();
else
return n;
}
// Fill buffer with random bytes
void rand_bytes(unsigned char *buf, size_t size) override
{
const int errnum = rndbytes(buf, size);
if (errnum < 0)
throw MbedTLSException("mbedtls_ctr_drbg_random", errnum);
}
// Like rand_bytes, but don't throw exception.
// Return true on successs, false on fail.
bool rand_bytes_noexcept(unsigned char *buf, size_t size) override
{
return rndbytes(buf, size) >= 0;
}
/**
* function to get the mbedtls_ctr_drbg_context. This is needed for the pk_parse
* methods in mbed TLS 3.0 that require a random number generator to avoid side
* channel attacks when loading private keys. The returned context is tied
* to the internal state of this random number generator.
*/
mbedtls_ctr_drbg_context *get_ctr_drbg_ctx()
{
return &ctx;
}
private:
int rndbytes(unsigned char *buf, size_t size)
{
return mbedtls_ctr_drbg_random(&ctx, buf, size);
}
static int entropy_poll(void *arg, unsigned char *output, size_t len)
{
if (arg)
{
RandomAPI *entropy = (RandomAPI *)arg;
if (entropy->rand_bytes_noexcept(output, len))
return 0;
else
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
else
{
#ifndef OPENVPN_DISABLE_MBEDTLS_PLATFORM_ENTROPY_POLL
size_t olen;
return mbedtls_platform_entropy_poll(nullptr, output, len, &olen);
#else
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
#endif
}
}
mbedtls_ctr_drbg_context ctx;
RandomAPI::Ptr entropy;
};
} // namespace openvpn
#endif
|