Skip to content

Commit c15c6f0

Browse files
authored
MONGOCRYPT-788 Define FLE2FindTextPayload type (#985)
1 parent 1cad4ad commit c15c6f0

14 files changed

+1021
-71
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,15 @@ set (MONGOCRYPT_SOURCES
108108
src/mc-fle2-encryption-placeholder.c
109109
src/mc-fle2-find-equality-payload.c
110110
src/mc-fle2-find-equality-payload-v2.c
111+
src/mc-fle2-find-text-payload.c
111112
src/mc-fle2-payload-iev.c
112113
src/mc-fle2-payload-iev-v2.c
113114
src/mc-fle2-payload-uev.c
114115
src/mc-fle2-payload-uev-common.c
115116
src/mc-fle2-payload-uev-v2.c
116117
src/mc-fle2-rfds.c
117118
src/mc-fle2-tag-and-encrypted-metadata-block.c
119+
src/mc-parse-utils.c
118120
src/mc-range-edge-generation.c
119121
src/mc-range-mincover.c
120122
src/mc-range-encoding.c
@@ -469,6 +471,7 @@ set (TEST_MONGOCRYPT_SOURCES
469471
test/test-mc-fle2-encryption-placeholder.c
470472
test/test-mc-fle2-find-equality-payload-v2.c
471473
test/test-mc-fle2-find-range-payload-v2.c
474+
test/test-mc-fle2-find-text-payload.c
472475
test/test-mc-fle2-payload-iev.c
473476
test/test-mc-fle2-payload-iev-v2.c
474477
test/test-mc-fle2-payload-iup.c

src/mc-fle2-encryption-placeholder-private.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ typedef struct {
125125
uint32_t ub;
126126
} mc_FLE2SubstringInsertSpec_t;
127127

128+
bool mc_FLE2SubstringInsertSpec_parse(mc_FLE2SubstringInsertSpec_t *out,
129+
const bson_iter_t *in,
130+
mongocrypt_status_t *status);
131+
128132
/* mc_FLE2SuffixInsertSpec_t holds the parameters used to encode for suffix search. */
129133
typedef struct {
130134
// lb is the lower bound on the length of suffixes to be indexed.
@@ -133,6 +137,8 @@ typedef struct {
133137
uint32_t ub;
134138
} mc_FLE2SuffixInsertSpec_t;
135139

140+
bool mc_FLE2SuffixInsertSpec_parse(mc_FLE2SuffixInsertSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status);
141+
136142
/* mc_FLE2PrefixInsertSpec_t holds the parameters used to encode for prefix search. */
137143
typedef struct {
138144
// lb is the lower bound on the length of prefixes to be indexed.
@@ -141,6 +147,8 @@ typedef struct {
141147
uint32_t ub;
142148
} mc_FLE2PrefixInsertSpec_t;
143149

150+
bool mc_FLE2PrefixInsertSpec_parse(mc_FLE2PrefixInsertSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status);
151+
144152
/** mc_FLE2TextSearchInsertSpec_t represents the text search insert specification that is
145153
* encoded inside of a FLE2EncryptionPlaceholder. See
146154
* https://github.com/mongodb/mongo/blob/master/src/mongo/crypto/fle_field_schema.idl

src/mc-fle2-encryption-placeholder.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -502,9 +502,9 @@ bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, const bson_iter
502502

503503
#define ERROR_PREFIX "Error parsing FLE2SubstringInsertSpec: "
504504

505-
static bool mc_FLE2SubstringInsertSpec_parse(mc_FLE2SubstringInsertSpec_t *out,
506-
const bson_iter_t *in,
507-
mongocrypt_status_t *status) {
505+
bool mc_FLE2SubstringInsertSpec_parse(mc_FLE2SubstringInsertSpec_t *out,
506+
const bson_iter_t *in,
507+
mongocrypt_status_t *status) {
508508
bson_iter_t iter;
509509
bool has_mlen = false, has_ub = false, has_lb = false;
510510
BSON_ASSERT_PARAM(out);
@@ -544,8 +544,7 @@ static bool mc_FLE2SubstringInsertSpec_parse(mc_FLE2SubstringInsertSpec_t *out,
544544

545545
#define ERROR_PREFIX "Error parsing FLE2SuffixInsertSpec: "
546546

547-
static bool
548-
mc_FLE2SuffixInsertSpec_parse(mc_FLE2SuffixInsertSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status) {
547+
bool mc_FLE2SuffixInsertSpec_parse(mc_FLE2SuffixInsertSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status) {
549548
bson_iter_t iter;
550549
bool has_ub = false, has_lb = false;
551550

@@ -580,8 +579,7 @@ mc_FLE2SuffixInsertSpec_parse(mc_FLE2SuffixInsertSpec_t *out, const bson_iter_t
580579

581580
#define ERROR_PREFIX "Error parsing FLE2PrefixInsertSpec: "
582581

583-
static bool
584-
mc_FLE2PrefixInsertSpec_parse(mc_FLE2PrefixInsertSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status) {
582+
bool mc_FLE2PrefixInsertSpec_parse(mc_FLE2PrefixInsertSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status) {
585583
bson_iter_t iter;
586584
bool has_ub = false, has_lb = false;
587585
BSON_ASSERT_PARAM(out);

src/mc-fle2-find-equality-payload-v2.c

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <bson/bson.h>
1818

1919
#include "mc-fle2-find-equality-payload-private-v2.h"
20+
#include "mc-parse-utils-private.h"
2021
#include "mongocrypt-buffer-private.h"
2122
#include "mongocrypt.h"
2223

@@ -46,23 +47,7 @@ void mc_FLE2FindEqualityPayloadV2_cleanup(mc_FLE2FindEqualityPayloadV2_t *payloa
4647

4748
#define PARSE_BINARY(Name, Dest) \
4849
IF_FIELD(Name) { \
49-
bson_subtype_t subtype; \
50-
uint32_t len; \
51-
const uint8_t *data; \
52-
if (bson_iter_type(&iter) != BSON_TYPE_BINARY) { \
53-
CLIENT_ERR("Field '" #Name "' expected to be bindata, got: %d", (int)bson_iter_type(&iter)); \
54-
goto fail; \
55-
} \
56-
bson_iter_binary(&iter, &subtype, &len, &data); \
57-
if (subtype != BSON_SUBTYPE_BINARY) { \
58-
CLIENT_ERR("Field '" #Name "' expected to be bindata subtype %d, got: %d", \
59-
BSON_SUBTYPE_BINARY, \
60-
(int)subtype); \
61-
goto fail; \
62-
} \
63-
if (!_mongocrypt_buffer_copy_from_binary_iter(&out->Dest, &iter)) { \
64-
CLIENT_ERR("Unable to create mongocrypt buffer for BSON binary " \
65-
"field in '" #Name "'"); \
50+
if (!parse_bindata(BSON_SUBTYPE_BINARY, &iter, &out->Dest, status)) { \
6651
goto fail; \
6752
} \
6853
} \

src/mc-fle2-find-equality-payload.c

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <bson/bson.h>
1818

1919
#include "mc-fle2-find-equality-payload-private.h"
20+
#include "mc-parse-utils-private.h"
2021
#include "mongocrypt-buffer-private.h"
2122
#include "mongocrypt.h"
2223

@@ -47,23 +48,7 @@ void mc_FLE2FindEqualityPayload_cleanup(mc_FLE2FindEqualityPayload_t *payload) {
4748

4849
#define PARSE_BINARY(Name, Dest) \
4950
IF_FIELD(Name) { \
50-
bson_subtype_t subtype; \
51-
uint32_t len; \
52-
const uint8_t *data; \
53-
if (bson_iter_type(&iter) != BSON_TYPE_BINARY) { \
54-
CLIENT_ERR("Field '" #Name "' expected to be bindata, got: %d", (int)bson_iter_type(&iter)); \
55-
goto fail; \
56-
} \
57-
bson_iter_binary(&iter, &subtype, &len, &data); \
58-
if (subtype != BSON_SUBTYPE_BINARY) { \
59-
CLIENT_ERR("Field '" #Name "' expected to be bindata subtype %d, got: %d", \
60-
BSON_SUBTYPE_BINARY, \
61-
(int)subtype); \
62-
goto fail; \
63-
} \
64-
if (!_mongocrypt_buffer_copy_from_binary_iter(&out->Dest, &iter)) { \
65-
CLIENT_ERR("Unable to create mongocrypt buffer for BSON binary " \
66-
"field in '" #Name "'"); \
51+
if (!parse_bindata(BSON_SUBTYPE_BINARY, &iter, &out->Dest, status)) { \
6752
goto fail; \
6853
} \
6954
} \
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2025-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef MC_FLE2_FIND_TEXT_PAYLOAD_PRIVATE_H
18+
#define MC_FLE2_FIND_TEXT_PAYLOAD_PRIVATE_H
19+
20+
#include "mc-fle2-encryption-placeholder-private.h"
21+
#include "mongocrypt-buffer-private.h"
22+
#include "mongocrypt-private.h"
23+
#include "mongocrypt.h"
24+
25+
#define DEF_TEXT_SEARCH_FIND_TOKEN_SET(Type) \
26+
typedef struct { \
27+
_mongocrypt_buffer_t edcDerivedToken; \
28+
_mongocrypt_buffer_t escDerivedToken; \
29+
_mongocrypt_buffer_t serverDerivedFromDataToken; \
30+
} mc_Text##Type##FindTokenSet_t;
31+
32+
DEF_TEXT_SEARCH_FIND_TOKEN_SET(Exact);
33+
DEF_TEXT_SEARCH_FIND_TOKEN_SET(Substring);
34+
DEF_TEXT_SEARCH_FIND_TOKEN_SET(Suffix);
35+
DEF_TEXT_SEARCH_FIND_TOKEN_SET(Prefix);
36+
37+
typedef struct {
38+
struct {
39+
mc_TextExactFindTokenSet_t value;
40+
bool set;
41+
} exact; // e
42+
43+
struct {
44+
mc_TextSubstringFindTokenSet_t value;
45+
bool set;
46+
} substring; // s
47+
48+
struct {
49+
mc_TextSuffixFindTokenSet_t value;
50+
bool set;
51+
} suffix; // u
52+
53+
struct {
54+
mc_TextPrefixFindTokenSet_t value;
55+
bool set;
56+
} prefix; // p
57+
} mc_TextSearchFindTokenSets_t;
58+
59+
/**
60+
* FLE2FindTextPayload represents an FLE2 payload of a substring/suffix/prefix indexed field to
61+
* query. It is created client side.
62+
*
63+
* FLE2FindTextPayload has the following data layout:
64+
*
65+
* struct {
66+
* uint8_t fle_blob_subtype = 18;
67+
* uint8_t bson[];
68+
* } FLE2FindTextPayload;
69+
*
70+
* bson is a BSON document of this form:
71+
* {
72+
* ts: {
73+
* e: optional<TextExactFindTokenSet> // required tokens if doing full string match
74+
* s: optional<TextSubstringFindTokenSet> // required tokens if doing substring match
75+
* u: optional<TextSuffixFindTokenSet> // required tokens if doing suffix match
76+
* p: optional<TextPrefixFindTokenSet> // required tokens if doing prefix match
77+
* }
78+
* cm: <int64> // Queryable Encryption max contentionFactor
79+
* cf: <bool> // case folding parameter
80+
* df: <bool> // diacritic folding parameter
81+
* ss: optional<FLE2SubstringInsertSpec> // substring-indexing parameters (if applicable)
82+
* fs: optional<FLE2SuffixInsertSpec> // suffix-indexing parameters (if applicable)
83+
* ps: optional<FLE2PrefixInsertSpec> // prefix-indexing parameters (if applicable)
84+
* }
85+
* where for each of T in [Exact, Substring, Suffix, Prefix], Text<T>FindTokenSet is a document of form:
86+
* {
87+
* d: <binary> // EDCText<T>DerivedFromDataToken
88+
* s: <binary> // ESCText<T>DerivedFromDataToken
89+
* l: <binary> // ServerText<T>DerivedFromDataToken
90+
* }
91+
*/
92+
typedef struct {
93+
mc_TextSearchFindTokenSets_t tokenSets; // ts
94+
int64_t maxContentionFactor; // cm
95+
bool caseFold; // cf
96+
bool diacriticFold; // df
97+
98+
struct {
99+
mc_FLE2SubstringInsertSpec_t value;
100+
bool set;
101+
} substringSpec; // ss
102+
103+
struct {
104+
mc_FLE2SuffixInsertSpec_t value;
105+
bool set;
106+
} suffixSpec; // fs
107+
108+
struct {
109+
mc_FLE2PrefixInsertSpec_t value;
110+
bool set;
111+
} prefixSpec; // ps
112+
} mc_FLE2FindTextPayload_t;
113+
114+
void mc_FLE2FindTextPayload_init(mc_FLE2FindTextPayload_t *payload);
115+
116+
bool mc_FLE2FindTextPayload_parse(mc_FLE2FindTextPayload_t *out, const bson_t *in, mongocrypt_status_t *status);
117+
118+
bool mc_FLE2FindTextPayload_serialize(const mc_FLE2FindTextPayload_t *payload, bson_t *out);
119+
120+
void mc_FLE2FindTextPayload_cleanup(mc_FLE2FindTextPayload_t *payload);
121+
122+
#endif /* MC_FLE2_FIND_TEXT_PAYLOAD_PRIVATE_H */

0 commit comments

Comments
 (0)