Skip to content

Commit c112b4b

Browse files
authored
src: start using ncrypto for CSPRNG calls
PR-URL: #53984 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Ethan Arrowood <ethan@arrowood.dev> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
1 parent cf2bce6 commit c112b4b

12 files changed

+29
-67
lines changed

src/crypto/crypto_context.cc

+4-4
Original file line numberDiff line numberDiff line change
@@ -547,9 +547,9 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
547547
// OpenSSL 1.1.0 changed the ticket key size, but the OpenSSL 1.0.x size was
548548
// exposed in the public API. To retain compatibility, install a callback
549549
// which restores the old algorithm.
550-
if (CSPRNG(sc->ticket_key_name_, sizeof(sc->ticket_key_name_)).is_err() ||
551-
CSPRNG(sc->ticket_key_hmac_, sizeof(sc->ticket_key_hmac_)).is_err() ||
552-
CSPRNG(sc->ticket_key_aes_, sizeof(sc->ticket_key_aes_)).is_err()) {
550+
if (!ncrypto::CSPRNG(sc->ticket_key_name_, sizeof(sc->ticket_key_name_)) ||
551+
!ncrypto::CSPRNG(sc->ticket_key_hmac_, sizeof(sc->ticket_key_hmac_)) ||
552+
!ncrypto::CSPRNG(sc->ticket_key_aes_, sizeof(sc->ticket_key_aes_))) {
553553
return THROW_ERR_CRYPTO_OPERATION_FAILED(
554554
env, "Error generating ticket keys");
555555
}
@@ -1324,7 +1324,7 @@ int SecureContext::TicketCompatibilityCallback(SSL* ssl,
13241324

13251325
if (enc) {
13261326
memcpy(name, sc->ticket_key_name_, sizeof(sc->ticket_key_name_));
1327-
if (CSPRNG(iv, 16).is_err() ||
1327+
if (!ncrypto::CSPRNG(iv, 16) ||
13281328
EVP_EncryptInit_ex(
13291329
ectx, EVP_aes_128_cbc(), nullptr, sc->ticket_key_aes_, iv) <= 0 ||
13301330
HMAC_Init_ex(hctx,

src/crypto/crypto_keygen.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "debug_utils-inl.h"
55
#include "env-inl.h"
66
#include "memory_tracker-inl.h"
7+
#include "ncrypto.h"
78
#include "threadpoolwork-inl.h"
89
#include "v8.h"
910

@@ -71,7 +72,7 @@ Maybe<bool> SecretKeyGenTraits::AdditionalConfig(
7172
KeyGenJobStatus SecretKeyGenTraits::DoKeyGen(Environment* env,
7273
SecretKeyGenConfig* params) {
7374
ByteSource::Builder bytes(params->length);
74-
if (CSPRNG(bytes.data<unsigned char>(), params->length).is_err())
75+
if (!ncrypto::CSPRNG(bytes.data<unsigned char>(), params->length))
7576
return KeyGenJobStatus::FAILED;
7677
params->out = std::move(bytes).release();
7778
return KeyGenJobStatus::OK;

src/crypto/crypto_random.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "crypto/crypto_util.h"
44
#include "env-inl.h"
55
#include "memory_tracker-inl.h"
6+
#include "ncrypto.h"
67
#include "threadpoolwork-inl.h"
78
#include "v8.h"
89

@@ -60,7 +61,7 @@ bool RandomBytesTraits::DeriveBits(
6061
Environment* env,
6162
const RandomBytesConfig& params,
6263
ByteSource* unused) {
63-
return CSPRNG(params.buffer, params.size).is_ok();
64+
return ncrypto::CSPRNG(params.buffer, params.size);
6465
}
6566

6667
void RandomPrimeConfig::MemoryInfo(MemoryTracker* tracker) const {
@@ -154,7 +155,7 @@ bool RandomPrimeTraits::DeriveBits(Environment* env,
154155
ByteSource* unused) {
155156
// BN_generate_prime_ex() calls RAND_bytes_ex() internally.
156157
// Make sure the CSPRNG is properly seeded.
157-
CHECK(CSPRNG(nullptr, 0).is_ok());
158+
CHECK(ncrypto::CSPRNG(nullptr, 0));
158159

159160
if (BN_generate_prime_ex(
160161
params.prime.get(),

src/crypto/crypto_util.cc

-34
Original file line numberDiff line numberDiff line change
@@ -49,40 +49,6 @@ using v8::Value;
4949

5050
namespace crypto {
5151

52-
MUST_USE_RESULT CSPRNGResult CSPRNG(void* buffer, size_t length) {
53-
unsigned char* buf = static_cast<unsigned char*>(buffer);
54-
do {
55-
if (1 == RAND_status()) {
56-
#if OPENSSL_VERSION_MAJOR >= 3
57-
if (1 == RAND_bytes_ex(nullptr, buf, length, 0)) return {true};
58-
#else
59-
while (length > INT_MAX && 1 == RAND_bytes(buf, INT_MAX)) {
60-
buf += INT_MAX;
61-
length -= INT_MAX;
62-
}
63-
if (length <= INT_MAX && 1 == RAND_bytes(buf, static_cast<int>(length)))
64-
return {true};
65-
#endif
66-
}
67-
#if OPENSSL_VERSION_MAJOR >= 3
68-
const auto code = ERR_peek_last_error();
69-
// A misconfigured OpenSSL 3 installation may report 1 from RAND_poll()
70-
// and RAND_status() but fail in RAND_bytes() if it cannot look up
71-
// a matching algorithm for the CSPRNG.
72-
if (ERR_GET_LIB(code) == ERR_LIB_RAND) {
73-
const auto reason = ERR_GET_REASON(code);
74-
if (reason == RAND_R_ERROR_INSTANTIATING_DRBG ||
75-
reason == RAND_R_UNABLE_TO_FETCH_DRBG ||
76-
reason == RAND_R_UNABLE_TO_CREATE_DRBG) {
77-
return {false};
78-
}
79-
}
80-
#endif
81-
} while (1 == RAND_poll());
82-
83-
return {false};
84-
}
85-
8652
int PasswordCallback(char* buf, int size, int rwflag, void* u) {
8753
const ByteSource* passphrase = *static_cast<const ByteSource**>(u);
8854
if (passphrase != nullptr) {

src/crypto/crypto_util.h

-13
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,6 @@ void InitCrypto(v8::Local<v8::Object> target);
9191

9292
extern void UseExtraCaCerts(const std::string& file);
9393

94-
struct CSPRNGResult {
95-
const bool ok;
96-
MUST_USE_RESULT bool is_ok() const { return ok; }
97-
MUST_USE_RESULT bool is_err() const { return !ok; }
98-
};
99-
100-
// Either succeeds with exactly |length| bytes of cryptographically
101-
// strong pseudo-random data, or fails. This function may block.
102-
// Don't assume anything about the contents of |buffer| on error.
103-
// As a special case, |length == 0| can be used to check if the CSPRNG
104-
// is properly seeded without consuming entropy.
105-
MUST_USE_RESULT CSPRNGResult CSPRNG(void* buffer, size_t length);
106-
10794
int PasswordCallback(char* buf, int size, int rwflag, void* u);
10895

10996
int NoPasswordCallback(char* buf, int size, int rwflag, void* u);

src/inspector_io.cc

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
#include "inspector_io.h"
22

3-
#include "inspector_socket_server.h"
4-
#include "inspector/main_thread_interface.h"
5-
#include "inspector/node_string.h"
6-
#include "crypto/crypto_util.h"
73
#include "base_object-inl.h"
4+
#include "crypto/crypto_util.h"
85
#include "debug_utils-inl.h"
6+
#include "inspector/main_thread_interface.h"
7+
#include "inspector/node_string.h"
8+
#include "inspector_socket_server.h"
9+
#include "ncrypto.h"
910
#include "node.h"
1011
#include "node_internals.h"
1112
#include "node_mutex.h"
12-
#include "v8-inspector.h"
1313
#include "util-inl.h"
14+
#include "v8-inspector.h"
1415
#include "zlib.h"
1516

1617
#include <deque>
@@ -46,7 +47,7 @@ std::string ScriptPath(uv_loop_t* loop, const std::string& script_name) {
4647
// Used ver 4 - with numbers
4748
std::string GenerateID() {
4849
uint16_t buffer[8];
49-
CHECK(crypto::CSPRNG(buffer, sizeof(buffer)).is_ok());
50+
CHECK(ncrypto::CSPRNG(buffer, sizeof(buffer)));
5051

5152
char uuid[256];
5253
snprintf(uuid, sizeof(uuid), "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",

src/node.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "node_version.h"
4848

4949
#if HAVE_OPENSSL
50+
#include "ncrypto.h"
5051
#include "node_crypto.h"
5152
#endif
5253

@@ -1142,14 +1143,14 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
11421143
}
11431144

11441145
// Ensure CSPRNG is properly seeded.
1145-
CHECK(crypto::CSPRNG(nullptr, 0).is_ok());
1146+
CHECK(ncrypto::CSPRNG(nullptr, 0));
11461147

11471148
V8::SetEntropySource([](unsigned char* buffer, size_t length) {
11481149
// V8 falls back to very weak entropy when this function fails
11491150
// and /dev/urandom isn't available. That wouldn't be so bad if
11501151
// the entropy was only used for Math.random() but it's also used for
11511152
// hash table and address space layout randomization. Better to abort.
1152-
CHECK(crypto::CSPRNG(buffer, length).is_ok());
1153+
CHECK(ncrypto::CSPRNG(buffer, length));
11531154
return true;
11541155
});
11551156
#endif // !defined(OPENSSL_IS_BORINGSSL)

src/quic/cid.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <node_mutex.h>
66
#include <string_bytes.h>
77
#include "nbytes.h"
8+
#include "ncrypto.h"
89
#include "quic/defs.h"
910

1011
namespace node {
@@ -132,7 +133,7 @@ class RandomCIDFactory : public CID::Factory {
132133
// a CID of the requested size, we regenerate the pool
133134
// and reset it to zero.
134135
if (pos_ + length_hint > kPoolSize) {
135-
CHECK(crypto::CSPRNG(pool_, kPoolSize).is_ok());
136+
CHECK(ncrypto::CSPRNG(pool_, kPoolSize));
136137
pos_ = 0;
137138
}
138139
}

src/quic/endpoint.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "application.h"
2020
#include "bindingdata.h"
2121
#include "defs.h"
22+
#include "ncrypto.h"
2223

2324
namespace node {
2425

@@ -87,7 +88,7 @@ namespace {
8788
bool is_diagnostic_packet_loss(double probability) {
8889
if (LIKELY(probability == 0.0)) return false;
8990
unsigned char c = 255;
90-
CHECK(crypto::CSPRNG(&c, 1).is_ok());
91+
CHECK(ncrypto::CSPRNG(&c, 1));
9192
return (static_cast<double>(c) / 255) < probability;
9293
}
9394
#endif // DEBUG

src/quic/packet.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "bindingdata.h"
1515
#include "cid.h"
1616
#include "defs.h"
17+
#include "ncrypto.h"
1718
#include "tokens.h"
1819

1920
namespace node {
@@ -331,7 +332,7 @@ Packet* Packet::CreateStatelessResetPacket(
331332

332333
StatelessResetToken token(token_secret, path_descriptor.dcid);
333334
uint8_t random[kRandlen];
334-
CHECK(crypto::CSPRNG(random, kRandlen).is_ok());
335+
CHECK(ncrypto::CSPRNG(random, kRandlen));
335336

336337
auto packet = Create(env,
337338
listener,

src/quic/session.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "defs.h"
2525
#include "endpoint.h"
2626
#include "logstream.h"
27+
#include "ncrypto.h"
2728
#include "packet.h"
2829
#include "preferredaddress.h"
2930
#include "sessionticket.h"
@@ -2163,7 +2164,7 @@ struct Session::Impl {
21632164
static void on_rand(uint8_t* dest,
21642165
size_t destlen,
21652166
const ngtcp2_rand_ctx* rand_ctx) {
2166-
CHECK(crypto::CSPRNG(dest, destlen).is_ok());
2167+
CHECK(ncrypto::CSPRNG(dest, destlen));
21672168
}
21682169

21692170
static int on_early_data_rejected(ngtcp2_conn* conn, void* user_data) {

src/quic/tokens.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <util-inl.h>
99
#include <algorithm>
1010
#include "nbytes.h"
11+
#include "ncrypto.h"
1112

1213
namespace node {
1314
namespace quic {
@@ -22,7 +23,7 @@ TokenSecret::TokenSecret() : buf_() {
2223
// If someone manages to get visibility into that cache then they would know
2324
// the secrets for a larger number of tokens, which could be bad. For now,
2425
// generating on each call is safer, even if less performant.
25-
CHECK(crypto::CSPRNG(buf_, QUIC_TOKENSECRET_LEN).is_ok());
26+
CHECK(ncrypto::CSPRNG(buf_, QUIC_TOKENSECRET_LEN));
2627
}
2728

2829
TokenSecret::TokenSecret(const uint8_t* secret) : buf_() {

0 commit comments

Comments
 (0)