Skip to content

Commit 13aae88

Browse files
committed
fix(NODE-XXXX): provide native crypto hooks for OpenSSL 3
1 parent 95849dd commit 13aae88

File tree

6 files changed

+544
-17
lines changed

6 files changed

+544
-17
lines changed

addon/mongocrypt.cc

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ Function MongoCrypt::Init(Napi::Env env) {
120120
InstanceMethod("makeDataKeyContext", &MongoCrypt::MakeDataKeyContext),
121121
InstanceMethod("makeRewrapManyDataKeyContext", &MongoCrypt::MakeRewrapManyDataKeyContext),
122122
InstanceAccessor("status", &MongoCrypt::Status, nullptr),
123+
InstanceAccessor("cryptoHooksProvider", &MongoCrypt::CryptoHooksProvider, nullptr),
123124
InstanceAccessor(
124125
"cryptSharedLibVersionInfo", &MongoCrypt::CryptSharedLibVersionInfo, nullptr),
125126
StaticValue("libmongocryptVersion", String::New(env, mongocrypt_version(nullptr)))});
@@ -201,7 +202,7 @@ static bool aes_256_generic_hook(MongoCrypt* mongoCrypt,
201202
return true;
202203
}
203204

204-
bool MongoCrypt::setupCryptoHooks() {
205+
std::unique_ptr<CryptoHooks> MongoCrypt::createJSCryptoHooks() {
205206
auto aes_256_cbc_encrypt = [](void* ctx,
206207
mongocrypt_binary_t* key,
207208
mongocrypt_binary_t* iv,
@@ -398,26 +399,51 @@ bool MongoCrypt::setupCryptoHooks() {
398399
return true;
399400
};
400401

402+
return std::make_unique<CryptoHooks>(CryptoHooks {
403+
"js",
404+
aes_256_cbc_encrypt,
405+
aes_256_cbc_decrypt,
406+
random,
407+
hmac_sha_512,
408+
hmac_sha_256,
409+
sha_256,
410+
aes_256_ctr_encrypt,
411+
aes_256_ctr_decrypt,
412+
nullptr,
413+
sign_rsa_sha256,
414+
this
415+
});
416+
}
417+
418+
bool MongoCrypt::installCryptoHooks() {
419+
const auto& hooks = *_crypto_hooks;
401420
if (!mongocrypt_setopt_crypto_hooks(_mongo_crypt.get(),
402-
aes_256_cbc_encrypt,
403-
aes_256_cbc_decrypt,
404-
random,
405-
hmac_sha_512,
406-
hmac_sha_256,
407-
sha_256,
408-
this)) {
421+
hooks.aes_256_cbc_encrypt,
422+
hooks.aes_256_cbc_decrypt,
423+
hooks.random,
424+
hooks.hmac_sha_512,
425+
hooks.hmac_sha_256,
426+
hooks.sha_256,
427+
hooks.ctx)) {
409428
return false;
410429
}
411430

412431
// Added after `mongocrypt_setopt_crypto_hooks`, they should be treated as the same during
413432
// configuration
414433
if (!mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(
415-
_mongo_crypt.get(), sign_rsa_sha256, this)) {
434+
_mongo_crypt.get(), hooks.sign_rsa_sha256, this)) {
416435
return false;
417436
}
418437

419438
if (!mongocrypt_setopt_aes_256_ctr(
420-
_mongo_crypt.get(), aes_256_ctr_encrypt, aes_256_ctr_decrypt, this)) {
439+
_mongo_crypt.get(), hooks.aes_256_ctr_encrypt, hooks.aes_256_ctr_decrypt, hooks.ctx)) {
440+
return false;
441+
}
442+
443+
if (hooks.aes_256_ecb_encrypt &&
444+
!mongocrypt_setopt_aes_256_ecb(
445+
_mongo_crypt.get(), hooks.aes_256_ecb_encrypt, hooks.ctx)
446+
) {
421447
return false;
422448
}
423449

@@ -472,7 +498,10 @@ MongoCrypt::MongoCrypt(const CallbackInfo& info)
472498
}
473499
}
474500

