From 6b546efa112a3499fc0ebfb1e811ef13150ca4f4 Mon Sep 17 00:00:00 2001 From: Dmitry Rybakov Date: Mon, 11 Nov 2024 22:00:23 +0100 Subject: [PATCH] Version 1.12.0 of libmongocrypt --- .../libmongocrypt/.evergreen/compile_cs.sh | 30 - .../libmongocrypt/.evergreen/config.yml | 46 +- .../.evergreen/debian_package_build.sh | 2 +- .../.evergreen/prep_c_driver_source.sh | 2 +- ext/libmongocrypt/libmongocrypt/CHANGELOG.md | 9 +- .../libmongocrypt/CMakeLists.txt | 5 +- ext/libmongocrypt/libmongocrypt/CODEOWNERS | 3 - ext/libmongocrypt/libmongocrypt/README.md | 53 +- .../libmongocrypt/bindings/cs/.gitignore | 12 - .../libmongocrypt/bindings/cs/CMakeLists.txt | 17 - .../bindings/cs/MongoDB.Driver.snk | Bin 596 -> 0 bytes .../MongoDB.Libmongocrypt.Example.csproj | 23 - .../Package.include.template.csproj | 11 - .../MongoDB.Libmongocrypt.Example/Program.cs | 442 ----------- .../MongoDB.Libmongocrypt.Test/BasicTests.cs | 748 ------------------ .../cs/MongoDB.Libmongocrypt.Test/BsonUtil.cs | 82 -- .../CallbackUtils.cs | 37 - .../CipherCallbacksTests.cs | 46 -- .../HashCallbackTests.cs | 37 - .../HmacShaCallbacksTests.cs | 37 - .../MongoDB.Libmongocrypt.Test.csproj | 37 - .../Package.include.template.csproj | 23 - .../SigningRSAESPKCSCallbackTests.cs | 64 -- .../test/example/collection-info.json | 37 - .../test/example/command-reply.json | 13 - .../test/example/encrypted-command-reply.json | 16 - .../test/example/encrypted-command.json | 11 - .../test/example/encrypted-value.json | 6 - .../test/example/key-filter.json | 19 - .../test/example/list-collections-filter.json | 3 - .../test/example/mongocryptd-command.json | 22 - .../xunit.runner.json | 6 - .../BasicTests.cs | 54 -- .../MongoDB.Libmongocrypt.Test32.csproj | 44 -- .../Package.include.template.csproj | 23 - .../cs/MongoDB.Libmongocrypt/AssemblyInfo.cs | 4 - .../cs/MongoDB.Libmongocrypt/Binary.cs | 145 ---- .../MongoDB.Libmongocrypt/BinarySafeHandle.cs | 60 -- .../CheckableSafeHandle.cs | 46 -- .../MongoDB.Libmongocrypt/CipherCallbacks.cs | 168 ---- .../ContextSafeHandle.cs | 48 -- .../cs/MongoDB.Libmongocrypt/CryptClient.cs | 257 ------ .../CryptClientFactory.cs | 138 ---- .../cs/MongoDB.Libmongocrypt/CryptContext.cs | 214 ----- .../MongoDB.Libmongocrypt/CryptException.cs | 37 - .../cs/MongoDB.Libmongocrypt/CryptOptions.cs | 67 -- .../cs/MongoDB.Libmongocrypt/HashCallback.cs | 59 -- .../MongoDB.Libmongocrypt/HmacShaCallbacks.cs | 96 --- .../cs/MongoDB.Libmongocrypt/IStatus.cs | 26 - .../MongoDB.Libmongocrypt/KmsCredentials.cs | 53 -- .../cs/MongoDB.Libmongocrypt/KmsKeyId.cs | 91 --- .../cs/MongoDB.Libmongocrypt/KmsRequest.cs | 125 --- .../KmsRequestCollection.cs | 60 -- .../cs/MongoDB.Libmongocrypt/Library.cs | 684 ---------------- .../cs/MongoDB.Libmongocrypt/LibraryLoader.cs | 289 ------- .../LibraryLoadingException.cs | 34 - .../cs/MongoDB.Libmongocrypt/License.txt | 14 - .../cs/MongoDB.Libmongocrypt/LogLevel.cs | 26 - .../MongoCryptSafeHandle.cs | 48 -- .../MongoDB.Libmongocrypt.csproj | 107 --- .../MongoDB.Libmongocrypt.ruleset | 85 -- .../MongoDB.Libmongocrypt.targets | 21 - .../OperatingSystemHelper.cs | 59 -- .../Package.include.template.csproj | 38 - .../cs/MongoDB.Libmongocrypt/PinnedBinary.cs | 49 -- .../SecureRandomCallback.cs | 51 -- .../SigningRSAESPKCSCallback.cs | 74 -- .../cs/MongoDB.Libmongocrypt/Status.cs | 94 --- .../MongoDB.Libmongocrypt/StatusSafeHandle.cs | 60 -- .../cs/MongoDB.Libmongocrypt/StyleCop.ruleset | 11 - .../cs/MongoDB.Libmongocrypt/stylecop.json | 8 - .../libmongocrypt/bindings/cs/README.md | 71 +- .../bindings/cs/Scripts/build.cake | 215 ----- .../bindings/cs/Scripts/build.config | 3 - .../bindings/cs/Scripts/build.ps1 | 275 ------- .../bindings/cs/Scripts/build.sh | 77 -- .../bindings/java/mongocrypt/build.gradle.kts | 2 +- .../bindings/python/.evergreen/integ-test.sh | 24 +- .../bindings/python/.evergreen/test.sh | 1 + .../bindings/python/CHANGELOG.rst | 9 +- .../bindings/python/libmongocrypt-version.txt | 2 +- .../asynchronous/state_machine.py | 2 +- .../bindings/python/pymongocrypt/binding.py | 6 - .../bindings/python/pymongocrypt/version.py | 2 +- .../bindings/python/pyproject.toml | 1 + .../libmongocrypt/bindings/python/release.sh | 2 +- .../libmongocrypt/bindings/python/sbom.json | 19 +- .../bindings/python/test/test_mongocrypt.py | 3 +- .../libmongocrypt/cmake/FetchMongoC.cmake | 2 +- .../libmongocrypt/cmake/ImportBSON.cmake | 6 +- .../libmongocrypt/doc/releasing.md | 38 +- .../libmongocrypt/etc/cyclonedx.sbom.json | 19 +- ext/libmongocrypt/libmongocrypt/etc/purls.txt | 2 +- .../libmongocrypt/integrating.md | 17 +- .../libmongocrypt/kms-message/README.md | 2 +- .../src/kms_message/kms_response_parser.h | 3 + .../kms-message/src/kms_response_parser.c | 8 + .../libmongocrypt/src/mc-cmp-private.h | 137 ++++ .../src/mc-fle-blob-subtype-private.h | 2 +- .../mc-fle2-encryption-placeholder-private.h | 20 + .../mc-fle2-find-range-payload-private-v2.h | 5 + ...mc-fle2-insert-update-payload-private-v2.h | 5 + .../src/mc-fle2-payload-iev-private-v2.h | 141 ++-- .../src/mc-fle2-payload-iev-v2.c | 228 ++++-- .../libmongocrypt/src/mc-fle2-rfds-private.h | 10 + ...tag-and-encrypted-metadata-block-private.h | 44 ++ ...mc-fle2-tag-and-encrypted-metadata-block.c | 81 ++ .../src/mc-range-edge-generation.c | 5 +- .../libmongocrypt/src/mc-range-encoding.c | 3 +- .../mc-range-mincover-generator.template.h | 4 +- .../libmongocrypt/src/mc-range-mincover.c | 1 + .../libmongocrypt/src/mc-rangeopts-private.h | 7 +- .../libmongocrypt/src/mc-rangeopts.c | 3 +- .../src/mongocrypt-cache-collinfo.c | 2 +- .../libmongocrypt/src/mongocrypt-cache-key.c | 2 +- .../src/mongocrypt-cache-private.h | 4 +- .../libmongocrypt/src/mongocrypt-cache.c | 2 +- .../libmongocrypt/src/mongocrypt-ciphertext.c | 2 +- .../src/mongocrypt-ctx-datakey.c | 3 +- .../src/mongocrypt-ctx-encrypt.c | 6 +- .../src/mongocrypt-ctx-private.h | 50 ++ .../libmongocrypt/src/mongocrypt-ctx.c | 23 +- .../libmongocrypt/src/mongocrypt-key-broker.c | 15 + .../src/mongocrypt-key-private.h | 9 + .../libmongocrypt/src/mongocrypt-key.c | 8 +- .../src/mongocrypt-kms-ctx-private.h | 6 + .../libmongocrypt/src/mongocrypt-kms-ctx.c | 174 ++++ .../libmongocrypt/src/mongocrypt-log.c | 1 - .../src/mongocrypt-marking-private.h | 4 + .../libmongocrypt/src/mongocrypt-marking.c | 3 +- .../libmongocrypt/src/mongocrypt-opts.c | 2 +- .../libmongocrypt/src/mongocrypt-private.h | 1 + .../libmongocrypt/src/mongocrypt.c | 19 + .../libmongocrypt/src/mongocrypt.h | 54 +- .../iev-v2/FLECrudTest-insertOneRangeV2.json | 10 +- .../data/iev-v2/FLECrudTest-insertOneV2.json | 1 + .../libmongocrypt/test/data/kms-tests.json | 8 +- .../test/data/multikey/command.json | 7 + .../data/multikey/key-document-a.json} | 37 +- .../test/data/multikey/key-document-b.json | 37 + .../test/data/multikey/mongocryptd_reply.json | 34 + .../test/data/multikey/schema_map.json | 35 + .../test/data/rmd/kms-decrypt-reply-429.txt | 6 + .../test/example-state-machine.c | 2 +- .../libmongocrypt/test/test-mc-cmp.c | 304 +++++++ .../test/test-mc-fle2-payload-iev-v2.c | 98 ++- .../test/test-mc-fle2-payload-iup-v2.c | 2 + ...mc-fle2-tag-and-encrypted-metadata-block.c | 56 ++ .../test/test-mc-range-mincover.c | 19 +- .../test/test-mongocrypt-assert-match-bson.h | 4 +- .../test/test-mongocrypt-cache.c | 18 - .../test/test-mongocrypt-crypto-hooks.c | 101 +-- .../test/test-mongocrypt-ctx-encrypt.c | 202 +++++ .../test-mongocrypt-ctx-rewrap-many-datakey.c | 79 ++ .../test/test-mongocrypt-datakey.c | 160 ++++ .../libmongocrypt/test/test-mongocrypt-kek.c | 4 +- .../test/test-mongocrypt-key-cache.c | 6 +- .../test/test-mongocrypt-kms-responses.c | 7 +- .../test/test-mongocrypt-marking.c | 10 +- .../libmongocrypt/test/test-mongocrypt.c | 24 + .../libmongocrypt/test/test-mongocrypt.h | 12 + lib/libmongocrypt_helper/version.rb | 4 +- sbom.json | 16 +- 163 files changed, 2257 insertions(+), 6409 deletions(-) delete mode 100644 ext/libmongocrypt/libmongocrypt/.evergreen/compile_cs.sh delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/.gitignore delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/CMakeLists.txt delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Driver.snk delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/MongoDB.Libmongocrypt.Example.csproj delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/Package.include.template.csproj delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/Program.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/BasicTests.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/BsonUtil.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/CallbackUtils.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/CipherCallbacksTests.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/HashCallbackTests.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/HmacShaCallbacksTests.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/Package.include.template.csproj delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/SigningRSAESPKCSCallbackTests.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/collection-info.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/command-reply.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command-reply.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-value.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-filter.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/list-collections-filter.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/mongocryptd-command.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/xunit.runner.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/BasicTests.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/Package.include.template.csproj delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/AssemblyInfo.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Binary.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/BinarySafeHandle.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CheckableSafeHandle.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CipherCallbacks.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/ContextSafeHandle.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClient.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClientFactory.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptContext.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptException.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptOptions.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/HashCallback.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/HmacShaCallbacks.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/IStatus.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsCredentials.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsKeyId.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsRequest.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsRequestCollection.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Library.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoader.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoadingException.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/License.txt delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LogLevel.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoCryptSafeHandle.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.ruleset delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.targets delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/OperatingSystemHelper.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Package.include.template.csproj delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/PinnedBinary.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/SecureRandomCallback.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/SigningRSAESPKCSCallback.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Status.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/StatusSafeHandle.cs delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/StyleCop.ruleset delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/stylecop.json delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.cake delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.config delete mode 100644 ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.ps1 delete mode 100755 ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.sh create mode 100644 ext/libmongocrypt/libmongocrypt/src/mc-cmp-private.h create mode 100644 ext/libmongocrypt/libmongocrypt/src/mc-fle2-tag-and-encrypted-metadata-block-private.h create mode 100644 ext/libmongocrypt/libmongocrypt/src/mc-fle2-tag-and-encrypted-metadata-block.c create mode 100644 ext/libmongocrypt/libmongocrypt/test/data/multikey/command.json rename ext/libmongocrypt/libmongocrypt/{bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-document.json => test/data/multikey/key-document-a.json} (58%) create mode 100644 ext/libmongocrypt/libmongocrypt/test/data/multikey/key-document-b.json create mode 100644 ext/libmongocrypt/libmongocrypt/test/data/multikey/mongocryptd_reply.json create mode 100644 ext/libmongocrypt/libmongocrypt/test/data/multikey/schema_map.json create mode 100644 ext/libmongocrypt/libmongocrypt/test/data/rmd/kms-decrypt-reply-429.txt create mode 100644 ext/libmongocrypt/libmongocrypt/test/test-mc-cmp.c create mode 100644 ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-tag-and-encrypted-metadata-block.c diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/compile_cs.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/compile_cs.sh deleted file mode 100644 index bcf9155..0000000 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/compile_cs.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# Compiles libmongocrypt dependencies and targets. -# -# Set extra cflags for libmongocrypt variables by setting LIBMONGOCRYPT_EXTRA_CFLAGS. -# - -. "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" - -echo "Begin compile process" - -evergreen_root="$(pwd)" - -if [ "$OS_NAME" = "windows" ]; then - # Make sure libbson.dll is in the path on Windows - export PATH="${MONGOCRYPT_INSTALL_PREFIX}/mongo-c-driver/bin:$PATH" - - for var in TMP TEMP NUGET_PACKAGES NUGET_HTTP_CACHE_PATH APPDATA; do export $var=z:\\data\\tmp; done - - # Make dotnet happy over ssh - export DOTNET_CLI_HOME=$(cygpath -w "${evergreen_root}/dotnet_home") -else - export PATH=$PATH:/usr/share/dotnet -fi - -dotnet_tool=$(which dotnet) - -"$dotnet_tool" build -c Release "$LIBMONGOCRYPT_DIR/cmake-build/bindings/cs/cs.sln" - -"$dotnet_tool" test -c Release "$LIBMONGOCRYPT_DIR/cmake-build/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj" -- RunConfiguration.TargetPlatform=x64 diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/config.yml b/ext/libmongocrypt/libmongocrypt/.evergreen/config.yml index 8a5da1e..f48216a 100755 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/config.yml +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/config.yml @@ -162,8 +162,10 @@ functions: - command: subprocess.exec params: binary: bash + working_dir: "${DRIVERS_TOOLS}" env: TOPOLOGY: replica_set + MONGODB_VERSION: "8.0" args: - ${DRIVERS_TOOLS}/.evergreen/run-orchestration.sh - command: "subprocess.exec" @@ -296,17 +298,6 @@ functions: ./curator version ./curator repo submit --config etc/repo_config.yaml --distro ${packager_distro} --edition org --version $pkg_version --arch ${packager_arch} --service https://barque.corp.mongodb.com/ --packages https://mciuploads.s3.amazonaws.com/${project}/${build_variant}/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt-distro-packages.tar.gz - "build csharp and test": - - command: "shell.exec" - params: - shell: bash - script: |- - . libmongocrypt/.evergreen/init.sh - if test "$OS_NAME" != "windows"; then export USE_NINJA=ON; fi - env ${compile_env|} DEFAULT_BUILD_ONLY=true \ - bash ./libmongocrypt/.evergreen/build_all.sh - env ${compile_env|} bash ./libmongocrypt/.evergreen/compile_cs.sh - "build python release": - command: shell.exec params: @@ -445,6 +436,17 @@ tasks: # Add detect_odr_violation=0 to ASAN_OPTIONS to ignore odr-violation in IntelDFP symbol: __dpml_bid_globals_table ASAN_OPTIONS="detect_leaks=1 detect_odr_violation=0" +- name: build-and-test-ubsan + commands: + - func: "fetch source" + - func: "build and test" + vars: + compile_env: >- + ${compile_env|} + LIBMONGOCRYPT_EXTRA_CFLAGS="-fsanitize=undefined -fno-omit-frame-pointer" + UBSAN_OPTIONS="halt_on_error=1,print_stacktrace=1" + + - name: build-and-test-asan-mac commands: - func: "fetch source" @@ -538,13 +540,6 @@ tasks: commands: - func: "download and merge python releases" -- name: build-and-test-csharp - commands: - - func: "fetch source" - - func: "build csharp and test" - vars: - test_env: PROJECT_DIRECTORY=${project_directory} - - name: publish-java depends_on: - variant: ubuntu2004-64 @@ -569,6 +564,7 @@ tasks: - variant: macos name: build-and-test-and-upload commands: + - func: "fetch source" # To set `tag_upload_location` expansion. - command: shell.exec params: script: mkdir all @@ -1090,7 +1086,6 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan-mac - # - build-and-test-csharp // temporary removed to make strong named release. - test-java - name: rhel72-zseries-test display_name: "RHEL 7.2 on zSeries" @@ -1131,7 +1126,6 @@ buildvariants: tasks: - build-and-test-and-upload - build-and-test-shared-bson - # - build-and-test-csharp // temporary removed to make strong named release. - test-java - name: windows-test-python display_name: "Windows Python" @@ -1272,17 +1266,10 @@ buildvariants: - name: rhel-62-64-bit display_name: "RHEL 6.2 64-bit" run_on: rhel62-small - expansions: - has_packages: true - packager_distro: rhel62 - packager_arch: x86_64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - test-java - - name: publish-packages - distros: - - rhel70-small - name: rhel-70-64-bit display_name: "RHEL 7.0 64-bit" run_on: rhel70-small @@ -1444,7 +1431,6 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - # - build-and-test-csharp // temporary removed to make strong named release. - test-java - name: publish-packages distros: @@ -1486,7 +1472,6 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - # - build-and-test-csharp // temporary removed to make strong named release. - test-java - upload-java - publish-packages @@ -1517,8 +1502,7 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - # see https://jira.mongodb.org/browse/MONGOCRYPT-515 - #- build-and-test-csharp + - build-and-test-ubsan - test-java - upload-java - name: publish-packages diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/debian_package_build.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/debian_package_build.sh index f7c9658..fa6d562 100644 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/debian_package_build.sh +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/debian_package_build.sh @@ -66,7 +66,7 @@ export DEBOOTSTRAP_DIR=`pwd`/debootstrap.git sudo -E ./debootstrap.git/debootstrap "${_dbs_args[@]}" ./unstable-chroot/ http://cdn-aws.deb.debian.org/debian cp -a libmongocrypt ./unstable-chroot/tmp/ sudo chroot ./unstable-chroot /bin/bash -c '(set -o xtrace && \ - apt-get install -y build-essential git-buildpackage fakeroot debhelper cmake curl ca-certificates libssl-dev pkg-config libbson-dev libintelrdfpmath-dev && \ + apt-get install -y build-essential git-buildpackage fakeroot debhelper cmake curl ca-certificates libssl-dev pkg-config libbson-dev libintelrdfpmath-dev python3-packaging && \ chown -R root:root /tmp/libmongocrypt && \ cd /tmp/libmongocrypt && \ git clean -fdx && \ diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/prep_c_driver_source.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/prep_c_driver_source.sh index dfff60e..5858a01 100755 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/prep_c_driver_source.sh +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/prep_c_driver_source.sh @@ -3,7 +3,7 @@ set -euxo pipefail # Clone mongo-c-driver and check out to a tagged version. -MONGO_C_DRIVER_VERSION=1.27.1 +MONGO_C_DRIVER_VERSION=1.28.1 # Force checkout with lf endings since .sh must have lf, not crlf on Windows git clone https://github.com/mongodb/mongo-c-driver.git --config core.eol=lf --config core.autocrlf=false --depth=1 --branch $MONGO_C_DRIVER_VERSION diff --git a/ext/libmongocrypt/libmongocrypt/CHANGELOG.md b/ext/libmongocrypt/libmongocrypt/CHANGELOG.md index 42283e5..8e22114 100644 --- a/ext/libmongocrypt/libmongocrypt/CHANGELOG.md +++ b/ext/libmongocrypt/libmongocrypt/CHANGELOG.md @@ -1,4 +1,11 @@ # ChangeLog +## 1.12.0 +### New features +- Add option to configure Data Encryption Key cache lifetime (`mongocrypt_setopt_key_expiration`) +- Add opt-in retry behavior for KMS operations (`mongocrypt_setopt_retry_kms`) +### Removed +- libmongocrypt is no longer published in the MongoDB package repository for RHEL 6. libmongocrypt may instead be built from source on RHEL 6, but support for RHEL 6 will be dropped in a future release. + ## 1.11.0 ### New features - Support `range` algorithm as stable. @@ -75,7 +82,7 @@ This release makes backwards breaking changes to Queryable Encryption (QE) behav - Set context error state during KMS provider validation. ## 1.6.1 ## Fixed -- Fix libbson dependency in pkg-config for PPA. +- Fix libbson dependency in pkg-config for MongoDB repository package. ## 1.6.0 ## New Features - Support accessToken to authenticate with Azure. diff --git a/ext/libmongocrypt/libmongocrypt/CMakeLists.txt b/ext/libmongocrypt/libmongocrypt/CMakeLists.txt index e70cfd2..5fe90aa 100644 --- a/ext/libmongocrypt/libmongocrypt/CMakeLists.txt +++ b/ext/libmongocrypt/libmongocrypt/CMakeLists.txt @@ -83,8 +83,6 @@ if (ENABLE_MORE_WARNINGS_AS_ERRORS) ) endif () -add_subdirectory (bindings/cs) - include (GenerateExportHeader) include (CTest) @@ -116,6 +114,7 @@ set (MONGOCRYPT_SOURCES src/mc-fle2-payload-uev-common.c src/mc-fle2-payload-uev-v2.c src/mc-fle2-rfds.c + src/mc-fle2-tag-and-encrypted-metadata-block.c src/mc-range-edge-generation.c src/mc-range-mincover.c src/mc-range-encoding.c @@ -459,6 +458,7 @@ endif () set (TEST_MONGOCRYPT_SOURCES test/test-gcp-auth.c + test/test-mc-cmp.c test/test-mc-efc.c test/test-mc-fle2-find-equality-payload-v2.c test/test-mc-fle2-find-range-payload-v2.c @@ -469,6 +469,7 @@ set (TEST_MONGOCRYPT_SOURCES test/test-mc-fle2-payload-uev.c test/test-mc-fle2-payload-uev-v2.c test/test-mc-fle2-rfds.c + test/test-mc-fle2-tag-and-encrypted-metadata-block.c test/test-mc-range-edge-generation.c test/test-mc-range-mincover.c test/test-mc-rangeopts.c diff --git a/ext/libmongocrypt/libmongocrypt/CODEOWNERS b/ext/libmongocrypt/libmongocrypt/CODEOWNERS index 00c3bc5..d1db98f 100644 --- a/ext/libmongocrypt/libmongocrypt/CODEOWNERS +++ b/ext/libmongocrypt/libmongocrypt/CODEOWNERS @@ -5,6 +5,3 @@ bindings/python @mongodb/dbx-python # Java Bindings bindings/java @jyemin @rozza - -# CSharp Bindings -bindings/cs @DmitryLukyanov diff --git a/ext/libmongocrypt/libmongocrypt/README.md b/ext/libmongocrypt/libmongocrypt/README.md index a62f9bb..6516946 100644 --- a/ext/libmongocrypt/libmongocrypt/README.md +++ b/ext/libmongocrypt/libmongocrypt/README.md @@ -112,10 +112,38 @@ See [releasing](./doc/releasing.md). Distribution packages (i.e., .deb/.rpm) are built and published for several Linux distributions. The installation of these packages for supported platforms is documented here. ### Unstable Development Distribution Packages ### -To install the latest unstable development package, change `1.11` to `development` in the package URLs listed in the subsequent instructions. For example, `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.11` in the instructions would become `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/development`. Do not use the unstable version of libmongocrypt in a production environment. +To install the latest unstable development package, change `1.12` to `development` in the package URLs listed in the subsequent instructions. For example, `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.12` in the instructions would become `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/development`. Do not use the unstable version of libmongocrypt in a production environment. ### .deb Packages (Debian and Ubuntu) ### +The repository containing the Debian and Ubuntu .deb packages can be configured automatically, using extrepo, or manually. Once the repository is configured then the packages can be installed. + +#### Repository configuration with extrepo #### + +Extrepo is available on Debian 11 and newer, as well as Ubuntu 20.04 and newer. + +First, install the extrepo package: + +``` +sudo apt install extrepo +``` + +If you would like to see the information about the repository, it can be viewed with the search command: + +``` +extrepo search libmongocrypt +``` + +In order to enable the repository, execute this command: + +``` +sudo extrepo enable libmongocrypt +``` + +Once the repository is configured, continue with package installation. + +#### Manual repository configuration #### + First, import the public key used to sign the package repositories: ``` @@ -125,24 +153,21 @@ sudo sh -c 'curl -s --location https://pgp.mongodb.com/libmongocrypt.asc | gpg - Second, create a list entry for the repository. For Ubuntu systems (be sure to change `` to `xenial`, `bionic`, `focal`, or `jammy`, as appropriate to your system): ``` -echo "deb https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.11 universe" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list +echo "deb https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.12 universe" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list ``` For Debian systems (be sure to change `` to `stretch`, `buster`, `bullseye`, or `bookworm` as appropriate to your system): ``` -echo "deb https://libmongocrypt.s3.amazonaws.com/apt/debian /libmongocrypt/1.11 main" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list +echo "deb https://libmongocrypt.s3.amazonaws.com/apt/debian /libmongocrypt/1.12 main" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list ``` -Third, update the package cache: +#### Package installation #### -``` -sudo apt-get update -``` - -Finally, install the libmongocrypt packages: +Finally, update the package cache and install the libmongocrypt packages: ``` +sudo apt-get update sudo apt-get install -y libmongocrypt-dev ``` @@ -156,7 +181,7 @@ Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository -baseurl=https://libmongocrypt.s3.amazonaws.com/yum/redhat/$releasever/libmongocrypt/1.11/x86_64 +baseurl=https://libmongocrypt.s3.amazonaws.com/yum/redhat/$releasever/libmongocrypt/1.12/x86_64 gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/libmongocrypt.asc @@ -175,7 +200,7 @@ Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository -baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2023/libmongocrypt/1.11/x86_64 +baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2023/libmongocrypt/1.12/x86_64 gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/libmongocrypt.asc @@ -194,7 +219,7 @@ Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository -baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2/libmongocrypt/1.11/x86_64 +baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2/libmongocrypt/1.12/x86_64 gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/libmongocrypt.asc @@ -213,7 +238,7 @@ Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository -baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2013.03/libmongocrypt/1.11/x86_64 +baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2013.03/libmongocrypt/1.12/x86_64 gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/libmongocrypt.asc @@ -236,7 +261,7 @@ sudo rpm --import https://pgp.mongodb.com/libmongocrypt.asc Second, add the repository (be sure to change `` to `12` or `15`, as appropriate to your system): ``` -sudo zypper addrepo --gpgcheck "https://libmongocrypt.s3.amazonaws.com/zypper/suse//libmongocrypt/1.11/x86_64" libmongocrypt +sudo zypper addrepo --gpgcheck "https://libmongocrypt.s3.amazonaws.com/zypper/suse//libmongocrypt/1.12/x86_64" libmongocrypt ``` Finally, install the libmongocrypt packages: diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/.gitignore b/ext/libmongocrypt/libmongocrypt/bindings/cs/.gitignore deleted file mode 100644 index 8ea8da7..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -# C# binary directories -bin/ -obj/ - -# Rider settings -.idea/ - -# VS settings -.vs/ - -# Other -/Scripts/Tools diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/CMakeLists.txt b/ext/libmongocrypt/libmongocrypt/bindings/cs/CMakeLists.txt deleted file mode 100644 index f55cc07..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ - -configure_file(cs.sln cs.sln COPYONLY) -configure_file(MongoDB.Driver.snk MongoDB.Driver.snk COPYONLY) - -configure_file(MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj COPYONLY) -configure_file(MongoDB.Libmongocrypt/Package.include.template.csproj MongoDB.Libmongocrypt/Package.csproj.include) - -configure_file(MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj COPYONLY) -configure_file(MongoDB.Libmongocrypt.Test/Package.include.template.csproj MongoDB.Libmongocrypt.Test/Package.csproj.include) - -configure_file(MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj COPYONLY) -configure_file(MongoDB.Libmongocrypt.Test/Package.include.template.csproj MongoDB.Libmongocrypt.Test32/Package.csproj.include) - -configure_file(MongoDB.Libmongocrypt.Example/MongoDB.Libmongocrypt.Example.csproj MongoDB.Libmongocrypt.Example/MongoDB.Libmongocrypt.Example.csproj COPYONLY) -configure_file(MongoDB.Libmongocrypt.Example/Package.include.template.csproj MongoDB.Libmongocrypt.Example/Package.csproj.include) - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Driver.snk b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Driver.snk deleted file mode 100644 index f8eaad4c83ffd99202de3aac958f115824211313..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096sD1Qw&gTSD5$c_x!Jn1`P5CiPJUXl$; zjB+?uPfagRXc214D9N%DLEJirc6q@?Rv9ZRFJI!p9b!%hl+y_Rdz8O#*DCKDK>>gM zC35MI8PUcWW9E#|?PqgJLd!EdfQ~q4%jPkYaunk(K%cStV*R$ANlYa$=1M^17uN1? zdmXUaa~!|IBHp7E?aR_%7KCJv^}uS7FU%Srm0@vcEl4xlOWz`B0Ha~gPV7)iJqKN- zYCdAnbTaPCtM&JrRI7CQ4%v|tCH)E1$_P6^gbm^%Y6$o^ySnqD3S_^1fTR@R8Q2g< z5_OAp2`vXnoJ6~+RW4drhH#lsu$1xvS9aV(m2L6L_=O?sQ4AYpB)37Ro7%PcDyXJVheS*_ - - - Exe - net472;netcoreapp2.1 - net472;netcoreapp2.1 - netcoreapp2.1 - - AnyCPU - false - - - - - - - - - - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/Package.include.template.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/Package.include.template.csproj deleted file mode 100644 index 255ea6b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/Package.include.template.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - false - @CMAKE_CURRENT_LIST_DIR@/MongoDB.Libmongocrypt.Example - - - - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/Program.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/Program.cs deleted file mode 100644 index 7556d3d..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/Program.cs +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using MongoDB.Bson; -using MongoDB.Bson.IO; -using MongoDB.Bson.Serialization; -using MongoDB.Bson.Serialization.Serializers; -using MongoDB.Libmongocrypt; -using MongoDB.Driver; -using System; -using System.IO; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Cryptography.X509Certificates; - -namespace drivertest -{ - class BsonUtil - { - public static BsonDocument ToDocument(Binary bin) - { - MemoryStream stream = new MemoryStream(bin.ToArray()); - using (var jsonReader = new BsonBinaryReader(stream)) - { - var context = BsonDeserializationContext.CreateRoot(jsonReader); - return BsonDocumentSerializer.Instance.Deserialize(context); - } - } - - public static byte[] ToBytes(BsonDocument doc) - { - BsonBinaryWriterSettings settings = new BsonBinaryWriterSettings() - { - // C# driver "magically" changes UUIDs underneath by default so tell it not to - GuidRepresentation = GuidRepresentation.Standard - }; - return doc.ToBson(null, settings); - } - - public static BsonDocument Concat(BsonDocument doc1, BsonDocument doc2) - { - BsonDocument dest = new BsonDocument(); - BsonDocumentWriter writer = new BsonDocumentWriter(dest); - var context = BsonSerializationContext.CreateRoot(writer); - - writer.WriteStartDocument(); - - foreach (var field in doc1) - { - writer.WriteName(field.Name); - BsonValueSerializer.Instance.Serialize(context, field.Value); - } - - foreach (var field in doc2) - { - writer.WriteName(field.Name); - BsonValueSerializer.Instance.Serialize(context, field.Value); - } - - writer.WriteEndDocument(); - return writer.Document; - } - - - public static BsonDocument FromJSON(string str) - { - using (var jsonReader = new JsonReader(str)) - { - var context = BsonDeserializationContext.CreateRoot(jsonReader); - return BsonDocumentSerializer.Instance.Deserialize(context); - } - } - } - - class MongoCryptDController - { - MongoClient _clientCryptD; - IMongoCollection _keyVault; - Uri _kmsEndpoint; - - public MongoCryptDController(MongoUrl urlCryptD, IMongoCollection keyVault, Uri kmsEndpoint) - { - _clientCryptD = new MongoClient(urlCryptD); - _keyVault = keyVault; - _kmsEndpoint = kmsEndpoint; - } - - public Guid GenerateKey(KmsCredentials credentials, KmsKeyId kmsKeyId) - { - var options = new CryptOptions(new[] { credentials }); - - BsonDocument key = null; - - using (var cryptClient = CryptClientFactory.Create(options)) - using (var context = cryptClient.StartCreateDataKeyContext(kmsKeyId)) - { - key = ProcessState(context, _keyVault.Database, null); - } - - _keyVault.InsertOne(key); - Guid g = key["_id"].AsGuid; - return g; - } - - public BsonDocument EncryptCommand(KmsCredentials credentials, IMongoCollection coll, BsonDocument cmd) - { - var options = new CryptOptions(new[] { credentials }); - - using (var cryptClient = CryptClientFactory.Create(options)) - using (var context = cryptClient.StartEncryptionContext(coll.Database.DatabaseNamespace.DatabaseName, command: BsonUtil.ToBytes(cmd))) - { - return ProcessState(context, coll.Database, cmd); - } - } - - public BsonDocument DecryptCommand(KmsCredentials credentials, IMongoDatabase db, BsonDocument doc) - { - var options = new CryptOptions(new[] { credentials }); - - using (var cryptClient = CryptClientFactory.Create(options)) - using (var context = cryptClient.StartDecryptionContext(BsonUtil.ToBytes(doc))) - { - return ProcessState(context, db, null); - } - } - - public static bool ValidateServerCertificate( - object sender, - X509Certificate certificate, - X509Chain chain, - SslPolicyErrors sslPolicyErrors) - { - if (sslPolicyErrors == SslPolicyErrors.None) - return true; - - Console.WriteLine("Certificate error: {0}", sslPolicyErrors); - - // Ignore certificate errors when testing against localhost - return true; - } - - void DoKmsRequest(KmsRequest request) - { - TcpClient tcpClient = new TcpClient(); - - Console.WriteLine("KMS: " + request.Endpoint); - - // change me to use the mock - if (_kmsEndpoint != null) - { - tcpClient.Connect(_kmsEndpoint.DnsSafeHost, _kmsEndpoint.Port); - } - else - { - tcpClient.Connect(request.Endpoint, 443); - } - SslStream stream = new SslStream(tcpClient.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate)); - - stream.AuthenticateAsClient("localhost"); - - Binary bin = request.Message; - stream.Write(bin.ToArray()); - - byte[] buffer = new byte[4096]; - while (request.BytesNeeded > 0) - { - MemoryStream memBuffer = new MemoryStream(); - int read = stream.Read(buffer, 0, buffer.Length); - if (read > 0) - { - memBuffer.Write(buffer, 0, read); - } - request.Feed(memBuffer.ToArray()); - } - } - - private BsonDocument ProcessState(CryptContext context, IMongoDatabase db, BsonDocument cmd) - { - BsonDocument ret = cmd; - - while (!context.IsDone) - { - Console.WriteLine("\n----------------------------------\nState:" + context.State); - switch (context.State) - { - case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: - { - var binary = context.GetOperation(); - var doc = BsonUtil.ToDocument(binary); - - Console.WriteLine("ListCollections Query: " + doc); - - ListCollectionsOptions opts = new ListCollectionsOptions() - { - Filter = new BsonDocumentFilterDefinition(doc) - }; - - var reply = db.ListCollections(opts); - - var replyDocs = reply.ToList(); - Console.WriteLine("ListCollections Reply: " + replyDocs); - - foreach (var replyDoc in replyDocs) - { - Console.WriteLine("ListCollections Reply: " + replyDoc); - context.Feed(BsonUtil.ToBytes(replyDoc)); - } - context.MarkDone(); - - break; - } - case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: - { - var binary = context.GetOperation(); - var commandWithSchema = BsonUtil.ToDocument(binary); - Console.WriteLine("MongoCryptD Query: " + commandWithSchema); - - var cryptDB = _clientCryptD.GetDatabase(db.DatabaseNamespace.DatabaseName); - - var reply = cryptDB.RunCommand(new BsonDocumentCommand(commandWithSchema)); - Console.WriteLine("MongoCryptD Reply: " + reply); - - context.Feed(BsonUtil.ToBytes(reply)); - context.MarkDone(); - - break; - } - case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS: - { - var binary = context.GetOperation(); - Console.WriteLine("Buffer:" + BitConverter.ToString(binary.ToArray())); - - var doc = BsonUtil.ToDocument(binary); - - Console.WriteLine("GetKeys Query: " + doc); - - var reply = _keyVault.Find(new BsonDocumentFilterDefinition(doc)); - - var replyDocs = reply.ToList(); - Console.WriteLine("GetKeys Reply: " + replyDocs); - - foreach (var replyDoc in replyDocs) - { - context.Feed(BsonUtil.ToBytes(replyDoc)); - } - - context.MarkDone(); - - break; - } - case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS: - { - var requests = context.GetKmsMessageRequests(); - foreach (var req in requests) - { - DoKmsRequest(req); - } - requests.MarkDone(); - break; - } - case CryptContext.StateCode.MONGOCRYPT_CTX_READY: - { - Binary b = context.FinalizeForEncryption(); - Console.WriteLine("Buffer:" + BitConverter.ToString(b.ToArray())); - ret = BsonUtil.ToDocument(b); - break; - } - case CryptContext.StateCode.MONGOCRYPT_CTX_DONE: - { - Console.WriteLine("DONE!!"); - return ret; - } - case CryptContext.StateCode.MONGOCRYPT_CTX_ERROR: - { - throw new NotImplementedException(); - } - } - } - - return ret; - } - } - - class Program - { - static IMongoCollection SetupKeyStore(MongoClient client) - { - var dbAdmin = client.GetDatabase("admin"); - var collKeyVault = dbAdmin.GetCollection("datakeys"); - - // Clear the key vault - collKeyVault.DeleteMany(new BsonDocumentFilterDefinition(new BsonDocument())); - - return collKeyVault; - } - - static IMongoCollection SetupTestCollection(MongoClient client, Guid keyID) - { - var database = client.GetDatabase("test"); - - // Reset state - database.DropCollection("test"); - - var s = new BsonDocument - { - { "$jsonSchema" , - new BsonDocument - { - { "type", "object" }, - { "properties" , new BsonDocument - { - { "ssn" , new BsonDocument - { - - { "encrypt" , new BsonDocument - { - { "keyId" , new BsonArray( new BsonValue[] { keyID } ) }, - { "bsonType" , "string"}, - { "algorithm" , "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" }, - } - } - } - } - } - } - } - } - }; - - database.CreateCollection("test", new CreateCollectionOptions() { Validator = new BsonDocumentFilterDefinition(s) }); - - return database.GetCollection("test"); - - } - - static string GetEnvironmenVariabletOrValue(string env, string def) - { - string value = Environment.GetEnvironmentVariable(env); - if (value != null) - { - return value; - } - return def; - } - - static void Main(string[] args) - { - // The C# driver transmutes data unless you specify this stupid line! - BsonDefaults.GuidRepresentation = GuidRepresentation.Standard; - - Console.WriteLine("Using url: " + args); - // or change me to use the mock - Uri kmsURL = Environment.GetEnvironmentVariable("FLE_AWS_SECRET_ACCESS_KEY") != null ? null : new Uri("https://localhost:8000"); - - var cryptDUrl = new MongoUrl("mongodb://localhost:27020"); - var client = new MongoClient("mongodb://localhost:27017"); - - IMongoCollection collKeyVault = SetupKeyStore(client); - - var controller = new MongoCryptDController(cryptDUrl, collKeyVault, kmsURL); - - var awsKeyId = new KmsKeyId( - new BsonDocument - { - { "provider", "aws" }, - { "region", "us-east-1" }, - { "key", "arn:aws:kms:us-east-1:579766882180:key/0689eb07-d588-4bbf-a83e-42157a92576b" } - }.ToBson()); - - var kmsCredentials = new KmsCredentials( - new BsonDocument - { - { "aws", - new BsonDocument - { - { "secretAccessKey", GetEnvironmenVariabletOrValue("FLE_AWS_SECRET_ACCESS_KEY", "us-east-1") }, - { "accessKeyId", GetEnvironmenVariabletOrValue("FLE_AWS_ACCESS_KEY_ID", "us-east-1") } - } - } - }.ToBson()); - - - Guid keyID = controller.GenerateKey(kmsCredentials, awsKeyId); - - IMongoCollection collection = SetupTestCollection(client, keyID); - var database = collection.Database; - - // Insert a document with SSN - var insertDoc = new BsonDocument - { - { "ssn" , "123-45-6789" }, - }; - - var insertDocCmd = new BsonDocument - { - { "insert" , "test" }, - { "documents", new BsonArray(new BsonValue[] { insertDoc }) } - }; - - var insertEncryptedDoc = new BsonDocument(controller.EncryptCommand(kmsCredentials, collection, insertDocCmd)); - - Console.WriteLine("Insert Doc: " + insertEncryptedDoc); - - insertEncryptedDoc.Remove("$db"); - database.RunCommand(new BsonDocumentCommand(insertEncryptedDoc)); - - - var findDoc = BsonUtil.FromJSON(@"{ -'find': 'test', -'filter' : { '$or': [{ '_id': 1},{ 'ssn': '123-45-6789'}]}, - }"); - - - var findCmd = new BsonDocumentCommand(controller.EncryptCommand(kmsCredentials, collection, findDoc)); - - Console.WriteLine("Find CMD: " + findCmd.Document); - - findCmd.Document.Remove("$db"); - - var commandResult = database.RunCommand(findCmd); - - Console.WriteLine("Find Result: " + commandResult); - - var decryptedDocument = controller.DecryptCommand(kmsCredentials, database, commandResult); - - Console.WriteLine("Find Result (DECRYPTED): " + decryptedDocument); - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/BasicTests.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/BasicTests.cs deleted file mode 100644 index 082055e..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/BasicTests.cs +++ /dev/null @@ -1,748 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using MongoDB.Bson; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using Xunit; -using System.Text; -using FluentAssertions; -using Xunit.Abstractions; -using MongoDB.Libmongocrypt.Test.Callbacks; - -namespace MongoDB.Libmongocrypt.Test -{ - public class BasicTests - { - private static ITestOutputHelper _output; - private const string AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"; - private const string AEAD_AES_256_CBC_HMAC_SHA_512_Random = "AEAD_AES_256_CBC_HMAC_SHA_512-Random"; - - public BasicTests(ITestOutputHelper output) - { - _output = output; - } - - [Fact] - public void EncryptQuery() - { - using (var cryptClient = CryptClientFactory.Create(CreateOptions())) - using (var context = - cryptClient.StartEncryptionContext("test", command: BsonUtil.ToBytes(ReadJsonTestFile("cmd.json")))) - { - var (_, bsonCommand) = ProcessContextToCompletion(context); - bsonCommand.Should().Equal((ReadJsonTestFile("encrypted-command.json"))); - } - } - - [Fact] - public void EncryptQueryStepwise() - { - using (var cryptClient = CryptClientFactory.Create(CreateOptions())) - using (var context = cryptClient.StartEncryptionContext("test", command: BsonUtil.ToBytes(ReadJsonTestFile("cmd.json")))) - { - var (state, _, operationSent) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); - operationSent.Should().Equal((ReadJsonTestFile("list-collections-filter.json"))); - - (state, _, operationSent) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); - operationSent.Should().Equal(ReadJsonTestFile("mongocryptd-command.json")); - - (state, _, operationSent) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS); - operationSent.Should().Equal(ReadJsonTestFile("key-filter.json")); - - (state, _, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); - // kms fluent assertions inside ProcessState() - - (state, _, operationSent) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); - operationSent.Should().Equal((ReadJsonTestFile("encrypted-command.json"))); - } - } - - [Fact] - public void EncryptQueryWithSchemaStepwise() - { - var listCollectionsReply = ReadJsonTestFile("collection-info.json"); - var schema = new BsonDocument("test.test", listCollectionsReply["options"]["validator"]["$jsonSchema"]); - - var options = new CryptOptions( - new[] { CreateKmsCredentials("aws") }, - BsonUtil.ToBytes(schema)); - - using (var cryptClient = CryptClientFactory.Create(options)) - using (var context = - cryptClient.StartEncryptionContext( - db: "test", - command: BsonUtil.ToBytes(ReadJsonTestFile("cmd.json")))) - { - - var (state, _, operationSent) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); - var mongoCryptdCommand = ReadJsonTestFile("mongocryptd-command.json"); - mongoCryptdCommand["isRemoteSchema"] = false; - operationSent.Should().Equal(mongoCryptdCommand); - - (state, _, operationSent) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS); - operationSent.Should().Equal(ReadJsonTestFile("key-filter.json")); - - (state, _, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); - // kms fluent assertions inside ProcessState() - - (state, _, operationSent) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); - operationSent.Should().Equal((ReadJsonTestFile("encrypted-command.json"))); - } - } - - [Fact] - public void DecryptQuery() - { - using (var cryptClient = CryptClientFactory.Create(CreateOptions())) - using (var context = - cryptClient.StartDecryptionContext(BsonUtil.ToBytes(ReadJsonTestFile("encrypted-command-reply.json")))) - { - var (_, bsonCommand) = ProcessContextToCompletion(context); - bsonCommand.Should().Equal(ReadJsonTestFile("command-reply.json")); - } - } - - [Fact] - public void DecryptQueryStepwise() - { - using (var cryptClient = CryptClientFactory.Create(CreateOptions())) - using (var context = cryptClient.StartDecryptionContext(BsonUtil.ToBytes(ReadJsonTestFile("encrypted-command-reply.json")))) - { - var (state, _, operationProduced) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS); - operationProduced.Should().Equal(ReadJsonTestFile("key-filter.json")); - - (state, _, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); - // kms fluent assertions inside ProcessState() - - (state, _, operationProduced) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); - operationProduced.Should().Equal(ReadJsonTestFile("command-reply.json")); - - (state, _, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); - } - } - - [Fact] - public void EncryptBadBson() - { - using (var cryptClient = CryptClientFactory.Create(CreateOptions())) - { - Func startEncryptionContext = () => - cryptClient.StartEncryptionContext("test", command: new byte[] { 0x1, 0x2, 0x3 }); - - // Ensure if we encrypt non-sense, it throws an exception demonstrating our exception code is good - var exception = Record.Exception(startEncryptionContext); - - exception.Should().BeOfType(); - } - } - - [Fact] - public void EncryptExplicit() - { - var keyDoc = ReadJsonTestFile("key-document.json"); - var keyId = keyDoc["_id"].AsBsonBinaryData.Bytes; - - BsonDocument doc = new BsonDocument() - { - { "v" , "hello" }, - }; - - var testData = BsonUtil.ToBytes(doc); - - byte[] encryptedBytes; - using (var cryptClient = CryptClientFactory.Create(CreateOptions())) - using (var context = StartExplicitEncryptionContextWithKeyId(cryptClient, keyId, AEAD_AES_256_CBC_HMAC_SHA_512_Random, testData)) - { - var (encryptedBinary, encryptedDocument) = ProcessContextToCompletion(context); - encryptedBytes = encryptedBinary.ToArray(); // need to copy bytes out before the context gets destroyed - } - - using (var cryptClient = CryptClientFactory.Create(CreateOptions())) - using (var context = cryptClient.StartExplicitDecryptionContext(encryptedBytes)) - { - var (decryptedResult, _) = ProcessContextToCompletion(context); - - decryptedResult.ToArray().Should().Equal(testData); - } - } - - [Fact] - public void EncryptExplicitStepwise() - { - var keyDoc = ReadJsonTestFile("key-document.json"); - var keyId = keyDoc["_id"].AsBsonBinaryData.Bytes; - - var doc = new BsonDocument("v", "hello"); - - var testData = BsonUtil.ToBytes(doc); - - using (var cryptClient = CryptClientFactory.Create(CreateOptions())) - { - byte[] encryptedResult; - using (var context = StartExplicitEncryptionContextWithKeyId( - cryptClient, - keyId: keyId, - encryptionAlgorithm: AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, - message: testData)) - { - var (state, binaryProduced, operationProduced) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS); - operationProduced.Should().Equal(ReadJsonTestFile("key-filter.json")); - - (state, _, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); - // kms fluent assertions inside ProcessState() - - (state, binaryProduced, operationProduced) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); - operationProduced.Should().Equal(ReadJsonTestFile("encrypted-value.json")); - encryptedResult = binaryProduced.ToArray(); // need to copy bytes out before the context gets destroyed - - (state, _, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); - } - - using (var context = cryptClient.StartExplicitDecryptionContext(encryptedResult)) - { - var (state, decryptedBinary, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); - decryptedBinary.ToArray().Should().Equal(testData); - - (state, _, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); - } - } - } - - [Fact] - public void TestAwsKeyCreationWithEndPoint() - { - var endpoint = "kms.us-east-1.amazonaws.com"; - var keyId = CreateKmsKeyId("aws", endpoint); - var key = CreateKmsCredentials("aws"); - - using (var cryptClient = CryptClientFactory.Create(new CryptOptions(new[] { key }))) - using (var context = cryptClient.StartCreateDataKeyContext(keyId)) - { - var (_, dataKeyDocument) = ProcessContextToCompletion(context, isKmsDecrypt: false); - dataKeyDocument["masterKey"]["endpoint"].Should().Be(endpoint); - } - } - - [Fact] - public void TestAwsKeyCreationWithEndpointStepwise() - { - var endpoint = "kms.us-east-1.amazonaws.com"; - var keyId = CreateKmsKeyId("aws", endpoint); - var key = CreateKmsCredentials("aws"); - - using (var cryptClient = CryptClientFactory.Create(new CryptOptions(new[] { key }))) - using (var context = cryptClient.StartCreateDataKeyContext(keyId)) - { - BsonDocument dataKeyDocument; - var (state, _, _) = ProcessState(context, isKmsDecrypt: false); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); - - (state, _, dataKeyDocument) = ProcessState(context, isKmsDecrypt: false); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); - dataKeyDocument["masterKey"]["endpoint"].Should().Be(endpoint); - - (state, _, _) = ProcessState(context, isKmsDecrypt: false); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); - } - } - - [Fact] - public void TestAwsKeyCreationWithkeyAltNames() - { - var keyAltNames = new[] { "KeyMaker", "Architect" }; - var keyAltNameDocuments = keyAltNames.Select(name => new BsonDocument("keyAltName", name)); - var keyAltNameBuffers = keyAltNameDocuments.Select(BsonUtil.ToBytes); - var keyId = CreateKmsKeyId("aws", keyAltNameBuffers: keyAltNameBuffers); - var key = CreateKmsCredentials("aws"); - - using (var cryptClient = CryptClientFactory.Create(new CryptOptions(new[] { key }))) - using (var context = cryptClient.StartCreateDataKeyContext(keyId)) - { - var (_, dataKeyDocument) = ProcessContextToCompletion(context, isKmsDecrypt: false); - dataKeyDocument.Should().NotBeNull(); - var actualKeyAltNames = dataKeyDocument["keyAltNames"].AsBsonArray.Select(x => x.AsString); - var expectedKeyAltNames = keyAltNames.Reverse(); // https://jira.mongodb.org/browse/CDRIVER-3277? - actualKeyAltNames.Should().BeEquivalentTo(expectedKeyAltNames); - } - } - - [Fact] - public void TestAwsKeyCreationWithkeyAltNamesStepwise() - { - var keyAltNames = new[] { "KeyMaker", "Architect" }; - var keyAltNameDocuments = keyAltNames.Select(name => new BsonDocument("keyAltName", name)); - var keyAltNameBuffers = keyAltNameDocuments.Select(BsonUtil.ToBytes); - var keyId = CreateKmsKeyId("aws", keyAltNameBuffers: keyAltNameBuffers); - var key = CreateKmsCredentials("aws"); - - using (var cryptClient = CryptClientFactory.Create(new CryptOptions(new[] { key }))) - using (var context = - cryptClient.StartCreateDataKeyContext(keyId)) - { - BsonDocument dataKeyDocument; - var (state, _, _) = ProcessState(context, isKmsDecrypt: false); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS); - - (state, _, dataKeyDocument) = ProcessState(context, isKmsDecrypt: false); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); - dataKeyDocument.Should().NotBeNull(); - var actualKeyAltNames = dataKeyDocument["keyAltNames"].AsBsonArray.Select(x => x.AsString); - var expectedKeyAltNames = keyAltNames.Reverse(); // https://jira.mongodb.org/browse/CDRIVER-3277? - actualKeyAltNames.Should().BeEquivalentTo(expectedKeyAltNames); - - (state, _, _) = ProcessState(context, isKmsDecrypt: false); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); - } - } - - [Fact] - public void TestLocalKeyCreationWithkeyAltNames() - { - var keyAltNames = new[] { "KeyMaker", "Architect" }; - var keyAltNameDocuments = keyAltNames.Select(name => new BsonDocument("keyAltName", name)); - var keyAltNameBuffers = keyAltNameDocuments.Select(BsonUtil.ToBytes); - var key = CreateKmsCredentials("local"); - var keyId = CreateKmsKeyId("local", keyAltNameBuffers: keyAltNameBuffers); - var cryptOptions = new CryptOptions(new[] { key }); - - using (var cryptClient = CryptClientFactory.Create(cryptOptions)) - using (var context = - cryptClient.StartCreateDataKeyContext(keyId)) - { - var (_, dataKeyDocument) = ProcessContextToCompletion(context); - dataKeyDocument.Should().NotBeNull(); - var actualKeyAltNames = dataKeyDocument["keyAltNames"].AsBsonArray.Select(x => x.AsString); - var expectedKeyAltNames = keyAltNames.Reverse(); // https://jira.mongodb.org/browse/CDRIVER-3277? - actualKeyAltNames.Should().BeEquivalentTo(expectedKeyAltNames); - } - } - - [Fact] - public void TestLocalKeyCreationWithkeyAltNamesStepwise() - { - var keyAltNames = new[] { "KeyMaker", "Architect" }; - var keyAltNameDocuments = keyAltNames.Select(name => new BsonDocument("keyAltName", name)); - var keyAltNameBuffers = keyAltNameDocuments.Select(BsonUtil.ToBytes); - var key = CreateKmsCredentials("local"); - var keyId = CreateKmsKeyId("local", keyAltNameBuffers: keyAltNameBuffers); - var cryptOptions = new CryptOptions(new[] { key }); - - using (var cryptClient = CryptClientFactory.Create(cryptOptions)) - using (var context = - cryptClient.StartCreateDataKeyContext(keyId)) - { - var (state, _, dataKeyDocument) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); - dataKeyDocument.Should().NotBeNull(); - var actualKeyAltNames = dataKeyDocument["keyAltNames"].AsBsonArray.Select(x => x.AsString); - var expectedKeyAltNames = keyAltNames.Reverse(); // https://jira.mongodb.org/browse/CDRIVER-3277? - actualKeyAltNames.Should().BeEquivalentTo(expectedKeyAltNames); - - (state, _, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); - } - } - - [Fact] - public void TestLocalKeyCreation() - { - var key = CreateKmsCredentials("local"); - var keyId = CreateKmsKeyId("local"); - var cryptOptions = new CryptOptions(new[] { key }); - - using (var cryptClient = CryptClientFactory.Create(cryptOptions)) - using (var context = - cryptClient.StartCreateDataKeyContext(keyId)) - { - var (_, dataKeyDocument) = ProcessContextToCompletion(context); - dataKeyDocument.Should().NotBeNull(); - } - } - - - [Fact] - public void TestLocalKeyCreationStepwise() - { - var key = CreateKmsCredentials("local"); - var keyId = CreateKmsKeyId("local"); - var cryptOptions = new CryptOptions(new[] { key }); - - using (var cryptClient = CryptClientFactory.Create(cryptOptions)) - using (var context = - cryptClient.StartCreateDataKeyContext(keyId)) - { - var (state, _, dataKeyDocument) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_READY); - dataKeyDocument.Should().NotBeNull(); - - (state, _, _) = ProcessState(context); - state.Should().Be(CryptContext.StateCode.MONGOCRYPT_CTX_DONE); - } - } - - [Theory] - [InlineData("aws")] - [InlineData("azure")] -#if NETCOREAPP3_0 - [InlineData("gcp")] -#endif - [InlineData("kmip")] - public void TestGetKmsProviderName(string kmsName) - { - var key = CreateKmsCredentials(kmsName); - var keyId = CreateKmsKeyId(kmsName); - var cryptOptions = new CryptOptions(new[] { key }); - - using (var cryptClient = CryptClientFactory.Create(cryptOptions)) - using (var context = cryptClient.StartCreateDataKeyContext(keyId)) - { - var request = context.GetKmsMessageRequests().Single(); - request.KmsProvider.Should().Be(kmsName); - } - } - - // private methods - private static KmsCredentials CreateKmsCredentials(string kmsName) - { - BsonDocument kmsCredentialsDocument; - switch (kmsName) - { - case "local": - kmsCredentialsDocument = new BsonDocument - { - { - "local", - new BsonDocument - { - { "key", new BsonBinaryData(new byte[96]) } - } - } - }; - break; - case "aws": - kmsCredentialsDocument = new BsonDocument - { - { - "aws", - new BsonDocument - { - { "secretAccessKey", "dummy" }, - { "accessKeyId", "dummy" } - } - } - }; - break; - case "azure": - kmsCredentialsDocument = new BsonDocument - { - { - "azure", - new BsonDocument - { - { "tenantId", "dummy" }, - { "clientId", "dummy" }, - { "clientSecret", "dummy" } - } - } - }; - break; - case "gcp": - kmsCredentialsDocument = new BsonDocument - { - { - "gcp", - new BsonDocument - { - { "email", "dummy" }, - { "privateKey", SigningRSAESPKCSCallbackTests.PrivateKey } - } - } - }; - break; - case "kmip": - kmsCredentialsDocument = new BsonDocument - { - { - "kmip", - new BsonDocument - { - { "endpoint", "dummy" } - } - } - }; - break; - default: throw new Exception($"Unsupported kms {kmsName}."); - } - return new KmsCredentials(kmsCredentialsDocument.ToBson()); - } - - private static KmsKeyId CreateKmsKeyId(string kmsName, string endPoint = null, IEnumerable keyAltNameBuffers = null) - { - BsonDocument datakeyOptionsDocument; - switch (kmsName) - { - case "local": - datakeyOptionsDocument = new BsonDocument - { - { "provider", "local" }, - }; - break; - case "aws": - datakeyOptionsDocument = new BsonDocument - { - { "provider", "aws" }, - { "key", "cmk" }, - { "region", "us-east-1" }, - { "endpoint", () => endPoint, endPoint != null } - }; - break; - case "azure": - datakeyOptionsDocument = new BsonDocument - { - { "provider", "azure" }, - { "keyName", "dummy" }, - { "keyVaultEndpoint", endPoint ?? "dummy.azure.net" } - }; - break; - case "gcp": - datakeyOptionsDocument = new BsonDocument - { - { "provider", "gcp" }, - { "projectId", "dummy" }, - { "location", "dummy" }, - { "keyRing", "dummy" }, - { "keyName", "dummy" }, - { "endpoint", () => endPoint, endPoint != null } - }; - break; - case "kmip": - datakeyOptionsDocument = new BsonDocument - { - { "provider", "kmip" } - }; - break; - default: throw new Exception($"Unsupported kms {kmsName}."); - } - return new KmsKeyId(datakeyOptionsDocument.ToBson(), keyAltNameBuffers); - } - - private CryptOptions CreateOptions() - { - return new CryptOptions( - new[] - { - CreateKmsCredentials("aws"), - CreateKmsCredentials("local") - }); - } - - private (Binary binarySent, BsonDocument document) ProcessContextToCompletion(CryptContext context, bool isKmsDecrypt = true) - { - BsonDocument document = null; - Binary binary = null; - - while (!context.IsDone) - { - (_, binary, document) = ProcessState(context, isKmsDecrypt); - } - - return (binary, document); - } - - /// - /// Processes the current state, simulating the execution the operation/post requests needed to reach the next state - /// Returns (stateProcessed, binaryOperationProduced, bsonOperationProduced) - /// - /// - private (CryptContext.StateCode stateProcessed, Binary binaryProduced, BsonDocument bsonOperationProduced) ProcessState(CryptContext context, bool isKmsDecrypt = true) - { - _output.WriteLine("\n----------------------------------\nState:" + context.State); - switch (context.State) - { - case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: - { - var binary = context.GetOperation(); - var doc = BsonUtil.ToDocument(binary); - _output.WriteLine("ListCollections: " + doc); - var reply = ReadJsonTestFile("collection-info.json"); - _output.WriteLine("Reply:" + reply); - context.Feed(BsonUtil.ToBytes(reply)); - context.MarkDone(); - return (CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO, binary, doc); - } - - case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: - { - var binary = context.GetOperation(); - var doc = BsonUtil.ToDocument(binary); - _output.WriteLine("Markings: " + doc); - var reply = ReadJsonTestFile("mongocryptd-reply.json"); - _output.WriteLine("Reply:" + reply); - context.Feed(BsonUtil.ToBytes(reply)); - context.MarkDone(); - return (CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS, binary, doc); - } - - case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS: - { - var binary = context.GetOperation(); - var doc = BsonUtil.ToDocument(binary); - _output.WriteLine("Key Document: " + doc); - var reply = ReadJsonTestFile("key-document.json"); - _output.WriteLine("Reply:" + reply); - context.Feed(BsonUtil.ToBytes(reply)); - context.MarkDone(); - return (CryptContext.StateCode.MONGOCRYPT_CTX_NEED_MONGO_KEYS, binary, doc); - } - - case CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS: - { - var requests = context.GetKmsMessageRequests(); - foreach (var req in requests) - { - var binary = req.Message; - _output.WriteLine("Key Document: " + binary); - var postRequest = binary.ToString(); - // TODO: add different hosts handling - postRequest.Should().Contain("Host:kms.us-east-1.amazonaws.com"); // only AWS - - var reply = ReadHttpTestFile(isKmsDecrypt ? "kms-decrypt-reply.txt" : "kms-encrypt-reply.txt"); - _output.WriteLine("Reply: " + reply); - req.Feed(Encoding.UTF8.GetBytes(reply)); - req.BytesNeeded.Should().Be(0); - } - - requests.MarkDone(); - return (CryptContext.StateCode.MONGOCRYPT_CTX_NEED_KMS, null, null); - } - - case CryptContext.StateCode.MONGOCRYPT_CTX_READY: - { - Binary binary = context.FinalizeForEncryption(); - _output.WriteLine("Buffer:" + binary.ToArray()); - var document = BsonUtil.ToDocument(binary); - _output.WriteLine("Document:" + document); - return (CryptContext.StateCode.MONGOCRYPT_CTX_READY, binary, document); - } - - case CryptContext.StateCode.MONGOCRYPT_CTX_DONE: - { - _output.WriteLine("DONE!!"); - return (CryptContext.StateCode.MONGOCRYPT_CTX_DONE, null, null); - } - - case CryptContext.StateCode.MONGOCRYPT_CTX_ERROR: - { - // We expect exceptions are thrown before we get to this state - throw new NotImplementedException(); - } - } - - throw new NotImplementedException(); - } - - public CryptContext StartExplicitEncryptionContextWithKeyId(CryptClient client, byte[] keyId, string encryptionAlgorithm, byte[] message) - { - return client.StartExplicitEncryptionContext(keyId, keyAltName: null, queryType: null, contentionFactor: null, encryptionAlgorithm, message, rangeOptions: null); - } - - static IEnumerable FindTestDirectories() - { - string[] searchPaths = new[] { Path.Combine("..", "test", "example"), Path.Combine("..", "test", "data") }; - var assemblyLocation = Path.GetDirectoryName(typeof(BasicTests).GetTypeInfo().Assembly.Location); - string cwd = Directory.GetCurrentDirectory(); // Assume we are in a child directory of the repo - var searchDirectory = assemblyLocation ?? cwd; - var testDirs = Enumerable.Range(1, 10) - .Select(i => Enumerable.Repeat("..", i)) - .Select(dotsSeq => dotsSeq.Aggregate(Path.Combine)) - .SelectMany(previousDirectories => - searchPaths.Select(searchPath => Path.Combine(searchDirectory, previousDirectories, searchPath))) - .Where(Directory.Exists) - .ToArray(); - - if (!testDirs.Any()) - { - throw new DirectoryNotFoundException("test/example"); - } - - return testDirs; - } - - static string ReadHttpTestFile(string file) - { - // The HTTP tests assume \r\n - // And git strips \r on Unix machines by default so fix up the files - - var text = ReadTestFile(file); - - StringBuilder builder = new StringBuilder(text.Length); - for (int i = 0; i < text.Length; i++) - { - if (text[i] == '\n' && text[i - 1] != '\r') - builder.Append('\r'); - builder.Append(text[i]); - } - return builder.ToString(); - } - - static BsonDocument ReadJsonTestFile(string file) - { - var text = ReadTestFile(file); - - if (text == null) - { - throw new FileNotFoundException(file); - } - - // Work around C# drivers and C driver have different extended json support - text = text.Replace("\"$numberLong\"", "$numberLong"); - - return BsonUtil.FromJSON(text); - } - - static string ReadTestFile(string fileName) - { - return FindTestDirectories() - .Select(directory => Path.Combine(directory, fileName)) - .Where(File.Exists) - .Select(File.ReadAllText) - .FirstOrDefault(); - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/BsonUtil.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/BsonUtil.cs deleted file mode 100644 index 88986a6..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/BsonUtil.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using MongoDB.Bson; -using MongoDB.Bson.IO; -using MongoDB.Bson.Serialization; -using MongoDB.Bson.Serialization.Serializers; -using System.IO; - -namespace MongoDB.Libmongocrypt.Test -{ - class BsonUtil - { - public static BsonDocument ToDocument(Binary bin) - { - MemoryStream stream = new MemoryStream(bin.ToArray()); - using (var jsonReader = new BsonBinaryReader(stream)) - { - var context = BsonDeserializationContext.CreateRoot(jsonReader); - return BsonDocumentSerializer.Instance.Deserialize(context); - } - } - - public static byte[] ToBytes(BsonDocument doc) - { - BsonBinaryWriterSettings settings = new BsonBinaryWriterSettings() - { - // C# driver "magically" changes UUIDs underneath by default so tell it not to - GuidRepresentation = GuidRepresentation.Standard - }; - return doc.ToBson(null, settings); - } - - public static BsonDocument Concat(BsonDocument doc1, BsonDocument doc2) - { - BsonDocument dest = new BsonDocument(); - BsonDocumentWriter writer = new BsonDocumentWriter(dest); - var context = BsonSerializationContext.CreateRoot(writer); - - writer.WriteStartDocument(); - - foreach (var field in doc1) - { - writer.WriteName(field.Name); - BsonValueSerializer.Instance.Serialize(context, field.Value); - } - - foreach (var field in doc2) - { - writer.WriteName(field.Name); - BsonValueSerializer.Instance.Serialize(context, field.Value); - } - - writer.WriteEndDocument(); - return writer.Document; - } - - - public static BsonDocument FromJSON(string str) - { - var jsonReaderSettings = new JsonReaderSettings { GuidRepresentation = GuidRepresentation.Unspecified }; - using (var jsonReader = new JsonReader(str, jsonReaderSettings)) - { - var context = BsonDeserializationContext.CreateRoot(jsonReader); - return BsonDocumentSerializer.Instance.Deserialize(context); - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/CallbackUtils.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/CallbackUtils.cs deleted file mode 100644 index ff1e364..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/CallbackUtils.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace MongoDB.Libmongocrypt.Test -{ - internal static class CallbackUtils - { - public static byte[] GetBytesFromHex(string hex) - { - if (hex.Length % 2 != 0) - { - throw new ArgumentException("Hex string must contain an even number of hex digits."); - } - - int length = hex.Length; - byte[] bytes = new byte[length / 2]; - for (int i = 0; i < length; i += 2) - bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); - return bytes; - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/CipherCallbacksTests.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/CipherCallbacksTests.cs deleted file mode 100644 index e80f241..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/CipherCallbacksTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using FluentAssertions; -using System.Security.Cryptography; -using Xunit; - -namespace MongoDB.Libmongocrypt.Test -{ - public class CipherCallbacksTests - { - [Theory] - [InlineData(CipherMode.CBC, "671db60d464b09e9c3b03242dd29bdc5")] - [InlineData(CipherMode.ECB, "ae6b200f30d6e8e424127e9c58affaf8")] - public void CipherTest(CipherMode mode, string expectedHex) - { - var keyHex = "92faa793d717675e2be804584a8a98252083fe6bf16010546a92e2ef4bdd27fd"; - var ivHex = "31164b2f661e41fed5df60bfcfa40baa"; - var inputHex = "379ddb78c30e5e4bf19dd81ae705796f"; - var keyBytes = CallbackUtils.GetBytesFromHex(keyHex); - var ivBytes = CallbackUtils.GetBytesFromHex(ivHex); - var inputBytes = CallbackUtils.GetBytesFromHex(inputHex); // decryptedBytes - var expectedEncryptedBytes = CallbackUtils.GetBytesFromHex(expectedHex); - var encryptedBytes = CipherCallbacks.AesCrypt(keyBytes, ivBytes, inputBytes, CryptMode.Encrypt, mode); - - encryptedBytes.Should().Equal(expectedEncryptedBytes); - - var decryptedBytes = CipherCallbacks.AesCrypt(keyBytes, ivBytes, encryptedBytes, CryptMode.Decrypt, mode); - - decryptedBytes.Should().Equal(inputBytes); - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/HashCallbackTests.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/HashCallbackTests.cs deleted file mode 100644 index 45ed80e..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/HashCallbackTests.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using FluentAssertions; -using Xunit; - -namespace MongoDB.Libmongocrypt.Test -{ - public class HashCallbackTests - { - [Fact] - public void HashTest() - { - var inputHex = "74657374206f66206d6163"; - var expectedHex = "9ff3e52fa31c9e0fa0b08e19c40591553ea64b73709633271975bfab2db9d980"; - - var inputBytes = CallbackUtils.GetBytesFromHex(inputHex); - var expectedBytes = CallbackUtils.GetBytesFromHex(expectedHex); - - var resultBytes = HashCallback.CalculateHash(inputBytes); - resultBytes.Should().Equal(expectedBytes); - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/HmacShaCallbacksTests.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/HmacShaCallbacksTests.cs deleted file mode 100644 index 8f188f4..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/HmacShaCallbacksTests.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using FluentAssertions; -using Xunit; - -namespace MongoDB.Libmongocrypt.Test -{ - public class HmacShaCallbacksTests - { - [Theory] - [InlineData(256, "74657374206f66206d6163", "37626663386235656333306537336439386565666133653263633334643635376535323734623537656633326661353862663638313534396535663737303138", "ebfaa874ff7fcf5b48637a4aff49ed60f48b53a0802719d6ad85f96d315b2df2")] - [InlineData(512, "74657374206f6620686d61630a", "06645237ece5638d1dcb66c70d8158c6ba5922dce3ae9f95242147fce0f989d9", "c8bc88465593980da5ed9bd213dcc4594106f6573d08eddc2b7cead3a642ef37dd848e8901a8c340f2a5d909057d28b1355fc9c82e7f7710e688f8c0c7635e9a")] - public void HmacShaTest(int bitness, string inputHex, string keyHex, string expectedHex) - { - var keyBytes = CallbackUtils.GetBytesFromHex(keyHex); - var inputBytes = CallbackUtils.GetBytesFromHex(inputHex); - var expectedBytes = CallbackUtils.GetBytesFromHex(expectedHex); - - var resultBytes = HmacShaCallbacks.CalculateHash(keyBytes, inputBytes, bitness); - resultBytes.Should().Equal(expectedBytes); - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj deleted file mode 100644 index 7678ad0..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - - net472;netcoreapp2.1;netcoreapp3.0 - netcoreapp2.1;netcoreapp3.0 - - AnyCPU - false - true - ..\MongoDB.Driver.snk - - - - - - - - - - - - . - - - - - - - PreserveNewest - - - - - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/Package.include.template.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/Package.include.template.csproj deleted file mode 100644 index f850767..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/Package.include.template.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - false - @CMAKE_CURRENT_LIST_DIR@/MongoDB.Libmongocrypt.Test - @CMAKE_CURRENT_BINARY_DIR@/MongoDB.Libmongocrypt.Test - - - - - - - - - - - - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/SigningRSAESPKCSCallbackTests.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/SigningRSAESPKCSCallbackTests.cs deleted file mode 100644 index e23dda9..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/SigningRSAESPKCSCallbackTests.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Text; -using FluentAssertions; -using Xunit; - -namespace MongoDB.Libmongocrypt.Test.Callbacks -{ - public class SigningRSAESPKCSCallbackTests - { - private static string DataToSign = "data to sign"; - - public static string PrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4JOyv5z05cL18ztpknRC7CFY2gYol4DAKerdVUoDJ" - + "xCTmFMf39dVUEqD0WDiw/qcRtSO1/FRut08PlSPmvbyKetsLoxlpS8lukSzEFpFK7+L+R4miFOl6HvECyg7lbC1H/WGAhIz9yZRlXhRo9qmO/fB6PV9IeYtU+1xY" - + "uXicjCDPp36uuxBAnCz7JfvxJ3mdVc0vpSkbSb141nWuKNYR1mgyvvL6KzxO6mYsCo4hRAdhuizD9C4jDHk0V2gDCFBk0h8SLEdzStX8L0jG90/Og4y7J1b/cPo/" - + "kbYokkYisxe8cPlsvGBf+rZex7XPxc1yWaP080qeABJb+S88O//LAgMBAAECggEBAKVxP1m3FzHBUe2NZ3fYCc0Qa2zjK7xl1KPFp2u4CU+9sy0oZJUqQHUdm5CM" - + "prqWwIHPTftWboFenmCwrSXFOFzujljBO7Z3yc1WD3NJl1ZNepLcsRJ3WWFH5V+NLJ8Bdxlj1DMEZCwr7PC5+vpnCuYWzvT0qOPTl9RNVaW9VVjHouJ9Fg+s2DrS" - + "hXDegFabl1iZEDdI4xScHoYBob06A5lw0WOCTayzw0Naf37lM8Y4psRAmI46XLiF/Vbuorna4hcChxDePlNLEfMipICcuxTcei1RBSlBa2t1tcnvoTy6cuYDqqIm" - + "RYjp1KnMKlKQBnQ1NjS2TsRGm+F0FbreVCECgYEA4IDJlm8q/hVyNcPe4OzIcL1rsdYN3bNm2Y2O/YtRPIkQ446ItyxD06d9VuXsQpFp9jNACAPfCMSyHpPApqlx" - + "dc8z/xATlgHkcGezEOd1r4E7NdTpGg8y6Rj9b8kVlED6v4grbRhKcU6moyKUQT3+1B6ENZTOKyxuyDEgTwZHtFECgYEA0fqdv9h9s77d6eWmIioP7FSymq93pC4u" - + "mxf6TVicpjpMErdD2ZfJGulN37dq8FOsOFnSmFYJdICj/PbJm6p1i8O21lsFCltEqVoVabJ7/0alPfdG2U76OeBqI8ZubL4BMnWXAB/VVEYbyWCNpQSDTjHQYs54" - + "qa2I0dJB7OgJt1sCgYEArctFQ02/7H5Rscl1yo3DBXO94SeiCFSPdC8f2Kt3MfOxvVdkAtkjkMACSbkoUsgbTVqTYSEOEc2jTgR3iQ13JgpHaFbbsq64V0QP3TAx" - + "bLIQUjYGVgQaF1UfLOBv8hrzgj45z/ST/G80lOl595+0nCUbmBcgG1AEWrmdF0/3RmECgYAKvIzKXXB3+19vcT2ga5Qq2l3TiPtOGsppRb2XrNs9qKdxIYvHmXo/" - + "9QP1V3SRW0XoD7ez8FpFabp42cmPOxUNk3FK3paQZABLxH5pzCWI9PzIAVfPDrm+sdnbgG7vAnwfL2IMMJSA3aDYGCbF9EgefG+STcpfqq7fQ6f5TBgLFwKBgCd7" - + "gn1xYL696SaKVSm7VngpXlczHVEpz3kStWR5gfzriPBxXgMVcWmcbajRser7ARpCEfbxM1UJyv6oAYZWVSNErNzNVb4POqLYcCNySuC6xKhs9FrEQnyKjyk8wI4V" - + "nrEMGrQ8e+qYSwYk9Gh6dKGoRMAPYVXQAO0fIsHF/T0a"; - - private static string ExpectedSignature = "VocBRhpMmQ2XCzVehWSqheQLnU889gf3dhU4AnVnQTJjsKx/CM23qKDPkZDd2A/BnQsp99SN7ksIX5Raj0TPw" - + "yN5OCN/YrNFNGoOFlTsGhgP/hyE8X3Duiq6sNO0SMvRYNPFFGlJFsp1Fw3Z94eYMg4/Wpw5s4+Jo5Zm/qY7aTJIqDKDQ3CNHLeJgcMUOc9sz01/GzoUYKDVODHSx" - + "rYEk5ireFJFz9vP8P7Ha+VDUZuQIQdXer9NBbGFtYmWprY3nn4D3Dw93Sn0V0dIqYeIo91oKyslvMebmUM95S2PyIJdEpPb2DJDxjvX/0LLwSWlSXRWy9gapWoBk" - + "b4ynqZBsg=="; - - [Fact] - public void GetSignatureTest() - { - byte[] privateKeyBytes = Convert.FromBase64String(PrivateKey); - var dataBytes = Encoding.ASCII.GetBytes(DataToSign); -#if NETCOREAPP3_0 - byte[] signature = SigningRSAESPKCSCallback.HashAndSignBytes(dataBytes, privateKeyBytes); - string output = Convert.ToBase64String(signature); - - output.Should().Be(ExpectedSignature); -#else - var ex = Record.Exception(() => SigningRSAESPKCSCallback.HashAndSignBytes(dataBytes, privateKeyBytes)); - ex.Should().BeOfType(); -#endif - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/collection-info.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/collection-info.json deleted file mode 100644 index 924feed..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/collection-info.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "type": "collection", - "name": "test", - "idIndex": { - "ns": "test.test", - "name": "_id_", - "key": { - "_id": { - "$numberInt": "1" - } - }, - "v": { - "$numberInt": "2" - } - }, - "options": { - "validator": { - "$jsonSchema": { - "properties": { - "ssn": { - "encrypt": { - "keyId": { - "$binary": { - "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", - "subType": "04" - } - }, - "type": "string", - "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" - } - } - }, - "bsonType": "object" - } - } - } -} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/command-reply.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/command-reply.json deleted file mode 100644 index c110f73..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/command-reply.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "cursor": { - "firstBatch": [ - { - "_id": 1, - "ssn": "457-55-5462" - } - ], - "id": 0, - "ns": "test.test" - }, - "ok": 1 -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command-reply.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command-reply.json deleted file mode 100644 index 73d4d34..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command-reply.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "cursor" : { - "firstBatch" : [ - { - "_id": 1, - "ssn": { - "$binary": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", - "$type": "06" - } - } - ], - "id" : 0, - "ns" : "test.test" - }, - "ok" : 1 -} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command.json deleted file mode 100644 index 8b8cfaa..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "filter": { - "ssn": { - "$binary": { - "base64": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", - "subType": "06" - } - } - }, - "find": "test" -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-value.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-value.json deleted file mode 100644 index e1a832b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/encrypted-value.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "v": { - "$binary": "AWFhYWFhYWFhYWFhYWFhYWECW+zDjR/69eS6VtuMD5+O2lZw6JyiWOw3avI7mnUkdpKzPfvy8F/nlZrgZa2cGmQsb0TmLZuk5trldosnGKD91w==", - "$type": "06" - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-filter.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-filter.json deleted file mode 100644 index 9ad7c70..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-filter.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$or": [ - { - "_id": { - "$in": [ - { - "$binary": "YWFhYWFhYWFhYWFhYWFhYQ==", - "$type": "04" - } - ] - } - }, - { - "keyAltNames": { - "$in": [] - } - } - ] -} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/list-collections-filter.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/list-collections-filter.json deleted file mode 100644 index 2f37dc5..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/list-collections-filter.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "test" -} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/mongocryptd-command.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/mongocryptd-command.json deleted file mode 100644 index 642f06f..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/mongocryptd-command.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "find": "test", - "filter": { - "ssn": "457-55-5462" - }, - "jsonSchema": { - "properties": { - "ssn": { - "encrypt": { - "keyId": { - "$binary": "YWFhYWFhYWFhYWFhYWFhYQ==", - "$type": "04" - }, - "type": "string", - "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" - } - } - }, - "bsonType": "object" - }, - "isRemoteSchema": true -} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/xunit.runner.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/xunit.runner.json deleted file mode 100644 index 991c5d6..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/xunit.runner.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://xunit.github.io/schema/current/xunit.runner.schema.json", - - "appDomain": "denied", - "shadowCopy": false -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/BasicTests.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/BasicTests.cs deleted file mode 100644 index 70e02dc..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/BasicTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using Xunit; -using FluentAssertions; -using MongoDB.Bson; - -namespace MongoDB.Libmongocrypt.Test32 -{ - public class BasicTests - { - BsonDocument CreateAwsCredentialsDocument() => - new BsonDocument - { - { - "aws", - new BsonDocument - { - { "secretAccessKey", "us-east-1" }, - { "accessKeyId", "us-east-1" } - } - } - }; - - CryptOptions CreateOptions() => - new CryptOptions( - new[] - { - new KmsCredentials(CreateAwsCredentialsDocument().ToBson()) - } - ); - - [Fact] - public void CryptClientShouldFailToiInitializeWhenTargetingX86() - { - var exception = Record.Exception(() => CryptClientFactory.Create(CreateOptions())); - exception.Should().BeOfType(); - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj deleted file mode 100644 index 5f5cb2d..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - net472;netcoreapp2.1;netcoreapp3.0 - netcoreapp2.1;netcoreapp3.0 - false - true - ..\MongoDB.Driver.snk - - - - - - - - - - - - - - - - . - - - - x86 - - - - x86 - - - - - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/Package.include.template.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/Package.include.template.csproj deleted file mode 100644 index e5c69cd..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/Package.include.template.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - false - @CMAKE_CURRENT_LIST_DIR@/MongoDB.Libmongocrypt.Test32 - @CMAKE_CURRENT_BINARY_DIR@/MongoDB.Libmongocrypt.Test32 - - - - - - - - - - - - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/AssemblyInfo.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/AssemblyInfo.cs deleted file mode 100644 index 0d7b58a..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/AssemblyInfo.cs +++ /dev/null @@ -1,4 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("MongoDB.Libmongocrypt.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010035287f0d3883c0a075c88e0cda3ce93b621003ecbd5e920d4a8c7238564f4d2f4f68116aca28c9b21341dc3a877679c14556192b2b2f5fe2c11d624e0894d308ff7b94bf6fd72aef1b41017ffe2572e99019d1c61963e68cd0ed67734a42cb333b808e3867cbe631937214e32e409fb1fa62fdb69d494c2530e64a40e417d6ee")] -[assembly: InternalsVisibleTo("MongoDB.Libmongocrypt.Test32, PublicKey=002400000480000094000000060200000024000052534131000400000100010035287f0d3883c0a075c88e0cda3ce93b621003ecbd5e920d4a8c7238564f4d2f4f68116aca28c9b21341dc3a877679c14556192b2b2f5fe2c11d624e0894d308ff7b94bf6fd72aef1b41017ffe2572e99019d1c61963e68cd0ed67734a42cb333b808e3867cbe631937214e32e409fb1fa62fdb69d494c2530e64a40e417d6ee")] diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Binary.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Binary.cs deleted file mode 100644 index 3fd3714..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Binary.cs +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace MongoDB.Libmongocrypt -{ - /// - /// A pointer and length pair the contains raw bytes to pass or retrive from libmongocrypt. - /// - /// - public class Binary : IDisposable - { - private static readonly byte[] __empty = new byte[0]; - - private BinarySafeHandle _handle; - - internal Binary() - { - _handle = Library.mongocrypt_binary_new(); - } - - internal Binary(BinarySafeHandle handle) - { - _handle = handle; - } - - /// - /// Gets the data. - /// - /// - /// The data. - /// - public IntPtr Data - { - get - { - if (!_handle.IsInvalid) - { - return Marshal.ReadIntPtr(_handle.DangerousGetHandle()); - } - return IntPtr.Zero; - } - } - - /// - /// Gets the length. - /// - /// - /// The length. - /// - public uint Length - { - get - { - if (!_handle.IsInvalid) - { - return (uint)Marshal.ReadInt32(_handle.DangerousGetHandle(), IntPtr.Size); - } - return 0; - } - } - - internal BinarySafeHandle Handle => _handle; - - /// - /// Converts to array. - /// - public byte[] ToArray() - { - if (Length > 0) - { - byte[] arr = new byte[Length]; - Marshal.Copy(Data, arr, 0, arr.Length); - return arr; - } - else - { - return __empty; - } - } - - /// - /// Write bytes into Data. - /// - public void WriteBytes(byte[] bytes) - { - // The length of the new bytes can be smaller than allocated memory - // because sometimes the allocated memory contains reserved blocks for future usage - if (bytes.Length <= Length) - { - Marshal.Copy(bytes, 0, Data, bytes.Length); - } - else - { - // this code path is not expected, but it's worth doing it to avoid silent saving of corrupted data - throw new InvalidDataException($"Incorrect bytes size {bytes.Length}. The bytes size must be less than or equal to {Length}."); - } - } - - /// - /// Converts to string. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return Marshal.PtrToStringAnsi(Data); - } - - #region IDisposable - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - // Adapted from: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netcore-3.0 - if (_handle != null && !_handle.IsInvalid) - { - // Free the handle - _handle.Dispose(); - } - } - #endregion - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/BinarySafeHandle.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/BinarySafeHandle.cs deleted file mode 100644 index fe13256..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/BinarySafeHandle.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; - -namespace MongoDB.Libmongocrypt -{ - /// - /// SafeHandle to manage the lifetime of a mongocrypt_binary_t. - /// - /// - internal class BinarySafeHandle : SafeHandle - { - private BinarySafeHandle() - : base(IntPtr.Zero, true) - { - } - - private BinarySafeHandle(IntPtr ptr) - : base(ptr, false) - { - } - - public static BinarySafeHandle FromIntPtr(IntPtr ptr) - { - return new BinarySafeHandle(ptr); - } - - public override bool IsInvalid - { - get - { - return handle == IntPtr.Zero; - } - } - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected override bool ReleaseHandle() - { - // Here, we must obey all rules for constrained execution regions. - Library.mongocrypt_binary_destroy(handle); - return true; - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CheckableSafeHandle.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CheckableSafeHandle.cs deleted file mode 100644 index b5d109f..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CheckableSafeHandle.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2010–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; - -namespace MongoDB.Libmongocrypt -{ - /// - /// SafeHandle to manage the lifetime of a mongocrypt_ctx_t. - /// - /// - internal abstract class CheckableSafeHandle : SafeHandle - { - internal CheckableSafeHandle() : base(IntPtr.Zero, true) - { - } - - public override bool IsInvalid - { - get - { - return handle == IntPtr.Zero; - } - } - - public abstract void Check(Status status, bool success); - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected abstract override bool ReleaseHandle(); - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CipherCallbacks.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CipherCallbacks.cs deleted file mode 100644 index d177f51..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CipherCallbacks.cs +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Security.Cryptography; - -namespace MongoDB.Libmongocrypt -{ - internal enum CryptMode - { - Encrypt, - Decrypt - } - - internal static class CipherCallbacks - { - public static bool EncryptCbc( - IntPtr ctx, - IntPtr key, - IntPtr iv, - IntPtr @in, - IntPtr @out, - ref uint bytes_written, - IntPtr statusPtr) - { - using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) - { - try - { - var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); - var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); - var outputBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); - var ivBinary = new Binary(BinarySafeHandle.FromIntPtr(iv)); - - byte[] keyBytes = keyBinary.ToArray(); - byte[] ivBytes = ivBinary.ToArray(); - byte[] inputBytes = inputBinary.ToArray(); - - var outputBytes = AesCrypt(keyBytes, ivBytes, inputBytes, CryptMode.Encrypt, CipherMode.CBC); - bytes_written = (uint)outputBytes.Length; - outputBinary.WriteBytes(outputBytes); - return true; - } - catch (Exception e) - { - status.SetStatus(1, e.Message); - return false; - } - } - } - - public static bool DecryptCbc( - IntPtr ctx, - IntPtr key, - IntPtr iv, - IntPtr @in, - IntPtr @out, - ref uint bytes_written, - IntPtr statusPtr) - { - using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) - { - try - { - var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); - var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); - var outputBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); - var ivBinary = new Binary(BinarySafeHandle.FromIntPtr(iv)); - - byte[] keyBytes = keyBinary.ToArray(); - byte[] ivBytes = ivBinary.ToArray(); - byte[] inputBytes = inputBinary.ToArray(); - - var outputBytes = AesCrypt(keyBytes, ivBytes, inputBytes, CryptMode.Decrypt, CipherMode.CBC); - bytes_written = (uint)outputBytes.Length; - outputBinary.WriteBytes(outputBytes); - - return true; - } - catch (Exception e) - { - status.SetStatus(1, e.Message); - return false; - } - } - } - - public static bool EncryptEcb( - IntPtr ctx, - IntPtr key, - IntPtr iv, - IntPtr @in, - IntPtr @out, - ref uint bytes_written, - IntPtr statusPtr) - { - using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) - { - try - { - var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); - var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); - var outputBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); - var ivBinary = new Binary(BinarySafeHandle.FromIntPtr(iv)); - - byte[] keyBytes = keyBinary.ToArray(); - byte[] ivBytes = ivBinary.ToArray(); - byte[] inputBytes = inputBinary.ToArray(); - - var outputBytes = AesCrypt(keyBytes, ivBytes, inputBytes, CryptMode.Encrypt, CipherMode.ECB); - bytes_written = (uint)outputBytes.Length; - outputBinary.WriteBytes(outputBytes); - return true; - } - catch (Exception e) - { - status.SetStatus(1, e.Message); - return false; - } - } - } - - public static byte[] AesCrypt(byte[] keyBytes, byte[] ivBytes, byte[] inputBytes, CryptMode cryptMode, CipherMode cipherMode) - { - using (var aes = new RijndaelManaged()) - { - aes.Mode = cipherMode; - - aes.Key = keyBytes; - if (ivBytes.Length > 0) - { - aes.IV = ivBytes; - } - - aes.Padding = PaddingMode.None; // mongocrypt level is responsible for padding - - using (var encrypto = CreateCryptoTransform(aes)) - { - byte[] encryptedBytes = encrypto.TransformFinalBlock(inputBytes, 0, inputBytes.Length); - return encryptedBytes; - } - - ICryptoTransform CreateCryptoTransform(RijndaelManaged rijndaelManaged) - { - switch (cryptMode) - { - case CryptMode.Encrypt: return rijndaelManaged.CreateEncryptor(); - case CryptMode.Decrypt: return rijndaelManaged.CreateDecryptor(); - default: throw new InvalidOperationException($"Unsupported crypt mode {cryptMode}."); // should not be reached - } - } - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/ContextSafeHandle.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/ContextSafeHandle.cs deleted file mode 100644 index 02430e1..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/ContextSafeHandle.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Runtime.ConstrainedExecution; - -namespace MongoDB.Libmongocrypt -{ - /// - /// SafeHandle to manage the lifetime of a mongocrypt_ctx_t. - /// - /// - internal class ContextSafeHandle : CheckableSafeHandle - { - private ContextSafeHandle() : base() - { - } - - public override void Check(Status status, bool success) - { - if (!success) - { - Library.mongocrypt_ctx_status(this, status.Handle); - status.ThrowExceptionIfNeeded(); - } - } - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected override bool ReleaseHandle() - { - // Here, we must obey all rules for constrained execution regions. - Library.mongocrypt_ctx_destroy(handle); - return true; - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClient.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClient.cs deleted file mode 100644 index 9ad606f..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClient.cs +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Runtime.InteropServices; - -namespace MongoDB.Libmongocrypt -{ - /// - /// CryptClient represents a session with libmongocrypt. - /// - /// It can be used to encrypt and decrypt documents. - /// - /// - public class CryptClient : IDisposable, IStatus - { - private MongoCryptSafeHandle _handle; - private Status _status; - - internal CryptClient(MongoCryptSafeHandle handle, Status status) - { - _handle = handle ?? throw new ArgumentNullException(paramName: nameof(handle)); - _status = status ?? throw new ArgumentNullException(paramName: nameof(status)); - } - - /// - /// Gets the crypt shared library version. - /// - /// A crypt shared library version. - public string CryptSharedLibraryVersion - { - get - { - var versionPtr = Library.mongocrypt_crypt_shared_lib_version_string(_handle, out _); - var result = Marshal.PtrToStringAnsi(versionPtr); - - return result; - } - } - - /// - /// Starts the create data key context. - /// - /// The key identifier. - /// A crypt context for creating a data key - public CryptContext StartCreateDataKeyContext(KmsKeyId keyId) - { - ContextSafeHandle handle = Library.mongocrypt_ctx_new(_handle); - - keyId.SetCredentials(handle, _status); - - handle.Check(_status, Library.mongocrypt_ctx_datakey_init(handle)); - - return new CryptContext(handle); - } - - /// - /// Starts the encryption context. - /// - /// The database of the collection. - /// The command. - /// A encryption context. - public CryptContext StartEncryptionContext(string db, byte[] command) - { - ContextSafeHandle handle = Library.mongocrypt_ctx_new(_handle); - - IntPtr stringPointer = (IntPtr)Marshal.StringToHGlobalAnsi(db); - - try - { - unsafe - { - fixed (byte* c = command) - { - var commandPtr = (IntPtr)c; - using (var pinnedCommand = new PinnedBinary(commandPtr, (uint)command.Length)) - { - // Let mongocrypt run strlen - handle.Check(_status, Library.mongocrypt_ctx_encrypt_init(handle, stringPointer, -1, pinnedCommand.Handle)); - } - } - } - } - finally - { - Marshal.FreeHGlobal(stringPointer); - } - - return new CryptContext(handle); - } - - /// - /// Starts an explicit encryption context. - /// - public CryptContext StartExplicitEncryptionContext(byte[] keyId, byte[] keyAltName, string queryType, long? contentionFactor, string encryptionAlgorithm, byte[] message, byte[] rangeOptions, bool isExpressionMode = false) - { - var handle = Library.mongocrypt_ctx_new(_handle); - - if (keyId != null) - { - PinnedBinary.RunAsPinnedBinary(handle, keyId, _status, (h, pb) => Library.mongocrypt_ctx_setopt_key_id(h, pb)); - } - else if (keyAltName != null) - { - PinnedBinary.RunAsPinnedBinary(handle, keyAltName, _status, (h, pb) => Library.mongocrypt_ctx_setopt_key_alt_name(h, pb)); - } - - if (rangeOptions != null) - { - PinnedBinary.RunAsPinnedBinary(handle, rangeOptions, _status, (h, pb) => Library.mongocrypt_ctx_setopt_algorithm_range(h, pb)); - } - - handle.Check(_status, Library.mongocrypt_ctx_setopt_algorithm(handle, encryptionAlgorithm, -1)); - - if (queryType != null) - { - handle.Check(_status, Library.mongocrypt_ctx_setopt_query_type(handle, queryType, -1)); - } - - if (contentionFactor.HasValue) - { - var contentionFactorInt = contentionFactor.Value; - handle.Check(_status, Library.mongocrypt_ctx_setopt_contention_factor(handle, contentionFactorInt)); - } - - PinnedBinary.RunAsPinnedBinary( - handle, - message, - _status, - (h, pb) => - { - if (isExpressionMode) - { - // mongocrypt_ctx_explicit_encrypt_expression_init shares the same code as mongocrypt_ctx_explicit_encrypt_init. - // The only difference is the validation of the queryType argument: - // * mongocrypt_ctx_explicit_encrypt_expression_init requires queryType of "rangePreview". - // * mongocrypt_ctx_explicit_encrypt_init rejects queryType of "rangePreview". - return Library.mongocrypt_ctx_explicit_encrypt_expression_init(h, pb); - } - else - { - return Library.mongocrypt_ctx_explicit_encrypt_init(h, pb); - } - }); - - return new CryptContext(handle); - } - - /// - /// Starts the decryption context. - /// - /// The bson document to decrypt. - /// A decryption context - public CryptContext StartDecryptionContext(byte[] buffer) - { - ContextSafeHandle handle = Library.mongocrypt_ctx_new(_handle); - - unsafe - { - fixed (byte* p = buffer) - { - IntPtr ptr = (IntPtr)p; - using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)buffer.Length)) - { - handle.Check(_status, Library.mongocrypt_ctx_decrypt_init(handle, pinned.Handle)); - } - } - } - - return new CryptContext(handle); - } - - /// - /// Starts an explicit decryption context. - /// - /// The buffer. - /// A encryption context - public CryptContext StartExplicitDecryptionContext(byte[] buffer) - { - ContextSafeHandle handle = Library.mongocrypt_ctx_new(_handle); - - unsafe - { - fixed (byte* p = buffer) - { - IntPtr ptr = (IntPtr)p; - using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)buffer.Length)) - { - // Let mongocrypt run strlen - handle.Check(_status, Library.mongocrypt_ctx_explicit_decrypt_init(handle, pinned.Handle)); - } - } - } - - return new CryptContext(handle); - } - - public CryptContext StartRewrapMultipleDataKeysContext(KmsKeyId kmsKey, byte[] filter) - { - var handle = Library.mongocrypt_ctx_new(_handle); - - kmsKey.SetCredentials(handle, _status); - - PinnedBinary.RunAsPinnedBinary(handle, filter, _status, (h, pb) => Library.mongocrypt_ctx_rewrap_many_datakey_init(h, pb)); - - return new CryptContext(handle); - } - - void IStatus.Check(Status status) - { - Library.mongocrypt_status(_handle, status.Handle); - } - - #region IDisposable - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - // Adapted from: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netcore-3.0 - if (_handle != null && !_handle.IsInvalid) - { - // Free the handle - _handle.Dispose(); - } - - // Free the status - _status.Dispose(); - } - #endregion - - // private methods - private void Check(bool success) - { - if (!success) - { - _status.Check(this); - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClientFactory.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClientFactory.cs deleted file mode 100644 index fb2ebb9..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClientFactory.cs +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Linq; - -namespace MongoDB.Libmongocrypt -{ - /// - /// A factory for CryptClients. - /// - public class CryptClientFactory - { - // MUST be static fields since otherwise these callbacks can be collected via the garbage collector - // regardless they're used by mongocrypt level or no - private static Library.Delegates.CryptoCallback __cryptoAes256EcbEncryptCallback = new Library.Delegates.CryptoCallback(CipherCallbacks.EncryptEcb); - private static Library.Delegates.CryptoCallback __cryptoAes256CbcDecryptCallback = new Library.Delegates.CryptoCallback(CipherCallbacks.DecryptCbc); - private static Library.Delegates.CryptoCallback __cryptoAes256CbcEncryptCallback = new Library.Delegates.CryptoCallback(CipherCallbacks.EncryptCbc); - private static Library.Delegates.HashCallback __cryptoHashCallback = new Library.Delegates.HashCallback(HashCallback.Hash); - private static Library.Delegates.CryptoHmacCallback __cryptoHmacSha256Callback = new Library.Delegates.CryptoHmacCallback(HmacShaCallbacks.HmacSha256); - private static Library.Delegates.CryptoHmacCallback __cryptoHmacSha512Callback = new Library.Delegates.CryptoHmacCallback(HmacShaCallbacks.HmacSha512); - private static Library.Delegates.RandomCallback __randomCallback = new Library.Delegates.RandomCallback(SecureRandomCallback.GenerateRandom); - private static Library.Delegates.CryptoHmacCallback __signRsaesPkcs1HmacCallback = new Library.Delegates.CryptoHmacCallback(SigningRSAESPKCSCallback.RsaSign); - - // mongocrypt_is_crypto_available is only available in libmongocrypt version >= 1.9 - private static readonly Version __mongocryptIsCryptoAvailableMinVersion = Version.Parse("1.9"); - - /// Creates a CryptClient with the specified options. - /// The options. - /// A CryptClient - public static CryptClient Create(CryptOptions options) - { - MongoCryptSafeHandle handle = null; - Status status = null; - - var cryptoAvailable = Version.Parse(Library.Version.Split('-', '+').First()) >= __mongocryptIsCryptoAvailableMinVersion && Library.mongocrypt_is_crypto_available(); - - try - { - handle = Library.mongocrypt_new(); - status = new Status(); - - if (!cryptoAvailable) - { - handle.Check( - status, - Library.mongocrypt_setopt_crypto_hooks( - handle, - __cryptoAes256CbcEncryptCallback, - __cryptoAes256CbcDecryptCallback, - __randomCallback, - __cryptoHmacSha512Callback, - __cryptoHmacSha256Callback, - __cryptoHashCallback, - IntPtr.Zero)); - - handle.Check( - status, - Library.mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( - handle, - __signRsaesPkcs1HmacCallback, - IntPtr.Zero)); - - handle.Check( - status, - Library.mongocrypt_setopt_aes_256_ecb( - handle, - __cryptoAes256EcbEncryptCallback, - IntPtr.Zero)); - } - - foreach (var kmsCredentials in options.KmsCredentials) - { - kmsCredentials.SetCredentials(handle, status); - } - - if (options.Schema != null) - { - PinnedBinary.RunAsPinnedBinary(handle, options.Schema, status, (h, pb) => Library.mongocrypt_setopt_schema_map(h, pb)); - } - - if (options.EncryptedFieldsMap != null) - { - PinnedBinary.RunAsPinnedBinary(handle, options.EncryptedFieldsMap, status, (h, pb) => Library.mongocrypt_setopt_encrypted_field_config_map(h, pb)); - } - - if (options.BypassQueryAnalysis) - { - Library.mongocrypt_setopt_bypass_query_analysis(handle); - } - - if (options.CryptSharedLibPath != null) - { - Library.mongocrypt_setopt_set_crypt_shared_lib_path_override(handle, options.CryptSharedLibPath); - } - - if (options.CryptSharedLibSearchPath != null) - { - Library.mongocrypt_setopt_append_crypt_shared_lib_search_path(handle, options.CryptSharedLibSearchPath); - } - - Library.mongocrypt_setopt_use_need_kms_credentials_state(handle); - - Library.mongocrypt_init(handle); - - if (options.IsCryptSharedLibRequired) - { - var versionPtr = Library.mongocrypt_crypt_shared_lib_version_string(handle, out _); - if (versionPtr == IntPtr.Zero) - { - throw new CryptException(Library.StatusType.MONGOCRYPT_STATUS_ERROR_CLIENT, uint.MaxValue, "CryptSharedLib is required, but was not found or not loaded."); - } - } - } - catch - { - handle?.Dispose(); - status?.Dispose(); - throw; - } - - return new CryptClient(handle, status); - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptContext.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptContext.cs deleted file mode 100644 index e9a62a8..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptContext.cs +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -namespace MongoDB.Libmongocrypt -{ - /// - /// A encryption or decryption session. It may not be reused. - /// - /// - /// - public class CryptContext : IDisposable, IStatus - { - /// - /// States of the CryptContext state machine - /// - public enum StateCode - { - /// - /// LibMongoCrypt hit an error - /// - MONGOCRYPT_CTX_ERROR = 0, - - /// - /// LibMongoCrypt wants the collection information by running a OP_MSG command against the users' mongod. - /// - MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, - - /// - /// LibMongoCrypt wants a command to be run against mongocryptd. - /// - MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, - - /// - /// LibMongoCrypt wants a command to be run against mongod key vault. - /// - MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, - - /// - /// LibMongoCrypt wants a request sent to KMS. - /// - MONGOCRYPT_CTX_NEED_KMS = 4, - - /// - /// LibMongoCrypt is ready to do encryption, call Finish(). - /// - MONGOCRYPT_CTX_READY = 5, - - /// - /// LibMongoCrypt is complete. - /// - MONGOCRYPT_CTX_DONE = 6, - - /// - /// LibMongoCrypt requires new credentials. - /// - MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS = 7 - } - - private ContextSafeHandle _handle; - private Status _status; - - internal CryptContext(ContextSafeHandle handle) - { - _handle = handle; - _status = new Status(); - } - - /// - /// Gets the state. - /// - /// - /// The state. - /// - public StateCode State - { - get - { - return Library.mongocrypt_ctx_state(_handle); - } - } - - /// - /// Gets a value indicating whether this instance is done. - /// - /// - /// true if this instance is done; otherwise, false. - /// - public bool IsDone - { - get { return State == StateCode.MONGOCRYPT_CTX_DONE; } - } - - /// - /// Gets the operation. - /// - /// Binary payload to send to either KMS, mongod, or mongocryptd - public Binary GetOperation() - { - Binary binary = new Binary(); - Check(Library.mongocrypt_ctx_mongo_op(_handle, binary.Handle)); - return binary; - } - - /// - /// Feeds the result from running a remote operation back to the libmongocrypt. - /// - /// The buffer. - public void Feed(byte[] buffer) - { - unsafe - { - fixed (byte* p = buffer) - { - IntPtr ptr = (IntPtr)p; - using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)buffer.Length)) - { - Check(Library.mongocrypt_ctx_mongo_feed(_handle, pinned.Handle)); - } - } - } - } - - /// - /// Signal the feeding is done. - /// - public void MarkDone() - { - Check(Library.mongocrypt_ctx_mongo_done(_handle)); - } - - /// - /// Finalizes for encryption. - /// - /// The encrypted or decrypted result. - public Binary FinalizeForEncryption() - { - Binary binary = new Binary(); - Check(Library.mongocrypt_ctx_finalize(_handle, binary.Handle)); - return binary; - } - - /// - /// Gets a collection of KMS message requests to make - /// - /// Collection of KMS Messages - public KmsRequestCollection GetKmsMessageRequests() - { - var requests = new List(); - for (IntPtr request = Library.mongocrypt_ctx_next_kms_ctx(_handle); request != IntPtr.Zero; request = Library.mongocrypt_ctx_next_kms_ctx(_handle)) - { - requests.Add(new KmsRequest(request)); - } - - return new KmsRequestCollection(requests, this); - } - - public void SetCredentials(byte[] credentials) - { - PinnedBinary.RunAsPinnedBinary(_handle, credentials, _status, (h, b) => Library.mongocrypt_ctx_provide_kms_providers(h, b)); - } - - void IStatus.Check(Status status) - { - Library.mongocrypt_ctx_status(_handle, status.Handle); - } - - #region IDisposable - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - // Adapted from: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netcore-3.0 - if (_handle != null && !_handle.IsInvalid) - { - // Free the handle - _handle.Dispose(); - } - } - #endregion - - internal void MarkKmsDone() - { - Check(Library.mongocrypt_ctx_kms_done(_handle)); - } - - private void Check(bool success) - { - if (!success) - { - _status.Check(this); - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptException.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptException.cs deleted file mode 100644 index eafe395..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptException.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace MongoDB.Libmongocrypt -{ - /// - /// An exception from libmongocrypt. - /// - /// - public class CryptException : Exception - { - private readonly uint _code; - private readonly Library.StatusType _statusType; - - internal CryptException(Library.StatusType statusType, uint code, string message) - : base(message) - { - _code = code; - _statusType = statusType; - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptOptions.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptOptions.cs deleted file mode 100644 index 2fbe36f..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptOptions.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace MongoDB.Libmongocrypt -{ - /// - /// Options to configure mongocrypt with. - /// - public class CryptOptions - { - public bool BypassQueryAnalysis { get; } - public string CryptSharedLibPath { get; } - public string CryptSharedLibSearchPath { get; } - public byte[] EncryptedFieldsMap { get; } - public bool IsCryptSharedLibRequired { get; } - public IReadOnlyList KmsCredentials { get; } - public byte[] Schema { get; } - - public CryptOptions(IEnumerable credentials) : this(credentials, null) - { - } - - public CryptOptions( - IEnumerable credentials, - byte[] schema) : this(credentials, null, schema, false, null, null, false) - { - } - - public CryptOptions( - IEnumerable credentials, - byte[] encryptedFieldsMap, - byte[] schema, - bool bypassQueryAnalysis, - string cryptSharedLibPath, - string cryptSharedLibSearchPath, - bool isCryptSharedLibRequired) - { - BypassQueryAnalysis = bypassQueryAnalysis; - CryptSharedLibPath = cryptSharedLibPath; - CryptSharedLibSearchPath = cryptSharedLibSearchPath; - IsCryptSharedLibRequired = isCryptSharedLibRequired; - EncryptedFieldsMap = encryptedFieldsMap; - KmsCredentials = new ReadOnlyCollection((credentials ?? throw new ArgumentNullException(nameof(credentials))).ToList()); - Schema = schema; - } - - // TODO: - add configurable logging support - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/HashCallback.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/HashCallback.cs deleted file mode 100644 index 3418d2d..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/HashCallback.cs +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Security.Cryptography; - -namespace MongoDB.Libmongocrypt -{ - internal static class HashCallback - { - public static bool Hash( - IntPtr ctx, - IntPtr @in, - IntPtr @out, - IntPtr statusPtr) - { - using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) - { - try - { - var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); - var outBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); - - var outBytes = CalculateHash(inputBinary.ToArray()); - outBinary.WriteBytes(outBytes); - return true; - } - catch (Exception ex) - { - status.SetStatus(1, ex.Message); - return false; - } - } - } - - public static byte[] CalculateHash(byte[] inputBytes) - { - using (var sha256 = SHA256.Create()) - { - sha256.Initialize(); - _ = sha256.TransformFinalBlock(inputBytes, 0, inputBytes.Length); - return sha256.Hash; - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/HmacShaCallbacks.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/HmacShaCallbacks.cs deleted file mode 100644 index 691aa5e..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/HmacShaCallbacks.cs +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Security.Cryptography; - -namespace MongoDB.Libmongocrypt -{ - internal static class HmacShaCallbacks - { - public static bool HmacSha512( - IntPtr ctx, - IntPtr key, - IntPtr @in, - IntPtr @out, - IntPtr statusPtr) - { - return Hmac(key, @in, @out, statusPtr, bitness: 512); - } - - public static bool HmacSha256( - IntPtr ctx, - IntPtr key, - IntPtr @in, - IntPtr @out, - IntPtr statusPtr) - { - return Hmac(key, @in, @out, statusPtr, bitness: 256); - } - - public static byte[] CalculateHash(byte[] keyBytes, byte[] inputBytes, int bitness) - { - using (var hmac = GetHmacByBitness(bitness, keyBytes)) - { - hmac.Initialize(); - _ = hmac.TransformFinalBlock(inputBytes, 0, inputBytes.Length); - return hmac.Hash; - } - } - - private static HMAC GetHmacByBitness(int bitness, byte[] keyBytes) - { - switch (bitness) - { - case 256: return new HMACSHA256(keyBytes); - case 512: return new HMACSHA512(keyBytes); - default: throw new ArgumentOutOfRangeException($"The bitness {bitness} is unsupported."); // should not be reached - } - } - - private static bool Hmac( - IntPtr key, - IntPtr @in, - IntPtr @out, - IntPtr statusPtr, - int bitness) - { - using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) - { - try - { - var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); - var inBinary = new Binary(BinarySafeHandle.FromIntPtr(@in)); - var outBinary = new Binary(BinarySafeHandle.FromIntPtr(@out)); - - var keyBytes = keyBinary.ToArray(); - var inBytes = inBinary.ToArray(); - - var outBytes = CalculateHash(keyBytes, inBytes, bitness: bitness); - outBinary.WriteBytes(outBytes); - - return true; - } - catch (Exception ex) - { - // let mongocrypt level to handle the error - status.SetStatus(1, ex.Message); - return false; - } - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/IStatus.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/IStatus.cs deleted file mode 100644 index e5f607f..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/IStatus.cs +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace MongoDB.Libmongocrypt -{ - /// - /// Interface for checking the status of the various libmongocrypt options. - /// - internal interface IStatus - { - void Check(Status status); - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsCredentials.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsCredentials.cs deleted file mode 100644 index 9366ebe..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsCredentials.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace MongoDB.Libmongocrypt -{ - /// - /// KMS Credentials. - /// - public class KmsCredentials - { - private readonly byte[] _credentialsBytes; - - /// - /// Creates a class. - /// - /// The byte representation of credentials bson document. - public KmsCredentials(byte[] credentialsBytes) - { - _credentialsBytes = credentialsBytes ?? throw new ArgumentNullException(nameof(credentialsBytes)); - } - - // internal methods - internal void SetCredentials(MongoCryptSafeHandle handle, Status status) - { - unsafe - { - fixed (byte* p = _credentialsBytes) - { - IntPtr ptr = (IntPtr)p; - using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)_credentialsBytes.Length)) - { - handle.Check(status, Library.mongocrypt_setopt_kms_providers(handle, pinned.Handle)); - } - } - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsKeyId.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsKeyId.cs deleted file mode 100644 index f2fda7f..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsKeyId.cs +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Collections.Generic; -using System.Linq; - -namespace MongoDB.Libmongocrypt -{ - /// - /// Represent a kms key. - /// - public class KmsKeyId - { - private readonly IReadOnlyList _alternateKeyNameBytes; - private readonly byte[] _dataKeyOptionsBytes; - private readonly byte[] _keyMaterialBytes; - - /// - /// Creates an class. - /// - /// The byte representation of dataOptions bson document. - /// The byte representation of alternate keyName. - public KmsKeyId( - byte[] dataKeyOptionsBytes, - IEnumerable alternateKeyNameBytes = null, - byte[] keyMaterialBytes = null) - { - _dataKeyOptionsBytes = dataKeyOptionsBytes; - _alternateKeyNameBytes = (alternateKeyNameBytes ?? Enumerable.Empty()).ToList().AsReadOnly(); - _keyMaterialBytes = keyMaterialBytes; - } - - /// - /// Alternate key name bytes. - /// - public IReadOnlyList AlternateKeyNameBytes => _alternateKeyNameBytes; - - /// - /// Data key options bytes. - /// - public byte[] DataKeyOptionsBytes => _dataKeyOptionsBytes; - - /// - /// Key material bytes. - /// - public byte[] KeyMaterialBytes => _keyMaterialBytes; - - // internal methods - internal void SetCredentials(ContextSafeHandle context, Status status) - { - if (_dataKeyOptionsBytes != null) - { - PinnedBinary.RunAsPinnedBinary(context, _dataKeyOptionsBytes, status, (h, pb) => Library.mongocrypt_ctx_setopt_key_encryption_key(h, pb)); - } - - SetAlternateKeyNamesIfConfigured(context, status); - - SetKeyMaterialIfConfigured(context, status); - } - - // private methods - private void SetAlternateKeyNamesIfConfigured(ContextSafeHandle context, Status status) - { - foreach (var alternateKeyNameBytes in _alternateKeyNameBytes) - { - PinnedBinary.RunAsPinnedBinary(context, alternateKeyNameBytes, status, (h, pb) => Library.mongocrypt_ctx_setopt_key_alt_name(h, pb)); - } - } - - private void SetKeyMaterialIfConfigured(ContextSafeHandle context, Status status) - { - if (_keyMaterialBytes != null) - { - PinnedBinary.RunAsPinnedBinary(context, _keyMaterialBytes, status, (h, pb) => Library.mongocrypt_ctx_setopt_key_material(h, pb)); - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsRequest.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsRequest.cs deleted file mode 100644 index 6b4602b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsRequest.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Runtime.InteropServices; - -namespace MongoDB.Libmongocrypt -{ - /// - /// Contains a KMS request to make to a remote server. - /// - /// - public class KmsRequest : IStatus - { - private readonly Status _status; - private readonly IntPtr _id; - - internal KmsRequest(IntPtr id) - { - _id = id; - _status = new Status(); - } - - /// - /// Gets the bytes needed from the remote side. No more data is need when this returns 0. - /// - /// - /// The number of bytes needed. - /// - public uint BytesNeeded - { - get { return Library.mongocrypt_kms_ctx_bytes_needed(_id); } - } - - /// - /// Gets the endpoint. - /// - /// - /// The endpoint. - /// - public string Endpoint - { - get - { - IntPtr stringPointer = IntPtr.Zero; - Check(Library.mongocrypt_kms_ctx_endpoint(_id, ref stringPointer)); - return Marshal.PtrToStringAnsi(stringPointer); - } - } - - /// - /// Gets the kms provider name. - /// - /// - /// The kms provider name. - /// - public string KmsProvider - { - get - { - var kmsProviderNamePointer = Library.mongocrypt_kms_ctx_get_kms_provider(_id, length: out _); - return Marshal.PtrToStringAnsi(kmsProviderNamePointer); - } - } - - /// - /// Gets the message to send to KMS. - /// - /// The message - public Binary Message - { - get { - Binary binary = new Binary(); - - Check(Library.mongocrypt_kms_ctx_message(_id, binary.Handle)); - return binary; - } - } - - /// - /// Feeds the response back to the libmongocrypt - /// - /// The response. - public void Feed(byte[] buffer) - { - unsafe - { - fixed (byte* p = buffer) - { - IntPtr ptr = (IntPtr)p; - using (PinnedBinary pinned = new PinnedBinary(ptr, (uint)buffer.Length)) - { - Check(Library.mongocrypt_kms_ctx_feed(_id, pinned.Handle)); - } - } - } - } - - void IStatus.Check(Status status) - { - Library.mongocrypt_kms_ctx_status(_id, status.Handle); - } - - private void Check(bool success) - { - if (!success) - { - _status.Check(this); - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsRequestCollection.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsRequestCollection.cs deleted file mode 100644 index 01b716b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/KmsRequestCollection.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections; -using System.Collections.Generic; - -namespace MongoDB.Libmongocrypt -{ - /// - /// A collection of kms requests to make. - /// - /// When all requests are done, MarkDone most be called. - /// - /// - public class KmsRequestCollection : IReadOnlyCollection - { - private List _requests; - private CryptContext _parent; - - internal KmsRequestCollection(List requests, CryptContext parent) - { - _requests = requests; - _parent = parent; - } - - int IReadOnlyCollection.Count => _requests.Count; - - IEnumerator IEnumerable.GetEnumerator() - { - return _requests.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return _requests.GetEnumerator(); - } - - /// - /// Marks alls the KMS requests as complete. - /// - public void MarkDone() - { - _parent.MarkKmsDone(); - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Library.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Library.cs deleted file mode 100644 index 13d1bab..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Library.cs +++ /dev/null @@ -1,684 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Runtime.InteropServices; - -namespace MongoDB.Libmongocrypt -{ - /// - /// The low-level interface to libmongocrypt. - /// - public class Library - { - static Library() - { - _mongocrypt_version = new Lazy( - () => __loader.Value.GetFunction("mongocrypt_version"), true); - - _mongocrypt_new = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_new")), true); - _mongocrypt_setopt_log_handler = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_setopt_log_handler")), true); - - _mongocrypt_init = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_init")), true); - _mongocrypt_destroy = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_destroy")), true); - _mongocrypt_status = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_status")), true); - - _mongocrypt_setopt_kms_providers = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_setopt_kms_providers")), true); - _mongocrypt_ctx_setopt_key_encryption_key = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_key_encryption_key")), true); - - _mongocrypt_is_crypto_available = new Lazy( - () => __loader.Value.GetFunction("mongocrypt_is_crypto_available"), true); - - _mongocrypt_setopt_aes_256_ecb = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_setopt_aes_256_ecb")), true); - _mongocrypt_setopt_bypass_query_analysis = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_setopt_bypass_query_analysis")), true); - _mongocrypt_setopt_crypto_hooks = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_setopt_crypto_hooks")), true); - _mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5")), true); - _mongocrypt_setopt_encrypted_field_config_map = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_setopt_encrypted_field_config_map")), true); - _mongocrypt_setopt_schema_map = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_setopt_schema_map")), true); - - _mongocrypt_setopt_append_crypt_shared_lib_search_path = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_setopt_append_crypt_shared_lib_search_path")), true); - _mongocrypt_setopt_set_crypt_shared_lib_path_override = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_setopt_set_crypt_shared_lib_path_override")), true); - _mongocrypt_setopt_use_need_kms_credentials_state = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_setopt_use_need_kms_credentials_state")), true); - _mongocrypt_crypt_shared_lib_version_string = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_crypt_shared_lib_version_string")), true); - _mongocrypt_crypt_shared_lib_version = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_crypt_shared_lib_version")), true); - - _mongocrypt_status_new = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_status_new")), true); - _mongocrypt_status_destroy = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_status_destroy")), - true); - - _mongocrypt_status_type = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_status_type")), true); - _mongocrypt_status_code = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_status_code")), true); - _mongocrypt_status_message = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_status_message")), - true); - _mongocrypt_status_ok = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_status_ok")), true); - _mongocrypt_status_set = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_status_set")), true); - - _mongocrypt_binary_new = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_binary_new")), true); - _mongocrypt_binary_destroy = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_binary_destroy")), - true); - _mongocrypt_binary_new_from_data = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_binary_new_from_data")), true); - _mongocrypt_binary_data = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_binary_data")), true); - _mongocrypt_binary_len = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_binary_len")), true); - - _mongocrypt_ctx_new = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_new")), true); - _mongocrypt_ctx_setopt_key_material = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_key_material")), true); - _mongocrypt_ctx_setopt_masterkey_aws = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_masterkey_aws")), true); - _mongocrypt_ctx_setopt_masterkey_aws_endpoint = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_masterkey_aws_endpoint")), true); - _mongocrypt_ctx_setopt_masterkey_local = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_masterkey_local")), true); - _mongocrypt_ctx_setopt_key_alt_name = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_key_alt_name")), true); - _mongocrypt_ctx_setopt_key_id = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_key_id")), true); - _mongocrypt_ctx_setopt_algorithm = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_algorithm")), true); - _mongocrypt_ctx_setopt_algorithm_range = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_algorithm_range")), true); - _mongocrypt_ctx_setopt_contention_factor = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_contention_factor")), true); - _mongocrypt_ctx_setopt_query_type = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_setopt_query_type")), true); - - _mongocrypt_ctx_status = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_status")), true); - _mongocrypt_ctx_encrypt_init = new Lazy( - () => __loader.Value - .GetFunction(("mongocrypt_ctx_encrypt_init")), true); - _mongocrypt_ctx_decrypt_init = new Lazy( - () => __loader.Value - .GetFunction(("mongocrypt_ctx_decrypt_init")), true); - _mongocrypt_ctx_explicit_encrypt_init = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_explicit_encrypt_init")), true); - _mongocrypt_ctx_explicit_encrypt_expression_init = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_explicit_encrypt_expression_init")), true); - _mongocrypt_ctx_explicit_decrypt_init = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_ctx_explicit_decrypt_init")), true); - _mongocrypt_ctx_datakey_init = new Lazy( - () => __loader.Value - .GetFunction(("mongocrypt_ctx_datakey_init")), true); - _mongocrypt_ctx_provide_kms_providers = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_provide_kms_providers")), true); - _mongocrypt_ctx_state = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_state")), true); - _mongocrypt_ctx_mongo_op = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_mongo_op")), true); - _mongocrypt_ctx_mongo_feed = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_mongo_feed")), - true); - _mongocrypt_ctx_mongo_done = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_mongo_done")), - true); - - _mongocrypt_ctx_next_kms_ctx = new Lazy( - () => __loader.Value - .GetFunction(("mongocrypt_ctx_next_kms_ctx")), true); - _mongocrypt_ctx_rewrap_many_datakey_init = new Lazy( - () => __loader.Value - .GetFunction(("mongocrypt_ctx_rewrap_many_datakey_init")), true); - _mongocrypt_kms_ctx_endpoint = new Lazy( - () => __loader.Value - .GetFunction(("mongocrypt_kms_ctx_endpoint")), true); - _mongocrypt_kms_ctx_message = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_kms_ctx_message")), - true); - _mongocrypt_kms_ctx_bytes_needed = new Lazy( - () => __loader.Value.GetFunction( - ("mongocrypt_kms_ctx_bytes_needed")), true); - _mongocrypt_kms_ctx_feed = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_kms_ctx_feed")), true); - _mongocrypt_kms_ctx_status = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_kms_ctx_status")), - true); - _mongocrypt_ctx_kms_done = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_kms_done")), true); - - _mongocrypt_ctx_finalize = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_finalize")), true); - _mongocrypt_ctx_destroy = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_ctx_destroy")), true); - _mongocrypt_kms_ctx_get_kms_provider = new Lazy( - () => __loader.Value.GetFunction(("mongocrypt_kms_ctx_get_kms_provider")), true); - } - - /// - /// Gets the version of libmongocrypt. - /// - /// - /// The version. - /// - public static string Version - { - get - { - uint length; - IntPtr p = mongocrypt_version(out length); - return Marshal.PtrToStringAnsi(p); - } - } - - internal static Delegates.mongocrypt_version mongocrypt_version => _mongocrypt_version.Value; - - internal static Delegates.mongocrypt_new mongocrypt_new => _mongocrypt_new.Value; - internal static Delegates.mongocrypt_setopt_log_handler mongocrypt_setopt_log_handler => _mongocrypt_setopt_log_handler.Value; - internal static Delegates.mongocrypt_setopt_kms_providers mongocrypt_setopt_kms_providers => _mongocrypt_setopt_kms_providers.Value; - internal static Delegates.mongocrypt_ctx_setopt_key_encryption_key mongocrypt_ctx_setopt_key_encryption_key => _mongocrypt_ctx_setopt_key_encryption_key.Value; - - internal static Delegates.mongocrypt_is_crypto_available mongocrypt_is_crypto_available => _mongocrypt_is_crypto_available.Value; - - internal static Delegates.mongocrypt_setopt_aes_256_ecb mongocrypt_setopt_aes_256_ecb => _mongocrypt_setopt_aes_256_ecb.Value; - internal static Delegates.mongocrypt_setopt_bypass_query_analysis mongocrypt_setopt_bypass_query_analysis => _mongocrypt_setopt_bypass_query_analysis.Value; - internal static Delegates.mongocrypt_setopt_crypto_hooks mongocrypt_setopt_crypto_hooks => _mongocrypt_setopt_crypto_hooks.Value; - internal static Delegates.mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5 => _mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5.Value; - internal static Delegates.mongocrypt_setopt_encrypted_field_config_map mongocrypt_setopt_encrypted_field_config_map => _mongocrypt_setopt_encrypted_field_config_map.Value; - internal static Delegates.mongocrypt_setopt_schema_map mongocrypt_setopt_schema_map => _mongocrypt_setopt_schema_map.Value; - - internal static Delegates.mongocrypt_setopt_append_crypt_shared_lib_search_path mongocrypt_setopt_append_crypt_shared_lib_search_path => _mongocrypt_setopt_append_crypt_shared_lib_search_path.Value; - internal static Delegates.mongocrypt_setopt_set_crypt_shared_lib_path_override mongocrypt_setopt_set_crypt_shared_lib_path_override => _mongocrypt_setopt_set_crypt_shared_lib_path_override.Value; - internal static Delegates.mongocrypt_setopt_use_need_kms_credentials_state mongocrypt_setopt_use_need_kms_credentials_state => _mongocrypt_setopt_use_need_kms_credentials_state.Value; - internal static Delegates.mongocrypt_crypt_shared_lib_version_string mongocrypt_crypt_shared_lib_version_string => _mongocrypt_crypt_shared_lib_version_string.Value; - internal static Delegates.mongocrypt_crypt_shared_lib_version mongocrypt_crypt_shared_lib_version => _mongocrypt_crypt_shared_lib_version.Value; - - internal static Delegates.mongocrypt_init mongocrypt_init => _mongocrypt_init.Value; - internal static Delegates.mongocrypt_destroy mongocrypt_destroy => _mongocrypt_destroy.Value; - internal static Delegates.mongocrypt_status mongocrypt_status => _mongocrypt_status.Value; - internal static Delegates.mongocrypt_status_new mongocrypt_status_new => _mongocrypt_status_new.Value; - internal static Delegates.mongocrypt_status_destroy mongocrypt_status_destroy => _mongocrypt_status_destroy.Value; - - internal static Delegates.mongocrypt_status_type mongocrypt_status_type => _mongocrypt_status_type.Value; - internal static Delegates.mongocrypt_status_code mongocrypt_status_code => _mongocrypt_status_code.Value; - internal static Delegates.mongocrypt_status_message mongocrypt_status_message => _mongocrypt_status_message.Value; - internal static Delegates.mongocrypt_status_ok mongocrypt_status_ok => _mongocrypt_status_ok.Value; - internal static Delegates.mongocrypt_status_set mongocrypt_status_set => _mongocrypt_status_set.Value; - - internal static Delegates.mongocrypt_binary_new mongocrypt_binary_new => _mongocrypt_binary_new.Value; - internal static Delegates.mongocrypt_binary_destroy mongocrypt_binary_destroy => _mongocrypt_binary_destroy.Value; - internal static Delegates.mongocrypt_binary_new_from_data mongocrypt_binary_new_from_data => _mongocrypt_binary_new_from_data.Value; - internal static Delegates.mongocrypt_binary_data mongocrypt_binary_data => _mongocrypt_binary_data.Value; - internal static Delegates.mongocrypt_binary_len mongocrypt_binary_len => _mongocrypt_binary_len.Value; - - internal static Delegates.mongocrypt_ctx_new mongocrypt_ctx_new => _mongocrypt_ctx_new.Value; - internal static Delegates.mongocrypt_ctx_setopt_key_material mongocrypt_ctx_setopt_key_material => _mongocrypt_ctx_setopt_key_material.Value; - internal static Delegates.mongocrypt_ctx_setopt_masterkey_aws mongocrypt_ctx_setopt_masterkey_aws => _mongocrypt_ctx_setopt_masterkey_aws.Value; - internal static Delegates.mongocrypt_ctx_setopt_masterkey_aws_endpoint mongocrypt_ctx_setopt_masterkey_aws_endpoint => _mongocrypt_ctx_setopt_masterkey_aws_endpoint.Value; - internal static Delegates.mongocrypt_ctx_status mongocrypt_ctx_status => _mongocrypt_ctx_status.Value; - internal static Delegates.mongocrypt_ctx_encrypt_init mongocrypt_ctx_encrypt_init => _mongocrypt_ctx_encrypt_init.Value; - internal static Delegates.mongocrypt_ctx_decrypt_init mongocrypt_ctx_decrypt_init => _mongocrypt_ctx_decrypt_init.Value; - internal static Delegates.mongocrypt_ctx_explicit_encrypt_init mongocrypt_ctx_explicit_encrypt_init => _mongocrypt_ctx_explicit_encrypt_init.Value; - internal static Delegates.mongocrypt_ctx_explicit_encrypt_expression_init mongocrypt_ctx_explicit_encrypt_expression_init => _mongocrypt_ctx_explicit_encrypt_expression_init.Value; - internal static Delegates.mongocrypt_ctx_explicit_decrypt_init mongocrypt_ctx_explicit_decrypt_init => _mongocrypt_ctx_explicit_decrypt_init.Value; - internal static Delegates.mongocrypt_ctx_datakey_init mongocrypt_ctx_datakey_init => _mongocrypt_ctx_datakey_init.Value; - internal static Delegates.mongocrypt_ctx_provide_kms_providers mongocrypt_ctx_provide_kms_providers => _mongocrypt_ctx_provide_kms_providers.Value; - internal static Delegates.mongocrypt_ctx_setopt_masterkey_local mongocrypt_ctx_setopt_masterkey_local => _mongocrypt_ctx_setopt_masterkey_local.Value; - internal static Delegates.mongocrypt_ctx_setopt_key_id mongocrypt_ctx_setopt_key_id => _mongocrypt_ctx_setopt_key_id.Value; - internal static Delegates.mongocrypt_ctx_setopt_key_alt_name mongocrypt_ctx_setopt_key_alt_name => _mongocrypt_ctx_setopt_key_alt_name.Value; - internal static Delegates.mongocrypt_ctx_setopt_algorithm mongocrypt_ctx_setopt_algorithm => _mongocrypt_ctx_setopt_algorithm.Value; - internal static Delegates.mongocrypt_ctx_setopt_algorithm_range mongocrypt_ctx_setopt_algorithm_range => _mongocrypt_ctx_setopt_algorithm_range.Value; - internal static Delegates.mongocrypt_ctx_setopt_contention_factor mongocrypt_ctx_setopt_contention_factor => _mongocrypt_ctx_setopt_contention_factor.Value; - internal static Delegates.mongocrypt_ctx_setopt_query_type mongocrypt_ctx_setopt_query_type => _mongocrypt_ctx_setopt_query_type.Value; - - internal static Delegates.mongocrypt_ctx_state mongocrypt_ctx_state => _mongocrypt_ctx_state.Value; - internal static Delegates.mongocrypt_ctx_mongo_op mongocrypt_ctx_mongo_op => _mongocrypt_ctx_mongo_op.Value; - internal static Delegates.mongocrypt_ctx_mongo_feed mongocrypt_ctx_mongo_feed => _mongocrypt_ctx_mongo_feed.Value; - internal static Delegates.mongocrypt_ctx_mongo_done mongocrypt_ctx_mongo_done => _mongocrypt_ctx_mongo_done.Value; - - internal static Delegates.mongocrypt_ctx_next_kms_ctx mongocrypt_ctx_next_kms_ctx => _mongocrypt_ctx_next_kms_ctx.Value; - internal static Delegates.mongocrypt_ctx_rewrap_many_datakey_init mongocrypt_ctx_rewrap_many_datakey_init => _mongocrypt_ctx_rewrap_many_datakey_init.Value; - internal static Delegates.mongocrypt_kms_ctx_endpoint mongocrypt_kms_ctx_endpoint => _mongocrypt_kms_ctx_endpoint.Value; - internal static Delegates.mongocrypt_kms_ctx_message mongocrypt_kms_ctx_message => _mongocrypt_kms_ctx_message.Value; - internal static Delegates.mongocrypt_kms_ctx_bytes_needed mongocrypt_kms_ctx_bytes_needed => _mongocrypt_kms_ctx_bytes_needed.Value; - internal static Delegates.mongocrypt_kms_ctx_feed mongocrypt_kms_ctx_feed => _mongocrypt_kms_ctx_feed.Value; - internal static Delegates.mongocrypt_kms_ctx_status mongocrypt_kms_ctx_status => _mongocrypt_kms_ctx_status.Value; - internal static Delegates.mongocrypt_ctx_kms_done mongocrypt_ctx_kms_done => _mongocrypt_ctx_kms_done.Value; - internal static Delegates.mongocrypt_ctx_finalize mongocrypt_ctx_finalize => _mongocrypt_ctx_finalize.Value; - internal static Delegates.mongocrypt_ctx_destroy mongocrypt_ctx_destroy => _mongocrypt_ctx_destroy.Value; - internal static Delegates.mongocrypt_kms_ctx_get_kms_provider mongocrypt_kms_ctx_get_kms_provider => _mongocrypt_kms_ctx_get_kms_provider.Value; - - private static readonly Lazy __loader = new Lazy( - () => new LibraryLoader(), true); - private static readonly Lazy _mongocrypt_version; - private static readonly Lazy _mongocrypt_new; - private static readonly Lazy _mongocrypt_setopt_log_handler; - - private static readonly Lazy _mongocrypt_setopt_kms_providers; - private static readonly Lazy _mongocrypt_ctx_setopt_key_encryption_key; - - private static readonly Lazy _mongocrypt_is_crypto_available; - - private static readonly Lazy _mongocrypt_setopt_aes_256_ecb; - private static readonly Lazy _mongocrypt_setopt_bypass_query_analysis; - private static readonly Lazy _mongocrypt_setopt_crypto_hooks; - private static readonly Lazy _mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5; - private static readonly Lazy _mongocrypt_setopt_encrypted_field_config_map; - private static readonly Lazy _mongocrypt_setopt_schema_map; - - private static readonly Lazy _mongocrypt_setopt_append_crypt_shared_lib_search_path; - private static readonly Lazy _mongocrypt_setopt_set_crypt_shared_lib_path_override; - private static readonly Lazy _mongocrypt_setopt_use_need_kms_credentials_state; - private static readonly Lazy _mongocrypt_crypt_shared_lib_version_string; - private static readonly Lazy _mongocrypt_crypt_shared_lib_version; - - private static readonly Lazy _mongocrypt_init; - private static readonly Lazy _mongocrypt_destroy; - - private static readonly Lazy _mongocrypt_status; - - private static readonly Lazy _mongocrypt_status_new; - private static readonly Lazy _mongocrypt_status_destroy; - private static readonly Lazy _mongocrypt_status_type; - private static readonly Lazy _mongocrypt_status_code; - private static readonly Lazy _mongocrypt_status_message; - private static readonly Lazy _mongocrypt_status_ok; - private static readonly Lazy _mongocrypt_status_set; - - private static readonly Lazy _mongocrypt_binary_new; - private static readonly Lazy _mongocrypt_binary_destroy; - private static readonly Lazy _mongocrypt_binary_new_from_data; - private static readonly Lazy _mongocrypt_binary_data; - private static readonly Lazy _mongocrypt_binary_len; - - private static readonly Lazy _mongocrypt_ctx_new; - - private static readonly Lazy _mongocrypt_ctx_setopt_key_material; - private static readonly Lazy _mongocrypt_ctx_setopt_masterkey_aws; - private static readonly Lazy _mongocrypt_ctx_setopt_masterkey_aws_endpoint; - - private static readonly Lazy _mongocrypt_ctx_status; - private static readonly Lazy _mongocrypt_ctx_encrypt_init; - private static readonly Lazy _mongocrypt_ctx_decrypt_init; - - private static readonly Lazy _mongocrypt_ctx_explicit_encrypt_init; - private static readonly Lazy _mongocrypt_ctx_explicit_encrypt_expression_init; - - private static readonly Lazy _mongocrypt_ctx_explicit_decrypt_init; - - private static readonly Lazy _mongocrypt_ctx_datakey_init; - private static readonly Lazy _mongocrypt_ctx_provide_kms_providers; - - private static readonly Lazy _mongocrypt_ctx_setopt_masterkey_local; - - private static readonly Lazy _mongocrypt_ctx_setopt_key_id; - private static readonly Lazy _mongocrypt_ctx_setopt_key_alt_name; - private static readonly Lazy _mongocrypt_ctx_setopt_algorithm; - private static readonly Lazy _mongocrypt_ctx_setopt_algorithm_range; - private static readonly Lazy _mongocrypt_ctx_setopt_contention_factor; - private static readonly Lazy _mongocrypt_ctx_setopt_query_type; - - private static readonly Lazy _mongocrypt_ctx_state; - private static readonly Lazy _mongocrypt_ctx_mongo_op; - private static readonly Lazy _mongocrypt_ctx_mongo_feed; - private static readonly Lazy _mongocrypt_ctx_mongo_done; - - private static readonly Lazy _mongocrypt_ctx_next_kms_ctx; - private static readonly Lazy _mongocrypt_ctx_rewrap_many_datakey_init; - private static readonly Lazy _mongocrypt_kms_ctx_endpoint; - private static readonly Lazy _mongocrypt_kms_ctx_message; - private static readonly Lazy _mongocrypt_kms_ctx_bytes_needed; - private static readonly Lazy _mongocrypt_kms_ctx_feed; - private static readonly Lazy _mongocrypt_kms_ctx_status; - private static readonly Lazy _mongocrypt_ctx_kms_done; - private static readonly Lazy _mongocrypt_ctx_finalize; - private static readonly Lazy _mongocrypt_ctx_destroy; - private static readonly Lazy _mongocrypt_kms_ctx_get_kms_provider; - - // nested types - internal enum StatusType - { - MONGOCRYPT_STATUS_OK = 0, - MONGOCRYPT_STATUS_ERROR_CLIENT, - MONGOCRYPT_STATUS_ERROR_KMS - } - - internal class Delegates - { - // NOTE: Bool is expected to be 4 bytes during marshalling so we need to overwite it - // https://blogs.msdn.microsoft.com/jaredpar/2008/10/14/pinvoke-and-bool-or-should-i-say-bool/ - public delegate IntPtr mongocrypt_version(out uint length); - - public delegate MongoCryptSafeHandle mongocrypt_new(); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_is_crypto_available(); - - public delegate void LogCallback([MarshalAs(UnmanagedType.I4)] LogLevel level, IntPtr messasge, - uint message_length, IntPtr context); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_setopt_log_handler(MongoCryptSafeHandle handle, - [MarshalAs(UnmanagedType.FunctionPtr)] LogCallback log_fn, IntPtr log_ctx); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_setopt_kms_providers( - MongoCryptSafeHandle handle, BinarySafeHandle kms_providers); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_key_encryption_key( - ContextSafeHandle handle, BinarySafeHandle bin); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool HashCallback( - IntPtr ctx, - IntPtr @in, - IntPtr @out, - IntPtr status); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool CryptoHmacCallback( - IntPtr ctx, - IntPtr key, - IntPtr @in, - IntPtr @out, - IntPtr status); - - /// - /// typedef bool (*mongocrypt_crypto_fn) ( - /// void *ctx, - // mongocrypt_binary_t* key, - // mongocrypt_binary_t *iv, - // mongocrypt_binary_t*in, - // mongocrypt_binary_t*out, - // uint32_t* bytes_written, - // mongocrypt_status_t *status); - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool CryptoCallback( - IntPtr ctx, - IntPtr key, - IntPtr iv, - IntPtr @in, - IntPtr @out, - ref uint bytes_written, - IntPtr status); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool RandomCallback( - IntPtr ctx, - IntPtr @out, - uint count, - IntPtr statusPtr); - - /// - /// bool mongocrypt_setopt_aes_256_ecb(mongocrypt_t* crypt, mongocrypt_crypto_fn aes_256_ecb_encrypt, void* ctx); - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_setopt_aes_256_ecb( - MongoCryptSafeHandle handle, - [MarshalAs(UnmanagedType.FunctionPtr)] CryptoCallback aes_256_ecb_encrypt, - IntPtr ctx); - - /// - /// void mongocrypt_setopt_bypass_query_analysis(mongocrypt_t* crypt); - /// - public delegate void mongocrypt_setopt_bypass_query_analysis(MongoCryptSafeHandle handle); - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_setopt_crypto_hooks( - MongoCryptSafeHandle handle, - [MarshalAs(UnmanagedType.FunctionPtr)] CryptoCallback aes_256_cbc_encrypt, - [MarshalAs(UnmanagedType.FunctionPtr)] CryptoCallback aes_256_cbc_decrypt, - [MarshalAs(UnmanagedType.FunctionPtr)] RandomCallback random, - [MarshalAs(UnmanagedType.FunctionPtr)] CryptoHmacCallback hmac_sha_512, - [MarshalAs(UnmanagedType.FunctionPtr)] CryptoHmacCallback hmac_sha_256, - [MarshalAs(UnmanagedType.FunctionPtr)] HashCallback mongocrypt_hash_fn, - IntPtr ctx); - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( - MongoCryptSafeHandle handle, - [MarshalAs(UnmanagedType.FunctionPtr)] CryptoHmacCallback sign_rsaes_pkcs1_v1_5, - IntPtr sign_ctx); - /// - /// bool mongocrypt_setopt_encrypted_field_config_map(mongocrypt_t* crypt, mongocrypt_binary_t* efc_map) - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_setopt_encrypted_field_config_map(MongoCryptSafeHandle handle, BinarySafeHandle efc_map); - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_setopt_schema_map(MongoCryptSafeHandle handle, BinarySafeHandle schema); - /// - /// void mongocrypt_setopt_append_crypt_shared_lib_search_path(mongocrypt_t* crypt, const char* path); - /// - public delegate void mongocrypt_setopt_append_crypt_shared_lib_search_path(MongoCryptSafeHandle handle, [MarshalAs(UnmanagedType.LPStr)] string path); - /// - /// void mongocrypt_setopt_set_crypt_shared_lib_path_override(mongocrypt_t* crypt, const char* path); - /// - public delegate void mongocrypt_setopt_set_crypt_shared_lib_path_override(MongoCryptSafeHandle handle, [MarshalAs(UnmanagedType.LPStr)] string path); - /// - /// void mongocrypt_setopt_use_need_kms_credentials_state(mongocrypt_t* crypt); - /// - /// - public delegate void mongocrypt_setopt_use_need_kms_credentials_state(MongoCryptSafeHandle handle); - /// - /// const char * mongocrypt_crypt_shared_lib_version_string(const mongocrypt_t* crypt, uint32_t *len); - /// - public delegate IntPtr mongocrypt_crypt_shared_lib_version_string(MongoCryptSafeHandle handle, out uint length); - /// - /// uint64_t mongocrypt_crypt_shared_lib_version(const mongocrypt_t* crypt); - /// - public delegate ulong mongocrypt_crypt_shared_lib_version(MongoCryptSafeHandle handle); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_init(MongoCryptSafeHandle handle); - - public delegate void mongocrypt_destroy(IntPtr ptr); - - public delegate bool mongocrypt_status(MongoCryptSafeHandle handle, StatusSafeHandle ptr); - - public delegate StatusSafeHandle mongocrypt_status_new(); - - public delegate void mongocrypt_status_destroy(IntPtr ptr); - - public delegate StatusType mongocrypt_status_type(StatusSafeHandle ptr); - - public delegate uint mongocrypt_status_code(StatusSafeHandle ptr); - - public delegate IntPtr mongocrypt_status_message(StatusSafeHandle ptr, out uint length); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_status_ok(StatusSafeHandle ptr); - - // currently it does nothing due to MONGOCRYPT-257 - public delegate void mongocrypt_status_set(StatusSafeHandle ptr, int type, uint code, IntPtr msg, int length); - - public delegate BinarySafeHandle mongocrypt_binary_new(); - - public delegate void mongocrypt_binary_destroy(IntPtr ptr); - - public delegate BinarySafeHandle mongocrypt_binary_new_from_data(IntPtr ptr, uint len); - - public delegate IntPtr mongocrypt_binary_data(BinarySafeHandle handle); - - public delegate uint mongocrypt_binary_len(BinarySafeHandle handle); - - public delegate ContextSafeHandle mongocrypt_ctx_new(MongoCryptSafeHandle handle); - /// - /// bool mongocrypt_ctx_setopt_key_material(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* key_material) - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_key_material(ContextSafeHandle handle, BinarySafeHandle key_material); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_masterkey_aws(ContextSafeHandle handle, IntPtr region, - int region_len, IntPtr cmk, int cmk_len); - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_masterkey_aws_endpoint( - ContextSafeHandle handle, - IntPtr endpoint, - int endpoint_len); - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_status(ContextSafeHandle handle, StatusSafeHandle status); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_encrypt_init(ContextSafeHandle handle, IntPtr ns, int length, - BinarySafeHandle binary); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_decrypt_init(ContextSafeHandle handle, BinarySafeHandle binary); - - /// - /// bool mongocrypt_ctx_explicit_encrypt_init(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* msg) - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_explicit_encrypt_init(ContextSafeHandle handle, BinarySafeHandle binary); - /// - /// bool mongocrypt_ctx_explicit_encrypt_expression_init(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* msg) - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_explicit_encrypt_expression_init(ContextSafeHandle handle, BinarySafeHandle msg); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool - mongocrypt_ctx_explicit_decrypt_init(ContextSafeHandle handle, BinarySafeHandle binary); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_datakey_init(ContextSafeHandle handle); - - /// - /// bool mongocrypt_ctx_provide_kms_providers(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* kms_providers_definition); - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_provide_kms_providers(ContextSafeHandle handle, BinarySafeHandle kms_providers_definition); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_schema_map(ContextSafeHandle handle, BinarySafeHandle binary); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_masterkey_local(ContextSafeHandle handle); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_key_alt_name(ContextSafeHandle handle, BinarySafeHandle binary); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_key_id(ContextSafeHandle handle, BinarySafeHandle binary); - - /// - /// bool mongocrypt_ctx_setopt_algorithm(mongocrypt_ctx_t* ctx, const char* algorithm, int len); - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_algorithm(ContextSafeHandle handle, [MarshalAs(UnmanagedType.LPStr)] string algorithm, int length); - /// - /// bool mongocrypt_ctx_setopt_algorithm_range(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* opts); - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_algorithm_range(ContextSafeHandle handle, BinarySafeHandle opts); - /// - /// bool mongocrypt_ctx_setopt_contention_factor(mongocrypt_ctx_t* ctx, int64_t contention_factor); - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_contention_factor(ContextSafeHandle ctx, long contention_factor); - /// - /// bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t* ctx, const char* query_type, int len) - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_setopt_query_type(ContextSafeHandle ctx, [MarshalAs(UnmanagedType.LPStr)] string query_type, int length); - - public delegate CryptContext.StateCode mongocrypt_ctx_state(ContextSafeHandle handle); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_mongo_op(ContextSafeHandle handle, BinarySafeHandle bsonOp); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_mongo_feed(ContextSafeHandle handle, BinarySafeHandle reply); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_mongo_done(ContextSafeHandle handle); - - public delegate IntPtr mongocrypt_ctx_next_kms_ctx(ContextSafeHandle handle); - - /// - /// bool mongocrypt_ctx_rewrap_many_datakey_init(mongocrypt_ctx_t* ctx, mongocrypt_binary_t* filter); - /// - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_rewrap_many_datakey_init(ContextSafeHandle handle, BinarySafeHandle filter); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_kms_ctx_endpoint(IntPtr handle, ref IntPtr endpoint); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_kms_ctx_message(IntPtr handle, BinarySafeHandle binary); - - public delegate uint mongocrypt_kms_ctx_bytes_needed(IntPtr handle); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_kms_ctx_feed(IntPtr handle, BinarySafeHandle binary); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_kms_ctx_status(IntPtr handle, StatusSafeHandle status); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_kms_done(ContextSafeHandle handle); - - [return: MarshalAs(UnmanagedType.I1)] - public delegate bool mongocrypt_ctx_finalize(ContextSafeHandle handle, BinarySafeHandle binary); - - public delegate void mongocrypt_ctx_destroy(IntPtr ptr); - public delegate IntPtr mongocrypt_kms_ctx_get_kms_provider(IntPtr handle, out uint length); - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoader.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoader.cs deleted file mode 100644 index cccb36a..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoader.cs +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace MongoDB.Libmongocrypt -{ - /// - /// LibraryLoader abstracts loading C functions from a shared library across OS - /// - internal class LibraryLoader - { - private ISharedLibraryLoader _loader; - private static readonly string __libmongocryptLibPath = Environment.GetEnvironmentVariable("LIBMONGOCRYPT_PATH"); - - public LibraryLoader() - { - if (!Environment.Is64BitProcess) - { - throw new PlatformNotSupportedException($"{this.GetType().Namespace} needs to be run in a 64-bit process."); - } - - // Windows: - // https://stackoverflow.com/questions/2864673/specify-the-search-path-for-dllimport-in-net - // - // See for better ways - // https://github.com/dotnet/coreclr/issues/930 - // https://github.com/dotnet/corefx/issues/32015 - List candidatePaths = new List(); - - // In the nuget package, get the shared library from a relative path of this assembly - // Also, when running locally, get the shared library from a relative path of this assembly - var assembly = typeof(LibraryLoader).GetTypeInfo().Assembly; - var location = assembly.Location; - string basepath = Path.GetDirectoryName(location); - candidatePaths.Add(basepath); - - switch (OperatingSystemHelper.CurrentOperatingSystem) - { - case OperatingSystemPlatform.MacOS: - _loader = new DarwinLibraryLoader(candidatePaths); - break; - case OperatingSystemPlatform.Linux: - _loader = new LinuxLibrary(candidatePaths); - break; - case OperatingSystemPlatform.Windows: - _loader = new WindowsLibrary(candidatePaths); - break; - default: - // should not be reached. If we're here, then there is a bug in OperatingSystemHelper - throw new PlatformNotSupportedException("Unsupported operating system."); - } - } - - private static string FindLibrary(IList basePaths, string[] suffixPaths, string library) - { - var candidates = new List(); - foreach (var basePath in basePaths) - { - foreach (var suffix in suffixPaths) - { - string path = Path.Combine(basePath, suffix, library); - if (File.Exists(path)) - { - return path; - } - candidates.Add(path); - } - } - - throw new FileNotFoundException("Could not find: " + library + " --\n Tried: " + string.Join(",", candidates)); - } - - public T GetFunction(string name) - { - IntPtr ptr = _loader.GetFunction(name); - if (ptr == IntPtr.Zero) - { - throw new FunctionNotFoundException(name); - } - - return Marshal.GetDelegateForFunctionPointer(ptr); - - } - - public class FunctionNotFoundException : Exception - { - public FunctionNotFoundException(string message) : base(message) { } - } - - private interface ISharedLibraryLoader - { - IntPtr GetFunction(string name); - } - - /// - /// macOS Dynamic Library loader using dlsym - /// - private class DarwinLibraryLoader : ISharedLibraryLoader - { - - // See dlfcn.h - // #define RTLD_LAZY 0x1 - // #define RTLD_NOW 0x2 - // #define RTLD_LOCAL 0x4 - // #define RTLD_GLOBAL 0x8 - public const int RTLD_GLOBAL = 0x8; - public const int RTLD_NOW = 0x2; - - private static readonly string[] __suffixPaths = - { - "../../runtimes/osx/native/", - "runtimes/osx/native/", - string.Empty - }; - - private readonly IntPtr _handle; - public DarwinLibraryLoader(List candidatePaths) - { - var path = __libmongocryptLibPath ?? FindLibrary(candidatePaths, __suffixPaths, "libmongocrypt.dylib"); - _handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW); - if (_handle == IntPtr.Zero) - { - throw new FileNotFoundException(path); - } - } - - public IntPtr GetFunction(string name) - { - return dlsym(_handle, name); - } - -#pragma warning disable IDE1006 // Naming Styles - [DllImport("libdl")] - public static extern IntPtr dlopen(string filename, int flags); - - [DllImport("libdl", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr dlsym(IntPtr handle, string symbol); -#pragma warning restore IDE1006 // Naming Styles - } - - /// - /// Linux Shared Object loader using dlsym - /// - private class LinuxLibrary : ISharedLibraryLoader - { - // See dlfcn.h - // #define RTLD_LAZY 0x1 - // #define RTLD_NOW 0x2 - // #define RTLD_LOCAL 0x4 - // #define RTLD_GLOBAL 0x100 - public const int RTLD_GLOBAL = 0x100; - public const int RTLD_NOW = 0x2; - private static readonly bool _use_libdl1; - - static LinuxLibrary() - { - try - { - Libdl1.dlerror(); - _use_libdl1 = true; - } - catch - { - _use_libdl1 = false; - } - } - - private static readonly string[] __suffixPaths = - { - "../../runtimes/linux/native/", - "runtimes/linux/native/", - string.Empty - }; - - private readonly IntPtr _handle; - public LinuxLibrary(List candidatePaths) - { - var path = __libmongocryptLibPath ?? FindLibrary(candidatePaths, __suffixPaths, "libmongocrypt.so"); - - _handle = _use_libdl1 - ? Libdl1.dlopen(path, RTLD_GLOBAL | RTLD_NOW) - : Libdl2.dlopen(path, RTLD_GLOBAL | RTLD_NOW); - - if (_handle == IntPtr.Zero) - { - throw new FileNotFoundException(path); - } - } - - public IntPtr GetFunction(string name) - { - return _use_libdl1 ? Libdl1.dlsym(_handle, name) : Libdl2.dlsym(_handle, name); - } - } - - /// - /// Windows DLL loader using GetProcAddress - /// - private class WindowsLibrary : ISharedLibraryLoader - { - private static readonly string[] __suffixPaths = - { - @"..\..\runtimes\win\native\", - @".\runtimes\win\native\", - string.Empty - }; - - private readonly IntPtr _handle; - public WindowsLibrary(List candidatePaths) - { - var path = __libmongocryptLibPath ?? FindLibrary(candidatePaths, __suffixPaths, "mongocrypt.dll"); - _handle = LoadLibrary(path); - if (_handle == IntPtr.Zero) - { - var gle = Marshal.GetLastWin32Error(); - - // error code 193 indicates that a 64-bit OS has tried to load a 32-bit dll - // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499- - throw new LibraryLoadingException(path + ", Windows Error: " + gle); - } - } - - public IntPtr GetFunction(string name) - { - var ptr = GetProcAddress(_handle, name); - if (ptr == null) - { - var gle = Marshal.GetLastWin32Error(); - throw new FunctionNotFoundException(name + ", Windows Error: " + gle); - } - - return ptr; - } - - [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)] - public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); - - [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] - public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); - } - - private static class Libdl1 - { - private const string LibName = "libdl"; - -#pragma warning disable IDE1006 // Naming Styles - [DllImport(LibName)] - public static extern IntPtr dlopen(string filename, int flags); - - [DllImport(LibName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr dlsym(IntPtr handle, string symbol); - - [DllImport(LibName)] - public static extern string dlerror(); -#pragma warning restore IDE1006 // Naming Styles - } - - private static class Libdl2 - { - private const string LibName = "libdl.so.2"; - -#pragma warning disable IDE1006 // Naming Styles - [DllImport(LibName)] - public static extern IntPtr dlopen(string filename, int flags); - - [DllImport(LibName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr dlsym(IntPtr handle, string symbol); -#pragma warning restore IDE1006 // Naming Styles - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoadingException.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoadingException.cs deleted file mode 100644 index ba545fd..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoadingException.cs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -using System; - -namespace MongoDB.Libmongocrypt -{ - /// - /// An exception that indicates that an error occured while loading a library. - /// - public class LibraryLoadingException : Exception - { - /// - /// Initializes an instance of a - /// - /// The message. - public LibraryLoadingException(string message) : base(message) - { - } - - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/License.txt b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/License.txt deleted file mode 100644 index b5ee401..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/License.txt +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright 2010–present MongoDB Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LogLevel.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LogLevel.cs deleted file mode 100644 index 66dcc0e..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LogLevel.cs +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace MongoDB.Libmongocrypt -{ - public enum LogLevel { - MONGOCRYPT_LOG_LEVEL_FATAL = 0, - MONGOCRYPT_LOG_LEVEL_ERROR = 1, - MONGOCRYPT_LOG_LEVEL_WARNING = 2, - MONGOCRYPT_LOG_LEVEL_INFO = 3, - MONGOCRYPT_LOG_LEVEL_TRACE = 4 - }; -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoCryptSafeHandle.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoCryptSafeHandle.cs deleted file mode 100644 index ab6609e..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoCryptSafeHandle.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Runtime.ConstrainedExecution; - -namespace MongoDB.Libmongocrypt -{ - /// - /// SafeHandle to manage the lifetime of a mongocrypt_t. - /// - /// - internal class MongoCryptSafeHandle : CheckableSafeHandle - { - private MongoCryptSafeHandle() : base() - { - } - - public override void Check(Status status, bool success) - { - if (!success) - { - Library.mongocrypt_status(this, status.Handle); - status.ThrowExceptionIfNeeded(); - } - } - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected override bool ReleaseHandle() - { - // Here, we must obey all rules for constrained execution regions. - Library.mongocrypt_destroy(handle); - return true; - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj deleted file mode 100644 index 049f45e..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj +++ /dev/null @@ -1,107 +0,0 @@ - - - - net472;netstandard2.0;netstandard2.1 - netstandard2.0;netstandard2.1 - AnyCPU - 7.3 - true - MongoDB.Libmongocrypt.ruleset - - - - MongoDB.Libmongocrypt - MongoDB.Libmongocrypt - MongoDB Inc. - Copyright © 2019–present MongoDB Inc. - Libmongocrypt wrapper for the .NET driver. - MongoDB Inc. - http://jobs.mongodb.org/files/logos/889002/889002.png - true - Libmongocrypt wrapper for the .NET driver. - http://www.mongodb.org/display/DOCS/CSharp+Language+Center - License.txt - mongodb;mongo;nosql - en-US - true - true - ..\MongoDB.Driver.snk - - - - ../../../cmake-build/$(Configuration) - - - - - libmongocrypt.so - Always - - - - libmongocrypt.dylib - Always - - - - mongocrypt.dll - Always - - - - mongocrypt.pdb - Always - - - - - - - true - runtimes/win/native - - - true - runtimes/linux/native - - - true - runtimes/osx/native - - - - - - true - $(PackageLicenseFile) - - - - - - true - build - - - - - 1.1.0 - - - - bin\x64\Debug\MongoDB.Libmongocrypt.xml - - - - true - bin\x64\Release\MongoDB.Libmongocrypt.xml - - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.ruleset b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.ruleset deleted file mode 100644 index bea289f..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.ruleset +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.targets b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.targets deleted file mode 100644 index 3d3ff67..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.targets +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Always - mongocrypt.dll - - - - - Always - libmongocrypt.so - - - - - Always - libmongocrypt.dylib - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/OperatingSystemHelper.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/OperatingSystemHelper.cs deleted file mode 100644 index c084a70..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/OperatingSystemHelper.cs +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !NET472 -using System; -using System.Runtime.InteropServices; -#endif - -namespace MongoDB.Libmongocrypt -{ - internal enum OperatingSystemPlatform - { - Windows, - Linux, - MacOS - } - - internal static class OperatingSystemHelper - { - public static OperatingSystemPlatform CurrentOperatingSystem - { - get - { -#if NET472 - return OperatingSystemPlatform.Windows; -#else - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return OperatingSystemPlatform.MacOS; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return OperatingSystemPlatform.Linux; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return OperatingSystemPlatform.Windows; - } - - // should not be reached. If we're here, then there is a bug in the library - throw new PlatformNotSupportedException($"Unsupported platform '{RuntimeInformation.OSDescription}'."); -#endif - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Package.include.template.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Package.include.template.csproj deleted file mode 100644 index dcc97a0..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Package.include.template.csproj +++ /dev/null @@ -1,38 +0,0 @@ - - - - false - @CMAKE_CURRENT_LIST_DIR@/MongoDB.Libmongocrypt - - - - - - - - - PreserveNewest - x64/native/linux/libmongocrypt.so - true - - - - PreserveNewest - x64/native/osx/libmongocrypt.dylib - true - - - - PreserveNewest - x64/native/windows/mongocrypt.dll - true - - - - PreserveNewest - x64/native/windows/mongocrypt.dll - true - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/PinnedBinary.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/PinnedBinary.cs deleted file mode 100644 index f63e42e..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/PinnedBinary.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace MongoDB.Libmongocrypt -{ - /// - /// A handle to a binary that must be either in unsafe code or pinned by the GC. - /// - /// - internal class PinnedBinary : Binary - { - #region static - internal static void RunAsPinnedBinary(THandle handle, byte[] bytes, Status status, Func handleFunc) where THandle : CheckableSafeHandle - { - unsafe - { - fixed (byte* map = bytes) - { - var ptr = (IntPtr)map; - using (var pinned = new PinnedBinary(ptr, (uint)bytes.Length)) - { - handle.Check(status, handleFunc(handle, pinned.Handle)); - } - } - } - } - #endregion - - internal PinnedBinary(IntPtr ptr, uint len) - : base(Library.mongocrypt_binary_new_from_data(ptr, len)) - { - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/SecureRandomCallback.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/SecureRandomCallback.cs deleted file mode 100644 index caf1bb0..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/SecureRandomCallback.cs +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Security.Cryptography; - -namespace MongoDB.Libmongocrypt -{ - internal static class SecureRandomCallback - { - public static bool GenerateRandom( - IntPtr ctx, - IntPtr @out, - uint count, - IntPtr statusPtr) - { - using (var outBinary = new Binary(BinarySafeHandle.FromIntPtr(@out))) - using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) - { - try - { - using (var randomNumberGenerator = RandomNumberGenerator.Create()) - { - var bytes = new byte[count]; - randomNumberGenerator.GetBytes(bytes); - outBinary.WriteBytes(bytes); - return true; - } - } - catch (Exception e) - { - status.SetStatus(1, e.Message); - return false; - } - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/SigningRSAESPKCSCallback.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/SigningRSAESPKCSCallback.cs deleted file mode 100644 index c166b36..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/SigningRSAESPKCSCallback.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2020–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -#if NETSTANDARD2_1 -using System.Security.Cryptography; -#endif - -namespace MongoDB.Libmongocrypt -{ - internal static class SigningRSAESPKCSCallback - { - public static bool RsaSign( - IntPtr ctx, - IntPtr key, - IntPtr inData, - IntPtr outData, - IntPtr statusPtr) - { - using (var status = new Status(StatusSafeHandle.FromIntPtr(statusPtr))) - { - try - { - var keyBinary = new Binary(BinarySafeHandle.FromIntPtr(key)); - var inputBinary = new Binary(BinarySafeHandle.FromIntPtr(inData)); - var outBinary = new Binary(BinarySafeHandle.FromIntPtr(outData)); - - byte[] inputBytes = inputBinary.ToArray(); - byte[] keyBytes = keyBinary.ToArray(); - - // Hash and sign the data. - var signedData = HashAndSignBytes(inputBytes, keyBytes); - - outBinary.WriteBytes(signedData); - - return true; - } - catch (Exception e) - { - // let mongocrypt level to handle the error - status.SetStatus(1, e.Message); - return false; - } - } - } - - public static byte[] HashAndSignBytes(byte[] dataToSign, byte[] key) - { -#if NETSTANDARD2_1 - using (var rsaProvider = new RSACryptoServiceProvider()) - { - rsaProvider.ImportPkcs8PrivateKey(key, out _); - - return rsaProvider.SignData(dataToSign, SHA256.Create()); - } -#else - throw new System.PlatformNotSupportedException("RSACryptoServiceProvider.ImportPkcs8PrivateKey is supported only on frameworks higher or equal to .netstandard2.1."); -#endif - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Status.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Status.cs deleted file mode 100644 index fbde6d8..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Status.cs +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Runtime.InteropServices; - -namespace MongoDB.Libmongocrypt -{ - /// - /// A LibMongoCrypt Status - /// - /// - internal class Status : IDisposable - { - private StatusSafeHandle _handle; - - public Status() - { - _handle = Library.mongocrypt_status_new(); - } - - public Status(StatusSafeHandle handle) - { - _handle = handle; - } - - public void Check(IStatus status) - { - status.Check(this); - ThrowExceptionIfNeeded(); - } - - public void SetStatus(uint code, string msg) - { - IntPtr stringPointer = (IntPtr)Marshal.StringToHGlobalAnsi(msg); - try - { - Library.mongocrypt_status_set(_handle, (int)Library.StatusType.MONGOCRYPT_STATUS_ERROR_CLIENT, code, stringPointer, -1); - } - finally - { - Marshal.FreeHGlobal(stringPointer); - } - } - - #region IDisposable - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - // Adapted from: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netcore-3.0 - if (_handle != null && !_handle.IsInvalid) - { - // Free the handle - _handle.Dispose(); - } - } - #endregion - - internal StatusSafeHandle Handle => _handle; - - internal void ThrowExceptionIfNeeded() - { - if (!Library.mongocrypt_status_ok(_handle)) - { - var statusType = Library.mongocrypt_status_type(_handle); - var statusCode = Library.mongocrypt_status_code(_handle); - - uint length; - IntPtr msgPtr = Library.mongocrypt_status_message(_handle, out length); - var message = Marshal.PtrToStringAnsi(msgPtr); - - throw new CryptException(statusType, statusCode, message); - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/StatusSafeHandle.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/StatusSafeHandle.cs deleted file mode 100644 index 50ecc3c..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/StatusSafeHandle.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2019–present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; - -namespace MongoDB.Libmongocrypt -{ - /// - /// SafeHandle to manage the lifetime of a mongocrypt_status_t. - /// - /// - internal class StatusSafeHandle : SafeHandle - { - private StatusSafeHandle() - : base(IntPtr.Zero, true) - { - } - - private StatusSafeHandle(IntPtr ptr) - : base(ptr, false) - { - } - - public static StatusSafeHandle FromIntPtr(IntPtr ptr) - { - return new StatusSafeHandle(ptr); - } - - public override bool IsInvalid - { - get - { - return handle == IntPtr.Zero; - } - } - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected override bool ReleaseHandle() - { - // Here, we must obey all rules for constrained execution regions. - Library.mongocrypt_status_destroy(handle); - return true; - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/StyleCop.ruleset b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/StyleCop.ruleset deleted file mode 100644 index 3222b85..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/StyleCop.ruleset +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/stylecop.json b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/stylecop.json deleted file mode 100644 index bf24a78..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/stylecop.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", - "settings": { - "layoutRules": { - "newlineAtEndOfFile": "require" - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/README.md b/ext/libmongocrypt/libmongocrypt/bindings/cs/README.md index 2469dc1..e58949a 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/README.md +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/README.md @@ -1,69 +1,6 @@ -# Requirements +### The C# bindings have been moved! -__All__ - -CMake 3.12 or later - -__Windows__ - -Visual Studio 2017 15.9+ - -__Linux, macOS__ - -dotnet 2.1+ - - -# Quick Instructions - -*Requires:* Cygwin -``` -1. bash ./libmongocrypt/.evergreen/compile.sh -``` -*Note*: You must call this from the parent directory of the libmongocrypt repo. It will not work within the repo directory - - -## Developer Instructions - -### Windows -To build libmongocrypt on Windows. This example assumes kms-message and the c driver are installed to "d:/usr" - -``` -1. mkdir build -2. "C:\Program Files\CMake\bin\cmake.exe" -Thost=x64 -G "Visual Studio 15 2017 Win64" -DCMAKE_INSTALL_PREFIX=d:/usr -DCMAKE_PREFIX_PATH=d:/usr -DCMAKE_BUILD_TYPE=Debug "-DCMAKE_C_FLAGS=-Id:/usr/include" .. -3. msbuild libmongocrypt.sln -4. cd bindings/cs -5. msbuild cs.sln -``` - -### Troubleshooting - -If you see `Windows Error: 126` during tests, like the example below, it means that `libbson-1.0.dll` is not in your path. - -``` - System.TypeInitializationException : The type initializer for 'MongoDB.Libmongocrypt.Library' threw an exception. ----- System.IO.FileNotFoundException : D:\repo\libmongocrypt\build\bindings\cs\MongoDB.Libmongocrypt.Test\bin\x64\Debug\netcoreapp2.1\mongocrypt.dll, Windows Error: 126 -``` - - -### Linux and macOS - -*Note* Only building from the cmake build directory is supported - -``` -1. Build libmongocrypt with CMake -2. cd /bindings/cs -3. dotnet build cs.build -``` -*Note*: You can use the ```LIBMONGOCRYPT_PATH``` environment variable to load a locally installed -libmongocrypt build. You should specify the absolute path to the libmongocrypt library itself, not just the containing folder. For example on Linux: -```$ export LIBMONGOCRYPT_PATH='/path/to/libmongocrypt.so'```. - -# Testing -Do not modify xunit.runner.json -- Be wary of https://github.com/xunit/xunit/issues/1654 - -### Debugging on Linux -To attach to a unit test with lldb, print the PID in the process and then attach. - -Tests always run in child processes and lldb, as of 7.0, cannot follow child processes. +#### https://github.com/mongodb/mongo-csharp-driver/tree/main/src/MongoDB.Driver.Encryption +They have been renamed from ```MongoDB.Libmongocrypt``` to ```MongoDB.Driver.Encryption``` +and can be found on nuget here: https://www.nuget.org/packages/MongoDB.Driver.Encryption/ diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.cake b/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.cake deleted file mode 100644 index 84adfcf..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.cake +++ /dev/null @@ -1,215 +0,0 @@ -#addin nuget:?package=Cake.FileHelpers&version=5.0.0 -#addin nuget:?package=Cake.Git&version=2.0.0 -#addin nuget:?package=Cake.Incubator&version=7.0.0 -#tool dotnet:?package=GitVersion.Tool&version=5.10.3 - -using System; -using System.Linq; - -var target = Argument("target", "CreatePackage"); -var configuration = Argument("configuration", "Release"); - -var gitVersion = GitVersion(); - -var buildDirectory = MakeAbsolute(Directory(GetSettingValue("buildDirectory", "c:\\build"))); -var libmongocryptAllDirectory=buildDirectory.Combine("libmongocrypt-all"); -var downloadedMongocryptDirectory=buildDirectory.Combine("downloadedMongocryptDirectory"); -var localReleaseVersion = "0.0.0-local"; -var releaseVersion = GetSettingValue("releaseVersion", localReleaseVersion); -var fork = GetSettingValue("fork", "git@github.com:mongodb/libmongocrypt.git"); -var branch = GetSettingValue("branch", "master"); - -// 1.10.0 - latest libmongocrypt release -var libmongocryptAllUrl = GetSettingValue("url", "https://mciuploads.s3.amazonaws.com/libmongocrypt/all/1.10.0/libmongocrypt-all.tar.gz"); - -var csharpBindingsGitTagName = $"csharp-v{releaseVersion}"; -var csharpBindingsDirectory = buildDirectory.Combine(csharpBindingsGitTagName); -var libmongocryptRelWithDebInfoDirectory = csharpBindingsDirectory.Combine("cmake-build").Combine($"{configuration}"); -var libmongocryptCsDirectory = csharpBindingsDirectory.Combine("bindings").Combine("cs"); -var libmongocryptSolutionDirectory = libmongocryptCsDirectory.Combine("MongoDB.Libmongocrypt"); -var libmongocryptSolutionFile = libmongocryptSolutionDirectory.CombineWithFilePath("MongoDB.Libmongocrypt.csproj"); -var libmongocryptTestsSolutionDirectory = libmongocryptCsDirectory.Combine("MongoDB.Libmongocrypt.Test"); -var artifactsDirectory = buildDirectory.Combine("artifacts"); - -Task("Prepare") - .Does(() => - { - if (DirectoryExists(buildDirectory)) - { - DeleteDirectory( - buildDirectory, - new DeleteDirectorySettings { - Recursive = true, - Force = true - }); - } - CreateDirectory(buildDirectory); - - Information($"Release version: {releaseVersion}"); - Information($"Fork: {fork}"); - Information($"Branch: {branch}"); - Information($"Native libraries url: {libmongocryptAllUrl}"); - - Information("Downloading native libs.."); - EnsureDirectoryExists(libmongocryptAllDirectory); - var nativeLibrariesArchive = libmongocryptAllDirectory.CombineWithFilePath("libmongocrypt-all.tar"); - DownloadFile(libmongocryptAllUrl, nativeLibrariesArchive); - - Information("Unzipping.."); - UncompressToTheCurrentDirectory(nativeLibrariesArchive); - - Information("Cloning the libmongocrypt repo.."); - EnsureDirectoryExists(csharpBindingsDirectory); - Git(csharpBindingsDirectory, $"clone {fork} -b {branch} ."); - Information("Done git clone.."); - - EnsureDirectoryExists(libmongocryptRelWithDebInfoDirectory); - EnsureDirectoryExists(downloadedMongocryptDirectory); - CopyFile( - libmongocryptAllDirectory.Combine("windows-test").Combine("bin").CombineWithFilePath("mongocrypt.dll"), - downloadedMongocryptDirectory.CombineWithFilePath("mongocrypt.dll")); - CopyFile( - libmongocryptAllDirectory.Combine("ubuntu1804-64").Combine("nocrypto").Combine("lib").CombineWithFilePath("libmongocrypt.so"), - downloadedMongocryptDirectory.CombineWithFilePath("libmongocrypt.so")); - CopyFile( - libmongocryptAllDirectory.Combine("macos").Combine("lib").CombineWithFilePath("libmongocrypt.dylib"), - downloadedMongocryptDirectory.CombineWithFilePath("libmongocrypt.dylib")); - CopyDirectory(downloadedMongocryptDirectory, libmongocryptRelWithDebInfoDirectory); - }); - -Task("Tests") - .IsDependentOn("Prepare") - .DoesForEach( - () => - { - var monikersDetails = new List<(string Moniker, string Bitness)> - { - { ("net472", "x64") }, - { ("netcoreapp2.1", "x64") }, - { ("netcoreapp3.0", "x64") }, - { ("net50", "x64") } - }; - return monikersDetails; - }, - (monikerInfo) => - { - Information($"Test running {monikerInfo.Moniker}.."); - var settings = new DotNetTestSettings - { - Configuration = configuration, - Framework = monikerInfo.Moniker, - ArgumentCustomization = args => args.Append($"-- RunConfiguration.TargetPlatform={monikerInfo.Bitness}") - }; - var projectFullPath = libmongocryptTestsSolutionDirectory.CombineWithFilePath("MongoDB.Libmongocrypt.Test.csproj").FullPath; - Information(projectFullPath); - DotNetTest( - projectFullPath, - settings - ); - }) - .DeferOnError(); - -Task("CreatePackage") - .IsDependentOn("Tests") - .Does(() => - { - var projectFullPath = libmongocryptSolutionFile.FullPath; - Information($"Project path: {projectFullPath}. ReleaseVersion: {releaseVersion}"); - var settings = new DotNetPackSettings - { - Configuration = configuration, - OutputDirectory = artifactsDirectory, - EnvironmentVariables = new Dictionary - { - { "Version", releaseVersion }, - } - }; - DotNetPack( - projectFullPath, - settings); - }); - -Task("NugetPush") - .Does(() => - { - ThrowIfLocalRelease(); - - var nugetApi = GetSettingValue("NugetApiKey", null); - var packageFilePath = artifactsDirectory.CombineWithFilePath($"{libmongocryptSolutionFile.GetFilenameWithoutExtension().ToString()}.{releaseVersion}.nupkg"); - Information(packageFilePath); - DotNetNuGetPush( - packageFilePath, - new DotNetNuGetPushSettings - { - ApiKey = nugetApi, - Source = "https://api.nuget.org/v3/index.json" - }); - }); - -Task("CreateGitTag") - .Does(() => - { - ThrowIfLocalRelease(); - - Information($"Directory: {libmongocryptSolutionDirectory}"); - Information("Show origin:"); - Git(libmongocryptSolutionDirectory, "remote -v"); - Git(libmongocryptSolutionDirectory, $"tag -a {csharpBindingsGitTagName} -m {csharpBindingsGitTagName}"); - Git(libmongocryptSolutionDirectory, $"push origin {csharpBindingsGitTagName}"); - }); - -RunTarget(target); - -string GetSettingValue(string commandArgumentName, string defaultValue) -{ - var optionValue = Argument(commandArgumentName, (string)null); - if (optionValue != null) - { - return optionValue; - } - - var environmentVariableName = $"LIBMONGOCRYPT_PACKAGING_{commandArgumentName.ToUpper()}"; - var environmentVariable = Environment.GetEnvironmentVariable(environmentVariableName); - if (environmentVariable == null) - { - if (defaultValue == null) - { - throw new Exception($"Neither {commandArgumentName} command argument nor {environmentVariableName} environmentVariable have been configured."); - } - else - { - return defaultValue; - } - } - - return environmentVariable; -} - -void Git(DirectoryPath workingDirectory, string command) -{ - CustomToolCall(workingDirectory, "git", command); -} - -void UncompressToTheCurrentDirectory(FilePath archiveFilePath) -{ - CustomToolCall(archiveFilePath.GetDirectory(), "tar", "xzvf", archiveFilePath.GetFilename().ToString()); -} - -void CustomToolCall(DirectoryPath workingDirectory, string tool, params string[] arguments) -{ - var argumentsBuilder = new ProcessArgumentBuilder(); - foreach (var argument in arguments) - { - argumentsBuilder.Append(argument); - } - Information($"{tool} {string.Join(" ", arguments)}"); - StartProcess(tool, new ProcessSettings { Arguments = argumentsBuilder, WorkingDirectory = workingDirectory }); -} - -void ThrowIfLocalRelease() -{ - if (releaseVersion == localReleaseVersion) - { - throw new Exception("Attempt to publish a local nuget."); - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.config b/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.config deleted file mode 100644 index 6600eee..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.config +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -CAKE_VERSION=2.2.0 -DOTNET_VERSION=6.0.400 \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.ps1 b/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.ps1 deleted file mode 100644 index 1f9fe37..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.ps1 +++ /dev/null @@ -1,275 +0,0 @@ -########################################################################## -# This is the Cake bootstrapper script for PowerShell. -# This file was downloaded from https://github.com/cake-build/resources -# Feel free to change this file to fit your needs. -########################################################################## - -<# - -.SYNOPSIS -This is a Powershell script to bootstrap a Cake build. - -.DESCRIPTION -This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) -and execute your Cake build script with the parameters you provide. - -.PARAMETER Script -The build script to execute. -.PARAMETER Target -The build script target to run. -.PARAMETER Configuration -The build configuration to use. -.PARAMETER Verbosity -Specifies the amount of information to be displayed. -.PARAMETER ShowDescription -Shows description about tasks. -.PARAMETER DryRun -Performs a dry run. -.PARAMETER SkipToolPackageRestore -Skips restoring of packages. -.PARAMETER ScriptArgs -Remaining arguments are added here. - -.LINK -https://cakebuild.net - -#> - -[CmdletBinding()] -Param( - [string]$Script, - [string]$Target, - [string]$Configuration, - [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] - [string]$Verbosity, - [switch]$ShowDescription, - [Alias("WhatIf", "Noop")] - [switch]$DryRun, - [switch]$SkipToolPackageRestore, - [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] - [string[]]$ScriptArgs -) - -# This is an automatic variable in PowerShell Core, but not in Windows PowerShell 5.x -if (-not (Test-Path variable:global:IsCoreCLR)) { - $IsCoreCLR = $false -} - -# Attempt to set highest encryption available for SecurityProtocol. -# PowerShell will not set this by default (until maybe .NET 4.6.x). This -# will typically produce a message for PowerShell v2 (just an info -# message though) -try { - # Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48) - # Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won't - # exist in .NET 4.0, even though they are addressable if .NET 4.5+ is - # installed (.NET 4.5 is an in-place upgrade). - # PowerShell Core already has support for TLS 1.2 so we can skip this if running in that. - if (-not $IsCoreCLR) { - [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48 - } - } catch { - Write-Output 'Unable to set PowerShell to use TLS 1.2 and TLS 1.1 due to old .NET Framework installed. If you see underlying connection closed or trust errors, you may need to upgrade to .NET Framework 4.5+ and PowerShell v3' - } - -[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null -function MD5HashFile([string] $filePath) -{ - if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) - { - return $null - } - - [System.IO.Stream] $file = $null; - [System.Security.Cryptography.MD5] $md5 = $null; - try - { - $md5 = [System.Security.Cryptography.MD5]::Create() - $file = [System.IO.File]::OpenRead($filePath) - return [System.BitConverter]::ToString($md5.ComputeHash($file)) - } - finally - { - if ($file -ne $null) - { - $file.Dispose() - } - } -} - -function GetProxyEnabledWebClient -{ - $wc = New-Object System.Net.WebClient - $proxy = [System.Net.WebRequest]::GetSystemWebProxy() - $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials - $wc.Proxy = $proxy - return $wc -} - -Write-Host "Preparing to run build script..." - -if(!$PSScriptRoot){ - $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent -} - -if(!$Script){ - $Script = Join-Path $PSScriptRoot "build.cake" -} -$TOOLS_DIR = Join-Path $PSScriptRoot "tools" -$ADDINS_DIR = Join-Path $TOOLS_DIR "Addins" -$MODULES_DIR = Join-Path $TOOLS_DIR "Modules" -$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" -$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" -$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" -$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" -$ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config" -$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config" - -$env:CAKE_PATHS_TOOLS = $TOOLS_DIR -$env:CAKE_PATHS_ADDINS = $ADDINS_DIR -$env:CAKE_PATHS_MODULES = $MODULES_DIR - -# Make sure tools folder exists -if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { - Write-Verbose -Message "Creating tools directory..." - New-Item -Path $TOOLS_DIR -Type Directory | Out-Null -} - -# Make sure that packages.config exist. -if (!(Test-Path $PACKAGES_CONFIG)) { - Write-Verbose -Message "Downloading packages.config..." - try { - $wc = GetProxyEnabledWebClient - $wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) - } catch { - Throw "Could not download packages.config." - } -} - -# Try find NuGet.exe in path if not exists -if (!(Test-Path $NUGET_EXE)) { - Write-Verbose -Message "Trying to find nuget.exe in PATH..." - $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) } - $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 - if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { - Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." - $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName - } -} - -# Try download NuGet.exe if not exists -if (!(Test-Path $NUGET_EXE)) { - Write-Verbose -Message "Downloading NuGet.exe..." - try { - $wc = GetProxyEnabledWebClient - $wc.DownloadFile($NUGET_URL, $NUGET_EXE) - } catch { - Throw "Could not download NuGet.exe." - } -} - -# These are automatic variables in PowerShell Core, but not in Windows PowerShell 5.x -if (-not (Test-Path variable:global:ismacos)) { - $IsLinux = $false - $IsMacOS = $false -} - -# Save nuget.exe path to environment to be available to child processed -$env:NUGET_EXE = $NUGET_EXE -$env:NUGET_EXE_INVOCATION = if ($IsLinux -or $IsMacOS) { - "mono `"$NUGET_EXE`"" -} else { - "`"$NUGET_EXE`"" -} - -# Restore tools from NuGet? -if(-Not $SkipToolPackageRestore.IsPresent) { - Push-Location - Set-Location $TOOLS_DIR - - # Check for changes in packages.config and remove installed tools if true. - [string] $md5Hash = MD5HashFile $PACKAGES_CONFIG - if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or - ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { - Write-Verbose -Message "Missing or changed package.config hash..." - Get-ChildItem -Exclude packages.config,nuget.exe,Cake.Bakery | - Remove-Item -Recurse -Force - } - - Write-Verbose -Message "Restoring tools from NuGet..." - - $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" - - if ($LASTEXITCODE -ne 0) { - Throw "An error occurred while restoring NuGet tools." - } - else - { - $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" - } - Write-Verbose -Message ($NuGetOutput | Out-String) - - Pop-Location -} - -# Restore addins from NuGet -if (Test-Path $ADDINS_PACKAGES_CONFIG) { - Push-Location - Set-Location $ADDINS_DIR - - Write-Verbose -Message "Restoring addins from NuGet..." - $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`"" - - if ($LASTEXITCODE -ne 0) { - Throw "An error occurred while restoring NuGet addins." - } - - Write-Verbose -Message ($NuGetOutput | Out-String) - - Pop-Location -} - -# Restore modules from NuGet -if (Test-Path $MODULES_PACKAGES_CONFIG) { - Push-Location - Set-Location $MODULES_DIR - - Write-Verbose -Message "Restoring modules from NuGet..." - $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`"" - - if ($LASTEXITCODE -ne 0) { - Throw "An error occurred while restoring NuGet modules." - } - - Write-Verbose -Message ($NuGetOutput | Out-String) - - Pop-Location -} - -# Make sure that Cake has been installed. -if (!(Test-Path $CAKE_EXE)) { - Throw "Could not find Cake.exe at $CAKE_EXE" -} - -$CAKE_EXE_INVOCATION = if ($IsLinux -or $IsMacOS) { - "mono `"$CAKE_EXE`"" -} else { - "`"$CAKE_EXE`"" -} - - # Build an array (not a string) of Cake arguments to be joined later -$cakeArguments = @() -if ($Script) { $cakeArguments += "`"$Script`"" } -if ($Target) { $cakeArguments += "--target=`"$Target`"" } -if ($Configuration) { $cakeArguments += "--configuration=$Configuration" } -if ($Verbosity) { $cakeArguments += "--verbosity=$Verbosity" } -if ($ShowDescription) { $cakeArguments += "--showdescription" } -if ($DryRun) { $cakeArguments += "--dryrun" } -$cakeArguments += $ScriptArgs - -# Start Cake -Write-Host "Running build script..." -Invoke-Expression "& $CAKE_EXE_INVOCATION --bootstrap" -Invoke-Expression "& $CAKE_EXE_INVOCATION $($cakeArguments -join " ")" -exit $LASTEXITCODE diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.sh b/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.sh deleted file mode 100755 index 45c4883..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash -# Define varibles -SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -source $SCRIPT_DIR/build.config -TOOLS_DIR=$SCRIPT_DIR/tools -CAKE_EXE=$TOOLS_DIR/dotnet-cake -CAKE_PATH=$TOOLS_DIR/.store/cake.tool/$CAKE_VERSION - -if [ "$CAKE_VERSION" = "" ] || [ "$DOTNET_VERSION" = "" ]; then - echo "An error occured while parsing Cake / .NET Core SDK version." - exit 1 -fi - -# Make sure the tools folder exist. -if [ ! -d "$TOOLS_DIR" ]; then - mkdir "$TOOLS_DIR" -fi - -########################################################################### -# INSTALL .NET CORE CLI -########################################################################### - -export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 -export DOTNET_CLI_TELEMETRY_OPTOUT=1 -export DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0 -export DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX=2 - -DOTNET_INSTALLED_VERSION=$(dotnet --version 2>&1) - -if [ "$DOTNET_VERSION" != "$DOTNET_INSTALLED_VERSION" ]; then - echo "Installing .NET CLI..." - if [ ! -d "$SCRIPT_DIR/.dotnet" ]; then - mkdir "$SCRIPT_DIR/.dotnet" - fi - curl -Lsfo "$SCRIPT_DIR/.dotnet/dotnet-install.sh" https://dot.net/v1/dotnet-install.sh - bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --channel 1.1 --install-dir .dotnet --no-path - bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --channel 2.1 --install-dir .dotnet --no-path - bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --version $DOTNET_VERSION --install-dir .dotnet --no-path - export PATH="$SCRIPT_DIR/.dotnet":$PATH - export DOTNET_ROOT="$SCRIPT_DIR/.dotnet" -fi - -########################################################################### -# INSTALL CAKE -########################################################################### - -CAKE_INSTALLED_VERSION=$(dotnet-cake --version 2>&1) - -if [ "$CAKE_VERSION" != "$CAKE_INSTALLED_VERSION" ]; then - if [ ! -f "$CAKE_EXE" ] || [ ! -d "$CAKE_PATH" ]; then - if [ -f "$CAKE_EXE" ]; then - dotnet tool uninstall --tool-path $TOOLS_DIR Cake.Tool - fi - - echo "Installing Cake $CAKE_VERSION..." - dotnet tool install --tool-path $TOOLS_DIR --version $CAKE_VERSION Cake.Tool - if [ $? -ne 0 ]; then - echo "An error occured while installing Cake." - exit 1 - fi - fi - - # Make sure that Cake has been installed. - if [ ! -f "$CAKE_EXE" ]; then - echo "Could not find Cake.exe at '$CAKE_EXE'." - exit 1 - fi -else - CAKE_EXE="dotnet-cake" -fi - -########################################################################### -# RUN BUILD SCRIPT -########################################################################### - -# Start Cake -(exec "$CAKE_EXE" build.cake --bootstrap) && (exec "$CAKE_EXE" build.cake "$@") diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/build.gradle.kts b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/build.gradle.kts index dd9ce02..a58258e 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/build.gradle.kts +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/build.gradle.kts @@ -45,7 +45,7 @@ allprojects { } group = "org.mongodb" -version = "1.11.0-SNAPSHOT" +version = "1.12.0-SNAPSHOT" description = "MongoDB client-side crypto support" java { diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-test.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-test.sh index 8bf1eb1..2efdc9a 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-test.sh +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-test.sh @@ -10,27 +10,21 @@ BASE_PYTHON=$(find_python3) # MONGOCRYPT_DIR is set by libmongocrypt/.evergreen/config.yml MONGOCRYPT_DIR="$MONGOCRYPT_DIR" +CRYPT_SHARED_DIR="$DRIVERS_TOOLS" MACHINE=$(uname -m) if [ $MACHINE == "aarch64" ]; then PYTHON="/opt/mongodbtoolchain/v4/bin/python3" - TARGET=rhel82 else - TARGET=rhel80 - PYTHON="/opt/python/3.8/bin/python3" + PYTHON="/opt/python/3.13/bin/python3" fi -CRYPT_SHARED_DIR="$(pwd)/crypt_shared" -/opt/mongodbtoolchain/v3/bin/python3 $DRIVERS_TOOLS/.evergreen/mongodl.py --component \ - crypt_shared --version latest --out $CRYPT_SHARED_DIR --target $TARGET - -if [ -e "${MONGOCRYPT_DIR}/lib64/" ]; then - export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib64/libmongocrypt.so - PYMONGOCRYPT_LIB_CRYPTO=${MONGOCRYPT_DIR}/lib64/libmongocrypt.so +if [ -d "${MONGOCRYPT_DIR}/nocrypto/lib64" ]; then + PYMONGOCRYPT_LIB="${MONGOCRYPT_DIR}/nocrypto/lib64/libmongocrypt.so" else - export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib/libmongocrypt.so - PYMONGOCRYPT_LIB_CRYPTO=${MONGOCRYPT_DIR}/lib/libmongocrypt.so + PYMONGOCRYPT_LIB="${MONGOCRYPT_DIR}/nocrypto/lib/libmongocrypt.so" fi +export PYMONGOCRYPT_LIB createvirtualenv $PYTHON .venv pip install -e . @@ -38,9 +32,9 @@ pushd $PYMONGO_DIR pip install -e ".[test,encryption]" source ${DRIVERS_TOOLS}/.evergreen/csfle/secrets-export.sh set -x -TEST_CRYPT_SHARED=1 DYLD_FALLBACK_LIBRARY_PATH=$CRYPT_SHARED_DIR/lib/:${DYLD_FALLBACK_LIBRARY_PATH:-} \ - LD_LIBRARY_PATH=$CRYPT_SHARED_DIR/lib:${LD_LIBRARY_PATH-} \ - PATH=$CRYPT_SHARED_DIR/bin:$PATH \ +TEST_CRYPT_SHARED=1 DYLD_FALLBACK_LIBRARY_PATH=$CRYPT_SHARED_DIR:${DYLD_FALLBACK_LIBRARY_PATH:-} \ + LD_LIBRARY_PATH=$CRYPT_SHARED_DIR:${LD_LIBRARY_PATH-} \ + PATH=$CRYPT_SHARED_DIR:$PATH \ AUTH=auth SSL=ssl \ .evergreen/run-tests.sh -m encryption diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/test.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/test.sh index cc7e52f..288ff9a 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/test.sh +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/test.sh @@ -62,6 +62,7 @@ else "/opt/python/3.10/bin/python3" "/opt/python/3.11/bin/python3" "/opt/python/3.12/bin/python3" + "/opt/python/3.13/bin/python3" ) fi /opt/mongodbtoolchain/v3/bin/python3 drivers-evergreen-tools/.evergreen/mongodl.py --component \ diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst b/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst index 05b93a3..0721424 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst @@ -1,8 +1,15 @@ Changelog ========= +Changes in Version 1.11.0 +------------------------- + +- Bundle libmongocrypt 1.11.0 in release wheels. +- Add support for Python 3.13. +- Fix bug in Python async support for ``AsyncMongoCryptCallback.fetch_keys``. + Changes in Version 1.10.1 ------------------------- +------------------------- - Bundle libmongocrypt 1.10.1 in release wheels. diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/libmongocrypt-version.txt b/ext/libmongocrypt/libmongocrypt/bindings/python/libmongocrypt-version.txt index 4dae298..1cac385 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/libmongocrypt-version.txt +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/libmongocrypt-version.txt @@ -1 +1 @@ -1.10.1 +1.11.0 diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/state_machine.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/state_machine.py index f1a391d..4468c7c 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/state_machine.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/state_machine.py @@ -134,7 +134,7 @@ async def run_state_machine(ctx, callback): ctx.complete_mongo_operation() elif state == lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS: key_filter = ctx.mongo_operation() - for key in await callback.fetch_keys(key_filter): + async for key in callback.fetch_keys(key_filter): ctx.add_mongo_operation_result(key) ctx.complete_mongo_operation() elif state == lib.MONGOCRYPT_CTX_NEED_KMS: diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py index 5394e2a..d43ca97 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py @@ -665,7 +665,6 @@ def _parse_version(version): /// String constant for setopt_algorithm "Indexed" explicit encryption /// String constant for setopt_algorithm "Unindexed" explicit encryption // DEPRECATED: support "RangePreview" has been removed in favor of "range". -// NOTE: "Range" is currently unstable API and subject to backwards breaking changes. /** * Identify the AWS KMS master key to use for creating a data key. @@ -849,8 +848,6 @@ def _parse_version(version): * Contexts created for explicit encryption will not go through mongocryptd. * Requires query_type to be "range". * - * NOTE: "range" is currently unstable API and subject to backwards breaking changes. - * * This method expects the passed-in BSON to be of the form: * { "v" : FLE2RangeFindDriverSpec } * @@ -1360,7 +1357,6 @@ def _parse_version(version): /** * DEPRECATED: Use of `mongocrypt_setopt_use_range_v2` is deprecated. Range V2 is always enabled. - * NOTE: "range" is currently unstable API and subject to backwards breaking changes. * * @param[in] crypt The @ref mongocrypt_t object. * @@ -1412,7 +1408,6 @@ def _parse_version(version): /** * Set options for explicit encryption with the "range" algorithm. - * NOTE: "range" is currently unstable API and subject to backwards breaking changes. * * @p opts is a BSON document of the form: * { @@ -1433,7 +1428,6 @@ def _parse_version(version): /// String constants for setopt_query_type // DEPRECATED: Support "rangePreview" has been removed in favor of "range". -/// NOTE: "range" is currently unstable API and subject to backwards breaking changes. """ ) diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py index 133d385..f32604b 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.11.0.dev0" +__version__ = "1.12.0.dev0" _MIN_LIBMONGOCRYPT_VERSION = "1.8.0" diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pyproject.toml b/ext/libmongocrypt/libmongocrypt/bindings/python/pyproject.toml index ec0c9dc..f69cf3c 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pyproject.toml +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pyproject.toml @@ -36,6 +36,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Database", ] diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/release.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/release.sh index 2b67658..5ddb51e 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/release.sh +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/release.sh @@ -19,7 +19,7 @@ set -o errexit # Exit the script with error if any of the commands fail LIBMONGOCRYPT_VERSION=$(cat ./libmongocrypt-version.txt) REVISION=$(git rev-list -n 1 $LIBMONGOCRYPT_VERSION) # The libmongocrypt release branch. -BRANCH="r1.10" +BRANCH="r1.11" # The python executable to use. PYTHON=${PYTHON:-python} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/sbom.json b/ext/libmongocrypt/libmongocrypt/bindings/python/sbom.json index 605d4ff..c290a9e 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/sbom.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/sbom.json @@ -1,31 +1,31 @@ { "components": [ { - "bom-ref": "pkg:github/mongodb/libmongocrypt@1.10.1", + "bom-ref": "pkg:github/mongodb/libmongocrypt@1.11.0", "externalReferences": [ { "type": "distribution", - "url": "https://github.com/mongodb/libmongocrypt/archive/refs/tags/1.10.1.tar.gz" + "url": "https://github.com/mongodb/libmongocrypt/archive/refs/tags/1.11.0.tar.gz" }, { "type": "website", - "url": "https://github.com/mongodb/libmongocrypt/tree/1.10.1" + "url": "https://github.com/mongodb/libmongocrypt/tree/1.11.0" } ], "group": "mongodb", "name": "libmongocrypt", - "purl": "pkg:github/mongodb/libmongocrypt@1.10.1", + "purl": "pkg:github/mongodb/libmongocrypt@1.11.0", "type": "library", - "version": "1.10.1" + "version": "1.11.0" } ], "dependencies": [ { - "ref": "pkg:github/mongodb/libmongocrypt@1.10.1" + "ref": "pkg:github/mongodb/libmongocrypt@1.11.0" } ], "metadata": { - "timestamp": "2024-06-28T19:11:17.100829+00:00", + "timestamp": "2024-08-08T02:35:36.986098+00:00", "tools": [ { "externalReferences": [ @@ -68,9 +68,10 @@ } ] }, - "serialNumber": "urn:uuid:b09e93cf-eb1b-4d38-add5-86b01139769f", + "serialNumber": "urn:uuid:14e22848-7554-4f82-bcd1-76d2891b4c66", "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", - "specVersion": "1.5" + "specVersion": "1.5", + "vulnerabilities": [] } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py b/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py index d492442..a9cca34 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py @@ -478,7 +478,8 @@ async def mark_command(self, ns, cmd): return self.mongocryptd_reply async def fetch_keys(self, filter): - return self.key_docs + for doc in self.key_docs: + yield doc async def insert_data_key(self, data_key): raise NotImplementedError diff --git a/ext/libmongocrypt/libmongocrypt/cmake/FetchMongoC.cmake b/ext/libmongocrypt/libmongocrypt/cmake/FetchMongoC.cmake index 2e25c10..f43d94d 100644 --- a/ext/libmongocrypt/libmongocrypt/cmake/FetchMongoC.cmake +++ b/ext/libmongocrypt/libmongocrypt/cmake/FetchMongoC.cmake @@ -2,7 +2,7 @@ include (FetchContent) # Set the tag that we will fetch. # When updating the version of libbson, also update the version in etc/purls.txt -set (MONGOC_FETCH_TAG_FOR_LIBBSON "1.27.1" CACHE STRING "The Git tag of mongo-c-driver that will be fetched to obtain libbson") +set (MONGOC_FETCH_TAG_FOR_LIBBSON "1.28.1" CACHE STRING "The Git tag of mongo-c-driver that will be fetched to obtain libbson") # Add an option to disable patching if a patch command is unavailable. option (LIBBSON_PATCH_ENABLED "Whether to apply patches to the libbson library" ON) diff --git a/ext/libmongocrypt/libmongocrypt/cmake/ImportBSON.cmake b/ext/libmongocrypt/libmongocrypt/cmake/ImportBSON.cmake index b170c69..b967af9 100644 --- a/ext/libmongocrypt/libmongocrypt/cmake/ImportBSON.cmake +++ b/ext/libmongocrypt/libmongocrypt/cmake/ImportBSON.cmake @@ -140,8 +140,10 @@ function (_import_bson) set (ENABLE_SNAPPY OFF CACHE BOOL "Toggle snappy for the mongoc subproject (not required by libmongocrypt)") # Disable deprecated automatic init and cleanup. (May be overridden by the user) set (ENABLE_AUTOMATIC_INIT_AND_CLEANUP OFF CACHE BOOL "Enable automatic init and cleanup (GCC only)") - # Disable over-alignment of bson types. (May be overridden by the user) - set (ENABLE_EXTRA_ALIGNMENT ${_extra_alignment_default} CACHE BOOL "Toggle extra alignment of bson_t") + if (DEFINED _extra_alignment_default) + # Disable over-alignment of bson types. (May be overridden by the user) + set (ENABLE_EXTRA_ALIGNMENT ${_extra_alignment_default} CACHE BOOL "Toggle extra alignment of bson_t") + endif () # We don't want the subproject to find libmongocrypt set (ENABLE_CLIENT_SIDE_ENCRYPTION OFF CACHE BOOL "Disable client-side encryption for the libmongoc subproject") # Clear `BUILD_VERSION` so C driver does not use a `BUILD_VERSION` meant for libmongocrypt. diff --git a/ext/libmongocrypt/libmongocrypt/doc/releasing.md b/ext/libmongocrypt/libmongocrypt/doc/releasing.md index c2a2a43..ba8a3d4 100644 --- a/ext/libmongocrypt/libmongocrypt/doc/releasing.md +++ b/ext/libmongocrypt/libmongocrypt/doc/releasing.md @@ -17,8 +17,6 @@ Go to [Snyk](https://app.snyk.io/) and select the `dev-prod` organization. If ac ![Reference Targets](img/reference-targets.png) -Copy the organization ID from [Snyk settings](https://app.snyk.io/org/dev-prod/manage/settings). - ##### Update Snyk Update the Snyk reference target tracking the to-be-released branch. For a patch release (e.g. x.y.z), check-out the `rx.y` branch and update the `rx.y` reference target. For a minor release (e.g. x.y.0), check out the `master` branch update the `master` reference target. @@ -44,15 +42,6 @@ snyk monitor \ --remote-repo-url=https://github.com/mongodb/libmongocrypt.git ``` -```bash -snyk auth -snyk monitor \ ---org=$ORGANIZATION_ID \ ---target-reference= \ ---unmanaged \ ---remote-repo-url=https://github.com/mongodb/libmongocrypt.git -``` - Check the updated reference targets in Snyk for detected vulnerabilities. #### Check Silk @@ -80,7 +69,7 @@ Do the following when releasing: - Ensure `etc/purls.txt` is up-to-date. - Update `etc/third_party_vulnerabilities.md` with any updates to new or known vulnerabilities for third party dependencies that must be reported. - If this is a new minor release (e.g. `x.y.0`): - - Update the Linux distribution package installation instructions in the below sections to refer to the new version `x.y`. + - Update the Linux distribution package installation instructions in [README.md](../README.md) to refer to the new version `x.y`. - Update the [libmongocrypt-release](https://spruce.mongodb.com/project/libmongocrypt-release/settings/general) Evergreen project (requires auth) to set `Branch Name` to `rx.y`. - Commit the changes on the `rx.y` branch with a message like "Update CHANGELOG.md for x.y.z". - Tag the commit with `git tag -a `. @@ -106,7 +95,7 @@ Do the following when releasing: For a new minor release, use `master` for `--branch`. For a patch release, use the release branch (e.g. `rx.y`). Secrets can be obtained from [AWS Secrets Manager](https://wiki.corp.mongodb.com/display/DRIVERS/Using+AWS+Secrets+Manager+to+Store+Testing+Secrets) under `drivers/libmongocrypt`. - Attach `etc/third_party_vulnerabilities.md` to the release. - - Attach `ssdlc_compliance_report.md` to the release. + - Attach `etc/ssdlc_compliance_report.md` to the release. - If this is a new minor release (e.g. `x.y.0`): - File a DOCSP ticket to update the installation instructions on [Install libmongocrypt](https://www.mongodb.com/docs/manual/core/csfle/reference/libmongocrypt/). ([Example](https://jira.mongodb.org/browse/DOCSP-36863)) @@ -150,4 +139,25 @@ Do the following when releasing: Submit a PR to update the Homebrew package https://github.com/mongodb/homebrew-brew/blob/master/Formula/libmongocrypt.rb. ([Example](https://github.com/mongodb/homebrew-brew/pull/208)). If not on macOS, request a team member to do this step. ## Debian steps ## -Refer to the [Debian](https://github.com/mongodb/mongo-c-driver/blob/master/docs/dev/debian.rst) steps. If you are not a Debian maintainer on the team, request a team member to do this step. +If you are not a Debian maintainer on the team, request a team member to do the steps in this section. + +Refer to the [Debian](https://github.com/mongodb/mongo-c-driver/blob/master/docs/dev/debian.rst) steps. + +For a minor release (e.g. x.y.0), submit a merge request to the [extrepo-data](https://salsa.debian.org/extrepo-team/extrepo-data) project in Debian to update the PPA. The change would look something like this: + +``` +diff --git a/repos/debian/libmongocrypt.yaml b/repos/debian/libmongocrypt.yaml +index 609dc0b..f7530a9 100644 +--- a/repos/debian/libmongocrypt.yaml ++++ b/repos/debian/libmongocrypt.yaml +@@ -4,7 +4,7 @@ libmongocrypt: + source: + Types: deb + URIs: https://libmongocrypt.s3.amazonaws.com/apt/debian +- Suites: /libmongocrypt/1.11 ++ Suites: /libmongocrypt/1.12 + Components: main + Architectures: amd64 arm64 + suites: +``` + diff --git a/ext/libmongocrypt/libmongocrypt/etc/cyclonedx.sbom.json b/ext/libmongocrypt/libmongocrypt/etc/cyclonedx.sbom.json index a12ef9b..6c9af6d 100644 --- a/ext/libmongocrypt/libmongocrypt/etc/cyclonedx.sbom.json +++ b/ext/libmongocrypt/libmongocrypt/etc/cyclonedx.sbom.json @@ -1,16 +1,16 @@ { "components": [ { - "bom-ref": "pkg:github/mongodb/mongo-c-driver@v1.27.1#src/libbson", + "bom-ref": "pkg:github/mongodb/mongo-c-driver@v1.28.1#src/libbson", "copyright": "Copyright 2009-present MongoDB, Inc.", "externalReferences": [ { "type": "distribution", - "url": "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/v1.27.1.tar.gz" + "url": "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/v1.28.1.tar.gz" }, { "type": "website", - "url": "https://github.com/mongodb/mongo-c-driver/tree/v1.27.1" + "url": "https://github.com/mongodb/mongo-c-driver/tree/v1.28.1" } ], "group": "mongodb", @@ -22,9 +22,9 @@ } ], "name": "mongo-c-driver", - "purl": "pkg:github/mongodb/mongo-c-driver@v1.27.1#src/libbson", + "purl": "pkg:github/mongodb/mongo-c-driver@v1.28.1#src/libbson", "type": "library", - "version": "v1.27.1" + "version": "v1.28.1" }, { "bom-ref": "pkg:generic/IntelRDFPMathLib@20U2?download_url=https://www.netlib.org/misc/intel/IntelRDFPMathLib20U2.tar.gz", @@ -53,11 +53,11 @@ "ref": "pkg:generic/IntelRDFPMathLib@20U2?download_url=https://www.netlib.org/misc/intel/IntelRDFPMathLib20U2.tar.gz" }, { - "ref": "pkg:github/mongodb/mongo-c-driver@v1.27.1#src/libbson" + "ref": "pkg:github/mongodb/mongo-c-driver@v1.28.1#src/libbson" } ], "metadata": { - "timestamp": "2024-05-10T12:07:55.084050+00:00", + "timestamp": "2024-10-10T20:09:56.207649+00:00", "tools": [ { "externalReferences": [ @@ -101,8 +101,9 @@ ] }, "serialNumber": "urn:uuid:879e1b41-08d8-4505-8c89-2285bc3e442c", - "version": 1, + "version": 2, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", - "specVersion": "1.5" + "specVersion": "1.5", + "vulnerabilities": [] } diff --git a/ext/libmongocrypt/libmongocrypt/etc/purls.txt b/ext/libmongocrypt/libmongocrypt/etc/purls.txt index b6b8558..241c721 100644 --- a/ext/libmongocrypt/libmongocrypt/etc/purls.txt +++ b/ext/libmongocrypt/libmongocrypt/etc/purls.txt @@ -8,7 +8,7 @@ # `copyright` property. This information can be manually added. # libbson is obtained via `cmake/FetchMongoC.cmake`. -pkg:github/mongodb/mongo-c-driver@v1.27.1?#src/libbson +pkg:github/mongodb/mongo-c-driver@v1.28.1?#src/libbson # IntelDFP is obtained via `cmake/IntelDFP.cmake` pkg:generic/IntelRDFPMathLib@20U2?download_url=https://www.netlib.org/misc/intel/IntelRDFPMathLib20U2.tar.gz diff --git a/ext/libmongocrypt/libmongocrypt/integrating.md b/ext/libmongocrypt/libmongocrypt/integrating.md index fe9b231..a45f295 100644 --- a/ext/libmongocrypt/libmongocrypt/integrating.md +++ b/ext/libmongocrypt/libmongocrypt/integrating.md @@ -63,7 +63,7 @@ Seek help in the slack channel \#drivers-fle. After you have a binding, integrate libmongocrypt in your driver to support client side encryption. -See the [driver spec](https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.rst) +See the [driver spec](https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.md) for a reference of the user-facing API. libmongocrypt is needed for: - Automatic encryption/decryption @@ -203,19 +203,26 @@ The responses from one or more HTTP messages to KMS. (Note, the driver MAY fan out all HTTP requests at the same time). 2. For each context: - a. Create/reuse a TLS socket connected to the endpoint indicated by + a. Delay the message by the time in microseconds indicated by + `mongocrypt_kms_ctx_usleep` if returned value is greater than 0. + + b. Create/reuse a TLS socket connected to the endpoint indicated by `mongocrypt_kms_ctx_endpoint`. The endpoint string is a host name with a port number separated by a colon. E.g. "kms.us-east-1.amazonaws.com:443". A port number will always be included. Drivers may assume the host name is not an IP address or IP literal. - b. Write the message from `mongocrypt_kms_ctx_message` to the + c. Write the message from `mongocrypt_kms_ctx_message` to the > socket. - c. Feed the reply back with `mongocrypt_kms_ctx_feed`. Repeat + d. Feed the reply back with `mongocrypt_kms_ctx_feed`. Repeat > until `mongocrypt_kms_ctx_bytes_needed` returns 0. + If any step encounters a network error, continue to the next KMS context if + `mongocrypt_kms_ctx_fail` returns true. Otherwise, abort and report an + error. + 3. When done feeding all replies, call `mongocrypt_ctx_kms_done`. **Applies to...** @@ -236,7 +243,7 @@ Credentials for one or more KMS providers. **Driver needs to...** -Fetch credentials for supported KMS providers. See the [Client Side Encryption specification](https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.rst#automatic-credentials) for details. +Fetch credentials for supported KMS providers. See the [Client Side Encryption specification](https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.md#automatic-credentials) for details. Pass credentials to libmongocrypt using `mongocrypt_ctx_provide_kms_providers`. diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/README.md b/ext/libmongocrypt/libmongocrypt/kms-message/README.md index 2155f5f..d45e005 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/README.md +++ b/ext/libmongocrypt/libmongocrypt/kms-message/README.md @@ -11,7 +11,7 @@ implements the request format. - `test_kms_azure_online` makes live requests, and has additional requirements (must have working credentials). ### Requirements -- A complete installation of the C driver. (libbson is needed for parsing JSON, and libmongoc is used for creating TLS streams). See http://mongoc.org/libmongoc/current/installing.html for installation instructions. For macOS, `brew install mongo-c-driver` will suffice. +- A complete installation of the C driver. (libbson is needed for parsing JSON, and libmongoc is used for creating TLS streams). See the [C Driver Manual](https://www.mongodb.com/docs/languages/c/c-driver/current/libmongoc/tutorials/obtaining-libraries/) for installation instructions. For macOS, `brew install mongo-c-driver` will suffice. - An Azure key vault, and a service principal with an access policy allowing encrypt / decrypt key operations. The following environment variables must be set: - AZURE_TENANT_ID - AZURE_CLIENT_ID diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_response_parser.h b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_response_parser.h index 8f134bc..915f0ac 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_response_parser.h +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_response_parser.h @@ -57,6 +57,9 @@ kms_response_parser_error (kms_response_parser_t *parser); KMS_MSG_EXPORT (void) kms_response_parser_destroy (kms_response_parser_t *parser); +KMS_MSG_EXPORT (void) +kms_response_parser_reset (kms_response_parser_t *parser); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_response_parser.c b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_response_parser.c index 4d2e7a1..67336d7 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_response_parser.c +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_response_parser.c @@ -38,6 +38,14 @@ _parser_init (kms_response_parser_t *parser) parser->kmip = NULL; } +void +kms_response_parser_reset (kms_response_parser_t *parser) +{ + KMS_ASSERT(!parser->kmip); // KMIP is not-yet supported. + _parser_destroy(parser); + _parser_init(parser); +} + kms_response_parser_t * kms_response_parser_new (void) { diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-cmp-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-cmp-private.h new file mode 100644 index 0000000..0ed34b0 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/src/mc-cmp-private.h @@ -0,0 +1,137 @@ +/* + * Copyright 2018-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// `cmp.h` is a modified copy of `bson-cmp.h` from libbson 1.28.0. +#ifndef MC_CMP_H +#define MC_CMP_H + +#include /* ssize_t + BSON_CONCAT */ + +#include +#include +#include + +/* Sanity check: ensure ssize_t limits are as expected relative to size_t. */ +BSON_STATIC_ASSERT2(ssize_t_size_min_check, SSIZE_MIN + 1 == -SSIZE_MAX); +BSON_STATIC_ASSERT2(ssize_t_size_max_check, (size_t)SSIZE_MAX <= SIZE_MAX); + +/* Based on the "Safe Integral Comparisons" proposal merged in C++20: + * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0586r2.html + * + * Due to lack of type deduction in C, relational comparison functions (e.g. + * `cmp_less`) are defined in sets of four "functions" according to the + * signedness of each value argument, e.g.: + * - mc_cmp_less_ss (signed-value, signed-value) + * - mc_cmp_less_uu (unsigned-value, unsigned-value) + * - mc_cmp_less_su (signed-value, unsigned-value) + * - mc_cmp_less_us (unsigned-value, signed-value) + * + * Similarly, the `in_range` function is defined as a set of two "functions" + * according to the signedness of the value argument: + * - mc_in_range_signed (Type, signed-value) + * - mc_in_range_unsigned (Type, unsigned-value) + * + * The user must take care to use the correct signedness for the provided + * argument(s). Enabling compiler warnings for implicit sign conversions is + * recommended. + */ + +#define MC_CMP_SET(op, ss, uu, su, us) \ + static BSON_INLINE bool BSON_CONCAT3(mc_cmp_, op, _ss)(int64_t t, int64_t u) { return (ss); } \ + \ + static BSON_INLINE bool BSON_CONCAT3(mc_cmp_, op, _uu)(uint64_t t, uint64_t u) { return (uu); } \ + \ + static BSON_INLINE bool BSON_CONCAT3(mc_cmp_, op, _su)(int64_t t, uint64_t u) { return (su); } \ + \ + static BSON_INLINE bool BSON_CONCAT3(mc_cmp_, op, _us)(uint64_t t, int64_t u) { return (us); } + +MC_CMP_SET(equal, t == u, t == u, t < 0 ? false : (uint64_t)(t) == u, u < 0 ? false : t == (uint64_t)(u)) + +MC_CMP_SET(not_equal, !mc_cmp_equal_ss(t, u), !mc_cmp_equal_uu(t, u), !mc_cmp_equal_su(t, u), !mc_cmp_equal_us(t, u)) + +MC_CMP_SET(less, t < u, t < u, t < 0 ? true : (uint64_t)(t) < u, u < 0 ? false : t < (uint64_t)(u)) + +MC_CMP_SET(greater, mc_cmp_less_ss(u, t), mc_cmp_less_uu(u, t), mc_cmp_less_us(u, t), mc_cmp_less_su(u, t)) + +MC_CMP_SET(less_equal, + !mc_cmp_greater_ss(t, u), + !mc_cmp_greater_uu(t, u), + !mc_cmp_greater_su(t, u), + !mc_cmp_greater_us(t, u)) + +MC_CMP_SET(greater_equal, !mc_cmp_less_ss(t, u), !mc_cmp_less_uu(t, u), !mc_cmp_less_su(t, u), !mc_cmp_less_us(t, u)) + +#undef MC_CMP_SET + +/* Return true if the given value is within the range of the corresponding + * signed type. The suffix must match the signedness of the given value. */ +#define MC_IN_RANGE_SET_SIGNED(Type, min, max) \ + static BSON_INLINE bool BSON_CONCAT3(mc_in_range, _##Type, _signed)(int64_t value) { \ + return mc_cmp_greater_equal_ss(value, min) && mc_cmp_less_equal_ss(value, max); \ + } \ + \ + static BSON_INLINE bool BSON_CONCAT3(mc_in_range, _##Type, _unsigned)(uint64_t value) { \ + return mc_cmp_greater_equal_us(value, min) && mc_cmp_less_equal_us(value, max); \ + } + +/* Return true if the given value is within the range of the corresponding + * unsigned type. The suffix must match the signedness of the given value. */ +#define MC_IN_RANGE_SET_UNSIGNED(Type, max) \ + static BSON_INLINE bool BSON_CONCAT3(mc_in_range, _##Type, _signed)(int64_t value) { \ + return mc_cmp_greater_equal_su(value, 0u) && mc_cmp_less_equal_su(value, max); \ + } \ + \ + static BSON_INLINE bool BSON_CONCAT3(mc_in_range, _##Type, _unsigned)(uint64_t value) { \ + return mc_cmp_less_equal_uu(value, max); \ + } + +MC_IN_RANGE_SET_SIGNED(signed_char, SCHAR_MIN, SCHAR_MAX) +MC_IN_RANGE_SET_SIGNED(short, SHRT_MIN, SHRT_MAX) +MC_IN_RANGE_SET_SIGNED(int, INT_MIN, INT_MAX) +MC_IN_RANGE_SET_SIGNED(long, LONG_MIN, LONG_MAX) +MC_IN_RANGE_SET_SIGNED(long_long, LLONG_MIN, LLONG_MAX) + +MC_IN_RANGE_SET_UNSIGNED(unsigned_char, UCHAR_MAX) +MC_IN_RANGE_SET_UNSIGNED(unsigned_short, USHRT_MAX) +MC_IN_RANGE_SET_UNSIGNED(unsigned_int, UINT_MAX) +MC_IN_RANGE_SET_UNSIGNED(unsigned_long, ULONG_MAX) +MC_IN_RANGE_SET_UNSIGNED(unsigned_long_long, ULLONG_MAX) + +MC_IN_RANGE_SET_SIGNED(int8_t, INT8_MIN, INT8_MAX) +MC_IN_RANGE_SET_SIGNED(int16_t, INT16_MIN, INT16_MAX) +MC_IN_RANGE_SET_SIGNED(int32_t, INT32_MIN, INT32_MAX) +MC_IN_RANGE_SET_SIGNED(int64_t, INT64_MIN, INT64_MAX) + +MC_IN_RANGE_SET_UNSIGNED(uint8_t, UINT8_MAX) +MC_IN_RANGE_SET_UNSIGNED(uint16_t, UINT16_MAX) +MC_IN_RANGE_SET_UNSIGNED(uint32_t, UINT32_MAX) +MC_IN_RANGE_SET_UNSIGNED(uint64_t, UINT64_MAX) + +MC_IN_RANGE_SET_SIGNED(ssize_t, SSIZE_MIN, SSIZE_MAX) +MC_IN_RANGE_SET_UNSIGNED(size_t, SIZE_MAX) + +#undef MC_IN_RANGE_SET_SIGNED +#undef MC_IN_RANGE_SET_UNSIGNED + +/* Return true if the value with *signed* type is in the representable range of + * Type and false otherwise. */ +#define mc_in_range_signed(Type, value) BSON_CONCAT3(mc_in_range, _##Type, _signed)(value) + +/* Return true if the value with *unsigned* type is in the representable range + * of Type and false otherwise. */ +#define mc_in_range_unsigned(Type, value) BSON_CONCAT3(mc_in_range, _##Type, _unsigned)(value) + +#endif /* MC_CMP_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle-blob-subtype-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle-blob-subtype-private.h index 949b22f..3fda8e9 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle-blob-subtype-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle-blob-subtype-private.h @@ -19,7 +19,7 @@ /* FLE Blob Subtype is the first byte of a BSON Binary Subtype 6. * FLE1 Blob Subtypes are defined in: - * https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/subtype6.rst + * https://github.com/mongodb/specifications/blob/master/source/bson-binary-encrypted/binary-encrypted.md * FLE2 Blob Subtypes are currently defined in: * https://github.com/markbenvenuto/mongo-enterprise-modules/blob/fle2/fle_protocol.md#reference-bindata-6-subtypes. */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h index 3e26ec6..b2168da 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h @@ -54,6 +54,11 @@ typedef struct { mc_optional_int32_t trimFactor; } mc_FLE2RangeFindSpecEdgesInfo_t; +// `mc_FLE2RangeFindSpecEdgesInfo_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mc_FLE2RangeFindSpecEdgesInfo_t, + BSON_ALIGNOF(mc_FLE2RangeFindSpecEdgesInfo_t) >= BSON_ALIGNOF(bson_iter_t)); + /** FLE2RangeFindSpec represents the range find specification that is encoded * inside of a FLE2EncryptionPlaceholder. See * https://github.com/mongodb/mongo/blob/master/src/mongo/crypto/fle_field_schema.idl @@ -76,6 +81,11 @@ typedef struct { mc_FLE2RangeOperator_t secondOperator; } mc_FLE2RangeFindSpec_t; +// `mc_FLE2RangeFindSpec_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mc_FLE2RangeFindSpec_t, + BSON_ALIGNOF(mc_FLE2RangeFindSpec_t) >= BSON_ALIGNOF(mc_FLE2RangeFindSpecEdgesInfo_t)); + bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, const bson_iter_t *in, bool use_range_v2, @@ -99,6 +109,11 @@ typedef struct { mc_optional_int32_t trimFactor; } mc_FLE2RangeInsertSpec_t; +// `mc_FLE2RangeInsertSpec_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mc_FLE2RangeInsertSpec_t, + BSON_ALIGNOF(mc_FLE2RangeInsertSpec_t) >= BSON_ALIGNOF(bson_iter_t)); + bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, const bson_iter_t *in, bool use_range_v2, @@ -131,6 +146,11 @@ typedef struct { int64_t sparsity; } mc_FLE2EncryptionPlaceholder_t; +// `mc_FLE2EncryptionPlaceholder_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mc_FLE2EncryptionPlaceholder_t, + BSON_ALIGNOF(mc_FLE2EncryptionPlaceholder_t) >= BSON_ALIGNOF(bson_iter_t)); + void mc_FLE2EncryptionPlaceholder_init(mc_FLE2EncryptionPlaceholder_t *placeholder); bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out, diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h index c5ed226..79bbd8c 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h @@ -78,6 +78,11 @@ typedef struct { bson_value_t indexMax; // mx } mc_FLE2FindRangePayloadV2_t; +// `mc_FLE2FindRangePayloadV2_t` inherits extended alignment from libbson. To dynamically allocate, use aligned +// allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mc_FLE2FindRangePayloadV2_t, + BSON_ALIGNOF(mc_FLE2FindRangePayloadV2_t) >= BSON_ALIGNOF(bson_value_t)); + /** * EdgeFindTokenSetV2 is the following BSON document: * d: // EDCDerivedFromDataTokenAndContentionFactor diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h index 2ed4b32..911ca74 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h @@ -87,6 +87,11 @@ typedef struct { _mongocrypt_buffer_t userKeyId; } mc_FLE2InsertUpdatePayloadV2_t; +// `mc_FLE2InsertUpdatePayloadV2_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mc_FLE2InsertUpdatePayloadV2_t, + BSON_ALIGNOF(mc_FLE2InsertUpdatePayloadV2_t) >= BSON_ALIGNOF(bson_value_t)); + /** * EdgeTokenSetV2 is the following BSON document: * d: // EDCDerivedFromDataTokenAndContentionFactor diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-private-v2.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-private-v2.h index 5a585cd..4ead175 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-private-v2.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-private-v2.h @@ -17,6 +17,7 @@ #ifndef MONGOCRYPT_INDEXED_ENCRYPTED_VALUE_PRIVATE_V2_H #define MONGOCRYPT_INDEXED_ENCRYPTED_VALUE_PRIVATE_V2_H +#include "mc-fle2-tag-and-encrypted-metadata-block-private.h" #include "mc-tokens-private.h" #include "mongocrypt-buffer-private.h" #include "mongocrypt-crypto-private.h" @@ -24,58 +25,20 @@ /* * FLE2IndexedEqualityEncryptedValueV2 and FLE2IndexedRangeEncryptedValueV2 - * share a common internal implementation. Accessors such as add/get_[SK]_Key - * may be called for either type and produce appropriate results, - * however the _parse() method is unique per type. + * share a common internal implementation. * * Lifecycle: * 1. mc_FLE2IndexedEncryptedValueV2_init - * 2. mc_FLE2Indexed(Equality|Range)EncryptedValueV2_parse + * 2. mc_FLE2IndexedEncryptedValueV2_parse * 3. mc_FLE2IndexedEncryptedValueV2_get_S_KeyId * 4. mc_FLE2IndexedEncryptedValueV2_add_S_Key * 5. mc_FLE2IndexedEncryptedValueV2_get_K_KeyId * 6. mc_FLE2IndexedEncryptedValueV2_add_K_Key * 7. mc_FLE2IndexedEncryptedValueV2_get_ClientValue - * 8. mc_FLE2IndexedEncryptedValueV2_destroy - */ - -typedef struct _mc_FLE2IndexedEncryptedValueV2_t mc_FLE2IndexedEncryptedValueV2_t; - -mc_FLE2IndexedEncryptedValueV2_t *mc_FLE2IndexedEncryptedValueV2_new(void); - -bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev, - const _mongocrypt_buffer_t *buf, - mongocrypt_status_t *status); - -bson_type_t mc_FLE2IndexedEncryptedValueV2_get_bson_value_type(const mc_FLE2IndexedEncryptedValueV2_t *iev, - mongocrypt_status_t *status); - -const _mongocrypt_buffer_t *mc_FLE2IndexedEncryptedValueV2_get_S_KeyId(const mc_FLE2IndexedEncryptedValueV2_t *iev, - mongocrypt_status_t *status); - -bool mc_FLE2IndexedEncryptedValueV2_add_S_Key(_mongocrypt_crypto_t *crypto, - mc_FLE2IndexedEncryptedValueV2_t *iev, - const _mongocrypt_buffer_t *S_Key, - mongocrypt_status_t *status); - -const _mongocrypt_buffer_t * -mc_FLE2IndexedEncryptedValueV2_get_ClientEncryptedValue(const mc_FLE2IndexedEncryptedValueV2_t *iev, - mongocrypt_status_t *status); - -const _mongocrypt_buffer_t *mc_FLE2IndexedEncryptedValueV2_get_K_KeyId(const mc_FLE2IndexedEncryptedValueV2_t *iev, - mongocrypt_status_t *status); - -bool mc_FLE2IndexedEncryptedValueV2_add_K_Key(_mongocrypt_crypto_t *crypto, - mc_FLE2IndexedEncryptedValueV2_t *iev, - const _mongocrypt_buffer_t *K_Key, - mongocrypt_status_t *status); - -const _mongocrypt_buffer_t *mc_FLE2IndexedEncryptedValueV2_get_ClientValue(const mc_FLE2IndexedEncryptedValueV2_t *iev, - mongocrypt_status_t *status); - -void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *iev); - -/* + * 8. mc_FLE2IndexedEncryptedValueV2_serialize + * 9. mc_FLE2IndexedEncryptedValueV2_destroy + * + * * FLE2IndexedEqualityEncryptedValueV2 has the following data layout: * * struct FLE2IndexedEqualityEncryptedValueV2 { @@ -90,8 +53,6 @@ void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *ie * EncryptCTR(ServerEncryptionToken, K_KeyId || ClientEncryptedValue) * ClientEncryptedValue := EncryptCBCAEAD(K_Key, clientValue, AD=K_KeyId) * - * The MetadataBlock is ignored by libmongocrypt, - * but has the following structure and a fixed size of 96 octets: * * struct FLE2TagAndEncryptedMetadataBlock { * uint8_t encryptedCount[32]; // EncryptCTR(countEncryptionToken, @@ -99,13 +60,8 @@ void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *ie * uint8_t tag[32]; // HMAC-SHA256(count, edcTwiceDerived) * uint8_t encryptedZeros[32]; // EncryptCTR(zerosEncryptionToken, 0*) * } - */ - -bool mc_FLE2IndexedEqualityEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev, - const _mongocrypt_buffer_t *buf, - mongocrypt_status_t *status); - -/* + * + * * FLE2IndexedRangeEncryptedValueV2 has the following data layout: * * struct FLE2IndexedRangeEncryptedValueV2 { @@ -122,12 +78,81 @@ bool mc_FLE2IndexedEqualityEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2 * 1/ `edge_count` is introduced as an octet following `original_bson_type`. * 2/ Rather than a single metadata block, we have {edge_count} blocks. * - * Since libmongocrypt ignores metadata blocks, we can ignore most all - * differences between Equality and Range types for IndexedEncrypted data. */ -bool mc_FLE2IndexedRangeEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev, - const _mongocrypt_buffer_t *buf, - mongocrypt_status_t *status); +typedef struct _mc_FLE2IndexedEncryptedValueV2_t mc_FLE2IndexedEncryptedValueV2_t; + +mc_FLE2IndexedEncryptedValueV2_t *mc_FLE2IndexedEncryptedValueV2_new(void); +bson_type_t mc_FLE2IndexedEncryptedValueV2_get_bson_value_type(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mongocrypt_status_t *status); + +/* + * Populates an mc_FLE2IndexedEncryptedValueV2_t from a buffer. + * + * Input buffer must take the form of: + * fle_blob_subtype (8u) + * S_KeyId (8u * 16u) + * original_bson_type (8u) + * if (range) + * edge_count(8u) + * ServerEncryptedValue (8u * SEV_len) + * metadata (96u * {range ? edge_count : 1u}) + * + * Returns an error if the input buffer is not valid. + */ +bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev, + const _mongocrypt_buffer_t *buf, + mongocrypt_status_t *status); + +/* + * Serializes an mc_FLE2IndexedEncryptedValueV2_t into a buffer. + * + * The serialized output follows the same layout as the input `buf` to + * mc_FLE2IndexedEncryptedValueV2_parse, allowing for round-trip + * conversions between the serialized and parsed forms. + * + * Returns an error if the input structure is not valid, or if the buffer + * provided is insufficient to hold the serialized data. + */ +bool mc_FLE2IndexedEncryptedValueV2_serialize(const mc_FLE2IndexedEncryptedValueV2_t *iev, + _mongocrypt_buffer_t *buf, + mongocrypt_status_t *status); + +const _mongocrypt_buffer_t *mc_FLE2IndexedEncryptedValueV2_get_S_KeyId(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mongocrypt_status_t *status); + +bool mc_FLE2IndexedEncryptedValueV2_add_S_Key(_mongocrypt_crypto_t *crypto, + mc_FLE2IndexedEncryptedValueV2_t *iev, + const _mongocrypt_buffer_t *S_Key, + mongocrypt_status_t *status); + +const _mongocrypt_buffer_t * +mc_FLE2IndexedEncryptedValueV2_get_ClientEncryptedValue(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mongocrypt_status_t *status); + +const _mongocrypt_buffer_t *mc_FLE2IndexedEncryptedValueV2_get_K_KeyId(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mongocrypt_status_t *status); + +bool mc_FLE2IndexedEncryptedValueV2_add_K_Key(_mongocrypt_crypto_t *crypto, + mc_FLE2IndexedEncryptedValueV2_t *iev, + const _mongocrypt_buffer_t *K_Key, + mongocrypt_status_t *status); + +const _mongocrypt_buffer_t *mc_FLE2IndexedEncryptedValueV2_get_ClientValue(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mongocrypt_status_t *status); + +uint8_t mc_FLE2IndexedEncryptedValueV2_get_edge_count(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mongocrypt_status_t *status); + +bool mc_FLE2IndexedEncryptedValueV2_get_edge(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mc_FLE2TagAndEncryptedMetadataBlock_t *out, + const uint8_t edge_index, + mongocrypt_status_t *status); + +bool mc_FLE2IndexedEncryptedValueV2_get_metadata(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mc_FLE2TagAndEncryptedMetadataBlock_t *out, + mongocrypt_status_t *status); + +void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *iev); #endif /* MONGOCRYPT_INDEXED_ENCRYPTED_VALUE_PRIVATE_V2_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c index 32d8687..211d335 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c @@ -19,6 +19,7 @@ #include "mc-fle-blob-subtype-private.h" #include "mc-fle2-payload-iev-private-v2.h" +#include "mc-fle2-tag-and-encrypted-metadata-block-private.h" #include "mc-reader-private.h" #include "mc-tokens-private.h" #include "mc-writer-private.h" @@ -54,6 +55,8 @@ struct _mc_FLE2IndexedEncryptedValueV2_t { // Populated during _add_K_Key // ClientValue := DecryptCBCAEAD(K_Key, ClientEncryptedValue, AD=K_KeyId) _mongocrypt_buffer_t ClientValue; + + mc_FLE2TagAndEncryptedMetadataBlock_t *metadata; }; #define kMetadataLen 96U // encCount(32) + tag(32) + encZeros(32) @@ -69,31 +72,6 @@ mc_FLE2IndexedEncryptedValueV2_t *mc_FLE2IndexedEncryptedValueV2_new(void) { return bson_malloc0(sizeof(mc_FLE2IndexedEncryptedValueV2_t)); } -bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev, - const _mongocrypt_buffer_t *buf, - mongocrypt_status_t *status) { - BSON_ASSERT_PARAM(iev); - BSON_ASSERT_PARAM(buf); - - if ((buf->data == NULL) || (buf->len == 0)) { - CLIENT_ERR("Empty buffer passed to mc_FLE2IndexedEncryptedValueV2_parse"); - return false; - } - - if (buf->data[0] == MC_SUBTYPE_FLE2IndexedEqualityEncryptedValueV2) { - return mc_FLE2IndexedEqualityEncryptedValueV2_parse(iev, buf, status); - } else if (buf->data[0] == MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2) { - return mc_FLE2IndexedRangeEncryptedValueV2_parse(iev, buf, status); - } else { - CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_parse expected " - "fle_blob_subtype %d or %d got: %" PRIu8, - MC_SUBTYPE_FLE2IndexedEqualityEncryptedValueV2, - MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2, - iev->fle_blob_subtype); - return false; - } -} - bson_type_t mc_FLE2IndexedEncryptedValueV2_get_bson_value_type(const mc_FLE2IndexedEncryptedValueV2_t *iev, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(iev); @@ -322,70 +300,99 @@ void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *ie _mongocrypt_buffer_cleanup(&iev->DecryptedServerEncryptedValue); _mongocrypt_buffer_cleanup(&iev->ServerEncryptedValue); _mongocrypt_buffer_cleanup(&iev->S_KeyId); + + for (int i = 0; i < iev->edge_count; i++) { + mc_FLE2TagAndEncryptedMetadataBlock_cleanup(&iev->metadata[i]); + } + + // Metadata array is dynamically allocated + bson_free(iev->metadata); + bson_free(iev); } -// ----------------------------------------------------------------------- -// Equality +uint8_t mc_FLE2IndexedEncryptedValueV2_get_edge_count(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(iev); -bool mc_FLE2IndexedEqualityEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev, - const _mongocrypt_buffer_t *buf, - mongocrypt_status_t *status) { + if (iev->type == kTypeInit) { + CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_get_edge_count " + "must be called after " + "mc_FLE2IndexedEncryptedValueV2_parse"); + return 0; + } + + if (iev->type != kTypeRange) { + CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_get_edge_count must be called with type range"); + return 0; + } + + return iev->edge_count; +} + +bool mc_FLE2IndexedEncryptedValueV2_get_edge(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mc_FLE2TagAndEncryptedMetadataBlock_t *out, + const uint8_t edge_index, + mongocrypt_status_t *status) { BSON_ASSERT_PARAM(iev); - BSON_ASSERT_PARAM(buf); + BSON_ASSERT_PARAM(out); - if (iev->type != kTypeInit) { - CLIENT_ERR("mc_FLE2IndexedEqualityEncryptedValueV2_parse must not be " - "called twice"); + if (iev->type == kTypeInit) { + CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_get_edge " + "must be called after " + "mc_FLE2IndexedEncryptedValueV2_parse"); return false; } - mc_reader_t reader; - mc_reader_init_from_buffer(&reader, buf, __FUNCTION__); - - CHECK_AND_RETURN(mc_reader_read_u8(&reader, &iev->fle_blob_subtype, status)); + if (iev->type != kTypeRange) { + CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_get_edge must be called with type range"); + return false; + } - if (iev->fle_blob_subtype != MC_SUBTYPE_FLE2IndexedEqualityEncryptedValueV2) { - CLIENT_ERR("mc_FLE2IndexedEqualityEncryptedValueV2_parse expected " - "fle_blob_subtype %d got: %" PRIu8, - MC_SUBTYPE_FLE2IndexedEqualityEncryptedValueV2, - iev->fle_blob_subtype); + if (edge_index >= iev->edge_count) { + CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_get_edge must be called with index edge_index less than edge count"); return false; } - /* Read S_KeyId. */ - CHECK_AND_RETURN(mc_reader_read_uuid_buffer(&reader, &iev->S_KeyId, status)); + // Write edge into out struct + *out = iev->metadata[edge_index]; + return true; +} - /* Read original_bson_type. */ - CHECK_AND_RETURN(mc_reader_read_u8(&reader, &iev->bson_value_type, status)); +bool mc_FLE2IndexedEncryptedValueV2_get_metadata(const mc_FLE2IndexedEncryptedValueV2_t *iev, + mc_FLE2TagAndEncryptedMetadataBlock_t *out, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(iev); + BSON_ASSERT_PARAM(out); - /* Read ServerEncryptedValue. */ - const uint64_t SEV_and_metadata_len = mc_reader_get_remaining_length(&reader); - if (SEV_and_metadata_len < kMinSEVAndMetadataLen) { - CLIENT_ERR("Invalid payload size %" PRIu64 ", smaller than minimum length %d", - SEV_and_metadata_len, - kMinSEVAndMetadataLen); + if (iev->type == kTypeInit) { + CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_get_metadata " + "must be called after " + "mc_FLE2IndexedEncryptedValueV2_parse"); return false; } - const uint64_t SEV_len = SEV_and_metadata_len - kMetadataLen; - CHECK_AND_RETURN(mc_reader_read_buffer(&reader, &iev->ServerEncryptedValue, SEV_len, status)); - // Ignore Metadata block. - BSON_ASSERT(mc_reader_get_remaining_length(&reader) == kMetadataLen); + if (iev->type != kTypeEquality) { + CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_get_metadata must be called with type equality"); + return false; + } - iev->type = kTypeEquality; + // Write edge into out struct + *out = *iev->metadata; return true; } -// ----------------------------------------------------------------------- -// Range - -bool mc_FLE2IndexedRangeEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev, - const _mongocrypt_buffer_t *buf, - mongocrypt_status_t *status) { +bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev, + const _mongocrypt_buffer_t *buf, + mongocrypt_status_t *status) { BSON_ASSERT_PARAM(iev); BSON_ASSERT_PARAM(buf); + if ((buf->data == NULL) || (buf->len == 0)) { + CLIENT_ERR("Empty buffer passed to mc_FLE2IndexedEncryptedValueV2_parse"); + return false; + } + if (iev->type != kTypeInit) { CLIENT_ERR("mc_FLE2IndexedRangeEncryptedValueV2_parse must not be " "called twice"); @@ -397,10 +404,13 @@ bool mc_FLE2IndexedRangeEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t CHECK_AND_RETURN(mc_reader_read_u8(&reader, &iev->fle_blob_subtype, status)); - if (iev->fle_blob_subtype != MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2) { - CLIENT_ERR("mc_FLE2IndexedRangeEncryptedValueV2_parse expected " - "fle_blob_subtype %d got: %" PRIu8, - MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2, + if (iev->fle_blob_subtype == MC_SUBTYPE_FLE2IndexedEqualityEncryptedValueV2) { + iev->type = kTypeEquality; + } else if (iev->fle_blob_subtype == MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2) { + iev->type = kTypeRange; + } else { + CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_parse expected " + "fle_blob_subtype MC_SUBTYPE_FLE2Indexed(Equality|Range)EncryptedValueV2 got: %" PRIu8, iev->fle_blob_subtype); return false; } @@ -412,26 +422,88 @@ bool mc_FLE2IndexedRangeEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t CHECK_AND_RETURN(mc_reader_read_u8(&reader, &iev->bson_value_type, status)); /* Read edge_count */ - CHECK_AND_RETURN(mc_reader_read_u8(&reader, &iev->edge_count, status)); + // Set equality edge_count to 1 as it doesn't technically exist but + // there will be a singular metadata block + if (iev->type == kTypeEquality) { + iev->edge_count = 1; + } else { + CHECK_AND_RETURN(mc_reader_read_u8(&reader, &iev->edge_count, status)); + } + // Maximum edge_count(255) times kMetadataLen(96) fits easily without // overflow. - const uint64_t edges_len = iev->edge_count * kMetadataLen; + const uint64_t metadata_len = iev->edge_count * kMetadataLen; /* Read ServerEncryptedValue. */ - const uint64_t min_required_len = kMinServerEncryptedValueLen + edges_len; - const uint64_t SEV_and_edges_len = mc_reader_get_remaining_length(&reader); - if (SEV_and_edges_len < min_required_len) { + const uint64_t min_required_len = kMinServerEncryptedValueLen + metadata_len; + const uint64_t SEV_and_metadata_len = mc_reader_get_remaining_length(&reader); + if (SEV_and_metadata_len < min_required_len) { CLIENT_ERR("Invalid payload size %" PRIu64 ", smaller than minimum length %" PRIu64, - SEV_and_edges_len, + SEV_and_metadata_len, min_required_len); return false; } - const uint64_t SEV_len = SEV_and_edges_len - edges_len; + const uint64_t SEV_len = SEV_and_metadata_len - metadata_len; CHECK_AND_RETURN(mc_reader_read_buffer(&reader, &iev->ServerEncryptedValue, SEV_len, status)); - // Ignore Metadata block. - BSON_ASSERT(mc_reader_get_remaining_length(&reader) == edges_len); + iev->metadata = (mc_FLE2TagAndEncryptedMetadataBlock_t *)bson_malloc0( + iev->edge_count * sizeof(mc_FLE2TagAndEncryptedMetadataBlock_t)); + + // Read each metadata element + for (uint8_t i = 0; i < iev->edge_count; i++) { + _mongocrypt_buffer_t tmp_buf; + + CHECK_AND_RETURN(mc_reader_read_buffer(&reader, &tmp_buf, kMetadataLen, status)); + CHECK_AND_RETURN(mc_FLE2TagAndEncryptedMetadataBlock_parse(&iev->metadata[i], &tmp_buf, status)); + + _mongocrypt_buffer_cleanup(&tmp_buf); + } - iev->type = kTypeRange; return true; } + +bool mc_FLE2IndexedEncryptedValueV2_serialize(const mc_FLE2IndexedEncryptedValueV2_t *iev, + _mongocrypt_buffer_t *buf, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(iev); + BSON_ASSERT_PARAM(buf); + + if (iev->type != kTypeRange && iev->type != kTypeEquality) { + CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_serialize must be called with type equality or range"); + return false; + } + + mc_writer_t writer; + mc_writer_init_from_buffer(&writer, buf, __FUNCTION__); + + // Serialize fle_blob_subtype + CHECK_AND_RETURN(mc_writer_write_u8(&writer, iev->fle_blob_subtype, status)); + + // Serialize S_KeyId + CHECK_AND_RETURN(mc_writer_write_uuid_buffer(&writer, &iev->S_KeyId, status)); + + // Serialize bson_value_type + CHECK_AND_RETURN(mc_writer_write_u8(&writer, iev->bson_value_type, status)); + + // Serialize edge_count (only serialized for type range) + if (iev->type == kTypeRange) { + CHECK_AND_RETURN(mc_writer_write_u8(&writer, iev->edge_count, status)); + } + + // Serialize encrypted value + CHECK_AND_RETURN( + mc_writer_write_buffer(&writer, &iev->ServerEncryptedValue, iev->ServerEncryptedValue.len, status)); + + // Serialize metadata + for (int i = 0; i < iev->edge_count; ++i) { + _mongocrypt_buffer_t tmp_buf; + _mongocrypt_buffer_init_size(&tmp_buf, kMetadataLen); + + CHECK_AND_RETURN(mc_FLE2TagAndEncryptedMetadataBlock_serialize(&iev->metadata[i], &tmp_buf, status)); + CHECK_AND_RETURN(mc_writer_write_buffer(&writer, &tmp_buf, kMetadataLen, status)); + + _mongocrypt_buffer_cleanup(&tmp_buf); + } + + return true; +} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds-private.h index d89827c..cbdde69 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds-private.h @@ -41,6 +41,11 @@ typedef struct { mc_FLE2RangeOperator_t secondOp; } mc_FLE2RangeFindDriverSpec_t; +// `mc_FLE2RangeFindDriverSpec_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mc_FLE2RangeFindDriverSpec_t, + BSON_ALIGNOF(mc_FLE2RangeFindDriverSpec_t) >= BSON_ALIGNOF(bson_iter_t)); + // mc_FLE2RangeFindDriverSpec_parse parses a FLE2RangeFindDriverSpec document. bool mc_FLE2RangeFindDriverSpec_parse(mc_FLE2RangeFindDriverSpec_t *spec, const bson_t *in, @@ -79,6 +84,11 @@ typedef struct { mc_optional_int32_t trimFactor; } mc_makeRangeFindPlaceholder_args_t; +// `mc_makeRangeFindPlaceholder_args_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mc_makeRangeFindPlaceholder_args_t, + BSON_ALIGNOF(mc_makeRangeFindPlaceholder_args_t) >= BSON_ALIGNOF(bson_iter_t)); + // mc_makeRangeFindPlaceholder creates a placeholder to be consumed by // libmongocrypt to encrypt a range find query. It is included in the header to // be used by tests. diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-tag-and-encrypted-metadata-block-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-tag-and-encrypted-metadata-block-private.h new file mode 100644 index 0000000..e287c43 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-tag-and-encrypted-metadata-block-private.h @@ -0,0 +1,44 @@ +/* + * Copyright 2024-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MC_FLE2_TAG_AND_ENCRYPTED_METADATA_BLOCK_H +#define MC_FLE2_TAG_AND_ENCRYPTED_METADATA_BLOCK_H + +#include "mc-reader-private.h" +#include "mc-writer-private.h" +#include "mongocrypt-private.h" + +typedef struct { + _mongocrypt_buffer_t encryptedCount; + _mongocrypt_buffer_t tag; + _mongocrypt_buffer_t encryptedZeros; +} mc_FLE2TagAndEncryptedMetadataBlock_t; + +#define kFieldLen 32U + +void mc_FLE2TagAndEncryptedMetadataBlock_init(mc_FLE2TagAndEncryptedMetadataBlock_t *metadata); + +void mc_FLE2TagAndEncryptedMetadataBlock_cleanup(mc_FLE2TagAndEncryptedMetadataBlock_t *metadata); + +bool mc_FLE2TagAndEncryptedMetadataBlock_parse(mc_FLE2TagAndEncryptedMetadataBlock_t *metadata, + const _mongocrypt_buffer_t *buf, + mongocrypt_status_t *status); + +bool mc_FLE2TagAndEncryptedMetadataBlock_serialize(const mc_FLE2TagAndEncryptedMetadataBlock_t *metadata, + _mongocrypt_buffer_t *buf, + mongocrypt_status_t *status); + +#endif /* MC_FLE2_TAG_AND_ENCRYPTED_METADATA_BLOCK_H */ \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-tag-and-encrypted-metadata-block.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-tag-and-encrypted-metadata-block.c new file mode 100644 index 0000000..404e984 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-tag-and-encrypted-metadata-block.c @@ -0,0 +1,81 @@ +/* + * Copyright 2024-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mc-fle2-tag-and-encrypted-metadata-block-private.h" +#include "mc-reader-private.h" +#include "mc-writer-private.h" +#include "mongocrypt-private.h" + +#define CHECK_AND_RETURN(x) \ + if (!(x)) { \ + return false; \ + } + +void mc_FLE2TagAndEncryptedMetadataBlock_init(mc_FLE2TagAndEncryptedMetadataBlock_t *metadata) { + BSON_ASSERT_PARAM(metadata); + memset(metadata, 0, sizeof(mc_FLE2TagAndEncryptedMetadataBlock_t)); +} + +void mc_FLE2TagAndEncryptedMetadataBlock_cleanup(mc_FLE2TagAndEncryptedMetadataBlock_t *metadata) { + BSON_ASSERT_PARAM(metadata); + + _mongocrypt_buffer_cleanup(&metadata->encryptedCount); + _mongocrypt_buffer_cleanup(&metadata->tag); + _mongocrypt_buffer_cleanup(&metadata->encryptedZeros); +} + +bool mc_FLE2TagAndEncryptedMetadataBlock_parse(mc_FLE2TagAndEncryptedMetadataBlock_t *metadata, + const _mongocrypt_buffer_t *buf, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(metadata); + BSON_ASSERT_PARAM(buf); + + if ((buf->data == NULL) || (buf->len == 0)) { + CLIENT_ERR("Empty buffer passed to mc_FLE2IndexedEncryptedValueV2_parse"); + return false; + } + + mc_reader_t reader; + mc_reader_init_from_buffer(&reader, buf, __FUNCTION__); + + mc_FLE2TagAndEncryptedMetadataBlock_init(metadata); + + CHECK_AND_RETURN(mc_reader_read_buffer(&reader, &metadata->encryptedCount, kFieldLen, status)); + + CHECK_AND_RETURN(mc_reader_read_buffer(&reader, &metadata->tag, kFieldLen, status)); + + CHECK_AND_RETURN(mc_reader_read_buffer(&reader, &metadata->encryptedZeros, kFieldLen, status)); + + return true; +} + +bool mc_FLE2TagAndEncryptedMetadataBlock_serialize(const mc_FLE2TagAndEncryptedMetadataBlock_t *metadata, + _mongocrypt_buffer_t *buf, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(metadata); + BSON_ASSERT_PARAM(buf); + + mc_writer_t writer; + mc_writer_init_from_buffer(&writer, buf, __FUNCTION__); + + CHECK_AND_RETURN(mc_writer_write_buffer(&writer, &metadata->encryptedCount, kFieldLen, status)); + + CHECK_AND_RETURN(mc_writer_write_buffer(&writer, &metadata->tag, kFieldLen, status)); + + CHECK_AND_RETURN(mc_writer_write_buffer(&writer, &metadata->encryptedZeros, kFieldLen, status)); + + return true; +} diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c b/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c index 10b266a..83b1900 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c @@ -19,6 +19,7 @@ #include "mc-array-private.h" #include "mc-check-conversions-private.h" +#include "mc-cmp-private.h" #include "mc-range-encoding-private.h" #include "mongocrypt-private.h" @@ -47,7 +48,7 @@ static mc_edges_t *mc_edges_new(const char *leaf, const size_t leaf_len = strlen(leaf); const int32_t trimFactor = trimFactorDefault(leaf_len, opt_trimFactor, use_range_v2); - if (trimFactor != 0 && bson_cmp_greater_equal_su(trimFactor, leaf_len)) { + if (trimFactor != 0 && mc_cmp_greater_equal_su(trimFactor, leaf_len)) { // We append a total of leaf_len + 1 (for the root) - trimFactor edges. When this number is equal to 1, we // degenerate into equality, which is not desired, so trimFactor must be less than leaf_len. CLIENT_ERR("trimFactor must be less than the number of bits (%ld) used to represent an element of the domain, " @@ -76,7 +77,7 @@ static mc_edges_t *mc_edges_new(const char *leaf, _mc_array_append_val(&edges->edges, leaf_copy); // Start loop at max(trimFactor, 1). The full leaf is unconditionally appended after loop. - BSON_ASSERT(bson_in_range_size_t_signed(trimFactor)); + BSON_ASSERT(mc_in_range_size_t_signed(trimFactor)); size_t trimFactor_sz = (size_t)trimFactor; size_t startLevel = trimFactor > 0 ? trimFactor_sz : 1; for (size_t i = startLevel; i < leaf_len; i++) { diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c b/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c index 9c9ea27..e7d423b 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c @@ -15,6 +15,7 @@ */ #include "mc-check-conversions-private.h" +#include "mc-cmp-private.h" #include "mc-range-encoding-private.h" #include "mongocrypt-private.h" #include "mongocrypt-util-private.h" // mc_isinf @@ -863,7 +864,7 @@ int32_t trimFactorDefault(size_t maxlen, mc_optional_int32_t trimFactor, bool us return 0; } - if (bson_cmp_greater_su(mc_FLERangeTrimFactorDefault, maxlen - 1)) { + if (mc_cmp_greater_su(mc_FLERangeTrimFactorDefault, maxlen - 1)) { return (int32_t)(maxlen - 1); } else { return mc_FLERangeTrimFactorDefault; diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h index 907bd97..9da1bff 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h @@ -124,7 +124,7 @@ static inline DECORATE_NAME(MinCoverGenerator) } size_t maxlen = (size_t)BITS - DECORATE_NAME(mc_count_leading_zeros)(max); int32_t trimFactor = trimFactorDefault(maxlen, opt_trimFactor, use_range_v2); - if (trimFactor != 0 && bson_cmp_greater_equal_su(trimFactor, maxlen)) { + if (trimFactor != 0 && mc_cmp_greater_equal_su(trimFactor, maxlen)) { CLIENT_ERR("Trim factor must be less than the number of bits (%ld) used to represent an element of the domain, " "but got %" PRId32, maxlen, @@ -169,7 +169,7 @@ static inline bool DECORATE_NAME(MinCoverGenerator_isLevelStored)(DECORATE_NAME( size_t maskedBits) { BSON_ASSERT_PARAM(mcg); size_t level = mcg->_maxlen - maskedBits; - BSON_ASSERT(bson_in_range_size_t_signed(mcg->_trimFactor)); + BSON_ASSERT(mc_in_range_size_t_signed(mcg->_trimFactor)); size_t trimFactor_sz = (size_t)mcg->_trimFactor; return 0 == maskedBits || (level >= trimFactor_sz && 0 == (level % mcg->_sparsity)); } diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c index 635ae6c..3e8d8d4 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c @@ -19,6 +19,7 @@ #include "mc-check-conversions-private.h" #include "mc-array-private.h" +#include "mc-cmp-private.h" #include "mc-range-edge-generation-private.h" // mc_count_leading_zeros_u32 #include "mc-range-encoding-private.h" // mc_getTypeInfo32, trimFactorDefault #include "mc-range-mincover-private.h" diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h index 014f22d..80f4c80 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h @@ -40,12 +40,17 @@ typedef struct { mc_optional_int32_t trimFactor; } mc_RangeOpts_t; +// `mc_RangeOpts_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mc_RangeOpts_t, + BSON_ALIGNOF(mc_RangeOpts_t) >= BSON_MAX(BSON_ALIGNOF(bson_t), BSON_ALIGNOF(bson_iter_t))); + /* mc_RangeOpts_parse parses a BSON document into mc_RangeOpts_t. * The document is expected to have the form: * { * "min": BSON value, * "max": BSON value, - * "sparsity": Int64, + * "sparsity": Optional, * "precision": Optional, * "trimFactor": Optional, * } diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c b/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c index 4a9e4c6..729ef49 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c @@ -17,6 +17,7 @@ #include "mc-rangeopts-private.h" #include "mc-check-conversions-private.h" +#include "mc-cmp-private.h" #include "mc-range-edge-generation-private.h" // mc_count_leading_zeros_XX #include "mc-range-encoding-private.h" // mc_getTypeInfoXX #include "mongocrypt-private.h" @@ -504,7 +505,7 @@ bool mc_RangeOpts_appendTrimFactor(const mc_RangeOpts_t *ro, } // if nbits = 0, we want to allow trim factor = 0. uint32_t test = nbits ? nbits : 1; - if (bson_cmp_greater_equal_su(ro->trimFactor.value, test)) { + if (mc_cmp_greater_equal_su(ro->trimFactor.value, test)) { CLIENT_ERR_PREFIXED("Trim factor (%d) must be less than the total number of bits (%d) used to represent " "any element in the domain.", ro->trimFactor.value, diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-collinfo.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-collinfo.c index 87dc4af..a25a5ae 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-collinfo.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-collinfo.c @@ -61,5 +61,5 @@ void _mongocrypt_cache_collinfo_init(_mongocrypt_cache_t *cache) { cache->destroy_value = _destroy_value; _mongocrypt_mutex_init(&cache->mutex); cache->pair = NULL; - cache->expiration = CACHE_EXPIRATION_MS; + cache->expiration = CACHE_EXPIRATION_MS_DEFAULT; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key.c index 68deb6b..24ac81f 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key.c @@ -129,7 +129,7 @@ void _mongocrypt_cache_key_init(_mongocrypt_cache_t *cache) { cache->dump_attr = _dump_attr; _mongocrypt_mutex_init(&cache->mutex); cache->pair = NULL; - cache->expiration = CACHE_EXPIRATION_MS; + cache->expiration = CACHE_EXPIRATION_MS_DEFAULT; } /* Since key cache may be looked up by either _id or keyAltName, diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-private.h index 2c6160b..841a494 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-private.h @@ -20,7 +20,7 @@ #include "mongocrypt-mutex-private.h" #include "mongocrypt-status-private.h" -#define CACHE_EXPIRATION_MS 60000 +#define CACHE_EXPIRATION_MS_DEFAULT 60000 /* A generic simple cache. * To avoid overusing the names "key" or "id", the cache contains @@ -74,4 +74,4 @@ void _mongocrypt_cache_set_expiration(_mongocrypt_cache_t *cache, uint64_t milli uint32_t _mongocrypt_cache_num_entries(_mongocrypt_cache_t *cache); -#endif /* MONGOCRYPT_CACHE_PRIVATE */ \ No newline at end of file +#endif /* MONGOCRYPT_CACHE_PRIVATE */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache.c index 489a7b9..aad4b25 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache.c @@ -28,7 +28,7 @@ static bool _pair_expired(_mongocrypt_cache_t *cache, _mongocrypt_cache_pair_t * current = bson_get_monotonic_time() / 1000; BSON_ASSERT(current >= INT64_MIN + pair->last_updated); BSON_ASSERT(cache->expiration <= INT64_MAX); - return (current - pair->last_updated) > (int64_t)cache->expiration; + return cache->expiration > 0 && (current - pair->last_updated) > (int64_t)cache->expiration; } /* Return the pair after the one being destroyed. */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ciphertext.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ciphertext.c index e7dac7c..3b029c9 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ciphertext.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ciphertext.c @@ -92,7 +92,7 @@ bool _mongocrypt_ciphertext_parse_unowned(_mongocrypt_buffer_t *in, ciphertext->original_bson_type = in->data[offset]; offset += 1; - memset(&ciphertext->data, 0, sizeof(ciphertext->data)); + _mongocrypt_buffer_init(&ciphertext->data); ciphertext->data.data = in->data + offset; ciphertext->data.len = in->len - offset; diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c index 4bb08ed..09f62cf 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c @@ -40,9 +40,10 @@ static mongocrypt_kms_ctx_t *_next_kms_ctx(mongocrypt_ctx_t *ctx) { BSON_ASSERT_PARAM(ctx); dkctx = (_mongocrypt_ctx_datakey_t *)ctx; - if (dkctx->kms_returned) { + if (!dkctx->kms.should_retry && dkctx->kms_returned) { return NULL; } + dkctx->kms.should_retry = false; // Reset retry state. dkctx->kms_returned = true; return &dkctx->kms; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c index f8c0c6d..a8e6740 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c @@ -1214,14 +1214,12 @@ _marking_to_bson_value(void *ctx, _mongocrypt_marking_t *marking, bson_value_t * static bool _replace_marking_with_ciphertext(void *ctx, _mongocrypt_buffer_t *in, bson_value_t *out, mongocrypt_status_t *status) { - _mongocrypt_marking_t marking; + _mongocrypt_marking_t marking = {0}; bool ret; BSON_ASSERT_PARAM(ctx); BSON_ASSERT_PARAM(in); - memset(&marking, 0, sizeof(marking)); - if (!_mongocrypt_marking_parse_unowned(in, &marking, status)) { _mongocrypt_marking_cleanup(&marking); return false; @@ -2425,7 +2423,7 @@ static bool explicit_encrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *ms _mongocrypt_ctx_encrypt_t *ectx; bson_t as_bson; bson_iter_t iter; - _mongocrypt_ctx_opts_spec_t opts_spec; + _mongocrypt_ctx_opts_spec_t opts_spec = {0}; if (!ctx) { return false; diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-private.h index dcf0312..688db86 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-private.h @@ -63,6 +63,7 @@ typedef struct __mongocrypt_ctx_opts_t { _mongocrypt_buffer_t key_material; mongocrypt_encryption_algorithm_t algorithm; _mongocrypt_kek_t kek; + bool retry_enabled; struct { mongocrypt_index_type_t value; @@ -87,6 +88,12 @@ typedef struct __mongocrypt_ctx_opts_t { } rangeopts; } _mongocrypt_ctx_opts_t; +// `_mongocrypt_ctx_opts_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_ctx_opts_t, + BSON_ALIGNOF(_mongocrypt_ctx_opts_t) + >= BSON_MAX(BSON_ALIGNOF(_mongocrypt_key_alt_name_t), BSON_ALIGNOF(mc_RangeOpts_t))); + /* All derived contexts may override these methods. */ typedef struct { const char *(*mongo_db_collinfo)(mongocrypt_ctx_t *ctx); @@ -202,6 +209,11 @@ typedef struct { const char *cmd_name; } _mongocrypt_ctx_encrypt_t; +// `_mongocrypt_ctx_encrypt_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_ctx_encrypt_t, + BSON_ALIGNOF(_mongocrypt_ctx_encrypt_t) >= BSON_ALIGNOF(mongocrypt_ctx_t)); + typedef struct { mongocrypt_ctx_t parent; /* TODO CDRIVER-3150: audit + rename these buffers. @@ -212,6 +224,11 @@ typedef struct { _mongocrypt_buffer_t decrypted_doc; } _mongocrypt_ctx_decrypt_t; +// `_mongocrypt_ctx_datakey_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_ctx_decrypt_t, + BSON_ALIGNOF(_mongocrypt_ctx_decrypt_t) >= BSON_ALIGNOF(mongocrypt_ctx_t)); + typedef struct { mongocrypt_ctx_t parent; mongocrypt_kms_ctx_t kms; @@ -225,6 +242,11 @@ typedef struct { _mongocrypt_buffer_t kmip_secretdata; } _mongocrypt_ctx_datakey_t; +// `_mongocrypt_ctx_datakey_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_ctx_datakey_t, + BSON_ALIGNOF(_mongocrypt_ctx_datakey_t) >= BSON_ALIGNOF(mongocrypt_ctx_t)); + typedef struct _mongocrypt_ctx_rmd_datakey_t _mongocrypt_ctx_rmd_datakey_t; struct _mongocrypt_ctx_rmd_datakey_t { @@ -242,12 +264,40 @@ typedef struct { _mongocrypt_buffer_t results; } _mongocrypt_ctx_rewrap_many_datakey_t; +// `_mongocrypt_ctx_rewrap_many_datakey_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_ctx_rewrap_many_datakey_t, + BSON_ALIGNOF(_mongocrypt_ctx_rewrap_many_datakey_t) >= BSON_ALIGNOF(mongocrypt_ctx_t)); + typedef struct { mongocrypt_ctx_t parent; _mongocrypt_buffer_t result; mc_EncryptedFieldConfig_t efc; } _mongocrypt_ctx_compact_t; +// `_mongocrypt_ctx_compact_t` inherits extended alignment from libbson. To dynamically allocate, use aligned +// allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_ctx_compact_t, + BSON_ALIGNOF(_mongocrypt_ctx_compact_t) >= BSON_ALIGNOF(mongocrypt_ctx_t)); + +#define MONGOCRYPT_CTX_ALLOC_SIZE \ + BSON_MAX(sizeof(_mongocrypt_ctx_encrypt_t), \ + BSON_MAX(sizeof(_mongocrypt_ctx_decrypt_t), \ + BSON_MAX(sizeof(_mongocrypt_ctx_datakey_t), \ + BSON_MAX(sizeof(_mongocrypt_ctx_rewrap_many_datakey_t), \ + sizeof(_mongocrypt_ctx_compact_t))))) + +#define MONGOCRYPT_CTX_ALLOC_ALIGNMENT \ + BSON_MAX(BSON_ALIGNOF(_mongocrypt_ctx_encrypt_t), \ + BSON_MAX(BSON_ALIGNOF(_mongocrypt_ctx_decrypt_t), \ + BSON_MAX(BSON_ALIGNOF(_mongocrypt_ctx_datakey_t), \ + BSON_MAX(BSON_ALIGNOF(_mongocrypt_ctx_rewrap_many_datakey_t), \ + BSON_ALIGNOF(_mongocrypt_ctx_compact_t))))) + +// `_mongocrypt_ctx_t` inherits extended alignment from libbson. To dynamically allocate, use +// aligned allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof_mongocrypt_ctx_t, BSON_ALIGNOF(mongocrypt_ctx_t) >= MONGOCRYPT_CTX_ALLOC_ALIGNMENT); + /* Used for option validation. True means required. False means prohibited. */ typedef enum { OPT_PROHIBITED = 0, OPT_REQUIRED, OPT_OPTIONAL } _mongocrypt_ctx_opt_spec_t; diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c index 15ba3d7..f0384d9 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c @@ -282,7 +282,6 @@ bool mongocrypt_ctx_setopt_algorithm(mongocrypt_ctx_t *ctx, const char *algorith mongocrypt_ctx_t *mongocrypt_ctx_new(mongocrypt_t *crypt) { mongocrypt_ctx_t *ctx; - size_t ctx_size; if (!crypt) { return NULL; @@ -294,19 +293,17 @@ mongocrypt_ctx_t *mongocrypt_ctx_new(mongocrypt_t *crypt) { CLIENT_ERR("cannot create context from uninitialized crypt"); return NULL; } - ctx_size = sizeof(_mongocrypt_ctx_encrypt_t); - if (sizeof(_mongocrypt_ctx_decrypt_t) > ctx_size) { - ctx_size = sizeof(_mongocrypt_ctx_decrypt_t); - } - if (sizeof(_mongocrypt_ctx_datakey_t) > ctx_size) { - ctx_size = sizeof(_mongocrypt_ctx_datakey_t); - } - ctx = bson_malloc0(ctx_size); + + // Allocate with memory and alignment large enough for any possible context type. + static const size_t ctx_alignment = MONGOCRYPT_CTX_ALLOC_ALIGNMENT; + static const size_t ctx_size = MONGOCRYPT_CTX_ALLOC_SIZE; + ctx = bson_aligned_alloc0(ctx_alignment, ctx_size); BSON_ASSERT(ctx); ctx->crypt = crypt; ctx->status = mongocrypt_status_new(); ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE; + ctx->opts.retry_enabled = crypt->retry_enabled; ctx->state = MONGOCRYPT_CTX_DONE; return ctx; } @@ -513,8 +510,9 @@ mongocrypt_kms_ctx_t *mongocrypt_ctx_next_kms_ctx(mongocrypt_ctx_t *ctx) { return NULL; } + mongocrypt_kms_ctx_t *ret; switch (ctx->state) { - case MONGOCRYPT_CTX_NEED_KMS: return ctx->vtable.next_kms_ctx(ctx); + case MONGOCRYPT_CTX_NEED_KMS: ret = ctx->vtable.next_kms_ctx(ctx); break; case MONGOCRYPT_CTX_ERROR: return NULL; case MONGOCRYPT_CTX_DONE: case MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: @@ -525,6 +523,11 @@ mongocrypt_kms_ctx_t *mongocrypt_ctx_next_kms_ctx(mongocrypt_ctx_t *ctx) { case MONGOCRYPT_CTX_READY: default: _mongocrypt_ctx_fail_w_msg(ctx, "wrong state"); return NULL; } + + if (ret) { + ret->retry_enabled = ctx->opts.retry_enabled; + } + return ret; } bool mongocrypt_ctx_provide_kms_providers(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *kms_providers_definition) { diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c index 3707be4..7af66c4 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c @@ -807,6 +807,13 @@ mongocrypt_kms_ctx_t *_mongocrypt_key_broker_next_kms(_mongocrypt_key_broker_t * // Return the first not-yet-returned auth request. for (size_t i = 0; i < mc_mapof_kmsid_to_authrequest_len(kb->auth_requests); i++) { auth_request_t *ar = mc_mapof_kmsid_to_authrequest_at(kb->auth_requests, i); + + if (ar->kms.should_retry) { + ar->kms.should_retry = false; + ar->returned = true; + return &ar->kms; + } + if (ar->returned) { continue; } @@ -817,6 +824,13 @@ mongocrypt_kms_ctx_t *_mongocrypt_key_broker_next_kms(_mongocrypt_key_broker_t * return NULL; } + // Check if any requests need retry + for (key_returned_t *ptr = kb->keys_returned; ptr != NULL; ptr = ptr->next) { + if (ptr->kms.should_retry) { + ptr->kms.should_retry = false; + return &ptr->kms; + } + } while (kb->decryptor_iter) { if (!kb->decryptor_iter->decrypted) { key_returned_t *key_returned; @@ -1148,6 +1162,7 @@ void _mongocrypt_key_broker_add_test_key(_mongocrypt_key_broker_t *kb, const _mo key_returned->decrypted = true; _mongocrypt_buffer_init(&key_returned->decrypted_key_material); _mongocrypt_buffer_resize(&key_returned->decrypted_key_material, MONGOCRYPT_KEY_LEN); + // Initialize test key material with all zeros. memset(key_returned->decrypted_key_material.data, 0, MONGOCRYPT_KEY_LEN); _mongocrypt_key_destroy(key_doc); /* Hijack state and move directly to DONE. */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-private.h index 3831d2f..5b681a0 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-private.h @@ -27,6 +27,11 @@ typedef struct __mongocrypt_key_alt_name_t { bson_value_t value; } _mongocrypt_key_alt_name_t; +// `_mongocrypt_key_alt_name_t` inherits extended alignment from libbson. To dynamically allocate, use aligned +// allocation (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_key_alt_name_t, + BSON_ALIGNOF(_mongocrypt_key_alt_name_t) >= BSON_ALIGNOF(bson_value_t)); + typedef struct { bson_t bson; /* original BSON for this key. */ _mongocrypt_buffer_t id; @@ -37,6 +42,10 @@ typedef struct { _mongocrypt_kek_t kek; } _mongocrypt_key_doc_t; +// `_mongocrypt_key_doc_t` inherits extended alignment from libbson. To dynamically allocate, use aligned allocation +// (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_key_doc_t, BSON_ALIGNOF(_mongocrypt_key_doc_t) >= BSON_ALIGNOF(bson_t)); + _mongocrypt_key_alt_name_t *_mongocrypt_key_alt_name_new(const bson_value_t *value); bool _mongocrypt_key_alt_name_from_iter(const bson_iter_t *iter, diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key.c index cc2e44f..003ee6d 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key.c @@ -271,7 +271,10 @@ bool _mongocrypt_key_parse_owned(const bson_t *bson, _mongocrypt_key_doc_t *out, _mongocrypt_key_doc_t *_mongocrypt_key_new(void) { _mongocrypt_key_doc_t *key_doc; - key_doc = (_mongocrypt_key_doc_t *)bson_malloc0(sizeof *key_doc); + key_doc = BSON_ALIGNED_ALLOC(_mongocrypt_key_doc_t); + // Use two sets of braces to avoid erroneous missing-braces warning in GCC. Refer: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 + *key_doc = (_mongocrypt_key_doc_t){{0}}; bson_init(&key_doc->bson); return key_doc; @@ -389,7 +392,8 @@ _mongocrypt_key_alt_name_t *_mongocrypt_key_alt_name_create(const char *name, .. _mongocrypt_key_alt_name_t *_mongocrypt_key_alt_name_new(const bson_value_t *value) { BSON_ASSERT_PARAM(value); - _mongocrypt_key_alt_name_t *name = bson_malloc0(sizeof(*name)); + _mongocrypt_key_alt_name_t *name = BSON_ALIGNED_ALLOC(_mongocrypt_key_alt_name_t); + *name = (_mongocrypt_key_alt_name_t){0}; BSON_ASSERT(name); bson_value_copy(value, &name->value); diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx-private.h index 4b465fd..2a14c79 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx-private.h @@ -56,8 +56,14 @@ struct _mongocrypt_kms_ctx_t { char *endpoint; _mongocrypt_log_t *log; char *kmsid; + int64_t sleep_usec; + int attempts; + bool retry_enabled; + bool should_retry; }; +static const int kms_max_attempts = 3; + bool _mongocrypt_kms_ctx_init_aws_decrypt(mongocrypt_kms_ctx_t *kms, _mongocrypt_opts_kms_providers_t *kms_providers, _mongocrypt_key_doc_t *key, diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c index d15a03e..1d43117 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c @@ -20,6 +20,7 @@ #include "mongocrypt-crypto-private.h" #include "mongocrypt-ctx-private.h" #include "mongocrypt-endpoint-private.h" +#include "mongocrypt-kek-private.h" #include "mongocrypt-kms-ctx-private.h" #include "mongocrypt-log-private.h" #include "mongocrypt-opts-private.h" @@ -27,6 +28,7 @@ #include "mongocrypt-status-private.h" #include "mongocrypt-util-private.h" #include "mongocrypt.h" +#include #include #include #include @@ -142,6 +144,9 @@ _init_common(mongocrypt_kms_ctx_t *kms, _mongocrypt_log_t *log, _kms_request_typ kms->status = mongocrypt_status_new(); kms->req_type = kms_type; _mongocrypt_buffer_init(&kms->result); + kms->sleep_usec = 0; + kms->attempts = 0; + kms->should_retry = false; } bool _mongocrypt_kms_ctx_init_aws_decrypt(mongocrypt_kms_ctx_t *kms, @@ -427,11 +432,21 @@ uint32_t mongocrypt_kms_ctx_bytes_needed(mongocrypt_kms_ctx_t *kms) { if (!mongocrypt_status_ok(kms->status) || !_mongocrypt_buffer_empty(&kms->result)) { return 0; } + if (kms->should_retry) { + return 0; + } want_bytes = kms_response_parser_wants_bytes(kms->parser, DEFAULT_MAX_KMS_BYTE_REQUEST); BSON_ASSERT(want_bytes >= 0); return (uint32_t)want_bytes; } +int64_t mongocrypt_kms_ctx_usleep(mongocrypt_kms_ctx_t *kms) { + if (!kms) { + return 0; + } + return kms->sleep_usec; +} + static void _handle_non200_http_status(int http_status, const char *body, size_t body_len, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(body); @@ -455,6 +470,56 @@ _handle_non200_http_status(int http_status, const char *body, size_t body_len, m CLIENT_ERR("Error in KMS response. HTTP status=%d. Response body=\n%s", http_status, body); } +static int64_t backoff_time_usec(int64_t attempts) { + static bool seeded = false; + if (!seeded) { + srand((uint32_t)time(NULL)); + seeded = true; + } + + /* Exponential backoff with jitter. */ + const int64_t base = 200000; /* 0.2 seconds */ + const int64_t max = 20000000; /* 20 seconds */ + BSON_ASSERT(attempts > 0); + int64_t backoff = base * ((int64_t)1 << (attempts - 1)); + if (backoff > max) { + backoff = max; + } + + /* Full jitter: between 1 and current max */ + return (int64_t)((double)rand() / (double)RAND_MAX * (double)backoff) + 1; +} + +static bool should_retry_http(int http_status, _kms_request_type_t t) { + static const int retryable_aws[] = {408, 429, 500, 502, 503, 509}; + static const int retryable_azure[] = {408, 429, 500, 502, 503, 504}; + if (t == MONGOCRYPT_KMS_AWS_ENCRYPT || t == MONGOCRYPT_KMS_AWS_DECRYPT) { + for (size_t i = 0; i < sizeof(retryable_aws) / sizeof(retryable_aws[0]); i++) { + if (http_status == retryable_aws[i]) { + return true; + } + } + } else if (t == MONGOCRYPT_KMS_AZURE_WRAPKEY || t == MONGOCRYPT_KMS_AZURE_UNWRAPKEY + || t == MONGOCRYPT_KMS_AZURE_OAUTH) { + for (size_t i = 0; i < sizeof(retryable_azure) / sizeof(retryable_azure[0]); i++) { + if (http_status == retryable_azure[i]) { + return true; + } + } + } else if (t == MONGOCRYPT_KMS_GCP_ENCRYPT || t == MONGOCRYPT_KMS_GCP_DECRYPT || t == MONGOCRYPT_KMS_GCP_OAUTH) { + if (http_status == 408 || http_status == 429 || http_status / 500 == 1) { + return true; + } + } + return false; +} + +static void set_retry(mongocrypt_kms_ctx_t *kms) { + kms->should_retry = true; + kms->attempts++; + kms->sleep_usec = backoff_time_usec(kms->attempts); +} + /* An AWS KMS context has received full response. Parse out the result or error. */ static bool _ctx_done_aws(mongocrypt_kms_ctx_t *kms, const char *json_field) { @@ -485,6 +550,21 @@ static bool _ctx_done_aws(mongocrypt_kms_ctx_t *kms, const char *json_field) { } body = kms_response_get_body(response, &body_len); + if (kms->retry_enabled && should_retry_http(http_status, kms->req_type)) { + if (kms->attempts >= kms_max_attempts) { + // Wrap error to indicate maximum retries occurred. + _handle_non200_http_status(http_status, body, body_len, status); + CLIENT_ERR("KMS request failed after maximum of %d retries: %s", + kms_max_attempts, + mongocrypt_status_message(status, NULL)); + goto fail; + } else { + ret = true; + set_retry(kms); + goto fail; + } + } + if (http_status != 200) { _handle_non200_http_status(http_status, body, body_len, status); goto fail; @@ -566,6 +646,21 @@ static bool _ctx_done_oauth(mongocrypt_kms_ctx_t *kms) { } body = kms_response_get_body(response, &body_len); + if (kms->retry_enabled && should_retry_http(http_status, kms->req_type)) { + if (kms->attempts >= kms_max_attempts) { + // Wrap error to indicate maximum retries occurred. + _handle_non200_http_status(http_status, body, body_len, status); + CLIENT_ERR("KMS request failed after maximum of %d retries: %s", + kms_max_attempts, + mongocrypt_status_message(status, NULL)); + goto fail; + } else { + ret = true; + set_retry(kms); + goto fail; + } + } + if (body_len == 0) { CLIENT_ERR("Empty KMS response. HTTP status=%d", http_status); goto fail; @@ -643,6 +738,21 @@ static bool _ctx_done_azure_wrapkey_unwrapkey(mongocrypt_kms_ctx_t *kms) { } body = kms_response_get_body(response, &body_len); + if (kms->retry_enabled && should_retry_http(http_status, kms->req_type)) { + if (kms->attempts >= kms_max_attempts) { + // Wrap error to indicate maximum retries occurred. + _handle_non200_http_status(http_status, body, body_len, status); + CLIENT_ERR("KMS request failed after maximum of %d retries: %s", + kms_max_attempts, + mongocrypt_status_message(status, NULL)); + goto fail; + } else { + ret = true; + set_retry(kms); + goto fail; + } + } + if (body_len == 0) { CLIENT_ERR("Empty KMS response. HTTP status=%d", http_status); goto fail; @@ -737,6 +847,21 @@ static bool _ctx_done_gcp(mongocrypt_kms_ctx_t *kms, const char *json_field) { } body = kms_response_get_body(response, &body_len); + if (kms->retry_enabled && should_retry_http(http_status, kms->req_type)) { + if (kms->attempts >= kms_max_attempts) { + // Wrap error to indicate maximum retries occurred. + _handle_non200_http_status(http_status, body, body_len, status); + CLIENT_ERR("KMS request failed after maximum of %d retries: %s", + kms_max_attempts, + mongocrypt_status_message(status, NULL)); + goto fail; + } else { + ret = true; + set_retry(kms); + goto fail; + } + } + if (http_status != 200) { _handle_non200_http_status(http_status, body, body_len, status); goto fail; @@ -995,6 +1120,55 @@ static bool _ctx_done_kmip_decrypt(mongocrypt_kms_ctx_t *kms_ctx) { return ret; } +bool mongocrypt_kms_ctx_fail(mongocrypt_kms_ctx_t *kms) { + if (!kms || !kms->retry_enabled) { + return false; + } + + kms->should_retry = false; + mongocrypt_status_t *status = kms->status; + + if (!kms->retry_enabled) { + CLIENT_ERR("KMS request failed due to network error"); + return false; + } + + if (kms->attempts >= kms_max_attempts) { + CLIENT_ERR("KMS request failed after %d retries due to a network error", kms_max_attempts); + return false; + } + + // Check if request type is retryable. Some requests are non-idempotent and cannot be safely retried. + _kms_request_type_t retryable_types[] = {MONGOCRYPT_KMS_AZURE_OAUTH, + MONGOCRYPT_KMS_GCP_OAUTH, + MONGOCRYPT_KMS_AWS_ENCRYPT, + MONGOCRYPT_KMS_AWS_DECRYPT, + MONGOCRYPT_KMS_AZURE_WRAPKEY, + MONGOCRYPT_KMS_AZURE_UNWRAPKEY, + MONGOCRYPT_KMS_GCP_ENCRYPT, + MONGOCRYPT_KMS_GCP_DECRYPT}; + bool is_retryable = false; + for (size_t i = 0; i < sizeof(retryable_types) / sizeof(retryable_types[0]); i++) { + if (retryable_types[i] == kms->req_type) { + is_retryable = true; + break; + } + } + if (!is_retryable) { + CLIENT_ERR("KMS request failed due to network error"); + return false; + } + + // Mark KMS context as retryable. Return again in `mongocrypt_ctx_next_kms_ctx`. + set_retry(kms); + + // Reset intermediate state of parser. + if (kms->parser) { + kms_response_parser_reset(kms->parser); + } + return true; +} + bool mongocrypt_kms_ctx_feed(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes) { if (!kms) { return false; diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-log.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-log.c index 3aee772..072104a 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-log.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-log.c @@ -37,7 +37,6 @@ void _mongocrypt_log_cleanup(_mongocrypt_log_t *log) { } _mongocrypt_mutex_cleanup(&log->mutex); - memset(log, 0, sizeof(*log)); } void _mongocrypt_stdout_log_fn(mongocrypt_log_level_t level, const char *message, uint32_t message_len, void *ctx) { diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h index 769fea5..f759c15 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h @@ -45,6 +45,10 @@ typedef struct { }; } _mongocrypt_marking_t; +// `_mongocrypt_marking_t` inherits extended alignment from libbson. To dynamically allocate, use aligned allocation +// (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_marking_t, BSON_ALIGNOF(_mongocrypt_marking_t) >= BSON_ALIGNOF(bson_iter_t)); + void _mongocrypt_marking_init(_mongocrypt_marking_t *marking); void _mongocrypt_marking_cleanup(_mongocrypt_marking_t *marking); diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c index a78775f..d974b10 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c @@ -460,7 +460,8 @@ static void _FLE2EncryptedPayloadCommon_cleanup(_FLE2EncryptedPayloadCommon_t *c _mongocrypt_buffer_cleanup(&common->escDerivedToken); _mongocrypt_buffer_cleanup(&common->eccDerivedToken); _mongocrypt_buffer_cleanup(&common->serverDerivedFromDataToken); - memset(common, 0, sizeof(*common)); + // Zero out memory so `_FLE2EncryptedPayloadCommon_cleanup` is safe to call twice. + *common = (_FLE2EncryptedPayloadCommon_t){{0}}; } // _get_tokenKey returns the tokenKey identified by indexKeyId. diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c index dc6680a..7f82362 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c @@ -990,7 +990,7 @@ bool _mongocrypt_parse_kms_providers(mongocrypt_binary_t *kms_providers_definiti } if (log && log->trace_enabled) { - char *as_str = bson_as_json(&as_bson, NULL); + char *as_str = bson_as_relaxed_extended_json(&as_bson, NULL); _mongocrypt_log(log, MONGOCRYPT_LOG_LEVEL_TRACE, "%s (%s=\"%s\")", BSON_FUNC, "kms_providers", as_str); bson_free(as_str); } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h index f14ed7b..147bd1e 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h @@ -125,6 +125,7 @@ struct _mongocrypt_t { _mongo_crypt_v1_vtable csfle; /// Pointer to the global csfle_lib object. Should not be freed directly. mongo_crypt_v1_lib *csfle_lib; + bool retry_enabled; }; typedef enum { diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c index be73f5b..14f427b 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "mongocrypt.h" #include "mlib/error.h" #include "mlib/path.h" #include "mlib/thread.h" @@ -24,6 +25,7 @@ #include "mongocrypt-binary-private.h" #include "mongocrypt-cache-collinfo-private.h" #include "mongocrypt-cache-key-private.h" +#include "mongocrypt-cache-private.h" #include "mongocrypt-config.h" #include "mongocrypt-crypto-private.h" #include "mongocrypt-log-private.h" @@ -167,6 +169,12 @@ bool mongocrypt_setopt_log_handler(mongocrypt_t *crypt, mongocrypt_log_fn_t log_ return true; } +bool mongocrypt_setopt_retry_kms(mongocrypt_t *crypt, bool enable) { + ASSERT_MONGOCRYPT_PARAM_UNINIT(crypt); + crypt->retry_enabled = enable; + return true; +} + bool mongocrypt_setopt_kms_provider_aws(mongocrypt_t *crypt, const char *aws_access_key_id, int32_t aws_access_key_id_len, @@ -214,6 +222,17 @@ bool mongocrypt_setopt_kms_provider_aws(mongocrypt_t *crypt, return true; } +bool mongocrypt_setopt_key_expiration(mongocrypt_t *crypt, uint64_t cache_expiration_ms) { + ASSERT_MONGOCRYPT_PARAM_UNINIT(crypt); + if (cache_expiration_ms > INT64_MAX) { + mongocrypt_status_t *status = crypt->status; + CLIENT_ERR("expiration time must be less than %" PRId64 ", but got %" PRIu64, INT64_MAX, cache_expiration_ms); + return false; + } + crypt->cache_key.expiration = cache_expiration_ms; + return true; +} + char *_mongocrypt_new_string_from_bytes(const void *in, int len) { const int max_bytes = 100; const int chars_per_byte = 2; diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt.h index 41c2c0e..7227e0e 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt.h @@ -310,6 +310,18 @@ mongocrypt_t *mongocrypt_new(void); MONGOCRYPT_EXPORT bool mongocrypt_setopt_log_handler(mongocrypt_t *crypt, mongocrypt_log_fn_t log_fn, void *log_ctx); +/** + * Enable or disable KMS retry behavior. + * + * @param[in] crypt The @ref mongocrypt_t object. + * @param[in] enable A boolean indicating whether to retry operations. + * @pre @ref mongocrypt_init has not been called on @p crypt. + * @returns A boolean indicating success. If false, an error status is set. + * Retrieve it with @ref mongocrypt_ctx_status + */ +MONGOCRYPT_EXPORT +bool mongocrypt_setopt_retry_kms(mongocrypt_t *crypt, bool enable); + /** * Configure an AWS KMS provider on the @ref mongocrypt_t object. * @@ -546,7 +558,7 @@ const char *mongocrypt_crypt_shared_lib_version_string(const mongocrypt_t *crypt * @brief Obtain a 64-bit constant encoding the version of the loaded * crypt_shared library, if available. * - * @param[in] crypt The mongocrypt_t object after a successul call to + * @param[in] crypt The mongocrypt_t object after a successful call to * mongocrypt_init. * * @return A 64-bit encoded version number, with the version encoded as four @@ -1082,6 +1094,8 @@ typedef struct _mongocrypt_kms_ctx_t mongocrypt_kms_ctx_t; * If KMS handles are being handled synchronously, the driver can reuse the same * TLS socket to send HTTP requests and receive responses. * + * The returned KMS handle does not outlive `ctx`. + * * @param[in] ctx A @ref mongocrypt_ctx_t. * @returns a new @ref mongocrypt_kms_ctx_t or NULL. */ @@ -1130,6 +1144,15 @@ bool mongocrypt_kms_ctx_endpoint(mongocrypt_kms_ctx_t *kms, const char **endpoin MONGOCRYPT_EXPORT uint32_t mongocrypt_kms_ctx_bytes_needed(mongocrypt_kms_ctx_t *kms); +/** + * Indicates how long to sleep before sending this request. + * + * @param[in] kms The @ref mongocrypt_kms_ctx_t. + * @returns How long to sleep in microseconds. + */ +MONGOCRYPT_EXPORT +int64_t mongocrypt_kms_ctx_usleep(mongocrypt_kms_ctx_t *kms); + /** * Feed bytes from the HTTP response. * @@ -1145,6 +1168,15 @@ uint32_t mongocrypt_kms_ctx_bytes_needed(mongocrypt_kms_ctx_t *kms); MONGOCRYPT_EXPORT bool mongocrypt_kms_ctx_feed(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes); +/** + * Indicate a network-level failure. + * + * @param[in] kms The @ref mongocrypt_kms_ctx_t. + * @return A boolean indicating whether the failed request may be retried. + */ +MONGOCRYPT_EXPORT +bool mongocrypt_kms_ctx_fail(mongocrypt_kms_ctx_t *kms); + /** * Get the status associated with a @ref mongocrypt_kms_ctx_t object. * @@ -1264,7 +1296,7 @@ void mongocrypt_ctx_destroy(mongocrypt_ctx_t *ctx); * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status - * with a message indiciating the error using @ref mongocrypt_status_set. + * with a message indicating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_crypto_fn)(void *ctx, mongocrypt_binary_t *key, @@ -1289,7 +1321,7 @@ typedef bool (*mongocrypt_crypto_fn)(void *ctx, * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status - * with a message indiciating the error using @ref mongocrypt_status_set. + * with a message indicating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_hmac_fn)(void *ctx, mongocrypt_binary_t *key, @@ -1308,7 +1340,7 @@ typedef bool (*mongocrypt_hmac_fn)(void *ctx, * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status - * with a message indiciating the error using @ref mongocrypt_status_set. + * with a message indicating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_hash_fn)(void *ctx, mongocrypt_binary_t *in, @@ -1326,7 +1358,7 @@ typedef bool (*mongocrypt_hash_fn)(void *ctx, * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status - * with a message indiciating the error using @ref mongocrypt_status_set. + * with a message indicating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_random_fn)(void *ctx, mongocrypt_binary_t *out, uint32_t count, mongocrypt_status_t *status); @@ -1473,7 +1505,7 @@ bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t *ctx, const char *query_t * { * "min": Optional, * "max": Optional, - * "sparsity": Int64, + * "sparsity": Optional, * "precision": Optional, * "trimFactor": Optional * } @@ -1487,6 +1519,16 @@ bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t *ctx, const char *query_t MONGOCRYPT_EXPORT bool mongocrypt_ctx_setopt_algorithm_range(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *opts); +/** + * Set the expiration time for the data encryption key cache. Defaults to 60 seconds if not set. + * + * @param[in] ctx The @ref mongocrypt_ctx_t object. + * @param[in] cache_expiration_ms The cache expiration time in milliseconds. If zero, the cache + * never expires. + */ +MONGOCRYPT_EXPORT +bool mongocrypt_setopt_key_expiration(mongocrypt_t *crypt, uint64_t cache_expiration_ms); + /// String constants for setopt_query_type #define MONGOCRYPT_QUERY_TYPE_EQUALITY_STR "equality" // DEPRECATED: Support "rangePreview" has been removed in favor of "range". diff --git a/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneRangeV2.json b/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneRangeV2.json index f4079d3..13649d1 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneRangeV2.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneRangeV2.json @@ -6,5 +6,13 @@ "K_KeyId": "ABCDEFAB123498761234123456789012", "K_Key": "cbebdf05fe16099fef502a6d045c1cbb77d29d2fe19f51aec5079a81008305d8868358845d2e3ab38e4fa9cbffcd651a0fc07201d7c9ed9ca3279bfa7cd673ec37b362a0aaa92f95062405a999afd49e4b1f7f818f766c49715407011ac37fa9", "bson_value_type": 16, - "bson_value": "05000000" + "bson_value": "05000000", + "metadata": + [ + "34bc1b32ce6404f3e39c97fdb86b077d70c86896fa329faf3029a14012fe4b743d2267d98b888e9006c683039c1a1347baf18e50f02704b146bfc018cf41a55752815f53d5795c66ad0ed2f2bde7f6471da0b7effca4fe213695f2a16ab9be13", + "6678ff929f4f077b0096782fd4ac3c296bbf2aff2520aca5585cfa8c8d14d481c5701e8b2c684b255911d7c3e1a0f1a93d75b8994f6f7621091bd062d86c439ac0d0836b30e0c9d24ed80d233a09ef441f3e1f08b525c9d2682b23e432bc6f58", + "5de4c0ab39c87e4cb0b3a63e5ea878c10e705acc4c59126f862536ccd79683d318b9b583f23da5713244e4cff9ec8fba5a12adbbb7513ff0304586a4f4cfbe3014a4219179a78618cf889080262b4b96786fb73d4b2ab2c39ab5a0934d9b3106", + "514d94c07296be6cbd9af53b45ee4507c923cdc230779a75c33772df7b884aa898d39eb1be108e0f285dcd2aa2f0e29dd87a04876db6ef9b88e4338e7a56f2df5267ce74d2ade2078fc5c4c2d2d341e9bfa921912e2768ffe7f81fd02a3fc26a", + "774adf3322ba11a79d78bf82779ca2884563b4b2d7db084fa129ce9b3b62882101154aeacca3f2615873cf24a72cf39a791a43422c79c6509712dccdaa1632322a2dff00a448ceb0b98918cd1274fee83a7c33c1a40ff17693f78d785b334bdc" + ] } \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneV2.json b/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneV2.json index a15fa3a..138d10b 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneV2.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneV2.json @@ -7,4 +7,5 @@ "K_Key": "cbebdf05fe16099fef502a6d045c1cbb77d29d2fe19f51aec5079a81008305d8868358845d2e3ab38e4fa9cbffcd651a0fc07201d7c9ed9ca3279bfa7cd673ec37b362a0aaa92f95062405a999afd49e4b1f7f818f766c49715407011ac37fa9", "bson_value_type": 2, "bson_value": "0700000073656372657400", + "metadata": ["81740531ddf2920cd9a640d02edf076abf87a8e31bb7b1afd78219c74f24fa538dbe68e7b9fa42edf928cadc495b51460d0c3b3174df01b0e8b19845da8b188af1ca67aaa23e828317e44cb237e3628f76de9ede194321cd9470a2df0b6923ae"] } \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/data/kms-tests.json b/ext/libmongocrypt/libmongocrypt/test/data/kms-tests.json index 3b47bc4..52067a4 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/kms-tests.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/kms-tests.json @@ -44,8 +44,8 @@ { "ctx": ["datakey", "decrypt"], "description": "Empty body", - "http_reply": ["HTTP/1.1 500 Internal error\r\n", "\r\n"], - "expect": "Error in KMS response. HTTP status=500" + "http_reply": ["HTTP/1.1 418 I'm a teapot\r\n", "\r\n"], + "expect": "Error in KMS response. HTTP status=418" }, { "ctx": ["datakey", "decrypt"], @@ -73,11 +73,11 @@ "ctx": ["datakey", "decrypt"], "description": "Content-Length explicitly 0", "http_reply": [ - "HTTP/1.1 500 Internal error\r\n", + "HTTP/1.1 418 I'm a teapot\r\n", "Content-Length: 0\r\n", "\r\n" ], - "expect": "Error in KMS response. HTTP status=500" + "expect": "Error in KMS response. HTTP status=418" }, { "description": "Non-error non-200 HTTP status", diff --git a/ext/libmongocrypt/libmongocrypt/test/data/multikey/command.json b/ext/libmongocrypt/libmongocrypt/test/data/multikey/command.json new file mode 100644 index 0000000..52defa5 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/multikey/command.json @@ -0,0 +1,7 @@ +{ + "find": "coll", + "filter": { + "uses_key_a": "foo", + "uses_key_b": "bar" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-document.json b/ext/libmongocrypt/libmongocrypt/test/data/multikey/key-document-a.json similarity index 58% rename from ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-document.json rename to ext/libmongocrypt/libmongocrypt/test/data/multikey/key-document-a.json index 5414072..7a7f2e7 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/test/example/key-document.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/multikey/key-document-a.json @@ -1,36 +1,35 @@ { - "status": { - "$numberInt": "1" - }, "_id": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, - "masterKey": { - "region": "us-east-1", - "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", - "provider": "aws" - }, - "updateDate": { - "$date": { - "$numberLong": "1557827033449" - } - }, + "keyAltNames": [ + "aaaaaaaaaaaaaaaa" + ], "keyMaterial": { "$binary": { - "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", + "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { - "$numberLong": "1557827033449" + "$numberLong": "1641016800000" } }, - "keyAltNames": [ - "altKeyName", - "another_altname" - ] + "updateDate": { + "$date": { + "$numberLong": "1641016860000" + } + }, + "status": { + "$numberInt": "1" + }, + "masterKey": { + "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", + "region": "us-east-1", + "provider": "aws" + } } diff --git a/ext/libmongocrypt/libmongocrypt/test/data/multikey/key-document-b.json b/ext/libmongocrypt/libmongocrypt/test/data/multikey/key-document-b.json new file mode 100644 index 0000000..ea468b5 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/multikey/key-document-b.json @@ -0,0 +1,37 @@ +{ + "_id": { + "$binary": { + "base64": "YmJiYmJiYmJiYmJiYmJiYg==", + "subType": "04" + } + }, + "keyAltNames": [ + "bbbbbbbbbbbbbbbb", + "additionalAltName" + ], + "keyMaterial": { + "$binary": { + "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEGkNTybTc7Eyif0f+qqE0lAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDB2j78AeuIQxcRh8cQIBEIB7vj9buHEaT7XHFIsKBJiyzZRmNnjvqMK5LSdzonKdx97jlqauvPvTDXSsdQDcspUs5oLrGmAXpbFResscxmbwZoKgUtWiuIOpeAcYuszCiMKt15s1WIMLDXUhYtfCmhRhekvgHnRAaK4HJMlGE+lKJXYI84E0b86Cd/g+", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1641020400000" + } + }, + "updateDate": { + "$date": { + "$numberLong": "1641020460000" + } + }, + "status": { + "$numberInt": "1" + }, + "masterKey": { + "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", + "region": "us-east-1", + "provider": "aws", + "endpoint": "example.com" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/multikey/mongocryptd_reply.json b/ext/libmongocrypt/libmongocrypt/test/data/multikey/mongocryptd_reply.json new file mode 100644 index 0000000..fa4067d --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/multikey/mongocryptd_reply.json @@ -0,0 +1,34 @@ +{ + "hasEncryptionPlaceholders": true, + "schemaRequiresEncryption": true, + "result": { + "find": "coll", + "filter": { + "$and": [ + { + "uses_key_a": { + "$eq": { + "$binary": { + "base64": "ADAAAAAQYQABAAAABWtpABAAAAAEYWFhYWFhYWFhYWFhYWFhYQJ2AAQAAABmb28AAA==", + "subType": "06" + } + } + } + }, + { + "uses_key_b": { + "$eq": { + "$binary": { + "base64": "ADAAAAAQYQABAAAABWtpABAAAAAEYmJiYmJiYmJiYmJiYmJiYgJ2AAQAAABiYXIAAA==", + "subType": "06" + } + } + } + } + ] + } + }, + "ok": { + "$numberDouble": "1.0" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/multikey/schema_map.json b/ext/libmongocrypt/libmongocrypt/test/data/multikey/schema_map.json new file mode 100644 index 0000000..ceaf0a9 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/multikey/schema_map.json @@ -0,0 +1,35 @@ +{ + "db.coll": { + "properties": { + "uses_key_a": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "uses_key_b": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "YmJiYmJiYmJiYmJiYmJiYg==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/rmd/kms-decrypt-reply-429.txt b/ext/libmongocrypt/libmongocrypt/test/data/rmd/kms-decrypt-reply-429.txt new file mode 100644 index 0000000..7eb1bca --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/rmd/kms-decrypt-reply-429.txt @@ -0,0 +1,6 @@ +HTTP/1.1 429 OK +x-amzn-RequestId: deeb35e5-4ecb-4bf1-9af5-84a54ff0af0e +Content-Type: application/x-amz-json-1.1 +Content-Length: 233 + +{"KeyId": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "Plaintext": "TqhXy3tKckECjy4/ZNykMWG8amBF46isVPzeOgeusKrwheBmYaU8TMG5AHR/NeUDKukqo8hBGgogiQOVpLPkqBQHD8YkLsNbDmHoGOill5QAHnniF/Lz405bGucB5TfR"} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c b/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c index 3de46d9..6ede0d8 100644 --- a/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c +++ b/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c @@ -108,7 +108,7 @@ static void _print_binary_as_bson(mongocrypt_binary_t *binary) { BSON_ASSERT(binary); bson_init_static(&as_bson, mongocrypt_binary_data(binary), mongocrypt_binary_len(binary)); - str = bson_as_json(&as_bson, NULL); + str = bson_as_relaxed_extended_json(&as_bson, NULL); printf("%s\n", str); bson_free(str); } diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-cmp.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-cmp.c new file mode 100644 index 0000000..1ee9b54 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-cmp.c @@ -0,0 +1,304 @@ +/* + * Copyright 2018-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// `test-mc-cmp.h` is a modified copy of `test-bson-cmp.c` from libbson 1.28.0. + +#include "test-mongocrypt.h" + +#include "mc-cmp-private.h" + +static void test_mc_cmp_equal(_mongocrypt_tester_t *tester) { + (void)tester; + + ASSERT(mc_cmp_equal_ss(0, 0)); + ASSERT(!mc_cmp_equal_ss(0, -1)); + ASSERT(!mc_cmp_equal_ss(0, 1)); + ASSERT(!mc_cmp_equal_ss(-1, 0)); + ASSERT(mc_cmp_equal_ss(-1, -1)); + ASSERT(!mc_cmp_equal_ss(-1, 1)); + ASSERT(!mc_cmp_equal_ss(1, 0)); + ASSERT(!mc_cmp_equal_ss(1, -1)); + ASSERT(mc_cmp_equal_ss(1, 1)); + + ASSERT(mc_cmp_equal_uu(0u, 0u)); + ASSERT(!mc_cmp_equal_uu(0u, 1u)); + ASSERT(!mc_cmp_equal_uu(1u, 0u)); + ASSERT(mc_cmp_equal_uu(1u, 1u)); + + ASSERT(mc_cmp_equal_su(0, 0u)); + ASSERT(!mc_cmp_equal_su(0, 1u)); + ASSERT(!mc_cmp_equal_su(-1, 0u)); + ASSERT(!mc_cmp_equal_su(-1, 1u)); + ASSERT(!mc_cmp_equal_su(1, 0u)); + ASSERT(mc_cmp_equal_su(1, 1u)); + + ASSERT(mc_cmp_equal_us(0u, 0)); + ASSERT(!mc_cmp_equal_us(0u, -1)); + ASSERT(!mc_cmp_equal_us(0u, 1)); + ASSERT(!mc_cmp_equal_us(1u, 0)); + ASSERT(!mc_cmp_equal_us(1u, -1)); + ASSERT(mc_cmp_equal_us(1u, 1)); +} + +static void test_mc_cmp_not_equal(_mongocrypt_tester_t *tester) { + (void)tester; + + ASSERT(!mc_cmp_not_equal_ss(0, 0)); + ASSERT(mc_cmp_not_equal_ss(0, -1)); + ASSERT(mc_cmp_not_equal_ss(0, 1)); + ASSERT(mc_cmp_not_equal_ss(-1, 0)); + ASSERT(!mc_cmp_not_equal_ss(-1, -1)); + ASSERT(mc_cmp_not_equal_ss(-1, 1)); + ASSERT(mc_cmp_not_equal_ss(1, 0)); + ASSERT(mc_cmp_not_equal_ss(1, -1)); + ASSERT(!mc_cmp_not_equal_ss(1, 1)); + + ASSERT(!mc_cmp_not_equal_uu(0u, 0u)); + ASSERT(mc_cmp_not_equal_uu(0u, 1u)); + ASSERT(mc_cmp_not_equal_uu(1u, 0u)); + ASSERT(!mc_cmp_not_equal_uu(1u, 1u)); + + ASSERT(!mc_cmp_not_equal_su(0, 0u)); + ASSERT(mc_cmp_not_equal_su(0, 1u)); + ASSERT(mc_cmp_not_equal_su(-1, 0u)); + ASSERT(mc_cmp_not_equal_su(-1, 1u)); + ASSERT(mc_cmp_not_equal_su(1, 0u)); + ASSERT(!mc_cmp_not_equal_su(1, 1u)); + + ASSERT(!mc_cmp_not_equal_us(0u, 0)); + ASSERT(mc_cmp_not_equal_us(0u, -1)); + ASSERT(mc_cmp_not_equal_us(0u, 1)); + ASSERT(mc_cmp_not_equal_us(1u, 0)); + ASSERT(mc_cmp_not_equal_us(1u, -1)); + ASSERT(!mc_cmp_not_equal_us(1u, 1)); +} + +static void test_mc_cmp_less(_mongocrypt_tester_t *tester) { + (void)tester; + + ASSERT(!mc_cmp_less_ss(0, 0)); + ASSERT(!mc_cmp_less_ss(0, -1)); + ASSERT(mc_cmp_less_ss(0, 1)); + ASSERT(mc_cmp_less_ss(-1, 0)); + ASSERT(!mc_cmp_less_ss(-1, -1)); + ASSERT(mc_cmp_less_ss(-1, 1)); + ASSERT(!mc_cmp_less_ss(1, 0)); + ASSERT(!mc_cmp_less_ss(1, -1)); + ASSERT(!mc_cmp_less_ss(1, 1)); + + ASSERT(!mc_cmp_less_uu(0u, 0u)); + ASSERT(mc_cmp_less_uu(0u, 1u)); + ASSERT(!mc_cmp_less_uu(1u, 0u)); + ASSERT(!mc_cmp_less_uu(1u, 1u)); + + ASSERT(!mc_cmp_less_su(0, 0u)); + ASSERT(mc_cmp_less_su(0, 1u)); + ASSERT(mc_cmp_less_su(-1, 0u)); + ASSERT(mc_cmp_less_su(-1, 1u)); + ASSERT(!mc_cmp_less_su(1, 0u)); + ASSERT(!mc_cmp_less_su(1, 1u)); + + ASSERT(!mc_cmp_less_us(0u, 0)); + ASSERT(!mc_cmp_less_us(0u, -1)); + ASSERT(mc_cmp_less_us(0u, 1)); + ASSERT(!mc_cmp_less_us(1u, 0)); + ASSERT(!mc_cmp_less_us(1u, -1)); + ASSERT(!mc_cmp_less_us(1u, 1)); +} + +static void test_mc_cmp_greater(_mongocrypt_tester_t *tester) { + (void)tester; + + ASSERT(!mc_cmp_greater_ss(0, 0)); + ASSERT(mc_cmp_greater_ss(0, -1)); + ASSERT(!mc_cmp_greater_ss(0, 1)); + ASSERT(!mc_cmp_greater_ss(-1, 0)); + ASSERT(!mc_cmp_greater_ss(-1, -1)); + ASSERT(!mc_cmp_greater_ss(-1, 1)); + ASSERT(mc_cmp_greater_ss(1, 0)); + ASSERT(mc_cmp_greater_ss(1, -1)); + ASSERT(!mc_cmp_greater_ss(1, 1)); + + ASSERT(!mc_cmp_greater_uu(0u, 0u)); + ASSERT(!mc_cmp_greater_uu(0u, 1u)); + ASSERT(mc_cmp_greater_uu(1u, 0u)); + ASSERT(!mc_cmp_greater_uu(1u, 1u)); + + ASSERT(!mc_cmp_greater_su(0, 0u)); + ASSERT(!mc_cmp_greater_su(0, 1u)); + ASSERT(!mc_cmp_greater_su(-1, 0u)); + ASSERT(!mc_cmp_greater_su(-1, 1u)); + ASSERT(mc_cmp_greater_su(1, 0u)); + ASSERT(!mc_cmp_greater_su(1, 1u)); + + ASSERT(!mc_cmp_greater_us(0u, 0)); + ASSERT(mc_cmp_greater_us(0u, -1)); + ASSERT(!mc_cmp_greater_us(0u, 1)); + ASSERT(mc_cmp_greater_us(1u, 0)); + ASSERT(mc_cmp_greater_us(1u, -1)); + ASSERT(!mc_cmp_greater_us(1u, 1)); +} + +static void test_mc_cmp_less_equal(_mongocrypt_tester_t *tester) { + (void)tester; + + ASSERT(mc_cmp_less_equal_ss(0, 0)); + ASSERT(!mc_cmp_less_equal_ss(0, -1)); + ASSERT(mc_cmp_less_equal_ss(0, 1)); + ASSERT(mc_cmp_less_equal_ss(-1, 0)); + ASSERT(mc_cmp_less_equal_ss(-1, -1)); + ASSERT(mc_cmp_less_equal_ss(-1, 1)); + ASSERT(!mc_cmp_less_equal_ss(1, 0)); + ASSERT(!mc_cmp_less_equal_ss(1, -1)); + ASSERT(mc_cmp_less_equal_ss(1, 1)); + + ASSERT(mc_cmp_less_equal_uu(0u, 0u)); + ASSERT(mc_cmp_less_equal_uu(0u, 1u)); + ASSERT(!mc_cmp_less_equal_uu(1u, 0u)); + ASSERT(mc_cmp_less_equal_uu(1u, 1u)); + + ASSERT(mc_cmp_less_equal_su(0, 0u)); + ASSERT(mc_cmp_less_equal_su(0, 1u)); + ASSERT(mc_cmp_less_equal_su(-1, 0u)); + ASSERT(mc_cmp_less_equal_su(-1, 1u)); + ASSERT(!mc_cmp_less_equal_su(1, 0u)); + ASSERT(mc_cmp_less_equal_su(1, 1u)); + + ASSERT(mc_cmp_less_equal_us(0u, 0)); + ASSERT(!mc_cmp_less_equal_us(0u, -1)); + ASSERT(mc_cmp_less_equal_us(0u, 1)); + ASSERT(!mc_cmp_less_equal_us(1u, 0)); + ASSERT(!mc_cmp_less_equal_us(1u, -1)); + ASSERT(mc_cmp_less_equal_us(1u, 1)); +} + +static void test_mc_cmp_greater_equal(_mongocrypt_tester_t *tester) { + (void)tester; + + ASSERT(mc_cmp_greater_equal_ss(0, 0)); + ASSERT(mc_cmp_greater_equal_ss(0, -1)); + ASSERT(!mc_cmp_greater_equal_ss(0, 1)); + ASSERT(!mc_cmp_greater_equal_ss(-1, 0)); + ASSERT(mc_cmp_greater_equal_ss(-1, -1)); + ASSERT(!mc_cmp_greater_equal_ss(-1, 1)); + ASSERT(mc_cmp_greater_equal_ss(1, 0)); + ASSERT(mc_cmp_greater_equal_ss(1, -1)); + ASSERT(mc_cmp_greater_equal_ss(1, 1)); + + ASSERT(mc_cmp_greater_equal_uu(0u, 0u)); + ASSERT(!mc_cmp_greater_equal_uu(0u, 1u)); + ASSERT(mc_cmp_greater_equal_uu(1u, 0u)); + ASSERT(mc_cmp_greater_equal_uu(1u, 1u)); + + ASSERT(mc_cmp_greater_equal_su(0, 0u)); + ASSERT(!mc_cmp_greater_equal_su(0, 1u)); + ASSERT(!mc_cmp_greater_equal_su(-1, 0u)); + ASSERT(!mc_cmp_greater_equal_su(-1, 1u)); + ASSERT(mc_cmp_greater_equal_su(1, 0u)); + ASSERT(mc_cmp_greater_equal_su(1, 1u)); + + ASSERT(mc_cmp_greater_equal_us(0u, 0)); + ASSERT(mc_cmp_greater_equal_us(0u, -1)); + ASSERT(!mc_cmp_greater_equal_us(0u, 1)); + ASSERT(mc_cmp_greater_equal_us(1u, 0)); + ASSERT(mc_cmp_greater_equal_us(1u, -1)); + ASSERT(mc_cmp_greater_equal_us(1u, 1)); +} + +static void test_mc_in_range(_mongocrypt_tester_t *tester) { + (void)tester; + + const int64_t int8_min = INT8_MIN; + const int64_t int8_max = INT8_MAX; + const int64_t int32_min = INT32_MIN; + const int64_t int32_max = INT32_MAX; + + const uint64_t uint8_max = UINT8_MAX; + const uint64_t uint32_max = UINT32_MAX; + + const ssize_t ssize_min = SSIZE_MIN; + const ssize_t ssize_max = SSIZE_MAX; + + ASSERT(!mc_in_range_signed(int8_t, int8_min - 1)); + ASSERT(mc_in_range_signed(int8_t, int8_min)); + ASSERT(mc_in_range_signed(int8_t, 0)); + ASSERT(mc_in_range_signed(int8_t, int8_max)); + ASSERT(!mc_in_range_signed(int8_t, int8_max + 1)); + + ASSERT(mc_in_range_unsigned(int8_t, 0u)); + ASSERT(mc_in_range_unsigned(int8_t, (uint64_t)int8_max)); + ASSERT(!mc_in_range_unsigned(int8_t, (uint64_t)(int8_max + 1))); + + ASSERT(!mc_in_range_signed(uint8_t, int8_min - 1)); + ASSERT(!mc_in_range_signed(uint8_t, int8_min)); + ASSERT(mc_in_range_signed(uint8_t, 0)); + ASSERT(mc_in_range_signed(uint8_t, int8_max)); + ASSERT(mc_in_range_signed(uint8_t, int8_max + 1)); + ASSERT(mc_in_range_signed(uint8_t, (int64_t)uint8_max)); + ASSERT(!mc_in_range_signed(uint8_t, (int64_t)uint8_max + 1)); + + ASSERT(mc_in_range_unsigned(uint8_t, 0u)); + ASSERT(mc_in_range_unsigned(uint8_t, uint8_max)); + ASSERT(!mc_in_range_unsigned(uint8_t, uint8_max + 1u)); + + ASSERT(!mc_in_range_signed(int32_t, int32_min - 1)); + ASSERT(mc_in_range_signed(int32_t, int32_min)); + ASSERT(mc_in_range_signed(int32_t, 0)); + ASSERT(mc_in_range_signed(int32_t, int32_max)); + ASSERT(!mc_in_range_signed(int32_t, int32_max + 1)); + + ASSERT(mc_in_range_unsigned(int32_t, 0u)); + ASSERT(mc_in_range_unsigned(int32_t, (uint64_t)int32_max)); + ASSERT(!mc_in_range_unsigned(int32_t, (uint64_t)(int32_max + 1))); + + ASSERT(!mc_in_range_signed(uint32_t, int32_min - 1)); + ASSERT(!mc_in_range_signed(uint32_t, int32_min)); + ASSERT(mc_in_range_signed(uint32_t, 0)); + ASSERT(mc_in_range_signed(uint32_t, int32_max)); + ASSERT(mc_in_range_signed(uint32_t, int32_max + 1)); + ASSERT(mc_in_range_signed(uint32_t, (int64_t)uint32_max)); + ASSERT(!mc_in_range_signed(uint32_t, (int64_t)uint32_max + 1)); + + ASSERT(mc_in_range_unsigned(uint32_t, 0u)); + ASSERT(mc_in_range_unsigned(uint32_t, uint32_max)); + ASSERT(!mc_in_range_unsigned(uint32_t, uint32_max + 1u)); + + ASSERT(mc_in_range_signed(ssize_t, ssize_min)); + ASSERT(mc_in_range_signed(ssize_t, 0)); + ASSERT(mc_in_range_signed(ssize_t, ssize_max)); + + ASSERT(mc_in_range_unsigned(ssize_t, 0u)); + ASSERT(mc_in_range_unsigned(ssize_t, (size_t)ssize_max)); + ASSERT(!mc_in_range_unsigned(ssize_t, (size_t)ssize_max + 1u)); + + ASSERT(!mc_in_range_signed(size_t, ssize_min)); + ASSERT(mc_in_range_signed(size_t, 0)); + ASSERT(mc_in_range_signed(size_t, ssize_max)); + + ASSERT(mc_in_range_unsigned(size_t, 0u)); + ASSERT(mc_in_range_unsigned(size_t, (size_t)ssize_max)); + ASSERT(mc_in_range_unsigned(size_t, (size_t)ssize_max + 1u)); +} + +void _mongocrypt_tester_install_mc_cmp(_mongocrypt_tester_t *tester) { + INSTALL_TEST(test_mc_cmp_equal); + INSTALL_TEST(test_mc_cmp_not_equal); + INSTALL_TEST(test_mc_cmp_less); + INSTALL_TEST(test_mc_cmp_greater); + INSTALL_TEST(test_mc_cmp_less_equal); + INSTALL_TEST(test_mc_cmp_greater_equal); + INSTALL_TEST(test_mc_in_range); +} diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iev-v2.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iev-v2.c index 9777ce5..df025d0 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iev-v2.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iev-v2.c @@ -32,8 +32,12 @@ typedef struct { _mongocrypt_buffer_t K_Key; uint8_t bson_value_type; _mongocrypt_buffer_t bson_value; + uint8_t edge_count; + mc_FLE2TagAndEncryptedMetadataBlock_t *metadata; } _mc_fle2_iev_v2_test; +#define kMetadataLen 96U + static void _mc_fle2_iev_v2_test_destroy(_mc_fle2_iev_v2_test *test) { _mongocrypt_buffer_cleanup(&test->payload); _mongocrypt_buffer_cleanup(&test->S_KeyId); @@ -41,6 +45,11 @@ static void _mc_fle2_iev_v2_test_destroy(_mc_fle2_iev_v2_test *test) { _mongocrypt_buffer_cleanup(&test->K_KeyId); _mongocrypt_buffer_cleanup(&test->K_Key); _mongocrypt_buffer_cleanup(&test->bson_value); + for (int i = 0; i < test->edge_count; ++i) { + mc_FLE2TagAndEncryptedMetadataBlock_cleanup(&test->metadata[i]); + } + + bson_free(test->metadata); } static bool _mc_fle2_iev_v2_test_parse(_mc_fle2_iev_v2_test *test, bson_iter_t *iter) { @@ -83,6 +92,60 @@ static bool _mc_fle2_iev_v2_test_parse(_mc_fle2_iev_v2_test *test, bson_iter_t * TEST_ERROR("Unknown type '%s'", value); } hasType = true; + } else if (!strcmp(field, "metadata")) { + ASSERT_OR_PRINT_MSG(!test->metadata, "Duplicate field 'metadata'"); + + // Use bson functions to loop through array + ASSERT(BSON_ITER_HOLDS_ARRAY(iter)); + const uint8_t *metadata_array_data = NULL; + uint32_t metadata_array_len = 0; + bson_iter_array(iter, &metadata_array_len, &metadata_array_data); + + bson_t metadata_array; + bson_iter_t metadata_array_iter; + if (!bson_init_static(&metadata_array, metadata_array_data, metadata_array_len) + || !bson_iter_init(&metadata_array_iter, &metadata_array)) { + TEST_ERROR("Failed to initialize array iterator"); + return false; + } + + // Count metadata blocks + size_t metadata_count = 0; + while (bson_iter_next(&metadata_array_iter)) { + ASSERT(BSON_ITER_HOLDS_UTF8(&metadata_array_iter)); + metadata_count++; + } + + // Allocate memory for the metadata array + test->metadata = (mc_FLE2TagAndEncryptedMetadataBlock_t *)bson_malloc0( + metadata_count * sizeof(mc_FLE2TagAndEncryptedMetadataBlock_t)); + if (!test->metadata) { + TEST_ERROR("Failed to allocate memory for metadata array"); + return false; + } + + // Reinitialize iter and parse each metadata block + bson_iter_init(&metadata_array_iter, &metadata_array); + int i = 0; + while (bson_iter_next(&metadata_array_iter)) { + ASSERT(BSON_ITER_HOLDS_UTF8(&metadata_array_iter)); + + mongocrypt_status_t *tmp_status = mongocrypt_status_new(); + const char *value = bson_iter_utf8(&metadata_array_iter, NULL); + + _mongocrypt_buffer_t tmp_buf; + _mongocrypt_buffer_copy_from_hex(&tmp_buf, value); + + ASSERT_OK_STATUS(mc_FLE2TagAndEncryptedMetadataBlock_parse(&test->metadata[i], &tmp_buf, tmp_status), + tmp_status); + + _mongocrypt_buffer_cleanup(&tmp_buf); + mongocrypt_status_destroy(tmp_status); + i++; + } + + test->edge_count = i; + } else { TEST_ERROR("Unknown field '%s'", field); } @@ -109,12 +172,14 @@ static void _mc_fle2_iev_v2_test_run(_mongocrypt_tester_t *tester, _mc_fle2_iev_ mc_FLE2IndexedEncryptedValueV2_t *iev = mc_FLE2IndexedEncryptedValueV2_new(); // Parse payload. - if (test->type == kTypeEquality) { - ASSERT_OK_STATUS(mc_FLE2IndexedEqualityEncryptedValueV2_parse(iev, &test->payload, status), status); - } else { - ASSERT(test->type == kTypeRange); - ASSERT_OK_STATUS(mc_FLE2IndexedRangeEncryptedValueV2_parse(iev, &test->payload, status), status); - } + ASSERT_OK_STATUS(mc_FLE2IndexedEncryptedValueV2_parse(iev, &test->payload, status), status); + + // Reserialize and assert that the result is the same as the initial input + _mongocrypt_buffer_t serialized_buf; + _mongocrypt_buffer_init_size(&serialized_buf, test->payload.len); + ASSERT_OK_STATUS(mc_FLE2IndexedEncryptedValueV2_serialize(iev, &serialized_buf, status), status); + ASSERT_CMPBUF(serialized_buf, test->payload); + _mongocrypt_buffer_cleanup(&serialized_buf); // Validate S_KeyId as parsed. const _mongocrypt_buffer_t *S_KeyId = mc_FLE2IndexedEncryptedValueV2_get_S_KeyId(iev, status); @@ -142,6 +207,27 @@ static void _mc_fle2_iev_v2_test_run(_mongocrypt_tester_t *tester, _mc_fle2_iev_ ASSERT_OK_STATUS(bson_value, status); ASSERT_CMPBUF(*bson_value, test->bson_value); + uint8_t edge_count = 1; + if (test->type == kTypeRange) { + // Validate edge count + edge_count = mc_FLE2IndexedEncryptedValueV2_get_edge_count(iev, status); + ASSERT_OK_STATUS(edge_count, status); + ASSERT_CMPINT(edge_count, ==, test->edge_count); + } + + // Validate edges/metadata + mc_FLE2TagAndEncryptedMetadataBlock_t metadata; + for (int i = 0; i < edge_count; ++i) { + if (test->type == kTypeRange) { + ASSERT(mc_FLE2IndexedEncryptedValueV2_get_edge(iev, &metadata, i, status)); + } else { + ASSERT(mc_FLE2IndexedEncryptedValueV2_get_metadata(iev, &metadata, status)); + } + ASSERT_CMPBUF(metadata.encryptedCount, test->metadata[i].encryptedCount); + ASSERT_CMPBUF(metadata.tag, test->metadata[i].tag); + ASSERT_CMPBUF(metadata.encryptedZeros, test->metadata[i].encryptedZeros); + } + // All done! mc_FLE2IndexedEncryptedValueV2_destroy(iev); mongocrypt_destroy(crypt); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c index af7ba18..91a6a6a 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c @@ -238,6 +238,8 @@ static void _test_mc_FLE2InsertUpdatePayloadV2_parses_crypto_params(_mongocrypt_ ASSERT(got.indexMax.value_type == BSON_TYPE_INT32); ASSERT_CMPINT32(got.indexMax.value.v_int32, ==, 1234567); + + mc_FLE2InsertUpdatePayloadV2_cleanup(&got); } void _mongocrypt_tester_install_fle2_payload_iup_v2(_mongocrypt_tester_t *tester) { diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-tag-and-encrypted-metadata-block.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-tag-and-encrypted-metadata-block.c new file mode 100644 index 0000000..d57fc14 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-tag-and-encrypted-metadata-block.c @@ -0,0 +1,56 @@ +#include "mc-fle2-tag-and-encrypted-metadata-block-private.h" +#include "test-mongocrypt-assert.h" +#include "test-mongocrypt.h" + +#define TEST_TAG_AND_ENCRYPTED_METADATA_BLOCK \ + "34bc1b32ce6404f3e39c97fdb86b077d70c86896fa329faf3029a14012fe4b743d2267d98b888e9006c683039c1a1347baf18e50f02704b1" \ + "46bfc018cf41a55752815f53d5795c66ad0ed2f2bde7f6471da0b7effca4fe213695f2a16ab9be13" + +static void _test_mc_FLE2TagAndEncryptedMetadataBlock_roundtrip(_mongocrypt_tester_t *tester) { + _mongocrypt_buffer_t input; + _mongocrypt_buffer_t expect_encryptedCount; + _mongocrypt_buffer_t expect_tag; + _mongocrypt_buffer_t expect_encryptedZeros; + _mongocrypt_buffer_t output; + mc_FLE2TagAndEncryptedMetadataBlock_t metadata; + + _mongocrypt_buffer_copy_from_hex(&expect_encryptedCount, + "34bc1b32ce6404f3e39c97fdb86b077d70c86896fa329faf3029a14012fe4b74"); + _mongocrypt_buffer_copy_from_hex(&expect_tag, "3d2267d98b888e9006c683039c1a1347baf18e50f02704b146bfc018cf41a557"); + _mongocrypt_buffer_copy_from_hex(&expect_encryptedZeros, + "52815f53d5795c66ad0ed2f2bde7f6471da0b7effca4fe213695f2a16ab9be13"); + + _mongocrypt_buffer_copy_from_hex(&input, TEST_TAG_AND_ENCRYPTED_METADATA_BLOCK); + + mongocrypt_status_t *status = mongocrypt_status_new(); + mc_FLE2TagAndEncryptedMetadataBlock_init(&metadata); + + // Parse into metadata struct + ASSERT_OK_STATUS(mc_FLE2TagAndEncryptedMetadataBlock_parse(&metadata, &input, status), status); + + // Check values + ASSERT_CMPBUF(expect_encryptedCount, metadata.encryptedCount); + ASSERT_CMPBUF(expect_tag, metadata.tag); + ASSERT_CMPBUF(expect_encryptedZeros, metadata.encryptedZeros); + + // Serialize back into buffer + _mongocrypt_buffer_init_size(&output, input.len); + ASSERT_OK_STATUS(mc_FLE2TagAndEncryptedMetadataBlock_serialize(&metadata, &output, status), status); + + // Check that unparsed input is the same as serialized output + ASSERT_CMPBUF(input, output); + + mongocrypt_status_destroy(status); + mc_FLE2TagAndEncryptedMetadataBlock_cleanup(&metadata); + _mongocrypt_buffer_cleanup(&expect_encryptedCount); + _mongocrypt_buffer_cleanup(&expect_tag); + _mongocrypt_buffer_cleanup(&expect_encryptedZeros); + _mongocrypt_buffer_cleanup(&input); + _mongocrypt_buffer_cleanup(&output); +} + +#undef TEST_TAG_AND_ENCRYPTED_METADATA_BLOCK + +void _mongocrypt_tester_install_fle2_tag_and_encrypted_metadata_block(_mongocrypt_tester_t *tester) { + INSTALL_TEST(_test_mc_FLE2TagAndEncryptedMetadataBlock_roundtrip); +} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c index 2214c66..5a06709 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c @@ -85,7 +85,7 @@ typedef struct { typedef struct _test_getMincover_args { mc_mincover_t *(*getMincover)(void *tests, size_t idx, mongocrypt_status_t *status); - const char *(*expectError)(void *tests, size_t idx); + const char *(*expectError)(void *tests, size_t idx, mongocrypt_status_t *status); const char *const *(*expectMincoverStrings)(void *tests, size_t idx); void (*dump)(void *tests, size_t idx, mc_mincover_t *got); } _test_getMincover_args; @@ -171,23 +171,25 @@ static mc_mincover_t *_test_getMincoverDecimal128_helper(void *tests, size_t idx } #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT -static const char *_test_expectError32(void *tests, size_t idx) { +static const char *_test_expectError32(void *tests, size_t idx, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(tests); + BSON_ASSERT_PARAM(status); return ((Int32Test *)tests + idx)->expectError; } -static const char *_test_expectError64(void *tests, size_t idx) { +static const char *_test_expectError64(void *tests, size_t idx, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(tests); + BSON_ASSERT_PARAM(status); return ((Int64Test *)tests + idx)->expectError; } -static const char *_test_expectErrorDouble(void *tests, size_t idx) { +static const char *_test_expectErrorDouble(void *tests, size_t idx, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(tests); + BSON_ASSERT_PARAM(status); DoubleTest *test = ((DoubleTest *)tests + idx); if (test->min.set && test->max.set && test->precision.set) { // Expect an error for tests including an invalid min/max/precision. uint32_t ignored; - mongocrypt_status_t *const status = mongocrypt_status_new(); if (!mc_canUsePrecisionModeDouble(test->min.value, test->max.value, test->precision.value, &ignored, status)) { if (!mongocrypt_status_ok(status)) { return mongocrypt_status_message(status, NULL); @@ -196,19 +198,18 @@ static const char *_test_expectErrorDouble(void *tests, size_t idx) { return "The domain of double values specified by the min, max, and precision cannot be represented in " "fewer than 64 bits"; } - mongocrypt_status_destroy(status); } return test->expectError; } #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT -static const char *_test_expectErrorDecimal128(void *tests, size_t idx) { +static const char *_test_expectErrorDecimal128(void *tests, size_t idx, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(tests); + BSON_ASSERT_PARAM(status); Decimal128Test *test = ((Decimal128Test *)tests + idx); if (test->min.set && test->max.set && test->precision.set) { // Expect an error for tests including an invalid min/max/precision. uint32_t ignored; - mongocrypt_status_t *const status = mongocrypt_status_new(); if (!mc_canUsePrecisionModeDecimal(test->min.value, test->max.value, test->precision.value, &ignored, status)) { if (!mongocrypt_status_ok(status)) { return mongocrypt_status_message(status, NULL); @@ -374,7 +375,7 @@ static void _test_getMincover_impl(void *tests, size_t num_tests, _test_getMinco for (size_t i = 0; i < num_tests; i++) { mongocrypt_status_t *const status = mongocrypt_status_new(); mc_mincover_t *got = args.getMincover(tests, i, status); - const char *expectError = args.expectError(tests, i); + const char *expectError = args.expectError(tests, i, status); if (expectError) { ASSERT_OR_PRINT_MSG(NULL == got, "expected error, got success"); ASSERT_STATUS_CONTAINS(status, expectError); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.h b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.h index 12bfb81..4db8856 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.h +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.h @@ -26,8 +26,8 @@ bool _check_match_bson(const bson_t *doc, const bson_t *pattern, char *errmsg, s if (1) { \ char errmsg[1024] = ""; \ if (!_check_match_bson(doc, pattern, errmsg, sizeof(errmsg))) { \ - char *doc_str = bson_as_json(doc, NULL); \ - char *pattern_str = bson_as_json(pattern, NULL); \ + char *doc_str = bson_as_relaxed_extended_json(doc, NULL); \ + char *pattern_str = bson_as_relaxed_extended_json(pattern, NULL); \ \ TEST_ERROR("ASSERT_MATCH failed with document:\n\n" \ "%s\n" \ diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache.c index 6a88933..7b0d80b 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache.c @@ -68,24 +68,6 @@ void _test_cache(_mongocrypt_tester_t *tester) { bson_destroy(entry2); } -static void _usleep(int64_t usec) { -#ifdef _WIN32 - LARGE_INTEGER ft; - HANDLE timer; - - BSON_ASSERT(usec >= 0); - - ft.QuadPart = -(10 * usec); - timer = CreateWaitableTimer(NULL, true, NULL); - SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); - WaitForSingleObject(timer, INFINITE); - CloseHandle(timer); -#else - BSON_ASSERT(usec >= 0); - usleep((useconds_t)usec); -#endif -} - static void _test_cache_expiration(_mongocrypt_tester_t *tester) { _mongocrypt_cache_t cache; mongocrypt_status_t *status; diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c index 090d68e..686593a 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c @@ -40,7 +40,18 @@ "CC0B95D217493205A038C50F537F452C59EFF6541D0026" /* a document containing the history of calls */ -static bson_string_t *call_history; +static char *call_history; + +// APPEND_CALLHISTORY appends a formatted string to `call_history`. +#define APPEND_CALLHISTORY(...) \ + if (1) { \ + char *previous = call_history; \ + char *addition = bson_strdup_printf(__VA_ARGS__); \ + call_history = bson_strdup_printf("%s%s", previous ? previous : "", addition); \ + bson_free(addition); \ + bson_free(previous); \ + } else \ + (void)0 static void _append_bin(const char *name, mongocrypt_binary_t *bin) { _mongocrypt_buffer_t tmp; @@ -48,7 +59,7 @@ static void _append_bin(const char *name, mongocrypt_binary_t *bin) { _mongocrypt_buffer_from_binary(&tmp, bin); hex = _mongocrypt_buffer_to_hex(&tmp); - bson_string_append_printf(call_history, "%s:%s\n", name, hex); + APPEND_CALLHISTORY("%s:%s\n", name, hex); bson_free(hex); _mongocrypt_buffer_cleanup(&tmp); } @@ -61,7 +72,7 @@ static bool _mock_aes_256_xxx_encrypt(void *ctx, uint32_t *bytes_written, mongocrypt_status_t *status) { BSON_ASSERT(0 == strncmp("error_on:", (char *)ctx, strlen("error_on:"))); - bson_string_append_printf(call_history, "call:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("call:%s\n", BSON_FUNC); _append_bin("key", key); if (NULL != iv) { _append_bin("iv", iv); @@ -71,7 +82,7 @@ static bool _mock_aes_256_xxx_encrypt(void *ctx, uint8_t *out_u8 = out->data; memcpy(out_u8 + *bytes_written, in->data, in->len); *bytes_written += in->len; - bson_string_append_printf(call_history, "ret:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("ret:%s\n", BSON_FUNC); if (0 == strcmp((char *)ctx, "error_on:aes_256_cbc_encrypt") || 0 == strcmp((char *)ctx, "error_on:aes_256_ctr_encrypt") || 0 == strcmp((char *)ctx, "error_on:aes_256_ecb_encrypt")) { @@ -89,7 +100,7 @@ static bool _mock_aes_256_xxx_decrypt(void *ctx, uint32_t *bytes_written, mongocrypt_status_t *status) { BSON_ASSERT(0 == strncmp("error_on:", (char *)ctx, strlen("error_on:"))); - bson_string_append_printf(call_history, "call:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("call:%s\n", BSON_FUNC); _append_bin("key", key); _append_bin("iv", iv); _append_bin("in", in); @@ -97,7 +108,7 @@ static bool _mock_aes_256_xxx_decrypt(void *ctx, uint8_t *out_u8 = out->data; memcpy(out_u8 + *bytes_written, in->data, in->len); *bytes_written += in->len; - bson_string_append_printf(call_history, "ret:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("ret:%s\n", BSON_FUNC); if (0 == strcmp((char *)ctx, "error_on:aes_256_cbc_decrypt") || 0 == strcmp((char *)ctx, "error_on:aes_256_ctr_decrypt")) { mongocrypt_status_set(status, MONGOCRYPT_STATUS_ERROR_CLIENT, 1, (char *)ctx, -1); @@ -114,11 +125,11 @@ bool _hmac_sha_512(void *ctx, _mongocrypt_buffer_t tmp; BSON_ASSERT(0 == strncmp("error_on:", (char *)ctx, strlen("error_on:"))); - bson_string_append_printf(call_history, "call:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("call:%s\n", BSON_FUNC); _append_bin("key", key); _append_bin("in", in); - bson_string_append_printf(call_history, "ret:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("ret:%s\n", BSON_FUNC); _mongocrypt_buffer_copy_from_hex(&tmp, HMAC_HEX); memcpy(out->data, tmp.data, tmp.len); @@ -138,11 +149,11 @@ bool _hmac_sha_256(void *ctx, _mongocrypt_buffer_t tmp; BSON_ASSERT(0 == strncmp("error_on:", (char *)ctx, strlen("error_on:"))); - bson_string_append_printf(call_history, "call:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("call:%s\n", BSON_FUNC); _append_bin("key", key); _append_bin("in", in); - bson_string_append_printf(call_history, "ret:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("ret:%s\n", BSON_FUNC); _mongocrypt_buffer_copy_from_hex(&tmp, HASH_HEX); memcpy(out->data, tmp.data, tmp.len); @@ -158,10 +169,10 @@ bool _sha_256(void *ctx, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mong _mongocrypt_buffer_t tmp; BSON_ASSERT(0 == strncmp("error_on:", (char *)ctx, strlen("error_on:"))); - bson_string_append_printf(call_history, "call:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("call:%s\n", BSON_FUNC); _append_bin("in", in); - bson_string_append_printf(call_history, "ret:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("ret:%s\n", BSON_FUNC); _mongocrypt_buffer_copy_from_hex(&tmp, HASH_HEX); memcpy(out->data, tmp.data, tmp.len); @@ -178,9 +189,9 @@ bool _random(void *ctx, mongocrypt_binary_t *out, uint32_t count, mongocrypt_sta BSON_ASSERT(count <= 96); BSON_ASSERT(0 == strncmp("error_on:", (char *)ctx, strlen("error_on:"))); - bson_string_append_printf(call_history, "call:%s\n", BSON_FUNC); - bson_string_append_printf(call_history, "count:%d\n", (int)count); - bson_string_append_printf(call_history, "ret:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("call:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("count:%d\n", (int)count); + APPEND_CALLHISTORY("ret:%s\n", BSON_FUNC); _mongocrypt_buffer_t tmp; _mongocrypt_buffer_copy_from_hex(&tmp, RANDOM_HEX); @@ -201,11 +212,11 @@ bool _sign_rsaes_pkcs1_v1_5(void *ctx, _mongocrypt_buffer_t tmp; BSON_ASSERT(0 == strncmp("error_on:", (char *)ctx, strlen("error_on:"))); - bson_string_append_printf(call_history, "call:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("call:%s\n", BSON_FUNC); _append_bin("key", key); _append_bin("in", in); - bson_string_append_printf(call_history, "ret:%s\n", BSON_FUNC); + APPEND_CALLHISTORY("ret:%s\n", BSON_FUNC); memset(out->data, 0, out->len); _mongocrypt_buffer_copy_from_hex(&tmp, HASH_HEX); @@ -280,7 +291,7 @@ _test_crypto_hooks_encryption_helper(_mongocrypt_tester_t *tester, const char *e _mongocrypt_buffer_copy_from_hex(&associated_data, "AAAA"); _mongocrypt_buffer_copy_from_hex(&plaintext, "BBBB"); - call_history = bson_string_new(NULL); + call_history = NULL; if (ctr_hook || ecb_hook) { const _mongocrypt_value_encryption_algorithm_t *fle2alg = _mcFLE2Algorithm(); @@ -310,7 +321,7 @@ _test_crypto_hooks_encryption_helper(_mongocrypt_tester_t *tester, const char *e ciphertext.len = bytes_written; /* Check the full trace. */ - ASSERT_STREQUAL(call_history->str, expected_call_history); + ASSERT_STREQUAL(call_history, expected_call_history); /* Check the structure of the ciphertext */ BSON_ASSERT(0 @@ -331,7 +342,7 @@ _test_crypto_hooks_encryption_helper(_mongocrypt_tester_t *tester, const char *e _mongocrypt_buffer_cleanup(&ciphertext); mongocrypt_status_destroy(status); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); } static void _test_crypto_hooks_encryption(_mongocrypt_tester_t *tester) { @@ -365,7 +376,7 @@ _test_crypto_hooks_decryption_helper(_mongocrypt_tester_t *tester, const char *e _mongocrypt_buffer_copy_from_hex(&associated_data, "AAAA"); _mongocrypt_buffer_copy_from_hex(&ciphertext, IV_HEX "BBBB0E0E0E0E0E0E0E0E0E0E0E0E0E0E" HMAC_HEX_TAG); - call_history = bson_string_new(NULL); + call_history = NULL; if (ctr_hook || ecb_hook) { const _mongocrypt_value_encryption_algorithm_t *fle2alg = _mcFLE2Algorithm(); @@ -389,7 +400,7 @@ _test_crypto_hooks_decryption_helper(_mongocrypt_tester_t *tester, const char *e plaintext.len = bytes_written; /* Check the full trace. */ - ASSERT_STREQUAL(call_history->str, expected_call_history); + ASSERT_STREQUAL(call_history, expected_call_history); /* Check the resulting plaintext */ BSON_ASSERT(0 == _mongocrypt_buffer_cmp_hex(&plaintext, "BBBB")); @@ -403,7 +414,7 @@ _test_crypto_hooks_decryption_helper(_mongocrypt_tester_t *tester, const char *e _mongocrypt_buffer_cleanup(&ciphertext); mongocrypt_status_destroy(status); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); } static void _test_crypto_hooks_decryption(_mongocrypt_tester_t *tester) { @@ -435,7 +446,7 @@ static void _test_crypto_hooks_iv_gen_helper(_mongocrypt_tester_t *tester, char _mongocrypt_buffer_init(&iv); _mongocrypt_buffer_resize(&iv, MONGOCRYPT_IV_LEN); - call_history = bson_string_new(NULL); + call_history = NULL; ret = _mongocrypt_calculate_deterministic_iv(crypt->crypto, &key, &plaintext, &associated_data, &iv, status); @@ -443,7 +454,7 @@ static void _test_crypto_hooks_iv_gen_helper(_mongocrypt_tester_t *tester, char ASSERT_OK_STATUS(ret, status); /* Check the full trace. */ - ASSERT_STREQUAL(call_history->str, expected_call_history); + ASSERT_STREQUAL(call_history, expected_call_history); /* Check the resulting iv */ BSON_ASSERT(0 == _mongocrypt_buffer_cmp_hex(&iv, expected_iv)); @@ -458,7 +469,7 @@ static void _test_crypto_hooks_iv_gen_helper(_mongocrypt_tester_t *tester, char _mongocrypt_buffer_cleanup(&iv); mongocrypt_status_destroy(status); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); } static void _test_crypto_hooks_iv_gen(_mongocrypt_tester_t *tester) { @@ -481,7 +492,7 @@ static void _test_crypto_hooks_random_helper(_mongocrypt_tester_t *tester, const _mongocrypt_buffer_init(&random); _mongocrypt_buffer_resize(&random, 96); - call_history = bson_string_new(NULL); + call_history = NULL; ret = _mongocrypt_random(crypt->crypto, &random, random.len, status); @@ -489,7 +500,7 @@ static void _test_crypto_hooks_random_helper(_mongocrypt_tester_t *tester, const ASSERT_OK_STATUS(ret, status); /* Check the full trace. */ - ASSERT_STREQUAL(call_history->str, expected_call_history); + ASSERT_STREQUAL(call_history, expected_call_history); /* Check the resulting iv */ BSON_ASSERT(0 == _mongocrypt_buffer_cmp_hex(&random, RANDOM_HEX)); @@ -500,7 +511,7 @@ static void _test_crypto_hooks_random_helper(_mongocrypt_tester_t *tester, const _mongocrypt_buffer_cleanup(&random); mongocrypt_status_destroy(status); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); } static void _test_crypto_hooks_random(_mongocrypt_tester_t *tester) { @@ -518,7 +529,7 @@ static void _test_kms_request_helper(_mongocrypt_tester_t *tester, const char *e crypt = _create_mongocrypt(tester, error_on); ctx = mongocrypt_ctx_new(crypt); - call_history = bson_string_new(NULL); + call_history = NULL; ASSERT_OK(mongocrypt_ctx_setopt_masterkey_aws(ctx, "us-east-1", -1, "cmk", -1), ctx); @@ -530,8 +541,8 @@ static void _test_kms_request_helper(_mongocrypt_tester_t *tester, const char *e /* The call history includes some random data, just assert we've called * our hooks. */ - BSON_ASSERT(strstr(call_history->str, "call:_hmac_sha_256")); - BSON_ASSERT(strstr(call_history->str, "call:_sha_256")); + BSON_ASSERT(strstr(call_history, "call:_hmac_sha_256")); + BSON_ASSERT(strstr(call_history, "call:_sha_256")); } else { ASSERT_FAILS_STATUS(ret, status, error_on); } @@ -539,7 +550,7 @@ static void _test_kms_request_helper(_mongocrypt_tester_t *tester, const char *e mongocrypt_ctx_destroy(ctx); mongocrypt_status_destroy(status); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); } static void _test_kms_request(_mongocrypt_tester_t *tester) { @@ -565,7 +576,7 @@ static void _test_crypto_hooks_explicit_err(_mongocrypt_tester_t *tester) { mongocrypt_binary_t *bin, *key_id; const char *deterministic = MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR; - call_history = bson_string_new(NULL); + call_history = NULL; /* error on something during encryption. */ crypt = _create_mongocrypt(tester, "error_on:hmac_sha512"); @@ -585,7 +596,7 @@ static void _test_crypto_hooks_explicit_err(_mongocrypt_tester_t *tester) { mongocrypt_binary_destroy(key_id); mongocrypt_ctx_destroy(ctx); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); } /* validate that sha256 errors are handled correctly */ @@ -598,7 +609,7 @@ static void _test_crypto_hooks_explicit_sha256_err(_mongocrypt_tester_t *tester) crypt = _create_mongocrypt(tester, "error_on:sha256"); ctx = mongocrypt_ctx_new(crypt); - call_history = bson_string_new(NULL); + call_history = NULL; ASSERT_OK(mongocrypt_ctx_setopt_masterkey_aws(ctx, "us-east-1", -1, "cmk", -1), ctx); ASSERT_FAILS(mongocrypt_ctx_datakey_init(ctx), ctx, "failed to create KMS message"); @@ -606,7 +617,7 @@ static void _test_crypto_hooks_explicit_sha256_err(_mongocrypt_tester_t *tester) mongocrypt_ctx_destroy(ctx); mongocrypt_status_destroy(status); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); } static void _test_crypto_hook_sign_rsaes_pkcs1_v1_5(_mongocrypt_tester_t *tester) { @@ -614,7 +625,7 @@ static void _test_crypto_hook_sign_rsaes_pkcs1_v1_5(_mongocrypt_tester_t *tester mongocrypt_ctx_t *ctx; crypt = _create_mongocrypt(tester, "error_on:none"); - call_history = bson_string_new(NULL); + call_history = NULL; ctx = mongocrypt_ctx_new(crypt); mongocrypt_ctx_setopt_key_encryption_key(ctx, @@ -622,17 +633,17 @@ static void _test_crypto_hook_sign_rsaes_pkcs1_v1_5(_mongocrypt_tester_t *tester "'global', 'keyRing': 'ring', 'keyName': 'key'}")); ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); - BSON_ASSERT(strstr(call_history->str, "call:_sign_rsaes_pkcs1_v1_5")); - BSON_ASSERT(strstr(call_history->str, "key:000000")); + BSON_ASSERT(strstr(call_history, "call:_sign_rsaes_pkcs1_v1_5")); + BSON_ASSERT(strstr(call_history, "key:000000")); mongocrypt_ctx_destroy(ctx); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); /* Test error when creating a data key. */ crypt = _create_mongocrypt(tester, "error_on:sign_rsaes_pkcs1_v1_5"); ctx = mongocrypt_ctx_new(crypt); - call_history = bson_string_new(NULL); + call_history = NULL; mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON("{'provider': 'gcp', 'projectId': 'test', 'location': " @@ -641,12 +652,12 @@ static void _test_crypto_hook_sign_rsaes_pkcs1_v1_5(_mongocrypt_tester_t *tester mongocrypt_ctx_destroy(ctx); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); /* Test error when encrypting. */ crypt = _create_mongocrypt(tester, "error_on:sign_rsaes_pkcs1_v1_5"); ctx = mongocrypt_ctx_new(crypt); - call_history = bson_string_new(NULL); + call_history = NULL; ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_NEED_MONGO_KEYS); @@ -656,7 +667,7 @@ static void _test_crypto_hook_sign_rsaes_pkcs1_v1_5(_mongocrypt_tester_t *tester mongocrypt_ctx_destroy(ctx); mongocrypt_destroy(crypt); - bson_string_free(call_history, true); + bson_free(call_history); } #ifdef MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c index e362846..d6edc33 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c @@ -18,6 +18,7 @@ #include "kms_message/kms_b64.h" #include "mongocrypt-crypto-private.h" // MONGOCRYPT_KEY_LEN +#include "mongocrypt.h" #include "test-mongocrypt-assert-match-bson.h" #include "test-mongocrypt-crypto-std-hooks.h" #include "test-mongocrypt.h" @@ -755,6 +756,30 @@ static void _test_encrypt_caches_keys(_mongocrypt_tester_t *tester) { mongocrypt_destroy(crypt); } +static void _test_encrypt_cache_expiration(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_WITH_SHORT_CACHE); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_DONE); + mongocrypt_ctx_destroy(ctx); + + _usleep(2000); + /* The next context requests keys again + */ + ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/example/mongocryptd-reply.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + BSON_ASSERT(mongocrypt_ctx_state(ctx) == MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/example/key-document.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_DONE); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + static void _test_encrypt_caches_keys_by_alt_name(_mongocrypt_tester_t *tester) { mongocrypt_t *crypt; mongocrypt_ctx_t *ctx; @@ -5476,6 +5501,181 @@ static void _test_range_sends_cryptoParams(_mongocrypt_tester_t *tester) { _mongocrypt_buffer_cleanup(&key123_id); } +typedef struct _responses { + const char *key_document; + const char *oauth_response; + const char *decrypt_response; +} _responses; + +static void _test_encrypt_retry_provider(_responses r, _mongocrypt_tester_t *tester) { + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + + // Create context. + { + // Use explicit encryption to simplify (no schema needed). + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "keyDocumentName"}))), + ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + } + + // Feed key. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE(r.key_document)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + // Feed a retryable HTTP error. + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kctx); + // Expect KMS request is returned again for a retry. + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kctx, ctx); + ASSERT_CMPINT64(mongocrypt_kms_ctx_usleep(kctx), >, 0); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE(r.oauth_response)), kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + // Feed a retryable HTTP error. + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kctx); + // Expect KMS request is returned again for a retry. + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kctx, ctx); + ASSERT_CMPINT64(mongocrypt_kms_ctx_usleep(kctx), >, 0); + // Feed a successful response. + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE(r.decrypt_response)), kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +static void _test_encrypt_retry(_mongocrypt_tester_t *tester) { + // Test that an HTTP error is retried with AWS + { + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Expect no sleep is requested before any error. + ASSERT_CMPINT64(mongocrypt_kms_ctx_usleep(kms_ctx), ==, 0); + // Feed a retryable HTTP error. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kms_ctx); + // Expect KMS request is returned again for a retry. + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Feed a successful response. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-aws/decrypt-response.txt")), kms_ctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_DONE); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + // Azure + { + _responses r = { + "./test/data/key-document-azure.json", + "./test/data/kms-azure/oauth-response.txt", + "./test/data/kms-azure/decrypt-response.txt", + }; + _test_encrypt_retry_provider(r, tester); + } + // GCP + { + _responses r = { + "./test/data/key-document-gcp.json", + "./test/data/kms-gcp/oauth-response.txt", + "./test/data/kms-gcp/decrypt-response.txt", + }; + _test_encrypt_retry_provider(r, tester); + } + // Multiple keys + { + // Create crypt with retry enabled. + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers( + crypt, + TEST_BSON(BSON_STR({"aws" : {"accessKeyId" : "foo", "secretAccessKey" : "bar"}}))), + crypt); + ASSERT_OK(mongocrypt_setopt_retry_kms(crypt, true), crypt); + ASSERT_OK(mongocrypt_setopt_schema_map(crypt, TEST_FILE("./test/data/multikey/schema_map.json")), crypt); + ASSERT_OK(mongocrypt_init(crypt), crypt); + + // Encrypt a command requiring two keys. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/multikey/command.json")), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/multikey/mongocryptd_reply.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/multikey/key-document-a.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/multikey/key-document-b.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Expect two keys are needed. Obtain both. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx1 = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx1); + mongocrypt_kms_ctx_t *kctx2 = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx2); + + // Feed a successful response to the first. + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx1, TEST_FILE("./test/data/kms-aws/decrypt-response.txt")), kctx1); + + // Feed a retryable error response to the second. + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx2, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kctx2); + + // Expect the retried KMS context is returned again. + mongocrypt_kms_ctx_t *kctx_retry = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx_retry); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx_retry, TEST_FILE("./test/data/kms-aws/decrypt-response.txt")), + kctx_retry); + + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_DONE); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + // Test retry does not occur if not enabled. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers( + crypt, + TEST_BSON(BSON_STR({"aws" : {"accessKeyId" : "foo", "secretAccessKey" : "bar"}}))), + crypt); + ASSERT_OK(mongocrypt_init(crypt), crypt); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); // Give a retryable HTTP error. Expect error due to retry disabled. + ASSERT_FAILS(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), + kms_ctx, + "Error in KMS response"); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } +} + void _mongocrypt_tester_install_ctx_encrypt(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_explicit_encrypt_init); INSTALL_TEST(_test_encrypt_init); @@ -5489,6 +5689,7 @@ void _mongocrypt_tester_install_ctx_encrypt(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_local_schema); INSTALL_TEST(_test_encrypt_caches_collinfo); INSTALL_TEST(_test_encrypt_caches_keys); + INSTALL_TEST(_test_encrypt_cache_expiration); INSTALL_TEST(_test_encrypt_caches_keys_by_alt_name); INSTALL_TEST(_test_encrypt_random); INSTALL_TEST(_test_encrypt_is_remote_schema); @@ -5559,4 +5760,5 @@ void _mongocrypt_tester_install_ctx_encrypt(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_rangePreview_fails); INSTALL_TEST(_test_no_trimFactor); INSTALL_TEST(_test_range_sends_cryptoParams); + INSTALL_TEST(_test_encrypt_retry); } diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c index bdd7d6e..69381db 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "mongocrypt-kms-ctx-private.h" #include "test-mongocrypt.h" #define TEST_REWRAP_MASTER_KEY_ID_OLD \ @@ -496,6 +497,83 @@ static void _test_rewrap_many_datakey_need_kms_decrypt(_mongocrypt_tester_t *tes mongocrypt_destroy(crypt); } +static void _test_rewrap_many_datakey_need_kms_retry(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *const filter = TEST_BSON("{'keyAltName': {'$in': ['keyDocumentA', 'keyDocumentB']}}"); + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + mongocrypt_ctx_t *ctx = NULL; + mongocrypt_kms_ctx_t *kms = NULL; + + /* Ensure KMS decrypt requests retry for HTTP errors */ + ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_rewrap_many_datakey_init(ctx, filter), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/rmd/key-document-a.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); // To decrypt. + ASSERT((kms = mongocrypt_ctx_next_kms_ctx(ctx))); + for (int i = 0; i < kms_max_attempts; i++) { + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kms); + ASSERT(mongocrypt_kms_ctx_bytes_needed(kms) == 0); + ASSERT((kms = mongocrypt_ctx_next_kms_ctx(ctx))); + ASSERT(mongocrypt_kms_ctx_usleep(kms) > 0); + } + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/rmd/kms-decrypt-reply-a.txt")), kms); + ASSERT(mongocrypt_kms_ctx_bytes_needed(kms) == 0); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); // To encrypt. + mongocrypt_ctx_destroy(ctx); + + /* Clear key cache. */ + mongocrypt_destroy(crypt); + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + + /* Ensure KMS decrypt requests retried for HTTP errors fail after max attempts */ + ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_rewrap_many_datakey_init(ctx, filter), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/rmd/key-document-a.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + ASSERT((kms = mongocrypt_ctx_next_kms_ctx(ctx))); + for (int i = 0; i <= kms_max_attempts; i++) { + if (i == kms_max_attempts) { + ASSERT_FAILS(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), + kms, + "retries"); + break; + } + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kms); + ASSERT(mongocrypt_kms_ctx_bytes_needed(kms) == 0); + ASSERT((kms = mongocrypt_ctx_next_kms_ctx(ctx))); + ASSERT(mongocrypt_kms_ctx_usleep(kms) > 0); + } + ASSERT_FAILS(mongocrypt_ctx_kms_done(ctx), ctx, "retries"); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_ERROR); + mongocrypt_ctx_destroy(ctx); + + /* Clear key cache. */ + mongocrypt_destroy(crypt); + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + + /* Ensure KMS decrypt requests retry for network errors */ + ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_rewrap_many_datakey_init(ctx, filter), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/rmd/key-document-a.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + ASSERT((kms = mongocrypt_ctx_next_kms_ctx(ctx))); + ASSERT(mongocrypt_kms_ctx_fail(kms)); // Simulate driver-side network failure + ASSERT((kms = mongocrypt_ctx_next_kms_ctx(ctx))); + ASSERT(mongocrypt_kms_ctx_usleep(kms) > 0); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/rmd/kms-decrypt-reply-a.txt")), kms); + ASSERT(mongocrypt_kms_ctx_bytes_needed(kms) == 0); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); // To encrypt. + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + static void _test_rewrap_many_datakey_need_kms_encrypt(_mongocrypt_tester_t *tester) { mongocrypt_binary_t *const filter = TEST_BSON("{'keyAltName': {'$in': ['keyDocumentA', 'keyDocumentB']}}"); @@ -841,6 +919,7 @@ void _mongocrypt_tester_install_ctx_rewrap_many_datakey(_mongocrypt_tester_t *te INSTALL_TEST(_test_rewrap_many_datakey_init); INSTALL_TEST(_test_rewrap_many_datakey_need_mongo_keys); INSTALL_TEST(_test_rewrap_many_datakey_need_kms_decrypt); + INSTALL_TEST(_test_rewrap_many_datakey_need_kms_retry); INSTALL_TEST(_test_rewrap_many_datakey_need_kms_encrypt); INSTALL_TEST(_test_rewrap_many_datakey_finalize); INSTALL_TEST(_test_rewrap_many_datakey_kms_credentials); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c index 3265c3a..8be2898 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c @@ -399,6 +399,165 @@ static void _test_datakey_custom_key_material(_mongocrypt_tester_t *tester) { mongocrypt_destroy(crypt); } +static void _test_create_datakey_with_retry(_mongocrypt_tester_t *tester) { + // Test that an HTTP error is retried. + { + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK( + mongocrypt_ctx_setopt_key_encryption_key(ctx, + TEST_BSON("{'provider': 'aws', 'key': 'foo', 'region': 'bar'}")), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Expect no sleep is requested before any error. + ASSERT_CMPINT64(mongocrypt_kms_ctx_usleep(kms_ctx), ==, 0); + // Feed a retryable HTTP error. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kms_ctx); + // Expect KMS request is returned again for a retry. + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Feed a successful response. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-aws/encrypt-response.txt")), kms_ctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_DONE); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test that a network error is retried. + { + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK( + mongocrypt_ctx_setopt_key_encryption_key(ctx, + TEST_BSON("{'provider': 'aws', 'key': 'foo', 'region': 'bar'}")), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Expect no sleep is requested before any error. + ASSERT_CMPINT64(mongocrypt_kms_ctx_usleep(kms_ctx), ==, 0); + // Mark a network error. + ASSERT_OK(mongocrypt_kms_ctx_fail(kms_ctx), kms_ctx); + // Expect KMS request is returned again for a retry. + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Feed a successful response. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-aws/encrypt-response.txt")), kms_ctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_DONE); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test that an oauth request is retried for a network error. + { + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key( + ctx, + TEST_BSON("{'provider': 'azure', 'keyVaultEndpoint': 'example.com', 'keyName': 'foo' }")), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Expect an oauth request. + { + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kms_ctx, bin), kms_ctx); + const char *str = (const char *)mongocrypt_binary_data(bin); + ASSERT_STRCONTAINS(str, "oauth2"); + mongocrypt_binary_destroy(bin); + } + // Expect no sleep is requested before any error. + ASSERT_CMPINT64(mongocrypt_kms_ctx_usleep(kms_ctx), ==, 0); + // Mark a network error. + ASSERT_OK(mongocrypt_kms_ctx_fail(kms_ctx), kms_ctx); + // Expect KMS request is returned again for a retry. + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Expect an oauth request. + { + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kms_ctx, bin), kms_ctx); + const char *str = (const char *)mongocrypt_binary_data(bin); + ASSERT_STRCONTAINS(str, "oauth2"); + mongocrypt_binary_destroy(bin); + } + // Feed a successful response. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kms_ctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + + // Expect KMS request for encrypt. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Feed a successful response. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-azure/encrypt-response.txt")), kms_ctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_DONE); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test that an oauth request is retried for an HTTP error. + { + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key( + ctx, + TEST_BSON("{'provider': 'azure', 'keyVaultEndpoint': 'example.com', 'keyName': 'foo' }")), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Expect an oauth request. + { + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kms_ctx, bin), kms_ctx); + const char *str = (const char *)mongocrypt_binary_data(bin); + ASSERT_STRCONTAINS(str, "oauth2"); + mongocrypt_binary_destroy(bin); + } + // Expect no sleep is requested before any error. + ASSERT_CMPINT64(mongocrypt_kms_ctx_usleep(kms_ctx), ==, 0); + // Feed a retryable HTTP error. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/rmd/kms-decrypt-reply-429.txt")), kms_ctx); + // Expect KMS request is returned again for a retry. + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Expect an oauth request. + { + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kms_ctx, bin), kms_ctx); + const char *str = (const char *)mongocrypt_binary_data(bin); + ASSERT_STRCONTAINS(str, "oauth2"); + mongocrypt_binary_destroy(bin); + }; + + // Feed a successful response. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kms_ctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + + // Expect KMS request for encrypt. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT_OK(kms_ctx, ctx); + // Feed a successful response. + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-azure/encrypt-response.txt")), kms_ctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_DONE); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } +} + static void _test_create_data_key(_mongocrypt_tester_t *tester) { _test_create_data_key_with_provider(tester, MONGOCRYPT_KMS_PROVIDER_AWS, false /* with_alt_name */); _test_create_data_key_with_provider(tester, MONGOCRYPT_KMS_PROVIDER_LOCAL, false /* with_alt_name */); @@ -414,4 +573,5 @@ void _mongocrypt_tester_install_data_key(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_datakey_kms_per_ctx_credentials); INSTALL_TEST(_test_datakey_kms_per_ctx_credentials_not_requested); INSTALL_TEST(_test_datakey_kms_per_ctx_credentials_local); + INSTALL_TEST(_test_create_datakey_with_retry); } diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kek.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kek.c index 36e28aa..8c827a9 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kek.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kek.c @@ -45,7 +45,7 @@ static void _run_one_test(_mongocrypt_tester_t *tester, bson_t *test) { expect_append = expect; } - input_str = bson_as_json(&input, NULL); + input_str = bson_as_relaxed_extended_json(&input, NULL); printf("- testcase: %s\n", input_str); bson_free(input_str); @@ -98,4 +98,4 @@ void test_mongocrypt_kek_parsing(_mongocrypt_tester_t *tester) { void _mongocrypt_tester_install_kek(_mongocrypt_tester_t *tester) { INSTALL_TEST(test_mongocrypt_kek_parsing); -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-key-cache.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-key-cache.c index f9c8325..668ab4e 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-key-cache.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-key-cache.c @@ -268,7 +268,7 @@ static void _match_cache_entry(_mongocrypt_tester_t *tester, mongocrypt_ctx_t *c while (pair) { if (_match_one_cache_entry(pair, expected_entry)) { if (matched) { - printf("double matched entry: %s\n", bson_as_json(expected_entry, NULL)); + printf("double matched entry: %s\n", bson_as_relaxed_extended_json(expected_entry, NULL)); BSON_ASSERT(false); } matched = true; @@ -278,7 +278,7 @@ static void _match_cache_entry(_mongocrypt_tester_t *tester, mongocrypt_ctx_t *c } if (!matched) { - printf("could not match entry: %s\n", bson_as_json(expected_entry, NULL)); + printf("could not match entry: %s\n", bson_as_relaxed_extended_json(expected_entry, NULL)); BSON_ASSERT(false); } } @@ -419,4 +419,4 @@ static void _test_key_cache(_mongocrypt_tester_t *tester) { void _mongocrypt_tester_install_key_cache(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_key_cache); -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-responses.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-responses.c index 84996ac..377c8f4 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-responses.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-responses.c @@ -142,13 +142,14 @@ static void _test_one_kms_response(_mongocrypt_tester_t *tester, bson_t *test) { BSON_ASSERT(bson_iter_init_find(&iter, test, "expect")); if (BSON_ITER_HOLDS_ARRAY(&iter)) { // Concatenate array into one string. - bson_string_t *builder = bson_string_new(NULL); + expect = bson_strdup(""); bson_iter_recurse(&iter, &iter); while (bson_iter_next(&iter)) { ASSERT(BSON_ITER_HOLDS_UTF8(&iter)); - bson_string_append(builder, bson_iter_utf8(&iter, NULL)); + char *previous = expect; + expect = bson_strdup_printf("%s%s", expect, bson_iter_utf8(&iter, NULL)); + bson_free(previous); } - expect = bson_string_free(builder, false /* free segment */); } else { expect = bson_strdup(bson_iter_utf8(&iter, NULL)); } diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c index 28ec047..0ffaec7 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c @@ -173,12 +173,14 @@ static void test_mongocrypt_marking_parse(_mongocrypt_tester_t *tester) { #define ASSERT_MINCOVER_EQ(got, expectString) \ if (1) { \ - bson_string_t *gotStr = bson_string_new(""); \ + char *gotStr = bson_strdup(""); \ for (size_t i = 0; i < mc_mincover_len(got); i++) { \ - bson_string_append_printf(gotStr, "%s\n", mc_mincover_get(got, i)); \ + char *previous = gotStr; \ + gotStr = bson_strdup_printf("%s%s\n", gotStr, mc_mincover_get(got, i)); \ + bson_free(previous); \ } \ - ASSERT_STREQUAL(gotStr->str, expectString); \ - bson_string_free(gotStr, true); \ + ASSERT_STREQUAL(gotStr, expectString); \ + bson_free(gotStr); \ } else \ ((void)0) diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c index 7c6cde3..7100bf8 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c @@ -62,6 +62,24 @@ void _load_json_as_bson(const char *path, bson_t *out) { bson_json_reader_destroy(reader); } +void _usleep(int64_t usec) { +#ifdef _WIN32 + LARGE_INTEGER ft; + HANDLE timer; + + BSON_ASSERT(usec >= 0); + + ft.QuadPart = -(10 * usec); + timer = CreateWaitableTimer(NULL, true, NULL); + SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); +#else + BSON_ASSERT(usec >= 0); + usleep((useconds_t)usec); +#endif +} + #define TEST_DATA_COUNT_INC(var) \ (var)++; \ if ((var) >= TEST_DATA_COUNT) { \ @@ -461,6 +479,7 @@ mongocrypt_t *_mongocrypt_tester_mongocrypt(tester_mongocrypt_flags flags) { crypt = mongocrypt_new(); mongocrypt_setopt_log_handler(crypt, _mongocrypt_stdout_log_fn, NULL); mongocrypt_setopt_kms_provider_aws(crypt, "example", -1, "example", -1); + mongocrypt_setopt_retry_kms(crypt, true); localkey = mongocrypt_binary_new_from_data((uint8_t *)localkey_data, sizeof localkey_data); mongocrypt_setopt_kms_provider_local(crypt, localkey); mongocrypt_binary_destroy(localkey); @@ -500,6 +519,9 @@ mongocrypt_t *_mongocrypt_tester_mongocrypt(tester_mongocrypt_flags flags) { } else { crypt->opts.use_range_v2 = false; } + if (flags & TESTER_MONGOCRYPT_WITH_SHORT_CACHE) { + ASSERT(mongocrypt_setopt_key_expiration(crypt, 1)); + } ASSERT_OK(mongocrypt_init(crypt), crypt); if (flags & TESTER_MONGOCRYPT_WITH_CRYPT_SHARED_LIB) { if (mongocrypt_crypt_shared_lib_version(crypt) == 0) { @@ -892,6 +914,7 @@ int main(int argc, char **argv) { _mongocrypt_tester_install_fle2_payload_iup_v2(&tester); _mongocrypt_tester_install_fle2_payload_find_equality_v2(&tester); _mongocrypt_tester_install_fle2_payload_find_range_v2(&tester); + _mongocrypt_tester_install_fle2_tag_and_encrypted_metadata_block(&tester); _mongocrypt_tester_install_range_encoding(&tester); _mongocrypt_tester_install_range_edge_generation(&tester); _mongocrypt_tester_install_range_mincover(&tester); @@ -902,6 +925,7 @@ int main(int argc, char **argv) { _mongocrypt_tester_install_mc_writer(&tester); _mongocrypt_tester_install_opts(&tester); _mongocrypt_tester_install_named_kms_providers(&tester); + _mongocrypt_tester_install_mc_cmp(&tester); #ifdef MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO char osversion[32]; diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h index b4950ca..dfbc041 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h @@ -44,6 +44,8 @@ typedef enum tester_mongocrypt_flags { TESTER_MONGOCRYPT_WITH_CRYPT_V1 = 1 << 1, /// Enable range V2 TESTER_MONGOCRYPT_WITH_RANGE_V2 = 1 << 2, + /// Short cache expiration + TESTER_MONGOCRYPT_WITH_SHORT_CACHE = 1 << 3, } tester_mongocrypt_flags; /* Arbitrary max of 2048 instances of temporary test data. Increase as needed. @@ -79,6 +81,10 @@ typedef struct __mongocrypt_tester_t { _mongocrypt_buffer_t encrypted_doc; } _mongocrypt_tester_t; +// `_mongocrypt_tester_t` inherits extended alignment from libbson. To dynamically allocate, use aligned allocation +// (e.g. BSON_ALIGNED_ALLOC) +BSON_STATIC_ASSERT2(alignof__mongocrypt_tester_t, BSON_ALIGNOF(_mongocrypt_tester_t) >= BSON_ALIGNOF(bson_t)); + /* Load a .json file as bson */ void _load_json_as_bson(const char *path, bson_t *out); @@ -186,6 +192,8 @@ void _mongocrypt_tester_install_fle2_payload_find_equality_v2(_mongocrypt_tester void _mongocrypt_tester_install_fle2_payload_find_range_v2(_mongocrypt_tester_t *tester); +void _mongocrypt_tester_install_fle2_tag_and_encrypted_metadata_block(_mongocrypt_tester_t *tester); + void _mongocrypt_tester_install_gcp_auth(_mongocrypt_tester_t *tester); void _mongocrypt_tester_install_range_encoding(_mongocrypt_tester_t *tester); @@ -206,6 +214,8 @@ void _mongocrypt_tester_install_opts(_mongocrypt_tester_t *tester); void _mongocrypt_tester_install_named_kms_providers(_mongocrypt_tester_t *tester); +void _mongocrypt_tester_install_mc_cmp(_mongocrypt_tester_t *tester); + /* Conveniences for getting test data. */ /* Get a temporary bson_t from a JSON string. Do not free it. */ @@ -237,4 +247,6 @@ void _test_ctx_wrap_and_feed_key(mongocrypt_ctx_t *ctx, _mongocrypt_buffer_t *key, mongocrypt_status_t *status); +void _usleep(int64_t usec); + #endif diff --git a/lib/libmongocrypt_helper/version.rb b/lib/libmongocrypt_helper/version.rb index 5b6aada..bf393eb 100644 --- a/lib/libmongocrypt_helper/version.rb +++ b/lib/libmongocrypt_helper/version.rb @@ -1,5 +1,5 @@ module LibmongocryptHelper - VERSION = '1.11.0.0.1001' + VERSION = '1.12.0.0.1001' - LIBMONGOCRYPT_VERSION = '1.11.0' + LIBMONGOCRYPT_VERSION = '1.12.0' end diff --git a/sbom.json b/sbom.json index 21c7c9f..55be705 100644 --- a/sbom.json +++ b/sbom.json @@ -1,31 +1,31 @@ { "components": [ { - "bom-ref": "pkg:github/mongodb/libmongocrypt@1.11.0", + "bom-ref": "pkg:github/mongodb/libmongocrypt@1.12.0", "externalReferences": [ { "type": "distribution", - "url": "https://github.com/mongodb/libmongocrypt/archive/refs/tags/1.11.0.tar.gz" + "url": "https://github.com/mongodb/libmongocrypt/archive/refs/tags/1.12.0.tar.gz" }, { "type": "website", - "url": "https://github.com/mongodb/libmongocrypt/tree/1.11.0" + "url": "https://github.com/mongodb/libmongocrypt/tree/1.12.0" } ], "group": "mongodb", "name": "libmongocrypt", - "purl": "pkg:github/mongodb/libmongocrypt@1.11.0", + "purl": "pkg:github/mongodb/libmongocrypt@1.12.0", "type": "library", - "version": "1.11.0" + "version": "1.12.0" } ], "dependencies": [ { - "ref": "pkg:github/mongodb/libmongocrypt@1.11.0" + "ref": "pkg:github/mongodb/libmongocrypt@1.12.0" } ], "metadata": { - "timestamp": "2024-08-20T08:21:41.909456+00:00", + "timestamp": "2024-11-11T20:58:27.952151+00:00", "tools": [ { "externalReferences": [ @@ -69,7 +69,7 @@ ] }, "serialNumber": "urn:uuid:67ce9be7-c1c0-436f-a7d7-c636db7b882b", - "version": 2, + "version": 3, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.5",