-
Notifications
You must be signed in to change notification settings - Fork 570
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Entropy Source and DRNG Manager (ESDM) RNG support
ESDM is a Linux-based user-space PRNG daemon, with configurable entropy sources. See: https://github.com/smuellerDD/esdm It currently gets used, when a high level of control over entropy sources is desirable, e.g. for VPN appliance solutions. In order to use this source, the ESDM server daemon has to be running and botan must be configured --with-esdm. ESDM currently works only on Linux. Signed-off-by: Markus Theil <[email protected]>
- Loading branch information
Showing
13 changed files
with
308 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* ESDM RNG | ||
* (C) 2024, Markus Theil <[email protected]> | ||
* | ||
* Botan is released under the Simplified BSD License (see license.txt) | ||
*/ | ||
|
||
#include <botan/esdm_rng.h> | ||
|
||
#include <esdm/esdm_rpc_client.h> | ||
|
||
namespace Botan { | ||
|
||
namespace { | ||
/** | ||
* This helper makes sure that the ESDM service is initialized and | ||
* finalized as needed in a threadsafe fashion. Finalization happens | ||
* as soon as all instances of ESDM_RNG are destructed. This may | ||
* happen multiple times in the lifetime of the process. | ||
*/ | ||
class ESDM_Context { | ||
public: | ||
[[nodiscard]] static std::shared_ptr<void> instance() { | ||
static ESDM_Context g_instance; | ||
return g_instance.acquire(); | ||
} | ||
|
||
private: | ||
ESDM_Context() = default; | ||
|
||
[[nodiscard]] std::shared_ptr<void> acquire() { | ||
std::scoped_lock lk(m_mutex); | ||
if(m_refs++ == 0) { | ||
if(esdm_rpcc_init_unpriv_service(nullptr) != 0) { | ||
throw Botan::System_Error("unable to initialize ESDM unprivileged service"); | ||
} | ||
} | ||
return std::shared_ptr<void>{nullptr, [this](void*) { this->release(); }}; | ||
} | ||
|
||
void release() { | ||
std::scoped_lock lk(m_mutex); | ||
if(m_refs-- == 1) { | ||
esdm_rpcc_fini_unpriv_service(); | ||
} | ||
} | ||
|
||
private: | ||
std::mutex m_mutex; | ||
size_t m_refs = 0; | ||
}; | ||
} // namespace | ||
|
||
ESDM_RNG::ESDM_RNG(bool prediction_resistance) : | ||
m_prediction_resistance(prediction_resistance), m_ctx(ESDM_Context::instance()) {} | ||
|
||
void ESDM_RNG::fill_bytes_with_input(std::span<uint8_t> out, std::span<const uint8_t> in) { | ||
if(!in.empty()) { | ||
ssize_t ret = 0; | ||
/* | ||
* take additional input, but do not account entropy for it, | ||
* as this information is not included in the API | ||
*/ | ||
esdm_invoke(esdm_rpcc_write_data(in.data(), in.size())); | ||
if(ret != 0) { | ||
throw Botan::System_Error("Writing additional input to ESDM failed"); | ||
} | ||
} | ||
if(!out.empty()) { | ||
ssize_t ret = 0; | ||
if(m_prediction_resistance) { | ||
esdm_invoke(esdm_rpcc_get_random_bytes_pr(out.data(), out.size())); | ||
} else { | ||
esdm_invoke(esdm_rpcc_get_random_bytes_full(out.data(), out.size())); | ||
} | ||
if(ret != static_cast<ssize_t>(out.size())) { | ||
throw Botan::System_Error("Fetching random bytes from ESDM failed"); | ||
} | ||
} | ||
} | ||
|
||
RandomNumberGenerator& esdm_rng() { | ||
static ESDM_RNG g_esdm_rng; | ||
return g_esdm_rng; | ||
} | ||
|
||
} // namespace Botan |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* | ||
* ESDM RNG | ||
* (C) 2024, Markus Theil <[email protected]> | ||
* | ||
* Botan is released under the Simplified BSD License (see license.txt) | ||
*/ | ||
|
||
#ifndef BOTAN_ESDM_RNG_H_ | ||
#define BOTAN_ESDM_RNG_H_ | ||
|
||
#include <botan/rng.h> | ||
#include <memory> | ||
|
||
namespace Botan { | ||
|
||
/** | ||
* Return a shared reference to a global PRNG instance provided by ESDM | ||
*/ | ||
BOTAN_PUBLIC_API(3, 6) RandomNumberGenerator& esdm_rng(); | ||
|
||
/** | ||
* Entropy Source and DRNG Manager (ESDM) is a Linux/Unix based | ||
* PRNG manager, which can be seeded from NTG.1/SP800-90B sources. | ||
* | ||
* See: | ||
* - Repository: https://github.com/smuellerDD/esdm | ||
* - Further Docs: https://www.chronox.de/esdm/index.html | ||
* | ||
* Different entropy sources can be configured in respect of beeing | ||
* active and how much entropy is accounted for each of them. | ||
* | ||
* ESDM tracks its seed and reseed status and blocks, when not fully seeded. | ||
* For this functionality, the esdm_rpcc_get_random_bytes_pr (prediction resistant) or | ||
* esdm_rpcc_get_random_bytes_full (fully seeded) calls have to be used. | ||
* | ||
* Configurable modes: | ||
* - fully seeded (-> fast): provide entropy from a DRBG/PRNG after beeing fully seeded, | ||
* block until this point is reached, reseed from after a time | ||
* and/or invocation limit, block again if reseeding is not possible | ||
* - prediction resistance (-> slow): reseed ESDM with fresh entropy after each invocation | ||
* | ||
* You typically want to use the fast fully seeded mode, which is the default. | ||
* | ||
* Instances of this class communicate over RPC with ESDM. The esdm_rpc_client | ||
* library, provided by ESDM, is leveraged for this. | ||
* | ||
* Thread safety: | ||
* It is fine to construct, destruct and use objects of this class concurrently. | ||
* The communication with ESDM is thread-safe, as handled by esdm_rpc_client. | ||
* The initialization of esdm_rpc_client is not thread safe, therefore this class | ||
* takes care of it, with its embedded ESDM_Context. | ||
*/ | ||
class BOTAN_PUBLIC_API(3, 6) ESDM_RNG final : public Botan::RandomNumberGenerator { | ||
public: | ||
/** | ||
* Default constructor for ESDM, fully seeded mode | ||
*/ | ||
ESDM_RNG() : ESDM_RNG(false) {} | ||
|
||
/** | ||
* Construct ESDM instance with configurable mode | ||
*/ | ||
explicit ESDM_RNG(bool prediction_resistance); | ||
|
||
std::string name() const override { | ||
if(m_prediction_resistance) { | ||
return "esdm-pr"; | ||
} else { | ||
return "esdm-full"; | ||
} | ||
} | ||
|
||
/** | ||
* ESDM blocks, if it is not seeded, | ||
* | ||
* @return true | ||
*/ | ||
bool is_seeded() const override { return true; } | ||
|
||
/** | ||
* ESDM can inject additional inputs | ||
* but we do not account entropy for it | ||
* | ||
* @return true | ||
*/ | ||
bool accepts_input() const override { return true; } | ||
|
||
/** | ||
* the ESDM RNG does not hold any state outside ESDM, that should be cleared | ||
* here | ||
*/ | ||
void clear() override {} | ||
|
||
protected: | ||
void fill_bytes_with_input(std::span<uint8_t> out, std::span<const uint8_t> in) override; | ||
|
||
private: | ||
/** | ||
* tracks if predicition resistant or fully seeded interface should be queried | ||
*/ | ||
bool m_prediction_resistance; | ||
|
||
/** | ||
* takes care of thread-safe esdm_rpc_client initialization | ||
*/ | ||
std::shared_ptr<void> m_ctx; | ||
}; | ||
|
||
} // namespace Botan | ||
|
||
#endif /* BOTAN_ESDM_RNG_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<defines> | ||
ESDM_RNG -> 20240814 | ||
</defines> | ||
|
||
<module_info> | ||
name -> "ESDM RNG" | ||
brief -> "RNG based on ESDM - Entropy Source and DRNG Manager" | ||
</module_info> | ||
|
||
load_on vendor | ||
|
||
<header:public> | ||
esdm_rng.h | ||
</header:public> | ||
|
||
<libs> | ||
linux -> esdm_rpc_client | ||
</libs> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.