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

FIX: Assertion may be false for untrusted data #4391

Merged
merged 1 commit into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/lib/pubkey/pqcrystals/pqcrystals_encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ constexpr void pack(const Polynomial<PolyTrait, D>& p, BufferStuffer& stuffer, M
// Transform p[i] via a custom map function (that may be a NOOP).
const typename trait::unsigned_T mapped_coeff = map(p[i + j]);
const auto coeff_value = static_cast<typename trait::sink_t>(mapped_coeff);

// pack() is called only on data produced by us. If the values returned
// by the map function are not in the range [0, range] we have a bug.
BOTAN_DEBUG_ASSERT(coeff_value <= range);

// Bit-pack the coefficient into the collectors array and keep track of
Expand Down Expand Up @@ -170,8 +173,9 @@ constexpr void pack(const Polynomial<PolyTrait, D>& p, BufferStuffer& stuffer, M
*
* This takes a byte sequence represented by @p byte_source and unpacks its
* coefficients into the polynomial @p p. Optionally, the coefficients can be
* transformed using the @p unmap function after unpacking them. Note that the
* provided range is assumed for the coefficients _before_ the transformation.
* transformed using the @p unmap function after unpacking them. Note that
* the @p unmap function must be able to deal with out-of-range values, as the
* input to `unpack()` may be untrusted data.
*
* Kyber uses @p unmap to decompress the coefficients as needed, Dilithium uses
* it to convert the coefficients back to signed integers.
Expand Down Expand Up @@ -202,9 +206,13 @@ constexpr void unpack(Polynomial<PolyTrait, D>& p, ByteSourceT& byte_source, Unm
bit_offset = bit_offset - trait::bits_in_collector;
coeff_value |= collectors[++c] << (trait::bits_per_coeff - bit_offset);
}
const auto mapped_coeff = static_cast<typename trait::unsigned_T>(coeff_value & trait::value_mask);
BOTAN_DEBUG_ASSERT(mapped_coeff <= range);
p[i + j] = unmap(mapped_coeff);

// unpack() may be called on data produced by an untrusted party.
// The values passed into the unmap function may be out of range, hence
// it is acceptable for unmap to return an out-of-range value then.
//
// For that reason we cannot use BOTAN_ASSERT[_DEBUG] on the values.
p[i + j] = unmap(static_cast<typename trait::unsigned_T>(coeff_value & trait::value_mask));
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/tests/data/pubkey/kyber_encodings.vec
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,19 @@ Error = Private key does not have the correct byte count
PrivateRaw = C6C9B2CA96CE5B715A6262CAA2989B72EB6730B54BC89B65BC021FAAC7AB88E5833B9A7454C94E49CC55EBE30C6B7702EBAB0A40728E1F108E8FF14AF217556E85551810C2716B4248B9B10EA7BD5D05CF12425CA648A653B26B1D645595D95323F153CB1ACAB9D29ED955817592C017C4465DB30066FB68AE3429E5453FB0199C6E9967608939057632674B3DA8BB587174BAF362433C4B9B75BA304F995AA6238BDE7398BD460619E00F61CB4A2040BF09C5120F51BA7808AE171B1C9C733F4025B872904F45AA8AFDA6B1B8B86407A1C619065634F78296D6915156C44735634CB2AB498574282754E020473F02201219327A4B748CAC50617A01D101C34FB20EE04BA70BE541794440F0E815778444A310295B39164C7633A8448408D16B47E68E80096DED5373840B830E84CBE1F25100788E53E3CD35AA365674A334DA913EA7A6EDE3C002987ED94A6D5AEB8B3272B3EB8097B6F723C7541782F90F3126BF8ABAC201F51D009B258C877CDA9304FD73242050693E380380D3898749CC7FAABAE09477319228B6D9606D876469D622B15A6A4845CDAF1A6603F25AADF5A271C225C4213FD9422743705B33FBC2FA9BB55B585A8F858DE578BC44C4B3AA919660045733E222D5409E5C4B789A109F458961AEF8AC798342C2E854E2701013729921574E340B9AEE44BF9A2971FCD80B6AF994F7385FB505359346417963AF61986076ABC54ED6B4130C5042EB04EB6C885E2C4888A63A52BA49B9C6BFA41A91CE650EF234A4ABB8B1122A15E167ADF4A78115881B6C2B26C9CC32E2A5552DB35AF280A0919A09047562CD33AC8332B74E6B962E3643B14019C7479CA1A29BC420038DF52FB6A2A7DF10C7798ACD4AC315423361C8334D38B0099D4A5136AB32D599A0CD5983C4864567509E9672C3BF6BAC914B0ED5D04AFCB1A8DA16776E0391E4F5655E7147F955C5078C798FD362C93A6C7E9914454A591CD93972107C61057A9AE417B776A1BF6683505A2D85D53A6AE0BC4740278B69BD0A608CB0484B04122FB3D46F6C06A3CC5523EC054030C9A8A585A5DE82CA41B39082052D970BCFE55389AA956BB9E2C62AC5CE80FA64A15B4DE4FB71DA7100E04B85596849F3E0326570227B48589E45B387E612C36C8BABF09EFA22A021184BB6197B011842DCE1C9682492836B2E96C059C92C15BD8825A8C0265B795234F8756E505C1EAA29E482BFE4FC0CE945B75E84817E5310245CB57A3A51E2F91CCCDC850CF59027497D124BB36449B28C62BB90181F01372B0379C03B994343C7476B3146C87C6E25B677F30CA7BDE3369F1177B8A90BB2561B1C637D7E9CAB2C8BC4E0717669871B4451313DA55879F07FD01637ED052A82A5C7B3D1427611CC5D9B17827B4F3A28610ECA998903B4CBB2187C849E7D862867391812A94139DB76328C4EECB6AD0590C31FB627E1A3C319DA5D3DE44FEF088027108A6F9762D1B6075C0C3835A83A44F230E7B0ACD77241AD0CBFE4822BF189C868161A6B330DCE8C1A39A3042D81BA5AB86603205747995E6C6AAAF33149ABF8B2061137A773074F6846277C6A67C6789814AD32B088CD688924948528648238050EC9C8955EC7897125CA5F708112735687017F51788FDB9C68526AB14E76C25C490E7794315BF686596CAB483624754C834A7AAA4268BB98131A739A617907456D139805830945C8BDD0104ECB41A96AF92B86C04B72D963E47AA9168A0BD72210672AA7D15642B1220541643C2CFC0636A6AD344022C01CA6B3B787B659A06DC50F85B59C5806AF9833876EDB66C558A3EA71585DB88F62E520CFF0C3FC8208B390CBA833BCCEB5B72576CAD3F564DEFB9B5C7589CC7A4B5F5B0E857A3E90E7B87797379E47A27774172A0AAE0417CDECA89E3114837F1C3B4B614AD9E774802B4E4226C6C7A56F603C931878422600CE5EE3A44C2015287AB3665544C470AEE0AC2A31F8345B459BFA2B7900257B0A1B0DF9086352660956A54598251A347860518B8E507CCA39ABB73215A9C347499CA94C2DC24B0FD66EB9AC5DAC214B46B65694D114B3893EBA6663EE3A6AE1846B7A2398569BB4B06A1EF34584AF9CC3F4E415FAA9096B4B96B0915BF2D5808AB71CD65C890226C4BEE74DD97A91B1B6363849870DA23EF08A1CFD487C194D66FF16C96F3B02FB97D3D087B1FD1D6E91878E8380318F7B4843FBFC07C4BC1D13EDCC88E413D23BD8E73176A0B05B6D2381822474393D22585AF90351770587A6FCDEA8254D8EEC0CEF8668E30B3D24525B36AB3C75063B8A03D4
PublicRaw = F9951AFAD2C96730335CF42103F9267A11C16E209D366603B04789378684987B655CD57B2DCBCC195B137227B9ECD3BAB0C0183B5A0667E407D7C86402D7719869CD6570B30B8C227ACB8B478320D64353CCB94809052558B1AC94C0CF498219442B988FD64F7CF6423C372F46F26791D3680817B3EBB24BFA98CA2EB22FDF48919D1595F06115C70CA050C04B17D6A91E2926677120EF24AEAF499B43542EC0C91DB4A3B7AD6A5DB646C164D70F496225A7800DD81C634C004796A79148E47A4E312F3BF56BE80C2E9D01C431767FF50496ADA127C1D286A2FC9FB98677BBF95203F63296881D5C536B39F22222C570AD921C82565E1C7C069D69BB3CD431A4CCB5F0C790C6578C1EB0185F84C706137A7052680BD8AAAC941D34A3756EA8B006F732B995612E330616BC22F9EACF4423A1DFE18B0E63BF18B24DB8E1B2D1097CB2E305A80372E08492161871D8480D55DA41ED80AEF73682873A3065472A98816846550C80608A8FA8A9342BA87FAA6105B5C8C194C7268C694D38A08AA83102239073E02581A6A604B06B0673B43CECC07A0586B65CA8EA79BE8A140CF329223434745B576BF9CB2A70709D2621359621A057A3BFFEE465E421CA1D48096E06ACD6309F40A64126B0491D03BF7272ABB1475B72A54E9A2675262AC831B00BE163235280B76D5B88101524077A76A97C7A4F2A5AA8A547F14203F8BA26D1368B23E832987696E965177BB648CC3325766A4E8935074D9C7344E031917AB0DE452092E2720D121A0E32CC9E5B2325500BD1B76E38360A36E972CEFC56E93482E47605AF9A69A6F42D89C6C21E2B0CD5E14534A75012CC905E3042BB0043CF0280185A90D245B86C7097F2C1694F2BAE0CC5C995E580343A96A2656A108769F1DC0B7717B0C4A1A635DA3DF4D248B3D29116A8B939FCC063250198982EEF436E3564881A2A2C0F94AEAD47690A9C194C56CF47868026BA8CDEBB7631E643E6B20A9F24061B1C496518B89F1A45A6C5518B742990413D9B0012F895872E4B258371123839BD209C1A004B4575567C391A6158A464B9428761D0191F4B6CE2630A6F77590B25FA894D654EB1905481FF4CC75C2A435630DB1CEE9254090FA8D11E

Error = Decoded polynomial coefficients out of range
PrivateRaw = 2B44523FC0A955F93A28A8A08DA078E6AD11122E26852647D8E0C6795E0577E65D8BD5D2F82C871554442FEBF6E132EC08A596619CF00A63C1F1B35B758CC37A
PublicRaw = FFFF1AFAD2C96730335CF42103F9267A11C16E209D366603B04789378684987B655CD57B2DCBCC195B137227B9ECD3BAB0C0183B5A0667E407D7C86402D7719869CD6570B30B8C227ACB8B478320D64353CCB94809052558B1AC94C0CF498219442B988FD64F7CF6423C372F46F26791D3680817B3EBB24BFA98CA2EB22FDF48919D1595F06115C70CA050C04B17D6A91E2926677120EF24AEAF499B43542EC0C91DB4A3B7AD6A5DB646C164D70F496225A7800DD81C634C004796A79148E47A4E312F3BF56BE80C2E9D01C431767FF50496ADA127C1D286A2FC9FB98677BBF95203F63296881D5C536B39F22222C570AD921C82565E1C7C069D69BB3CD431A4CCB5F0C790C6578C1EB0185F84C706137A7052680BD8AAAC941D34A3756EA8B006F732B995612E330616BC22F9EACF4423A1DFE18B0E63BF18B24DB8E1B2D1097CB2E305A80372E08492161871D8480D55DA41ED80AEF73682873A3065472A98816846550C80608A8FA8A9342BA87FAA6105B5C8C194C7268C694D38A08AA83102239073E02581A6A604B06B0673B43CECC07A0586B65CA8EA79BE8A140CF329223434745B576BF9CB2A70709D2621359621A057A3BFFEE465E421CA1D48096E06ACD6309F40A64126B0491D03BF7272ABB1475B72A54E9A2675262AC831B00BE163235280B76D5B88101524077A76A97C7A4F2A5AA8A547F14203F8BA26D1368B23E832987696E965177BB648CC3325766A4E8935074D9C7344E031917AB0DE452092E2720D121A0E32CC9E5B2325500BD1B76E38360A36E972CEFC56E93482E47605AF9A69A6F42D89C6C21E2B0CD5E14534A75012CC905E3042BB0043CF0280185A90D245B86C7097F2C1694F2BAE0CC5C995E580343A96A2656A108769F1DC0B7717B0C4A1A635DA3DF4D248B3D29116A8B939FCC063250198982EEF436E3564881A2A2C0F94AEAD47690A9C194C56CF47868026BA8CDEBB7631E643E6B20A9F24061B1C496518B89F1A45A6C5518B742990413D9B0012F895872E4B258371123839BD209C1A004B4575567C391A6158A464B9428761D0191F4B6CE2630A6F77590B25FA894D654EB1905481FF4CC75C2A435630DB1CEE9254090FA8D11E

PrivateRaw = 3305F0CF680FEAD1BCC50ABB0B04F288BD3266AE12188FFF50D316FC00681A81D72D4E46CB5A96ABBBD507E8D7BB4C523080550B142D1594B9A75113D6D2D70C
PublicRaw = F9951AFAD2C96730335CF42103F9267A11C16E209D366603B04789378684987B655CD57B2DCBCC195B137227B9ECD3BAB0C0183B5A0667E407D7C86402D7719869CD6570B30B8C227ACB8B478320D64353CCB94809052558B1AC94C0CF498219442B988FD64F7CF6423C372F46F26791D3680817B3EBB24BFA98CA2EB22FDF48919D1595F06115C70CA050C04B17D6A91E2926677120EF24AEAF499B43542EC0C91DB4A3B7AD6A5DB646C164D70F496225A7800DD81C634C004796A79148E47A4E312F3BF56BE80C2E9D01C431767FF50496ADA127C1D286A2FC9FB98677BBF95203F63296881D5C536B39F22222C570AD921C82565E1C7C069D69BB3CD431A4CCB5F0C790C6578C1EB0185F84C706137A7052680BD8AAAC941D34A3756EA8B006F732B995612E330616BC22F9EACF4423A1DFE18B0E63BF18B24DB8E1B2D1097CB2E305A80372E08492161871D8480D55DA41ED80AEF73682873A3065472A98816846550C80608A8FA8A9342BA87FAA6105B5C8C194C7268C694D38A08AA83102239073E02581A6A604B06B0673B43CECC07A0586B65CA8EA79BE8A140CF329223434745B576BF9CB2A70709D2621359621A057A3BFFEE465E421CA1D48096E06ACD6309F40A64126B0491D03BF7272ABB1475B72A54E9A2675262AC831B00BE163235280B76D5B88101524077A76A97C7A4F2A5AA8A547F14203F8BA26D1368B23E832987696E965177BB648CC3325766A4E8935074D9C7344E031917AB0DE452092E2720D121A0E32CC9E5B2325500BD1B76E38360A36E972CEFC56E93482E47605AF9A69A6F42D89C6C21E2B0CD5E14534A75012CC905E3042BB0043CF0280185A90D245B86C7097F2C1694F2BAE0CC5C995E580343A96A2656A108769F1DC0B7717B0C4A1A635DA3DF4D248B3D29116A8B939FCC063250198982EEF436E3564881A2A2C0F94AEAD47690A9C194C56CF47868026BA8CDEBB7631E643E6B20A9F24061B1C496518B89F1A45A6C5518B742990413D9B0012F895872E4B258371123839BD209C1A004B4575567C391A6158A464B9428761D0191F4B6CE2630A6F77590B25FA894D654EB1905481FF4CC75C2A435630DB1CEE9254090FA8D11E

[ML-KEM-768]

Error = Decoded polynomial coefficients out of range
PrivateRaw = 2B44523FC0A955F93A28A8A08DA078E6AD11122E26852647D8E0C6795E0577E65D8BD5D2F82C871554442FEBF6E132EC08A596619CF00A63C1F1B35B758CC37A
PublicRaw = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

PrivateRaw = 2B44523FC0A955F93A28A8A08DA078E6AD11122E26852647D8E0C6795E0577E65D8BD5D2F82C871554442FEBF6E132EC08A596619CF00A63C1F1B35B758CC37A
PublicRaw = E7FA6FB9292D8BDB91C66181D0784DAE04A114C65DD4AC86605516B99849512C179898C85FBA5F9D9B39F0709CF8D4342F8202EFA02563FC3C2F492C90677D53D73855909A3ECCA2207144BEBABD20634C36BB228618C0EFCB68AFC22650DA363B66B9175565E43761EEA75771706949593870C95C4CFBAE1DB364A46742258A6708A76771565D07FA5750D15883473211D8C394488C99B2461C4AA0FD3C3735F587BE7CCD3E3321A1CC492CE1AC08B9143E04D017756E37094311A00CBE6C4C2A844973F9087F73C77E107421A75CC7D27231E1358847AB4614634166518FC94B787B7A40646F3BA04D62ECCDC7B4991588126689B94A10CE10EB3E054B4FECC084CAD4814DF98D5D6B28E034269474A493835CC3174293378E3C956BE9E3643AC936E626B2EE88BD7563354D743D5B856396471C403902156194BD99CF9364458BAA811D0C8EA7A36BFB23141DC73C48FA86ED1C4A5E7A1E7E80CE3BC4B3B9603D9D393015BAC94FDBA23CC9C657F83F28FC9CC7FB2ADFA28A92081089FA5BA39424A6B0BBFEDA383836A35425BEED4295BE4626149B90DBB744A4A718F8A38C778B379D4B970361CE507A9B3BC3030464AC20854F3A3C2D5CD5075AF54E5F2A6B6C17152B9AA941D08A3836553229A7341A3C73DA23F9F153D4244A97B828CE4794FA4C3E8EEB94A2270923324B6D563604650EAD65B7C1D97D2EA4057915C4A379AD84D224BB6862ACDC7315BC6C5DD8373053673814CEB50271558844E36498AEF96D480401BE44BD61E6AE611A595BD9989448997877A670A6AD77D9393AD8A60234B092A710383598867AA2AD9A5C96618D6AF83EE9416B8B3B8359E205436ACF98334C4B4BAB03E97165A2A9E5693498B82788939829E0AB60836B889675D5E65A92164AFAF3B98517C01753C711838D63E61FC793AFD6CA2DA2DB2763A280233672641198BA359DBF6081F39BCB3B5BC8FC87A22A8433BE67896F424BBD697FD1F72DD321A6BFCC77092A06BD577510BCCEE0F162DF4A49E6C976408B3F4A489705E966BFC95284C7472BC17733EA4B47C046115578EEE32CBF858CC14A14730136FD06995ED431628BBE8E75CE15DC874ECC93E0C38A3C14484F96C616F6CBF2042DEF27B13FF2CEDD3ABB7A74580AB9B8AD4058F0020493F6467048B31090C10EF83833988B1FD1580E62161121B7F380612E304E207BBAF24604892A60B83338165AA8F8992B2A8664A8BA71461C9D8EA100F5D5A3DACB2BB496A726938683904589C454849B26ADBA5448EB2928C5449DF93B8F620795BA3562681E1C0A6877F795876A603738464DFA2A91D8A50DF3B48388B1EB163751CBC4FECBAFA9A361A728BF7B75B308DA4CCDC578100038F2F2CD75A90491E9CE47B6B4011AB43823A660E76659B97984E626D61C8207F73CB3918DEDE5A21F99C15D8597C4905EA8C41271FC6D3234A5BB17CB9E64434A96A96F1BA183298AFBC505DEA078B178236A5A9009A3835A35786AC3406B650A65298BF9735B3DD3C483962377FC47F958A04A7CC6ECA0628C794599D09546E5C65C5CA487482CB84762E0F38B64418AF0B7268318A84F0875479870901668ECE34252D5C64F3028684255D6976E03065332399F17F462F787F236094607CC7BAA4C14B0AE9D21D2B3F63B

Expand Down
Loading