475-
if (options.Has("cryptoCallbacks")) {
501+
if (!_crypto_hooks) {
502+
_crypto_hooks = opensslcrypto::createOpenSSLCryptoHooks();
503+
}
504+
if (!_crypto_hooks && options.Has("cryptoCallbacks")) {
476505
Object cryptoCallbacks = options.Get("cryptoCallbacks").ToObject();
477506

478507
SetCallback("aes256CbcEncryptHook", cryptoCallbacks["aes256CbcEncryptHook"]);
@@ -484,10 +513,10 @@ MongoCrypt::MongoCrypt(const CallbackInfo& info)
484513
SetCallback("hmacSha256Hook", cryptoCallbacks["hmacSha256Hook"]);
485514
SetCallback("sha256Hook", cryptoCallbacks["sha256Hook"]);
486515
SetCallback("signRsaSha256Hook", cryptoCallbacks["signRsaSha256Hook"]);
487-
488-
if (!setupCryptoHooks()) {
489-
throw Error::New(Env(), "unable to configure crypto hooks");
490-
}
516+
_crypto_hooks = createJSCryptoHooks();
517+
}
518+
if (_crypto_hooks && !installCryptoHooks()) {
519+
throw Error::New(Env(), "unable to configure crypto hooks");
491520
}
492521

493522
if (options.Has("cryptSharedLibSearchPaths")) {
@@ -535,6 +564,11 @@ Value MongoCrypt::CryptSharedLibVersionInfo(const CallbackInfo& info) {
535564
return ret;
536565
}
537566

567+
Value MongoCrypt::CryptoHooksProvider(const CallbackInfo& info) {
568+
if (!_crypto_hooks) return Env().Null();
569+
return String::New(Env(), _crypto_hooks->id);
570+
}
571+
538572
Value MongoCrypt::Status(const CallbackInfo& info) {
539573
std::unique_ptr<mongocrypt_status_t, MongoCryptStatusDeleter> status(mongocrypt_status_new());
540574
mongocrypt_status(_mongo_crypt.get(), status.get());

addon/mongocrypt.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@ extern "C" {
1919

2020
namespace node_mongocrypt {
2121

22+
struct CryptoHooks {
23+
const char* id;
24+
mongocrypt_crypto_fn aes_256_cbc_encrypt;
25+
mongocrypt_crypto_fn aes_256_cbc_decrypt;
26+
mongocrypt_random_fn random;
27+
mongocrypt_hmac_fn hmac_sha_512;
28+
mongocrypt_hmac_fn hmac_sha_256;
29+
mongocrypt_hash_fn sha_256;
30+
mongocrypt_crypto_fn aes_256_ctr_encrypt;
31+
mongocrypt_crypto_fn aes_256_ctr_decrypt;
32+
mongocrypt_crypto_fn aes_256_ecb_encrypt;
33+
mongocrypt_hmac_fn sign_rsa_sha256;
34+
void* ctx;
35+
};
36+
2237
struct MongoCryptBinaryDeleter {
2338
void operator()(mongocrypt_binary_t* binary) {
2439
mongocrypt_binary_destroy(binary);
@@ -37,6 +52,10 @@ struct MongoCryptContextDeleter {
3752
}
3853
};
3954

55+
namespace opensslcrypto {
56+
std::unique_ptr<CryptoHooks> createOpenSSLCryptoHooks();
57+
}
58+
4059
class MongoCrypt : public Napi::ObjectWrap<MongoCrypt> {
4160
public:
4261
static Napi::Function Init(Napi::Env env);
@@ -51,20 +70,23 @@ class MongoCrypt : public Napi::ObjectWrap<MongoCrypt> {
5170

5271
Napi::Value Status(const Napi::CallbackInfo& info);
5372
Napi::Value CryptSharedLibVersionInfo(const Napi::CallbackInfo& info);
73+
Napi::Value CryptoHooksProvider(const Napi::CallbackInfo& info);
5474

5575
private:
5676
friend class Napi::ObjectWrap<MongoCrypt>;
5777
Napi::Function GetCallback(const char* name);
5878
void SetCallback(const char* name, Napi::Value fn);
5979

6080
explicit MongoCrypt(const Napi::CallbackInfo& info);
61-
bool setupCryptoHooks();
81+
std::unique_ptr<CryptoHooks> createJSCryptoHooks();
82+
bool installCryptoHooks();
6283

6384
static void logHandler(mongocrypt_log_level_t level,
6485
const char* message,
6586
uint32_t message_len,
6687
void* ctx);
6788

89+
std::unique_ptr<CryptoHooks> _crypto_hooks;
6890
std::unique_ptr<mongocrypt_t, MongoCryptDeleter> _mongo_crypt;
6991
};
7092

0 commit comments

Comments
 (0)