File: rand.hpp

package info (click to toggle)
openvpn3-client 25%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,276 kB
  • sloc: cpp: 190,085; python: 7,218; ansic: 1,866; sh: 1,361; java: 402; lisp: 81; makefile: 17
file content (130 lines) | stat: -rw-r--r-- 3,576 bytes parent folder | download
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