2323#include "mc-reader-private.h"
2424#include "mc-tokens-private.h"
2525#include "mc-writer-private.h"
26+ #include <mongocrypt-util-private.h>
2627#include <stdint.h>
2728
28- typedef enum {
29- kTypeInit ,
30- kTypeEquality ,
31- kTypeRange ,
32- } _mc_fle2_iev_v2_type ;
33-
34- struct _mc_FLE2IndexedEncryptedValueV2_t {
35- // Raw payload values
36- uint8_t fle_blob_subtype ;
37- uint8_t bson_value_type ;
38- uint8_t edge_count ;
39- _mongocrypt_buffer_t S_KeyId ;
40- _mongocrypt_buffer_t ServerEncryptedValue ;
41-
42- // Decode State
43- _mc_fle2_iev_v2_type type ;
44- bool ClientEncryptedValueDecoded ;
45- bool ClientValueDecoded ;
46-
47- // Populated during _add_S_Key
48- // DecryptedServerEncryptedValue := DecryptCTR(S_Key, ServerEncryptedValue)
49- _mongocrypt_buffer_t DecryptedServerEncryptedValue ;
50-
51- // Views on DecryptedServerEncryptedValue (DSEV)
52- _mongocrypt_buffer_t K_KeyId ; // First 16 octets, UUID
53- _mongocrypt_buffer_t ClientEncryptedValue ; // Remainder of DSEV
54-
55- // Populated during _add_K_Key
56- // ClientValue := DecryptCBCAEAD(K_Key, ClientEncryptedValue, AD=K_KeyId)
57- _mongocrypt_buffer_t ClientValue ;
58-
59- mc_FLE2TagAndEncryptedMetadataBlock_t * metadata ;
60- };
61-
62- #define kMetadataLen 96U // encCount(32) + tag(32) + encZeros(32)
6329#define kMinServerEncryptedValueLen 17U // IV(16) + EncryptCTR(1byte)
6430#define kMinSEVAndMetadataLen (kMinServerEncryptedValueLen + kMetadataLen)
6531
@@ -76,7 +42,7 @@ bson_type_t mc_FLE2IndexedEncryptedValueV2_get_bson_value_type(const mc_FLE2Inde
7642 mongocrypt_status_t * status ) {
7743 BSON_ASSERT_PARAM (iev );
7844
79- if (iev -> type == kTypeInit ) {
45+ if (iev -> type == kFLE2IEVTypeInitV2 ) {
8046 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_bson_value_type "
8147 "must be called after "
8248 "mc_FLE2IndexedEncryptedValueV2_parse" );
@@ -90,7 +56,7 @@ const _mongocrypt_buffer_t *mc_FLE2IndexedEncryptedValueV2_get_S_KeyId(const mc_
9056 mongocrypt_status_t * status ) {
9157 BSON_ASSERT_PARAM (iev );
9258
93- if (iev -> type == kTypeInit ) {
59+ if (iev -> type == kFLE2IEVTypeInitV2 ) {
9460 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_S_KeyId "
9561 "must be called after "
9662 "mc_FLE2IndexedEncryptedValueV2_parse" );
@@ -109,7 +75,7 @@ bool mc_FLE2IndexedEncryptedValueV2_add_S_Key(_mongocrypt_crypto_t *crypto,
10975 BSON_ASSERT_PARAM (S_Key );
11076 BSON_ASSERT_PARAM (status );
11177
112- if (iev -> type == kTypeInit ) {
78+ if (iev -> type == kFLE2IEVTypeInitV2 ) {
11379 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_add_S_Key must "
11480 "be called after "
11581 "mc_FLE2IndexedEncryptedValueV2_parse" );
@@ -315,14 +281,14 @@ uint8_t mc_FLE2IndexedEncryptedValueV2_get_edge_count(const mc_FLE2IndexedEncryp
315281 mongocrypt_status_t * status ) {
316282 BSON_ASSERT_PARAM (iev );
317283
318- if (iev -> type == kTypeInit ) {
284+ if (iev -> type == kFLE2IEVTypeInitV2 ) {
319285 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_edge_count "
320286 "must be called after "
321287 "mc_FLE2IndexedEncryptedValueV2_parse" );
322288 return 0 ;
323289 }
324290
325- if (iev -> type != kTypeRange ) {
291+ if (iev -> type != kFLE2IEVTypeRangeV2 ) {
326292 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_edge_count must be called with type range" );
327293 return 0 ;
328294 }
@@ -337,20 +303,21 @@ bool mc_FLE2IndexedEncryptedValueV2_get_edge(const mc_FLE2IndexedEncryptedValueV
337303 BSON_ASSERT_PARAM (iev );
338304 BSON_ASSERT_PARAM (out );
339305
340- if (iev -> type == kTypeInit ) {
306+ if (iev -> type == kFLE2IEVTypeInitV2 ) {
341307 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_edge "
342308 "must be called after "
343309 "mc_FLE2IndexedEncryptedValueV2_parse" );
344310 return false;
345311 }
346312
347- if (iev -> type != kTypeRange ) {
313+ if (iev -> type != kFLE2IEVTypeRangeV2 ) {
348314 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_edge must be called with type range" );
349315 return false;
350316 }
351317
352318 if (edge_index >= iev -> edge_count ) {
353- CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_edge must be called with index edge_index less than edge count" );
319+ CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_edge must be called with index edge_index less "
320+ "than edge count" );
354321 return false;
355322 }
356323
@@ -365,14 +332,14 @@ bool mc_FLE2IndexedEncryptedValueV2_get_metadata(const mc_FLE2IndexedEncryptedVa
365332 BSON_ASSERT_PARAM (iev );
366333 BSON_ASSERT_PARAM (out );
367334
368- if (iev -> type == kTypeInit ) {
335+ if (iev -> type == kFLE2IEVTypeInitV2 ) {
369336 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_metadata "
370337 "must be called after "
371338 "mc_FLE2IndexedEncryptedValueV2_parse" );
372339 return false;
373340 }
374341
375- if (iev -> type != kTypeEquality ) {
342+ if (iev -> type != kFLE2IEVTypeEqualityV2 ) {
376343 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_metadata must be called with type equality" );
377344 return false;
378345 }
@@ -393,7 +360,7 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
393360 return false;
394361 }
395362
396- if (iev -> type != kTypeInit ) {
363+ if (iev -> type != kFLE2IEVTypeInitV2 ) {
397364 CLIENT_ERR ("mc_FLE2IndexedRangeEncryptedValueV2_parse must not be "
398365 "called twice" );
399366 return false;
@@ -405,9 +372,9 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
405372 CHECK_AND_RETURN (mc_reader_read_u8 (& reader , & iev -> fle_blob_subtype , status ));
406373
407374 if (iev -> fle_blob_subtype == MC_SUBTYPE_FLE2IndexedEqualityEncryptedValueV2 ) {
408- iev -> type = kTypeEquality ;
375+ iev -> type = kFLE2IEVTypeEqualityV2 ;
409376 } else if (iev -> fle_blob_subtype == MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2 ) {
410- iev -> type = kTypeRange ;
377+ iev -> type = kFLE2IEVTypeRangeV2 ;
411378 } else {
412379 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_parse expected "
413380 "fle_blob_subtype MC_SUBTYPE_FLE2Indexed(Equality|Range)EncryptedValueV2 got: %" PRIu8 ,
@@ -424,7 +391,7 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
424391 /* Read edge_count */
425392 // Set equality edge_count to 1 as it doesn't technically exist but
426393 // there will be a singular metadata block
427- if (iev -> type == kTypeEquality ) {
394+ if (iev -> type == kFLE2IEVTypeEqualityV2 ) {
428395 iev -> edge_count = 1 ;
429396 } else {
430397 CHECK_AND_RETURN (mc_reader_read_u8 (& reader , & iev -> edge_count , status ));
@@ -462,18 +429,31 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
462429 return true;
463430}
464431
432+ static inline uint32_t mc_FLE2IndexedEncryptedValueV2_serialized_length (const mc_FLE2IndexedEncryptedValueV2_t * iev ) {
433+ // fle_blob_subtype: 1 byte
434+ // S_KeyId: UUID_LEN bytes
435+ // bson_value_type: 1 byte
436+ // if range: edge_count: 1 byte
437+ // ServerEncryptedValue: ServerEncryptedValue.len bytes
438+ // metadata: edge_count * kMetadataLen bytes
439+ return iev -> ServerEncryptedValue .len + 1 + UUID_LEN + 1 + (iev -> type == kFLE2IEVTypeRangeV2 ? 1 : 0 )
440+ + iev -> edge_count * kMetadataLen ;
441+ }
442+
465443bool mc_FLE2IndexedEncryptedValueV2_serialize (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
466444 _mongocrypt_buffer_t * buf ,
467445 mongocrypt_status_t * status ) {
468446 BSON_ASSERT_PARAM (iev );
469447 BSON_ASSERT_PARAM (buf );
470448
471- if (iev -> type != kTypeRange && iev -> type != kTypeEquality ) {
449+ if (iev -> type != kFLE2IEVTypeRangeV2 && iev -> type != kFLE2IEVTypeEqualityV2 ) {
472450 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_serialize must be called with type equality or range" );
473451 return false;
474452 }
475453
454+ uint32_t expected_len = mc_FLE2IndexedEncryptedValueV2_serialized_length (iev );
476455 mc_writer_t writer ;
456+ _mongocrypt_buffer_resize (buf , expected_len );
477457 mc_writer_init_from_buffer (& writer , buf , __FUNCTION__ );
478458
479459 // Serialize fle_blob_subtype
@@ -486,7 +466,7 @@ bool mc_FLE2IndexedEncryptedValueV2_serialize(const mc_FLE2IndexedEncryptedValue
486466 CHECK_AND_RETURN (mc_writer_write_u8 (& writer , iev -> bson_value_type , status ));
487467
488468 // Serialize edge_count (only serialized for type range)
489- if (iev -> type == kTypeRange ) {
469+ if (iev -> type == kFLE2IEVTypeRangeV2 ) {
490470 CHECK_AND_RETURN (mc_writer_write_u8 (& writer , iev -> edge_count , status ));
491471 }
492472
@@ -497,7 +477,7 @@ bool mc_FLE2IndexedEncryptedValueV2_serialize(const mc_FLE2IndexedEncryptedValue
497477 // Serialize metadata
498478 for (int i = 0 ; i < iev -> edge_count ; ++ i ) {
499479 _mongocrypt_buffer_t tmp_buf ;
500- _mongocrypt_buffer_init_size (& tmp_buf , kMetadataLen );
480+ _mongocrypt_buffer_init (& tmp_buf );
501481
502482 CHECK_AND_RETURN (mc_FLE2TagAndEncryptedMetadataBlock_serialize (& iev -> metadata [i ], & tmp_buf , status ));
503483 CHECK_AND_RETURN (mc_writer_write_buffer (& writer , & tmp_buf , kMetadataLen , status ));
@@ -506,4 +486,69 @@ bool mc_FLE2IndexedEncryptedValueV2_serialize(const mc_FLE2IndexedEncryptedValue
506486 }
507487
508488 return true;
509- }
489+ }
490+
491+ bool is_fle2_equality_indexed_supported_type (int bson_type ) {
492+ switch (bson_type ) {
493+ case BSON_TYPE_BINARY :
494+ case BSON_TYPE_CODE :
495+ case BSON_TYPE_REGEX :
496+ case BSON_TYPE_UTF8 :
497+
498+ case BSON_TYPE_INT32 :
499+ case BSON_TYPE_INT64 :
500+ case BSON_TYPE_BOOL :
501+ case BSON_TYPE_TIMESTAMP :
502+ case BSON_TYPE_DATE_TIME :
503+ case BSON_TYPE_OID :
504+
505+ case BSON_TYPE_SYMBOL :
506+ case BSON_TYPE_DBPOINTER : return true;
507+ default : // All other defined types are non-deterministic or singletons.
508+ return false;
509+ }
510+ }
511+
512+ #define CHECK (condition , msg ) \
513+ do { \
514+ if (!(condition)) { \
515+ CLIENT_ERR("mc_FLE2IndexedEncryptedValueV2_validate failed: " msg); \
516+ return false; \
517+ } \
518+ } while (0)
519+
520+ bool mc_FLE2IndexedEncryptedValueV2_validate (const mc_FLE2IndexedEncryptedValueV2_t * iev , mongocrypt_status_t * status ) {
521+ BSON_ASSERT_PARAM (iev );
522+ CHECK (iev -> type == kFLE2IEVTypeEqualityV2 , "validate only supports type equality" );
523+ CHECK (iev -> fle_blob_subtype == MC_SUBTYPE_FLE2IndexedEqualityEncryptedValueV2 ,
524+ "fle_blob_subtype does not match type" );
525+ CHECK (is_fle2_equality_indexed_supported_type (iev -> bson_value_type ), "bson_value_type is invalid" );
526+ CHECK (iev -> edge_count == 1 , "edge_count must be 1 for equality" );
527+
528+ CHECK (iev -> ServerEncryptedValue .len >= kMinServerEncryptedValueLen , "SEV.len is less than minimum" );
529+ CHECK (iev -> S_KeyId .len == UUID_LEN , "S_KeyId is not the correct length for a UUID" );
530+
531+ CHECK (!iev -> ClientValueDecoded || iev -> ClientEncryptedValueDecoded ,
532+ "Found decrypted client value without encrypted client value" );
533+ if (iev -> ClientEncryptedValueDecoded ) {
534+ const _mongocrypt_value_encryption_algorithm_t * fle2alg = _mcFLE2Algorithm ();
535+ const uint32_t DecryptedServerEncryptedValueLen =
536+ fle2alg -> get_plaintext_len (iev -> ServerEncryptedValue .len , status );
537+ if (!mongocrypt_status_ok (status )) {
538+ return false;
539+ }
540+ CHECK (iev -> DecryptedServerEncryptedValue .len == DecryptedServerEncryptedValueLen , "DSEV.len was unexpected" );
541+ CHECK (iev -> ClientEncryptedValue .len == iev -> DecryptedServerEncryptedValue .len - UUID_LEN ,
542+ "CEV.len was unexpected" );
543+ CHECK (iev -> K_KeyId .len == UUID_LEN , "K_KeyId is not the correct length for a UUID" );
544+ }
545+ if (iev -> ClientValueDecoded ) {
546+ const _mongocrypt_value_encryption_algorithm_t * fle2v2aead = _mcFLE2v2AEADAlgorithm ();
547+ const uint32_t ClientValueLen = fle2v2aead -> get_plaintext_len (iev -> ClientEncryptedValue .len , status );
548+ if (!mongocrypt_status_ok (status )) {
549+ return false;
550+ }
551+ CHECK (iev -> ClientValue .len == ClientValueLen , "ClientValue.len was unexpected" );
552+ }
553+ return mc_FLE2TagAndEncryptedMetadataBlock_validate (iev -> metadata , status );
554+ }
0 commit comments