From bb12cda6504fecbf7a8ffc97d0cadc9cafbd1a29 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Wed, 31 Jul 2024 12:57:32 -0400 Subject: [PATCH] MONGOCRYPT-705 Add crypto parameters to payloads (#872) * apply crypto params to `mc_FLE2InsertUpdatePayloadV2_t` Add new fields. Note fields that only applicable to range payloads * change `_assert_match_bson` to a macro To include the line number of the macro invocation on error. And remove unnecessary NULL check. * apply crypto params to `mc_FLE2FindRangePayloadV2_t` Fix documentation for `FLE2FindRangePayloadV2`. `g` is nested inside a `payload` document. See server IDL for reference. * read random numbers as little-endian To fix new tests on zSeries. May simplify testing with deterministic random-number generation on big-endian machines. * update payloads in existing tests Payloads now include crypto param fields. * update payloads in Python and Java tests Notably: java bindings test with `trimFactor` of 0. Python tests with `trimFactor` of 1. * represent `trimFactor` as an `int32_t` To match server representation * include value of trimFactor in error message, error if negative * represent `precision` as an `int32_t` To match server representation --- .../int32/encrypted-payload.json | 2 +- .../int32/encrypted-payload.json | 2 +- src/mc-fle2-encryption-placeholder-private.h | 8 +- src/mc-fle2-encryption-placeholder.c | 8 +- src/mc-fle2-find-range-payload-private-v2.h | 21 +- src/mc-fle2-find-range-payload-v2.c | 38 ++- ...mc-fle2-insert-update-payload-private-v2.h | 17 +- src/mc-fle2-insert-update-payload-v2.c | 90 ++++++- src/mc-fle2-rfds-private.h | 4 +- src/mc-fle2-rfds.c | 6 +- src/mc-range-edge-generation-private.h | 15 +- src/mc-range-edge-generation.c | 26 +- src/mc-range-encoding-private.h | 10 +- src/mc-range-encoding.c | 34 +-- src/mc-range-mincover-generator.template.h | 27 +- src/mc-range-mincover-private.h | 15 +- src/mc-range-mincover.c | 9 + src/mc-rangeopts-private.h | 8 +- src/mc-rangeopts.c | 13 +- src/mongocrypt-crypto.c | 2 + src/mongocrypt-marking.c | 23 +- .../no-trimFactor/find/encrypted-payload.json | 2 +- .../insert/encrypted-payload.json | 2 +- .../auto-find-int32/cmd.json | 8 + .../auto-find-int32/encrypted-field-map.json | 19 ++ .../auto-find-int32/encrypted-payload.json | 53 ++++ .../auto-find-int32/mongocryptd-reply.json | 58 ++++ .../auto-insert-int32/cmd.json | 11 + .../encrypted-field-map.json | 19 ++ .../auto-insert-int32/encrypted-payload.json | 40 +++ .../auto-insert-int32/mongocryptd-reply.json | 45 ++++ .../expected.json | 26 ++ .../to-encrypt.json | 20 ++ .../explicit-find-int32/expected.json | 26 ++ .../explicit-find-int32/to-encrypt.json | 20 ++ .../explicit-insert-double/expected.json | 8 + .../expected.json | 8 + .../explicit-insert-int32/expected.json | 8 + test/test-mc-fle2-find-range-payload-v2.c | 44 ++- test/test-mc-fle2-payload-iup-v2.c | 76 ++++++ test/test-mc-range-edge-generation.c | 16 +- test/test-mc-range-encoding.c | 108 ++++---- test/test-mc-range-mincover.c | 12 +- test/test-mc-rangeopts.c | 4 +- test/test-mongocrypt-assert-match-bson.c | 24 +- test/test-mongocrypt-assert-match-bson.h | 23 +- test/test-mongocrypt-ctx-encrypt.c | 255 ++++++++++++++++-- test/test-mongocrypt-marking.c | 11 + 48 files changed, 1137 insertions(+), 187 deletions(-) create mode 100644 test/data/range-sends-cryptoParams/auto-find-int32/cmd.json create mode 100644 test/data/range-sends-cryptoParams/auto-find-int32/encrypted-field-map.json create mode 100644 test/data/range-sends-cryptoParams/auto-find-int32/encrypted-payload.json create mode 100644 test/data/range-sends-cryptoParams/auto-find-int32/mongocryptd-reply.json create mode 100644 test/data/range-sends-cryptoParams/auto-insert-int32/cmd.json create mode 100644 test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-field-map.json create mode 100644 test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-payload.json create mode 100644 test/data/range-sends-cryptoParams/auto-insert-int32/mongocryptd-reply.json create mode 100644 test/data/range-sends-cryptoParams/explicit-find-int32-defaults/expected.json create mode 100644 test/data/range-sends-cryptoParams/explicit-find-int32-defaults/to-encrypt.json create mode 100644 test/data/range-sends-cryptoParams/explicit-find-int32/expected.json create mode 100644 test/data/range-sends-cryptoParams/explicit-find-int32/to-encrypt.json create mode 100644 test/data/range-sends-cryptoParams/explicit-insert-double/expected.json create mode 100644 test/data/range-sends-cryptoParams/explicit-insert-int32-defaults/expected.json create mode 100644 test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json diff --git a/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/encrypted-payload.json b/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/encrypted-payload.json index 796f336a0..7db5540ca 100644 --- a/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/encrypted-payload.json +++ b/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/encrypted-payload.json @@ -5,7 +5,7 @@ "age": { "$gte": { "$binary": { - "base64": "Dd0BAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAAA==", + "base64": "DQECAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAEnNwAAEAAAAAAAAAEHRmAAEAAAAQbW4AAAAAABBteADIAAAAAA==", "subType": "06" } } diff --git a/bindings/python/test/data/fle2-find-range-explicit-v2/int32/encrypted-payload.json b/bindings/python/test/data/fle2-find-range-explicit-v2/int32/encrypted-payload.json index 796f336a0..3c8ab7b64 100644 --- a/bindings/python/test/data/fle2-find-range-explicit-v2/int32/encrypted-payload.json +++ b/bindings/python/test/data/fle2-find-range-explicit-v2/int32/encrypted-payload.json @@ -5,7 +5,7 @@ "age": { "$gte": { "$binary": { - "base64": "Dd0BAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAAA==", + "base64": "DQECAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAEnNwAAEAAAAAAAAAEHRmAAAAAAAQbW4AAAAAABBteADIAAAAAA==", "subType": "06" } } diff --git a/src/mc-fle2-encryption-placeholder-private.h b/src/mc-fle2-encryption-placeholder-private.h index 2177bb2e4..3e26ec671 100644 --- a/src/mc-fle2-encryption-placeholder-private.h +++ b/src/mc-fle2-encryption-placeholder-private.h @@ -49,9 +49,9 @@ typedef struct { bson_iter_t indexMax; // precision determines the number of digits after the decimal point for // floating point values. - mc_optional_uint32_t precision; + mc_optional_int32_t precision; // trimFactor determines how many root levels of the hypergraph to trim. - mc_optional_uint32_t trimFactor; + mc_optional_int32_t trimFactor; } mc_FLE2RangeFindSpecEdgesInfo_t; /** FLE2RangeFindSpec represents the range find specification that is encoded @@ -94,9 +94,9 @@ typedef struct { bson_iter_t max; // precision determines the number of digits after the decimal point for // floating point values. - mc_optional_uint32_t precision; + mc_optional_int32_t precision; // trimFactor determines how many root levels of the hypergraph to trim. - mc_optional_uint32_t trimFactor; + mc_optional_int32_t trimFactor; } mc_FLE2RangeInsertSpec_t; bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, diff --git a/src/mc-fle2-encryption-placeholder.c b/src/mc-fle2-encryption-placeholder.c index fc0dd7fee..fc839b887 100644 --- a/src/mc-fle2-encryption-placeholder.c +++ b/src/mc-fle2-encryption-placeholder.c @@ -279,7 +279,7 @@ static bool mc_FLE2RangeFindSpecEdgesInfo_parse(mc_FLE2RangeFindSpecEdgesInfo_t goto fail; } - out->precision = OPT_U32((uint32_t)val); + out->precision = OPT_I32(val); } END_IF_FIELD @@ -294,7 +294,7 @@ static bool mc_FLE2RangeFindSpecEdgesInfo_parse(mc_FLE2RangeFindSpecEdgesInfo_t goto fail; } - out->trimFactor = OPT_U32((uint32_t)val); + out->trimFactor = OPT_I32(val); } END_IF_FIELD } @@ -454,7 +454,7 @@ bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, CLIENT_ERR_PREFIXED("'precision' must be non-negative"); goto fail; } - out->precision = OPT_U32((uint32_t)val); + out->precision = OPT_I32(val); } END_IF_FIELD @@ -468,7 +468,7 @@ bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, CLIENT_ERR_PREFIXED("'trimFactor' must be non-negative"); goto fail; } - out->trimFactor = OPT_U32((uint32_t)val); + out->trimFactor = OPT_I32(val); } END_IF_FIELD } diff --git a/src/mc-fle2-find-range-payload-private-v2.h b/src/mc-fle2-find-range-payload-private-v2.h index d64c7eec6..c5ed2261a 100644 --- a/src/mc-fle2-find-range-payload-private-v2.h +++ b/src/mc-fle2-find-range-payload-private-v2.h @@ -23,6 +23,7 @@ #include "mc-array-private.h" #include "mc-fle2-range-operator-private.h" +#include "mc-optional-private.h" /** FLE2FindRangePayloadEdgesInfoV2 represents the token information for a range * find query. It is encoded inside an FLE2FindRangePayloadV2. @@ -44,8 +45,17 @@ typedef struct { * } FLE2FindRangePayloadV2; * * bson is a BSON document of this form: - * g: array // Array of Edges - * cm: // Queryable Encryption max counter + * payload: + * g: array // Array of Edges + * cm: // Queryable Encryption max counter + * payloadId: // Payload ID. + * firstOperator: + * secondOperator: + * sp: optional // Sparsity. + * pn: optional // Precision. + * tf: optional // Trim Factor. + * mn: optional // Index Min. + * mx: optional // Index Max. */ typedef struct { struct { @@ -61,6 +71,11 @@ typedef struct { // secondOperator represents the second query operator for which this payload // was generated. Only populated for two-sided ranges. It is 0 if unset. mc_FLE2RangeOperator_t secondOperator; + mc_optional_int64_t sparsity; // sp + mc_optional_int32_t precision; // pn + mc_optional_int32_t trimFactor; // tf + bson_value_t indexMin; // mn + bson_value_t indexMax; // mx } mc_FLE2FindRangePayloadV2_t; /** @@ -81,7 +96,7 @@ typedef struct { void mc_FLE2FindRangePayloadV2_init(mc_FLE2FindRangePayloadV2_t *payload); -bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payload, bson_t *out); +bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payload, bson_t *out, bool use_range_v2); void mc_FLE2FindRangePayloadV2_cleanup(mc_FLE2FindRangePayloadV2_t *payload); diff --git a/src/mc-fle2-find-range-payload-v2.c b/src/mc-fle2-find-range-payload-v2.c index be27e033f..e07cd7678 100644 --- a/src/mc-fle2-find-range-payload-v2.c +++ b/src/mc-fle2-find-range-payload-v2.c @@ -53,7 +53,7 @@ void mc_FLE2FindRangePayloadV2_cleanup(mc_FLE2FindRangePayloadV2_t *payload) { return false; \ } -bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payload, bson_t *out) { +bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payload, bson_t *out, bool use_range_v2) { BSON_ASSERT_PARAM(out); BSON_ASSERT_PARAM(payload); @@ -131,6 +131,42 @@ bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payl return false; } + if (use_range_v2) { + // Encode parameters that were used to generate the mincover. + // The crypto parameters are all optionally set. Find payloads may come in pairs (a lower and upper bound). + // One of the pair includes the mincover. The other payload was not generated with crypto parameters. + + if (payload->sparsity.set) { + if (!BSON_APPEND_INT64(out, "sp", payload->sparsity.value)) { + return false; + } + } + + if (payload->precision.set) { + if (!BSON_APPEND_INT32(out, "pn", payload->precision.value)) { + return false; + } + } + + if (payload->trimFactor.set) { + if (!BSON_APPEND_INT32(out, "tf", payload->trimFactor.value)) { + return false; + } + } + + if (payload->indexMin.value_type != BSON_TYPE_EOD) { + if (!BSON_APPEND_VALUE(out, "mn", &payload->indexMin)) { + return false; + } + } + + if (payload->indexMax.value_type != BSON_TYPE_EOD) { + if (!BSON_APPEND_VALUE(out, "mx", &payload->indexMax)) { + return false; + } + } + } + return true; } diff --git a/src/mc-fle2-insert-update-payload-private-v2.h b/src/mc-fle2-insert-update-payload-private-v2.h index 3f1f9fe71..2ed4b32d6 100644 --- a/src/mc-fle2-insert-update-payload-private-v2.h +++ b/src/mc-fle2-insert-update-payload-private-v2.h @@ -20,6 +20,7 @@ #include #include "mc-array-private.h" +#include "mc-optional-private.h" #include "mongocrypt-buffer-private.h" #include "mongocrypt-private.h" #include "mongocrypt.h" @@ -45,7 +46,12 @@ * e: // ServerDataEncryptionLevel1Token * l: // ServerDerivedFromDataToken * k: // Randomly sampled contention factor value - * g: array // Array of Edges + * g: array // Array of Edges. Only included for range payloads. + * sp: optional // Sparsity. Only included for range payloads. + * pn: optional // Precision. Only included for range payloads. + * tf: optional // Trim Factor. Only included for range payloads. + * mn: optional // Index Min. Only included for range payloads. + * mx: optional // Index Max. Only included for range payloads. * * p is the result of: * Encrypt( @@ -72,6 +78,11 @@ typedef struct { _mongocrypt_buffer_t serverDerivedFromDataToken; // l int64_t contentionFactor; // k mc_array_t edgeTokenSetArray; // g + mc_optional_int64_t sparsity; // sp + mc_optional_int32_t precision; // pn + mc_optional_int32_t trimFactor; // tf + bson_value_t indexMin; // mn + bson_value_t indexMax; // mx _mongocrypt_buffer_t plaintext; _mongocrypt_buffer_t userKeyId; } mc_FLE2InsertUpdatePayloadV2_t; @@ -110,7 +121,9 @@ const _mongocrypt_buffer_t *mc_FLE2InsertUpdatePayloadV2_decrypt(_mongocrypt_cry bool mc_FLE2InsertUpdatePayloadV2_serialize(const mc_FLE2InsertUpdatePayloadV2_t *payload, bson_t *out); -bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePayloadV2_t *payload, bson_t *out); +bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePayloadV2_t *payload, + bson_t *out, + bool use_range_v2); void mc_FLE2InsertUpdatePayloadV2_cleanup(mc_FLE2InsertUpdatePayloadV2_t *payload); diff --git a/src/mc-fle2-insert-update-payload-v2.c b/src/mc-fle2-insert-update-payload-v2.c index f4e9bf309..b86e41239 100644 --- a/src/mc-fle2-insert-update-payload-v2.c +++ b/src/mc-fle2-insert-update-payload-v2.c @@ -18,6 +18,7 @@ #include "mc-fle2-insert-update-payload-private-v2.h" #include "mongocrypt-buffer-private.h" +#include "mongocrypt-util-private.h" // mc_bson_type_to_string #include "mongocrypt.h" void mc_FLE2InsertUpdatePayloadV2_init(mc_FLE2InsertUpdatePayloadV2_t *payload) { @@ -53,6 +54,8 @@ void mc_FLE2InsertUpdatePayloadV2_cleanup(mc_FLE2InsertUpdatePayloadV2_t *payloa mc_EdgeTokenSetV2_cleanup(&entry); } _mc_array_destroy(&payload->edgeTokenSetArray); + bson_value_destroy(&payload->indexMin); + bson_value_destroy(&payload->indexMax); } #define IF_FIELD(Name) \ @@ -104,6 +107,7 @@ bool mc_FLE2InsertUpdatePayloadV2_parse(mc_FLE2InsertUpdatePayloadV2_t *out, bool has_d = false, has_s = false, has_p = false; bool has_u = false, has_t = false, has_v = false; bool has_e = false, has_l = false, has_k = false; + bool has_sp = false, has_pn = false, has_tf = false, has_mn = false, has_mx = false; bson_t in_bson; BSON_ASSERT_PARAM(out); @@ -163,6 +167,57 @@ bool mc_FLE2InsertUpdatePayloadV2_parse(mc_FLE2InsertUpdatePayloadV2_t *out, PARSE_BINARY(v, value) PARSE_BINARY(e, serverEncryptionToken) PARSE_BINARY(l, serverDerivedFromDataToken) + + IF_FIELD(sp) { + if (!BSON_ITER_HOLDS_INT64(&iter)) { + CLIENT_ERR("Field 'sp' expected to hold an int64, got: %s", + mc_bson_type_to_string(bson_iter_type(&iter))); + goto fail; + } + int64_t sparsity = bson_iter_int64(&iter); + out->sparsity = OPT_I64(sparsity); + } + END_IF_FIELD + + IF_FIELD(pn) { + if (!BSON_ITER_HOLDS_INT32(&iter)) { + CLIENT_ERR("Field 'pn' expected to hold an int32, got: %s", + mc_bson_type_to_string(bson_iter_type(&iter))); + goto fail; + } + int32_t precision = bson_iter_int32(&iter); + if (precision < 0) { + CLIENT_ERR("Field 'pn' must be non-negative, got: %" PRId32, precision); + goto fail; + } + out->precision = OPT_I32(precision); + } + END_IF_FIELD + + IF_FIELD(tf) { + if (!BSON_ITER_HOLDS_INT32(&iter)) { + CLIENT_ERR("Field 'tf' expected to hold an int32, got: %s", + mc_bson_type_to_string(bson_iter_type(&iter))); + goto fail; + } + int32_t trimFactor = bson_iter_int32(&iter); + if (trimFactor < 0) { + CLIENT_ERR("Field 'tf' must be non-negative, got: %" PRId32, trimFactor); + goto fail; + } + out->trimFactor = OPT_I32(trimFactor); + } + END_IF_FIELD + + IF_FIELD(mn) { + bson_value_copy(bson_iter_value(&iter), &out->indexMin); + } + END_IF_FIELD + + IF_FIELD(mx) { + bson_value_copy(bson_iter_value(&iter), &out->indexMax); + } + END_IF_FIELD } CHECK_HAS(d); @@ -174,6 +229,7 @@ bool mc_FLE2InsertUpdatePayloadV2_parse(mc_FLE2InsertUpdatePayloadV2_t *out, CHECK_HAS(e); CHECK_HAS(l); CHECK_HAS(k); + // The fields `sp`, `pn`, `tf`, `mn`, and `mx` are only set for "range" payloads. if (!_mongocrypt_buffer_from_subrange(&out->userKeyId, &out->value, 0, UUID_LEN)) { CLIENT_ERR("failed to create userKeyId buffer"); @@ -213,7 +269,9 @@ bool mc_FLE2InsertUpdatePayloadV2_serialize(const mc_FLE2InsertUpdatePayloadV2_t return true; } -bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePayloadV2_t *payload, bson_t *out) { +bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePayloadV2_t *payload, + bson_t *out, + bool use_range_v2) { BSON_ASSERT_PARAM(out); BSON_ASSERT_PARAM(payload); @@ -257,6 +315,36 @@ bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePay return false; } + if (use_range_v2) { + // Encode parameters that were used to generate the payload. + BSON_ASSERT(payload->sparsity.set); + if (!BSON_APPEND_INT64(out, "sp", payload->sparsity.value)) { + return false; + } + + // Precision may be unset. + if (payload->precision.set) { + if (!BSON_APPEND_INT32(out, "pn", payload->precision.value)) { + return false; + } + } + + BSON_ASSERT(payload->trimFactor.set); + if (!BSON_APPEND_INT32(out, "tf", payload->trimFactor.value)) { + return false; + } + + BSON_ASSERT(payload->indexMin.value_type != BSON_TYPE_EOD); + if (!BSON_APPEND_VALUE(out, "mn", &payload->indexMin)) { + return false; + } + + BSON_ASSERT(payload->indexMax.value_type != BSON_TYPE_EOD); + if (!BSON_APPEND_VALUE(out, "mx", &payload->indexMax)) { + return false; + } + } + return true; } diff --git a/src/mc-fle2-rfds-private.h b/src/mc-fle2-rfds-private.h index f0a505940..d89827c27 100644 --- a/src/mc-fle2-rfds-private.h +++ b/src/mc-fle2-rfds-private.h @@ -75,8 +75,8 @@ typedef struct { bson_iter_t indexMax; int64_t maxContentionFactor; int64_t sparsity; - mc_optional_uint32_t precision; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_makeRangeFindPlaceholder_args_t; // mc_makeRangeFindPlaceholder creates a placeholder to be consumed by diff --git a/src/mc-fle2-rfds.c b/src/mc-fle2-rfds.c index 7bf7a7634..0622bfd9d 100644 --- a/src/mc-fle2-rfds.c +++ b/src/mc-fle2-rfds.c @@ -364,12 +364,10 @@ bool mc_makeRangeFindPlaceholder(mc_makeRangeFindPlaceholder_args_t *args, TRY(bson_append_iter(edgesInfo, "indexMin", -1, &args->indexMin)); TRY(bson_append_iter(edgesInfo, "indexMax", -1, &args->indexMax)); if (args->precision.set) { - BSON_ASSERT(args->precision.value <= INT32_MAX); - TRY(BSON_APPEND_INT32(edgesInfo, "precision", (int32_t)args->precision.value)); + TRY(BSON_APPEND_INT32(edgesInfo, "precision", args->precision.value)); } if (args->trimFactor.set) { - BSON_ASSERT(args->trimFactor.value <= INT32_MAX); - TRY(BSON_APPEND_INT32(edgesInfo, "trimFactor", (int32_t)args->trimFactor.value)); + TRY(BSON_APPEND_INT32(edgesInfo, "trimFactor", args->trimFactor.value)); } TRY(BSON_APPEND_DOCUMENT(v, "edgesInfo", edgesInfo)); } diff --git a/src/mc-range-edge-generation-private.h b/src/mc-range-edge-generation-private.h index 454bdda92..268eef335 100644 --- a/src/mc-range-edge-generation-private.h +++ b/src/mc-range-edge-generation-private.h @@ -40,12 +40,15 @@ void mc_edges_destroy(mc_edges_t *edges); // mc_edges_is_leaf returns whether the given edge is the leaf node of the edge set. bool mc_edges_is_leaf(const mc_edges_t *edges, const char *edge); +// Return the trimFactor that was used to generate these edges. +int32_t mc_edges_get_used_trimFactor(const mc_edges_t *edges); + typedef struct { int32_t value; mc_optional_int32_t min; mc_optional_int32_t max; size_t sparsity; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t trimFactor; } mc_getEdgesInt32_args_t; // mc_getEdgesInt32 implements the Edge Generation algorithm described in @@ -57,7 +60,7 @@ typedef struct { mc_optional_int64_t min; mc_optional_int64_t max; size_t sparsity; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t trimFactor; } mc_getEdgesInt64_args_t; // mc_getEdgesInt64 implements the Edge Generation algorithm described in @@ -69,8 +72,8 @@ typedef struct { size_t sparsity; mc_optional_double_t min; mc_optional_double_t max; - mc_optional_uint32_t precision; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_getEdgesDouble_args_t; // mc_getEdgesDouble implements the Edge Generation algorithm described in @@ -82,8 +85,8 @@ typedef struct { mc_dec128 value; size_t sparsity; mc_optional_dec128_t min, max; - mc_optional_uint32_t precision; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_getEdgesDecimal128_args_t; mc_edges_t *mc_getEdgesDecimal128(mc_getEdgesDecimal128_args_t args, mongocrypt_status_t *status, bool use_range_v2); diff --git a/src/mc-range-edge-generation.c b/src/mc-range-edge-generation.c index c16fe6982..10b266a1a 100644 --- a/src/mc-range-edge-generation.c +++ b/src/mc-range-edge-generation.c @@ -27,11 +27,16 @@ struct _mc_edges_t { /* edges is an array of `char*` edge strings. */ mc_array_t edges; char *leaf; + int32_t usedTrimFactor; // The `trimFactor` that was used to produce these edges. }; +int32_t mc_edges_get_used_trimFactor(const mc_edges_t *edges) { + return edges->usedTrimFactor; +} + static mc_edges_t *mc_edges_new(const char *leaf, size_t sparsity, - mc_optional_uint32_t opt_trimFactor, + mc_optional_int32_t opt_trimFactor, mongocrypt_status_t *status, bool use_range_v2) { BSON_ASSERT_PARAM(leaf); @@ -41,16 +46,23 @@ static mc_edges_t *mc_edges_new(const char *leaf, } const size_t leaf_len = strlen(leaf); - const uint32_t trimFactor = trimFactorDefault(leaf_len, opt_trimFactor, use_range_v2); - if (trimFactor != 0 && trimFactor >= leaf_len) { + const int32_t trimFactor = trimFactorDefault(leaf_len, opt_trimFactor, use_range_v2); + if (trimFactor != 0 && bson_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", - leaf_len); + CLIENT_ERR("trimFactor must be less than the number of bits (%ld) used to represent an element of the domain, " + "but got %" PRId32, + leaf_len, + trimFactor); + return NULL; + } + if (trimFactor < 0) { + CLIENT_ERR("trimFactor must be >= 0, but got %" PRId32, trimFactor); return NULL; } mc_edges_t *edges = bson_malloc0(sizeof(mc_edges_t)); + edges->usedTrimFactor = trimFactor; edges->sparsity = sparsity; _mc_array_init(&edges->edges, sizeof(char *)); edges->leaf = bson_strdup(leaf); @@ -64,7 +76,9 @@ 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. - size_t startLevel = trimFactor > 0 ? trimFactor : 1; + BSON_ASSERT(bson_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++) { if (i % sparsity == 0) { char *edge = bson_malloc(i + 1); diff --git a/src/mc-range-encoding-private.h b/src/mc-range-encoding-private.h index 361dd0b75..2250b1fb4 100644 --- a/src/mc-range-encoding-private.h +++ b/src/mc-range-encoding-private.h @@ -83,13 +83,13 @@ typedef struct { double value; mc_optional_double_t min; mc_optional_double_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; } mc_getTypeInfoDouble_args_t; // `mc_canUsePrecisionModeDouble` returns true if the domain can be represented in fewer than 64 bits. bool mc_canUsePrecisionModeDouble(double min, double max, - uint32_t precision, + int32_t precision, uint32_t *maxBitsOut, mongocrypt_status_t *status); @@ -111,13 +111,13 @@ typedef struct { typedef struct { mc_dec128 value; mc_optional_dec128_t min, max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; } mc_getTypeInfoDecimal128_args_t; // `mc_canUsePrecisionModeDecimal` returns true if the domain can be represented in fewer than 128 bits. bool mc_canUsePrecisionModeDecimal(mc_dec128 min, mc_dec128 max, - uint32_t precision, + int32_t precision, uint32_t *maxBitsOut, mongocrypt_status_t *status); @@ -137,5 +137,5 @@ bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args, extern const int64_t mc_FLERangeSparsityDefault; -uint32_t trimFactorDefault(size_t maxlen, mc_optional_uint32_t trimFactor, bool use_range_v2); +int32_t trimFactorDefault(size_t maxlen, mc_optional_int32_t trimFactor, bool use_range_v2); #endif /* MC_RANGE_ENCODING_PRIVATE_H */ diff --git a/src/mc-range-encoding.c b/src/mc-range-encoding.c index b679d8f3a..9c9ea2779 100644 --- a/src/mc-range-encoding.c +++ b/src/mc-range-encoding.c @@ -198,10 +198,11 @@ bool ceil_log2_double(uint64_t i, uint32_t *maxBitsOut, mongocrypt_status_t *sta bool mc_canUsePrecisionModeDouble(double min, double max, - uint32_t precision, + int32_t precision, uint32_t *maxBitsOut, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(maxBitsOut); + BSON_ASSERT(precision >= 0); if (min >= max) { CLIENT_ERR("Invalid bounds for double range precision, min must be less than max. min: %g, max: %g", min, max); @@ -259,7 +260,7 @@ bool mc_canUsePrecisionModeDouble(double min, if (((uint64_t)scaled_prc) > UINT64_MAX - range) { CLIENT_ERR("Invalid value for min, max, and precision. The calculated domain size is too large. min: %g, max: " - "%g, precision: %" PRIu32, + "%g, precision: %" PRId32, min, max, precision); @@ -317,8 +318,8 @@ bool mc_getTypeInfoDouble(mc_getTypeInfoDouble_args_t args, } if (args.precision.set) { - if (args.precision.value > INT32_MAX) { - CLIENT_ERR("Precision cannot be greater than %" PRId32 ", got %" PRIu32, INT32_MAX, args.precision.value); + if (args.precision.value < 0) { + CLIENT_ERR("Precision must be non-negative, but got %" PRId32, args.precision.value); return false; } @@ -354,7 +355,7 @@ bool mc_getTypeInfoDouble(mc_getTypeInfoDouble_args_t args, } CLIENT_ERR("The domain of double values specified by the min, max, and precision cannot be represented in " - "fewer than 53 bits. min: %g, max: %g, precision: %" PRIu32, + "fewer than 53 bits. min: %g, max: %g, precision: %" PRId32, args.min.value, args.max.value, args.precision.value); @@ -498,10 +499,11 @@ bool ceil_log2_int128(mlib_int128 i, uint32_t *maxBitsOut, mongocrypt_status_t * bool mc_canUsePrecisionModeDecimal(mc_dec128 min, mc_dec128 max, - uint32_t precision, + int32_t precision, uint32_t *maxBitsOut, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(maxBitsOut); + BSON_ASSERT(precision >= 0); if (!mc_dec128_is_finite(max)) { CLIENT_ERR("Invalid upper bound for Decimal128 precision. Max is infinite."); @@ -529,7 +531,7 @@ bool mc_canUsePrecisionModeDecimal(mc_dec128 min, if (mc_dec128_not_equal(scaled_max, scaled_max_trunc)) { CLIENT_ERR("Invalid upper bound for Decimal128 precision. Fractional digits must be less than " - "the specified precision value. max: %s, precision: %" PRIu32, + "the specified precision value. max: %s, precision: %" PRId32, mc_dec128_to_string(max).str, precision); return false; @@ -537,7 +539,7 @@ bool mc_canUsePrecisionModeDecimal(mc_dec128 min, if (mc_dec128_not_equal(scaled_min, scaled_min_trunc)) { CLIENT_ERR("Invalid lower bound for Decimal128 precision. Fractional digits must be less than " - "the specified precision value. min: %s, precision: %" PRIu32, + "the specified precision value. min: %s, precision: %" PRId32, mc_dec128_to_string(min).str, precision); return false; @@ -570,7 +572,7 @@ bool mc_canUsePrecisionModeDecimal(mc_dec128 min, mc_dec128 prc_dec = mc_dec128_from_double((double)precision); if (mc_dec128_less(t_5, prc_dec)) { - CLIENT_ERR("Invalid value for precision. precision: %" PRIu32, precision); + CLIENT_ERR("Invalid value for precision. precision: %" PRId32, precision); return false; } @@ -583,7 +585,7 @@ bool mc_canUsePrecisionModeDecimal(mc_dec128 min, mlib_int128 range128 = mlib_int128_sub(i_1, i_2); if (precision > UINT8_MAX) { - CLIENT_ERR("Invalid value for precision. Must be less than 255. precision: %" PRIu32, precision); + CLIENT_ERR("Invalid value for precision. Must be less than 255. precision: %" PRId32, precision); return false; } @@ -610,8 +612,8 @@ bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args, } if (args.precision.set) { - if (args.precision.value > INT32_MAX) { - CLIENT_ERR("Precision cannot be greater than %" PRId32 ", got %" PRIu32, INT32_MAX, args.precision.value); + if (args.precision.value < 0) { + CLIENT_ERR("Precision must be non-negative, but got %" PRId32, args.precision.value); return false; } @@ -849,9 +851,9 @@ bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args, #endif // defined MONGOCRYPT_HAVE_DECIMAL128_SUPPORT const int64_t mc_FLERangeSparsityDefault = 2; -const uint32_t mc_FLERangeTrimFactorDefault = 6; +const int32_t mc_FLERangeTrimFactorDefault = 6; -uint32_t trimFactorDefault(size_t maxlen, mc_optional_uint32_t trimFactor, bool use_range_v2) { +int32_t trimFactorDefault(size_t maxlen, mc_optional_int32_t trimFactor, bool use_range_v2) { if (trimFactor.set) { return trimFactor.value; } @@ -861,8 +863,8 @@ uint32_t trimFactorDefault(size_t maxlen, mc_optional_uint32_t trimFactor, bool return 0; } - if (mc_FLERangeTrimFactorDefault > maxlen - 1) { - return (uint32_t)maxlen - 1; + if (bson_cmp_greater_su(mc_FLERangeTrimFactorDefault, maxlen - 1)) { + return (int32_t)(maxlen - 1); } else { return mc_FLERangeTrimFactorDefault; } diff --git a/src/mc-range-mincover-generator.template.h b/src/mc-range-mincover-generator.template.h index 6fd9d732d..907bd9767 100644 --- a/src/mc-range-mincover-generator.template.h +++ b/src/mc-range-mincover-generator.template.h @@ -89,7 +89,7 @@ typedef struct { UINT_T _rangeMin; UINT_T _rangeMax; size_t _sparsity; - uint32_t _trimFactor; + int32_t _trimFactor; // _maxlen is the maximum bit length of edges in the mincover. size_t _maxlen; } DECORATE_NAME(MinCoverGenerator); @@ -99,7 +99,7 @@ static inline DECORATE_NAME(MinCoverGenerator) UINT_T rangeMax, UINT_T max, size_t sparsity, - mc_optional_uint32_t opt_trimFactor, + mc_optional_int32_t opt_trimFactor, mongocrypt_status_t *status, bool use_range_v2) { BSON_ASSERT_PARAM(status); @@ -123,10 +123,16 @@ static inline DECORATE_NAME(MinCoverGenerator) return NULL; } size_t maxlen = (size_t)BITS - DECORATE_NAME(mc_count_leading_zeros)(max); - uint32_t trimFactor = trimFactorDefault(maxlen, opt_trimFactor, use_range_v2); - if (trimFactor != 0 && trimFactor >= maxlen) { - CLIENT_ERR("Trim factor must be less than the number of bits (%zu) used to represent an element of the domain", - maxlen); + int32_t trimFactor = trimFactorDefault(maxlen, opt_trimFactor, use_range_v2); + if (trimFactor != 0 && bson_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, + trimFactor); + return NULL; + } + if (trimFactor < 0) { + CLIENT_ERR("Trim factor must be >= 0, but got (%" PRId32 ")", trimFactor); return NULL; } DECORATE_NAME(MinCoverGenerator) *mcg = bson_malloc0(sizeof(DECORATE_NAME(MinCoverGenerator))); @@ -163,7 +169,9 @@ static inline bool DECORATE_NAME(MinCoverGenerator_isLevelStored)(DECORATE_NAME( size_t maskedBits) { BSON_ASSERT_PARAM(mcg); size_t level = mcg->_maxlen - maskedBits; - return 0 == maskedBits || (level >= mcg->_trimFactor && 0 == (level % mcg->_sparsity)); + BSON_ASSERT(bson_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)); } char * @@ -218,6 +226,11 @@ static inline mc_mincover_t *DECORATE_NAME(MinCoverGenerator_minCover)(DECORATE_ return mc; } +static inline int32_t DECORATE_NAME(MinCoverGenerator_usedTrimFactor)(DECORATE_NAME(MinCoverGenerator) * mcg) { + BSON_ASSERT_PARAM(mcg); + return mcg->_trimFactor; +} + // adjustBounds increments *lowerBound if includeLowerBound is false and // decrements *upperBound if includeUpperBound is false. // lowerBound, min, upperBound, and max are expected to come from the result diff --git a/src/mc-range-mincover-private.h b/src/mc-range-mincover-private.h index 7783aba53..2129dff08 100644 --- a/src/mc-range-mincover-private.h +++ b/src/mc-range-mincover-private.h @@ -33,6 +33,9 @@ const char *mc_mincover_get(mc_mincover_t *mincover, size_t index); // mc_mincover_len returns the number of represented mincover. size_t mc_mincover_len(mc_mincover_t *mincover); +// Return the trimFactor that was used to generate this mincover. +int32_t mc_mincover_get_used_trimFactor(const mc_mincover_t *mincover); + // mc_mincover_destroys frees `mincover`. void mc_mincover_destroy(mc_mincover_t *mincover); @@ -44,7 +47,7 @@ typedef struct { mc_optional_int32_t min; mc_optional_int32_t max; size_t sparsity; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t trimFactor; } mc_getMincoverInt32_args_t; // mc_getMincoverInt32 implements the Mincover Generation algorithm described in @@ -61,7 +64,7 @@ typedef struct { mc_optional_int64_t min; mc_optional_int64_t max; size_t sparsity; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t trimFactor; } mc_getMincoverInt64_args_t; // mc_getMincoverInt64 implements the Mincover Generation algorithm described in @@ -78,8 +81,8 @@ typedef struct { size_t sparsity; mc_optional_double_t min; mc_optional_double_t max; - mc_optional_uint32_t precision; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_getMincoverDouble_args_t; // mc_getMincoverDouble implements the Mincover Generation algorithm described @@ -96,8 +99,8 @@ typedef struct { bool includeUpperBound; size_t sparsity; mc_optional_dec128_t min, max; - mc_optional_uint32_t precision; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_getMincoverDecimal128_args_t; // mc_getMincoverDecimal128 implements the Mincover Generation algorithm diff --git a/src/mc-range-mincover.c b/src/mc-range-mincover.c index 2d006277c..635ae6cd0 100644 --- a/src/mc-range-mincover.c +++ b/src/mc-range-mincover.c @@ -27,6 +27,7 @@ struct _mc_mincover_t { /* mincover is an array of `char*` edge strings. */ mc_array_t mincover; + int32_t usedTrimFactor; // The `trimFactor` that was used to produce this mincover. }; static mc_mincover_t *mc_mincover_new(void) { @@ -48,6 +49,10 @@ size_t mc_mincover_len(mc_mincover_t *mincover) { return mincover->mincover.len; } +int32_t mc_mincover_get_used_trimFactor(const mc_mincover_t *mincover) { + return mincover->usedTrimFactor; +} + void mc_mincover_destroy(mc_mincover_t *mincover) { if (NULL == mincover) { return; @@ -155,6 +160,7 @@ mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args, mongocrypt_s return NULL; } mc_mincover_t *mc = MinCoverGenerator_minCover_u32(mcg); + mc->usedTrimFactor = MinCoverGenerator_usedTrimFactor_u32(mcg); MinCoverGenerator_destroy_u32(mcg); return mc; } @@ -187,6 +193,7 @@ mc_mincover_t *mc_getMincoverInt64(mc_getMincoverInt64_args_t args, mongocrypt_s return NULL; } mc_mincover_t *mc = MinCoverGenerator_minCover_u64(mcg); + mc->usedTrimFactor = MinCoverGenerator_usedTrimFactor_u64(mcg); MinCoverGenerator_destroy_u64(mcg); return mc; } @@ -230,6 +237,7 @@ mc_mincover_t *mc_getMincoverDouble(mc_getMincoverDouble_args_t args, mongocrypt return NULL; } mc_mincover_t *mc = MinCoverGenerator_minCover_u64(mcg); + mc->usedTrimFactor = MinCoverGenerator_usedTrimFactor_u64(mcg); MinCoverGenerator_destroy_u64(mcg); return mc; } @@ -274,6 +282,7 @@ mc_getMincoverDecimal128(mc_getMincoverDecimal128_args_t args, mongocrypt_status return NULL; } mc_mincover_t *mc = MinCoverGenerator_minCover_u128(mcg); + mc->usedTrimFactor = MinCoverGenerator_usedTrimFactor_u128(mcg); MinCoverGenerator_destroy_u128(mcg); return mc; } diff --git a/src/mc-rangeopts-private.h b/src/mc-rangeopts-private.h index e2ae64225..014f22d43 100644 --- a/src/mc-rangeopts-private.h +++ b/src/mc-rangeopts-private.h @@ -36,8 +36,8 @@ typedef struct { } max; int64_t sparsity; - mc_optional_uint32_t precision; - mc_optional_uint32_t trimFactor; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_RangeOpts_t; /* mc_RangeOpts_parse parses a BSON document into mc_RangeOpts_t. @@ -46,8 +46,8 @@ typedef struct { * "min": BSON value, * "max": BSON value, * "sparsity": Int64, - * "precision": Optional, - * "trimFactor": Optional, + * "precision": Optional, + * "trimFactor": Optional, * } */ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, bool use_range_v2, mongocrypt_status_t *status); diff --git a/src/mc-rangeopts.c b/src/mc-rangeopts.c index 18ff33b4b..4a9e4c638 100644 --- a/src/mc-rangeopts.c +++ b/src/mc-rangeopts.c @@ -95,7 +95,7 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, bool use_range_v2, CLIENT_ERR_PREFIXED("'precision' must be non-negative"); return false; } - ro->precision = OPT_U32((uint32_t)val); + ro->precision = OPT_I32(val); } END_IF_FIELD @@ -110,7 +110,7 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, bool use_range_v2, CLIENT_ERR_PREFIXED("'trimFactor' must be non-negative"); return false; } - ro->trimFactor = OPT_U32((uint32_t)val); + ro->trimFactor = OPT_I32(val); } END_IF_FIELD @@ -440,7 +440,7 @@ bool mc_getNumberOfBits(const mc_RangeOpts_t *ro, } else if (valueType == BSON_TYPE_DOUBLE) { double value = 0; mc_optional_double_t rmin = {false, 0}, rmax = {false, 0}; - mc_optional_uint32_t prec = ro->precision; + mc_optional_int32_t prec = ro->precision; if (ro->min.set) { BSON_ASSERT(ro->max.set); value = bson_iter_double(&ro->min.value); @@ -459,7 +459,7 @@ bool mc_getNumberOfBits(const mc_RangeOpts_t *ro, else if (valueType == BSON_TYPE_DECIMAL128) { mc_dec128 value = MC_DEC128_ZERO; mc_optional_dec128_t rmin = {false, MC_DEC128_ZERO}, rmax = {false, MC_DEC128_ZERO}; - mc_optional_uint32_t prec = ro->precision; + mc_optional_int32_t prec = ro->precision; if (ro->min.set) { BSON_ASSERT(ro->max.set); value = mc_dec128_from_bson_iter(&ro->min.value); @@ -497,7 +497,6 @@ bool mc_RangeOpts_appendTrimFactor(const mc_RangeOpts_t *ro, // A default `trimFactor` will be selected later with `trimFactorDefault` return true; } - BSON_ASSERT(ro->trimFactor.value <= INT32_MAX); uint32_t nbits; if (!mc_getNumberOfBits(ro, valueType, &nbits, status, use_range_v2)) { @@ -505,14 +504,14 @@ 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 (ro->trimFactor.value >= test) { + if (bson_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, nbits); return false; } - if (!BSON_APPEND_INT32(out, fieldName, (int32_t)ro->trimFactor.value)) { + if (!BSON_APPEND_INT32(out, fieldName, ro->trimFactor.value)) { CLIENT_ERR_PREFIXED("failed to append BSON"); return false; } diff --git a/src/mongocrypt-crypto.c b/src/mongocrypt-crypto.c index 1d9847fef..2d2a4c4db 100644 --- a/src/mongocrypt-crypto.c +++ b/src/mongocrypt-crypto.c @@ -1388,6 +1388,8 @@ bool _mongocrypt_random_uint64(_mongocrypt_crypto_t *crypto, } memcpy(&rand_u64, rand_u64_buf.data, rand_u64_buf.len); + // Use little-endian to enable deterministic tests on big-endian machines. + rand_u64 = BSON_UINT64_FROM_LE(rand_u64); if (rand_u64 >= min) { break; diff --git a/src/mongocrypt-marking.c b/src/mongocrypt-marking.c index 0c007ce04..a78775f1d 100644 --- a/src/mongocrypt-marking.c +++ b/src/mongocrypt-marking.c @@ -1130,6 +1130,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo BSON_ASSERT_PARAM(ciphertext); BSON_ASSERT(kb->crypt); BSON_ASSERT(marking->type == MONGOCRYPT_MARKING_FLE2_ENCRYPTION); + const bool use_range_v2 = kb->crypt->opts.use_range_v2; if (!kb->crypt->opts.use_fle2_v2) { return _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange_v1(kb, marking, ciphertext, status); @@ -1145,7 +1146,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo // Parse the value ("v"), min ("min"), and max ("max") from // FLE2EncryptionPlaceholder for range insert. mc_FLE2RangeInsertSpec_t insertSpec; - if (!mc_FLE2RangeInsertSpec_parse(&insertSpec, &placeholder->v_iter, kb->crypt->opts.use_range_v2, status)) { + if (!mc_FLE2RangeInsertSpec_parse(&insertSpec, &placeholder->v_iter, use_range_v2, status)) { goto fail; } @@ -1226,10 +1227,17 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo } } + // Include "range" payload fields introduced in SERVER-91889. + payload.sparsity = OPT_I64(placeholder->sparsity); + payload.precision = insertSpec.precision; + payload.trimFactor = OPT_I32(mc_edges_get_used_trimFactor(edges)); + bson_value_copy(bson_iter_value(&insertSpec.min), &payload.indexMin); + bson_value_copy(bson_iter_value(&insertSpec.max), &payload.indexMax); + { bson_t out; bson_init(&out); - mc_FLE2InsertUpdatePayloadV2_serializeForRange(&payload, &out); + mc_FLE2InsertUpdatePayloadV2_serializeForRange(&payload, &out, use_range_v2); _mongocrypt_buffer_steal_from_bson(&ciphertext->data, &out); } // Do not set ciphertext->original_bson_type and ciphertext->key_id. They are @@ -1791,6 +1799,15 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange(_mongocrypt_ } } payload.payload.set = true; + + if (use_range_v2) { + // Include "range" payload fields introduced in SERVER-91889. + payload.sparsity = OPT_I64(placeholder->sparsity); + payload.precision = findSpec.edgesInfo.value.precision; + payload.trimFactor = OPT_I32(mc_mincover_get_used_trimFactor(mincover)); + bson_value_copy(bson_iter_value(&findSpec.edgesInfo.value.indexMin), &payload.indexMin); + bson_value_copy(bson_iter_value(&findSpec.edgesInfo.value.indexMax), &payload.indexMax); + } } payload.payloadId = findSpec.payloadId; @@ -1800,7 +1817,7 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange(_mongocrypt_ // Serialize. { bson_t out = BSON_INITIALIZER; - mc_FLE2FindRangePayloadV2_serialize(&payload, &out); + mc_FLE2FindRangePayloadV2_serialize(&payload, &out, use_range_v2); _mongocrypt_buffer_steal_from_bson(&ciphertext->data, &out); } _mongocrypt_buffer_steal(&ciphertext->key_id, &placeholder->index_key_id); diff --git a/test/data/no-trimFactor/find/encrypted-payload.json b/test/data/no-trimFactor/find/encrypted-payload.json index 805c480bb..0dce092b6 100644 --- a/test/data/no-trimFactor/find/encrypted-payload.json +++ b/test/data/no-trimFactor/find/encrypted-payload.json @@ -13,7 +13,7 @@ "encrypted": { "$gte": { "$binary": { - "base64": "Dd0AAAADcGF5bG9hZACZAAAABGcAhQAAAAMwAH0AAAAFZAAgAAAAABVoe9wkcCyHpbOGCU+k9auwnEcS2CtNpRqiecg98ONpBXMAIAAAAABvqHHsxgHdi12FXVttMVYYwNK4R2zYUjeXQHAURNBvzwVsACAAAAAAfmp4QWZF7LiYXH6RYjf1kc6OpgRnCadlHki6cRrMilsAABJjbQAIAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", + "base64": "DQEBAAADcGF5bG9hZACZAAAABGcAhQAAAAMwAH0AAAAFZAAgAAAAABVoe9wkcCyHpbOGCU+k9auwnEcS2CtNpRqiecg98ONpBXMAIAAAAABvqHHsxgHdi12FXVttMVYYwNK4R2zYUjeXQHAURNBvzwVsACAAAAAAfmp4QWZF7LiYXH6RYjf1kc6OpgRnCadlHki6cRrMilsAABJjbQAIAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAASc3AAAQAAAAAAAAAQdGYABgAAABBtbgAAAACAEG14AP///38A", "subType": "06" } } diff --git a/test/data/no-trimFactor/insert/encrypted-payload.json b/test/data/no-trimFactor/insert/encrypted-payload.json index 797276b0b..722f052b2 100644 --- a/test/data/no-trimFactor/insert/encrypted-payload.json +++ b/test/data/no-trimFactor/insert/encrypted-payload.json @@ -5,7 +5,7 @@ "plainText": "sample", "encrypted": { "$binary": { - "base64": "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", + "base64": "CyAVAAAFZAAgAAAAAFX/OCQuK7sgFC5OgvIzRF0iZF5yZhqqgVEw+BDk04D/BXMAIAAAAADf8ZGTnPqqur9tusELGqTbSNtoJgj8i071DXm7kQpcSgVwADEAAAAAAwECAwECAwECAwECAwECAz+VM8kdZjiqXJ2Kga/NSZuITHP/iMRHFXZ17XdXy4FMWwV1ABAAAAAEEjRWeBI0mHYSNBI0VniQEhB0ABAAAAAFdgBQAAAAABI0VngSNJh2EjQSNFZ4kBIBAgMBAgMBAgMBAgMBAgMB978eymjOG8LzTgudRZqpbK4Tm1RK3tB9QMB9lTWKiy6Wqp7twzRA/ZbjQ69RKj60BWUAIAAAAADrmnP3kS2GpCl+gdL2da90KHTkBX46iQ/sZRoj7uPz7AVsACAAAAAAlO36MaVLVRDFW6xrI+0UTkyQdFfSCEBPkZg8sFzuTJYSawAGAAAAAAAAAARnAJkTAAADMAC2AAAABWQAIAAAAABx4c6MPMR3Yyxzi0dTMjQ7UdRNgI8uP2LTi1vhGYnLMAVzACAAAAAAon13gVyXE18K3ylqp/ovYStGulVBaekS2mKVRFq7RQgFbAAgAAAAAH5qeEFmRey4mFx+kWI39ZHOjqYEZwmnZR5IunEazIpbBXAAMQAAAAACAwECAwECAwECAwECAwECy273HayEz3hgoMYG56e0sxacPePKwPiqCCS575wlTLMxAAMxALYAAAAFZAAgAAAAALhKoC9+IzmWByMV7+lxHqBz30ckyd4wjXTJIaxvSHGQBXMAIAAAAADOFYCxSi5cl0dHBBpG2MuoCMK4VW7bnHkT4W0b8/S9QAVsACAAAAAA2ed4R4wYD6DT0P+N6o3gDJPE0DjljbRAv5vme3jb42sFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgMucSLry7LOh6S3NFriDyboyFWjjO7jUCKQmfnXNTVgRlsAAzIAtgAAAAVkACAAAAAA+QfEdnHiCdqN2uZKt8sulOoCI4Je4Lf2KfPWurcO6kcFcwAgAAAAAFvZ404SMykRwVDQtyApzVblLcZf0hl98cHQjbouG3VABWwAIAAAAAAYo/AvCQYlIUoNWV6sySJLiHk24w/YX3vRwwLVDjDsUgVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAele8PzNsBFG/0E0aRIa/STYmSf8Er7TW/aD841prevDywADMwC2AAAABWQAIAAAAADp37F20ZoHis9Y04z918sGyOCzOAnedki7o0xjs8aV4wVzACAAAAAA6gskIxd1RdPkI/t10Xs2RuQfNNaYAl0RCc/fEb9W590FbAAgAAAAAMf1cfJpJNlRk23xnpecqLu+IubHI7xMG6hGbCEA6QiiBXAAMQAAAAACAwECAwECAwECAwECAwECgxikv+dmmfSOXBQZkSatlNnFs2ATq0yp24nzunnI7mYwAAM0ALYAAAAFZAAgAAAAAG1JiCyGj5jLeMtQ0/UdOjg7P/gpwnYf6zlmRUnSU9tXBXMAIAAAAACtFe8XxEL7jbB4o17AIUTZ77heOzagFgk+Z2eL+QFeDQVsACAAAAAADYD3CyooN8IiEWsc1sPc1xCoRwH4F/+IYxDCubSkq+AFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgNNcU1NRd5pnVOIkx5k9qmZLy9F4raY2lK9H/NHP8CDC1sAAzUAtgAAAAVkACAAAAAAR3PxltBrzRZyAM57P9ciNMRpfyK+XB+QS0HJB/pFd3wFcwAgAAAAAEJoiSyFo2mxiXooeBm6E+rf3J90hTozFIFKSa5kPF1BBWwAIAAAAADmWysyKhf8UccKx78IliHTWao9pe/AwmLMDbMAnVJHPQVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAfDvmp5aIFHmt2vMpiuJI5jiaH7XRZ2dvrYZN5kjisPCywADNgC2AAAABWQAIAAAAACXnb80p8rHO1VZHz+NTqjUpoimkBybXrjMNLPk0Y2OUwVzACAAAAAAwRn8p8mm9fil7GXa4feiUPoaknS8X/eHqhu+Ynx2HEoFbAAgAAAAAAMUtyBHzqCfsTv4qaEnDPoB5Yb8qT4VjUppsq0/OY0mBXAAMQAAAAACAwECAwECAwECAwECAwECqAp8Ozm1Kd/Pk4q2oao5gsfAFcI39uY/eF2SybroFfEwAAM3ALYAAAAFZAAgAAAAAOW+ccgZnspe3Zk0B15sNoxYs+++vkIhLYDssUWrpf+ZBXMAIAAAAAC13nmuhE1cSoIdkJleu6iHCYZARpCxvagwSrdjvgaRUgVsACAAAAAAIrk7klUCamSAp05f9qK6PqR041yRVCaJ7dctpSUm5/gFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgNVutv0BdHOWmHtoNn6bEXHyRFbnxCJcfOzMiOveMdMVFsAAzgAtgAAAAVkACAAAAAAxbzcIam2ob0pklDpzLYr/BteO9cOCoJ0aWD6fGucXl0FcwAgAAAAAP5nX0Erewnh2CHdBDf3QsCG2XW2z90KD5B6Y+rzAl6ZBWwAIAAAAAAuKpEiz1IaNOIZ1+6lpo/M5wuUuwcW1GwgOCkqjExoOAVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAUzgTPP0+DG25jA52gXEcrK7bZQVD3qkpacpHd20tMAaywADOQC2AAAABWQAIAAAAAAcPMjPbOYfcAFEE0S3iUwoG9sWv8iy+fXbRTI5lfZ87QVzACAAAAAALfwKPHpI8mYj7xwh0i1P8MCp0LElos16pjLHMYy17gYFbAAgAAAAAHaai/vRhi3N4fiKYQomGNBSheDejcjnijIsVNmCu7vhBXAAMQAAAAACAwECAwECAwECAwECAwECRO+KoIpbLkFJkPNNknDUIv1zVweuC9zCdHTrmkor570wAAMxMAC2AAAABWQAIAAAAAAmoUbqGpreYSpgpkRV3PcLPwT90pv4J6Sq9hkzr1UyawVzACAAAAAAYK4KHqanlnpDmejdMXMo9/IdK47uVhuMyw1Lmg2S53gFbAAgAAAAAELpvtDOvYFsTO0EEkccCZpolG2C2oRSTimCz5l11QLTBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDgMqoRCc7BGqgadidlaTFtzKKMFdubtfXSHXfVstTOn5bAAMxMQC2AAAABWQAIAAAAAD0ugfk8nq6aFeln4+QLIhFyOkLafGcozN8MvybVLzaRgVzACAAAAAAC1ORUt0477aATkfBAN86Ky6TzUN4zYnGFdZw5VLJ3hcFbAAgAAAAAAs9x1SnVpMfNv5Bm1aXGwHmbbI9keWa9HRD35XuCBK5BXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBudSC4AK71+G+X6MfMuwKWRMnLOC4aidsIoUO0hV/QJTLAAMxMgC2AAAABWQAIAAAAADyKcEZ3l9iBRpFzfpofEfy1FkKktV1wzi2YMq438HAiQVzACAAAAAAJKWF4iNZdB6uI0t36zEsQpTi3cjhjMlUgJKxrQ5j19UFbAAgAAAAADj8Gb1dH1WJp8Z7W4Byzvjen38gy94jJ+bF4zcH8tB9BXAAMQAAAAACAwECAwECAwECAwECAwECTbYFftNKqDnEXKQbq2y3kKk4Wn5qJdjsUtSdBsj93m4wAAMxMwC2AAAABWQAIAAAAADQjZ9MCafSB+PIyoWl6zDRGcS/vGxSwQyuHHXESorF8AVzACAAAAAAMGC5dQYjHcHV9A+JDoOjcv7wEoZMiy6WCzo//5fJ7/EFbAAgAAAAAA8R9s/RrnxTOkU+fqYFsnAm0kmNKXhr0V3k/1OrtuTRBXAAMQAAAAADAQIDAQIDAQIDAQIDAQID0AQbL4e/j9E2BD/JqlROMj5nCV/Ms+LNiEKrM1EIMvdbAAMxNAC2AAAABWQAIAAAAADIgkDOvv4jRMk0e6Hw1NmMK/mrkkE68c74ahE/puHvbQVzACAAAAAA4CP/wdQvRwOl5t4mMgbwyhqjv01uiZveIj+U0dDmeJoFbAAgAAAAADpXRUP1KWfQopIEZgILyQjoq1rNc1SAgsP1U5QU0CREBXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBUqTscwusf1Sb9zr4ADXAuCcXXu6uLjV0FWzq5pdQ5hnLAAMxNQC2AAAABWQAIAAAAAClQOAmtdtHutim1zys0oMAxMkmClbHfAnkSLoTEjhwqwVzACAAAAAAVgt1FbCG6npznV3DHPsm1Zn2GJZMjjlE0wTUcCI0tOUFbAAgAAAAAArpkUe9A6CGOWFewttmaEMuVb6cJXc2tkP1R7vLf/SeBXAAMQAAAAACAwECAwECAwECAwECAwECPxj1iUCVNl0Z4rKvXKa9B6QsnyDHJyj8AUL42+SqvV4wAAMxNgC2AAAABWQAIAAAAACsc01M1lll1fAJc/LmqhR8KmQqlJ0ZGjHJ/Af0Jt3dzAVzACAAAAAAJ2n9ToriAiOreicCfmkRn3naQ7bIul0Xyjvnp6XTJbwFbAAgAAAAAKF92FNer/Q+vMlgRHGXnQP+EX9HQa2YYjTSon7O2IxDBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDxw1fFAt+kDNIihdC2r7837lNWG9IgpFMSUNza2MS+LpbAAMxNwC2AAAABWQAIAAAAACnNRIgrtUTrL9bvDzNfdzpGsdqBElHVWVpYyPXwSwrvgVzACAAAAAAjmBoFQHWGwST1BE0yaBiekIcYVsoUf/BSrLwO9UhtEsFbAAgAAAAAEe9aNvZUOhoa4IYjG0TUFY0Lbx6KYY//F0HqCDbN/u7BXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBPOd7p95VI1OtxfXq+5NSCH+ogPjo9lFrfeGODJKXKsjLAAMxOAC2AAAABWQAIAAAAAB69tLt+1PAUprgtKZWy3B9JL6GclTOi3dOgCCHgqPBnwVzACAAAAAAB8hNPjMyYRMHnH9XCVrcICu4ISWW3eCEUcSXZng35MAFbAAgAAAAAEcoyl5TBd6oEp+t0qD1tN0yjRtlGoa54w65U3dhexqRBXAAMQAAAAACAwECAwECAwECAwECAwECbtvNosMhvTRt45A7SQdH8hZippMddPE8g4K7zb6p7XswAAMxOQC2AAAABWQAIAAAAADO9uLhaBzFY2pp5k2huL0y7Ia9bbX9Td+8jbnze8vEoAVzACAAAAAAqE4YrbpDF0KstI1C6t+5gafrNKpWWc0gzHNa1VbxPjgFbAAgAAAAABkNIn+3njU/Zxu3Jz1yp3hxtx8KveIfzSQx6uLAsQLYBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDSCq69zvfhVJPRL0CTghUwWd8L3PWYQF7TwvOGZAw4z5bAAMyMAC2AAAABWQAIAAAAADUDjjIXc3gEKI0xh3UbzZvVMjQEJ3pHZDlee13ah248wVzACAAAAAAWfptH702DcaNwRMi0N3AN7Tr5qZhuecBsaFvVotkeOwFbAAgAAAAAO8B7P2R0zSBT5JbmwInpRsNZ2IJUMuL8l9VZjftP3WiBXAAMQAAAAABAgMBAgMBAgMBAgMBAgMB631+rWK1NZGz0Pf84u7wRYlfBwWhHkmrhvIRYczS5m/LAAMyMQC2AAAABWQAIAAAAABugPtcm/HV5MD8yyuw4bpcdO1+K8CkSbE/dhzK93fyJAVzACAAAAAAuKJP+IQVI2kYA02OeeHFQEmvuVVPFYtpD7nAcl4U8rYFbAAgAAAAAJRkWtjoKRlC5wNyXtyBUyPeH8hFa0fcZTw8R8alLt7QBXAAMQAAAAACAwECAwECAwECAwECAwEC0bHPZHQG/05yfKLiObxeknR1PuPEvJrR3f/s2ZiK+w0wAAMyMgC2AAAABWQAIAAAAAAtxq6iNLgn0d0g2oKCMOXZWf8LooZXa7CkhMlzX3U12gVzACAAAAAALUryeDpD1NktbkYTXUpsNQIJYr8I+fZBz4mFLSgtk44FbAAgAAAAAA9jJQaYWTOtI4mag6rZ7zycKpIHLEW0IkS8GCF5qSaMBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDzS5QIrvfRsnOnnZT+Z2BdcKeeWaIwToaTPER4e7sTohbAAMyMwC2AAAABWQAIAAAAAC6uNqCo6p+ohuqlioUo7bhj6L+0kJpFl3yLYfYhqbnrAVzACAAAAAAH6WDk481/wTTL/Y6t765GCYPH0niPXWzamTeZ6lEQkcFbAAgAAAAABhXLMOXrnco598ejjUHAkNGZR8eNVnDMWrAuQ16j2O/BXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBrSKQIVC2x1PtPhLkhY2Jahu7/uoimtsZXTegUO7y3MTLAAMyNAC2AAAABWQAIAAAAABkREAiEohu2Q1tDoksY567QbeolBSWlN9kY2VxQk2FnAVzACAAAAAAvDKcTZwlJBLt/1aRXy5ekX9Z/YcbhakokeaeY74zV4kFbAAgAAAAAEnd5ZUyXOLvEAhNT4ZKIDWE3wcv5mdo0crUrZauKMbnBXAAMQAAAAACAwECAwECAwECAwECAwEC1SEc0Ww2+DWHgLn9H3PFQ0KDejGQLLiQQ6CyyHitXjIwAAMyNQC2AAAABWQAIAAAAABn8GOJ0BUhqxsCMujadpEuMjQH/JqjdSe+d7ck4BJpBgVzACAAAAAA/+5+gxu0s/JHvMroY0hgg4/pNDl6+FbjkVVL4pp0wKAFbAAgAAAAAIZjTmkgXeFszdl7b+WoFTth6LSUyRYvg6eh5JiOaoBYBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDH4rc2ZooIeKkTPqox5+Nw09+L+D6wJq4Ei3fLly1HaZbAAMyNgC2AAAABWQAIAAAAAA+kw8ODbANBx/7vTQYS+vKeqcxI7s64zzuGVo9ISg+EAVzACAAAAAAijiBsW795UOqu7fNmYqbj7uSBToUCGU/mdufHc5RCl0FbAAgAAAAAFIO6h0rFmqi1XsueSDzF02jzB81vUi+aMj/LuTEHIdqBXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBOL+SA7F+3RSUqlMTq7mr/YYm5JnUr8uVrojhKonnlN7LAAASc3AAAQAAAAAAAAAQdGYABgAAABBtbgAAAACAEG14AP///38A", "subType": "06" } } diff --git a/test/data/range-sends-cryptoParams/auto-find-int32/cmd.json b/test/data/range-sends-cryptoParams/auto-find-int32/cmd.json new file mode 100644 index 000000000..b5d57a8f9 --- /dev/null +++ b/test/data/range-sends-cryptoParams/auto-find-int32/cmd.json @@ -0,0 +1,8 @@ +{ + "find": "test", + "filter": { + "encrypted": { + "$numberInt": "123456" + } + } +} diff --git a/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-field-map.json b/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-field-map.json new file mode 100644 index 000000000..e6884600b --- /dev/null +++ b/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-field-map.json @@ -0,0 +1,19 @@ +{ + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } +} diff --git a/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-payload.json b/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-payload.json new file mode 100644 index 000000000..46b87e8f0 --- /dev/null +++ b/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-payload.json @@ -0,0 +1,53 @@ +{ + "find": "test", + "filter": { + "$and": [ + { + "encrypted": { + "$gte": { + "$binary": { + "base64": "DQEBAAADcGF5bG9hZACZAAAABGcAhQAAAAMwAH0AAAAFZAAgAAAAABVoe9wkcCyHpbOGCU+k9auwnEcS2CtNpRqiecg98ONpBXMAIAAAAABvqHHsxgHdi12FXVttMVYYwNK4R2zYUjeXQHAURNBvzwVsACAAAAAAfmp4QWZF7LiYXH6RYjf1kc6OpgRnCadlHki6cRrMilsAABJjbQAIAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAASc3AAAgAAAAAAAAAQdGYABgAAABBtbgAAAACAEG14AP///38A", + "subType": "06" + } + } + } + }, + { + "encrypted": { + "$lte": { + "$binary": { + "base64": "DTsAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", + "subType": "06" + } + } + } + } + ] + }, + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ], + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc" + } + } + } +} diff --git a/test/data/range-sends-cryptoParams/auto-find-int32/mongocryptd-reply.json b/test/data/range-sends-cryptoParams/auto-find-int32/mongocryptd-reply.json new file mode 100644 index 000000000..ff9134f77 --- /dev/null +++ b/test/data/range-sends-cryptoParams/auto-find-int32/mongocryptd-reply.json @@ -0,0 +1,58 @@ +{ + "hasEncryptionPlaceholders": true, + "schemaRequiresEncryption": true, + "result": { + "find": "test", + "filter": { + "$and": [ + { + "encrypted": { + "$gte": { + "$binary": { + "base64": "AxABAAAQdAACAAAAEGEAAwAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAAQSNFZ4EjSYdhI0EjRWeJASA3YAsQAAAANlZGdlc0luZm8AawAAABBsb3dlckJvdW5kAEDiAQAIbGJJbmNsdWRlZAABEHVwcGVyQm91bmQAQOIBAAh1YkluY2x1ZGVkAAEQdHJpbUZhY3RvcgAGAAAAEGluZGV4TWluAAAAAIAQaW5kZXhNYXgA////fwAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAAEmNtAAgAAAAAAAAAEnMAAgAAAAAAAAAA", + "subType": "06" + } + } + } + }, + { + "encrypted": { + "$lte": { + "$binary": { + "base64": "A5oAAAAQdAACAAAAEGEAAwAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAAQSNFZ4EjSYdhI0EjRWeJASA3YAOwAAABBwYXlsb2FkSWQAAAAAABBmaXJzdE9wZXJhdG9yAAIAAAAQc2Vjb25kT3BlcmF0b3IABAAAAAASY20ACAAAAAAAAAAScwACAAAAAAAAAAA=", + "subType": "06" + } + } + } + } + ] + }, + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } + } + } + }, + "ok": { + "$numberDouble": "1.0" + } +} diff --git a/test/data/range-sends-cryptoParams/auto-insert-int32/cmd.json b/test/data/range-sends-cryptoParams/auto-insert-int32/cmd.json new file mode 100644 index 000000000..ce0965f2f --- /dev/null +++ b/test/data/range-sends-cryptoParams/auto-insert-int32/cmd.json @@ -0,0 +1,11 @@ +{ + "insert": "test", + "documents": [ + { + "plainText": "sample", + "encrypted": { + "$numberInt": "123456" + } + } + ] +} diff --git a/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-field-map.json b/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-field-map.json new file mode 100644 index 000000000..e6884600b --- /dev/null +++ b/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-field-map.json @@ -0,0 +1,19 @@ +{ + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } +} diff --git a/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-payload.json b/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-payload.json new file mode 100644 index 000000000..934fe11ad --- /dev/null +++ b/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-payload.json @@ -0,0 +1,40 @@ +{ + "insert": "test", + "documents": [ + { + "plainText": "sample", + "encrypted": { + "$binary": { + "base64": "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", + "subType": "06" + } + } + } + ], + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ], + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc" + } + } + } +} diff --git a/test/data/range-sends-cryptoParams/auto-insert-int32/mongocryptd-reply.json b/test/data/range-sends-cryptoParams/auto-insert-int32/mongocryptd-reply.json new file mode 100644 index 000000000..2ad49ecc0 --- /dev/null +++ b/test/data/range-sends-cryptoParams/auto-insert-int32/mongocryptd-reply.json @@ -0,0 +1,45 @@ +{ + "hasEncryptionPlaceholders": true, + "schemaRequiresEncryption": true, + "result": { + "insert": "test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } + } + }, + "documents": [ + { + "plainText": "sample", + "encrypted": { + "$binary": { + "base64": "A30AAAAQdAABAAAAEGEAAwAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAAQSNFZ4EjSYdhI0EjRWeJASA3YAHgAAABB2AEDiAQAQbWluAAAAAIAQbWF4AP///38AEmNtAAgAAAAAAAAAEnMAAgAAAAAAAAAA", + "subType": "06" + } + } + } + ] + }, + "ok": { + "$numberDouble": "1.0" + } +} diff --git a/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/expected.json b/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/expected.json new file mode 100644 index 000000000..192fb91e2 --- /dev/null +++ b/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/expected.json @@ -0,0 +1,26 @@ +{ + "v": { + "$and": [ + { + "age": { + "$gte": { + "$binary": { + "base64": "DYECAAADcGF5bG9hZAAZAgAABGcABQIAAAMwAH0AAAAFZAAgAAAAANBGT3k4GTmoze5hCRukb6u82SvYtFyGp+AHjlySsjWOBXMAIAAAAAB9cQ+iwhaAuhOnOn/BFalNNBn3Tx1mHngGdjzKvNPfsgVsACAAAAAA5ZNdJZh+4XZcHqJMhqWcLUo4YkxCxPhhRU7UFru8pk8AAzEAfQAAAAVkACAAAAAAzrlE+7ZYgnH71G+SpzjCefAEj4qNkUQOfn0FUFuKWycFcwAgAAAAAKZDfaea7ZYGynYzTtP38WQAewOs6QD3NH4RO9XwuJG5BWwAIAAAAACpq6FrRDHryiZeM1B50z/fz/J5yK3fEqAlFj4E6KCdSwADMgB9AAAABWQAIAAAAABTX/+x7fmCvi5gAWgsy5xZowLqeEc/z1qE7Eh9QkpMmQVzACAAAAAAjOLpo8K1z0hnG5U/e+p5IVCfR23vd98ZDgqy00xqJuwFbAAgAAAAAFqIYZydW8nwOUai0Cbz6IKBHpkuCbTP/VsBNDG9j1wUAAMzAH0AAAAFZAAgAAAAADgmrmBDpEvWF++05l1otn4vG6Q+GoYpGgdV2EIGSYXaBXMAIAAAAAD2b6bl3/wn2zPllR9z8Kl96rDn8OwdHZuVhUC9sYjFngVsACAAAAAARtUrQP0hYeNlaA1/I+sENuShjFgWyxY3Jw9URdcLiJAAABJjbQABAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAASc3AAAgAAAAAAAAAQdGYABgAAABBtbgAAAAAAEG14AIfWEgAA", + "subType": "06" + } + } + } + }, + { + "age": { + "$lte": { + "$binary": { + "base64": "DTsAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", + "subType": "06" + } + } + } + } + ] + } +} diff --git a/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/to-encrypt.json b/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/to-encrypt.json new file mode 100644 index 000000000..4c294e887 --- /dev/null +++ b/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/to-encrypt.json @@ -0,0 +1,20 @@ +{ + "v": { + "$and": [ + { + "age": { + "$gte": { + "$numberInt": "23" + } + } + }, + { + "age": { + "$lte": { + "$numberInt": "35" + } + } + } + ] + } +} diff --git a/test/data/range-sends-cryptoParams/explicit-find-int32/expected.json b/test/data/range-sends-cryptoParams/explicit-find-int32/expected.json new file mode 100644 index 000000000..472240e2e --- /dev/null +++ b/test/data/range-sends-cryptoParams/explicit-find-int32/expected.json @@ -0,0 +1,26 @@ +{ + "v": { + "$and": [ + { + "age": { + "$gte": { + "$binary": { + "base64": "DYEDAAADcGF5bG9hZAAZAwAABGcABQMAAAMwAH0AAAAFZAAgAAAAANBGT3k4GTmoze5hCRukb6u82SvYtFyGp+AHjlySsjWOBXMAIAAAAAB9cQ+iwhaAuhOnOn/BFalNNBn3Tx1mHngGdjzKvNPfsgVsACAAAAAA5ZNdJZh+4XZcHqJMhqWcLUo4YkxCxPhhRU7UFru8pk8AAzEAfQAAAAVkACAAAAAAzrlE+7ZYgnH71G+SpzjCefAEj4qNkUQOfn0FUFuKWycFcwAgAAAAAKZDfaea7ZYGynYzTtP38WQAewOs6QD3NH4RO9XwuJG5BWwAIAAAAACpq6FrRDHryiZeM1B50z/fz/J5yK3fEqAlFj4E6KCdSwADMgB9AAAABWQAIAAAAAA9l5+QldlpI2N4eSiV+2l4tS9xZM+Y8kwcP+KhiEA8owVzACAAAAAAmdQflu77krN/4fFaB4la/ZWystLLh6nNv6xE9ErNZmMFbAAgAAAAACJbpdQ2++FVjMz+SdScn4lx3wsi1Y9gBcJozBfHuC6dAAMzAH0AAAAFZAAgAAAAAAhh9K4YcA+N8ACgj7B4smCyJmmJImd5oOUxjgM3T208BXMAIAAAAAB8LMl/6O3elk8pcE6o/WWd6HQKpQgr22l1tt2CpA+V7QVsACAAAAAAIMPlQ/IXn7oI3v3ltx2/1ql4oP/HRQPRjFyh/qTXANoAAzQAfQAAAAVkACAAAAAAXvLR5mSdJiSJ1DFwqIs6GYKvY+1bd0llpUdegS3y6tEFcwAgAAAAABAbG+tZXZ/z9VokQYAH23Kd7R4B9hjN0M3kWn/KBj8CBWwAIAAAAAACdaE9Ls6mFpsHzPBdVxPze4wHSHyPOW9xjCKEW3nYKgADNQB9AAAABWQAIAAAAAALlsQ6TaYfVYomaBlpbXtQcSyRgpJWDQVMh9YGaoJKwwVzACAAAAAA2OMU7sh4xR5O2482Idkiluu2zVJ2/OytctuyOxrgBWsFbAAgAAAAAA8vwTEAaqZNyh/H/6rELrEWzB/Q+JsF/NJ3zszdMjy+AAASY20AAQAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAEnNwAAMAAAAAAAAAEHRmAAQAAAAQbW4AAAAAABBteACH1hIAAA==", + "subType": "06" + } + } + } + }, + { + "age": { + "$lte": { + "$binary": { + "base64": "DTsAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", + "subType": "06" + } + } + } + } + ] + } +} diff --git a/test/data/range-sends-cryptoParams/explicit-find-int32/to-encrypt.json b/test/data/range-sends-cryptoParams/explicit-find-int32/to-encrypt.json new file mode 100644 index 000000000..4c294e887 --- /dev/null +++ b/test/data/range-sends-cryptoParams/explicit-find-int32/to-encrypt.json @@ -0,0 +1,20 @@ +{ + "v": { + "$and": [ + { + "age": { + "$gte": { + "$numberInt": "23" + } + } + }, + { + "age": { + "$lte": { + "$numberInt": "35" + } + } + } + ] + } +} diff --git a/test/data/range-sends-cryptoParams/explicit-insert-double/expected.json b/test/data/range-sends-cryptoParams/explicit-insert-double/expected.json new file mode 100644 index 000000000..b518db1ca --- /dev/null +++ b/test/data/range-sends-cryptoParams/explicit-insert-double/expected.json @@ -0,0 +1,8 @@ +{ + "v": { + "$binary": { + "base64": "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", + "subType": "06" + } + } +} diff --git a/test/data/range-sends-cryptoParams/explicit-insert-int32-defaults/expected.json b/test/data/range-sends-cryptoParams/explicit-insert-int32-defaults/expected.json new file mode 100644 index 000000000..42c2b5db0 --- /dev/null +++ b/test/data/range-sends-cryptoParams/explicit-insert-int32-defaults/expected.json @@ -0,0 +1,8 @@ +{ + "v": { + "$binary": { + "base64": "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", + "subType": "06" + } + } +} diff --git a/test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json b/test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json new file mode 100644 index 000000000..07cc65089 --- /dev/null +++ b/test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json @@ -0,0 +1,8 @@ +{ + "v": { + "$binary": { + "base64": "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", + "subType": "06" + } + } +} diff --git a/test/test-mc-fle2-find-range-payload-v2.c b/test/test-mc-fle2-find-range-payload-v2.c index f984fdcca..79b2036e3 100644 --- a/test/test-mc-fle2-find-range-payload-v2.c +++ b/test/test-mc-fle2-find-range-payload-v2.c @@ -17,6 +17,7 @@ #include #include "mc-fle2-find-range-payload-private-v2.h" +#include "test-mongocrypt-assert-match-bson.h" #include "test-mongocrypt-assert.h" #include "test-mongocrypt.h" @@ -72,7 +73,8 @@ static void _test_FLE2FindRangePayloadV2_roundtrip(_mongocrypt_tester_t *tester) payload.secondOperator = expect_secondOperator; bson_init(&out_bson); - mc_FLE2FindRangePayloadV2_serialize(&payload, &out_bson); + const bool use_range_v2 = false; + mc_FLE2FindRangePayloadV2_serialize(&payload, &out_bson, use_range_v2); ASSERT_EQUAL_BSON(&in_bson, &out_bson); @@ -84,6 +86,44 @@ static void _test_FLE2FindRangePayloadV2_roundtrip(_mongocrypt_tester_t *tester) #undef TEST_FIND_RANGE_PAYLOAD_HEX_V2 +static void _test_FLE2FindRangePayloadV2_includes_crypto_params(_mongocrypt_tester_t *tester) { + mc_FLE2FindRangePayloadV2_t payload; + mc_FLE2FindRangePayloadV2_init(&payload); + payload.sparsity = OPT_I64(1); + payload.precision = OPT_I32(2); + payload.trimFactor = OPT_I32(3); + bson_value_t indexMin = {.value.v_int32 = 4, .value_type = BSON_TYPE_INT32}; + bson_value_copy(&indexMin, &payload.indexMin); + bson_value_t indexMax = {.value.v_int32 = 5, .value_type = BSON_TYPE_INT32}; + bson_value_copy(&indexMax, &payload.indexMax); + + // Test crypto params from SERVER-91889 are included in "range" payload. + { + bson_t got = BSON_INITIALIZER; + const bool use_range_v2 = true; + ASSERT(mc_FLE2FindRangePayloadV2_serialize(&payload, &got, use_range_v2)); + _assert_match_bson(&got, TMP_BSON(BSON_STR({"sp" : 1, "pn" : 2, "tf" : 3, "mn" : 4, "mx" : 5}))); + bson_destroy(&got); + } + + // Test crypto params from SERVER-91889 are excluded in "rangePreview" payload. + { + bson_t got = BSON_INITIALIZER; + const bool use_range_v2 = false; + ASSERT(mc_FLE2FindRangePayloadV2_serialize(&payload, &got, use_range_v2)); + _assert_match_bson(&got, TMP_BSON(BSON_STR({ + "sp" : {"$exists" : false}, + "pn" : {"$exists" : false}, + "tf" : {"$exists" : false}, + "mn" : {"$exists" : false}, + "mx" : {"$exists" : false} + }))); + bson_destroy(&got); + } + mc_FLE2FindRangePayloadV2_cleanup(&payload); +} + void _mongocrypt_tester_install_fle2_payload_find_range_v2(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_FLE2FindRangePayloadV2_roundtrip); -} \ No newline at end of file + INSTALL_TEST(_test_FLE2FindRangePayloadV2_includes_crypto_params); +} diff --git a/test/test-mc-fle2-payload-iup-v2.c b/test/test-mc-fle2-payload-iup-v2.c index 46470b995..af7ba180b 100644 --- a/test/test-mc-fle2-payload-iup-v2.c +++ b/test/test-mc-fle2-payload-iup-v2.c @@ -14,7 +14,9 @@ * limitations under the License. */ +#include "mc-fle-blob-subtype-private.h" #include "mc-fle2-insert-update-payload-private-v2.h" +#include "test-mongocrypt-assert-match-bson.h" #include "test-mongocrypt.h" #define TEST_IUP_HEX_V2 \ @@ -166,7 +168,81 @@ static void _test_mc_FLE2InsertUpdatePayloadV2_decrypt(_mongocrypt_tester_t *tes #undef TEST_IUP_HEX_V2 +static void _test_mc_FLE2InsertUpdatePayloadV2_includes_crypto_params(_mongocrypt_tester_t *tester) { + mc_FLE2InsertUpdatePayloadV2_t payload; + mc_FLE2InsertUpdatePayloadV2_init(&payload); + payload.sparsity = OPT_I64(1); + payload.precision = OPT_I32(2); + payload.trimFactor = OPT_I32(3); + bson_value_t indexMin = {.value.v_int32 = 4, .value_type = BSON_TYPE_INT32}; + bson_value_copy(&indexMin, &payload.indexMin); + bson_value_t indexMax = {.value.v_int32 = 5, .value_type = BSON_TYPE_INT32}; + bson_value_copy(&indexMax, &payload.indexMax); + + // Test crypto params from SERVER-91889 are included in "range" payload. + { + bson_t got = BSON_INITIALIZER; + const bool use_range_v2 = true; + ASSERT(mc_FLE2InsertUpdatePayloadV2_serializeForRange(&payload, &got, use_range_v2)); + _assert_match_bson(&got, TMP_BSON(BSON_STR({"sp" : 1, "pn" : 2, "tf" : 3, "mn" : 4, "mx" : 5}))); + bson_destroy(&got); + } + + // Test crypto params from SERVER-91889 are excluded in "rangePreview" payload. + { + bson_t got = BSON_INITIALIZER; + const bool use_range_v2 = false; + ASSERT(mc_FLE2InsertUpdatePayloadV2_serializeForRange(&payload, &got, use_range_v2)); + _assert_match_bson(&got, TMP_BSON(BSON_STR({ + "sp" : {"$exists" : false}, + "pn" : {"$exists" : false}, + "tf" : {"$exists" : false}, + "mn" : {"$exists" : false}, + "mx" : {"$exists" : false} + }))); + bson_destroy(&got); + } + mc_FLE2InsertUpdatePayloadV2_cleanup(&payload); +} + +static void _test_mc_FLE2InsertUpdatePayloadV2_parses_crypto_params(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *payload = TEST_FILE("test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json"); + + _mongocrypt_buffer_t payload_buf; + // Unwrap the { "v": } into a `_mongocrypt_buffer_t`. + { + bson_t payload_bson; + ASSERT(_mongocrypt_binary_to_bson(payload, &payload_bson)); + bson_iter_t iter; + ASSERT(bson_iter_init_find(&iter, &payload_bson, "v")); + ASSERT(_mongocrypt_buffer_from_binary_iter(&payload_buf, &iter)); + } + + mc_FLE2InsertUpdatePayloadV2_t got; + mc_FLE2InsertUpdatePayloadV2_init(&got); + + mongocrypt_status_t *status = mongocrypt_status_new(); + ASSERT_OK_STATUS(mc_FLE2InsertUpdatePayloadV2_parse(&got, &payload_buf, status), status); + mongocrypt_status_destroy(status); + + ASSERT(got.sparsity.set); + ASSERT_CMPINT64(got.sparsity.value, ==, 3); + + ASSERT(!got.precision.set); // Payload does not include precision. + + ASSERT(got.trimFactor.set); + ASSERT_CMPINT32(got.trimFactor.value, ==, 4); + + ASSERT(got.indexMin.value_type == BSON_TYPE_INT32); + ASSERT_CMPINT32(got.indexMin.value.v_int32, ==, 0); + + ASSERT(got.indexMax.value_type == BSON_TYPE_INT32); + ASSERT_CMPINT32(got.indexMax.value.v_int32, ==, 1234567); +} + void _mongocrypt_tester_install_fle2_payload_iup_v2(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_FLE2InsertUpdatePayloadV2_parse); INSTALL_TEST(_test_mc_FLE2InsertUpdatePayloadV2_decrypt); + INSTALL_TEST(_test_mc_FLE2InsertUpdatePayloadV2_includes_crypto_params); + INSTALL_TEST(_test_mc_FLE2InsertUpdatePayloadV2_parses_crypto_params); } diff --git a/test/test-mc-range-edge-generation.c b/test/test-mc-range-edge-generation.c index 6769624c1..a994f4b25 100644 --- a/test/test-mc-range-edge-generation.c +++ b/test/test-mc-range-edge-generation.c @@ -32,7 +32,7 @@ typedef struct { // expectEdges includes a trailing NULL pointer. const char *expectEdges[MAX_INT32_EDGES + 1]; const char *expectError; - uint32_t trimFactor; + int32_t trimFactor; } Int32Test; #undef MAX_INT32_EDGES @@ -82,6 +82,12 @@ static void _test_getEdgesInt32(_mongocrypt_tester_t *tester) { .trimFactor = 3, .expectError = "trimFactor must be less than the number of bits (3) used to represent an element of the domain"}, + {.value = 2, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 1, + .trimFactor = -1, + .expectError = "trimFactor must be >= 0"}, {.value = 2, .min = OPT_I32_C(0), .max = OPT_I32_C(7), @@ -110,7 +116,7 @@ static void _test_getEdgesInt32(_mongocrypt_tester_t *tester) { .min = test->min, .max = test->max, .sparsity = test->sparsity, - .trimFactor = OPT_U32(test->trimFactor)}; + .trimFactor = OPT_I32(test->trimFactor)}; const bool use_range_v2 = true; mc_edges_t *got = mc_getEdgesInt32(args, status, use_range_v2); if (test->expectError != NULL) { @@ -203,7 +209,7 @@ static void _test_getEdgesInt64(_mongocrypt_tester_t *tester) { .min = test->min, .max = test->max, .sparsity = test->sparsity, - .trimFactor = OPT_U32(test->trimFactor)}; + .trimFactor = OPT_I32(test->trimFactor)}; const bool use_range_v2 = true; mc_edges_t *got = mc_getEdgesInt64(args, status, use_range_v2); if (test->expectError != NULL) { @@ -264,7 +270,7 @@ static void _test_getEdgesDouble(_mongocrypt_tester_t *tester) { const uint32_t trimFactor = 0; // At present, all test cases expect trimFactor=0. mc_getEdgesDouble_args_t args = {.value = test->value, .sparsity = test->sparsity, - .trimFactor = OPT_U32(trimFactor)}; + .trimFactor = OPT_I32(trimFactor)}; const bool use_range_v2 = true; mc_edges_t *got = mc_getEdgesDouble(args, status, use_range_v2); @@ -332,7 +338,7 @@ static void _test_getEdgesDecimal128(_mongocrypt_tester_t *tester) { // .min = test->min, // .max = test->max, .sparsity = (size_t)test->sparsity, - .trimFactor = OPT_U32(trimFactor)}; + .trimFactor = OPT_I32(trimFactor)}; const bool use_range_v2 = true; mc_edges_t *got = mc_getEdgesDecimal128(args, status, use_range_v2); diff --git a/test/test-mc-range-encoding.c b/test/test-mc-range-encoding.c index 68a0a3f21..27da76d0b 100644 --- a/test/test-mc-range-encoding.c +++ b/test/test-mc-range-encoding.c @@ -261,7 +261,7 @@ typedef struct { double value; mc_optional_double_t min; mc_optional_double_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; uint64_t expect; mc_optional_uint64_t expectMax; const char *expectError; @@ -323,43 +323,43 @@ static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { /* Test cases copied from Double_Bounds_Precision ... begin */ {.value = 3.141592653589, - .precision = OPT_U32_C(1), + .precision = OPT_I32_C(1), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = UINT64_C(1000031), .expectMax = OPT_U64_C(2097151)}, {.value = 3.141592653589, - .precision = OPT_U32_C(2), + .precision = OPT_I32_C(2), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 10000314, .expectMax = OPT_U64_C(33554431)}, {.value = 3.141592653589, - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 100003141, .expectMax = OPT_U64_C(268435455)}, {.value = 3.141592653589, - .precision = OPT_U32_C(4), + .precision = OPT_I32_C(4), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 1000031415, .expectMax = OPT_U64_C(2147483647)}, {.value = 3.141592653589, - .precision = OPT_U32_C(5), + .precision = OPT_I32_C(5), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 10000314159, .expectMax = OPT_U64_C(34359738367)}, {.value = 3.141592653589, - .precision = OPT_U32_C(6), + .precision = OPT_I32_C(6), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 100003141592, .expectMax = OPT_U64_C(274877906943)}, {.value = 3.141592653589, - .precision = OPT_U32_C(7), + .precision = OPT_I32_C(7), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 1000031415926, @@ -367,119 +367,119 @@ static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { {.value = 0, .max = OPT_DOUBLE_C(1), .min = OPT_DOUBLE_C(-1), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), .expect = 1000, .expectMax = OPT_U64_C(4095)}, {.value = 0, .max = OPT_DOUBLE_C(1), .min = OPT_DOUBLE_C(-1E5), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), .expect = 100000000, .expectMax = OPT_U64_C(134217727)}, {.value = -1E-33, .max = OPT_DOUBLE_C(1), .min = OPT_DOUBLE_C(-1E5), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), .expect = 100000000, .expectMax = OPT_U64_C(134217727)}, {.value = 0, .max = OPT_DOUBLE_C(DBL_MAX), .min = OPT_DOUBLE_C(-DBL_MAX), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), // Applying min/max/precision result in a domain needing >= 64 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 0, .max = OPT_DOUBLE_C(DBL_MAX), .min = OPT_DOUBLE_C(-DBL_MAX), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), // Applying min/max/precision result in a domain needing >= 64 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), - .precision = OPT_U32_C(0), + .precision = OPT_I32_C(0), .expect = 3, .expectMax = OPT_U64_C(7)}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), - .precision = OPT_U32_C(1), + .precision = OPT_I32_C(1), .expect = 31, .expectMax = OPT_U64_C(63)}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), - .precision = OPT_U32_C(2), + .precision = OPT_I32_C(2), .expect = 314, .expectMax = OPT_U64_C(1023)}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), .expect = 3141, .expectMax = OPT_U64_C(8191)}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), - .precision = OPT_U32_C(16), + .precision = OPT_I32_C(16), .expectError = "Invalid upper bound for double precision"}, {.value = -5, .max = OPT_DOUBLE_C(-1), .min = OPT_DOUBLE_C(-10), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), .expect = 5000, .expectMax = OPT_U64_C(16383)}, {.value = 1E100, .max = OPT_DOUBLE_C(DBL_MAX), .min = OPT_DOUBLE_C(-DBL_MAX), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), // Applying min/max/precision result in a domain needing >= 64 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 1E100, .max = OPT_DOUBLE_C(DBL_MAX), .min = OPT_DOUBLE_C(-DBL_MAX), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), // Applying min/max/precision result in a domain needing >= 64 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 1E9, .max = OPT_DOUBLE_C(1E10), .min = OPT_DOUBLE_C(0), - .precision = OPT_U32_C(3), + .precision = OPT_I32_C(3), .expect = 1000000000000, .expectMax = OPT_U64_C(17592186044415)}, {.value = 1E9, .max = OPT_DOUBLE_C(1E10), .min = OPT_DOUBLE_C(0), - .precision = OPT_U32_C(0), + .precision = OPT_I32_C(0), .expect = 1000000000, .expectMax = OPT_U64_C(17179869183)}, {.value = -5, .max = OPT_DOUBLE_C(10), .min = OPT_DOUBLE_C(-10), - .precision = OPT_U32_C(0), + .precision = OPT_I32_C(0), .expect = 5, .expectMax = OPT_U64_C(31)}, {.value = -5, .max = OPT_DOUBLE_C(10), .min = OPT_DOUBLE_C(-10), - .precision = OPT_U32_C(2), + .precision = OPT_I32_C(2), .expect = 500, .expectMax = OPT_U64_C(4095)}, {.value = 1E-30, .max = OPT_DOUBLE_C(10E-30), .min = OPT_DOUBLE_C(1E-30), - .precision = OPT_U32_C(35), + .precision = OPT_I32_C(35), // Applying min/max/precision result in a domain needing >= 53 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 1E-30, .max = OPT_DOUBLE_C(10E-30), .min = OPT_DOUBLE_C(1E-30), - .precision = OPT_U32_C(35), + .precision = OPT_I32_C(35), // Applying min/max/precision result in a domain needing >= 53 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, @@ -487,7 +487,7 @@ static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { {.value = DOUBLE_MIN_SAFE_INT, .max = OPT_DOUBLE_C(DOUBLE_MAX_SAFE_INT), .min = OPT_DOUBLE_C(DOUBLE_MIN_SAFE_INT), - .precision = OPT_U32_C(0), + .precision = OPT_I32_C(0), .expect = 0, // Applying min/max/precision result in a domain needing >= 53 bits to represent. // For range v2, expect an error. @@ -495,19 +495,19 @@ static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { {.value = 900719925474099.6, .max = OPT_DOUBLE_C(900719925474100.0), .min = OPT_DOUBLE_C(900719925474099.0), - .precision = OPT_U32_C(0), + .precision = OPT_I32_C(0), .expect = 0, .expectMax = OPT_U64_C(1)}, // Domain size is small but min/max * 10^precision loses precision. {.value = 900719925474099.6, .max = OPT_DOUBLE_C(900719925474100.0), .min = OPT_DOUBLE_C(900719925474099.0), - .precision = OPT_U32_C(1), + .precision = OPT_I32_C(1), .expectError = "Invalid upper bound for double precision. Absolute"}, {.value = -900719925474099.6, .max = OPT_DOUBLE_C(-900719925474099.0), .min = OPT_DOUBLE_C(-900719925474100.0), - .precision = OPT_U32_C(1), + .precision = OPT_I32_C(1), .expectError = "Invalid lower bound for double precision. Absolute"}, // 2^52 // The expected values increase by 4503599627370496 * 2^(i-52) + j @@ -516,7 +516,7 @@ static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { {.value = 0, .max = OPT_DOUBLE_C(4503599627370496), .min = OPT_DOUBLE_C(-4503599627370496), - .precision = OPT_U32_C(0), + .precision = OPT_I32_C(0), .expect = 0, // Applying min/max/precision result in a domain needing >= 53 bits to represent. // For range v2, expect an error. @@ -525,25 +525,25 @@ static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { {.value = -1, .min = OPT_DOUBLE_C(0), .max = OPT_DOUBLE_C(200), - .precision = OPT_U32_C(1), + .precision = OPT_I32_C(1), .expectError = "greater than or equal to the minimum value"}, {.value = -1, .min = OPT_DOUBLE_C(0), .max = OPT_DOUBLE_C(201), - .precision = OPT_U32_C(1), + .precision = OPT_I32_C(1), .expectError = "less than or equal to the maximum value"}, {// Expect error due to precision exceeding INT32_MAX. .value = 1, .min = OPT_DOUBLE_C(1), .max = OPT_DOUBLE_C(2), - .precision = OPT_U32_C((uint32_t)INT32_MAX + 1), - .expectError = "Precision cannot be greater than 2147483647"}, + .precision = OPT_I32_C(-1), + .expectError = "Precision must be non-negative"}, {// Expect error due to precision exceeding max finite double. // The largest double value is 1.7976931348623157x10^308. 10^309 results in infinity. .value = 1, .min = OPT_DOUBLE_C(0), .max = OPT_DOUBLE_C(1), - .precision = OPT_U32_C(309), + .precision = OPT_I32_C(309), .expectError = "Precision is too large"}}; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { @@ -588,7 +588,7 @@ typedef struct { mc_dec128 value; mc_optional_dec128_t min; mc_optional_dec128_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; mlib_int128 expect; const char *expectError; bool use_range_v1; // By default, use range v2. @@ -772,29 +772,29 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { ERROR_CASE(MC_DEC128_C(1), OPT_NULLOPT, OPT_MC_DEC128(MC_DEC128_C(2)), - OPT_U32(5), + OPT_I32(5), "min, max, and precision must all be set or must all be unset"), ERROR_CASE(MC_DEC128_C(1), OPT_MC_DEC128(MC_DEC128_C(0)), OPT_NULLOPT, - OPT_U32(5), + OPT_I32(5), "min, max, and precision must all be set or must all be unset"), ERROR_CASE(MC_DEC128_C(1), OPT_MC_DEC128(MC_DEC128_C(2)), OPT_MC_DEC128(MC_DEC128_C(1)), - OPT_U32(5), + OPT_I32(5), "The minimum value must be less than the maximum value"), ERROR_CASE(MC_DEC128_C(1), OPT_MC_DEC128(MC_DEC128_C(2)), OPT_MC_DEC128(MC_DEC128_C(3)), - OPT_U32(5), + OPT_I32(5), "Value must be greater than or equal to the minimum value " "and less than or equal to the maximum value"), ERROR_CASE(MC_DEC128_C(4), OPT_MC_DEC128(MC_DEC128_C(2)), OPT_MC_DEC128(MC_DEC128_C(3)), - OPT_U32(5), + OPT_I32(5), "Value must be greater than or equal to the minimum value " "and less than or equal to the maximum value"), @@ -827,7 +827,7 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .value = mc_dec128_from_string(Value), \ .min = OPT_MC_DEC128(MC_DEC128_C(-100000)), \ .max = OPT_MC_DEC128(MC_DEC128_C(100000)), \ - .precision = OPT_U32(Precision), \ + .precision = OPT_I32(Precision), \ .expect = MLIB_INT128(Expect), \ } ASSERT_EIBP("3.141592653589E-1", 10, 1000003141592653), @@ -845,7 +845,7 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .value = mc_dec128_from_string(Value), \ .min = OPT_MC_DEC128(MC_DEC128_C(-100000)), \ .max = OPT_MC_DEC128(mc_dec128_from_string("1E22")), \ - .precision = OPT_U32(Precision), \ + .precision = OPT_I32(Precision), \ .expect = mlib_int128_from_string(Expect, NULL), \ } @@ -862,7 +862,7 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .value = mc_dec128_from_string(#Value), \ .min = OPT_MC_DEC128(MC_DEC128_C(-100000)), \ .max = OPT_MC_DEC128(MC_DEC128_C(100000)), \ - .precision = OPT_U32(Precision), \ + .precision = OPT_I32(Precision), \ .expect = MLIB_INT128_CAST(Expect), \ } ASSERT_EIBP(3.141592653589, 1, 1000031), @@ -879,7 +879,7 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .value = mc_dec128_from_string(#Val), \ .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), \ - .precision = OPT_U32(Precision), \ + .precision = OPT_I32(Precision), \ .expect = MLIB_INT128_CAST(Expect), \ } @@ -891,13 +891,13 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .value = mc_dec128_from_string(#Val), \ .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), \ - .precision = OPT_U32(Precision), \ + .precision = OPT_I32(Precision), \ .expect = Expect, \ .use_range_v1 = true, \ }, \ (Decimal128Test) { \ .value = mc_dec128_from_string(#Val), .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ - .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), .precision = OPT_U32(Precision), \ + .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), .precision = OPT_I32(Precision), \ .expectError = "The domain of decimal values specified by the min, max, and precision " \ "cannot be represented in fewer than 128 bits" \ } @@ -907,13 +907,13 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .value = mc_dec128_from_string(#Val), \ .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), \ - .precision = OPT_U32(Precision), \ + .precision = OPT_I32(Precision), \ .expect = Expect, \ .use_range_v1 = true, \ }, \ (Decimal128Test) { \ .value = mc_dec128_from_string(#Val), .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ - .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), .precision = OPT_U32(Precision), .expectError = Error \ + .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), .precision = OPT_I32(Precision), .expectError = Error \ } ASSERT_EIBB(0, 1, -1, 3, 1000), @@ -972,13 +972,13 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { {// Expect error due to precision exceeding INT32_MAX. .min = OPT_MC_DEC128(MC_DEC128_C(1)), .max = OPT_MC_DEC128(MC_DEC128_C(2)), - .precision = OPT_U32((uint32_t)INT32_MAX + 1), - .expectError = "Precision cannot be greater than 2147483647"}, + .precision = OPT_I32(-1), + .expectError = "Precision must be non-negative"}, {// Expect error due to precision exceeding max finite Decimal128. // The largest decimal128 value is 9.99999...x10^6144. 10^6145 results in infinity. .min = OPT_MC_DEC128(MC_DEC128_C(0)), .max = OPT_MC_DEC128(MC_DEC128_C(1)), - .precision = OPT_U32(6145), + .precision = OPT_I32(6145), .expectError = "Precision is too large"}}; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { diff --git a/test/test-mc-range-mincover.c b/test/test-mc-range-mincover.c index d7d2c29ad..2214c66c7 100644 --- a/test/test-mc-range-mincover.c +++ b/test/test-mc-range-mincover.c @@ -63,7 +63,7 @@ typedef struct { size_t sparsity; mc_optional_double_t min; mc_optional_double_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; const char *expectMincoverStrings[MAX_MINCOVER_STRINGS]; const char *expectError; } DoubleTest; @@ -77,7 +77,7 @@ typedef struct { size_t sparsity; mc_optional_dec128_t min; mc_optional_dec128_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; const char *expectMincoverStrings[MAX_MINCOVER_STRINGS]; const char *expectError; } Decimal128Test; @@ -103,7 +103,7 @@ static mc_mincover_t *_test_getMincover32(void *tests, size_t idx, mongocrypt_st .min = test->min, .max = test->max, .sparsity = test->sparsity, - .trimFactor = OPT_U32(test->trimFactor)}, + .trimFactor = OPT_I32(test->trimFactor)}, status, use_range_v2); } @@ -122,7 +122,7 @@ static mc_mincover_t *_test_getMincover64(void *tests, size_t idx, mongocrypt_st .min = test->min, .max = test->max, .sparsity = test->sparsity, - .trimFactor = OPT_U32(trimFactor)}, + .trimFactor = OPT_I32(trimFactor)}, status, use_range_v2); } @@ -143,7 +143,7 @@ static mc_mincover_t *_test_getMincoverDouble_helper(void *tests, size_t idx, mo .min = test->precision.set ? test->min : (mc_optional_double_t){0}, .max = test->precision.set ? test->max : (mc_optional_double_t){0}, .precision = test->precision, - .trimFactor = OPT_U32(trimFactor)}, + .trimFactor = OPT_I32(trimFactor)}, status, use_range_v2); } @@ -165,7 +165,7 @@ static mc_mincover_t *_test_getMincoverDecimal128_helper(void *tests, size_t idx .min = test->precision.set ? test->min : (mc_optional_dec128_t){0}, .max = test->precision.set ? test->max : (mc_optional_dec128_t){0}, .precision = test->precision, - .trimFactor = OPT_U32(trimFactor)}, + .trimFactor = OPT_I32(trimFactor)}, status, use_range_v2); } diff --git a/test/test-mc-rangeopts.c b/test/test-mc-rangeopts.c index 24ca54346..ea9ce601c 100644 --- a/test/test-mc-rangeopts.c +++ b/test/test-mc-rangeopts.c @@ -29,7 +29,7 @@ static void test_mc_RangeOpts_parse(_mongocrypt_tester_t *tester) { mc_optional_int32_t expectMax; int64_t expectSparsity; mc_optional_uint32_t expectPrecision; - mc_optional_uint32_t expectTrimFactor; + mc_optional_int32_t expectTrimFactor; bool useRangeV2; } testcase; @@ -70,7 +70,7 @@ static void test_mc_RangeOpts_parse(_mongocrypt_tester_t *tester) { .in = RAW_STRING({"trimFactor" : 1, "sparsity" : {"$numberLong" : "1"}}), .useRangeV2 = true, .expectSparsity = 1, - .expectTrimFactor = OPT_U32(1)}, + .expectTrimFactor = OPT_I32(1)}, {.desc = "Does not require sparsity", .in = RAW_STRING({"min" : 123, "max" : 456}), .useRangeV2 = true, diff --git a/test/test-mongocrypt-assert-match-bson.c b/test/test-mongocrypt-assert-match-bson.c index d253eec05..4230c0f9f 100644 --- a/test/test-mongocrypt-assert-match-bson.c +++ b/test/test-mongocrypt-assert-match-bson.c @@ -888,22 +888,16 @@ const char *_mongoc_bson_type_to_str(bson_type_t t) { } } -void _assert_match_bson(const bson_t *doc, const bson_t *pattern) { +bool _check_match_bson(const bson_t *doc, const bson_t *pattern, char *errmsg, size_t errmsg_len) { // Set `retain_dots_in_keys` to interpret a pattern key "db.test" as a key, rather than a key path. match_ctx_t ctx = {.retain_dots_in_keys = true}; - if (!match_bson_with_ctx(doc, pattern, &ctx)) { - char *doc_str = doc ? bson_as_json(doc, NULL) : NULL; - char *pattern_str = bson_as_json(pattern, NULL); - - TEST_ERROR("ASSERT_MATCH failed with document:\n\n" - "%s\n" - "pattern:\n%s\n" - "%s\n", - doc_str ? doc_str : "{}", - pattern_str, - ctx.errmsg); - - bson_free(doc_str); - bson_free(pattern_str); + bool matched = match_bson_with_ctx(doc, pattern, &ctx); + if (matched) { + bson_strncpy(errmsg, "", errmsg_len); + } else { + if (matched) { + bson_strncpy(errmsg, ctx.errmsg, errmsg_len); + } } + return matched; } diff --git a/test/test-mongocrypt-assert-match-bson.h b/test/test-mongocrypt-assert-match-bson.h index 720f50984..12bfb81c2 100644 --- a/test/test-mongocrypt-assert-match-bson.h +++ b/test/test-mongocrypt-assert-match-bson.h @@ -20,6 +20,27 @@ #include /* Copied from libmongoc. */ -void _assert_match_bson(const bson_t *doc, const bson_t *pattern); +bool _check_match_bson(const bson_t *doc, const bson_t *pattern, char *errmsg, size_t errmsg_len); + +#define _assert_match_bson(doc, pattern) \ + 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); \ + \ + TEST_ERROR("ASSERT_MATCH failed with document:\n\n" \ + "%s\n" \ + "pattern:\n%s\n" \ + "%s\n", \ + doc_str ? doc_str : "{}", \ + pattern_str, \ + errmsg); \ + \ + bson_free(doc_str); \ + bson_free(pattern_str); \ + } \ + } else \ + (void)0 #endif /* TEST_MONGOCRYPT_ASSERT_MATCH_BSON_H */ diff --git a/test/test-mongocrypt-ctx-encrypt.c b/test/test-mongocrypt-ctx-encrypt.c index ccece1d1c..e362846a7 100644 --- a/test/test-mongocrypt-ctx-encrypt.c +++ b/test/test-mongocrypt-ctx-encrypt.c @@ -2169,7 +2169,7 @@ static void _test_encrypt_fle2_find_range_payload_decimal128_precision(_mongocry } #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT -static mongocrypt_t *_crypt_with_rng(_test_rng_data_source *rng_source, bool use_v2) { +static mongocrypt_t *_crypt_with_rng(_test_rng_data_source *rng_source, bool use_v2, bool use_range_v2) { mongocrypt_t *crypt; mongocrypt_binary_t *localkey; /* localkey_data is the KEK used to encrypt the keyMaterial @@ -2194,7 +2194,12 @@ static mongocrypt_t *_crypt_with_rng(_test_rng_data_source *rng_source, bool use // TODO(MONGOCRYPT-572): This test uses the QEv1 protocol. Update this test for QEv2 or remove. Note: decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, use_v2), crypt); - ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + if (use_range_v2) { + ASSERT_OK(mongocrypt_setopt_use_range_v2(crypt), crypt); + ASSERT_OK(mongocrypt_init(crypt), crypt); + } else { + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + } return crypt; } @@ -2214,6 +2219,7 @@ typedef struct { const char *expect_init_error; bool is_expression; bool use_v2; + bool use_range_v2; } ee_testcase; static void ee_testcase_run(ee_testcase *tc) { @@ -2224,13 +2230,16 @@ static void ee_testcase_run(ee_testcase *tc) { if (tc->rng_data.buf.len > 0) { // Use fixed data for random number generation to produce deterministic // results. - crypt = _crypt_with_rng(&tc->rng_data, tc->use_v2); + crypt = _crypt_with_rng(&tc->rng_data, tc->use_v2, tc->use_range_v2); } else { tester_mongocrypt_flags flags = TESTER_MONGOCRYPT_DEFAULT; // TODO(MONGOCRYPT-572): Remove tests cases for QEv1. if (!tc->use_v2) { flags |= TESTER_MONGOCRYPT_WITH_CRYPT_V1; } + if (tc->use_range_v2) { + flags |= TESTER_MONGOCRYPT_WITH_RANGE_V2; + } crypt = _mongocrypt_tester_mongocrypt(flags); } mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -2460,17 +2469,10 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { * Second 16 bytes are IV for 'p' field in FLE2InsertUpdatePayload * Third 16 bytes are IV for 'v' field in FLE2InsertUpdatePayload */ -#ifdef MONGOCRYPT_LITTLE_ENDIAN #define RNG_DATA \ "\x01\x00\x00\x00\x00\x00\x00\x00" \ "\xc7\x43\xd6\x75\x76\x9e\xa7\x88\xd5\xe5\xc4\x40\xdb\x24\x0d\xf9" \ "\x4c\xd9\x64\x10\x43\x81\xe6\x61\xfa\x1f\xa0\x5c\x49\x8e\xad\x21" -#else -#define RNG_DATA \ - "\x00\x00\x00\x00\x00\x00\x00\x01" \ - "\xc7\x43\xd6\x75\x76\x9e\xa7\x88\xd5\xe5\xc4\x40\xdb\x24\x0d\xf9" \ - "\x4c\xd9\x64\x10\x43\x81\xe6\x61\xfa\x1f\xa0\x5c\x49\x8e\xad\x21" -#endif /* MONGOCRYPT_LITTLE_ENDIAN */ uint8_t rng_data[] = RNG_DATA; tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data, .len = sizeof(rng_data) - 1u}}; #undef RNG_DATA @@ -2493,17 +2495,10 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { * Second 16 bytes are IV for 'p' field in FLE2InsertUpdatePayload * Third 16 bytes are IV for 'v' field in FLE2InsertUpdatePayload */ -#ifdef MONGOCRYPT_LITTLE_ENDIAN #define RNG_DATA \ "\x01\x00\x00\x00\x00\x00\x00\x00" \ "\xc7\x43\xd6\x75\x76\x9e\xa7\x88\xd5\xe5\xc4\x40\xdb\x24\x0d\xf9" \ "\x4c\xd9\x64\x10\x43\x81\xe6\x61\xfa\x1f\xa0\x5c\x49\x8e\xad\x21" -#else -#define RNG_DATA \ - "\x00\x00\x00\x00\x00\x00\x00\x01" \ - "\xc7\x43\xd6\x75\x76\x9e\xa7\x88\xd5\xe5\xc4\x40\xdb\x24\x0d\xf9" \ - "\x4c\xd9\x64\x10\x43\x81\xe6\x61\xfa\x1f\xa0\x5c\x49\x8e\xad\x21" -#endif /* MONGOCRYPT_LITTLE_ENDIAN */ uint8_t rng_data[] = RNG_DATA; tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data, .len = sizeof(rng_data) - 1u}}; #undef RNG_DATA @@ -5217,6 +5212,11 @@ static void autoencryption_test_run(autoencryption_test *aet) { } static void _test_no_trimFactor(_mongocrypt_tester_t *tester) { + if (!_aes_ctr_is_supported_by_os) { + printf("Common Crypto with no CTR support detected. Skipping."); + return; + } + mongocrypt_binary_t *key123 = TEST_FILE("./test/data/keys/12345678123498761234123456789012-local-document.json"); // Test insert. @@ -5256,6 +5256,226 @@ static void _test_no_trimFactor(_mongocrypt_tester_t *tester) { } } +// `lookup_payload_bson` looks up a payload from the BSON document `result` at path `path`. +// The BSON portion of the payload is parsed into `payload_bson`. +static void lookup_payload_bson(mongocrypt_binary_t *result, char *path, bson_t *payload_bson) { + bson_t result_bson; + ASSERT(_mongocrypt_binary_to_bson(result, &result_bson)); + + // Iterate to the path. + bson_iter_t iter; + ASSERT(bson_iter_init(&iter, &result_bson)); + if (!bson_iter_find_descendant(&iter, path, &iter)) { + TEST_ERROR("Unable to find path '%s'. Got: %s", path, tmp_json(&result_bson)); + } + + _mongocrypt_buffer_t buf; + ASSERT(_mongocrypt_buffer_from_binary_iter(&buf, &iter)); + ASSERT_CMPINT((int)buf.subtype, ==, (int)BSON_SUBTYPE_ENCRYPTED); + + // Expect a payload to start with an identifier byte. Expect the remainder to be BSON. + ASSERT_CMPUINT32(buf.len, >, 0); + ASSERT(bson_init_static(payload_bson, buf.data + 1, buf.len - 1)); +} + +// Test that the crypto params added in SERVER-91889 are sent for "range" payloads. +static void _test_range_sends_cryptoParams(_mongocrypt_tester_t *tester) { + if (!_aes_ctr_is_supported_by_os) { + printf("Common Crypto with no CTR support detected. Skipping."); + return; + } + + // Set up key data used for test. + _mongocrypt_buffer_t key123_id; + _mongocrypt_buffer_copy_from_hex(&key123_id, "12345678123498761234123456789012"); + mongocrypt_binary_t *key123 = TEST_FILE("./test/data/keys/12345678123498761234123456789012-local-document.json"); + // Use fixed random data for deterministic results. + mongocrypt_binary_t *rng_data = TEST_BIN(1024); + + // Test explicit insert. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for insert"; + tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data->data, .len = rng_data->len}}; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + tc.range_opts = TEST_BSON("{'min': 0, 'max': 1234567, 'sparsity': { '$numberLong': '3' }, 'trimFactor': 4}"); + tc.msg = TEST_BSON("{'v': 123456}"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON(BSON_STR({"sp" : 3, "tf" : 4, "mn" : 0, "mx" : 1234567, "pn" : {"$exists" : false}}))); + } + } + + // Test explicit insert with defaults. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for insert with correct defaults"; + tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data->data, .len = rng_data->len}}; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + // Use defaults for `sparsity` (2), and `trimFactor` (6). + tc.range_opts = TEST_BSON("{'min': 0, 'max': 1234567}"); + tc.msg = TEST_BSON("{'v': 123456}"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-insert-int32-defaults/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON(BSON_STR({"sp" : 2, "tf" : 6, "mn" : 0, "mx" : 1234567, "pn" : {"$exists" : false}}))); + } + } + + // Test explicit insert of double. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for insert for double"; + mongocrypt_binary_t *rng_data = TEST_BIN(1024); + tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data->data, .len = rng_data->len}}; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + tc.range_opts = TEST_BSON( + "{'min': 0.0, 'max': 1234567.0, 'precision': 2, 'sparsity': { '$numberLong': '3' }, 'trimFactor': 4}"); + tc.msg = TEST_BSON("{'v': 123456.0}"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-insert-double/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v", &payload_bson); + _assert_match_bson(&payload_bson, + TMP_BSON(BSON_STR({"sp" : 3, "tf" : 4, "mn" : 0.0, "mx" : 1234567.0, "pn" : 2}))); + } + } + + // Test explicit find. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for find with correct defaults"; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; + tc.is_expression = true; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + tc.range_opts = + TEST_BSON("{'min': 0, 'max': 1234567}"); // Use defaults for `sparsity` (2), and `trimFactor` (6). + tc.msg = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-find-int32-defaults/to-encrypt.json"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-find-int32-defaults/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v.$and.0.age.$gte", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON(BSON_STR({"sp" : 2, "tf" : 6, "mn" : 0, "mx" : 1234567, "pn" : {"$exists" : false}}))); + } + } + + // Test explicit find with defaults. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for find"; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; + tc.is_expression = true; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + tc.range_opts = TEST_BSON("{'min': 0, 'max': 1234567, 'sparsity': { '$numberLong': '3' }, 'trimFactor': 4}"); + tc.msg = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-find-int32/to-encrypt.json"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-find-int32/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v.$and.0.age.$gte", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON(BSON_STR({"sp" : 3, "tf" : 4, "mn" : 0, "mx" : 1234567, "pn" : {"$exists" : false}}))); + } + } + + // Test automatic insert of int32. + { + autoencryption_test aet = { + .desc = "'range' sends crypto params for insert", + .rng_data = {.buf = {.data = rng_data->data, .len = rng_data->len}}, + .cmd = TEST_FILE("./test/data/range-sends-cryptoParams/auto-insert-int32/cmd.json"), + .encrypted_field_map = + TEST_FILE("./test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-field-map.json"), + .mongocryptd_reply = + TEST_FILE("./test/data/range-sends-cryptoParams/auto-insert-int32/mongocryptd-reply.json"), + .keys_to_feed = {key123}, + .expect = TEST_FILE("./test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-payload.json")}; + + autoencryption_test_run(&aet); + + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(aet.expect, "documents.0.encrypted", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON( + BSON_STR({"sp" : 2, "tf" : 6, "mn" : -2147483648, "mx" : 2147483647, "pn" : {"$exists" : false}}))); + } + } + + // Test automatic find of int32. + { + autoencryption_test aet = { + .desc = "'range' sends crypto params for find", + .cmd = TEST_FILE("./test/data/range-sends-cryptoParams/auto-find-int32/cmd.json"), + .encrypted_field_map = + TEST_FILE("./test/data/range-sends-cryptoParams/auto-find-int32/encrypted-field-map.json"), + .mongocryptd_reply = + TEST_FILE("./test/data/range-sends-cryptoParams/auto-find-int32/mongocryptd-reply.json"), + .keys_to_feed = {key123}, + .expect = TEST_FILE("./test/data/range-sends-cryptoParams/auto-find-int32/encrypted-payload.json")}; + + autoencryption_test_run(&aet); + + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(aet.expect, "filter.$and.0.encrypted.$gte", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON( + BSON_STR({"sp" : 2, "tf" : 6, "mn" : -2147483648, "mx" : 2147483647, "pn" : {"$exists" : false}}))); + } + } + + _mongocrypt_buffer_cleanup(&key123_id); +} + void _mongocrypt_tester_install_ctx_encrypt(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_explicit_encrypt_init); INSTALL_TEST(_test_encrypt_init); @@ -5338,4 +5558,5 @@ void _mongocrypt_tester_install_ctx_encrypt(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_bulkWrite); INSTALL_TEST(_test_rangePreview_fails); INSTALL_TEST(_test_no_trimFactor); + INSTALL_TEST(_test_range_sends_cryptoParams); } diff --git a/test/test-mongocrypt-marking.c b/test/test-mongocrypt-marking.c index 0a6cc7114..28ec04710 100644 --- a/test/test-mongocrypt-marking.c +++ b/test/test-mongocrypt-marking.c @@ -444,6 +444,17 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te }), .expectedError = "Trim factor must be less than the number of bits (6) used to represent an element of the domain"}, + {.description = "Negative trim factor fails", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : -1 + }), + .expectedErrorAtParseTime = "'trimFactor' must be non-negative"}, {.description = "Int64 Bounds included", .findSpecJSON = RAW_STRING({ "lowerBound" : {"$numberLong" : "0"},