Skip to content

Commit

Permalink
Use native cryptography where available (#830)
Browse files Browse the repository at this point in the history
* Only register crypto Java callbacks if mongocrypt_is_crypto_available returns false
* Package crypto-enabled shared libraries on Mac and Windows
* Continue to package crypto-disabled shared libraries on Linux due to OpenSSL incompatibilities.
  Applications can force use of a crypto-enabled shared library by manually installing it in
  the system path or else specify the path via jna.library.path system variable.

JAVA-5306
  • Loading branch information
jyemin authored Jun 14, 2024
1 parent dadf22c commit 9750218
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 20 deletions.
2 changes: 1 addition & 1 deletion bindings/java/mongocrypt/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ tasks.register<Copy>("unzipJava") {
outputs.upToDateWhen { false }
from(tarTree(resources.gzip("${jnaDownloadsDir}/libmongocrypt-java.tar.gz")))
include(jnaMapping.keys.flatMap {
listOf("${it}/nocrypto/**/libmongocrypt.so", "${it}/nocrypto/**/libmongocrypt.dylib", "${it}/nocrypto/**/mongocrypt.dll" )
listOf("${it}/nocrypto/**/libmongocrypt.so", "${it}/lib/**/libmongocrypt.dylib", "${it}/bin/**/mongocrypt.dll" )
})
eachFile {
path = "${jnaMapping[path.substringBefore("/")]}/${name}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,17 @@ public interface mongocrypt_random_fn extends Callback {
public static native boolean
mongocrypt_status(mongocrypt_t crypt, mongocrypt_status_t status);

/**
* Returns true if libmongocrypt was built with native crypto support.
*
* <p>
* If libmongocrypt was not built with native crypto support, setting crypto hooks is required.
* </p>
*
* @return true if libmongocrypt was built with native crypto support
*/
public static native boolean
mongocrypt_is_crypto_available();

/**
* Destroy the @ref mongocrypt_t object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_query_type;
import static com.mongodb.crypt.capi.CAPI.mongocrypt_destroy;
import static com.mongodb.crypt.capi.CAPI.mongocrypt_init;
import static com.mongodb.crypt.capi.CAPI.mongocrypt_is_crypto_available;
import static com.mongodb.crypt.capi.CAPI.mongocrypt_new;
import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_aes_256_ctr;
import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_append_crypt_shared_lib_search_path;
Expand Down Expand Up @@ -118,25 +119,39 @@ class MongoCryptImpl implements MongoCrypt {

configure(() -> mongocrypt_setopt_log_handler(wrapped, logCallback, null));

// We specify NoPadding here because the underlying C library is responsible for padding prior
// to executing the callback
aesCBC256EncryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.ENCRYPT_MODE);
aesCBC256DecryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.DECRYPT_MODE);
aesCTR256EncryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.ENCRYPT_MODE);
aesCTR256DecryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.DECRYPT_MODE);

hmacSha512Callback = new MacCallback("HmacSHA512");
hmacSha256Callback = new MacCallback("HmacSHA256");
sha256Callback = new MessageDigestCallback("SHA-256");
secureRandomCallback = new SecureRandomCallback(new SecureRandom());

configure(() -> mongocrypt_setopt_crypto_hooks(wrapped, aesCBC256EncryptCallback, aesCBC256DecryptCallback,
secureRandomCallback, hmacSha512Callback, hmacSha256Callback,
sha256Callback, null));

signingRSAESPKCSCallback = new SigningRSAESPKCSCallback();
configure(() -> mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(wrapped, signingRSAESPKCSCallback, null));
configure(() -> mongocrypt_setopt_aes_256_ctr(wrapped, aesCTR256EncryptCallback, aesCTR256DecryptCallback, null));
if (mongocrypt_is_crypto_available()) {
LOGGER.debug("libmongocrypt is compiled with cryptography support, so not registering Java callbacks");
aesCBC256EncryptCallback = null;
aesCBC256DecryptCallback = null;
aesCTR256EncryptCallback = null;
aesCTR256DecryptCallback = null;
hmacSha512Callback = null;
hmacSha256Callback = null;
sha256Callback = null;
secureRandomCallback = null;
signingRSAESPKCSCallback = null;
} else {
LOGGER.debug("libmongocrypt is compiled without cryptography support, so registering Java callbacks");
// We specify NoPadding here because the underlying C library is responsible for padding prior
// to executing the callback
aesCBC256EncryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.ENCRYPT_MODE);
aesCBC256DecryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.DECRYPT_MODE);
aesCTR256EncryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.ENCRYPT_MODE);
aesCTR256DecryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.DECRYPT_MODE);

hmacSha512Callback = new MacCallback("HmacSHA512");
hmacSha256Callback = new MacCallback("HmacSHA256");
sha256Callback = new MessageDigestCallback("SHA-256");
secureRandomCallback = new SecureRandomCallback(new SecureRandom());

configure(() -> mongocrypt_setopt_crypto_hooks(wrapped, aesCBC256EncryptCallback, aesCBC256DecryptCallback,
secureRandomCallback, hmacSha512Callback, hmacSha256Callback,
sha256Callback, null));

signingRSAESPKCSCallback = new SigningRSAESPKCSCallback();
configure(() -> mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(wrapped, signingRSAESPKCSCallback, null));
configure(() -> mongocrypt_setopt_aes_256_ctr(wrapped, aesCTR256EncryptCallback, aesCTR256DecryptCallback, null));
}

if (options.getLocalKmsProviderOptions() != null) {
try (BinaryHolder localMasterKeyBinaryHolder = toBinary(options.getLocalKmsProviderOptions().getLocalMasterKey())) {
Expand Down

0 comments on commit 9750218

Please sign in to comment.