Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MONGOCRYPT-758 Implement FLE2IndexedTextEncryptedValue parse & decrypt #936

Merged
merged 12 commits into from
Jan 24, 2025
5 changes: 4 additions & 1 deletion src/mc-fle-blob-subtype-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ typedef enum {
MC_SUBTYPE_FLE2FindRangePayloadV2 = 13,
MC_SUBTYPE_FLE2IndexedEqualityEncryptedValueV2 = 14,
MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2 = 15,
MC_SUBTYPE_FLE2UnindexedEncryptedValueV2 = 16
MC_SUBTYPE_FLE2UnindexedEncryptedValueV2 = 16,

/* Text Search Subtypes */
MC_SUBTYPE_FLE2IndexedTextEncryptedValue = 17,
} mc_fle_blob_subtype_t;

#endif /* MC_FLE_BLOB_SUBTYPE_PRIVATE_H */
54 changes: 53 additions & 1 deletion src/mc-fle2-payload-iev-private-v2.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "mongocrypt-status-private.h"

/*
* FLE2IndexedEqualityEncryptedValueV2 and FLE2IndexedRangeEncryptedValueV2
* FLE2IndexedEqualityEncryptedValueV2, FLE2IndexedRangeEncryptedValueV2, and FLEIndexedTextEncryptedValue
* share a common internal implementation.
*
* Lifecycle:
Expand Down Expand Up @@ -78,19 +78,43 @@
* 1/ `edge_count` is introduced as an octet following `original_bson_type`.
* 2/ Rather than a single metadata block, we have {edge_count} blocks.
*
* FLE2IndexedTextEncryptedValue has the following data layout:
*
* struct FLE2IndexedTextEncryptedValue {
* uint8_t fle_blob_subtype = 17;
* uint8_t S_KeyId[16];
* uint8_t original_bson_type;
* uint8_t edge_count;
* uint8_t substr_tag_count;
* uint8_t suffix_tag_count;
* uint8_t ServerEncryptedValue[ServerEncryptedValue.length];
* FLE2TagAndEncryptedMetadataBlock exact_metadata;
* FLE2TagAndEncryptedMetadataBlock substr_metadata[substr_tag_count];
* FLE2TagAndEncryptedMetadataBlock suffix_metadata[suffix_tag_count];
* FLE2TagAndEncryptedMetadataBlock prefix_metadata[edge_count - suffix_tag_count - substr_tag_count - 1];
* }
* The main difference in this format is that we split `metadata` into 4
* sections, one for each text search index type. We add two octets,
* `substr_tag_count` and `suffix_tag_count`, following `edge_count`
* in order to track the delineation of the metadata. Similarly to
* FLE2IndexedEqualityEncryptedValueV2, we have `edge_count` total
* blocks.
*/

typedef enum {
kFLE2IEVTypeInitV2,
kFLE2IEVTypeEqualityV2,
kFLE2IEVTypeRangeV2,
kFLE2IEVTypeText,
} _mc_fle2_iev_v2_type;

typedef struct _mc_FLE2IndexedEncryptedValueV2_t {
// Raw payload values
uint8_t fle_blob_subtype;
uint8_t bson_value_type;
uint8_t edge_count;
uint8_t substr_tag_count;
uint8_t suffix_tag_count;
_mongocrypt_buffer_t S_KeyId;
_mongocrypt_buffer_t ServerEncryptedValue;

Expand Down Expand Up @@ -182,6 +206,15 @@ const _mongocrypt_buffer_t *mc_FLE2IndexedEncryptedValueV2_get_ClientValue(const
uint8_t mc_FLE2IndexedEncryptedValueV2_get_edge_count(const mc_FLE2IndexedEncryptedValueV2_t *iev,
mongocrypt_status_t *status);

uint8_t mc_FLE2IndexedEncryptedValueV2_get_substr_tag_count(const mc_FLE2IndexedEncryptedValueV2_t *iev,
mongocrypt_status_t *status);

uint8_t mc_FLE2IndexedEncryptedValueV2_get_suffix_tag_count(const mc_FLE2IndexedEncryptedValueV2_t *iev,
mongocrypt_status_t *status);

uint8_t mc_FLE2IndexedEncryptedValueV2_get_prefix_tag_count(const mc_FLE2IndexedEncryptedValueV2_t *iev,
mongocrypt_status_t *status);

bool mc_FLE2IndexedEncryptedValueV2_get_edge(const mc_FLE2IndexedEncryptedValueV2_t *iev,
mc_FLE2TagAndEncryptedMetadataBlock_t *out,
const uint8_t edge_index,
Expand All @@ -191,6 +224,25 @@ bool mc_FLE2IndexedEncryptedValueV2_get_metadata(const mc_FLE2IndexedEncryptedVa
mc_FLE2TagAndEncryptedMetadataBlock_t *out,
mongocrypt_status_t *status);

bool mc_FLE2IndexedEncryptedValueV2_get_exact_metadata(const mc_FLE2IndexedEncryptedValueV2_t *iev,
mc_FLE2TagAndEncryptedMetadataBlock_t *out,
mongocrypt_status_t *status);

bool mc_FLE2IndexedEncryptedValueV2_get_substr_metadata(const mc_FLE2IndexedEncryptedValueV2_t *iev,
mc_FLE2TagAndEncryptedMetadataBlock_t *out,
const uint8_t block_index,
mongocrypt_status_t *status);

bool mc_FLE2IndexedEncryptedValueV2_get_suffix_metadata(const mc_FLE2IndexedEncryptedValueV2_t *iev,
mc_FLE2TagAndEncryptedMetadataBlock_t *out,
const uint8_t block_index,
mongocrypt_status_t *status);

bool mc_FLE2IndexedEncryptedValueV2_get_prefix_metadata(const mc_FLE2IndexedEncryptedValueV2_t *iev,
mc_FLE2TagAndEncryptedMetadataBlock_t *out,
const uint8_t block_index,
mongocrypt_status_t *status);

void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *iev);

#endif /* MONGOCRYPT_INDEXED_ENCRYPTED_VALUE_PRIVATE_V2_H */
Loading
Loading