diff options
author | sergey.galtsev <sergey.galtsev@mongodb.com> | 2022-04-08 01:00:11 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-04-08 01:27:22 +0000 |
commit | e6cce2875f3efa0c9b1443cf66efab95d5325a8f (patch) | |
tree | 066dbdda0ceb7d62d00bdbf9507fc025234c432d /src/mongo/crypto | |
parent | 0e7af76ae586749bf71928963c857cb50f760b9b (diff) | |
download | mongo-e6cce2875f3efa0c9b1443cf66efab95d5325a8f.tar.gz |
SERVER-63594 Add EDC, ESC, ECC, and ECOC test vectors
Diffstat (limited to 'src/mongo/crypto')
-rw-r--r-- | src/mongo/crypto/fle_crypto_test.cpp | 330 |
1 files changed, 213 insertions, 117 deletions
diff --git a/src/mongo/crypto/fle_crypto_test.cpp b/src/mongo/crypto/fle_crypto_test.cpp index 376ac0db6fd..0dce8b2c99f 100644 --- a/src/mongo/crypto/fle_crypto_test.cpp +++ b/src/mongo/crypto/fle_crypto_test.cpp @@ -171,119 +171,214 @@ KeyMaterial TestKeyVault::getKey(const UUID& uuid) { } } -// TODO (SERVER-63594) - regenerate test vectors and reimplement test -// -// TEST(FLETokens, TestVectors) { - -// // Level 1 -// auto collectionToken = -// FLELevel1TokenGenerator::generateCollectionsLevel1Token(getIndexKey()); - -// ASSERT_EQUALS(CollectionsLevel1Token(decodePrf( -// "ff2103ff205a36f39704f643c270c129919f008c391d9589a6d2c86a7429d0d3"_sd)), -// collectionToken); - -// ASSERT_EQUALS(ServerDataEncryptionLevel1Token(decodePrf( -// "d915ccc1eb81687fb5fc5b799f48c99fbe17e7a011a46a48901b9ae3d790656b"_sd)), -// FLELevel1TokenGenerator::generateServerDataEncryptionLevel1Token(getIndexKey())); - -// // Level 2 -// auto edcToken = FLECollectionTokenGenerator::generateEDCToken(collectionToken); -// ASSERT_EQUALS( -// EDCToken(decodePrf("167d2d2ff8e4144df37ff759db593fde0ecc7d9636f96d62dacad672eccad349"_sd)), - -// edcToken); -// auto escToken = FLECollectionTokenGenerator::generateESCToken(collectionToken); -// ASSERT_EQUALS( -// ESCToken(decodePrf("bfd480f1658f49f48985734737bc07d0bc36b88210277605c55ff3c9c3ef50b0"_sd)), -// escToken); -// auto eccToken = FLECollectionTokenGenerator::generateECCToken(collectionToken); -// ASSERT_EQUALS( -// ECCToken(decodePrf("9d34f9c182d75a5a3347c2f903e3e647105c651d52cf9555c9420ba07ddd3aa2"_sd)), -// eccToken); -// ASSERT_EQUALS( -// ECOCToken(decodePrf("e354e3b05e81e08b970ca061cb365163fd33dec2f982ddf9440e742ed288a8f8"_sd)), -// FLECollectionTokenGenerator::generateECOCToken(collectionToken)); - - -// // Level 3 -// std::vector<uint8_t> sampleValue = {0xc0, 0x7c, 0x0d, 0xf5, 0x12, 0x57, 0x94, 0x8e, -// 0x1a, 0x0f, 0xc7, 0x0d, 0xd4, 0x56, 0x8e, 0x3a, -// 0xf9, 0x9b, 0x23, 0xb3, 0x43, 0x4c, 0x98, 0x58, -// 0x23, 0x7c, 0xa7, 0xdb, 0x62, 0xdb, 0x97, 0x66}; - -// auto edcDataToken = -// FLEDerivedFromDataTokenGenerator::generateEDCDerivedFromDataToken(edcToken, sampleValue); -// ASSERT_EQUALS(EDCDerivedFromDataToken(decodePrf( -// "53eaa4c23a3ff65e6b7c7dbc4b1389cf0a6151b1ede5383a0673ff9c67855ff9"_sd)), -// edcDataToken); - -// auto escDataToken = -// FLEDerivedFromDataTokenGenerator::generateESCDerivedFromDataToken(escToken, sampleValue); -// ASSERT_EQUALS(ESCDerivedFromDataToken(decodePrf( -// "acb3fab332131bbeaf112814f29ae0f2b10e97dc94b62db56c594661248e7467"_sd)), -// escDataToken); - -// auto eccDataToken = -// FLEDerivedFromDataTokenGenerator::generateECCDerivedFromDataToken(eccToken, sampleValue); -// ASSERT_EQUALS(ECCDerivedFromDataToken(decodePrf( -// "826cfd35c35dcc7d4fbe13f33a3520749853bd1ea4c47919482252fba3a70cec"_sd)), -// eccDataToken); - -// // Level 4 -// FLECounter counter = 1234567890; - -// auto edcDataCounterToken = FLEDerivedFromDataTokenAndContentionFactorTokenGenerator:: -// generateEDCDerivedFromDataTokenAndContentionFactorToken(edcDataToken, counter); -// ASSERT_EQUALS(EDCDerivedFromDataTokenAndContentionFactorToken(decodePrf( -// "70fb9a3f760996f2f1438c5bf2a4d52bcba01b0badc3596276f49ffb2f0b136e"_sd)), -// edcDataCounterToken); - - -// auto escDataCounterToken = FLEDerivedFromDataTokenAndContentionFactorTokenGenerator:: -// generateESCDerivedFromDataTokenAndContentionFactorToken(escDataToken, counter); -// ASSERT_EQUALS(ESCDerivedFromDataTokenAndContentionFactorToken(decodePrf( -// "7076c7b05fb4be4fe585eed930b852a6d088a0c55f3c96b50069e8a26ebfb347"_sd)), -// escDataCounterToken); - - -// auto eccDataCounterToken = FLEDerivedFromDataTokenAndContentionFactorTokenGenerator:: -// generateECCDerivedFromDataTokenAndContentionFactorToken(eccDataToken, counter); -// ASSERT_EQUALS(ECCDerivedFromDataTokenAndContentionFactorToken(decodePrf( -// "6c6a349956c19f9c5e638e612011a71fbb71921edb540310c17cd0208b7f548b"_sd)), -// eccDataCounterToken); - - -// // Level 5 -// auto edcTwiceToken = -// FLETwiceDerivedTokenGenerator::generateEDCTwiceDerivedToken(edcDataCounterToken); -// ASSERT_EQUALS(EDCTwiceDerivedToken(decodePrf( -// "3643fd370e2719c03234cdeec787dfdc7d8fceecafa8a992e3c1f9d4d53449fe"_sd)), -// edcTwiceToken); - -// auto escTwiceTagToken = -// FLETwiceDerivedTokenGenerator::generateESCTwiceDerivedTagToken(escDataCounterToken); -// ASSERT_EQUALS(ESCTwiceDerivedTagToken(decodePrf( -// "c73bc4ff5e70222c653140b2b4998b4d62db973f20f116f66ff811a9a907a78f"_sd)), -// escTwiceTagToken); -// auto escTwiceValueToken = -// FLETwiceDerivedTokenGenerator::generateESCTwiceDerivedValueToken(escDataCounterToken); -// ASSERT_EQUALS(ESCTwiceDerivedValueToken(decodePrf( -// "34150c6f5ab56dc39ddb935accb7f53e5276322fa937650b76a4dda9723d6fba"_sd)), -// escTwiceValueToken); - - -// auto eccTwiceTagToken = -// FLETwiceDerivedTokenGenerator::generateECCTwiceDerivedTagToken(eccDataCounterToken); -// ASSERT_EQUALS(ECCTwiceDerivedTagToken(decodePrf( -// "0bc36f73062f5182c2403bffd155ec06eccfde0df8de5facaca4cc1cb320a385"_sd)), -// eccTwiceTagToken); -// auto eccTwiceValueToken = -// FLETwiceDerivedTokenGenerator::generateECCTwiceDerivedValueToken(eccDataCounterToken); -// ASSERT_EQUALS(ECCTwiceDerivedValueToken(decodePrf( -// "2d7e08d58afa9f5ad215636e566d38584cbb48467d1bc9ff376eeca01fbfda6f"_sd)), -// eccTwiceValueToken); -// } +TEST(FLETokens, TestVectors) { + + // Level 1 + auto collectionToken = FLELevel1TokenGenerator::generateCollectionsLevel1Token(getIndexKey()); + + ASSERT_EQUALS(CollectionsLevel1Token(decodePrf( + "BD53ACAC665EDD01E0CA30CB648B2B8F4967544047FD4E7D12B1A9BF07339928"_sd)), + collectionToken); + + ASSERT_EQUALS(ServerDataEncryptionLevel1Token(decodePrf( + "EB9A73F7912D86A4297E81D2F675AF742874E4057E3A890FEC651A23EEE3F3EC"_sd)), + FLELevel1TokenGenerator::generateServerDataEncryptionLevel1Token(getIndexKey())); + + // Level 2 + auto edcToken = FLECollectionTokenGenerator::generateEDCToken(collectionToken); + ASSERT_EQUALS( + EDCToken(decodePrf("82B0AB0F8F1D31AEB6F4DBC915EF17CBA2FE21E36EC436984EB63BECEC173831"_sd)), + edcToken); + auto escToken = FLECollectionTokenGenerator::generateESCToken(collectionToken); + ASSERT_EQUALS( + ESCToken(decodePrf("279C575B52B73677EEF07D9C1126EBDF08C35369570A9B75E44A9AFDCCA96B6D"_sd)), + escToken); + auto eccToken = FLECollectionTokenGenerator::generateECCToken(collectionToken); + ASSERT_EQUALS( + ECCToken(decodePrf("C58F671F04A8CFDD8FB1F718F563139F1286D7950E97C0C4A94EDDF0EDB127FE"_sd)), + eccToken); + ASSERT_EQUALS( + ECOCToken(decodePrf("9E837ED3926CB8ED680E0E7DCB2A481A3E398BE7851FA1CE4D738FA5E67FFCC9"_sd)), + FLECollectionTokenGenerator::generateECOCToken(collectionToken)); + + + // Level 3 + std::vector<uint8_t> sampleValue = {0xc0, 0x7c, 0x0d, 0xf5, 0x12, 0x57, 0x94, 0x8e, + 0x1a, 0x0f, 0xc7, 0x0d, 0xd4, 0x56, 0x8e, 0x3a, + 0xf9, 0x9b, 0x23, 0xb3, 0x43, 0x4c, 0x98, 0x58, + 0x23, 0x7c, 0xa7, 0xdb, 0x62, 0xdb, 0x97, 0x66}; + + auto edcDataToken = + FLEDerivedFromDataTokenGenerator::generateEDCDerivedFromDataToken(edcToken, sampleValue); + ASSERT_EQUALS(EDCDerivedFromDataToken(decodePrf( + "CEA098AA664E578D4E9CE05B50ADD15DF2F0316CD5CCB08E720C61D8C7580E2A"_sd)), + edcDataToken); + + auto escDataToken = + FLEDerivedFromDataTokenGenerator::generateESCDerivedFromDataToken(escToken, sampleValue); + ASSERT_EQUALS(ESCDerivedFromDataToken(decodePrf( + "DE6A1AC292BC62094C33E94647B044B9B10514317B75F4128DDA2E0FB686704F"_sd)), + escDataToken); + + auto eccDataToken = + FLEDerivedFromDataTokenGenerator::generateECCDerivedFromDataToken(eccToken, sampleValue); + ASSERT_EQUALS(ECCDerivedFromDataToken(decodePrf( + "9A95D4F44734447E3F0266D1629513A0B7698CCE8C1524F329CE7970627FFD06"_sd)), + eccDataToken); + + // Level 4 + FLECounter counter = 1234567890; + + auto edcDataCounterToken = FLEDerivedFromDataTokenAndContentionFactorTokenGenerator:: + generateEDCDerivedFromDataTokenAndContentionFactorToken(edcDataToken, counter); + ASSERT_EQUALS(EDCDerivedFromDataTokenAndContentionFactorToken(decodePrf( + "D8CC38AE6A64BD1BF195A2D35734C13AF2B1729AD1052A81BE00BF29C67A696E"_sd)), + edcDataCounterToken); + + + auto escDataCounterToken = FLEDerivedFromDataTokenAndContentionFactorTokenGenerator:: + generateESCDerivedFromDataTokenAndContentionFactorToken(escDataToken, counter); + ASSERT_EQUALS(ESCDerivedFromDataTokenAndContentionFactorToken(decodePrf( + "8AAF04CBA6DC16BFB37CADBA43DCA66C183634CB3DA278DE174556AE6E17CEBB"_sd)), + escDataCounterToken); + + + auto eccDataCounterToken = FLEDerivedFromDataTokenAndContentionFactorTokenGenerator:: + generateECCDerivedFromDataTokenAndContentionFactorToken(eccDataToken, counter); + ASSERT_EQUALS(ECCDerivedFromDataTokenAndContentionFactorToken(decodePrf( + "E9580F805E0D07AF384EBA185384F28A49C3DB93AFA4A187A1F4DA129271D82C"_sd)), + eccDataCounterToken); + + + // Level 5 + auto edcTwiceToken = + FLETwiceDerivedTokenGenerator::generateEDCTwiceDerivedToken(edcDataCounterToken); + ASSERT_EQUALS(EDCTwiceDerivedToken(decodePrf( + "B39A7EC33FD976EFB8EEBBBF3A265A933E2128D709BB88C77E3D42AA735F697C"_sd)), + edcTwiceToken); + + auto escTwiceTagToken = + FLETwiceDerivedTokenGenerator::generateESCTwiceDerivedTagToken(escDataCounterToken); + ASSERT_EQUALS(ESCTwiceDerivedTagToken(decodePrf( + "D6F76A9D4767E0889B709517C8CF0412D81874AEB6E6CEBFBDDFF7B013EB7154"_sd)), + escTwiceTagToken); + auto escTwiceValueToken = + FLETwiceDerivedTokenGenerator::generateESCTwiceDerivedValueToken(escDataCounterToken); + ASSERT_EQUALS(ESCTwiceDerivedValueToken(decodePrf( + "53F0A51A43447B9881D5E79BA4C5F78E80BC2BC6AA42B00C81079EBF4C9D5A7C"_sd)), + escTwiceValueToken); + + + auto eccTwiceTagToken = + FLETwiceDerivedTokenGenerator::generateECCTwiceDerivedTagToken(eccDataCounterToken); + ASSERT_EQUALS(ECCTwiceDerivedTagToken(decodePrf( + "5DD9F09757BE35BB33FFAF6FC5CDFC649248E59AEA9FF7D9E2A9F36B6F5A6152"_sd)), + eccTwiceTagToken); + auto eccTwiceValueToken = + FLETwiceDerivedTokenGenerator::generateECCTwiceDerivedValueToken(eccDataCounterToken); + ASSERT_EQUALS(ECCTwiceDerivedValueToken(decodePrf( + "EFA5746DB796DAC6FAACB7E5F28DB53B333588A43131F0C026B19D2B1215EAE2"_sd)), + eccTwiceValueToken); + + // Unindexed field decryption + // Encryption can not be generated using test vectors because IV is random + + TestKeyVault keyVault; + const std::string uxCiphertext = hexblob::decode( + "06ABCDEFAB12349876123412345678901202F2CE7FDD0DECD5442CC98C10B9138741785173E323132982740496768877A3BA46581CED4A34031B1174B5C524C15BAAE687F88C29FC71F40A32BCD53D63CDA0A6646E8677E167BB3A933529F5B519CFE255BBC323D943B4F105"_sd); + auto [uxBsonType, uxPlaintext] = + FLE2UnindexedEncryptedValue::deserialize(&keyVault, ConstDataRange(uxCiphertext)); + ASSERT_EQUALS(uxBsonType, BSONType::String); + ASSERT_EQUALS( + hexblob::encode(uxPlaintext.data(), uxPlaintext.size()), + "260000004C6F7279207761732061206D6F75736520696E2061206269672062726F776E20686F75736500"); + + // Equality indexed field decryption + // Encryption can not be generated using test vectors because IV is random + + const std::string ixCiphertext = hexblob::decode( + "000000000000000000000000000000000297044B8E1B5CF4F9052EDB50236A343597C418A74352F98357A77E0D4299C04151CBEC24A5D5349A5A5EAA1FE334154FEEB6C8E7BD636089904F76950B2184D146792CBDF9179FFEDDB7D90FC257BB13DCB3E731182A447E2EF1BE7A2AF13DC9362701BABDE0B5E78CF4A92227D5B5D1E1556E75BAB5B4E9F5CEFEA3BA3E3D5D31D11B20619437A30550EFF5B602357567CF05058E4F84A103293F70302F3A50667642DD0325D194A197"_sd); + ServerDataEncryptionLevel1Token serverEncryptToken( + decodePrf("EB9A73F7912D86A4297E81D2F675AF742874E4057E3A890FEC651A23EEE3F3EC"_sd)); + + auto swServerPayload = FLE2IndexedEqualityEncryptedValue::decryptAndParse( + serverEncryptToken, ConstDataRange(ixCiphertext)); + ASSERT_OK(swServerPayload.getStatus()); + + auto cdrEqualHex = [](ConstDataRange cdr, const StringData hex) -> bool { + const std::string s = hexblob::decode(hex); + return cdr.length() == s.size() && std::equal(s.begin(), s.end(), cdr.data<char>()); + }; + + auto sp = swServerPayload.getValue(); + ASSERT(cdrEqualHex(sp.edc.toCDR(), + "97C8DFE394D80A4EE335E3F9FDC024D18BE4B92F9444FCA316FF9896D7BF455D"_sd)); + ASSERT(cdrEqualHex(sp.esc.toCDR(), + "EBB22F74BE0FA4AD863188D3F33AF0B95CB4CA4ED0091E1A43513DB20E9D59AE"_sd)); + ASSERT(cdrEqualHex(sp.ecc.toCDR(), + "A1DF0BB04C977BD4BC0B487FFFD2E3BBB96078354DE9F204EE5872BB10F01971"_sd)); + ASSERT_EQ(sp.count, 123456); + ASSERT(cdrEqualHex( + sp.clientEncryptedValue, + "260000004C6F7279207761732061206D6F75736520696E2061206269672062726F776E20686F75736500"_sd)); +} + +TEST(FLETokens, TestVectorESCCollectionDecryptDocument) { + ESCTwiceDerivedTagToken escTwiceTag( + decodePrf("B1C4E1C67F4AB83DE7632B801BDD198D65401B17EC633EB4D608DE97FAFCE02B"_sd)); + ESCTwiceDerivedValueToken escTwiceValue( + decodePrf("E2E3F08343FD16BCB36927FFA39C7BCC6AA1E33E6E553DF9FE445ABB988D30D1"_sd)); + + BSONObj doc = fromjson(R"({ + "_id": { + "$binary": { + "base64": "bdK0MLySL7lEaje7JHIWvvpx/AQWZID2kW47M1XLFUg=", + "subType": "0" + } + }, + "value": { + "$binary": { + "base64": "+17srnmE1l+T1np0IJxoeLRzD1ac5st9k/a0YHxeqk0=", + "subType": "0" + } + } + })"); + + auto swDoc = ESCCollection::decryptDocument(escTwiceValue, doc); + ASSERT_OK(swDoc.getStatus()); + ASSERT_EQ(swDoc.getValue().compactionPlaceholder, false); + ASSERT_EQ(swDoc.getValue().position, 0); + ASSERT_EQ(swDoc.getValue().count, 123456789); +} + +TEST(FLETokens, TestVectorECCCollectionDecryptDocument) { + ECCTwiceDerivedTagToken twiceTag( + decodePrf("8879748219186CAC6B5E77D664A05C4BA2C7690F09ACC16B8E9910B80FF4B5AB"_sd)); + ECCTwiceDerivedValueToken twiceValue( + decodePrf("F868EB46AA38963658E453DE05B2955225CB00C96B72975DACF9D837C8189FA2"_sd)); + + BSONObj doc = fromjson(R"({ + "_id": { + "$binary": { + "base64": "TTB8rMJipFwpSMbWMf3Rpx8RuRP4Fnc6bJl1tdMc84A=", + "subType": "0" + } + }, + "value": { + "$binary": { + "base64": "anHlFVy/XbIDENbKPUVf5OgPv2fkt3JBxYAUGTStAj4=", + "subType": "0" + } + } + })"); + + auto swDoc = ECCCollection::decryptDocument(twiceValue, doc); + + ASSERT_OK(swDoc.getStatus()); + ASSERT(swDoc.getValue().valueType == ECCValueType::kNormal); + ASSERT_EQ(swDoc.getValue().start, 123456789); + ASSERT_EQ(swDoc.getValue().end, 123456789); +} TEST(FLE_ESC, RoundTrip) { TestKeyVault keyVault; @@ -1000,9 +1095,7 @@ TEST(FLE_EDC, ServerSide_Payloads) { EncryptedStateCollectionTokens(escDataCounterkey, eccDataCounterkey).serialize(ecocToken); uassertStatusOK(swEncryptedTokens); iupayload.setEncryptedTokens(swEncryptedTokens.getValue()); - - std::vector<uint8_t> cipherText = {0x1, 0x2, 0x3, 0x4, 0x5}; - iupayload.setValue(cipherText); + iupayload.setValue(value); iupayload.setType(element.type()); FLE2IndexedEqualityEncryptedValue serverPayload(iupayload, 123456); @@ -1020,7 +1113,10 @@ TEST(FLE_EDC, ServerSide_Payloads) { ASSERT_EQ(sp.ecc, serverPayload.ecc); ASSERT_EQ(sp.count, serverPayload.count); ASSERT(sp.clientEncryptedValue == serverPayload.clientEncryptedValue); - ASSERT(cipherText == serverPayload.clientEncryptedValue); + ASSERT_EQ(serverPayload.clientEncryptedValue.size(), value.length()); + ASSERT(std::equal(serverPayload.clientEncryptedValue.begin(), + serverPayload.clientEncryptedValue.end(), + value.data<uint8_t>())); } TEST(FLE_EDC, DuplicateSafeContent_CompatibleType) { |