From 7b5c5e4b45a5961f740edb831a268ad386e31546 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Tue, 18 Jun 2024 17:43:05 +0200 Subject: [PATCH 01/53] Revert changes to Kyber (Round 3) for ML-KEM --- libcrux-kem/src/kem.rs | 2 +- libcrux-ml-kem/src/ind_cca.rs | 24 ++++++++++++++++++---- libcrux-ml-kem/tests/kyber.rs | 38 +++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 libcrux-ml-kem/tests/kyber.rs diff --git a/libcrux-kem/src/kem.rs b/libcrux-kem/src/kem.rs index 55035b6c..cfd70c38 100644 --- a/libcrux-kem/src/kem.rs +++ b/libcrux-kem/src/kem.rs @@ -622,7 +622,7 @@ impl Ct { Algorithm::X25519MlKem768Draft00 => { let key: [u8; MlKem768Ciphertext::len() + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; - let (kct, xct) = key.split_at(MlKem768Ciphertext::len()); + let (xct, kct) = key.split_at(32); Ok(Self::X25519MlKem768Draft00( kct.try_into().map_err(|_| Error::InvalidCiphertext)?, xct.try_into().map_err(|_| Error::InvalidCiphertext)?, diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index 719f009b..4a024c71 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -1,3 +1,5 @@ +use libcrux_sha3::shake256; + use crate::{ constant_time_ops::{ compare_ciphertexts_in_constant_time, select_shared_secret_in_constant_time, @@ -136,7 +138,8 @@ fn encapsulate< public_key: &MlKemPublicKey, randomness: [u8; SHARED_SECRET_SIZE], ) -> (MlKemCiphertext, MlKemSharedSecret) { - let mut to_hash: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&randomness); + let hashed_randomness = Hasher::H(&randomness); + let mut to_hash: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&hashed_randomness); to_hash[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(public_key.as_slice())); let hashed = Hasher::G(&to_hash); @@ -157,9 +160,13 @@ fn encapsulate< ETA2_RANDOMNESS_SIZE, Vector, Hasher, - >(public_key.as_slice(), randomness, pseudorandomness); + >(public_key.as_slice(), hashed_randomness, pseudorandomness); + + let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); + kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext.as_slice())); + let shared_secret = shake256::<32>(&kdf_input); let mut shared_secret_array = [0u8; SHARED_SECRET_SIZE]; - shared_secret_array.copy_from_slice(shared_secret); + shared_secret_array.copy_from_slice(&shared_secret); (MlKemCiphertext::from(ciphertext), shared_secret_array) } @@ -232,8 +239,17 @@ pub(crate) fn decapsulate< &expected_ciphertext, ); + let mut kdf_input_rejection_sampled: [u8; 2 * H_DIGEST_SIZE] = + into_padded_array(&implicit_rejection_shared_secret); + kdf_input_rejection_sampled[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext.as_slice())); + let implicit_rejection_shared_secret = shake256::<32>(&kdf_input_rejection_sampled); + + let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); + kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext.as_slice())); + let shared_secret = shake256::<32>(&kdf_input); + select_shared_secret_in_constant_time( - shared_secret, + &shared_secret, &implicit_rejection_shared_secret, selector, ) diff --git a/libcrux-ml-kem/tests/kyber.rs b/libcrux-ml-kem/tests/kyber.rs new file mode 100644 index 00000000..4c87c8a2 --- /dev/null +++ b/libcrux-ml-kem/tests/kyber.rs @@ -0,0 +1,38 @@ +use libcrux_ml_kem::mlkem768; + +#[test] +fn kyber768() { + let key_pair = mlkem768::generate_key_pair(hex::decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f").unwrap().try_into().unwrap()); + + let public_key = key_pair.pk(); + let secret_key = key_pair.sk(); + + assert_eq!( + public_key.as_ref(), + hex::decode("A72C2D9C843EE9F8313ECC7F86D6294D59159D9A879A542E260922ADF999051CC45200C9FFDB60449C49465979272367C083A7D6267A3ED7A7FD47957C219327F7CA73A4007E1627F00B11CC80573C15AEE6640FB8562DFA6B240CA0AD351AC4AC155B96C14C8AB13DD262CDFD51C4BB5572FD616553D17BDD430ACBEA3E95F0B698D66990AB51E5D03783A8B3D278A5720454CF9695CFDCA08485BA099C51CD92A7EA7587C1D15C28E609A81852601B0604010679AA482D51261EC36E36B8719676217FD74C54786488F4B4969C05A8BA27CA3A77CCE73B965923CA554E422B9B61F4754641608AC16C9B8587A32C1C5DD788F88B36B717A46965635DEB67F45B129B99070909C93EB80B42C2B3F3F70343A7CF37E8520E7BCFC416ACA4F18C7981262BA2BFC756AE03278F0EC66DC2057696824BA6769865A601D7148EF6F54E5AF5686AA2906F994CE38A5E0B938F239007003022C03392DF3401B1E4A3A7EBC6161449F73374C8B0140369343D9295FDF511845C4A46EBAAB6CA5492F6800B98C0CC803653A4B1D6E6AAED1932BACC5FEFAA818BA502859BA5494C5F5402C8536A9C4C1888150617F80098F6B2A99C39BC5DC7CF3B5900A21329AB59053ABAA64ED163E859A8B3B3CA3359B750CCC3E710C7AC43C8191CB5D68870C06391C0CB8AEC72B897AC6BE7FBAACC676ED66314C83630E89448C88A1DF04ACEB23ABF2E409EF333C622289C18A2134E650C45257E47475FA33AA537A5A8F7680214716C50D470E3284963CA64F54677AEC54B5272162BF52BC8142E1D4183FC017454A6B5A496831759064024745978CBD51A6CEDC8955DE4CC6D363670A47466E82BE5C23603A17BF22ACDB7CC984AF08C87E14E27753CF587A8EC3447E62C649E887A67C36C9CE98721B697213275646B194F36758673A8ED11284455AFC7A8529F69C97A3C2D7B8C636C0BA55614B768E624E712930F776169B01715725351BC74B47395ED52B25A1313C95164814C34C979CBDFAB85954662CAB485E75087A98CC74BB82CA2D1B5BF2803238480638C40E90B43C7460E7AA917F010151FAB1169987B372ABB59271F7006C24E60236B84B9DDD600623704254617FB498D89E58B0368BCB2103E79353EB587860C1422E476162E425BC2381DB82C6592737E1DD602864B0167A71EC1F223305C02FE25052AF2B3B5A55A0D7A2022D9A798DC0C5874A98702AAF4054C5D80338A5248B5B7BD09C53B5E2A084B047D277A861B1A73BB51488DE04EF573C85230A0470B73175C9FA50594F66A5F50B4150054C93B68186F8B5CBC49316C8548A642B2B36A1D454C7489AC33B2D2CE6668096782A2C1E0866D21A65E16B585E7AF8618BDF3184C1986878508917277B93E10706B1614972B2A94C7310FE9C708C231A1A8AC8D9314A529A97F469BF64962D820648443099A076D55D4CEA824A58304844F99497C10A25148618A315D72CA857D1B04D575B94F85C01D19BEF211BF0AA3362E7041FD16596D808E867B44C4C00D1CDA3418967717F147D0EB21B42AAEE74AC35D0B92414B958531AADF463EC6305AE5ECAF79174002F26DDECC813BF32672E8529D95A4E730A7AB4A3E8F8A8AF979A665EAFD465FC64A0C5F8F3F9003489415899D59A543D8208C54A3166529B53922").unwrap(), + "lhs: computed public key hash, rhs: hash from kat" + ); + assert_eq!( + secret_key.as_ref(), + hex::decode("07638FB69868F3D320E5862BD96933FEB311B362093C9B5D50170BCED43F1B536D9A204BB1F22695950BA1F2A9E8EB828B284488760B3FC84FABA04275D5628E39C5B2471374283C503299C0AB49B66B8BBB56A4186624F919A2BA59BB08D8551880C2BEFC4F87F25F59AB587A79C327D792D54C974A69262FF8A78938289E9A87B688B083E0595FE218B6BB1505941CE2E81A5A64C5AAC60417256985349EE47A52420A5F97477B7236AC76BC70E8288729287EE3E34A3DBC3683C0B7B10029FC203418537E7466BA6385A8FF301EE12708F82AAA1E380FC7A88F8F205AB7E88D7E95952A55BA20D09B79A47141D62BF6EB7DD307B08ECA13A5BC5F6B68581C6865B27BBCDDAB142F4B2CBFF488C8A22705FAA98A2B9EEA3530C76662335CC7EA3A00777725EBCCCD2A4636B2D9122FF3AB77123CE0883C1911115E50C9E8A94194E48DD0D09CFFB3ADCD2C1E92430903D07ADBF00532031575AA7F9E7B5A1F3362DEC936D4043C05F2476C07578BC9CBAF2AB4E382727AD41686A96B2548820BB03B32F11B2811AD62F489E951632ABA0D1DF89680CC8A8B53B481D92A68D70B4EA1C3A6A561C0692882B5CA8CC942A8D495AFCB06DE89498FB935B775908FE7A03E324D54CC19D4E1AABD3593B38B19EE1388FE492B43127E5A504253786A0D69AD32601C28E2C88504A5BA599706023A61363E17C6B9BB59BDC697452CD059451983D738CA3FD034E3F5988854CA05031DB09611498988197C6B30D258DFE26265541C89A4B31D6864E9389B03CB74F7EC4323FB9421A4B9790A26D17B0398A26767350909F84D57B6694DF830664CA8B3C3C03ED2AE67B89006868A68527CCD666459AB7F056671000C6164D3A7F266A14D97CBD7004D6C92CACA770B844A4FA9B182E7B18CA885082AC5646FCB4A14E1685FEB0C9CE3372AB95365C04FD83084F80A23FF10A05BF15F7FA5ACC6C0CB462C33CA524FA6B8BB359043BA68609EAA2536E81D08463B19653B5435BA946C9ADDEB202B04B031CC960DCC12E4518D428B32B257A4FC7313D3A7980D80082E934F9D95C32B0A0191A23604384DD9E079BBBAA266D14C3F756B9F2133107433A4E83FA7187282A809203A4FAF841851833D121AC383843A5E55BC2381425E16C7DB4CC9AB5C1B0D91A47E2B8DE0E582C86B6B0D907BB360B97F40AB5D038F6B75C814B27D9B968D419832BC8C2BEE605EF6E5059D33100D90485D378450014221736C07407CAC260408AA64926619788B8601C2A752D1A6CBF820D7C7A04716203225B3895B9342D147A8185CFC1BB65BA06B4142339903C0AC4651385B45D98A8B19D28CD6BAB088787F7EE1B12461766B43CBCCB96434427D93C065550688F6948ED1B5475A425F1B85209D061C08B56C1CC069F6C0A7C6F29358CAB911087732A649D27C9B98F9A48879387D9B00C25959A71654D6F6A946164513E47A75D005986C2363C09F6B537ECA78B9303A5FA457608A586A653A347DB04DFCC19175B3A301172536062A658A95277570C8852CA8973F4AE123A334047DD711C8927A634A03388A527B034BF7A8170FA702C1F7C23EC32D18A2374890BE9C787A9409C82D192C4BB705A2F996CE405DA72C2D9C843EE9F8313ECC7F86D6294D59159D9A879A542E260922ADF999051CC45200C9FFDB60449C49465979272367C083A7D6267A3ED7A7FD47957C219327F7CA73A4007E1627F00B11CC80573C15AEE6640FB8562DFA6B240CA0AD351AC4AC155B96C14C8AB13DD262CDFD51C4BB5572FD616553D17BDD430ACBEA3E95F0B698D66990AB51E5D03783A8B3D278A5720454CF9695CFDCA08485BA099C51CD92A7EA7587C1D15C28E609A81852601B0604010679AA482D51261EC36E36B8719676217FD74C54786488F4B4969C05A8BA27CA3A77CCE73B965923CA554E422B9B61F4754641608AC16C9B8587A32C1C5DD788F88B36B717A46965635DEB67F45B129B99070909C93EB80B42C2B3F3F70343A7CF37E8520E7BCFC416ACA4F18C7981262BA2BFC756AE03278F0EC66DC2057696824BA6769865A601D7148EF6F54E5AF5686AA2906F994CE38A5E0B938F239007003022C03392DF3401B1E4A3A7EBC6161449F73374C8B0140369343D9295FDF511845C4A46EBAAB6CA5492F6800B98C0CC803653A4B1D6E6AAED1932BACC5FEFAA818BA502859BA5494C5F5402C8536A9C4C1888150617F80098F6B2A99C39BC5DC7CF3B5900A21329AB59053ABAA64ED163E859A8B3B3CA3359B750CCC3E710C7AC43C8191CB5D68870C06391C0CB8AEC72B897AC6BE7FBAACC676ED66314C83630E89448C88A1DF04ACEB23ABF2E409EF333C622289C18A2134E650C45257E47475FA33AA537A5A8F7680214716C50D470E3284963CA64F54677AEC54B5272162BF52BC8142E1D4183FC017454A6B5A496831759064024745978CBD51A6CEDC8955DE4CC6D363670A47466E82BE5C23603A17BF22ACDB7CC984AF08C87E14E27753CF587A8EC3447E62C649E887A67C36C9CE98721B697213275646B194F36758673A8ED11284455AFC7A8529F69C97A3C2D7B8C636C0BA55614B768E624E712930F776169B01715725351BC74B47395ED52B25A1313C95164814C34C979CBDFAB85954662CAB485E75087A98CC74BB82CA2D1B5BF2803238480638C40E90B43C7460E7AA917F010151FAB1169987B372ABB59271F7006C24E60236B84B9DDD600623704254617FB498D89E58B0368BCB2103E79353EB587860C1422E476162E425BC2381DB82C6592737E1DD602864B0167A71EC1F223305C02FE25052AF2B3B5A55A0D7A2022D9A798DC0C5874A98702AAF4054C5D80338A5248B5B7BD09C53B5E2A084B047D277A861B1A73BB51488DE04EF573C85230A0470B73175C9FA50594F66A5F50B4150054C93B68186F8B5CBC49316C8548A642B2B36A1D454C7489AC33B2D2CE6668096782A2C1E0866D21A65E16B585E7AF8618BDF3184C1986878508917277B93E10706B1614972B2A94C7310FE9C708C231A1A8AC8D9314A529A97F469BF64962D820648443099A076D55D4CEA824A58304844F99497C10A25148618A315D72CA857D1B04D575B94F85C01D19BEF211BF0AA3362E7041FD16596D808E867B44C4C00D1CDA3418967717F147D0EB21B42AAEE74AC35D0B92414B958531AADF463EC6305AE5ECAF79174002F26DDECC813BF32672E8529D95A4E730A7AB4A3E8F8A8AF979A665EAFD465FC64A0C5F8F3F9003489415899D59A543D8208C54A3166529B53922D4EC143B50F01423B177895EDEE22BB739F647ECF85F50BC25EF7B5A725DEE868626ED79D451140800E03B59B956F8210E556067407D13DC90FA9E8B872BFB8F").unwrap(), + "lhs: computed secret key hash, rhs: hash from kat" + ); + + let (ciphertext, shared_secret) = + mlkem768::encapsulate(key_pair.public_key(), hex::decode("147c03f7a5bebba406c8fae1874d7f13c80efe79a3a9a874cc09fe76f6997615").unwrap().try_into().unwrap()); + + + assert_eq!( + ciphertext.as_ref(), + hex::decode("B52C56B92A4B7CE9E4CB7C5B1B163167A8A1675B2FDEF84A5B67CA15DB694C9F11BD027C30AE22EC921A1D911599AF0585E48D20DA70DF9F39E32EF95D4C8F44BFEFDAA5DA64F1054631D04D6D3CFD0A540DD7BA3886E4B5F13E878788604C95C096EAB3919F427521419A946C26CC041475D7124CDC01D0373E5B09C7A70603CFDB4FB3405023F2264DC3F983C4FC02A2D1B268F2208A1F6E2A6209BFF12F6F465F0B069C3A7F84F606D8A94064003D6EC114C8E808D3053884C1D5A142FBF20112EB360FDA3F0F28B172AE50F5E7D83801FB3F0064B687187074BD7FE30EDDAA334CF8FC04FA8CED899CEADE4B4F28B68372BAF98FF482A415B731155B75CEB976BE0EA0285BA01A27F1857A8FB377A3AE0C23B2AA9A079BFABFF0D5B2F1CD9B718BEA03C42F343A39B4F142D01AD8ACBB50E38853CF9A50C8B44C3CF671A4A9043B26DDBB24959AD6715C08521855C79A23B9C3D6471749C40725BDD5C2776D43AED20204BAA141EFB3304917474B7F9F7A4B08B1A93DAED98C67495359D37D67F7438BEE5E43585634B26C6B3810D7CDCBC0F6EB877A6087E68ACB8480D3A8CF6900447E49B417F15A53B607A0E216B855970D37406870B4568722DA77A4084703816784E2F16BED18996532C5D8B7F5D214464E5F3F6E905867B0CE119E252A66713253544685D208E1723908A0CE97834652E08AE7BDC881A131B73C71E84D20D68FDEFF4F5D70CD1AF57B78E3491A9865942321800A203C05ED1FEEB5A28E584E19F6535E7F84E4A24F84A72DCAF5648B4A4235DD664464482F03176E888C28BFC6C1CB238CFFA35A321E71791D9EA8ED0878C61121BF8D2A4AB2C1A5E120BC40ABB1892D1715090A0EE48252CA297A99AA0E510CF26B1ADD06CA543E1C5D6BDCD3B9C585C8538045DB5C252EC3C8C3C954D9BE5907094A894E60EAB43538CFEE82E8FFC0791B0D0F43AC1627830A61D56DAD96C62958B0DE780B78BD47A604550DAB83FFF227C324049471F35248CFB849B25724FF704D5277AA352D550958BE3B237DFF473EC2ADBAEA48CA2658AEFCC77BBD4264AB374D70EAE5B964416CE8226A7E3255A0F8D7E2ADCA062BCD6D78D60D1B32E11405BE54B66EF0FDDD567702A3BCCFEDE3C584701269ED14809F06F8968356BB9267FE86E514252E88BB5C30A7ECB3D0E621021EE0FBF7871B09342BF84F55C97EAF86C48189C7FF4DF389F077E2806E5FA73B3E9458A16C7E275F4F602275580EB7B7135FB537FA0CD95D6EA58C108CD8943D70C1643111F4F01CA8A8276A902666ED81B78D168B006F16AAA3D8E4CE4F4D0FB0997E41AEFFB5B3DAA838732F357349447F387776C793C0479DE9E99498CC356FDB0075A703F23C55D47B550EC89B02ADE89329086A50843456FEDC3788AC8D97233C54560467EE1D0F024B18428F0D73B30E19F5C63B9ABF11415BEA4D0170130BAABD33C05E6524E5FB5581B22B0433342248266D0F1053B245CC2462DC44D34965102482A8ED9E4E964D5683E5D45D0C8269").unwrap(), + "lhs: computed ciphertext hash, rhs: hash from akt" + ); + assert_eq!( + shared_secret.as_ref(), + hex::decode("914CB67FE5C38E73BF74181C0AC50428DEDF7750A98058F7D536708774535B29").unwrap(), + "lhs: computed shared secret from encapsulate, rhs: shared secret from kat" + ); + + let shared_secret_from_decapsulate = mlkem768::decapsulate(key_pair.private_key(), &ciphertext); + assert_eq!(shared_secret_from_decapsulate, shared_secret.as_ref(), "lhs: shared secret computed via decapsulation, rhs: shared secret computed via encapsulation"); +} From 5126d6a5bac3f077e4d9ff7fa7ec7d83b9e836d7 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Tue, 18 Jun 2024 18:02:48 +0200 Subject: [PATCH 02/53] Fix swapped private key decoding --- libcrux-kem/src/kem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrux-kem/src/kem.rs b/libcrux-kem/src/kem.rs index cfd70c38..6056c561 100644 --- a/libcrux-kem/src/kem.rs +++ b/libcrux-kem/src/kem.rs @@ -410,7 +410,7 @@ impl PrivateKey { Algorithm::X25519MlKem768Draft00 => { let key: [u8; MlKem768PrivateKey::len() + 32] = bytes.try_into().map_err(|_| Error::InvalidPrivateKey)?; - let (ksk, xsk) = key.split_at(MlKem768PrivateKey::len()); + let (xsk, ksk) = key.split_at(32); Ok(Self::X25519MlKem768Draft00( X25519MlKem768Draft00PrivateKey { mlkem: ksk.try_into().map_err(|_| Error::InvalidPrivateKey)?, From 11d7bb9bd3749fe74160b9c2218ba438033e353f Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 19 Jun 2024 09:04:52 +0200 Subject: [PATCH 03/53] Pull out Kyber encaps --- libcrux-ml-kem/src/ind_cca.rs | 53 +++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index 4a024c71..3d8419a3 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -118,7 +118,7 @@ fn generate_keypair< MlKemKeyPair::from(private_key, MlKemPublicKey::from(public_key)) } -fn encapsulate< +fn kyber_encapsulate< const K: usize, const CIPHERTEXT_SIZE: usize, const PUBLIC_KEY_SIZE: usize, @@ -139,7 +139,51 @@ fn encapsulate< randomness: [u8; SHARED_SECRET_SIZE], ) -> (MlKemCiphertext, MlKemSharedSecret) { let hashed_randomness = Hasher::H(&randomness); - let mut to_hash: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&hashed_randomness); + let (ciphertext, shared_secret) = encapsulate::< + K, + CIPHERTEXT_SIZE, + PUBLIC_KEY_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + VECTOR_U_BLOCK_LEN, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + Vector, + Hasher, + >(public_key, hashed_randomness); + let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); + kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext.as_slice())); + let shared_secret = shake256::<32>(&kdf_input); + + (MlKemCiphertext::from(ciphertext), shared_secret) +} + +fn encapsulate< + const K: usize, + const CIPHERTEXT_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_SIZE: usize, + const C2_SIZE: usize, + const VECTOR_U_COMPRESSION_FACTOR: usize, + const VECTOR_V_COMPRESSION_FACTOR: usize, + const VECTOR_U_BLOCK_LEN: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, + Vector: Operations, + Hasher: Hash, +>( + public_key: &MlKemPublicKey, + randomness: [u8; SHARED_SECRET_SIZE], +) -> (MlKemCiphertext, MlKemSharedSecret) { + let mut to_hash: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&randomness); to_hash[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(public_key.as_slice())); let hashed = Hasher::G(&to_hash); @@ -160,11 +204,8 @@ fn encapsulate< ETA2_RANDOMNESS_SIZE, Vector, Hasher, - >(public_key.as_slice(), hashed_randomness, pseudorandomness); + >(public_key.as_slice(), randomness, pseudorandomness); - let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); - kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext.as_slice())); - let shared_secret = shake256::<32>(&kdf_input); let mut shared_secret_array = [0u8; SHARED_SECRET_SIZE]; shared_secret_array.copy_from_slice(&shared_secret); (MlKemCiphertext::from(ciphertext), shared_secret_array) From 017ac5fa3d294f44fbebce2dc8cb51e842a30337 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 20 Jun 2024 10:18:51 +0200 Subject: [PATCH 04/53] Make Kyber API available behind `kyber` feature --- libcrux-ml-kem/Cargo.toml | 1 + libcrux-ml-kem/src/ind_cca.rs | 103 ++++++----- libcrux-ml-kem/src/ind_cca/instantiations.rs | 87 ++++++++++ libcrux-ml-kem/src/ind_cca/multiplexing.rs | 172 +++++++++++++++++++ libcrux-ml-kem/src/mlkem1024.rs | 112 ++++++++++++ libcrux-ml-kem/src/mlkem512.rs | 112 ++++++++++++ libcrux-ml-kem/src/mlkem768.rs | 111 ++++++++++++ libcrux-ml-kem/tests/kyber.rs | 6 +- 8 files changed, 647 insertions(+), 57 deletions(-) diff --git a/libcrux-ml-kem/Cargo.toml b/libcrux-ml-kem/Cargo.toml index ecb2670a..5198a6e5 100644 --- a/libcrux-ml-kem/Cargo.toml +++ b/libcrux-ml-kem/Cargo.toml @@ -26,6 +26,7 @@ simd128 = ["libcrux-sha3/simd128"] simd256 = ["libcrux-sha3/simd256"] tests = [] # Test utilities. DO NOT USE. std = [] +kyber = [] [dev-dependencies] rand = { version = "0.8" } diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index 3d8419a3..5145d734 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -118,51 +118,6 @@ fn generate_keypair< MlKemKeyPair::from(private_key, MlKemPublicKey::from(public_key)) } -fn kyber_encapsulate< - const K: usize, - const CIPHERTEXT_SIZE: usize, - const PUBLIC_KEY_SIZE: usize, - const T_AS_NTT_ENCODED_SIZE: usize, - const C1_SIZE: usize, - const C2_SIZE: usize, - const VECTOR_U_COMPRESSION_FACTOR: usize, - const VECTOR_V_COMPRESSION_FACTOR: usize, - const VECTOR_U_BLOCK_LEN: usize, - const ETA1: usize, - const ETA1_RANDOMNESS_SIZE: usize, - const ETA2: usize, - const ETA2_RANDOMNESS_SIZE: usize, - Vector: Operations, - Hasher: Hash, ->( - public_key: &MlKemPublicKey, - randomness: [u8; SHARED_SECRET_SIZE], -) -> (MlKemCiphertext, MlKemSharedSecret) { - let hashed_randomness = Hasher::H(&randomness); - let (ciphertext, shared_secret) = encapsulate::< - K, - CIPHERTEXT_SIZE, - PUBLIC_KEY_SIZE, - T_AS_NTT_ENCODED_SIZE, - C1_SIZE, - C2_SIZE, - VECTOR_U_COMPRESSION_FACTOR, - VECTOR_V_COMPRESSION_FACTOR, - VECTOR_U_BLOCK_LEN, - ETA1, - ETA1_RANDOMNESS_SIZE, - ETA2, - ETA2_RANDOMNESS_SIZE, - Vector, - Hasher, - >(public_key, hashed_randomness); - let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); - kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext.as_slice())); - let shared_secret = shake256::<32>(&kdf_input); - - (MlKemCiphertext::from(ciphertext), shared_secret) -} - fn encapsulate< const K: usize, const CIPHERTEXT_SIZE: usize, @@ -179,10 +134,12 @@ fn encapsulate< const ETA2_RANDOMNESS_SIZE: usize, Vector: Operations, Hasher: Hash, + Scheme: Variant, >( public_key: &MlKemPublicKey, randomness: [u8; SHARED_SECRET_SIZE], ) -> (MlKemCiphertext, MlKemSharedSecret) { + let randomness = Scheme::entropy_preprocess(&randomness); let mut to_hash: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&randomness); to_hash[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(public_key.as_slice())); @@ -206,8 +163,8 @@ fn encapsulate< Hasher, >(public_key.as_slice(), randomness, pseudorandomness); - let mut shared_secret_array = [0u8; SHARED_SECRET_SIZE]; - shared_secret_array.copy_from_slice(&shared_secret); + let shared_secret_array = Scheme::kdf(shared_secret, &ciphertext); + (MlKemCiphertext::from(ciphertext), shared_secret_array) } @@ -230,6 +187,7 @@ pub(crate) fn decapsulate< const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize, Vector: Operations, Hasher: Hash, + Scheme: Variant, >( private_key: &MlKemPrivateKey, ciphertext: &MlKemCiphertext, @@ -280,14 +238,9 @@ pub(crate) fn decapsulate< &expected_ciphertext, ); - let mut kdf_input_rejection_sampled: [u8; 2 * H_DIGEST_SIZE] = - into_padded_array(&implicit_rejection_shared_secret); - kdf_input_rejection_sampled[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext.as_slice())); - let implicit_rejection_shared_secret = shake256::<32>(&kdf_input_rejection_sampled); - - let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); - kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext.as_slice())); - let shared_secret = shake256::<32>(&kdf_input); + let implicit_rejection_shared_secret = + Scheme::kdf(&implicit_rejection_shared_secret, ciphertext.as_slice()); + let shared_secret = Scheme::kdf(&shared_secret, ciphertext.as_slice()); select_shared_secret_in_constant_time( &shared_secret, @@ -295,3 +248,43 @@ pub(crate) fn decapsulate< selector, ) } + +pub(crate) trait Variant> { + fn kdf(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32]; + + fn entropy_preprocess(randomness: &[u8]) -> [u8; 32]; +} + +pub(crate) struct Kyber {} + +impl> + Variant for Kyber +{ + fn kdf(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32] { + let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); + kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext)); + shake256::<32>(&kdf_input) + } + + fn entropy_preprocess(randomness: &[u8]) -> [u8; 32] { + Hasher::H(&randomness) + } +} + +pub(crate) struct MlKem {} + +impl> Variant + for MlKem +{ + fn kdf(shared_secret: &[u8], _ciphertext: &[u8]) -> [u8; 32] { + let mut shared_secret_array = [0u8; SHARED_SECRET_SIZE]; + shared_secret_array.copy_from_slice(shared_secret); + shared_secret_array + } + + fn entropy_preprocess(randomness: &[u8]) -> [u8; 32] { + let mut randomness_array = [0u8; 32]; + randomness_array.copy_from_slice(randomness); + randomness_array + } +} diff --git a/libcrux-ml-kem/src/ind_cca/instantiations.rs b/libcrux-ml-kem/src/ind_cca/instantiations.rs index 72f17a93..66bfb56c 100644 --- a/libcrux-ml-kem/src/ind_cca/instantiations.rs +++ b/libcrux-ml-kem/src/ind_cca/instantiations.rs @@ -48,6 +48,45 @@ macro_rules! instantiate { } /// Portable encapsualte + #[cfg(feature = "kyber")] + pub(crate) fn kyber_encapsulate< + const K: usize, + const CIPHERTEXT_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_SIZE: usize, + const C2_SIZE: usize, + const VECTOR_U_COMPRESSION_FACTOR: usize, + const VECTOR_V_COMPRESSION_FACTOR: usize, + const VECTOR_U_BLOCK_LEN: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, + >( + public_key: &MlKemPublicKey, + randomness: [u8; SHARED_SECRET_SIZE], + ) -> (MlKemCiphertext, MlKemSharedSecret) { + crate::ind_cca::encapsulate::< + K, + CIPHERTEXT_SIZE, + PUBLIC_KEY_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + VECTOR_U_BLOCK_LEN, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + $vector, + $hash, + crate::ind_cca::Kyber, + >(public_key, randomness) + } + pub(crate) fn encapsulate< const K: usize, const CIPHERTEXT_SIZE: usize, @@ -82,9 +121,56 @@ macro_rules! instantiate { ETA2_RANDOMNESS_SIZE, $vector, $hash, + crate::ind_cca::MlKem, >(public_key, randomness) } + /// Portable decapsulate + #[cfg(feature = "kyber")] + pub fn kyber_decapsulate< + const K: usize, + const SECRET_KEY_SIZE: usize, + const CPA_SECRET_KEY_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const CIPHERTEXT_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_SIZE: usize, + const C2_SIZE: usize, + const VECTOR_U_COMPRESSION_FACTOR: usize, + const VECTOR_V_COMPRESSION_FACTOR: usize, + const C1_BLOCK_SIZE: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, + const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize, + >( + private_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, + ) -> MlKemSharedSecret { + crate::ind_cca::decapsulate::< + K, + SECRET_KEY_SIZE, + CPA_SECRET_KEY_SIZE, + PUBLIC_KEY_SIZE, + CIPHERTEXT_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + C1_BLOCK_SIZE, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + $vector, + $hash, + crate::ind_cca::Kyber, + >(private_key, ciphertext) + } + /// Portable decapsulate pub fn decapsulate< const K: usize, @@ -126,6 +212,7 @@ macro_rules! instantiate { IMPLICIT_REJECTION_HASH_INPUT_SIZE, $vector, $hash, + crate::ind_cca::MlKem, >(private_key, ciphertext) } } diff --git a/libcrux-ml-kem/src/ind_cca/multiplexing.rs b/libcrux-ml-kem/src/ind_cca/multiplexing.rs index 4a49471c..a1e1365f 100644 --- a/libcrux-ml-kem/src/ind_cca/multiplexing.rs +++ b/libcrux-ml-kem/src/ind_cca/multiplexing.rs @@ -25,6 +25,26 @@ use instantiations::portable::{ generate_keypair as generate_keypair_neon, validate_public_key as validate_public_key_neon, }; +#[cfg(all(feature = "simd256", feature = "kyber"))] +use instantiations::avx2::{ + kyber_decapsulate as kyber_decapsulate_avx2, kyber_encapsulate as kyber_encapsulate_avx2, +}; + +#[cfg(all(feature = "simd128", feature = "kyber"))] +use instantiations::neon::{ + kyber_decapsulate as kyber_decapsulate_neon, kyber_encapsulate as kyber_encapsulate_neon, +}; + +#[cfg(all(not(feature = "simd256"), feature = "kyber"))] +use instantiations::portable::{ + kyber_decapsulate as kyber_decapsulate_avx2, kyber_encapsulate as kyber_encapsulate_avx2, +}; + +#[cfg(all(not(feature = "simd128"), feature = "kyber"))] +use instantiations::portable::{ + kyber_decapsulate as kyber_decapsulate_neon, kyber_encapsulate as kyber_encapsulate_neon, +}; + pub(crate) fn validate_public_key< const K: usize, const RANKED_BYTES_PER_RING_ELEMENT: usize, @@ -90,6 +110,76 @@ pub(crate) fn generate_keypair< } } +#[cfg(feature = "kyber")] +pub(crate) fn kyber_encapsulate< + const K: usize, + const CIPHERTEXT_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_SIZE: usize, + const C2_SIZE: usize, + const VECTOR_U_COMPRESSION_FACTOR: usize, + const VECTOR_V_COMPRESSION_FACTOR: usize, + const VECTOR_U_BLOCK_LEN: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, +>( + public_key: &MlKemPublicKey, + randomness: [u8; SHARED_SECRET_SIZE], +) -> (MlKemCiphertext, MlKemSharedSecret) { + if libcrux_platform::simd256_support() { + kyber_encapsulate_avx2::< + K, + CIPHERTEXT_SIZE, + PUBLIC_KEY_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + VECTOR_U_BLOCK_LEN, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) + } else if libcrux_platform::simd128_support() { + kyber_encapsulate_neon::< + K, + CIPHERTEXT_SIZE, + PUBLIC_KEY_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + VECTOR_U_BLOCK_LEN, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) + } else { + instantiations::portable::kyber_encapsulate::< + K, + CIPHERTEXT_SIZE, + PUBLIC_KEY_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + VECTOR_U_BLOCK_LEN, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) + } +} + pub(crate) fn encapsulate< const K: usize, const CIPHERTEXT_SIZE: usize, @@ -159,6 +249,88 @@ pub(crate) fn encapsulate< } } +#[cfg(feature = "kyber")] +pub(crate) fn kyber_decapsulate< + const K: usize, + const SECRET_KEY_SIZE: usize, + const CPA_SECRET_KEY_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const CIPHERTEXT_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_SIZE: usize, + const C2_SIZE: usize, + const VECTOR_U_COMPRESSION_FACTOR: usize, + const VECTOR_V_COMPRESSION_FACTOR: usize, + const C1_BLOCK_SIZE: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, + const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize, +>( + private_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, +) -> MlKemSharedSecret { + if libcrux_platform::simd256_support() { + kyber_decapsulate_avx2::< + K, + SECRET_KEY_SIZE, + CPA_SECRET_KEY_SIZE, + PUBLIC_KEY_SIZE, + CIPHERTEXT_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + C1_BLOCK_SIZE, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) + } else if libcrux_platform::simd128_support() { + kyber_decapsulate_neon::< + K, + SECRET_KEY_SIZE, + CPA_SECRET_KEY_SIZE, + PUBLIC_KEY_SIZE, + CIPHERTEXT_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + C1_BLOCK_SIZE, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) + } else { + instantiations::portable::kyber_decapsulate::< + K, + SECRET_KEY_SIZE, + CPA_SECRET_KEY_SIZE, + PUBLIC_KEY_SIZE, + CIPHERTEXT_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + C1_BLOCK_SIZE, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) + } +} + pub(crate) fn decapsulate< const K: usize, const SECRET_KEY_SIZE: usize, diff --git a/libcrux-ml-kem/src/mlkem1024.rs b/libcrux-ml-kem/src/mlkem1024.rs index 2a1a28a3..49767d18 100644 --- a/libcrux-ml-kem/src/mlkem1024.rs +++ b/libcrux-ml-kem/src/mlkem1024.rs @@ -111,6 +111,33 @@ macro_rules! instantiate { >(public_key, randomness) } + /// Encapsulate Kyber 1024 + /// + /// Generates an ([`MlKem1024Ciphertext`], [`MlKemSharedSecret`]) tuple. + /// The input is a reference to an [`MlKem1024PublicKey`] and [`SHARED_SECRET_SIZE`] + /// bytes of `randomness`. + #[cfg(feature = "kyber")] + pub fn kyber_encapsulate( + public_key: &MlKem1024PublicKey, + randomness: [u8; SHARED_SECRET_SIZE], + ) -> (MlKem1024Ciphertext, MlKemSharedSecret) { + p::kyber_encapsulate::< + RANK_1024, + CPA_PKE_CIPHERTEXT_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + T_AS_NTT_ENCODED_SIZE_1024, + C1_SIZE_1024, + C2_SIZE_1024, + VECTOR_U_COMPRESSION_FACTOR_1024, + VECTOR_V_COMPRESSION_FACTOR_1024, + C1_BLOCK_SIZE_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) + } + /// Decapsulate ML-KEM 1024 /// /// Generates an [`MlKemSharedSecret`]. @@ -138,6 +165,35 @@ macro_rules! instantiate { IMPLICIT_REJECTION_HASH_INPUT_SIZE, >(private_key, ciphertext) } + + /// Decapsulate Kyber 1024 + /// + /// Generates an [`MlKemSharedSecret`]. + /// The input is a reference to an [`MlKem1024PrivateKey`] and an [`MlKem1024Ciphertext`]. + #[cfg(feature = "kyber")] + pub fn kyber_decapsulate( + private_key: &MlKem1024PrivateKey, + ciphertext: &MlKem1024Ciphertext, + ) -> MlKemSharedSecret { + p::kyber_decapsulate::< + RANK_1024, + SECRET_KEY_SIZE_1024, + CPA_PKE_SECRET_KEY_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + CPA_PKE_CIPHERTEXT_SIZE_1024, + T_AS_NTT_ENCODED_SIZE_1024, + C1_SIZE_1024, + C2_SIZE_1024, + VECTOR_U_COMPRESSION_FACTOR_1024, + VECTOR_V_COMPRESSION_FACTOR_1024, + C1_BLOCK_SIZE_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) + } } }; } @@ -215,6 +271,33 @@ pub fn encapsulate( >(public_key, randomness) } +/// Encapsulate Kyber 1024 +/// +/// Generates an ([`MlKem1024Ciphertext`], [`MlKemSharedSecret`]) tuple. +/// The input is a reference to an [`MlKem1024PublicKey`] and [`SHARED_SECRET_SIZE`] +/// bytes of `randomness`. +#[cfg(all(not(eurydice), feature = "kyber"))] +pub fn kyber_encapsulate( + public_key: &MlKem1024PublicKey, + randomness: [u8; SHARED_SECRET_SIZE], +) -> (MlKem1024Ciphertext, MlKemSharedSecret) { + multiplexing::kyber_encapsulate::< + RANK_1024, + CPA_PKE_CIPHERTEXT_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + T_AS_NTT_ENCODED_SIZE_1024, + C1_SIZE_1024, + C2_SIZE_1024, + VECTOR_U_COMPRESSION_FACTOR_1024, + VECTOR_V_COMPRESSION_FACTOR_1024, + C1_BLOCK_SIZE_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) +} + /// Decapsulate ML-KEM 1024 /// /// Generates an [`MlKemSharedSecret`]. @@ -243,3 +326,32 @@ pub fn decapsulate( IMPLICIT_REJECTION_HASH_INPUT_SIZE, >(private_key, ciphertext) } + +/// Decapsulate Kyber 1024 +/// +/// Generates an [`MlKemSharedSecret`]. +/// The input is a reference to an [`MlKem1024PrivateKey`] and an [`MlKem1024Ciphertext`]. +#[cfg(all(not(eurydice), feature = "kyber"))] +pub fn kyber_decapsulate( + private_key: &MlKem1024PrivateKey, + ciphertext: &MlKem1024Ciphertext, +) -> MlKemSharedSecret { + multiplexing::kyber_decapsulate::< + RANK_1024, + SECRET_KEY_SIZE_1024, + CPA_PKE_SECRET_KEY_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + CPA_PKE_CIPHERTEXT_SIZE_1024, + T_AS_NTT_ENCODED_SIZE_1024, + C1_SIZE_1024, + C2_SIZE_1024, + VECTOR_U_COMPRESSION_FACTOR_1024, + VECTOR_V_COMPRESSION_FACTOR_1024, + C1_BLOCK_SIZE_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) +} diff --git a/libcrux-ml-kem/src/mlkem512.rs b/libcrux-ml-kem/src/mlkem512.rs index f457e551..e0e6447d 100644 --- a/libcrux-ml-kem/src/mlkem512.rs +++ b/libcrux-ml-kem/src/mlkem512.rs @@ -107,6 +107,33 @@ macro_rules! instantiate { >(public_key, randomness) } + /// Encapsulate Kyber 512 + /// + /// Generates an ([`MlKem512Ciphertext`], [`MlKemSharedSecret`]) tuple. + /// The input is a reference to an [`MlKem512PublicKey`] and [`SHARED_SECRET_SIZE`] + /// bytes of `randomness`. + #[cfg(feature = "kyber")] + pub fn kyber_encapsulate( + public_key: &MlKem512PublicKey, + randomness: [u8; SHARED_SECRET_SIZE], + ) -> (MlKem512Ciphertext, MlKemSharedSecret) { + p::kyber_encapsulate::< + RANK_512, + CPA_PKE_CIPHERTEXT_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + T_AS_NTT_ENCODED_SIZE_512, + C1_SIZE_512, + C2_SIZE_512, + VECTOR_U_COMPRESSION_FACTOR_512, + VECTOR_V_COMPRESSION_FACTOR_512, + C1_BLOCK_SIZE_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) + } + /// Decapsulate ML-KEM 512 /// /// Generates an [`MlKemSharedSecret`]. @@ -134,6 +161,35 @@ macro_rules! instantiate { IMPLICIT_REJECTION_HASH_INPUT_SIZE, >(private_key, ciphertext) } + + /// Decapsulate ML-KEM 512 + /// + /// Generates an [`MlKemSharedSecret`]. + /// The input is a reference to an [`MlKem512PrivateKey`] and an [`MlKem512Ciphertext`]. + #[cfg(feature = "kyber")] + pub fn kyber_decapsulate( + private_key: &MlKem512PrivateKey, + ciphertext: &MlKem512Ciphertext, + ) -> MlKemSharedSecret { + p::kyber_decapsulate::< + RANK_512, + SECRET_KEY_SIZE_512, + CPA_PKE_SECRET_KEY_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + CPA_PKE_CIPHERTEXT_SIZE_512, + T_AS_NTT_ENCODED_SIZE_512, + C1_SIZE_512, + C2_SIZE_512, + VECTOR_U_COMPRESSION_FACTOR_512, + VECTOR_V_COMPRESSION_FACTOR_512, + C1_BLOCK_SIZE_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) + } } }; } @@ -209,6 +265,33 @@ pub fn encapsulate( >(public_key, randomness) } +/// Encapsulate Kyber 512 +/// +/// Generates an ([`MlKem512Ciphertext`], [`MlKemSharedSecret`]) tuple. +/// The input is a reference to an [`MlKem512PublicKey`] and [`SHARED_SECRET_SIZE`] +/// bytes of `randomness`. +#[cfg(all(not(eurydice), feature = "kyber"))] +pub fn kyber_encapsulate( + public_key: &MlKem512PublicKey, + randomness: [u8; SHARED_SECRET_SIZE], +) -> (MlKem512Ciphertext, MlKemSharedSecret) { + multiplexing::kyber_encapsulate::< + RANK_512, + CPA_PKE_CIPHERTEXT_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + T_AS_NTT_ENCODED_SIZE_512, + C1_SIZE_512, + C2_SIZE_512, + VECTOR_U_COMPRESSION_FACTOR_512, + VECTOR_V_COMPRESSION_FACTOR_512, + C1_BLOCK_SIZE_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) +} + /// Decapsulate ML-KEM 512 /// /// Generates an [`MlKemSharedSecret`]. @@ -237,3 +320,32 @@ pub fn decapsulate( IMPLICIT_REJECTION_HASH_INPUT_SIZE, >(private_key, ciphertext) } + +/// Decapsulate Kyber 512 +/// +/// Generates an [`MlKemSharedSecret`]. +/// The input is a reference to an [`MlKem512PrivateKey`] and an [`MlKem512Ciphertext`]. +#[cfg(all(not(eurydice), feature = "kyber"))] +pub fn kyber_decapsulate( + private_key: &MlKem512PrivateKey, + ciphertext: &MlKem512Ciphertext, +) -> MlKemSharedSecret { + multiplexing::kyber_decapsulate::< + RANK_512, + SECRET_KEY_SIZE_512, + CPA_PKE_SECRET_KEY_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + CPA_PKE_CIPHERTEXT_SIZE_512, + T_AS_NTT_ENCODED_SIZE_512, + C1_SIZE_512, + C2_SIZE_512, + VECTOR_U_COMPRESSION_FACTOR_512, + VECTOR_V_COMPRESSION_FACTOR_512, + C1_BLOCK_SIZE_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) +} diff --git a/libcrux-ml-kem/src/mlkem768.rs b/libcrux-ml-kem/src/mlkem768.rs index d946eb78..f7b01846 100644 --- a/libcrux-ml-kem/src/mlkem768.rs +++ b/libcrux-ml-kem/src/mlkem768.rs @@ -108,6 +108,33 @@ macro_rules! instantiate { >(public_key, randomness) } + /// Encapsulate Kyber 768 + /// + /// Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple. + /// The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`] + /// bytes of `randomness`. + #[cfg(feature = "kyber")] + pub fn kyber_encapsulate( + public_key: &MlKem768PublicKey, + randomness: [u8; SHARED_SECRET_SIZE], + ) -> (MlKem768Ciphertext, MlKemSharedSecret) { + p::kyber_encapsulate::< + RANK_768, + CPA_PKE_CIPHERTEXT_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + T_AS_NTT_ENCODED_SIZE_768, + C1_SIZE_768, + C2_SIZE_768, + VECTOR_U_COMPRESSION_FACTOR_768, + VECTOR_V_COMPRESSION_FACTOR_768, + C1_BLOCK_SIZE_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) + } + /// Decapsulate ML-KEM 768 /// /// Generates an [`MlKemSharedSecret`]. @@ -135,6 +162,34 @@ macro_rules! instantiate { IMPLICIT_REJECTION_HASH_INPUT_SIZE, >(private_key, ciphertext) } + /// Decapsulate Kyber 768 + /// + /// Generates an [`MlKemSharedSecret`]. + /// The input is a reference to an [`MlKem768PrivateKey`] and an [`MlKem768Ciphertext`]. + #[cfg(feature = "kyber")] + pub fn kyber_decapsulate( + private_key: &MlKem768PrivateKey, + ciphertext: &MlKem768Ciphertext, + ) -> MlKemSharedSecret { + p::kyber_decapsulate::< + RANK_768, + SECRET_KEY_SIZE_768, + CPA_PKE_SECRET_KEY_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + CPA_PKE_CIPHERTEXT_SIZE_768, + T_AS_NTT_ENCODED_SIZE_768, + C1_SIZE_768, + C2_SIZE_768, + VECTOR_U_COMPRESSION_FACTOR_768, + VECTOR_V_COMPRESSION_FACTOR_768, + C1_BLOCK_SIZE_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) + } } }; } @@ -217,6 +272,33 @@ pub fn encapsulate( >(public_key, randomness) } +/// Encapsulate Kyber 768 +/// +/// Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple. +/// The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`] +/// bytes of `randomness`. +#[cfg(all(not(eurydice), feature = "kyber"))] +pub fn kyber_encapsulate( + public_key: &MlKem768PublicKey, + randomness: [u8; SHARED_SECRET_SIZE], +) -> (MlKem768Ciphertext, MlKemSharedSecret) { + multiplexing::kyber_encapsulate::< + RANK_768, + CPA_PKE_CIPHERTEXT_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + T_AS_NTT_ENCODED_SIZE_768, + C1_SIZE_768, + C2_SIZE_768, + VECTOR_U_COMPRESSION_FACTOR_768, + VECTOR_V_COMPRESSION_FACTOR_768, + C1_BLOCK_SIZE_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) +} + /// Decapsulate ML-KEM 768 /// /// Generates an [`MlKemSharedSecret`]. @@ -246,6 +328,35 @@ pub fn decapsulate( >(private_key, ciphertext) } +/// Decapsulate ML-KEM 768 +/// +/// Generates an [`MlKemSharedSecret`]. +/// The input is a reference to an [`MlKem768PrivateKey`] and an [`MlKem768Ciphertext`]. +#[cfg(all(not(eurydice), feature = "kyber"))] +pub fn kyber_decapsulate( + private_key: &MlKem768PrivateKey, + ciphertext: &MlKem768Ciphertext, +) -> MlKemSharedSecret { + multiplexing::kyber_decapsulate::< + RANK_768, + SECRET_KEY_SIZE_768, + CPA_PKE_SECRET_KEY_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + CPA_PKE_CIPHERTEXT_SIZE_768, + T_AS_NTT_ENCODED_SIZE_768, + C1_SIZE_768, + C2_SIZE_768, + VECTOR_U_COMPRESSION_FACTOR_768, + VECTOR_V_COMPRESSION_FACTOR_768, + C1_BLOCK_SIZE_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) +} + #[cfg(test)] mod tests { use rand::{rngs::OsRng, RngCore}; diff --git a/libcrux-ml-kem/tests/kyber.rs b/libcrux-ml-kem/tests/kyber.rs index 4c87c8a2..830e1904 100644 --- a/libcrux-ml-kem/tests/kyber.rs +++ b/libcrux-ml-kem/tests/kyber.rs @@ -1,6 +1,8 @@ use libcrux_ml_kem::mlkem768; + #[test] +#[cfg(feature = "kyber")] fn kyber768() { let key_pair = mlkem768::generate_key_pair(hex::decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f").unwrap().try_into().unwrap()); @@ -19,7 +21,7 @@ fn kyber768() { ); let (ciphertext, shared_secret) = - mlkem768::encapsulate(key_pair.public_key(), hex::decode("147c03f7a5bebba406c8fae1874d7f13c80efe79a3a9a874cc09fe76f6997615").unwrap().try_into().unwrap()); + mlkem768::kyber_encapsulate(key_pair.public_key(), hex::decode("147c03f7a5bebba406c8fae1874d7f13c80efe79a3a9a874cc09fe76f6997615").unwrap().try_into().unwrap()); assert_eq!( @@ -33,6 +35,6 @@ fn kyber768() { "lhs: computed shared secret from encapsulate, rhs: shared secret from kat" ); - let shared_secret_from_decapsulate = mlkem768::decapsulate(key_pair.private_key(), &ciphertext); + let shared_secret_from_decapsulate = mlkem768::kyber_decapsulate(key_pair.private_key(), &ciphertext); assert_eq!(shared_secret_from_decapsulate, shared_secret.as_ref(), "lhs: shared secret computed via decapsulation, rhs: shared secret computed via encapsulation"); } From c7beed28e127ae39d07c9f7537ac90b0b21bd472 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 20 Jun 2024 10:30:11 +0200 Subject: [PATCH 05/53] Format --- libcrux-ml-kem/src/ind_cca.rs | 8 ++------ libcrux-ml-kem/tests/kyber.rs | 18 +++++++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index 5145d734..bb32cfdf 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -257,9 +257,7 @@ pub(crate) trait Variant> { pub(crate) struct Kyber {} -impl> - Variant for Kyber -{ +impl> Variant for Kyber { fn kdf(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32] { let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext)); @@ -273,9 +271,7 @@ impl> pub(crate) struct MlKem {} -impl> Variant - for MlKem -{ +impl> Variant for MlKem { fn kdf(shared_secret: &[u8], _ciphertext: &[u8]) -> [u8; 32] { let mut shared_secret_array = [0u8; SHARED_SECRET_SIZE]; shared_secret_array.copy_from_slice(shared_secret); diff --git a/libcrux-ml-kem/tests/kyber.rs b/libcrux-ml-kem/tests/kyber.rs index 830e1904..de4d220a 100644 --- a/libcrux-ml-kem/tests/kyber.rs +++ b/libcrux-ml-kem/tests/kyber.rs @@ -1,6 +1,5 @@ use libcrux_ml_kem::mlkem768; - #[test] #[cfg(feature = "kyber")] fn kyber768() { @@ -9,20 +8,24 @@ fn kyber768() { let public_key = key_pair.pk(); let secret_key = key_pair.sk(); - assert_eq!( + assert_eq!( public_key.as_ref(), hex::decode("A72C2D9C843EE9F8313ECC7F86D6294D59159D9A879A542E260922ADF999051CC45200C9FFDB60449C49465979272367C083A7D6267A3ED7A7FD47957C219327F7CA73A4007E1627F00B11CC80573C15AEE6640FB8562DFA6B240CA0AD351AC4AC155B96C14C8AB13DD262CDFD51C4BB5572FD616553D17BDD430ACBEA3E95F0B698D66990AB51E5D03783A8B3D278A5720454CF9695CFDCA08485BA099C51CD92A7EA7587C1D15C28E609A81852601B0604010679AA482D51261EC36E36B8719676217FD74C54786488F4B4969C05A8BA27CA3A77CCE73B965923CA554E422B9B61F4754641608AC16C9B8587A32C1C5DD788F88B36B717A46965635DEB67F45B129B99070909C93EB80B42C2B3F3F70343A7CF37E8520E7BCFC416ACA4F18C7981262BA2BFC756AE03278F0EC66DC2057696824BA6769865A601D7148EF6F54E5AF5686AA2906F994CE38A5E0B938F239007003022C03392DF3401B1E4A3A7EBC6161449F73374C8B0140369343D9295FDF511845C4A46EBAAB6CA5492F6800B98C0CC803653A4B1D6E6AAED1932BACC5FEFAA818BA502859BA5494C5F5402C8536A9C4C1888150617F80098F6B2A99C39BC5DC7CF3B5900A21329AB59053ABAA64ED163E859A8B3B3CA3359B750CCC3E710C7AC43C8191CB5D68870C06391C0CB8AEC72B897AC6BE7FBAACC676ED66314C83630E89448C88A1DF04ACEB23ABF2E409EF333C622289C18A2134E650C45257E47475FA33AA537A5A8F7680214716C50D470E3284963CA64F54677AEC54B5272162BF52BC8142E1D4183FC017454A6B5A496831759064024745978CBD51A6CEDC8955DE4CC6D363670A47466E82BE5C23603A17BF22ACDB7CC984AF08C87E14E27753CF587A8EC3447E62C649E887A67C36C9CE98721B697213275646B194F36758673A8ED11284455AFC7A8529F69C97A3C2D7B8C636C0BA55614B768E624E712930F776169B01715725351BC74B47395ED52B25A1313C95164814C34C979CBDFAB85954662CAB485E75087A98CC74BB82CA2D1B5BF2803238480638C40E90B43C7460E7AA917F010151FAB1169987B372ABB59271F7006C24E60236B84B9DDD600623704254617FB498D89E58B0368BCB2103E79353EB587860C1422E476162E425BC2381DB82C6592737E1DD602864B0167A71EC1F223305C02FE25052AF2B3B5A55A0D7A2022D9A798DC0C5874A98702AAF4054C5D80338A5248B5B7BD09C53B5E2A084B047D277A861B1A73BB51488DE04EF573C85230A0470B73175C9FA50594F66A5F50B4150054C93B68186F8B5CBC49316C8548A642B2B36A1D454C7489AC33B2D2CE6668096782A2C1E0866D21A65E16B585E7AF8618BDF3184C1986878508917277B93E10706B1614972B2A94C7310FE9C708C231A1A8AC8D9314A529A97F469BF64962D820648443099A076D55D4CEA824A58304844F99497C10A25148618A315D72CA857D1B04D575B94F85C01D19BEF211BF0AA3362E7041FD16596D808E867B44C4C00D1CDA3418967717F147D0EB21B42AAEE74AC35D0B92414B958531AADF463EC6305AE5ECAF79174002F26DDECC813BF32672E8529D95A4E730A7AB4A3E8F8A8AF979A665EAFD465FC64A0C5F8F3F9003489415899D59A543D8208C54A3166529B53922").unwrap(), "lhs: computed public key hash, rhs: hash from kat" ); assert_eq!( - secret_key.as_ref(), + secret_key.as_ref(), hex::decode("07638FB69868F3D320E5862BD96933FEB311B362093C9B5D50170BCED43F1B536D9A204BB1F22695950BA1F2A9E8EB828B284488760B3FC84FABA04275D5628E39C5B2471374283C503299C0AB49B66B8BBB56A4186624F919A2BA59BB08D8551880C2BEFC4F87F25F59AB587A79C327D792D54C974A69262FF8A78938289E9A87B688B083E0595FE218B6BB1505941CE2E81A5A64C5AAC60417256985349EE47A52420A5F97477B7236AC76BC70E8288729287EE3E34A3DBC3683C0B7B10029FC203418537E7466BA6385A8FF301EE12708F82AAA1E380FC7A88F8F205AB7E88D7E95952A55BA20D09B79A47141D62BF6EB7DD307B08ECA13A5BC5F6B68581C6865B27BBCDDAB142F4B2CBFF488C8A22705FAA98A2B9EEA3530C76662335CC7EA3A00777725EBCCCD2A4636B2D9122FF3AB77123CE0883C1911115E50C9E8A94194E48DD0D09CFFB3ADCD2C1E92430903D07ADBF00532031575AA7F9E7B5A1F3362DEC936D4043C05F2476C07578BC9CBAF2AB4E382727AD41686A96B2548820BB03B32F11B2811AD62F489E951632ABA0D1DF89680CC8A8B53B481D92A68D70B4EA1C3A6A561C0692882B5CA8CC942A8D495AFCB06DE89498FB935B775908FE7A03E324D54CC19D4E1AABD3593B38B19EE1388FE492B43127E5A504253786A0D69AD32601C28E2C88504A5BA599706023A61363E17C6B9BB59BDC697452CD059451983D738CA3FD034E3F5988854CA05031DB09611498988197C6B30D258DFE26265541C89A4B31D6864E9389B03CB74F7EC4323FB9421A4B9790A26D17B0398A26767350909F84D57B6694DF830664CA8B3C3C03ED2AE67B89006868A68527CCD666459AB7F056671000C6164D3A7F266A14D97CBD7004D6C92CACA770B844A4FA9B182E7B18CA885082AC5646FCB4A14E1685FEB0C9CE3372AB95365C04FD83084F80A23FF10A05BF15F7FA5ACC6C0CB462C33CA524FA6B8BB359043BA68609EAA2536E81D08463B19653B5435BA946C9ADDEB202B04B031CC960DCC12E4518D428B32B257A4FC7313D3A7980D80082E934F9D95C32B0A0191A23604384DD9E079BBBAA266D14C3F756B9F2133107433A4E83FA7187282A809203A4FAF841851833D121AC383843A5E55BC2381425E16C7DB4CC9AB5C1B0D91A47E2B8DE0E582C86B6B0D907BB360B97F40AB5D038F6B75C814B27D9B968D419832BC8C2BEE605EF6E5059D33100D90485D378450014221736C07407CAC260408AA64926619788B8601C2A752D1A6CBF820D7C7A04716203225B3895B9342D147A8185CFC1BB65BA06B4142339903C0AC4651385B45D98A8B19D28CD6BAB088787F7EE1B12461766B43CBCCB96434427D93C065550688F6948ED1B5475A425F1B85209D061C08B56C1CC069F6C0A7C6F29358CAB911087732A649D27C9B98F9A48879387D9B00C25959A71654D6F6A946164513E47A75D005986C2363C09F6B537ECA78B9303A5FA457608A586A653A347DB04DFCC19175B3A301172536062A658A95277570C8852CA8973F4AE123A334047DD711C8927A634A03388A527B034BF7A8170FA702C1F7C23EC32D18A2374890BE9C787A9409C82D192C4BB705A2F996CE405DA72C2D9C843EE9F8313ECC7F86D6294D59159D9A879A542E260922ADF999051CC45200C9FFDB60449C49465979272367C083A7D6267A3ED7A7FD47957C219327F7CA73A4007E1627F00B11CC80573C15AEE6640FB8562DFA6B240CA0AD351AC4AC155B96C14C8AB13DD262CDFD51C4BB5572FD616553D17BDD430ACBEA3E95F0B698D66990AB51E5D03783A8B3D278A5720454CF9695CFDCA08485BA099C51CD92A7EA7587C1D15C28E609A81852601B0604010679AA482D51261EC36E36B8719676217FD74C54786488F4B4969C05A8BA27CA3A77CCE73B965923CA554E422B9B61F4754641608AC16C9B8587A32C1C5DD788F88B36B717A46965635DEB67F45B129B99070909C93EB80B42C2B3F3F70343A7CF37E8520E7BCFC416ACA4F18C7981262BA2BFC756AE03278F0EC66DC2057696824BA6769865A601D7148EF6F54E5AF5686AA2906F994CE38A5E0B938F239007003022C03392DF3401B1E4A3A7EBC6161449F73374C8B0140369343D9295FDF511845C4A46EBAAB6CA5492F6800B98C0CC803653A4B1D6E6AAED1932BACC5FEFAA818BA502859BA5494C5F5402C8536A9C4C1888150617F80098F6B2A99C39BC5DC7CF3B5900A21329AB59053ABAA64ED163E859A8B3B3CA3359B750CCC3E710C7AC43C8191CB5D68870C06391C0CB8AEC72B897AC6BE7FBAACC676ED66314C83630E89448C88A1DF04ACEB23ABF2E409EF333C622289C18A2134E650C45257E47475FA33AA537A5A8F7680214716C50D470E3284963CA64F54677AEC54B5272162BF52BC8142E1D4183FC017454A6B5A496831759064024745978CBD51A6CEDC8955DE4CC6D363670A47466E82BE5C23603A17BF22ACDB7CC984AF08C87E14E27753CF587A8EC3447E62C649E887A67C36C9CE98721B697213275646B194F36758673A8ED11284455AFC7A8529F69C97A3C2D7B8C636C0BA55614B768E624E712930F776169B01715725351BC74B47395ED52B25A1313C95164814C34C979CBDFAB85954662CAB485E75087A98CC74BB82CA2D1B5BF2803238480638C40E90B43C7460E7AA917F010151FAB1169987B372ABB59271F7006C24E60236B84B9DDD600623704254617FB498D89E58B0368BCB2103E79353EB587860C1422E476162E425BC2381DB82C6592737E1DD602864B0167A71EC1F223305C02FE25052AF2B3B5A55A0D7A2022D9A798DC0C5874A98702AAF4054C5D80338A5248B5B7BD09C53B5E2A084B047D277A861B1A73BB51488DE04EF573C85230A0470B73175C9FA50594F66A5F50B4150054C93B68186F8B5CBC49316C8548A642B2B36A1D454C7489AC33B2D2CE6668096782A2C1E0866D21A65E16B585E7AF8618BDF3184C1986878508917277B93E10706B1614972B2A94C7310FE9C708C231A1A8AC8D9314A529A97F469BF64962D820648443099A076D55D4CEA824A58304844F99497C10A25148618A315D72CA857D1B04D575B94F85C01D19BEF211BF0AA3362E7041FD16596D808E867B44C4C00D1CDA3418967717F147D0EB21B42AAEE74AC35D0B92414B958531AADF463EC6305AE5ECAF79174002F26DDECC813BF32672E8529D95A4E730A7AB4A3E8F8A8AF979A665EAFD465FC64A0C5F8F3F9003489415899D59A543D8208C54A3166529B53922D4EC143B50F01423B177895EDEE22BB739F647ECF85F50BC25EF7B5A725DEE868626ED79D451140800E03B59B956F8210E556067407D13DC90FA9E8B872BFB8F").unwrap(), "lhs: computed secret key hash, rhs: hash from kat" ); - let (ciphertext, shared_secret) = - mlkem768::kyber_encapsulate(key_pair.public_key(), hex::decode("147c03f7a5bebba406c8fae1874d7f13c80efe79a3a9a874cc09fe76f6997615").unwrap().try_into().unwrap()); - + let (ciphertext, shared_secret) = mlkem768::kyber_encapsulate( + key_pair.public_key(), + hex::decode("147c03f7a5bebba406c8fae1874d7f13c80efe79a3a9a874cc09fe76f6997615") + .unwrap() + .try_into() + .unwrap(), + ); assert_eq!( ciphertext.as_ref(), @@ -35,6 +38,7 @@ fn kyber768() { "lhs: computed shared secret from encapsulate, rhs: shared secret from kat" ); - let shared_secret_from_decapsulate = mlkem768::kyber_decapsulate(key_pair.private_key(), &ciphertext); + let shared_secret_from_decapsulate = + mlkem768::kyber_decapsulate(key_pair.private_key(), &ciphertext); assert_eq!(shared_secret_from_decapsulate, shared_secret.as_ref(), "lhs: shared secret computed via decapsulation, rhs: shared secret computed via encapsulation"); } From 0571d1f8161e9db1b5f343223a56e0caf6777066 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 20 Jun 2024 14:24:59 +0200 Subject: [PATCH 06/53] Introduce `kyber` feature in `libcrux-kem` --- libcrux-kem/Cargo.toml | 1 + libcrux-kem/src/kem.rs | 215 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) diff --git a/libcrux-kem/Cargo.toml b/libcrux-kem/Cargo.toml index 1b194f3b..e59c608a 100644 --- a/libcrux-kem/Cargo.toml +++ b/libcrux-kem/Cargo.toml @@ -20,6 +20,7 @@ rand = { version = "0.8" } [features] tests = [] # Expose functions for testing. +kyber = ["libcrux-ml-kem/kyber"] [dev-dependencies] libcrux-kem = { version = "0.0.2-pre.2", path = "./", features = ["tests"] } diff --git a/libcrux-kem/src/kem.rs b/libcrux-kem/src/kem.rs index 6056c561..77f00ac9 100644 --- a/libcrux-kem/src/kem.rs +++ b/libcrux-kem/src/kem.rs @@ -88,6 +88,10 @@ pub enum Algorithm { MlKem768, X25519MlKem768Draft00, XWingKemDraft02, + #[cfg(feature = "kyber")] + X25519Kyber768Draft00, + #[cfg(feature = "kyber")] + XWingKyberDraft02, MlKem1024, } @@ -115,6 +119,10 @@ impl TryFrom for libcrux_ecdh::Algorithm { Algorithm::Secp521r1 => Ok(libcrux_ecdh::Algorithm::P521), Algorithm::X25519MlKem768Draft00 => Ok(libcrux_ecdh::Algorithm::X25519), Algorithm::XWingKemDraft02 => Ok(libcrux_ecdh::Algorithm::X25519), + #[cfg(feature = "kyber")] + Algorithm::XWingKyberDraft02 | Algorithm::X25519Kyber768Draft00 => { + Ok(libcrux_ecdh::Algorithm::X25519) + } _ => Err("provided algorithm is not an ECDH algorithm"), } } @@ -189,6 +197,10 @@ pub enum PrivateKey { MlKem768(MlKem768PrivateKey), X25519MlKem768Draft00(X25519MlKem768Draft00PrivateKey), XWingKemDraft02(XWingKemDraft02PrivateKey), + #[cfg(feature = "kyber")] + X25519Kyber768Draft00(X25519MlKem768Draft00PrivateKey), + #[cfg(feature = "kyber")] + XWingKyberDraft02(XWingKemDraft02PrivateKey), MlKem1024(MlKem1024PrivateKey), } @@ -252,6 +264,10 @@ pub enum PublicKey { MlKem768(MlKem768PublicKey), X25519MlKem768Draft00(X25519MlKem768Draft00PublicKey), XWingKemDraft02(XWingKemDraft02PublicKey), + #[cfg(feature = "kyber")] + X25519Kyber768Draft00(X25519MlKem768Draft00PublicKey), + #[cfg(feature = "kyber")] + XWingKyberDraft02(XWingKemDraft02PublicKey), MlKem1024(MlKem1024PublicKey), } @@ -263,6 +279,10 @@ pub enum Ct { MlKem768(MlKem768Ciphertext), X25519MlKem768Draft00(MlKem768Ciphertext, X25519PublicKey), XWingKemDraft02(MlKem768Ciphertext, X25519PublicKey), + #[cfg(feature = "kyber")] + X25519Kyber768Draft00(MlKem768Ciphertext, X25519PublicKey), + #[cfg(feature = "kyber")] + XWingKyberDraft02(MlKem768Ciphertext, X25519PublicKey), MlKem1024(MlKem1024Ciphertext), } @@ -354,6 +374,46 @@ impl Ct { Ok(Ss::MlKem1024(ss)) } + #[cfg(feature = "kyber")] + Ct::X25519Kyber768Draft00(kct, xct) => { + let (ksk, xsk) = + if let PrivateKey::X25519Kyber768Draft00(X25519MlKem768Draft00PrivateKey { + mlkem: kk, + x25519: xk, + }) = sk + { + (kk, xk) + } else { + return Err(Error::InvalidPrivateKey); + }; + let kss = mlkem768::kyber_decapsulate(ksk, kct); + let xss = x25519_derive(xct, xsk)?; + + Ok(Ss::X25519Kyber768Draft00(kss, xss)) + } + #[cfg(feature = "kyber")] + Ct::XWingKyberDraft02(ct_m, ct_x) => { + let (sk_m, sk_x, pk_x) = + if let PrivateKey::XWingKyberDraft02(XWingKemDraft02PrivateKey { + sk_m, + sk_x, + pk_x, + }) = sk + { + (sk_m, sk_x, pk_x) + } else { + return Err(Error::InvalidPrivateKey); + }; + let ss_m = mlkem768::kyber_decapsulate(sk_m, ct_m); + let ss_x = x25519_derive(ct_x, sk_x)?; + + Ok(Ss::XWingKyberDraft02( + ss_m, + ss_x, + X25519PublicKey(ct_x.0.clone()), + X25519PublicKey(pk_x.0.clone()), + )) + } } } } @@ -370,6 +430,15 @@ pub enum Ss { X25519PublicKey, // ss_X X25519PublicKey, // ct_X X25519PublicKey, // pk_X + ), + #[cfg(feature = "kyber")] + X25519Kyber768Draft00(MlKemSharedSecret, X25519PublicKey), + #[cfg(feature = "kyber")] + XWingKyberDraft02( + MlKemSharedSecret, // ss_M + X25519PublicKey, // ss_X + X25519PublicKey, // ct_X + X25519PublicKey, // pk_X ), MlKem1024(MlKemSharedSecret), } @@ -385,6 +454,10 @@ impl PrivateKey { PrivateKey::X25519MlKem768Draft00(k) => k.encode(), PrivateKey::XWingKemDraft02(k) => k.encode(), PrivateKey::MlKem1024(k) => k.as_slice().to_vec(), + #[cfg(feature = "kyber")] + PrivateKey::X25519Kyber768Draft00(k) => k.encode(), + #[cfg(feature = "kyber")] + PrivateKey::XWingKyberDraft02(k) => k.encode(), } } @@ -423,6 +496,24 @@ impl PrivateKey { .map_err(|_| Error::InvalidPrivateKey)?; Ok(Self::XWingKemDraft02(pk)) } + #[cfg(feature = "kyber")] + Algorithm::X25519Kyber768Draft00 => { + let key: [u8; MlKem768PrivateKey::len() + 32] = + bytes.try_into().map_err(|_| Error::InvalidPrivateKey)?; + let (xsk, ksk) = key.split_at(32); + Ok(Self::X25519Kyber768Draft00( + X25519MlKem768Draft00PrivateKey { + mlkem: ksk.try_into().map_err(|_| Error::InvalidPrivateKey)?, + x25519: xsk.try_into().map_err(|_| Error::InvalidPrivateKey)?, + }, + )) + } + #[cfg(feature = "kyber")] + Algorithm::XWingKyberDraft02 => { + let pk = XWingKemDraft02PrivateKey::decode(bytes) + .map_err(|_| Error::InvalidPrivateKey)?; + Ok(Self::XWingKyberDraft02(pk)) + } Algorithm::MlKem1024 => bytes .try_into() .map_err(|_| Error::InvalidPrivateKey) @@ -496,6 +587,40 @@ impl PublicKey { Ct::XWingKemDraft02(ct_m, X25519PublicKey(ct_x.0.clone())), )) } + + #[cfg(feature = "kyber")] + PublicKey::X25519Kyber768Draft00(X25519MlKem768Draft00PublicKey { + mlkem: kpk, + x25519: xpk, + }) => { + let seed = mlkem_rand(rng)?; + let (mlkem_ct, mlkem_ss) = mlkem768::kyber_encapsulate(kpk, seed); + let (x_sk, x_pk) = libcrux_ecdh::x25519_key_gen(rng)?; + let x_ss = x25519_derive(xpk, &x_sk)?; + + Ok(( + Ss::X25519Kyber768Draft00(mlkem_ss, x_ss), + Ct::X25519Kyber768Draft00(mlkem_ct, x_pk), + )) + } + + #[cfg(feature = "kyber")] + PublicKey::XWingKyberDraft02(XWingKemDraft02PublicKey { pk_m, pk_x }) => { + let seed = mlkem_rand(rng)?; + let (ct_m, ss_m) = mlkem768::kyber_encapsulate(pk_m, seed); + let (ek_x, ct_x) = libcrux_ecdh::x25519_key_gen(rng)?; + let ss_x = x25519_derive(pk_x, &ek_x)?; + + Ok(( + Ss::XWingKyberDraft02( + ss_m, + ss_x, + X25519PublicKey(ct_x.0.clone()), + X25519PublicKey(pk_x.0.clone()), + ), + Ct::XWingKyberDraft02(ct_m, X25519PublicKey(ct_x.0.clone())), + )) + } } } @@ -509,6 +634,10 @@ impl PublicKey { PublicKey::X25519MlKem768Draft00(k) => k.encode(), PublicKey::XWingKemDraft02(k) => k.encode(), PublicKey::MlKem1024(k) => k.as_ref().to_vec(), + #[cfg(feature = "kyber")] + PublicKey::X25519Kyber768Draft00(k) => k.encode(), + #[cfg(feature = "kyber")] + PublicKey::XWingKyberDraft02(k) => k.encode(), } } @@ -539,6 +668,14 @@ impl PublicKey { Algorithm::XWingKemDraft02 => { XWingKemDraft02PublicKey::decode(bytes).map(Self::XWingKemDraft02) } + #[cfg(feature = "kyber")] + Algorithm::X25519Kyber768Draft00 => { + X25519MlKem768Draft00PublicKey::decode(bytes).map(Self::X25519Kyber768Draft00) + } + #[cfg(feature = "kyber")] + Algorithm::XWingKyberDraft02 => { + XWingKemDraft02PublicKey::decode(bytes).map(Self::XWingKyberDraft02) + } Algorithm::MlKem1024 => MlKem1024PublicKey::try_from(bytes) .ok() .and_then(mlkem1024::validate_public_key) @@ -572,6 +709,24 @@ impl Ss { input.extend_from_slice(ct_x.0.as_ref()); input.extend_from_slice(pk_x.0.as_ref()); sha3::sha256(&input).to_vec() + } + #[cfg(feature = "kyber")] + Ss::X25519Kyber768Draft00(kk, xk) => { + let mut out = xk.0.to_vec(); + out.extend_from_slice(kk.as_ref()); + out + } + #[cfg(feature = "kyber")] + Ss::XWingKyberDraft02(ss_m, ss_x, ct_x, pk_x) => { + // \./ + // /^\ + // 5c2e2f2f5e5c + let mut input = vec![0x5c, 0x2e, 0x2f, 0x2f, 0x5e, 0x5c]; + input.extend_from_slice(ss_m.as_ref()); + input.extend_from_slice(ss_x.as_ref()); + input.extend_from_slice(ct_x.0.as_ref()); + input.extend_from_slice(pk_x.0.as_ref()); + sha3::sha256(&input).to_vec() } Ss::MlKem1024(k) => k.as_ref().to_vec(), } @@ -595,6 +750,18 @@ impl Ct { let mut out = ct_m.as_ref().to_vec(); out.extend_from_slice(ct_x.as_ref()); out + } + #[cfg(feature = "kyber")] + Ct::X25519Kyber768Draft00(kk, xk) => { + let mut out = xk.0.to_vec(); + out.extend_from_slice(kk.as_ref()); + out + } + #[cfg(feature = "kyber")] + Ct::XWingKyberDraft02(ct_m, ct_x) => { + let mut out = ct_m.as_ref().to_vec(); + out.extend_from_slice(ct_x.as_ref()); + out } Ct::MlKem1024(k) => k.as_ref().to_vec(), } @@ -636,6 +803,26 @@ impl Ct { ct_m.try_into().map_err(|_| Error::InvalidCiphertext)?, ct_x.try_into().map_err(|_| Error::InvalidCiphertext)?, )) + } + #[cfg(feature = "kyber")] + Algorithm::X25519Kyber768Draft00 => { + let key: [u8; MlKem768Ciphertext::len() + 32] = + bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; + let (xct, kct) = key.split_at(32); + Ok(Self::X25519Kyber768Draft00( + kct.try_into().map_err(|_| Error::InvalidCiphertext)?, + xct.try_into().map_err(|_| Error::InvalidCiphertext)?, + )) + } + #[cfg(feature = "kyber")] + Algorithm::XWingKyberDraft02 => { + let key: [u8; MlKem768Ciphertext::len() + 32] = + bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; + let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::len()); + Ok(Self::XWingKyberDraft02( + ct_m.try_into().map_err(|_| Error::InvalidCiphertext)?, + ct_x.try_into().map_err(|_| Error::InvalidCiphertext)?, + )) } Algorithm::MlKem1024 => bytes .try_into() @@ -724,6 +911,34 @@ pub fn key_gen( PublicKey::XWingKemDraft02(XWingKemDraft02PublicKey { pk_m, pk_x }), )) } + #[cfg(feature = "kyber")] + Algorithm::X25519Kyber768Draft00 => { + let (mlkem_private, mlkem_public) = gen_mlkem768(rng)?; + let (x25519_private, x25519_public) = libcrux_ecdh::x25519_key_gen(rng)?; + Ok(( + PrivateKey::X25519Kyber768Draft00(X25519MlKem768Draft00PrivateKey { + mlkem: mlkem_private, + x25519: x25519_private, + }), + PublicKey::X25519Kyber768Draft00(X25519MlKem768Draft00PublicKey { + mlkem: mlkem_public, + x25519: x25519_public, + }), + )) + } + #[cfg(feature = "kyber")] + Algorithm::XWingKyberDraft02 => { + let (sk_m, pk_m) = gen_mlkem768(rng)?; + let (sk_x, pk_x) = libcrux_ecdh::x25519_key_gen(rng)?; + Ok(( + PrivateKey::XWingKyberDraft02(XWingKemDraft02PrivateKey { + sk_m, + sk_x, + pk_x: X25519PublicKey(pk_x.0.clone()), + }), + PublicKey::XWingKyberDraft02(XWingKemDraft02PublicKey { pk_m, pk_x }), + )) + } _ => Err(Error::UnsupportedAlgorithm), } } From 283d99e5ad23c07eb033cd4ca734fc082ace3450 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 20 Jun 2024 14:26:01 +0200 Subject: [PATCH 07/53] Format --- libcrux-kem/src/kem.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libcrux-kem/src/kem.rs b/libcrux-kem/src/kem.rs index 77f00ac9..ec03433e 100644 --- a/libcrux-kem/src/kem.rs +++ b/libcrux-kem/src/kem.rs @@ -431,9 +431,9 @@ pub enum Ss { X25519PublicKey, // ct_X X25519PublicKey, // pk_X ), - #[cfg(feature = "kyber")] + #[cfg(feature = "kyber")] X25519Kyber768Draft00(MlKemSharedSecret, X25519PublicKey), - #[cfg(feature = "kyber")] + #[cfg(feature = "kyber")] XWingKyberDraft02( MlKemSharedSecret, // ss_M X25519PublicKey, // ss_X @@ -710,13 +710,13 @@ impl Ss { input.extend_from_slice(pk_x.0.as_ref()); sha3::sha256(&input).to_vec() } - #[cfg(feature = "kyber")] + #[cfg(feature = "kyber")] Ss::X25519Kyber768Draft00(kk, xk) => { let mut out = xk.0.to_vec(); out.extend_from_slice(kk.as_ref()); out } - #[cfg(feature = "kyber")] + #[cfg(feature = "kyber")] Ss::XWingKyberDraft02(ss_m, ss_x, ct_x, pk_x) => { // \./ // /^\ @@ -751,13 +751,13 @@ impl Ct { out.extend_from_slice(ct_x.as_ref()); out } - #[cfg(feature = "kyber")] - Ct::X25519Kyber768Draft00(kk, xk) => { + #[cfg(feature = "kyber")] + Ct::X25519Kyber768Draft00(kk, xk) => { let mut out = xk.0.to_vec(); out.extend_from_slice(kk.as_ref()); out - } - #[cfg(feature = "kyber")] + } + #[cfg(feature = "kyber")] Ct::XWingKyberDraft02(ct_m, ct_x) => { let mut out = ct_m.as_ref().to_vec(); out.extend_from_slice(ct_x.as_ref()); @@ -804,8 +804,8 @@ impl Ct { ct_x.try_into().map_err(|_| Error::InvalidCiphertext)?, )) } - #[cfg(feature = "kyber")] - Algorithm::X25519Kyber768Draft00 => { + #[cfg(feature = "kyber")] + Algorithm::X25519Kyber768Draft00 => { let key: [u8; MlKem768Ciphertext::len() + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; let (xct, kct) = key.split_at(32); @@ -813,8 +813,8 @@ impl Ct { kct.try_into().map_err(|_| Error::InvalidCiphertext)?, xct.try_into().map_err(|_| Error::InvalidCiphertext)?, )) - } - #[cfg(feature = "kyber")] + } + #[cfg(feature = "kyber")] Algorithm::XWingKyberDraft02 => { let key: [u8; MlKem768Ciphertext::len() + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; From 4be326bb4affa1468e459eed9f674ff82fd7959d Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 20 Jun 2024 18:03:21 +0200 Subject: [PATCH 08/53] Include verified ML-KEM in `libcrux-ml-kem` --- libcrux-ml-kem/src/kem.rs | 70 ++ libcrux-ml-kem/src/kem/kyber.rs | 355 ++++++++++ libcrux-ml-kem/src/kem/kyber/PERFORMANCE.md | 8 + libcrux-ml-kem/src/kem/kyber/arithmetic.rs | 201 ++++++ libcrux-ml-kem/src/kem/kyber/compress.rs | 135 ++++ .../src/kem/kyber/constant_time_ops.rs | 64 ++ libcrux-ml-kem/src/kem/kyber/constants.rs | 35 + .../src/kem/kyber/hash_functions.rs | 116 ++++ libcrux-ml-kem/src/kem/kyber/helper.rs | 57 ++ .../src/kem/kyber/implementation_notes.pdf | Bin 0 -> 348700 bytes libcrux-ml-kem/src/kem/kyber/ind_cpa.rs | 510 ++++++++++++++ libcrux-ml-kem/src/kem/kyber/kyber1024.rs | 160 +++++ libcrux-ml-kem/src/kem/kyber/kyber512.rs | 158 +++++ libcrux-ml-kem/src/kem/kyber/kyber768.rs | 178 +++++ libcrux-ml-kem/src/kem/kyber/matrix.rs | 158 +++++ libcrux-ml-kem/src/kem/kyber/ntt.rs | 339 ++++++++++ libcrux-ml-kem/src/kem/kyber/sampling.rs | 240 +++++++ libcrux-ml-kem/src/kem/kyber/serialize.rs | 626 ++++++++++++++++++ libcrux-ml-kem/src/kem/kyber/types.rs | 156 +++++ libcrux-ml-kem/src/lib.rs | 1 + 20 files changed, 3567 insertions(+) create mode 100644 libcrux-ml-kem/src/kem.rs create mode 100644 libcrux-ml-kem/src/kem/kyber.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/PERFORMANCE.md create mode 100644 libcrux-ml-kem/src/kem/kyber/arithmetic.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/compress.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/constant_time_ops.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/constants.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/hash_functions.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/helper.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/implementation_notes.pdf create mode 100644 libcrux-ml-kem/src/kem/kyber/ind_cpa.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/kyber1024.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/kyber512.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/kyber768.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/matrix.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/ntt.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/sampling.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/serialize.rs create mode 100644 libcrux-ml-kem/src/kem/kyber/types.rs diff --git a/libcrux-ml-kem/src/kem.rs b/libcrux-ml-kem/src/kem.rs new file mode 100644 index 00000000..16dbfc0f --- /dev/null +++ b/libcrux-ml-kem/src/kem.rs @@ -0,0 +1,70 @@ +//! # Key Encapsulation Mechanism +//! +//! A KEM interface. +//! +//! For ECDH structs, check the [`ecdh`] module. +//! +//! Available algorithms: +//! * [`Algorithm::X25519`]\: x25519 ECDH KEM. Also see [`ecdh#x25519`]. +//! * [`Algorithm::Secp256r1`]\: NIST P256 ECDH KEM. Also see [`ecdh#P256`]. +//! * [`Algorithm::MlKem512`]\: ML-KEM 512 from [FIPS 203]. +//! * [`Algorithm::MlKem768`]\: ML-KEM 768 from [FIPS 203]. +//! * [`Algorithm::MlKem1024`]\: ML-KEM 1024 from [FIPS 203]. +//! * [`Algorithm::X25519MlKem768Draft00`]\: Hybrid x25519 - ML-KEM 768 [draft kem for hpke](https://www.ietf.org/archive/id/draft-westerbaan-cfrg-hpke-xyber768d00-00.html). +//! * [`Algorithm::XWingKemDraft02`]\: Hybrid x25519 - ML-KEM 768 [draft xwing kem for hpke](https://www.ietf.org/archive/id/draft-connolly-cfrg-xwing-kem-02.html). +//! +//! ``` +//! use libcrux::{kem::*, drbg::Drbg, digest::Algorithm::Sha256}; +//! +//! let mut rng = Drbg::new(Sha256).unwrap(); +//! let (sk_a, pk_a) = key_gen(Algorithm::MlKem768, &mut rng).unwrap(); +//! let received_pk = pk_a.encode(); +//! +//! let pk = PublicKey::decode(Algorithm::MlKem768, &received_pk).unwrap(); +//! let (ss_b, ct_b) = pk.encapsulate(&mut rng).unwrap(); +//! let received_ct = ct_b.encode(); +//! +//! let ct_a = Ct::decode(Algorithm::MlKem768, &received_ct).unwrap(); +//! let ss_a = ct_a.decapsulate(&sk_a).unwrap(); +//! assert_eq!(ss_b.encode(), ss_a.encode()); +//! ``` +//! +//! [FIPS 203]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf + +// hacspec code: don't let clippy touch it. +#[allow(clippy::all)] +pub mod kyber; + +// TODO: These functions are currently exposed simply in order to make NIST KAT +// testing possible without an implementation of the NIST AES-CTR DRBG. Remove them +// (and change the visibility of the exported functions to pub(crate)) the +// moment we have an implementation of one. This is tracked by: +// https://github.com/cryspen/libcrux/issues/36 +#[cfg(feature = "tests")] +pub mod deterministic { + pub use super::kyber::kyber1024::decapsulate as kyber1024_decapsulate_derand; + pub use super::kyber::kyber1024::encapsulate as kyber1024_encapsulate_derand; + pub use super::kyber::kyber1024::generate_key_pair as kyber1024_generate_keypair_derand; + pub use super::kyber::kyber512::decapsulate as kyber512_decapsulate_derand; + pub use super::kyber::kyber512::encapsulate as kyber512_encapsulate_derand; + pub use super::kyber::kyber512::generate_key_pair as kyber512_generate_keypair_derand; + pub use super::kyber::kyber768::decapsulate as kyber768_decapsulate_derand; + pub use super::kyber::kyber768::encapsulate as kyber768_encapsulate_derand; + pub use super::kyber::kyber768::generate_key_pair as kyber768_generate_keypair_derand; +} + +use self::kyber::MlKemSharedSecret; +use self::kyber::{kyber1024, kyber512, kyber768}; +pub use kyber::{ + kyber1024::{MlKem1024Ciphertext, MlKem1024PrivateKey, MlKem1024PublicKey}, + kyber512::{MlKem512Ciphertext, MlKem512PrivateKey, MlKem512PublicKey}, + kyber768::{MlKem768Ciphertext, MlKem768PrivateKey, MlKem768PublicKey}, + MlKemCiphertext, MlKemKeyPair, +}; + +#[cfg(feature = "tests")] +pub use kyber::{ + kyber1024::validate_public_key as ml_kem1024_validate_public_key, + kyber512::validate_public_key as ml_kem512_validate_public_key, + kyber768::validate_public_key as ml_kem768_validate_public_key, +}; diff --git a/libcrux-ml-kem/src/kem/kyber.rs b/libcrux-ml-kem/src/kem/kyber.rs new file mode 100644 index 00000000..89c31082 --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber.rs @@ -0,0 +1,355 @@ +// This module is declared here since otherwise, hax reports the following error: +// +// The THIR body of item +// DefId(0:986 ~ libcrux[92b3]::kem::kyber768::parameters::COEFFICIENTS_IN_RING_ELEMENT) +// was stolen. +// +// This is being tracked in https://github.com/hacspec/hacspec-v2/issues/27 +pub(crate) mod constants; + +/// Helpers for verification and extraction +mod helper; + +mod arithmetic; +mod compress; +mod constant_time_ops; +mod hash_functions; +mod ind_cpa; +mod matrix; +mod ntt; +mod sampling; +mod serialize; +mod types; + +// Variants +pub mod kyber1024; +pub mod kyber512; +pub mod kyber768; + +pub use types::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; + +// TODO: We should make this an actual type as opposed to alias so we can enforce +// some checks at the type level. This is being tracked in: +// https://github.com/cryspen/libcrux/issues/123 +pub type MlKemSharedSecret = [u8; constants::SHARED_SECRET_SIZE]; + +use self::{ + arithmetic::PolynomialRingElement, + constant_time_ops::{ + compare_ciphertexts_in_constant_time, select_shared_secret_in_constant_time, + }, + constants::{CPA_PKE_KEY_GENERATION_SEED_SIZE, H_DIGEST_SIZE, SHARED_SECRET_SIZE}, + hash_functions::{G, H, PRF}, + ind_cpa::{into_padded_array, serialize_public_key}, + serialize::deserialize_ring_elements_reduced, +}; + +/// Seed size for key generation +pub(in crate::kem) const KEY_GENERATION_SEED_SIZE: usize = + CPA_PKE_KEY_GENERATION_SEED_SIZE + SHARED_SECRET_SIZE; + +/// Serialize the secret key. +#[inline(always)] +fn serialize_kem_secret_key( + private_key: &[u8], + public_key: &[u8], + implicit_rejection_value: &[u8], +) -> [u8; SERIALIZED_KEY_LEN] { + let mut out = [0u8; SERIALIZED_KEY_LEN]; + let mut pointer = 0; + out[pointer..pointer + private_key.len()].copy_from_slice(private_key); + pointer += private_key.len(); + out[pointer..pointer + public_key.len()].copy_from_slice(public_key); + pointer += public_key.len(); + out[pointer..pointer + H_DIGEST_SIZE].copy_from_slice(&H(public_key)); + pointer += H_DIGEST_SIZE; + out[pointer..pointer + implicit_rejection_value.len()] + .copy_from_slice(implicit_rejection_value); + out +} + +pub(super) fn validate_public_key< + const K: usize, + const RANKED_BYTES_PER_RING_ELEMENT: usize, + const PUBLIC_KEY_SIZE: usize, +>( + public_key: &[u8; PUBLIC_KEY_SIZE], +) -> bool { + let deserialized_pk = deserialize_ring_elements_reduced::( + &public_key[..RANKED_BYTES_PER_RING_ELEMENT], + ); + + let public_key_serialized = + serialize_public_key::( + deserialized_pk, + &public_key[RANKED_BYTES_PER_RING_ELEMENT..], + ); + + *public_key == public_key_serialized +} + +pub struct MlKemState { + secret_as_ntt: [PolynomialRingElement; K], + t_as_ntt: [PolynomialRingElement; K], + a_transpose: [[PolynomialRingElement; K]; K], + rej: [u8; 32], + ind_cpa_public_key_hash: [u8; 32], +} + +pub(super) fn generate_keypair_unpacked< + const K: usize, + const CPA_PRIVATE_KEY_SIZE: usize, + const PRIVATE_KEY_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const BYTES_PER_RING_ELEMENT: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, +>( + randomness: [u8; KEY_GENERATION_SEED_SIZE], +) -> (MlKemState, MlKemPublicKey) { + let ind_cpa_keypair_randomness = &randomness[0..CPA_PKE_KEY_GENERATION_SEED_SIZE]; + let implicit_rejection_value = &randomness[CPA_PKE_KEY_GENERATION_SEED_SIZE..]; + + let ((secret_as_ntt, t_as_ntt, a_transpose), ind_cpa_public_key) = + ind_cpa::generate_keypair_unpacked::< + K, + PUBLIC_KEY_SIZE, + BYTES_PER_RING_ELEMENT, + ETA1, + ETA1_RANDOMNESS_SIZE, + >(ind_cpa_keypair_randomness); + + let ind_cpa_public_key_hash = H(&ind_cpa_public_key); + + let rej: [u8; 32] = implicit_rejection_value.try_into().unwrap(); + let pubkey: MlKemPublicKey = MlKemPublicKey::from(ind_cpa_public_key); + ( + MlKemState { + secret_as_ntt, + t_as_ntt, + a_transpose, + rej, + ind_cpa_public_key_hash, + }, + pubkey, + ) +} + +pub(super) fn generate_keypair< + const K: usize, + const CPA_PRIVATE_KEY_SIZE: usize, + const PRIVATE_KEY_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const BYTES_PER_RING_ELEMENT: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, +>( + randomness: [u8; KEY_GENERATION_SEED_SIZE], +) -> MlKemKeyPair { + let ind_cpa_keypair_randomness = &randomness[0..CPA_PKE_KEY_GENERATION_SEED_SIZE]; + let implicit_rejection_value = &randomness[CPA_PKE_KEY_GENERATION_SEED_SIZE..]; + + let (ind_cpa_private_key, public_key) = ind_cpa::generate_keypair::< + K, + CPA_PRIVATE_KEY_SIZE, + PUBLIC_KEY_SIZE, + BYTES_PER_RING_ELEMENT, + ETA1, + ETA1_RANDOMNESS_SIZE, + >(ind_cpa_keypair_randomness); + + let secret_key_serialized = + serialize_kem_secret_key(&ind_cpa_private_key, &public_key, implicit_rejection_value); + let private_key: MlKemPrivateKey = + MlKemPrivateKey::from(secret_key_serialized); + + MlKemKeyPair::from(private_key, public_key.into()) +} + +pub(super) fn encapsulate< + const K: usize, + const CIPHERTEXT_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_SIZE: usize, + const C2_SIZE: usize, + const VECTOR_U_COMPRESSION_FACTOR: usize, + const VECTOR_V_COMPRESSION_FACTOR: usize, + const VECTOR_U_BLOCK_LEN: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, +>( + public_key: &MlKemPublicKey, + randomness: [u8; SHARED_SECRET_SIZE], +) -> (MlKemCiphertext, MlKemSharedSecret) { + let mut to_hash: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&randomness); + to_hash[H_DIGEST_SIZE..].copy_from_slice(&H(public_key.as_slice())); + + let hashed = G(&to_hash); + let (shared_secret, pseudorandomness) = hashed.split_at(SHARED_SECRET_SIZE); + + let ciphertext = ind_cpa::encrypt::< + K, + CIPHERTEXT_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + VECTOR_U_BLOCK_LEN, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key.as_slice(), randomness, pseudorandomness); + + let mut shared_secret_array = [0u8; constants::SHARED_SECRET_SIZE]; + shared_secret_array.copy_from_slice(shared_secret); + (ciphertext.into(), shared_secret_array) +} + +pub(super) fn decapsulate_unpacked< + const K: usize, + const SECRET_KEY_SIZE: usize, + const CPA_SECRET_KEY_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const CIPHERTEXT_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_SIZE: usize, + const C2_SIZE: usize, + const VECTOR_U_COMPRESSION_FACTOR: usize, + const VECTOR_V_COMPRESSION_FACTOR: usize, + const C1_BLOCK_SIZE: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, + const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize, +>( + state: &MlKemState, + ciphertext: &MlKemCiphertext, +) -> MlKemSharedSecret { + let secret_as_ntt: &[PolynomialRingElement; K] = &state.secret_as_ntt; + let t_as_ntt: &[PolynomialRingElement; K] = &state.t_as_ntt; + let a_transpose: &[[PolynomialRingElement; K]; K] = &state.a_transpose; + let implicit_rejection_value: &[u8] = &state.rej; + let ind_cpa_public_key_hash: &[u8] = &state.ind_cpa_public_key_hash; + + let decrypted = ind_cpa::decrypt_unpacked::< + K, + CIPHERTEXT_SIZE, + C1_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + >(secret_as_ntt, &ciphertext.value); + + let mut to_hash: [u8; SHARED_SECRET_SIZE + H_DIGEST_SIZE] = into_padded_array(&decrypted); + to_hash[SHARED_SECRET_SIZE..].copy_from_slice(ind_cpa_public_key_hash); + + let hashed = G(&to_hash); + let (shared_secret, pseudorandomness) = hashed.split_at(SHARED_SECRET_SIZE); + + let mut to_hash: [u8; IMPLICIT_REJECTION_HASH_INPUT_SIZE] = + into_padded_array(&implicit_rejection_value); + to_hash[SHARED_SECRET_SIZE..].copy_from_slice(ciphertext.as_ref()); + let implicit_rejection_shared_secret: [u8; SHARED_SECRET_SIZE] = PRF(&to_hash); + + let expected_ciphertext = ind_cpa::encrypt_unpacked::< + K, + CIPHERTEXT_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + C1_BLOCK_SIZE, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(t_as_ntt, a_transpose, decrypted, pseudorandomness); + + let selector = compare_ciphertexts_in_constant_time::( + ciphertext.as_ref(), + &expected_ciphertext, + ); + + select_shared_secret_in_constant_time( + shared_secret, + &implicit_rejection_shared_secret, + selector, + ) +} + +pub(super) fn decapsulate< + const K: usize, + const SECRET_KEY_SIZE: usize, + const CPA_SECRET_KEY_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const CIPHERTEXT_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_SIZE: usize, + const C2_SIZE: usize, + const VECTOR_U_COMPRESSION_FACTOR: usize, + const VECTOR_V_COMPRESSION_FACTOR: usize, + const C1_BLOCK_SIZE: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, + const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize, +>( + secret_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, +) -> MlKemSharedSecret { + let (ind_cpa_secret_key, secret_key) = secret_key.split_at(CPA_SECRET_KEY_SIZE); + let (ind_cpa_public_key, secret_key) = secret_key.split_at(PUBLIC_KEY_SIZE); + let (ind_cpa_public_key_hash, implicit_rejection_value) = secret_key.split_at(H_DIGEST_SIZE); + + let decrypted = ind_cpa::decrypt::< + K, + CIPHERTEXT_SIZE, + C1_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + >(ind_cpa_secret_key, &ciphertext.value); + + let mut to_hash: [u8; SHARED_SECRET_SIZE + H_DIGEST_SIZE] = into_padded_array(&decrypted); + to_hash[SHARED_SECRET_SIZE..].copy_from_slice(ind_cpa_public_key_hash); + + let hashed = G(&to_hash); + let (shared_secret, pseudorandomness) = hashed.split_at(SHARED_SECRET_SIZE); + + let mut to_hash: [u8; IMPLICIT_REJECTION_HASH_INPUT_SIZE] = + into_padded_array(&implicit_rejection_value); + to_hash[SHARED_SECRET_SIZE..].copy_from_slice(ciphertext.as_ref()); + let implicit_rejection_shared_secret: [u8; SHARED_SECRET_SIZE] = PRF(&to_hash); + + let expected_ciphertext = ind_cpa::encrypt::< + K, + CIPHERTEXT_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_SIZE, + C2_SIZE, + VECTOR_U_COMPRESSION_FACTOR, + VECTOR_V_COMPRESSION_FACTOR, + C1_BLOCK_SIZE, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(ind_cpa_public_key, decrypted, pseudorandomness); + + let selector = compare_ciphertexts_in_constant_time::( + ciphertext.as_ref(), + &expected_ciphertext, + ); + + select_shared_secret_in_constant_time( + shared_secret, + &implicit_rejection_shared_secret, + selector, + ) +} diff --git a/libcrux-ml-kem/src/kem/kyber/PERFORMANCE.md b/libcrux-ml-kem/src/kem/kyber/PERFORMANCE.md new file mode 100644 index 00000000..93bf98dd --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/PERFORMANCE.md @@ -0,0 +1,8 @@ +N.B.: All measurements were taken on an M1 MacBook Air with 16 GB of memory. + +| | Key Generation (µs) | Encapsulation (µs) | Decapsulation (µs) | +|:----------|----------------------:|---------------------:|---------------------:| +| libcrux | 30.671 | 36.31 | 36.3 | +| BoringSSL | 33.8152 | 28.7323 | 35.2664 | +| CIRCL | 39.785 | 44.517 | 49.626 | +| PQClean | 30.671 | 38.511 | 43.458 | \ No newline at end of file diff --git a/libcrux-ml-kem/src/kem/kyber/arithmetic.rs b/libcrux-ml-kem/src/kem/kyber/arithmetic.rs new file mode 100644 index 00000000..4543b6fb --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/arithmetic.rs @@ -0,0 +1,201 @@ +use crate::hax_utils::hax_debug_assert; + +use super::constants::{COEFFICIENTS_IN_RING_ELEMENT, FIELD_MODULUS}; + +/// Values having this type hold a representative 'x' of the Kyber field. +/// We use 'fe' as a shorthand for this type. +pub(crate) type FieldElement = i32; + +const MONTGOMERY_SHIFT: u8 = 16; +const MONTGOMERY_R: i32 = 1 << MONTGOMERY_SHIFT; + +/// If 'x' denotes a value of type `fe`, values having this type hold a +/// representative y ≡ x·MONTGOMERY_R^(-1) (mod FIELD_MODULUS). +/// We use 'mfe' as a shorthand for this type +pub(crate) type MontgomeryFieldElement = i32; + +/// If 'x' denotes a value of type `fe`, values having this type hold a +/// representative y ≡ x·MONTGOMERY_R (mod FIELD_MODULUS). +/// We use 'fer' as a shorthand for this type. +pub(crate) type FieldElementTimesMontgomeryR = i32; + +#[cfg_attr(hax, hax_lib_macros::requires(n == 4 || n == 5 || n == 10 || n == 11 || n == MONTGOMERY_SHIFT))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| result < 2u32.pow(n.into())))] +#[inline(always)] +pub(crate) fn get_n_least_significant_bits(n: u8, value: u32) -> u32 { + hax_debug_assert!(n == 4 || n == 5 || n == 10 || n == 11 || n == MONTGOMERY_SHIFT); + + value & ((1 << n) - 1) +} + +const BARRETT_SHIFT: i64 = 26; +const BARRETT_R: i64 = 1 << BARRETT_SHIFT; + +/// This is calculated as ⌊(BARRETT_R / FIELD_MODULUS) + 1/2⌋ +const BARRETT_MULTIPLIER: i64 = 20159; + +/// Signed Barrett Reduction +/// +/// Given an input `value`, `barrett_reduce` outputs a representative `result` +/// such that: +/// +/// - result ≡ value (mod FIELD_MODULUS) +/// - the absolute value of `result` is bound as follows: +/// +/// `|result| ≤ FIELD_MODULUS / 2 · (|value|/BARRETT_R + 1) +/// +/// In particular, if `|value| < BARRETT_R`, then `|result| < FIELD_MODULUS`. + +#[cfg_attr(hax, hax_lib_macros::requires((i64::from(value) > -BARRETT_R && i64::from(value) < BARRETT_R)))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| result > -FIELD_MODULUS && result < FIELD_MODULUS))] +pub(crate) fn barrett_reduce(value: FieldElement) -> FieldElement { + hax_debug_assert!( + i64::from(value) > -BARRETT_R && i64::from(value) < BARRETT_R, + "value is {value}" + ); + + let t = (i64::from(value) * BARRETT_MULTIPLIER) + (BARRETT_R >> 1); + let quotient = (t >> BARRETT_SHIFT) as i32; + + let result = value - (quotient * FIELD_MODULUS); + + hax_debug_assert!( + result > -FIELD_MODULUS && result < FIELD_MODULUS, + "value is {value}" + ); + + result +} + +const INVERSE_OF_MODULUS_MOD_MONTGOMERY_R: u32 = 62209; // FIELD_MODULUS^{-1} mod MONTGOMERY_R + +/// Signed Montgomery Reduction +/// +/// Given an input `value`, `montgomery_reduce` outputs a representative `o` +/// such that: +/// +/// - o ≡ value · MONTGOMERY_R^(-1) (mod FIELD_MODULUS) +/// - the absolute value of `o` is bound as follows: +/// +/// `|result| ≤ (|value| / MONTGOMERY_R) + (FIELD_MODULUS / 2) +/// +/// In particular, if `|value| ≤ FIELD_MODULUS * MONTGOMERY_R`, then `|o| < (3 · FIELD_MODULUS) / 2`. +#[cfg_attr(hax, hax_lib_macros::requires(value >= -FIELD_MODULUS * MONTGOMERY_R && value <= FIELD_MODULUS * MONTGOMERY_R))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| result >= -(3 * FIELD_MODULUS) / 2 && result <= (3 * FIELD_MODULUS) / 2))] +pub(crate) fn montgomery_reduce(value: FieldElement) -> MontgomeryFieldElement { + // This forces hax to extract code for MONTGOMERY_R before it extracts code + // for this function. The removal of this line is being tracked in: + // https://github.com/cryspen/libcrux/issues/134 + let _ = MONTGOMERY_R; + + hax_debug_assert!( + value >= -FIELD_MODULUS * MONTGOMERY_R && value <= FIELD_MODULUS * MONTGOMERY_R, + "value is {value}" + ); + + let t = get_n_least_significant_bits(MONTGOMERY_SHIFT, value as u32) + * INVERSE_OF_MODULUS_MOD_MONTGOMERY_R; + let k = get_n_least_significant_bits(MONTGOMERY_SHIFT, t) as i16; + + let k_times_modulus = (k as i32) * FIELD_MODULUS; + + let c = k_times_modulus >> MONTGOMERY_SHIFT; + let value_high = value >> MONTGOMERY_SHIFT; + + value_high - c +} + +/// If `fe` is some field element 'x' of the Kyber field and `fer` is congruent to +/// `y · MONTGOMERY_R`, this procedure outputs a value that is congruent to +/// `x · y`, as follows: +/// +/// `fe · fer ≡ x · y · MONTGOMERY_R (mod FIELD_MODULUS)` +/// +/// `montgomery_reduce` takes the value `x · y · MONTGOMERY_R` and outputs a representative +/// `x · y · MONTGOMERY_R * MONTGOMERY_R^{-1} ≡ x · y (mod FIELD_MODULUS)`. +#[inline(always)] +pub(crate) fn montgomery_multiply_fe_by_fer( + fe: FieldElement, + fer: FieldElementTimesMontgomeryR, +) -> FieldElement { + montgomery_reduce(fe * fer) +} + +/// This is calculated as (MONTGOMERY_R)^2 mod FIELD_MODULUS +const MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS: i32 = 1353; + +/// If x is some field element of the Kyber field and `mfe` is congruent to +/// x · MONTGOMERY_R^{-1}, this procedure outputs a value that is congruent to +/// `x`, as follows: +/// +/// mfe · MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS ≡ x · MONTGOMERY_R^{-1} * (MONTGOMERY_R)^2 (mod FIELD_MODULUS) +/// => mfe · MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS ≡ x · MONTGOMERY_R (mod FIELD_MODULUS) +/// +/// `montgomery_reduce` takes the value `x · MONTGOMERY_R` and outputs a representative +/// `x · MONTGOMERY_R * MONTGOMERY_R^{-1} ≡ x (mod FIELD_MODULUS)` +#[inline(always)] +pub(crate) fn to_standard_domain(mfe: MontgomeryFieldElement) -> FieldElement { + montgomery_reduce(mfe * MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS) +} + +/// Given a field element `fe` such that -FIELD_MODULUS ≤ fe < FIELD_MODULUS, +/// output `o` such that: +/// - `o` is congruent to `fe` +/// - 0 ≤ `o` FIELD_MODULUS +#[cfg_attr(hax, hax_lib_macros::requires(fe >= -FIELD_MODULUS && fe < FIELD_MODULUS))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| result >= 0 && result < (FIELD_MODULUS as u16)))] +#[inline(always)] +pub(crate) fn to_unsigned_representative(fe: FieldElement) -> u16 { + hax_debug_assert!(fe >= -FIELD_MODULUS && fe < FIELD_MODULUS); + (fe + (FIELD_MODULUS & (fe >> 31))) as u16 +} + +#[derive(Clone, Copy)] +pub struct PolynomialRingElement { + pub(crate) coefficients: [FieldElement; COEFFICIENTS_IN_RING_ELEMENT], +} + +impl PolynomialRingElement { + pub const ZERO: Self = Self { + coefficients: [0i32; 256], // FIXME: hax issue, this is COEFFICIENTS_IN_RING_ELEMENT + }; +} + +/// Given two polynomial ring elements `lhs` and `rhs`, compute the pointwise +/// sum of their constituent coefficients. +#[cfg_attr(hax, hax_lib_macros::requires( + hax_lib::forall(|i:usize| + hax_lib::implies(i < COEFFICIENTS_IN_RING_ELEMENT, || + (lhs.coefficients[i].abs() <= ((K as i32) - 1) * FIELD_MODULUS) && + (rhs.coefficients[i].abs() <= FIELD_MODULUS) + +))))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::forall(|i:usize| + hax_lib::implies(i < result.coefficients.len(), || + result.coefficients[i].abs() <= (K as i32) * FIELD_MODULUS +))))] +pub(crate) fn add_to_ring_element( + mut lhs: PolynomialRingElement, + rhs: &PolynomialRingElement, +) -> PolynomialRingElement { + hax_debug_assert!(lhs + .coefficients + .into_iter() + .all(|coefficient| coefficient.abs() <= ((K as i32) - 1) * FIELD_MODULUS)); + hax_debug_assert!(rhs + .coefficients + .into_iter() + .all(|coefficient| coefficient.abs() < FIELD_MODULUS)); + + for i in 0..lhs.coefficients.len() { + lhs.coefficients[i] += rhs.coefficients[i]; + } + + hax_debug_assert!(lhs + .coefficients + .into_iter() + .all(|coefficient| coefficient.abs() <= (K as i32) * FIELD_MODULUS)); + + lhs +} diff --git a/libcrux-ml-kem/src/kem/kyber/compress.rs b/libcrux-ml-kem/src/kem/kyber/compress.rs new file mode 100644 index 00000000..c2ea6f7d --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/compress.rs @@ -0,0 +1,135 @@ +use crate::hax_utils::hax_debug_assert; + +use super::{ + arithmetic::{get_n_least_significant_bits, FieldElement}, + constants::FIELD_MODULUS, +}; + +/// The `compress_*` functions implement the `Compress` function specified in the NIST FIPS +/// 203 standard (Page 18, Expression 4.5), which is defined as: +/// +/// ```plaintext +/// Compress_d: ℤq -> ℤ_{2ᵈ} +/// Compress_d(x) = ⌈(2ᵈ/q)·x⌋ +/// ``` +/// +/// Since `⌈x⌋ = ⌊x + 1/2⌋` we have: +/// +/// ```plaintext +/// Compress_d(x) = ⌊(2ᵈ/q)·x + 1/2⌋ +/// = ⌊(2^{d+1}·x + q) / 2q⌋ +/// ``` +/// +/// For further information about the function implementations, consult the +/// `implementation_notes.pdf` document in this directory. +/// +/// The NIST FIPS 203 standard can be found at +/// . + +#[cfg_attr(hax, hax_lib_macros::requires(fe < (FIELD_MODULUS as u16)))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::implies(833 <= fe && fe <= 2596, || result == 1) && + hax_lib::implies(!(833 <= fe && fe <= 2596), || result == 0) +))] +pub(super) fn compress_message_coefficient(fe: u16) -> u8 { + // The approach used here is inspired by: + // https://github.com/cloudflare/circl/blob/main/pke/kyber/internal/common/poly.go#L150 + + // If 833 <= fe <= 2496, + // then -832 <= shifted <= 831 + let shifted: i16 = 1664 - (fe as i16); + + // If shifted < 0, then + // (shifted >> 15) ^ shifted = flip_bits(shifted) = -shifted - 1, and so + // if -832 <= shifted < 0 then 0 < shifted_positive <= 831 + // + // If shifted >= 0 then + // (shifted >> 15) ^ shifted = shifted, and so + // if 0 <= shifted <= 831 then 0 <= shifted_positive <= 831 + let mask = shifted >> 15; + let shifted_to_positive = mask ^ shifted; + + let shifted_positive_in_range = shifted_to_positive - 832; + + // If x <= 831, then x - 832 <= -1, and so x - 832 < 0, which means + // the most significant bit of shifted_positive_in_range will be 1. + ((shifted_positive_in_range >> 15) & 1) as u8 +} + +#[cfg_attr(hax, + hax_lib_macros::requires( + (coefficient_bits == 4 || + coefficient_bits == 5 || + coefficient_bits == 10 || + coefficient_bits == 11) && + fe < (FIELD_MODULUS as u16)))] +#[cfg_attr(hax, + hax_lib_macros::ensures( + |result| result >= 0 && result < 2i32.pow(coefficient_bits as u32)))] +pub(super) fn compress_ciphertext_coefficient(coefficient_bits: u8, fe: u16) -> FieldElement { + hax_debug_assert!( + coefficient_bits == 4 + || coefficient_bits == 5 + || coefficient_bits == 10 + || coefficient_bits == 11 + ); + hax_debug_assert!(fe <= (FIELD_MODULUS as u16)); + + // This has to be constant time due to: + // https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/ldX0ThYJuBo/m/ovODsdY7AwAJ + let mut compressed = (fe as u64) << coefficient_bits; + compressed += 1664 as u64; + + compressed *= 10_321_340; + compressed >>= 35; + + get_n_least_significant_bits(coefficient_bits, compressed as u32) as FieldElement +} + +/// The `decompress_*` functions implement the `Decompress` function specified in the NIST FIPS +/// 203 standard (Page 18, Expression 4.6), which is defined as: +/// +/// ```plaintext +/// Decompress_d: ℤ_{2ᵈ} -> ℤq +/// Decompress_d(y) = ⌈(q/2ᵈ)·y⌋ +/// ``` +/// +/// Since `⌈x⌋ = ⌊x + 1/2⌋` we have: +/// +/// ```plaintext +/// Decompress_d(y) = ⌊(q/2ᵈ)·y + 1/2⌋ +/// = ⌊(2·y·q + 2ᵈ) / 2^{d+1})⌋ +/// ``` +/// +/// For further information about the function implementations, consult the +/// `implementation_notes.pdf` document in this directory. +/// +/// The NIST FIPS 203 standard can be found at +/// . + +#[cfg_attr(hax, hax_lib_macros::requires((fe == 0) || (fe == 1)))] +#[inline(always)] +pub(super) fn decompress_message_coefficient(fe: FieldElement) -> FieldElement { + -fe & ((FIELD_MODULUS + 1) / 2) +} + +#[cfg_attr(hax, hax_lib_macros::requires((coefficient_bits == 4 || coefficient_bits == 5 || coefficient_bits == 10 || coefficient_bits == 11) && (fe >= 0) && (fe < 2i32.pow(coefficient_bits as u32))))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| result < FIELD_MODULUS))] +pub(super) fn decompress_ciphertext_coefficient( + coefficient_bits: u8, + fe: FieldElement, +) -> FieldElement { + hax_debug_assert!( + coefficient_bits == 4 + || coefficient_bits == 5 + || coefficient_bits == 10 + || coefficient_bits == 11 + ); + hax_debug_assert!(fe >= 0 && fe <= 2i32.pow(coefficient_bits as u32)); + + let mut decompressed = (fe as u32) * (FIELD_MODULUS as u32); + decompressed = (decompressed << 1) + (1 << coefficient_bits); + decompressed >>= coefficient_bits + 1; + + decompressed as FieldElement +} diff --git a/libcrux-ml-kem/src/kem/kyber/constant_time_ops.rs b/libcrux-ml-kem/src/kem/kyber/constant_time_ops.rs new file mode 100644 index 00000000..2066a1d7 --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/constant_time_ops.rs @@ -0,0 +1,64 @@ +use super::constants::SHARED_SECRET_SIZE; +use crate::hax_utils::hax_debug_assert; + +// Examine the output that LLVM produces for this code from time to time to ensure +// operations are not being optimized away/constant-timedness is not being broken. + +/// Return 1 if `value` is not zero and 0 otherwise. +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::implies(value == 0, || result == 0) && + hax_lib::implies(value != 0, || result == 1) +))] +#[inline(never)] // Don't inline this to avoid that the compiler optimizes this out. +fn is_non_zero(value: u8) -> u8 { + let value = value as u16; + + let result = ((value | (!value).wrapping_add(1)) >> 8) & 1; + + result as u8 +} + +/// Return 1 if the bytes of `lhs` and `rhs` do not exactly +/// match and 0 otherwise. +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::implies(lhs == rhs, || result == 0) && + hax_lib::implies(lhs != rhs, || result == 1) +))] +pub(crate) fn compare_ciphertexts_in_constant_time( + lhs: &[u8], + rhs: &[u8], +) -> u8 { + hax_debug_assert!(lhs.len() == rhs.len()); + hax_debug_assert!(lhs.len() == CIPHERTEXT_SIZE); + + let mut r: u8 = 0; + for i in 0..CIPHERTEXT_SIZE { + r |= lhs[i] ^ rhs[i]; + } + + is_non_zero(r) +} + +/// If `selector` is not zero, return the bytes in `rhs`; return the bytes in +/// `lhs` otherwise. +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::implies(selector == 0, || result == lhs) && + hax_lib::implies(selector != 0, || result == rhs) +))] +pub(crate) fn select_shared_secret_in_constant_time( + lhs: &[u8], + rhs: &[u8], + selector: u8, +) -> [u8; SHARED_SECRET_SIZE] { + hax_debug_assert!(lhs.len() == rhs.len()); + hax_debug_assert!(lhs.len() == SHARED_SECRET_SIZE); + + let mask = is_non_zero(selector).wrapping_sub(1); + let mut out = [0u8; SHARED_SECRET_SIZE]; + + for i in 0..SHARED_SECRET_SIZE { + out[i] = (lhs[i] & mask) | (rhs[i] & !mask); + } + + out +} diff --git a/libcrux-ml-kem/src/kem/kyber/constants.rs b/libcrux-ml-kem/src/kem/kyber/constants.rs new file mode 100644 index 00000000..a48705a2 --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/constants.rs @@ -0,0 +1,35 @@ +/// Field modulus: 3329 +pub(crate) const FIELD_MODULUS: i32 = 3329; + +/// Each field element needs floor(log_2(FIELD_MODULUS)) + 1 = 12 bits to represent +pub(crate) const BITS_PER_COEFFICIENT: usize = 12; + +/// Coefficients per ring element +pub(crate) const COEFFICIENTS_IN_RING_ELEMENT: usize = 256; + +/// Bits required per (uncompressed) ring element +pub(crate) const BITS_PER_RING_ELEMENT: usize = COEFFICIENTS_IN_RING_ELEMENT * 12; + +/// Bytes required per (uncompressed) ring element +pub(crate) const BYTES_PER_RING_ELEMENT: usize = BITS_PER_RING_ELEMENT / 8; + +/// PKE message size +pub(crate) const SHARED_SECRET_SIZE: usize = 32; + +pub(crate) const CPA_PKE_KEY_GENERATION_SEED_SIZE: usize = 32; + +// [hax]: hacspec/hacspec-v2#27 stealing error +// Using these functions causes stealing errors in hax. +// /// Compute serialized length for output size of ByteEncode +// pub(in crate::kem::kyber) const fn serialized_len() -> usize { +// OUT_LEN * K +// } + +// /// Compute block length for output block size of ByteEncode u (c1) +// pub(in crate::kem::kyber) const fn block_len() -> usize { +// (COEFFICIENTS_IN_RING_ELEMENT * FACTOR) / 8 +// } + +// XXX: Eurydice can't handle this. +// digest_size(Algorithm::Sha3_256); +pub(crate) const H_DIGEST_SIZE: usize = 32; diff --git a/libcrux-ml-kem/src/kem/kyber/hash_functions.rs b/libcrux-ml-kem/src/kem/kyber/hash_functions.rs new file mode 100644 index 00000000..3bc9feb2 --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/hash_functions.rs @@ -0,0 +1,116 @@ +#![allow(non_snake_case)] + +use super::constants::H_DIGEST_SIZE; +use crate::constants::G_DIGEST_SIZE; + +use libcrux_sha3::portable::{ + self, + incremental::{ + shake128_absorb_final, shake128_init, shake128_squeeze_first_three_blocks, + shake128_squeeze_next_block, + }, + KeccakState1, +}; +pub(crate) fn G(input: &[u8]) -> [u8; G_DIGEST_SIZE] { + let mut digest = [0u8; G_DIGEST_SIZE]; + portable::sha512(&mut digest, input); + digest +} + +pub(crate) fn H(input: &[u8]) -> [u8; H_DIGEST_SIZE] { + let mut digest = [0u8; H_DIGEST_SIZE]; + portable::sha256(&mut digest, input); + digest +} + +pub(crate) fn PRF(input: &[u8]) -> [u8; LEN] { + let mut digest = [0u8; LEN]; + portable::shake256(&mut digest, input); + digest +} + +// #[inline(always)] +// pub(crate) fn absorb(input: [[u8; 34]; K]) -> Shake128StateX4 { +// debug_assert!(K == 2 || K == 3 || K == 4); + +// let mut state = Shake128StateX4::new(); +// // XXX: We need to do this dance to get it through hax and eurydice for now. +// let mut data: [&[u8]; K] = [&[0u8]; K]; +// for i in 0..K { +// data[i] = &input[i] as &[u8]; +// } +// state.absorb_final(data); +// state +// } + +#[inline(always)] +pub(crate) fn absorb(input: [[u8; 34]; K]) -> [KeccakState1; K] { + debug_assert!(K == 2 || K == 3 || K == 4); + + let mut state = [shake128_init(); K]; + for i in 0..K { + shake128_absorb_final(&mut state[i], &input[i]); + } + state +} + +const BLOCK_SIZE: usize = 168; +const THREE_BLOCKS: usize = BLOCK_SIZE * 3; + +// #[inline(always)] +// pub(crate) fn squeeze_three_blocks( +// xof_state: &mut Shake128StateX4, +// ) -> [[u8; THREE_BLOCKS]; K] { +// let output: [[u8; THREE_BLOCKS]; K] = xof_state.squeeze_blocks(); +// let mut out = [[0u8; THREE_BLOCKS]; K]; +// for i in 0..K { +// out[i] = output[i]; +// } +// out +// } + +#[inline(always)] +pub(crate) fn squeeze_three_blocks( + xof_state: &mut [KeccakState1; K], +) -> [[u8; THREE_BLOCKS]; K] { + debug_assert!(K == 2 || K == 3 || K == 4); + + let mut out = [[0u8; THREE_BLOCKS]; K]; + for i in 0..K { + shake128_squeeze_first_three_blocks(&mut xof_state[i], &mut out[i]); + } + out +} + +// #[inline(always)] +// pub(crate) fn squeeze_block( +// xof_state: &mut Shake128StateX4, +// ) -> [[u8; BLOCK_SIZE]; K] { +// let output: [[u8; BLOCK_SIZE]; K] = xof_state.squeeze_blocks(); +// let mut out = [[0u8; BLOCK_SIZE]; K]; +// for i in 0..K { +// out[i] = output[i]; +// } +// out +// } + +#[inline(always)] +pub(crate) fn squeeze_block( + xof_state: &mut [KeccakState1; K], +) -> [[u8; BLOCK_SIZE]; K] { + debug_assert!(K == 2 || K == 3 || K == 4); + + let mut out = [[0u8; BLOCK_SIZE]; K]; + for i in 0..K { + shake128_squeeze_next_block(&mut xof_state[i], &mut out[i]); + } + out +} + +/// Free the memory of the state. +/// +/// **NOTE:** That this needs to be done manually for now. +#[inline(always)] +pub(crate) fn free_state(xof_state: [KeccakState1; K]) { + // xof_state.free_memory(); +} diff --git a/libcrux-ml-kem/src/kem/kyber/helper.rs b/libcrux-ml-kem/src/kem/kyber/helper.rs new file mode 100644 index 00000000..c0bae70f --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/helper.rs @@ -0,0 +1,57 @@ +/// The following macros are defined so that the extraction from Rust to C code +/// can go through. + +#[cfg(not(hax))] +#[macro_export] +macro_rules! cloop { + (for ($i:ident, $chunk:ident) in $val:ident.$values:ident.chunks_exact($($chunk_size:expr),*).enumerate() $body:block) => { + for $i in 0..$val.$values.len() / ($($chunk_size)*) { + let $chunk = &$val.$values[$i*($($chunk_size)*) .. $i*($($chunk_size)*)+($($chunk_size)*)]; + $body + } + }; + (for ($i:ident, $chunk:ident) in $val:ident.chunks_exact($($chunk_size:expr),*).enumerate() $body:block) => { + for $i in 0..$val.len() / ($($chunk_size)*) { + let $chunk = &$val[$i*($($chunk_size)*) .. $i*($($chunk_size)*)+($($chunk_size)*)]; + $body + } + }; + (for ($i:ident, $item:ident) in $val:ident.iter().enumerate() $body:block) => { + for $i in 0..$val.len() { + let $item = &$val[$i]; + $body + } + }; + (for ($i:ident, $item:ident) in $val:ident.into_iter().enumerate() $body:block) => { + for $i in 0..$val.len() { + let $item = $val[$i]; + $body + } + }; + (for $i:ident in ($start:literal..$end:expr).step_by($step:literal) $body:block) => { + for $i in $start..$end / $step { + let $i = $i * $step; + $body + } + }; +} + +#[cfg(hax)] +#[macro_export] +macro_rules! cloop { + (for ($i:ident, $chunk:ident) in $val:ident.$values:ident.chunks_exact($($chunk_size:expr),*).enumerate() $body:block) => { + for ($i, $chunk) in $val.$values.chunks_exact($($chunk_size),*).enumerate() $body + }; + (for ($i:ident, $chunk:ident) in $val:ident.chunks_exact($($chunk_size:expr),*).enumerate() $body:block) => { + for ($i, $chunk) in $val.chunks_exact($($chunk_size),*).enumerate() $body + }; + (for ($i:ident, $item:ident) in $val:ident.iter().enumerate() $body:block) => { + for ($i, $item) in $val.iter().enumerate() $body + }; + (for ($i:ident, $item:ident) in $val:ident.into_iter().enumerate() $body:block) => { + for ($i, $item) in $val.into_iter().enumerate() $body + }; + (for $i:ident in ($start:literal..$end:expr).step_by($step:literal) $body:block) => { + for $i in ($start..$end).step_by($step) $body + }; +} diff --git a/libcrux-ml-kem/src/kem/kyber/implementation_notes.pdf b/libcrux-ml-kem/src/kem/kyber/implementation_notes.pdf new file mode 100644 index 0000000000000000000000000000000000000000..adc84302604712f39f42c7375dde699ecc99a884 GIT binary patch literal 348700 zcma%?Q;;Ugwyn#yZQDkdZQHhuF59+kv&*(^Tm6@D*S_bzofUESjL1ktzGcjeFUK57 zt|%%_&&;r1cf&tw`ixH(2P1R8BH$?T|}YHDv6Mgkh;+{ui^MGd~Ssle_?f25d8%TU1lsrL79&TY4F*-Mfo(q<|X8 zFPYMgmr61oI9HU=9=R zg~T(`b>kWq817bAlUmal>_A5c%y!Ieki$!hkiSyticzEN1D)h&G2yi_OPtQdpoFTt zPYuX2ak?7-cq3hO&~mIJ>(%~-x1gm-S8!~aXiPOzP?Pi@k-=(aAnapX%1!z zz6o{8+)F-|670_T@}LRKjV+Cd$1Mc4a$KLxt=@_0$vRn@0c>X#ryie%bH?rAu{l_AmKd8x#N$mf{H2n>xJ%Iv@HRr!*XelXDYT7bvGZo-uk zm73rEQk^Kg_jsw<+6#w_Vlj+jt=|~=Q|j#*`9{hgy#%Cw5mb(sYtlN6moH6nFS&(_ zPI4cEtvAY|K*}CUJM@0UBZqcOM*3w5N-u%@ZT!Su8Z%ixxSy5^$E$7g%%jpLM*`Of zJImN&q^A)5#b=-$7wLl&C!sdFh+|P5`qerhCSBb3eY`DruiDUG+;mgLw5(;p5AZYi z)E8NBuNPwYjjYI9XZ+yixRUQ>xy;447nJ?-y!+0#)q$t)WGBa3d1c zk3albVUNb?Dwm4FP;bfo3rgFWZM|)0*=9X`0Zy3B?E2x*@iC{4x?TW`nZ4=%%awmd z|H(5hw*Q@QEG#Un|82spXzREfNhABu)iW^?VP0{&^x3XMA~c{aS2`MsD2;HJ!%(K7 zu5B)oOqjmxJ;jPElbIb)@hIM-P_I^Wmw#m6)^C+Hhhyh{eMfPuIXKk+@v1+Lks>KM zZQcUJFpJQ&vx<-#3D4PUG!vq57%+{hJ^Cfub9T$M(Q#OD|6DxB@AY6Bk5V};Gyibp z(sP+o6YPF$ZAX#iGJ-8lG||0uzweT*9OaPD__ftMk2vFEn7P;|f6e~%W;5P%(&O+; z0{~2=kxdBi*8H5zIvGT|9x{{GTB@<+YV)!azQmz&e}c*BDslMh7>AgQORUU}mDt0$ z%D2d?*`})9$F$}_9n|8xTQ;{pUJi&)BFb#r0z;*{?u{G0JpXRhVVoS9>-7%Y#s){A z+qX#j6ELipTspWqw`ck!cS_}PnBfq7zn``rQ2Z>v+H2W8PTwWD5W;4%Ioxe&;CRtU z3GO+hcYFK28n)93te!3w=Kj2HFcK+DmP|JC66br+i6Wgj+;Z@5eL`{ubis4-Z#@RF z2|$8iJ4ruah@@4B6Oz)u?mF~}ryU0l3uB?@968)B&A2D?%aSAsXWy~ZA*`A zlH=Z4nt>)b0Wzj8o0DeI6$loK{Qg8;G$&cELVxfT#zTJy8+4%QL$fuO$RoazZQb2| z{#ZSfDOrlcWG2_PbZ5vVX=CusMoUG|S1oy;rz}6Z2ySo8tu6L*+LT z_rxE8OY|CtD-Gw6z@(VLh#mf*i=j@W6eDfkM%>gThP7HX56)9DF-gxgUfwZR!!2|b zv(u~J5J3P{Gh+}Z3~z)zeo1!5Z8$^-OBrZptk!IcZJ^a-=4ATU`+N8R=4cJ9&tr^! z(x7h57Y8hm0{Xh&4=8zb4v5d;5)E4w0E;^@yn`isC+^P&mviuh1n)b^?Ds}i57%@bG#vk=&#h&4rrpXPITQbvTRqizYVx+tM3#K0wD6 zgPwRhExHlWilgDy#Fu1cOy(IT3u3kDwF@colREO4epmWha zW90zSP2u`fSr|ZAP;pI48Dlvfo;45OUXg^npKm2itwVU^8OwLoL##zkNTWot?YKhc zK(77K=qaJJTB*2cZgO`_?7dQQiY>diQV6#3Exk_)(Vdy4!t1U(qbI^#LLz0Mc+@jQ zJewHH+iF$c*VqbjSEJ zzt?xlUt|sbiMmR-D{a8+wAbB;X%$%m;3i^PVH7S=5?o>-3K=DTqU?z$b$QyK&WYvgNZK4K+G+B@dqLKfGx#+iwlZe!^OjW_+lmKzl=U7hOV8W?#RR4w~1wXZw=anBL zB~N@P-8UelF0n?oSWrhT7ouN~z~&-RP4-=rm0FwnsDdMNzo7i4cwk-9v|jRy@)P0~ z_WWCb)636dd2bNG#LsP+z&NVM!D1Pqe4qF>m`o^@f>#8Yc%?#SMl!zuDl~Zs+Ha&@ za7{$ZBZOBm1-wtR9=HMgJ%gvu1OWx=u@r6ydMI}T_CtU`FfUFD=J&mWusSHJpLtwZ zQQi-*?2w)^-(JOS4n=IU(h9?@8fz26dBqbYwB-15Cs*!BIFCd+MGI#?$aGGh?;@BH z-DW5F^Lmj_B>uE6yAlw7oQ=pXdh*h$^Y}jJ{VMK&P&W1i6u|Rg?B7gRd{f@9-%3!b z!k;T|fJes<^VA{d#f;H>IpP5dxK*#VtW%1Je-1V~rrI2SdS;#}dTJ43^YJJY9&jwfDm5qsMVL-@W0P@iiZi3q|| z27A$SX&V*CtBdkyNXcP}`Zx(4`@18^kK&z^7Pu-29mBZg56WImrG08&J`!Sm#8RG- zB0d%4pJTtqfYaXBM{mHI38>{E(OwMLAuh_YRcSY%8lN1^zFHj#-dG>DBMGopX?(_! zMI-(!yGXbbS}03OOnZ1}(q5Yx;DH3Mr>O#%Ipo_rn`WD4Lu{{Ho%`g{N1kO~8>q|c z4CKeMkb!-;PWr1LZXyd~aRr%lTuPp!u5* z#v{W>LxWTE4ZNF#fQ(5F^&GAC8KSLyTM)CCR|PcAgYS@C`5gr420?cB_@$l9WW8hZ zs9kcaw;&A?EG_(vSGtC7V4#1!_aHxM+Dy4({Kmv+1T~HHFN4*h8tH>ck8gIdd3(-0m2TF(*! z@xSqhnTh3J_=lN|u$2`U-&C#ic016giu64R$`-U|Tj5R< zq2?#?%98}m2aSo!)LGx|E`Tkyme?BAQY{mH4K2-SD}$Z7djEGVb&uDx7xW->;IBQh zt~de@@uP>v_lL_pH=5&WE1QtCswPt~+VpIW=7>jONEIu3K9aV^a9Vs~sGwuvMxy#` zMVd-gP1JARgsp5Y4KLe6V^#A^%^2eNh82sCz#_0m`yj+X!ikGs1|qq^MKa9(hDinI zfgm-}tWcu?ik!>f?GE*Xn+^aRs!bu;Q2p^oE!>vZP^wx(jGBnLJ>H(fi8v-xzGwfq zdVgE8EZo+nr3s8M?W~sk@ef>tIyY| zQ|pf3=c89AwZjH<%7jp$1TuR|J$frx6-^w;mi3`6cnGv_U^G6LizG1-oel;;1M|LV zVBpp3IssidKFM-5j3jZ)wBNQEDz>lK;D#Pv0PYms5Ki@(ntl7n+S%*Hd*$2MsTE~I zrp>wozzU$tMg+>JrgIf=!(3o}wc-Bu*r2y8AeM`UQR@BMc%|&_>kctnVWjIeWEXNy zOsT$GbyeuI(jL)2l;6~H7o9ZJSGZ&6W!MP`D_Yu2ByqzM_Gt$_})$U{G|fBUzQJuK2AMa$<8uUL{!fFBJ!;p2a{w(Hb zHFmW9ROZ_*$gAnVTP}~Hhdcq+p|+HYr1f!z6ObU*uNR6|7`nwckxNR2IV<#ei>wN0 zI~}aS8=i7tZaiThAcofU_2j5pQJ=+(t92FGpLe5feSujeVN%6E%Y^*4_XXzF+*ew% zUcTof-W)%>m9KyK&d5s5r_!~jSBbLo^4#;ue(&iY(MauArnJE3=nX_gYksd2klz(* zAld!;V^pFRK`0(ni~-HM-4f#k?yokhMwiHh=4?HzSKlF0GGoG?#%L6?gPf5&-Is)% zznK4F@92>L4maCA@D=}oVo987mGXQ~P+iQ(&Mc`R>gibd_ttE#iiNRp2zWYOl5xd= zHCEv(4!Tjk!^N5+xYVjDMxqz-cKCC$_99sZ0rk3@1b?!t=y!*_k=;k^0r2ShCV0$m zb?M;E^cd#FUr=OCi~PV)pA>DBqD0#8qWe2~z805IviX8N%k}x`TO3?hkn`7WU#jLe z=RvK1gY9y~8m*4raH)>UR>&IgO`Q3vyn1&Z-v72}{pk^qu#|B)-JH>1V@~#$D!;Hw zPxz^DAjLIVvj5UkolERnyAqX2;ApQ){v{L`##z^M^Qg35Xh7noTx3#C9p zk7s4MILJY(Po%MO(aE#psFzpA6&@kyZL47$5)$FJ{UNLQ*$ao+piqNmnSDXSP4B`_b zCe1A{rc_Ha&vX&qK@?|+nD`mJN&_yUiCLE8SOYF{5O>b%-)~&YV(!lW!nW1ChpTB^j0OGc}U#e2sW<^D==MVA))i0v+L)A8R9hBRxw zXCt!wF2$YM7v+|rG|fT}4kqT3zTy}TpmWD%`T`la{F?uiJb(qt>eaMGk*UN%AhsK% zvj%i%*K;s#kwS!%AGHpv!nC*l@}LP9kUA-@u@d11{9sR(E){YUW=&Oka$ZwTpG?2% z#xb&{U$Lpd*0R%O+)a%;hGwh7IN> z?sHDdcA?1BogZTb5z{Ns2 zzoey)ZCK2GvjOE86p4f>fR=;&9Q$k?NC&SawHR>y_O(bSdWZx?JW6Z^yQeh1gdpo0@|F*XA7?4=S!cx4$ zpId^5jdJY#ubU{3x`3`u@2A-eY^T%C@{O6Dm=KHEx6G5MM7HMa_~!hx0R8KG!?kyZu3ibJx?eDgpFqE)U=1kQ;FgZw)uPc$k-u zCsQ@9ePyCsyWg;KNzPr{m6?2ja*WKS{)iY@}9(x6VOcJ$1caxLON z9PHcexkWmg;2 z2eH4#n0wMEOV7n{#H3{Z2VK5H=L8O?2rZx#LhfaJUExvRu%fCr6f}NlOa%4*G$dIe zYDu#)>RC^jqQ|{q4^Cq1F%F!89zkdg-De?Yv_+?3qWcKwS9ESwa9$rqB%!QK{Y-*SA7wR2&jikC3B{FcCxbSJz>yx9xTlNFOLw%{fQ`OO9tcR&sS(lC6GUejjL@(;R-SO2VIn5y7z8VA zyXEg98pjC;c6F-Y8f2vtd~(^*Dy%FWmJ@s*!9AIU+4`(e^t>_)HH6Uh{;NMNq3OV; zs0fxhRtzuvARB8B^5D1N|6piNy9IOH1YLqFfs1oOpK#@d`|j4hoY~ zl>Yt~lj76*m+=~EZWJ%wu#^s?h?xOhYA66HlUn!C5w#bdfwz>z){b58;*=48dSw9hgSX>ea z*4Z)eRBDE#`0TTa1!qzkHhKAa$D?I_XeivhI4Yej_KP2c{7f0P)g_iDswQ*go5umk znd&O2n$~=it@JUq@n1)XZmI5Wn}on34zDVp`Ao9w>jJJs0pg7mn_iposEuCikU47Z z*SHdltiTe#)&zAo`W9XKwF*2Xh#QY`ITRz{7cvC{N%MNLN<%b5{7DVOT|)S`+sz5?%bgsR z0{#_@fLY3LJB~VNwcCJ4viS@i>Te`#9exA)myI?cvG=^H6zO1TH{tsBM&<7ebaJJ? zuMY^p0>qBZ94ymajeKHZ9rpDn5%XHS;JZ$gG@j*Y>iC{7M5Tj7Xh9EOk@vg)dZdw9 zoxj0DLfFW=x>Xi(^@{6MpZe}V5hm8HVAi%)oFB04M|=bN#v$N1@OOxA*PyVJ1e^4I zcg?`HPIGV;CfNM)zc~0n1ga7en5>Zt8#YNW6*U(=t)A|$me^;~PsYw{YR{rqR6fVg z5H|?2Ny{!%e|T}Fr8}KyA}?piWFO;874$*)G;p@{F~LF$4yu+N0|l1BkJt6HJ>e+|w+OoqR?bZG~ST*~+wrGVJ_|b_RKWIn4JwBPdt~j@EUt@lRpV{8E zAmO#b3bQfaJu_qjf~c9Vg_e=rR+|?CB$4)YNxr{0*3ZGaym!OB_7%kQaR;Ga>PWBz z-9#F^wF&Y1HCpm=mV@{aiRd5o;z>(5+2RsNNJ_B9BsrrJ)L9@0qJ}WWwtlFgv}6ut zWter7l^hlH_WaT-jeB4 zXfg223~uanEPw{84&2M&W)xgJ{omd$MGj!>tR}3ylPHSa6AahoK_E70^l3;tT~v(p z!bk!F>A1EXGs(brjlHY8*j9A#wRJ|I0%sRY*-2CtvOJKV7H~s$pH6E4+wzn0KnXw- zGHSeL1_`S{_;SGJ%@Cy@R#K_~{p6llG2PQb^u3*V=FgP+9beJ7VQVn|_{V@Xq?a;n zpHCM&&tAIpvy-MNVLJT^jMSS{NMMjIJ8z}pM(HFQD-3vXK)wokB4bl5)RLX(c-%o3 zKu`k!LC6EUO2MC0j1rI74l=l}NdC*YMO?GUO5LKFuoLLnnD&oG=)ujil^VR31|qRR z3CtTxK;sTwb$0h-wBN+ey@`(hgCYl6T0HvKuG`tw&Vqn)=ptVR$40qE&NbpN>H+ty z_)+E1J&`gTzFuROzW!kTj$k(Qp0`tc`@((zgE(TJUI?#%}=WD1^05AXc8~ zEsM@t64|ymHI_$~%4A6!MyGRN(CPB3pay~^zK-6}d%PNGYeCvOKNV#yPAvol_8y6H zjW7JsS`y3XoqL{}@|3T^b3!vS#JBWK3`0v~?HN|*`ko+|?pJN()!rlw5xni%&YVb} zm3H4W`B6g5M=BUT;L!PnGiY>Muor8Y^j1Tg8Ctb#`zy92=EKK&AW;c{?{3lDpe;6V zCyVvcRl)l{3U(tQc+gv~uxPOn6{G&6eC*P`H>S1{zT>g(SlG`{3I!~GTT^aW_e|VMo^rIDN!N4{5^|?^)82&A@KAotGbU>1R_< zpFs#%KwRm^*3}>oWfLo-!ongZ?F)D3xd zwTLXIpbssdFH5dHOs`(_8Gv>cp^_6!gbF%B8ZY4y=Hw6G_V>~PCkeRZA)asXfOy=H@KY;SEVqV%WiD(Y|Wgk z1`xs7Bgp-4(=93Y%gBA(k$p25vM*&<1s%U5%c52Tgn0T*{&vcJ7#{Atv!$6Q&XiP3A#yYggrQSoDdZ1*&5 zH@KcE_ICfn7=ZqMb|RAokmFv9zM~%NvHxaqZHN!dkbjjycupifHF|{or(cahv|)B{ zxH}Fd`=MRW70?hH>>}y{y=*!n+yb&MLI9kI3VIUAr-u9CrwEi#j0{xa*Lby5{7_U z1(zU2@Dlw>N%MyKYxoB^EsfgkU-+Db`+xH}D-%2Cf6M1Lx?A?R6UcsR8q+Gm19|Ry zjKGggzwk_rY*Fe1fi|u|&6L_uR8%Fk^uPS%Uvz!eT?)BU@cI$c!c-OH+|&S-Dm(0D z8)Gr%0RqLjdxE+-yo?jo*e3(77-*g&B%e^|u%?9+o zHex)S)*{_}fZI3Y1;B8ApKK!fKdE1wV;?l(G}DD=JR`}(EUiQYD9t80V=2`TxM{&f zt~iNCipLaP&3Mh;9MX`-9Tl#s7Y9g3yGXYkH$Le?HFo^8bjeAf8Ac3=#VHT2%q};1%#p zLTh(lQ0>&@M}6)rwLPZ~&`KZmDSb8EZ;ad$Ee_lFGWSGdKPh&uCaV{3;*1pZ2w zDypan3cOq%f-h7z^Rh8zDZrwfts4E|=HvjgUW|;wGRtE`L0ga?S-4%nZHPAvVHH>r zctm?{oU_Ttf=5}XNA4`c7QILb#}KiFgor`@E(CeiJ}8n`P^L~lNmHD}J(sD|A0!W$ z2z;zOR=~9Q;eSFBW=(^hihvlkzJW^S_-GLLIMK+`JBSxFPmwGssW&?3NzQ37{F&RB zvj|{J(t-@Y$N2M`$*j@-=2wmrrms~*OA)&UVL;6LU3E7qjm&R4lUKA<^hD_qoH6g^ zrcInDRX(CRv?(r1^=ckGS!;XlCoZZlYZXzcm!wV#ecWl3(d|miu{^dgBHQ}7DN!sO zp$zv-jQe0S5dlEXFL-ey@+nlfp|E-R{x?6Rim+luE*ZKahoI47CCw>o8@wW<=2B?* zaJ}aYXY2-Tcl=eqh2d4ZIuW>ef+`go-K0+;!A}?HY z(!qSs^K1bxXG2IE2A7G(lCXHw-t1t74*P`%PC_`olRsGdfrx%WvSoxZ-|7DL!Tg9!t&D1)G2m&sKgOy-!8^MOPhC%2ejLgBtACF=c1B*gH<% zMF2-~kmgwuz#UUwi}c>B0S3$<5~?cg12&%)YWTQxX?~snT&Y!NEbnihnuR*3^`YH4aD zT=y!dk-xQBCHMc7EB`s*{3g7H$c9W*dtF0$m)E8=H*E`?SIH=^9IXlOEY=5wlDCSq z5FY^;gdx_v@`x`}$_+M3|JWw3Pc9m+4RU0i`ZdGefs}U= zyx^cee(bJV^3`E+{+2Kj_9MieE-*k5EG4NbBCZct>i4m{4nnSjjSx$^wpkyYtrUgn z!mPQRxvA6{wN-_me}Hc~CkWC@do^)2V!f1*gB+|rn;P3W7c?T{zz%G=r2Kk$9mXKk*xI>5tFjhvnJ+G%F<-Q5_Fh;rPvY{OPbkKZ zp%+1O{iNu>rRh_OU(`O-ACowbTE4wi*9MFSq&vjOR?KZY2HQ*#EBcbsbz za>k~!X~jRe*Qi7@4=*BfIF=P>QnWvsZ&ANm)Z*<*hM;}856#noeeh8-aqU!SWqh-hY86LG20lH#Ai8HesF~qE4&y zuhy;aX!CFD*1|y1emnN=)I?W%052g`oX|IIzbn^A>$ok0Ec`(=>e{GV9cdsQMnWhp zN8$3a*EKm zVce>>yJu_fF_IpN>FA^dzg2hJR*ml)-S~1c&!uc!P-H}?ss>vULPdQ&h#-z;Ie9%i%%S)7z@8_Xu=hm`X*8J#mb~#!79yyfdygdrg&A*a>_0QO z11vSS8NEx{p+PwowGs~{!v3Ju;IZXPV<@902tQTj_N{WDx2!mc0Vd+dbGE}%A;Ltc z@J&6&{6It**~TQ91%{A<@CZh>MZkZT;O3!$ATs#afV|^$(2ghpdfVIEZKtfo<2moH z3iByZUx-R@zAD-8(wG{R_X{@|9iY?oyr(akgwGd)R9Um?9HR34RTF^u2Ezcwca#)J zS(gvZB>b@m(GjH5q!kB`sV)3P9VOOsXcB3m&HGMM8WmB_5h$$g6z7Nd><If zB8PxltMuK1GJUj9mPOd5e98gVeaSOq8Q#Koj)m^gLUF0Ky3P@5i(rTcR+3vQg}j7A zx^9`rtY7Y_45~?ZZrxCs#NXGWN5O0$PIHD=n++p*KOW(z=9oI9weZ693vZ!`SF?QR z+>t#HRMaKQQ7{EQv3!1o3QA9sS@V(2@gwn(iw#-iRaJ`SH%B6K?P7hvHO>f@C!XH{ zWPSQqvhNYa0R4+t6)xXoJBcmO^--;aaOK;p4aClAumzb1Ut{xayGKdx7*A5?J&3(2 ze&#m9{SAGUT}`k_9^#m9ex}>xG;`!t9>3#YX{IqTU;d*Is8AXv`ZehoExEd#5?~o+ zmJkP-c)1WyRC^D2%;JEkwdRdWk|Bd$KbZgiEAvj(=x&8Ly*wnN* z@ibCsfj&Ebw4E;`mHu5Mxo{?096cR*;eNyF z^UA1{Cu-8$Mtv8{<+fI&eUrxKx;vYc*S(K<>(do`TCQJ~6LbENM9B`%%ahOd_uk~^ zi_`Dr<$uXiB&XN~JSJr;^_HJ3pdvo>w-1&f2o78{P)9WiAa(9B?n^9E_o-bY68cSy zQ$A8J-6c4w!~5V*Xn=W zh@{a$9(Bg6em115q)OY_;q{Jq6_9Nji;>|cw%PoAJ>zjfVCj-jO=$IHFmYS{byWyh z`jQjj^2tBA4u{=-{ror?nOaje2O|xJpJ3QC3&AOAoj^N{V9M0nHSJ^gZse&+@6-E! zePlNQ48V~hw3`SPP`l^C6%Ki60O}S?8XBQI~#J z&_=ZJWe>4f2s1iPB6J={u%w=(kjRJh z9X+n@3>_PH>)#BXJh;2HXcQrlshWbs(Ae~jq=XAKMnj>nVn@X>rC4LpA0$;#YTC6-McBq5zhRN))y1K@->mJcls0z6SIjj;}j@1x2{XG3s+PbnQobdUHiq ze>b5)s1sRcy3At!Z2N9*+q&O<#nh##GJap3WoG4;Nm6BI=&`~%D zi!#mCwPW^uhc)BAK8(Sk03khZ!0(u&kxJM0-8LC8_&;BW*&0`2745@7i?klJI!;A| zm=4m+v0n{=U$$gS@hlCnw8h19bHux0aU@6#j~;-ID(wKXq9=l5iylkAN=4L=;fkB$ zLa+-`rco>*DK_*=VD*iQblVw>Th~wLSVFHFJ%bc*gS}R#fRZIOwUI`()RJq~U@b?Y z`r7BryMX$DQgQ+D!lh#6Nu5M;5p!kyvKWL4iH_+CMfHWE9JXD}3@L)nDaay*qje;> z`jy)+G&0WP+s`wHMx}}dQOmbnr5EdcaJIe;qC8I|!iBiygM|}R^K5LJ-k_Y^^}y>Q zM^dC1w1}+U(}pF&z8Lbp_uba5HOT1dw7#W~9%-2!xqkI>Wg-o!h!Gw3kWDngWmSK6 zstU!3`8S(Mm~$JhA4;gD7EGuJg58xdZ3svMdl_Fn zK%ZI~r-E3NEmS=y(kKm%gA9lM+_E(c0KxA6`-}P&HSiJ$nDlSEDX_!2!9Sa;>ICIF zfzlY7FQJQN5F=crgxJU`*bRCwi!dTQLF|7Eu-X$>#s|&>fVCru$*04w*lt+8QMo6< zTU6V904~}Jtv3|~EPad{X#cXpO8vx0n=F;lOKfbWRE+e!jLooHUN~iW&(4|j{9eX% zAFcQ$$diYpK3w#w`}5%RWJP^!?AE@k)i3yd7yohZWkYTQy(gk~*%tC;fcOUR|2VMk zjkV{t-Mw4o6zcgg^7}dP_tVAa{K)4xW>H?co4@w2JZ_ppkuKu(&^lY(LjQ z>I{fUTpR(B%3UEixiD?(uMjF8i}8`C%E*fB7gs2{zxV+SRVY(_l}<+!(1n08sAO9K zV+O8XJj~9^zp_`46bAnzjhGfy!*W5YE(~e`;XVDQZZ5#Q-_3Ls6TcJL%#{Fl*2R=5 zAO4Js<-DQrvh85FDOn?X2n;fohSx+$pw7Cu>y=vkt%DSlKhAB{jDQ%(QaX+|;iDk! z*nbZ-v?u6AzWE)EG;(gt2Nf<9nU5*_42#|;gE+3l2s>S|Qqo14UVjqB@LO0fYnCEP zJ12I3Aumi(e(?szXl4w{25x7T*w%7TJCBOw=-mB*EgV^@D_1D4?5q(X*aiXMW}168 z(w zL3I-z5G_bhob_wN;!f?`@e+ATIoyjV>Rc;@QM9$FqG%&CNI|W5LoccMWkOY`dFzhH()|*d z@hrj3cy*}F1~UQF)~Cn2>%!eAon)y6Ofpm65T1`^4a#Iwssq(T%7{vhJ|Dzr#l%rY zj1B4~>^+puJb}6`lM{a{rnD`)kmpi1T-Z(?fE60PG)`1i=a6Is$q0)T+k#d)qh@V9 zikj{Al9OvJ*t=pWe1K$x7mj%>j(9b;r^`F~%Pe@t(lca6PyF_yUd7;fH`J3pC|@RQ$3G5#`^{F@M#-aAlvN+DPZ;M=xQ*(<=)OF zrNLrLv16fMqRSsvr-oLAVD@re-KdXt)=@+!w4zPfKNRW1q^ee!KIp!vb}+KO zRqgmUM`~SF%od;USZFEQB0lCe$N0o<7%bEunv6c^8F)Q-Oq443-7QDp^vQWhI}w)_ zZN7Ap^+nvW6>6YM)MX0dj%A=;isE68C3Yz&b5|*0!zuGXNIqy}875_m6d2Q(b5!D? zsB<)6$Cyg51SoKFSfk`Kfk#sKLd*JLCJeuWm^^OhUSE7hW!O4OLb-bQY&nlwj1!GtjaQ}86V8M4pISL2 z=I2r|Dk)~4;X!*zQtlaz935n=KALRXi zS}dc$W-w-OsOD`6OucNYtEa?qypjX{EU&pa~l7W0^Lh|8vlAQU7 zM|z+B*XzxTG^b4li(C%VhANhE2OK+J3b|f$33-^1pzm+FDjM?$mMWS@4z$RRD=4)h znukZ{$=KYU!l<;B%nBZ{m?pIY&Xh&f*fdEW%VZ(FnDh}{^9a_Ks%Yx8f23^~vHB_H zE+uKC8N}X?vRe(+RMO}9N-SFowFo<|%vnBEJKHzAlTl!UQ zRiVg&!zDZ#L9+^K$=5OQ=xdaF8w3R&zET`0paO$1eBMpu5MHg+i%WXJzpIG7HsV}x z24ohZ9&_U&MJiE_SYIiqmR_b~c^fh2NO5V3bxmDUeB2C`s;C5K7s^$<5DnG&es0Up z0gIxn#xao=Jk~ZeDP%aZoZt~!10)6s$M%kjr@B}39mHT0&5oQTRC!GdoRrY%pKOen z>r)CUqj*k0%pxJRyMt?(0o`4%Hz03u=5$BGNVH~UGPtFtH0=ZJRE-@x@ZKT!aojzZ-u^=czvg!T8qQ(q`{Z? zKdTt<1e(A85&@@m)OBG72T8O20#e-sCZD;Glcw{-=;EKV<|f>`ME0fad%U^uol1qM zCZaGr-t<4&l6bPC$5CM&Ehg-hW%L+!^kFxIzKY}O*>PHGG1nN|%D6tSCf&@Ga0OTf zHR1^2iAJ%jYF}5=rJ!V*r!i@I@?X;ugQ=CJ`@=hyPO*&$oUdzkHGkxSsv^Ui=AaV0 zEd~3P9@V@0+VgPaSY}L6dkjON6SuGviK8uv&=RZ`*eOcnV??H3l&5}1NChA8tnmdW z8Pcst;1CU$Mu&f|?p7+O7C zG`7478d|~AnIP!~L8(>!-gt*Vy);(dUfXcZo-K1Zw|#5=DeJO6h%D@c^N77|vrHKB znPRzs`}<*)cvZ+?C{lHE!G{&kCR)d&OKqkwxF?)#>A(c()>z*x@kbt54YhXi{W~Qn zK3=YD##rHRv~`TZ=RMl?1!kv#0VxpkC?n0G;j=igaNZ$ypLxs&fAMEvl9s=G-b0CL ze8g5@5EL}YCc;#FWuafqcP z%bCi^m%5b^tPA(jLfstrHO1}O{SExL!j}JYcD&&~BSujsl z@*~OMYa7e;1ZcXa8{n89<3UptSvI2^6D^>_bJBR__yR>N#luAzI23EllhY`(()Ota zK}<{Y5dz6hXauQ9jc$J=jl}7N%DHS?jP%6u3uEFRSFKCvaAh;)LPMRTA)4S)%(Na? zAm*O_1UPY{Ps>L6@NG=JnzDcRH4buqsJ$K@C|6F{dQDLH7?2&)sC0j#6k);oEz)sx zl-!q!tiR1TL&)I4F;vDiGT@Yg9Z;ZmW{YFaqnZ6A*EaX~=@L+HH7;Rc4Zx#Y@a zI7&c|Yagc#C7zbdnG=a}+Z*D}klK!xf%FV)5*X2NPpTS+RK8mZ0fmIPS}>>X6W^e0 zNavYWlO_dvJ}QwB6Z<;SCrQeMfbF;Cq)W+x74MJ{!-ep?nEi#CLN8z z@22w^)z@HeSq6%@PtdgL;vX=s_{c(mr{IxzK~#e;?5qA@ek~UUhHwlX1WJ1=#v`w{ zVzDBTs!#!?Fh;p_B0-(~J!kZFUZ(nzQBfBaoV-LjZ|6NQLwxTL_(2|+`HWu$BEWta z63iF-kE>an%Q&=?8XF%sN>nE_JsIJ!96=nrsKf3>+oN^)+|^XM2E4LgeUsFwCyM)o zn9sQC;kfR^&p)|nkIlcX*2SVlWl|iNsn~A$B$Fi4 zFYZK5gWcF`qVR+~aw+kSC|$+s=J=AJXGB#}8MY)0m1A zJ^LSf#Pq_`c6hzUn{BVmoqw<~`m~u!aJmEy@6_;danOLBv!NrWv`Xb!YJLarZ2t@_ zZN&VgR8|ypl*Wm$yV}cuhH%Rf#EC^jjG}**lJr+jne@0qj;Z{Kmu#ugJ=5m6`XiYR z{}sjNgQz5<;0@{tB_#A+?_~pg_%WqAxl#sh&7&(|BTflh^(r|f++|s{RF50ff~9p> z{Y8F?_2jP@7nuteee;&;n&Q)Aw6XeewQp>Wa)?Lv)}^VOmU(8qdh`9Qd$VrXy@x~( zbv10`o`1cLhZglbr@0Yv)qxtxL4C7c9u82Aa^)7}bjxiD#$M~DeSSq*{*BQ7Xr*_* zanH?BhYgu~Z=a%j()M?z_9Y{c`0CF~(XVzPEAH0&hFvr-z)B62LbMwo)&V5%l*ulF z%$lP4@x&H3we}IDC-J98Z+k}rD=5DEW5iBPPfP0iAKvQf!LeVD>Fd`eTmvC4H0@+C zCkNv6h<>xx8g$9+vjqOTgJB5Iu0CEXF!%Inj``;?ILIKKz0Ulq)uX8c45NC)xs4uk zv`m+Itx){hvZGH<`5+z~0gPgJJ4Im90onp_S%}&8H_30FLzm zWL1Isj`Rd-p}-2Dlh4P$JrPtFyTPV)ybExQjmSI&`^QD_c+6s|C$2_zcqABDtRI)m z{ixSVI<{&aZwL>%^PjT6dNlj9!78Zxu{SGGeCl8Bc0;8$Q`4{ZI2ksFnk8&zY{Vw~ zbZm?1z|Rd)Ed?_nLL-)&IFg425Ki-}F&wB@9)qZcCP{vzx_BYP5a=ERYLxdD^so#C z9N-7)g$pU5Tv$6hq4U*G#=e~UU{CZDo$a`{bJ2{PQfH3|y%OpW8f4O!ht$ z4a5H8%ofSoAa`!}S%T!j+)(ncAU$?gx^#E=h>X(nvNJvDzo?z-I8Va0@&m%V`*f?% zCgmVOG3EFyGwjP1E@bvO#0ON_Bi;Y$xL6{=gv*qIlZmR#F<0@zU9`B36Qzul2j*-TvcBocTj!BRzw^vS0I2 z7@)bw&gGczX`g>k900`zLa1V=b=phkI-GzU#bki6N?0MsK`yDZ)8RgdVe@@)_L5n% z|22617PGtpg+x72>{c6)GhjR3sNSWO8ta{84VJxl@7#h?KL_5o{GgxnF$t4SXlsgs zyRe$f@`TkykJ`8N=MTs*-YCfQNo8gFpcV5xLhJwu?9p6!<&J!=^w2PwKdyc=C#0ct zzPJ-AG8cJ2A#xGnjff+=?apkiEDNFjFql1zAS#$`S9!{^L!c92## zgqinTxcOI?;C#a+NJn1T1)U(bTyVM6Pz3lZWCoNvPCg}Bx3LNyc(rsjGc2{Ug zpXYI!ES{HnSWu%ZK<_Y47BlvK$OA=IspLRLs-&DPDty%T0p_VPWe{qkegU$EgTB2F zl7_@(TSA+MMwQ(@9HwxQ(cx#~pQby@tX^OXbufh{!~3~D;p$#$N~x1^+0pk(_7G|f zLQxkTnEMs0aJ2~c@WKlqWlIU_<~28QpyK$lFxs7Dd|Za_$>b0T2A-jaovmP40#^QP z`O+CGScEd(sF@5XID8dfEJ=mW>@5zK8Gdp0zW z$3@s1cLTI!poItH@Vwei9b%J1HGOktYjv2R+4}V0Tz38v8YrOMb-rBP$z<&gD_ovOL z!xjRGINH&K!&zvnSV7N-9?Bsu&q zBzf45*z>7&N3JFcu@fipPG7-o+18jfRHY1e$zyIDTN6z(ePLks>%)t%2h1!!Z)Epk zn8>(x_A__((;=X_h0^?X2^zD?M@#Gbi$(w?8c`IB5+w)vClS2{>VFy{(4saEM%NE| zxRcYI2!^b?d8%)3=>BHl!0)GpIeK8-$S%`4x^8v%ep%dK59gu%1H<%F!qBSprs2n} zb1O(Okg8cxcz%V$G(Yb)0uc_S?vKM0LnIgF?sv{#7W%2LwY@D5kMAJU&;rP`5sDk|*M`Io3K zVUMZFz;$=lE#lIZS2qP7YLf=hOb(9!&AH~$H!w@W>!jrkUkenIi8=N{C^bTYvJ$ot z4KLB~TqIgXD3>*Pt+*yb^_J@#YQYt`XifL={p|By>sC?N2S2H8lH!>n*r7ze#UsS( zURq08{4sa=B0w%sPK-40ktL58*^r^~SI4z$mkRATWT_pC@)om#Kof(3zYi zCHc{ajX<@LFPBbuk#4?mD6JoS7wIyBe6tw zLM6a56cEZSOFfXZ^O?4m5^jC85RVA+-0-MO55uel@9ko|U#Kt&^Y8xqA)2m?G7>w& z$pfP9U}@mX5VILwDn%`*Th1lyKQr{nbXj}wgMuRIsOOrudGcj0FCMR_jV}6TO;4qg z8|Wqqg&9R>pTV9)v-LSjuVJi@{OlAj+cdsn@i#690GZt7z64(A7n3Tf!(*j=d~VM> z(TV_TRotxPHFn{CD#auz_*+N|iKlLI6NtBaVck> z>nXKM<{Oe|HSzfTk#<3P4tDZX)jEG~b8NaVmBbhST#k|55u3O$p0w-A)t+4$weQ~L z*}@&LA>VF?D$zo387B1?D}Z7@3IZt%zJ9yfn)$JZjCr=!(2>#EFX4ogEw}x0FURf+ zwXf8hz0k#hcigz@-h4j%XyrcoQXpRv)}hUb;cL|Lqkdcxf?AHmfHA6$fmol=K(g`3 z+jy;cykHKZWINaaZOeEH|20s&C5^R5hSh;ass#r+ymA8ej4mJS=R5Ia%C89TP$Y;_ zWSR)t^KoXL4fGCFML{|)tKwpK-vd{W^)JcHq}4IO5F!8JE}}n02QAl5Q=n!lrDTV5 zQj+GGB)3$+kSb%0JiRH8S39X_aP}AZSmFdlrE3V1oB^b!bRpUSNzq)Yl9zamsSEN5 zl*A+y(g{So#$8COq`Pi(sDGBt3Oifm43FE-&z=HD>jE7RR}u<-tv- zhWg{dO3yG9js{ZdhVk3yXaFFXwAgE#yr21p2oWQm28Ps2CV5}~enk*ftVL{kEzv)7 z&?AvNNc-%fI$XQA$GFL6xd6{H4g>U4r*2N}R6u2(l-7|0+#-(#$Yaj2l_G7^ebaPw zh%jvGGPh0$s$e${3}4RwZj0AOI7ciVamJli_R{!b2&d< ze%z=a)CiT5$N)ORGFa)eGG0YWP=qP7L2&4S|4tST9HmRoZL@%ds#dbYJ{cj6?>glL z%8ZpGpUoo{-V>^gU+!<4e;LX%c3yw@%?D!lEzne(8rO&}EUWMHSGOLb0 zlPwuSXO;iEr@oeglK*j%|8&X3Utx`g@)>-&uvd}E_{qUgAVA|IA3?(M;Hy=+m9@VAX}#CY#r8RZ(vQ8CWO)`@2)Jx?XJ2%~po z#WqA+@>y0z9CxJ-mkM&j~(vV`(c2< zqjdUsa%08Aq+fJIGh4x+{KeC$YwuI8p%A)@3hZN>xeayR4j|=VBiZ1N(n;SOf+$Sd zGMooCBGvVVT*_zsd~53i_C$2Ph{H`W8`Ao#2d7T6y6H0^0z`GV$a z1(PaPDq0nffXm8C$JcWA_iD?#n%HkB4oO(ebG6hlKTbfJS|O}eJ-0HSc1UjbHr-*s zPV1;`0@vo6``LHxB@XuP%ny}5J5S3@s%&GXN2Mz+FXfxG`7G(D(kV5T9Htx!vdP8X z>@lOGPuSK?xtyPxL6=;BVBrN;;ZwUuS8;g54pF28rEL^W@*hpRaS zOO}89qU{qCuAly-pNh3NPKAo1*vEGFzYP8iTRincIJ;NtP)zPp^o7Rmtlw58WDNPn zdE68z9y_~|y2YkV5~FefgX* znWNs1@g0!UgR+9?Z@NKR@sJmv%QJbVaf{{ljht)C_C0Seg&-GFtp7p>?#2r*5hTxH zHr!Fw@W2236j3taexm4m_2jePqwx44l!|hjd|1DD@&yl>{~I{|pWPbD9`+{qbaIB4 zO3pS=bh7vi^z{Ej|wqZr4Ab zKS}=<&J8q>nE$q89ljHbg~4_eu4_kVLvPp2SR<8sGF7h?HV_y|;Q%fSJ`V%dj68{P zg33%;-Z*d~GTpwc+AT7>k)lA%VL(Ya_byr4xtO{F-Q2ilg78G;q?kIHJ*Z#)F#peQ zxR5ejQFp@xLuhBUwlLP5ppI#s@dWmFIL%XL^_&T$BX+V2`Va=q5sxxBFm^fve}q{x z2L=3l_&E0w(};((1!0`G;tWvFs50CDU_3h)iuhmsBuV#Jf(iih^?a8|*u&fO#6%Uq zIqVgjK*JZ;;F5Yd0RspzYF4E5fJSq`d3O|oJU~==4kO(96G-wLAR`ii@aVW>N1Op_u=%i!S2wTBzbL#d>CO6B|yZqU-K$7h22W(db%am1!-qAx^>|u4$Kvjes`qFDtK77NyaUH{a-e|7~w0HC+LZ<()~=Yo8{wqW6mK zBJWBOJg%Njncpy2ZZ5rs`fC&~4XZb8V0ERx<#@f$cUvp!Q5$G}6)oGXO%>;{`>#G+ zr-K4?#{oZho!VU%bfxA(nXOIDwM;sMeykTUn0nHvYK33#kMnQab$QS%zCPa#=rMXT zrBQ|*?);i`fkpRO2L>Gl*K}FU){;4j9w{;$q8GIfpeamo zBX)RpsK<}Jq>I0?BXp*Z@WWlfvTBFDalZ_{9u$k2R2rApf;xq%^X2Tt9}5zeQc2AT zjfpv?k@24b*RprBz`%=1$R5ee1*T2eF5!wqra6Kea79_)d1z4vIMvCMs%EIx0$dZH z4Qr1^`_h;sl}1%G68Cm4Fu?ikOoA2MAwmE&svLisvCZwJ^Fv%cCzR+9a#$VL5QVOilAEs#Adms4|DstLz#8a z(}&H41xU+k?my8TmQ0Xi0E9+{_Qj{P$~KFz5+kh;JFOS4zA7g!%!Y zqavn4D$oqb5qA&_bmWi^yl)R82EpV*rt^5@L*WO#yomeU%x$jyMDF;D2=7*>XhGi9!wfC-L8ojBiWHE zj^ieX*FcKfvNzbQZx7if!OmE5q~Q==GHK$HM#3sSgbOr|vBVp}B$`OfKhU?s{gsYp z7GE(8a?AewsyY{w*|qpUX54O0gmjedz6cwByx^_0R(+K?-Y^TApvp^0I#Yq88(pIM z9t(ez@Rb~~<*f9^VINjHRvOY*+eXlRw_G9!F&M~=ku}Y)CnnGK6dK8#flXqaT4pp_ zbe3sin_i>WSuD0d3Ij!!t=GWI(MfU$w zfTlhP8$Ne({dYmf!OzcU=IW@b&mV+_NUfToxLn8npYmV_102bnD3?wJgVCCBYyU|f zTn8I8L~sB+V4&5$(S&3$D>)b((JkBmt$|qkm!qa=y8&_LL^inTz8OMHMY!qzIjxpD z%Z|$*m9S@y>D5uXUPtDG!9M&ai=76{tU*1nMRrN%wqQbv2QDHmSE2hI6b(*gDoi)=*PAx$ z2{j2tIJ_oeJH3N9Yb{tquPLR}e6EsY46{onKlyTELk3Bntl;vysI}#@s1DpOxd_ki zPC=QZDW6h*S+`*|@A3KYs&@Uu!Ecc7u~e@(%Apw7@{DP2IaeN>qgyaDP}Ew8{^w+* zvYAb1V_z^5o2+o)DCBCoZUi|@BH^~>5$f&wWKWYt$(e2A^kCv2XM}#$GK$$8fj7Df zWzU*yjd!|QGg2Y+0(%JO2>x&A!obS@pExfz#{U|eXq`K4j-dS3_5yt`B+At9e99Zm zHvge;v0SeyZeDaygq0CMqQRwv=g5`*dF|nW&@Ui?R1`~*?g7{{yuX{-<-*^;VjNs& z^J35bb?kUOkROZIH?AjGKNk_@5CVCWrVJupUO)GE>2ccp-ha|stGM7|xiaD(xqibn z!e$jY`Z{)8bzw6req{7Y3otllg_SYQDnuU$UFw2TXc#(=?D}DCA}|5VDYt`MlnvDsK}DnOO!4w%5voCdoh!7h3)193*MHs zC=Ix~R+UI7>pmht)iq9%)DpA8?Y(pLovf&|I6+*BqDij$^5F#2{MO_BtOn7S} zL7$9_PrHfC?QLdtgOh#p?H1RElZ^V4x)K1P{w$EspQ@Ty+#QD4q;*%T(&^6M5;dygg$<+)gdv|Pk3>CRE9}fZi9L%4I%C=~T+I}?+-WC97)Ww7a z7&pB1qo1=gMW-u$qCV!fwe; zStM2>tisFN0;Dj^k53lU+jDoy=T>nALr1pQ|7CfU7S1=#pS%8=erK2}y@1r0o^z_tL!~2qs4W2$Dc}2cpF7Ny7BZ9ha^jqewzHh*;OSGTPZc(bonk z3<*j~p_f(*Ll``IPH7lI5dspA;BSx}L9WHZ0J6XkWDj9*Cn89{78?WbQh~_AZb@&~ zCq@v~x`*qo1bcF657ltBATY%J>^)pt>R%V`1u{Qqe)_!DIWMCYFKfq%_oOrST&nkB zU#PhqQ`RrCuuP8>+V;}C*<3ch9E)nT!KGPzo~?gugGQANp=Az0Xz0&HvO$F72#ZfRB5w6p^jQB7RIS<~hyDt?26(@0gND-)uE56F4LhAwJNuStLqaBg zc!8?r@iK_T)GA;E5I})V*M`4R6uS5Y1snn}V=U>?v!Ecz{SR-;8>2&5l&NC00V*Y2 z;kn|KNsU3%qsr{bb$r(!uswv%DeiK_KNbLvt<*Ri8ik`OkE6{d71ddOMsU^3i>4|( zJ~lqI>)Q&G&Exsgf|<2W$n_ZWo-!T9`na1*4&qrbK%Op6;34Q>Cac^fxPNXaH8ADx za2>_iU;~g{?mIN_A#H0`#+!vj{ZNii8-~!x3i1ez(lfbfSx{OK;FoLPl8bfd) zM26;ETo6pd9kxg6*IG=om=OVap@#p0vF2Y-MFbQ|y?c=bIrNIZxb)?ed$=`{4yq8m zH`+jZbr_zhktVlqMvE!q8t;)yV`MTuo09*{mmRa>N-`l~K2Q<*CFxoXp8=0@$fJQT zd@Mze@%&MIUu+aNATI#;>Vk!16O74) z55ho%QzMG`molXJ67oi}kmD`dl4v~iCdx8`99fsbXw+2NS&!;eF5e`0y!%8B8(I44 z-zybb@`lB4Llc2d>IAhh24ShFEpQ0z%HQJI5eE7P6qK(3NOAPIy*?)bIj3m69UAuf z%aM_?H1B((nO*Pc6uAA+7f$dRUbD74NU_|a3LayyKkUc(-so;L9E+U3f%@J;9p+HanqX^9W`SR?|OwV?~qr zEowV@^Bg$hEhw<_h)%i}8$Qqzcdth!yIX}4Zsj5}D9;thiy`CVbn9rkmh*(BLvHXk zsK~Mq$2|hyhk+`9Que97Y{AOWAKJLMP^EMhgA8Y+yup+BpMMMCRVEhT%JcPv# zp|m0w7K-0LNRyL{F=rO`DA996Y+IZE@(Rp5b-h?1dG!Hb8;{P^sZ9EJXe#d-pDCF% z%GUumk`gS3=?}Tf-UGYg4_jKm8LW-$k5$)uRWWr1uUeD!Nk_# zYyJIvjqGyAehyk{#Rlm%8Hz$Pl?OOASVrEX2BrC8O^)~$0C5k-f52)#6cUyd8CG0P zz8R~eIBhZ(ni1@|g0%W2!w`N8Bb=XiVr%({(W)AIQ&rW#&adYySz%w&k1=<;Xa?;8 zp54d8p13IG@Pf(fg%=ILUF>!z*Z1+}Z0~K?jLgr+#~o92@#WG%A3W1tj9in077|2e z)qT%(_F)e<&hLlxlKZ%6h#KP0 zT9?oBvXI!C=_^qSglfE!=GEj?edY)~)Q-yV_aOJKWa#g8<3A zsT3_mn{o?Zd-r@~8*_z5=7t9~jm-Cf$SS16+sEGYs+7?8X<7Ey)v8#MNh#Zs$@bXo zh590TbzreeSxB;!@v_XvI#`uW14sAPUFS)%>NY_sA%H7R#y7U+sVuj(@)k8OGfiu? z#9hA^#9onEkFwq1lJD=RbK|4@!*#Qq@+2>7TfJ`2 z#0>C72sTUSz&v8*ttdQNMeS>MSC;lJ&lQ5lGm@L%e!IZUc;qXjj+XjM>|=}SY(5C< zHprGc@W6ZPA$-kmnvL12-WUYRcvj;qJEHmD*Wo;q@&-TZawefIw=&NK7^F%&8SmB`DXnfpc zAedORYDiupeQtbQFsY=7(7U#F!jPfEk~jKt_3-?eIPav%$99pj zYGjz2UwWj8n?HNMici(8XHKoMoP2b7nc3SIWKKL2_eLuN)nsj|$pcq)*rfaM^Z5s$9{JHhAArryD)7sb zJ0n;nL+^wow~~LOhhwRlN*QoKS=N7wCxLC57e7DOPtyN%3C?-l)O9)#Q|RNeMZ4d6oKk$1=IIa{W7-(=n&$>65(8t@!aL5)I` zL}rQD*PkA-2td}<-wB1rMkec;C?qKH@BzR2hx+au1Dk+Q(p2^ulRde?2-0~d43>Zh zi5r(4fo?90@v?ve%5Nluttj7!VAfx5Ydf=c;h$}zice`2oy=h;h4-|w{D;BOq9i;% zUw5vr)AKuy2psP8H81P|&oKW2z%ZEK+@z*nURBuJ*q?h>_pg_y!~OHHIKHokpEM)y zT)18zfaOgcWB`UC#^IkZ@B7K$@4Mb*c(?j9d-Jh6cw?DPFa|Zi*0#l5MpMs}zjkcJ z#(;WkU%V6^LWpGzH*+o)&fK{VJk~{w1;4QI;6m*P~a@b?-0E0!9aj_%92u|0ju^mn>$GGS0p;OFLR_zW@cKorB zCnZh1{v@;#ZfOD#bxe^Gv4=P%3vA<5k^UgxsHKFaZ4CJCMUW%lQav_;(X=?aHV4@9)*=ztH*;%8zaY<^w zDtFCnS(PWTApb3?lg0Ao!GE*&A_v#I0&Sj6zF2Drm8bGTv_WqJFR5%%#qph*|Sx?SqfTV`C>$Yh8+&JMsYgciQ zC_YaV`6RF+@z5~TG^sOLtZu}plR%L_Pxs9*B0R?y59QOa^87i_TFmUz!HjpNezSbM zzgRZWkoJlDJOIZDyWQ#eEy!@-W^38?`&D=3qItiUyM>d>^}u~JX1xWED^ok1Uyfq^ zG0ThV0fFYfcC6lWKds$ccVTkRtjCbSQxxDYJc$s+L}Dxmd{}`#g?$ker1l~pP;x_P zO=V-LXPbSjKfjGPv`DYA#pR7dqY`ac1{)Dg2xq{Q4}i-G3R4iJ-yt6=&rAhi zSGZ>cf{qagGxG~;lUP$kqPmuS&Sr2aSy}tVsj{Cto+t)>XP-tV^k1tr{nuW?(%9mrHX z>MI$#2%6F}KEYU5d1sKWM?LfHV}4`~qvJ1qZ{kE%GBkPkk60Fw5%@Fn);dm9UI}O+ zW}&bDXsF5c*5Z~&PkHaF2L|Dn1}*0+4<6WJL(e2&4FvQDHQh?gTmR06snNySzd`bb zne~hxw)~-Evg*_QCt3O@n5^=ECupGM|l-{ge>rxK8 z%U^(r5G0=Lo%CN!r=~PwS;I93+ItbQCj;~!?n6)ul3@dBr!AuseB&=B9C$GC!(gF3 zOS4Bd?hkwWa4#ikRU@3x*@MjfVoTl~k6JRz|XXDrFBr<6@^{=|I&{0T~f& zPhBc);-;F7@8ugfb!ZP57xVD&Ka`FV3D(PS_QrTd3bEaBAHQS)RBC$_MSHIWj7WP8E6ESIdnBUs9dogfu*lqEnm7z0K0@5TZPAs*)o|$4#kIJ8=F63I4L8*f z+T;8-5B<}$n&1xrW)&>mKEg0R;tx>SmT40Wfz)HrpO^fynvX?kCJVC3K)9zuvHBf; zx1mLTDGa9iJ0qy+GLBel;Y3Q_^o_XkP znnL#A$e%BQIyIfJk>1T@e%#*UD{@n^jZ;5tD4#e%`ia(*Vf*c^mwgm@IHkWzTid)V z-Q=7(OZveB#dYGVW5`Q)P4B0#^}T@F7p1Yn&(!SEFi@@aM~m%KvV>h~pf>vN)2f4u z3bkc&S`-o-_2sP&a@~iJ(LakhCZcVM#-DZcYk>gGA6PxS0iXYXt2q8o#qs}LAI8YS z!v0^AcK?iO|AO=Xs&V(kS3;9K_!6J{D>Us$S}wQOI)*v$k%{N`g#ZcGe_lUf!SLz# z5Qu3uv_9Lz0hrCDU!DEFU1sO5Xp7eM>dYTMM^OgprqxH%2~szw=p~w&*1cVxC+nCy z`}zDP$Qj(93UE6nf*XaYLM}~SUM^0n@M`ONd_uhb$Ju7G+Lpsi8G*R|Eb}sXbo^ke zL|gf}>`Ypnes^BC%IEVb8UEw-Kc=&G-~HYl2yg&t02DR#md%jXSgvn^R$ z%xTr>>%#{JENLLZ|c=RL0bFVkqsFGS%OS=t|d?!RmmCI&F6OxN*f>Gchr zpw1ZtGjsIvhm3!QDo#FoNz^jXO&T@q)~-uoR@Q7)MJAvWkto%Ss z`3Q}cP^yVh(-K&J-K%3OiEz%Xol{w}l37#PX*Ur!NB{n_oDH;h%vK#~Y7La2i^r^P z42ZVk+{ZemCIZ)8i^wjlv@3U!iO;iQD*^o_8QB=~dqJC}SWg-SYh78<61LK)LoACF zw>c0oJlvmPpZ7jJrBhl7IOu{7aZ_F}O^y*I_(AAORWH~~P$mt;WSG`wO-d)c3>X4% zXUU(xlP1EhX9nI%c@vK63?=__8VeZQ9GG8jlu%;?T92ve=zx(ta?c2|EZ4 zfN7V1fbI30+sH;J8UdZDCH^Pl6Y{=rP!T?+7QmBm5nBSwfYs1tYKYu->4tN03W-!X z8P-q+yO2M}!fk&ybejXQRY5P?==B|NNR8USEvNpI);xhoM|~uy2?gnH;IKS-H)gLK0;4WlXdXNeM%@%NBQSe$*~aI zf%X~T=`cf(atf#s=kK-Q_FZMAJA_7B2>7FSjy@{1oLlDA7JVGOg7y*5&y8K1fi|u! z-h?6RZuOmK{*@!+ZgrbV5f%n4E|mTpz^CcV>g#YRbta<#tlsi`)dtdpx*2*cS+@n{ ztm0+fFzeS$S)>fB3CA!J@{cEPx)!UI@XQ{L_89(Kp2@fF_i1YMqCmt~n@}L0)+e1R z{G?nz{qQLGZ9L3Mj}$lw$xQZ4C9m`*XmU~~;aq3IR0gv@N->Hp|N2$=8SYmXdxqL| zP}~>HorDV1)h>Mosf@COYsu$`AKd#tTccExT#Fbl5q8=}6KR@6i9$;|19n+`55Fi3 zIc}7FpKt}Jy>4uTe;|t`4sw9T*}VofvH{RDhgL#@Gx7aomhJE^8_NoGPgTH#q1Jo& zun_8_7lv zmlG^wjsyi+9qMr_CK(MA;Es89c*Bj|uw@GPUC5s}N9H-X^N~eG?WivCXBc)=BxuR@ zMFrASZo}cktZ#f=dNY%0`kc!hfVZCY;dXddflYm({t9|H=RP?|>gfrXVW2;qbQecx z9EAESSZ|(uC+sZb<}#!h+OF9pRO$hZh^aFnxAFJVieV^9=cVzu%pqMN4INDO>=tiK zOdHSLuRaye#9x`?PzC!=S$?TuVkQY`COth=sxeVvqrAjl<($M{!!r9CNI;`(j~fIO zcfe)FnK*We>pvH+@|b^-;86tXzL#ojzch{{l{vpfRWhv!VahROlvucof+T-s7`xw0 zsrcA*N}y!H>`u|DZc{3>at98e(O;v1dQ*&v6C&{_?iNE%crEU6IWNyWfi&9N->35( z5pdS{%a9y(MEtQj-41g>Ym z27Cnr5|6;1)12Xgy?NwLv|v$LWSbCfnydD;n6ElM6sv?#$n>M3IN*$cXc>@oL450f zNZ08^VkEA9M6L@e!H?Et{AWyXpn=I29%(aH~ zx;aU!TS+X3hf#V_|ET}QDJo+wTKzsMNHpX}CFx}+<<~b`CRqh9TyQ}BE0=`fmMu24`~7i#)%bJYvVb8Z zaJqH+95U-DaM))yOrkTF9mW3ZmhnrS)(~kw(;Gf1eB@_0IozR8jX^F>CsaF3ay}H1 zOY+Oc6J;gj?n8-?FMMrF=FXWUE!V1|8=~7-;Wh5A{F2AN=Xdld9~*G)BUPBn3II!L-DcGHN3Zw?hCWax{iE+=3>Wldqy~Mx zB>o4x>uDEcVsZW_zQPR$q;yUCTJBs&7M%N~Gy9@`oEShOx0v5BsbtqMc>y60;6`drycOrvI5k~AJ(y%|oTc8aTZd#Z@2J|5`w zNBL#n&D`qE%IbD8cOYbY+=w{1sz4ZI5UHuxrpK4EcT(%d{j{K4F=VRo)vmo=uiIfE z(&=h!4l9Eg@*7z_usPojIu_l;4Nrklc=H-075>E|7 zD~MkMqAH+UrPI=ylGW`#93bg^tJ;_PZ_Y0FX%G-Qk#f6eb#cDC#k{$zT0q3RgfN6A z)SdFk+yn!31wsHldlD%Y!_X6)XAJ+6LfzzN&ez%A&`vD%j5D;gSX<3LxC?k|+9)G5C!X!-$pi2WYdgv!SPl4!DxVJWInBR}QYRyHKl91`E zgK7jOIA-Jk(9{Dlmv?Vo4VA(aWb|bxt>pR*sZ!(l;3n0SuM8C&gB=R~Yzl zM(z~X28}U1pQM+l+wqaTK)2%4K!Fm@L1K&XwyukUkKlk>nl0wq9C(1PCK!Fj7)haT zYgttWzyX;6!XY(YuH{5X5T&<*<&s*T;A_A(U>G*lkXO!{LTSy(65FhdBQO&Uxs6v_ zsOQFzX;#j!yMU_3Cm=^dD@g}RFV88ykB*A`)!v!9y>LFT>=7qL%uU!1uF3uCPtuH2 z*ZDVnHD(eYcNH!@81ho3jT4&~BBJ@+LG}~#NM;toO~ZT?)^oceqlWkR>lOImAoo(j zL7T5w`fnpLY2HE(t=-0pOQTAVxN=9h#l8jM8N#y7VZRX>=VnfpS<_2O03RTdd%>ha z^aQ7S%mKxvB$O9GMr_E4cl0$);a4q`=1gkt(^Fa$ulO^TsV?c4&zDfT55Ja{O!J89v052DB&&W!JAWMiBcmAELO8hyK3aH5d0Sf5n3 zTM>SXp)*P+@DT6ik_ys@n|5XbsE>aV)l?GFz{WH$DO!Wq&kQc#*68+y?bgF4RN%wgP9l)1FC=*Z%Dc!(G@6ld(;lczx4tTj3MGC1f#} z8xmd6_yAaZH?M@$NZX{2Wa>K$H4hw&zWkzORdlQg2K96VuyvF1b^6Y><`XPNI_LClh%} z%_RH|y(7Sdu#bEl@#DSWpKMdIpV{ML$tdEYbHy1Nri85aa8N4 z6Wk>MwOa!GDGd(3-#VI3S**Pd%xRQ9W4bb+Pc*-Eo)fn5FngD=a_YUm+xpYeVH-MK>bEr|7`O6W{WDtDz*=;E z?W4iR*(;gBhtL|21<)&p0npNpEEmFacr1qCmlq1kmUX>Ny~v}nAyY5 zBQqeTt2%ILXOBL*?D_O&l?IrJRu>#ij@hy+;kNBNu`w?MvM;5Ib~GAwaZOHcFDcuO zi*=$Ly2Ap;t1j+no#m_Q4D|2VnDlq-VGe4{F{(E!YbsIiD@WxjtPzhhX7b9|hpo?U z*Z`>*)dWLKjX0QZZ8gs6W1}}gUOJ&I5khEg)P8jB66R3c>LqLAo+*hP6rgjR{>h zBSxfU<34R;+1{>#Smhwb) z__;j#sq+0?2vbML@;>V9@@S!>wAX3kla7pA;e<%TX$JB(`sB^gYa@;-8Ig*XgI9k2 zE}$(0T)*XguV7B5S4(&C+G-wdOVYj>pbyU_j6SDJd7!owwCT{k4e}hw8Z!YRV&p&n z3#h~m8TcQ7Ec1UV6#f6P<@8$fQfX5Z;de%_V5V8Avm(}u&pa!`7|Ld&82-Rpk_!VE zh}p=Ra#DgT=jV3YOME3_5S<=I=G~t}wrab3d-vu#2i1%WW2R?wVE@Crxuu)TT@->* zaL(EprVYxXk|~6PP};Pp=<3>^fN=`4!0@hvI|Eg0Fq?tXowv5Ku=bkISRO?zYOo_) z=DW#}^ULRH@FkZS(TNDL0Dr?FCmB3!`9Mw%-KrmBAdxLNZx(p5=~2Q#RXPm64wr3U zOyAYo!3|)fss#6?2K|Z>HmS=Qq z#|1^nxB`7yYB*VGN+&H=tpAoRaQ*OkZP z=165wh}$0ng1|aYB1zCBs^I|yYVSaXLQsfaK^4*fdjd98h)Tj1q|t&YN+qP}HYL@HNzAyJg>=h^04;T@BJoW6YWq!GH0>t$3 zX!h~ZSvcSM>)Kqyz6Kd45DKJIai^Of^Z9V4^pFR%waCE#XUWpw^_+=qxtd%BpOoR8Gk>skAH zB@ksqB*T1JO_FFgss4&Bj27$al~~osQY$y{ZtmuFhQgIMZJeOXd8vgp`Jsus>R$7H zyY5uy_x(6I&RnfAx(5wAl7Pe{FCqU%1&|Y7yXfi$PdN)fLc?89v(@+9a$F(wFP?7# z$$d(DMzBpU*FX;i$-5cQvqpP4jSTEz&J_AXd&1^e;h;;B7KiO;gzLX^xtN5z7dm9e zMm)(5|Jkyiy~$YgG;%wdC|bYB+Rx>cSiD{>ik#v>STzpg1_FSQ`D{%Q&;@w}6d}~#+h>k{qp{dbHXL@F1uHEpemiL&RtygBZ zc|x9TzxepTH8g|I+w&*bLLz2-f?mYf4N~Q2oaS!SNG;U{&!=xZ&nNFr$_DMGW9p8a zlszis*~&+3bwfhD9w9{pcR9>(?vtFji0UMAd@u&SwP(9HAFLz9tv!-QG0;C?i!tM>yXe4ePc6rl5g0@ay!!SOG36BjOT2aD==TAxbJD z3NyHEPw!$@d2RPd<+1?Ol#^G^`M|n)V(jJhtdr3~% zE%>X#-UCI$+0601vDgiIAeG?98`H;VnK6^=eP3^`mJUcZitT1{uba^vSvgZx&DYXZqRnscgOKXAJSQ}CR1vRFJBk02A zJ^-kc1(%TZY`}I>d?c#8xHPan*Ybr+}Fk&olg`lFn#O6$;|z(B-TZ z;6N(@#Fo}x;1}7;SPhL8KvQnpd#G!Ui;};NmaoYp$N^Ndl3FSyFt+6ciht8t( z%FWwM{U-_`v6tCNep!CSh7_eJlGa$5vaagDpiEiqiGZ5wGk1-*oGGP)q!pyEq9p<4gmP`fDZgygL4BR_a78^5z^gLY zQx1UXCOv||Kuy7bv<$}dN&(3_06;iU4pOlKiV^pVbkPQqV@s$73hzQ9`J{?dKma!i zZ#vFsLzN)-p^_wo6xts&ag$GV<<*EuOyw%FESL-aK}e`Ry!GM=#8m z03Ubv$$w}D=B|nJSGDL(?_ZC{!|HayV;H0{Tq(MGW-<~+O%pK5L6F(HbdC6ry{Vf< zZ0ItlG@m-xY^`pi2MizQ51q9;RNKV{nDG-p-aqGzFyZ9$Ll)|>?ukSL7>Y8h!h8c& zTt8f*5tMBx&wc322&tF{Fx8TnbWD7UOTSX$~<-!j*S{r#*|PzUoblWK&SKs20zNoHKRi~BXi4CrWj zu*Zt_HklAxf06S=M@Vq!BL^=X|s~ZPp2#?i zm7K#w&R$A3Vw|@z&0Sw6i|IH7jS7Wvg6B{1&P>_^+SKC%m*g^HMMm)td$Y5kmic#D z0ifI;aZ2-rg6+#+fSV#teM|bK>cr)~vAq{~F9G*50o~&osQwJAdxI4Jidi(DZV%d7 zQp)-{M+szW1^TEbV?44Lp$MX3=phFCkVdLSA33%7{Ss3ChdWmNP&+XEe0oYA86tRt zM$?{c9vNL&-WBxNFEo+3y$7#vCdR5nKv}S$pf49CnbADwl>;Qh!we?~It310Np^;! zlbMMX;)5pR0ThG(RCtZvStJ==(IpPZrCd%d31mLVer zEv7;1LlR46NCVaqB`$j$QAGT3A$-p8?+%m>(An#U8T+gMeE3*EJU{}BU=#+Z&GzEbM1EM@8bd<2o zfFKQ4>cxnX$PiN;8aOS++olBvLAJ&8)wo0{nFBdT^2M5@4W`YJVW}q))CG-8Opav| z4h#=#c}5a za=Je1$6-O$j?S$a&92P=HhK=OdZcj$k@3WUr`V)!8%xQ!)6L{FSKQW3%)SwO;K3#F zH|2`~6x5BZ5B|z|2LzM>3#B=TbyP1BZ z+Ae;C5%vh4+y1zzL)XB$`tl*_Sp|_>8*Hv#@|nW#G21K8ZfhzL0Qz7#HC0-?yL;BJ ze+^#9Xw$#&dnRKfDP5YG+If9YwTtEVBkLIq^|w$XeY%z7QU+C_raN44s)~k{+j_Jt zX-dKFv2*-?-)hH^tTe{BHK_trRgktf{*8B{WfNaAacR6eb(q?{MtcvTs zU4Ewd2Ow(UkSl>X(a};m;R4~~0lo?!5ct3uQ7F;AIKrL`cz(MXn>9i=JFoM*);$UB z)oOv?ZfZeS3^8Dr-);5bN8?+WyB;ECB>>1NTgOFm9mnD_9}b0y+JF*-wPJ>|t5fdj zbla3D6uAoZT&s&U-HzR-f@sR9vxVE+MdgtU@FPtch*Zx&VDU)b`iz!XK?$``79Oe4 z!JyV?p+NAfBM0++!e^q?n=){#-7#zIB8)`>{8?`Wm->H63iP}ZujNhIuu*i=$n~DUblu2^jK&8nS&i&n!kV&c`rwOx=2f< zyES2V_ipW4U_3m%U;VFt+kJuP1ZX+|8bW zIR%n|)({b=LD#YxMn1Bat9DCPzu3Cf;I)Z;$FSt7(jm?k_W|xNs>}&;@nDVC{jnd| zTDElsPiW@6GK9*_UKBLtu^_l-1w6UYvtVtl_~dlI%3|~IZUL9ZMHb|MlH^H|ET#Gs zDF#5KIfqJY;+VN=%5c~*acM(^l;z3rV<95p9dFNJlR5legu3FgG*%}idOwX`-y$)g z(G`>tg1MWw-5&$NH?n`6a6>cUvcF$Iu0^YRY2e1U$*%A&M(!6WYT zZ>9}SAbTitC)vRTB%qg71p~Kv2LY~Zy&s&IbG9_ExZUi4Q;ODdnDIJp(w+(CLfzS$ zCZ_=_HsXFj*j+@F;!&*Zgl^obbAXLMkl#&VN9k5xOnudtGxPl!zBuaj(1{N@$7eNw~`=&qP4j!35D>gl%Lghp!++^TUyk z^xsqF7WXdyq@$N)@|6~b$B|_%?#I{dwP=%256U@pg!#fshQ}!I?hqMlAQ_^#Q!IHZ zIL2Nf0yG(zS-F3NVMZYU38*xq>Nq-K&35?(=QwSZR=9C9L5r8<`AA=6hi*^I=DGWn z9C)WZ*b;O|EM7w6dQ-z-zh@fN%c{v{AkMoo<%TiGH}-g(tg$+{pB0J4U<2svwG_Au z^c4JUzP0Enn3+}gK|i0cD7UyiWjq|0mCZQdNq7^f3E1yjFV_JD@XMiAW>!KF!o`Z3 zmsttSHkLk><J^BMCAQ5AGXe`Enlt&8chl)hOs4=Z^ z2}xJHc+YtzIMtZKFZKL&qHJv?46($>vbCf%Ev6%Z5KI=+Zk~zz(eSsw; z1sOgoP^vIydkOGYMMyQ%FW@463Va~^&9|zq?w$_+ZWl>@tN^bxfv`mNR^VRYHd6F7 zvA0cB)~2H6x{py5O6*lQ;)|bf>xCdjZPX`h0+mGPEoM{4x?;l`>wS1oc z@IGMsPfS8i_W!ygXN$q^YxN{xFH^&r{n#H$-PS67L9|O)p6&#f2%=F_EE4id z$=1)k!9?iu14c@q7)D0~31Q~_dVRmd3p34S%J}++(bfW-TyC2jblMM2nO<5$zmAI^Q$@QDI#` z*qm;#OrB36n3eg`g&*={G8VWw)-zD$j35+xtYAO4CY?ng4sRTr6L&-$BTih2p;UTU zV$DD_x-!6iR-$+VbVIC$>P&HzL-)BJx`|4NK zOeQ%qj43>`Y{EGAi|BJGfMY9$HXle{gt1?QHPGlO&UZd@UUBEf+AO!I{lw)gmgfkf zc4DjpHOen)c4ZL;h)I3e{^6{661dTLlkpRd%pvdTy1=jY_~4jMd`vH(a@;bXOc1&bSJ?Oba1aTMl^DprsP=w2JYM&m!T3xuy-T9a&ML&d<>->h*6o&?{x$-@n3e*O-(C$R51I5uV8j zoO?`HVDjYvZ}dd|!%WEHFxBt)i%1-3+XNE#vJHi`?(3h7P4kl!#b`}mNzjA!I>U8juYNMv?G)SlH@7G}-H{o&)^2c;LB(#QEemj1P zI&M9s(N}quPT5T!u4o@Jmo-&q0GbP2yh@baEaifNYJi9Og_@s)=7}*3VDfWN2Y#As z1$Tdd$$onZ#rAb7c&8^;04vnAJ01FZpt zXE1|L!R8g(_#$KY2!(m6`cPef8WaIWJ-KPEw4(=Q;j$8O*T|y`KZ|Nst2e5__+7NZ zj{b>P#jU!fi4zwtv#QeCrn9{u5pCI#>;RBG_XxOHt^VrR&+JL~9=6rV*=E6`g18EN00Bev9j^K7n8 zSJ})+EwcfC#awQQ6}l#uu7;DsrTjz*ro~8?e&HZ6A^yV)wlM!7g~Yl3GoAD>(WT?z z!Z<-7mjvE^ZbulMmZk8wtwt4L`N~}PFV!%=?iFu?Y5CdUG2|3E_;Nik9itwuv1}ii z%IIi>F)0K)74VHDhR79jg)yjD9FejXvdvTegbV`I3|Br=BuAO2Yc!0O>x+9lOaSEy zbwcri2FYL3&{gpZ!{V@mg-hMoi)>|kCb$hH0}_DG(#vdRz}H~|vN{6x(5D$*XtD0b zLR1HN&{+dDG#cJwt_BvWFkOl;T71ed+NvG0@!kRWwCT&u5gt{C)7q%o*wsl7)Sm4s zb_*@=^6-w-JXVCEl z$1TX7(WcJ-LYpet^?PY|2M>00l}wEX;SCrU2DFM5wUxn!crt3=Ec(ErxbbTu6tWMVMN0Pg`J2dL*u0}pnor^AcqHW2j)FLNs z0wsb4L^(pbm`4sg+Hv)WlGwpHBiJ}}R-pazqP=`g2w~#S$Y%95CA#n^+?03hCMtB6 zA?C+p(t^WfBVjh7ik_%~KUXd|mTA#Yc*O2G`f1SBS2M3u|7;2H)@oCK{?%S~?=pED z-u`OnqE=7iSCC>T=;C zLo+qAbGQP;JT*kn@nKSu^5K%~8!tDl0hNBvgG zZj@7mxh;6h7B@CS4J$i-ep^7x$R|ezm&$6b)W)V1w@#_us=dzwb1Lp>wRhzWQmjBM zyrh7mgd0=KfUk62N$t~0rr(cyR+QWLoxKdKf68B=+tPMxT#>RZIA5$>2#Yc%jZ6hz zk-%E_AhfAt_}6jDyvNfMx%eqD7>2=Xz&cEUeE5j9g+b+Jy}-N;z1MSc8<$X1sD~Hrv0cAhZmYg1 z1QIov9a0Z;Fye*p;yW|EL(U-OF+v@nQ1A-ZwjoZr9m*qw>(YV^5zZhNPLdUvhQu>m znzHtXTwA3cu<@O1liU1Si{pX}@x?5?J#yhF-Qttv6{ps=mTV?F;%mFG82HEv>y>t` zrD+Io61FYvT@r7Uu&k}Wp&WWx_xMs)owKd@Xsja%4Q)nkcl3Bz5?*JjvW^y(09_g> zuX$w`3^3!@K#5Pyz1p(5Pq~>8HdB6vgS1lU+h+0+OWcyyKO#Ic$yK$p1tbuiY zcD#ho+)Tm@*b9xk58aXPb5okNXkH0CoGBt=WTwEH_y`_2la^~Y5g`oHNJK9{DcDn4 zLQr6XM5jqJAzU)p}u;*++c@V5uLO+yH!G0N|uWxsghIU`T&&EuhH3Y@QKu1GDH$jr{a4fu3Q`^(qAkd9vlOV!6c6NyaX8 zrpU2D6&A(-UkSjPPec3Y4fBlSod1eyb#!iBe#9!+ttv7;IcB*v*9-=W3khZlyZBno z^K3*1M^v>34D~{(OF~PD!JsC-riC>*`X_d51=7#>G;5${*6w$FI_g(Z>H8n9UKUVp za%%WL`rl-bNfOw=XNu~kR-Q}`PPm;igBC_d=sydCmz?#D>vGx~@U*Knaax;M4y^&z zn0EW`26MgbJtRp|5c%er#!aL7yge) zKw^JS3jOqrM180qXqZWS6IEuYqv__#Ie&4?>yPQ@RG}lElR_RNEXU1Is;Y$km}-# zAg!|vaVmQ9*H0>52Y_Z&RS%l-hXxkz)l*K@rL{wA8J>594ZCui&cwttdx|H0yJXl# zF!D!t{^7BARb9Vlxym4k<3hvXtH)ppVbUf)niwm0m3>$~QT}96zoz%=p&DUaNwP>4 z0cE8teWtBGF}J*crbex#Jp;NRxJK1_C$x~5YOqSTWpD2tFz zpZJ|!wHd8w{Nr3Y>Qa}bS|eTl6Q0qaEW5J6T&UAQn`FF*xmeP(a8K1LycE;}MZT8B z5~zCeTF9lMbZ$#}iur}Yh=tty>`fcm_MtBs=l}!oUIcX{vzX}6l97MRwv(+{l_Sj0m=E=86GDI7TfNwi zT^-qj*@ynLzvMbLeB8Cs-B#hnEOCuQ?nevZ^zi2Ow@E%uq|HJlHHuzl1ziZZ)ij8{YM_};H~(9=MnMXk zw2_saa#!E&j%)bBwWkuVJl4*%28h@CV*l-7IsI=x5H^*&A5nRW3B$o3Wx#FqgatDbKU<}+(Y+SpGK0*-;4+dOg#^P zc{ZwQS;Fnt1QA>pPCcG^jxIy8n#%G8I;y=`v(W;|P2F!7X6T}0zvysO7S9}Kq*$Ng zN(*OlCToiw6do8pP47ksm^ziFoFA8ylh-2_&B^O75UR4|;h9{O%FB~jB99o-FLdYc z5ksuvNg8}D(t*GyLw{7Mw1S~uehSF-3hO=??1wi2hEDJRMyaZ3RM~LvY8hXPA74xQ z2*Z0+7Pzt=A>`@{lq_jtG8U^$|d}4$s@SO^moLZJjqJ6KqXG>gV{78 zKh&UfIG+vNr86H^*}x)YwLPELz(I#RiB6bp-*`Wq#*LN-)3*uiI~*8|kk_E%aEuIe z9HOiS1?4#WACNAxv?}zO#eH;vK|r-o<&yM5lwKE>vl<6_v?zfgmm7~PaKBHoEv{Ur zx6+tWk8JZ_v|9}yB?E}Ml-`ayQ zV~VjFTM9w?vD`P8WFjlGl2bU+*bR#MsgAY~)!;%-^w3DRI?yAgh0V?pGD~(f&o{ATl^)5sn9$ECu0cCY*Nalva?OL~ zGNZP)8?ppy&>o-JN>EI3m>jLnBpxd!y0pVvJU2Q~r%>2(8Z z5%9l*Eb~rWDoJ2amaF%+Z!#$IoyEo%XWQ!vW z2{&5r4+$SnkvM8x$VvjpCX+Td&$RrLl2|;z;L1VE^?uUu`>Nz4{TzgE6qhzX!e_6HnAi&ObXzc2|g*y3MhcwyS9 z2=1?nvx6xwM?BA78k z$mv6%Dp5&hhxy`Un7BC+KS0u?XXekJz;y{L^2=eB`tfV8)=#JX+qQAX?#O>=v0*tj zU7Ws8t!Ve$_wR&0*67FYnXlqMEh#_0IMoB+Sb5RU<pA5S#6i{^4`8cUNn(r(3&c_xNtc=6x1>`_^Tp z;d`dH`2hbDudDBoY*Lx%@EZA)c*-gP zj{{jR{vMrg-5ev1Vz|s&l;UuwO+VY-c~Zf2UgtU1$D`xXckVIz9{{l-XR808rT$|~ zo{i(b25(PmY1?g$V0y3C61+D>x|2KQ<|7sgEOba9G`SEHz&qek(3&9bL{1$`wfK6^ z>PXPFH|mTl`S*mS;?7LD@t%H&v3$hMU*V&(==pYay?$3GU?z%4OgBzuMllN0w5I1L zFyuE*n!Jq4%%Vp*u>S4bm_ZMiZgFXT^W!cw^{u?A)NS6r8aTXFb?V$^|FV;2f0&)r z@A0Mn?dTl0nAzfD(YCLuaM##hZGbFH;=>ts6taow_nGTl5{W{THsL<9?AdcwJFuHE z?Y!RDyfZDCXnXqlxc8mp;@;a0 zImnStUzFFld#W~dP~elNJsRTjTD3lci&A;{RbehguF!&zw5Ib1nk+2A1EHwhr4fVq zqbXKdCA!lq+>$AjYc8se=hg*bDakD4C?o_?Az^}Kza1)&&30~hm!6(am%&SdIfbzj zf|X`*BLQc}zPso3P(Fk9{*WG%6lv#fFSLd+d*!B4^<{Iob5AVr_`RGXUJPc6eT%CL zmJEI9>#xKBc?7rtzs2KBvzZ+1esM%_aj;KWW+@5kXSmT=Q&c3|RDy zAnen7Fhou9(?hA){Y2p#Ghe2dDgKF1l>8?yvIgTl(y4VxR8VHIwe! zHu|&Z5vTn?`_o+S42vY_rfs_zES(kQH>ZR&!3d4A^H-NfsQ5Y)?N7@aOmhzx(t zV`3?tjzlVFO5nEx99^~BLhFK89bCD?@CVvom=p{L|J_oqmPcz8IEGn37JvRBaX9{z zCZt1TQ<4=;AkCOGB!NZ0Iw?r9Ck)O16Z)W?8Lx#Z ztbh~6U5wT$?xRM_d7u$FS_Vp-gn4d4A;O-%3XLuDK!8q3gt#71hi1iBf)qdsrVsf0 zRc|N>c|Z(S{9H7 z%a*QGkpr^W&lQ2ZBD&#-Fz!ul>&G(F7SV89CY<+IEx2DMlr1E{AKZ{1XP^_%=4*u1 z?yV`e$^$OC*62;BzHsz^PQ_-!miUA~7gyJbzlIJ(SAd zaB~Xw9-LEai%WvJC2%_KL26in;j=lyxE6GG;ilfBb#NWq=XD@B8F8V3+?Ru;>%%*% zE8$ynDCt~Vmt~Pf+oBJ4mbGJR;r8`Gr$$JEw7H%AKPq6fw7~9YTmj1>?b|EZM8A$n zTzex5;J!}e0X=HVD$Y3(6WW|{fXxSu+1_oi)x7Rdc5K|i(ONPZ*O{8T7>_7v z2F}?Sq0NGr`D}<|2oD>MY8ir)8e3JnBQw1@jzmr7+67XAjK1U*J5<~C&;{Xj@7c(z z>WG4X$NFpVT8#~Z=@}u@h^u%q1mMZ$E*Mnkc!O13U6p6!rJ!b^d99RV<~r0}ki`g| z@k(LEaEl(8S-~p^e>xrCg+O?T9h{XFN!a+tu!T7h!@3D88ZaO>8_J3K^~Oh(D`by{-EuB z`CEq20q-hdT`7u^M~2U8!%03U>Qi1(3~^H*X8^5_-%h(-SWkW|nxDd(v$c(XENJY?N7*Cx8ITa#m4Tv3Snp`?`7Q@#+#iFyeZV zBw=RGuohMjD!%&4nIr*%5Nba|y-+@YH}ogjMvQt=WlN`bri;tgnd*?wdYwXDv~Gd^ z``F0?r@I7=)9%ZK4;cdlU#^SQ$MDBPjPIgk0ZwU21v>I0jw`H#og8&^_BHI>V$7|) ziU!ga&RK!n*}#kYPSkl$&P5Ge{7((DGiFr;Q~~9x4TQ%c_?AOYv}%+L%Nz(RAoq5) zn0<{}zH9?@@AlHBOWUU2^~5`06Kgr&U4A?)%>q7hqL={UR3|{ifmDyKu=nmTq=FBG zPWZht4lt(RQ~J5cj-qKC`L>X5&Qm4Ze#gz6bru>;LMqm?O@cLcnWRY$04rk!-Qx~0 zCg%%Xc|SCZl+8JdN01d!Yqp!Bx``ELw-twIjSU&9V+N|SvUzO&(-X>CFpz}TBub56 z05y+hoZ&xj5m}*sx*bGe5rDyo3sVR^izslJ*WS0}OWVo7LBU1s#CJCh>$Yf_3xdy~ z1?4xBcP&EiTWul{mWuc5p~$)%pu0EN_4EhyI~l%!MdG3UWi&b>XmJQmCo&c zTN2S2*#I!=&a^Dchr;INfxQ0tuv=K=e-f>K7&YRw(LwfHyi29$Sa9=VzHyv8ddSSH z4F#-66*w+7QpTPt%=rXITiM+L5O~2}ZM3}kvUqfDgBjoU`zI*= z*8vRGt8<#grw`SL4NNT@pmbFo}0Qvp3fZ-Ea-ysA&9ew`mTG)B+E*(F_4*K)yk zX-tf^=@$|fx*d)rj)}TF&Sx{m3cbB%LOUqW`U_+tyc5?&uukSI_zF-mSmV$uP&%Wn z2z>1ObWK%p%igP0ctI?iEVWBLoO0yaF&X#_e}~Bo%?U}!r+A8`a1_4EzngXzo_=a=IC^E>M|W4@JP)*y(M`ez@Vi zAZO#vc*Q#)nPVbbX1T#_N`bxuJow{5vww?6&Jr@wop7Yn)JCn(eNTCIBQA+ssIuMX zs=3X0=t96i`PaG;7M+s|SNs9XxRDu=>8J?+byi-nZi40VJFQ3LK1gOIV*q@EnohGD zvZ)EL3LDqkNJ^=i?wbMV5f<_0{wlr3k{WL`hTQzfz+F_`J&qS*QbCrjuCpvQE?9cE zR!r!oy^3tgG8=*GwkAnpEJ@U3UYiH{sEw9qLxJYCDBpx?s}sY>17;CqlL=q0$9S@B z1*~kV+2}99YNQUE{_|X-M8EM}-HX1FXet(%f&mkR`~fwL1t|{KcBEg(_V0(p9|kNWe+yM zL$Xk;Gc=E2?d-e#+fG>D#rF8zJE=#yBLkt}yENf&=5mqaFJ8x5?{iUt5fw`GDrXnBrMT!`m+> z%XUrf(YHPn6!AjnrFD+l_M#-u{C_EY+TS=UTla#nw9T)>;(2b~oa7v4Akg97rKt}Z z>>4(lj4%e73~R%Ls^giuNuv}jGD&-tq)I_en(IY0*Q?fUQb}7QS2;BScEWpZ3T=FR%rPQxmOzylfLP(oy3FW^mnkF2QkdYLlH)Ps5Qgs^e-deHb53nuy`T5JEH~h^ z$7@t;eaZ4sMT3&)D(e%laOyMkc2VrR!fF=h1zB(-v+P(?oq?EpA+ZEQGz;l~as-PU zX5T6HL8gGmcxb$zP`!JtUG30F6Am4WT6XHbiMQ{)R*WQ4f}(n%7*VT>@9)OklUIfg z@_idMdV8&@{1WTh^l%$Fq==ec7Z*HAM$DI?7Td4QAFtWh#@9f-F=;uf+1;eAyJJ>t zDwl8WOn@cI;EDw}%DDO(6ayC{o%AMuxF%*drsAKozJgS+MZm^Q34$?X(;OAFkVz93 z=LV&atDoB~%dBApBdnw+tuq^Y1jj0zD7<3c`C)Sg(+%Gr1KeT(nkv9e_^wWVwO-my2*ODzj2tHqImM$C4Kmmee@OfFvZgO>3ec%ne7HF;EOq&VHE*!b0CN zb!bSIWkLmGN~+}5xi8-$xhcgc&JONAUNH3y{3`d;g#^OC37Xwk-BUYJdAd+-xiN|3U=+D*h_@J-3pqYRu-a#o79 z;nIRtMqw%fI7PAMf`Ug%N4XlJv|_8=Ag(TSWxg#A0k}xoDhlIb*`xO~^60j| z%~Gu%<13Be0K7|sK8&vyM8)98=H95Ln5|rss2MH{Hq9R7&Dz(Zd;2>h@&}vMBp;;r zf$|gzt)+mki2+waYnl0uE;Mk&e^pu8WP-~iCH>P`E7yUmy0Vl85w&X5G1sIxW0G0- z7sp9S)2>C0H?c8i7uOvcHfP$-9_gIdK$@3a6VnJeI z`U~f7+q?ra7X+brEae4gVauM+i`caWQGx+sx6_3-0HrtdoyvA0@zeuE9gGS)Hdu{$ zi|Mk=jhJH{#Gg=V9PAT1>WpfJb6{EdPpPj_s8QR1qD!cOdCN)IYDlWJ$`gQbReeLBDhCDlxSYKlnAy7pb#$jDoY``Y6m~Ap`%7x%ioK%0g6`?pZS0$tOVM*h-%ec76qA?q zTe)$}nlnhSQ7IvW2RY|Vj6u>y0yZ&4vtGh zVUoM4 za{ga>>;Kj2$HDUdxB4-#{MQW5Z7tbYY<8sXOZB_9zxiYD2JwD~1mk_3fJl8|-fOyp zp_<|nQO)9=#+VY{Up12Ozn6ozf~K+rVP()%l$vl$#0pTn z{;I%mt;#gd;#0M8B{ZknE7sN;r z25BUr1#mJHC{CgWR?@@XG}h(WG@%PPlvSflrsU=QYc9mJY4*AT$_yy#L^R_x!qs)4 zl`%jW4JVI%XO?96^>A5pG5R^nF8Tf1D#?o92+z!t6U;=A!4zyX+h7dKN&6*&Om10!!xjdRh%_7zxe{ zI3Z5vA~JEEcVHeFZCk;-k^PR67^s(R?TQ-Q?~Urc9!GuE4d1S(r#%}rdcGfSW!=6G zLo;|;=(Lg6bD{bjtP`@7>p3fIurp{~kGwsk`PYG%UHepzc?wmBf4|9JWaIvZR z)){mMpV;;Je7x9ct+VYJBYGH3AqOuC4GU+GLgqz6rlW%NYwXyzN4tZjjZ1FIQ*Aw3 zE`_hFZ;fs8GJUr4E_>jOZMi+lpzm70VlF3c05t$^ZTrev=z(L7D>t7%R;ej|Po&!o zGs#}L%f1hHpw?RZi;$sB*#*A2Fnz>4TH(FH`t164{P1~hFC4HvD_y3?uj$qP!Q;xd zT9kObqT*ZuGwJE*8Aj>1C_%ohI$_qkVY!OS3TdT%zD9fD6&cmSX4Syf5MvhCz>C6G z0}rMwg*f3gw_U~e)!p@3`+T81$sgv$CO|_a^XJ8=Y;&4V%UYrpcTWaq%hSby*!3R9 z69h8ezgAP7nJ=0`4pEP~<3ir_Z1WD)c5T}(ZMlsD``)VmXD$$M?b;?znc{|iC*#%y zXq&uUg*Sk4O}BSoGYa)vu)^{Veb;#>iKDoPC$7PpOk8vtbPeQg-E8BwT5NY+l_f~Z zhGAU(3qBJq04G}O)7(V1U7GasM=+Px@ta533O9f1Qvn2V*aX&Y=3_>HsOSfrHa-qJ ztB*9;iVJ3CY6cf*iUi*OY%z|~oZ>{g8E23rDWYc%$RZSk)pQ(^7v{oQIEs@B^`ADh z!b(l!AumLUe4O`<}|MBs@0}-@=&zbhT6N*Tl;#gd7R9MI>CVMz2Swdb_rVRil z46hI!2(jOPe$F*KT%8qK0EaDn`KL$6j<3p&NZcnzf{Q-q)(?VW9lDp2g@mSG1 z<5od@KnVh1XqLsOo=IM#TBLU4_Xi_Jn1hSC{HIV&MT)DKgBy*+Pdo;;j-PBw>?PwX zWZ#|@_pJwNU~ECHun|`cFJW}cu!Ov#C;WtlG6+Xw;8Y zCab%TUkr;&dah|Z__ZGcR~oh0ATT!OHi*#qRg%+?6VQX?qMxns^0OD4=t0AgyWTy# zV~1ux) zMEIcm^Y~FeBR6z185@OPn-z&LktRQN;W#d8&b<6l6w7n@`A2<4rqoz{v-}_w)0UN&yvG4NSUqk237nb=I z@b2rXQg3bkupi{9iUhy_sTj-ls0@JP0M0dzI9gfodq0y%N$>wDIG7m!yWsc_)SHpz z|C_?NtSRF}+=}>5P)re)6Isb%#MrfUg^~QL@fgEvtxUfJP$_giMILDuTs`-`0@E{L z!7$(_s>eDJK^kJ6-K=ic2JA0?MymaG>^-0UYtZ$4iB3eaKW-_xcql1c!1`>>RAy0!qPp*X@}WtfkS&bJ5ReweBvn3#W1Ra7B(Z29Kk6W_xnhOf7p zUFmM6*5QIye1-L>WAmajs&#m210pH-``iJTDvvnNe624>0z-g-0w1;t426_@1T_Wc zApXYm50t~gruO_+VRc~ZSpa}^MH1PrxcV;ay41YmdiYq7B(B#%SL}NyR zyG0h~QZ%=;hk^`rPjNvi%Vh^eKAJCzYivf+kF|*ijmc;(D&z@JLvqq1fOrxF_h_t^ z200fmO{A&-79-R{x*g+$+vfN3Nz}2VWV?GSitWADTMgRp_Lb`;v-CrhVGPho`6TgJ zYO0IBmy}!W%BN{L>dHnD{-u$olUo}f8i9$zq{p8c-AL))=$+#(|3@O1xtf@&L_K+- zejG{~0lRp!5g;;v08hZAdklkgw0Kf(CCRuqPz!PW%Y2%$<`EQj4T$4q)WUCli;kHKh(iE2VeN>4fApJ|}XUhSG2f4Jefy!I5+g0SD9aY#6xmu-=*e zxl*tIzN(IlRDoQR=28&3U47m_Id>);Zln+ln^hPujuZFV)5$YYDySFBL>VW`F)s2y zYY0d&0MK`bX5hMpXstE)92{DPSe+N~#fnFHt^d~u7a_XvPJoyw4HmIV>fqAGLm|FY zx9C$PbXq4ybI$Sd#y%&1=HB&!6NR#GFo?O-#=~C`Upr$EC%Vvnm!B@8ZoHyj`l$xS z9*AAkD$Q>#2Y9Yi2>{Om1}mvZfW8k~2BanpiG>`{BAC7cR!THLyYxm2CX!d#ICdka zN|M5kD!=bSumDKFnus4^NYxkIv1_c-Nw0>goa(D<@C=4 zk@hzK)BNe&+TOd1_hO;1<@a;i>UN&rnRx5YIr;FskS0Zrt}YB&|CYSb-w>c7h_z^yOle7naN&hsdxHjh-nqbro zNnIc5f{hJ|5K~@xQ5t5nU53YJtyuaoshBzZ@nWD9%t+X#&4Bc1yJVFvav<+8C;n*@ z(@VSL9!D>oPew+W+TvI>0Bnjyp9F-E;Ms+X$Y`Y*7Os5|;-c}RJ@YR5>AQcUNvWx* za&B&Nr;a7VRm!0%{_I+1OD>^99G+MxWwK>E}?-EfnZgD1S(wi@>cu*P(Fh0Cp76WMKX%c{B9)TUfB?QYb6mSWo zHudaP%uWP_vwAHSRtQ2T0E#CjG45LuQE;q2X9xx&f0RvjKWXsU6-!W1m^E2kR%sb| zniF@C+-N_LJGQ(bt^eAPq@0iIO_qq&c>yq(d5gGdD)>r0QAn*a=wHR2P&ZT|jtme3 zHY`aoT3P#RH+k!3|BfOV)|(O_q_05KwIqLVs2`!E3?Y&mXa6tapF+bBD*pX+B^G`g zK=&2^ZY==a`)*|ZnXp!@c-*slmdLQr>mMH?sO#n!&9M_|BoCzdpo==FFs<|?t9omC6!l?^-dyDMo$DSt-w_WTi3wiu{HZK-P^EK4{+W7u%d#M#_TdX#m;vIZ%`yA1^-}okWfRQa_mTd zy$A)nlI3lDf(gKit4QDQ4hc4JH!M-~(~u3LF9bv>Wboh76B30a&YvRu#_6-HFXfRi zEi6gnj0WwCJc#onBFhN@0*%8e_tmx1NebtbsNg`O=}~_!*DayQq*84sjjTE)-8Kzf zjyFReyS9#`wDu|b1@=7oT{65P9JOO2RZz5x>OhRjAxGFn#Lx!| z`Qjj)hae>|=EDQr6dB^B$R-Qj@a-8x>}rvs*`+_5le7a_DQs#*9$wB~`Ey^)W5^&6 zKkj|wFl*w$`Y;s}Jz2ol_g137L99DT8oVg+D1 zK#&O93@gGUxa9q@LX$r4~dH#GQ4SUO?ty2I%1GC!9yA= z9>PRO<01I(j|6hhkW^3Q0Mb4)GK^thaA^*cVr?CNfSDrsx>-YpW67vTU3W8&aU8@q7Vpsx+(LNfajLo<3&2IC2dE?qVXJLR zuiYa#0w19h0hk;Nr!sUggH(V4HTAhen1easfWn45aS^iQ^>^)x$_y%7`a)PD2%O9) zub){Cn!aPZs1O?paDs3yht16Y-NW#raG_>rpTQ*6Bi5mhP1qHpuk-J($O*7g1Uu7H z4T^S3K-2n6wP1NAO*qM2$@K1|nNayQK{2lM2sa4y@>^}$5qo&v1edw+Ri&4mC| zRm_F}rn;+6NyFTpi-3$N+GJ>XUm~OLugh2vHV^1Kuaj{RTH(@PD-K{>%OtC5YM1n+ zvC9ck46(@?09&F6(deIUs&+e!9f)`K*#w*r@a@zBHf>D-ks>T5{|r-Fu<&^N(%m7s zWfTzM)Ec(;2S0zQ(t6>!zL`Y2aa61_Fj6?qt(cTZpEVsW8dFn&iCHzr0G8dd`7VAp#SU2!|OEGCD?9~>m+ zpyswqDDt&y?n5uJ#S7%wtkm*>81YzpD}>_>Sz0N@j^)E}@F6DrdcJrIWXC?^2U&G; z+extiktyr{Zsd#XQuNtb;MKwuK5=6FmHX?%c?|Oqg!Iar0|hr~H`Lbsn!~d3Hz9nf zS8R!Z7{v5chIf+f-7?Yc^Yd~B6L+g1Pa!z!$?Zr8z9d>ddJ(;Fxgz+HWAS|U-I!nH zW0U}A#RmIof6r!N9_W3*YvAp2E9d_DbaimQ+|G}6Zi{Rqx=3aFJkqt+ntQH=sK02IZnw+x^vdud7LH@=AJMU?lj7(|X^!Tlc8v&F(?YSc=l8 zofB3Kx4>zc5XG>ny~o>wHII?U57;MJA`G~AVVWOdt{Ye8DrRKGuikd^_5H+DCq?yO zVzT;lcxcyRDI-I&PK#nxHq&nscV|cRpq72w(PiG@*@IcgO>`azwhVcRugrB z>7QT^CpB-ZPK^l+qj1B8Y>Dt*X~=NZ&m%?ib4l_W4Ve@EyYJVym2TB;06A26RQrK$ zraXL7iZ^5yWvW;5f*EXvG}MER{9)V1@Jj*DT$lnlEtYAOxvq+pos`AYAP2Und1K^? zpU7yWHM=K&DmFFpVap6Z!OQm#WA~qfgX?i~CDbGl--r6KS~(aNB2x}hkco<*K3-z} zBY^?^q3?$NDp{N-A-Y*-A&Mb$`S(oduzH`=JqQwdH~6vWKPh$6vkza1L_u>sm4e94EogzfP76VW$$8?Gz=$#;t$cHZ|(AJIRi6>cZI!sd4Eh zD&?OOre9l`U5sldZ9oShu0H-cGhk`8=EEs754`Uvm%suLSY#S!Xn|C{=7U1)aT2^{ zsZIU?yzX@ue8PiO-%|HvO>cu8E3bY?X8bHUubiJSecm>AQc{|Dy^)71h$RCmzY$k z0en66OB_bJO7G^-?CQMt9u`s-)y{AyL}m)}MW5{E3^3NV4)|9Ca0-WeDvMiM8UT%q z?B*APv*Qk6D0;hk8sGs208mdW9B^uDE6e%U5gcMO zvr|12iwoc=CP4M%1s_u;<{F?Pwq)gmzxEeWVAu>4g!7)B(bL_X9%HkUk-bA5N`4WL zyDC5x0M$v&3Ej+%yvxmb+imG%#TV31HYg;rv6v|-R_sR zj80Xye+^8{imRW4@fX#USmrS9lrZk~^)#-3O`YE|x#_i`?Z>n4gNM#-z z>AzCrUukbaLAh~Bg~)veL80xr%^~lj@Kte@_5aRvc3^sQ`Y1R2OQddU>Yv_BfuL__ zYjF+mN&XSGwsm0ld4v_wgDi5B$TH8hAK*lmT4!1Ji+r%$0OLivIX}>hPO3`P)nJOEvL(nfJRJNwRfy z^;2B>vAOpvW@l|@bNXx-6*ukz>}ws+bvR1P{-viR^VqAVHZ(tT^?OkiFoNGnaHVhY zy34BBDXH$2kx8KeEK~i1m)3iH;YX8^-5k`OSXlY2rv~kxlOA#Yd&b)`x%6`QVgLPi z+^>9!FZI+SEs?ztc0rx;C1tSf%?Z`@HWvOe=CxG@-g#&7-a-t+7JFT>lPg@d?$u>`c0o8P-P zsq3?o2ly~}FQfa!C%G>^+ThXrROpX>%vV7GbA$KzaQHY|KY)B^oxcIp_<&viwimBIO21*% zt?iS${Xb?F(%ahFyt=r*9V@)77kqDew-ioJa!yKX#U5fxI|!K@@h@Sw1MYZFUWZ>y zM_w5gOHaH~w0zq+2>FU-Rz0A0ZCj9~FfPQkH{nX#P&CNhA6ZRHLLtp$6sdmRwG1Ts742w7l&mBodp5;1tgTguaPBnDJ>F|WjK{B|AyG% z-n~gm=4F(DT8e%)M%}HRr+bpe*csxm!aGg%xAE-b@@=?^rSgqV5|bE(+$R@pm7+k$ zyDXT1icFm|EOYZYq!6zD{Sd_8?s?@7J@E3xw$G&BHO%YY;gqAxB1cbMcx#MM{5Dv4 zzg;buajzuY4!u2V#mFU3faPi%bR!F(wyTne$x0)1UZ7Sd3h$+AXah4@VEubCcdc{3 z+|Nv&k~`HT8*yLy0fK0z+sNsg23_+fH$SK0n^i3$F*0B=H^Nxl4T?SsXAu1ht!dIF zb^6eKXt5~vQuR-2QK40?Z6CY&7JXv}KK*Pe)V99cAnRZDuy*j|!^cvBg(-;Yr+B85 z7GagZ8^@LnMYt)9+2JpfLtP#bT+f=@k3o%)BbNqKg5)RCov$l&0i}td}-L7d0Fwozm2L71z+nG5>#->oEIaa3U&AL7|8@Kgh?}FSDPusb3 zNA!uAdT*?Vg@MQXw$Zq)k!$(T%Vd;MBtx04#3C#kkvPGdmIR?bQ!oc_z1v9HZ0}3y z9qSPMyT}INXl*%m67)HxF%!js$t>K*Kp+y-bx;lUzQtN0ye?)XuYK1m`)qq8BnYC6 zPPwW4ir^tTAN>$&X4q2q_(mg9_jzq@&HHKrHP;K&Hu-77g?F~V4m?!-w#~v4dK6A@ zQBrm#6As+V-F=!%wLLFIF7wctMkh5LmmabOMVm zTu7Qx3s8Yp(ly_#*+Uwr>BEopTjeYYc4khMV;$ktgO;yTNvH|MFiISrLQS9JviMo< zu<%VQnr$3cb~tIWExoJfO*-0hS&THPsHdiJc6%3#prv7AiOY_`e$2Gdz3D9?Zt3u43lo*ngUITu`@93s7iDOp8y=|zR0B?xkgZ| zLYNcodDSkdP1@d)wOQ)ufE{hHn>^b+Rc2mL%Dlh1Wzw$TjRG+JBl)5kL(n=@Fz~)A zRr9X_1w3?Jrz@&^bDWjkUgs#7Ah^?yUQZDcQCh78y7y`2_z^(>9Zya%Xsgt>dK7eC z10@iEHV}!yOn2|!-X*Rk->1ki!8;WNiZZ5qd`E_o90UzLu|S``i01*-7jl-za2pyk zf$+agGE1u^Ibrr19p6JD9y^qE_2U#NNt>o18`#jxc>L>|;xPw6n;qNixLRq%9L##a zs>$#*hq)A<@le>sGXMbuc%&OG!x@j`c0Y$MU(Kz?S~xWMiEj+zPa>;M&QpyW`C3cq zO##Z&9VvkCBOd}z0rv}@aVL#=Rr3$>uDWy&3sgIuy9uPX?q-5CiYAHj`?KZ&9_1N* z6E#VvqmK=!Uf?$hCr{)bb)Vf^X3>l~N5b@T6T3bTJa^#y*s|>AE4=S4wKlg0@je|i z0@+by`QPNI&ZLM|0hin3Nd=FKsIT_05ga@QRGav*7BS1YtO>mi0tf>C3-TD!&SXtp-N2?251${>dtV%emhz*8IYciv}4m&&PMZPD>p%b{XW zG!zRpb)oCkx@6S(7_R$bwib*kExcbXY6CpzlR4w!7$Fv~>BSn6G1qoP#bZd_4Wd-r zU_h^aJfTLd5fRRg*k&mVRAe)XX7h|6GB)0HLbH*jJgI=IA@u`y)S*WYm%QLaKy~ZX zY7gp0NFI@gU!q$Nsapi~Q;1wrX1WWOgT=#xF>mFm<4 zsuP~0hA$17iiULMBeVwXUI_(Syq2Lu&b9vg+=9Q19{^7;0`KW*uDg9ZsQDEZ$kzPT zy4Q|k`mWl6-u>k>ydSx*_vAIA#T4s4RF-x6g5Y1dG`i29M&1r6mwIFDWvmqnS07~WMsx0rWM;2JMNTHweyw!Y|^5&h6Y^I4)O+4HnT_wrkjW}8kZH7c_~*nEE$ zZFXb#LwF~D0WP?#A`K(rsATTpSv)co@W?In`zqN?uU#y-4y|y4E>I&kmM`XLQlkj) z+-IvOGd~e&1ngF8jCcr<6pxUoh2gvBWPct}DbSs8hvRdza(I+h1(sDZFh%Vp*V_h= z3XBl#yRzE-E$l&g6WfB$`}>j$T}rxA&i67Jy0=)IuJG`A%(<31c+oB|_;NydI&DeN ze7|U6qVKm>w1-#vU6tAhC$?W66O>A*O<6Zq*s}BiZTV-vTk=VqjHGGx@C)oib(@N92tX|*z_A6vLJbP!d zqidL4t4#eZu?U-E_7$3tG@%?mAy@000V~CzUd<5N$)s@c8q_^Iu^#QC4)bV|sM#5Y z&8Pwb6QT@9Z*j1W^Oe~@aWTA6mGB6MMz1kvh}EN=1s>tOdVI<&)Y*KUeo7(UCv=9*)4dc5xxE4d1*-*et=ROBLSw^O6)5wv2mU2= zikXil6s8{YWe7K6NfiVhjm@{>OT=^N!ss7(i@~>uaY{MA_nXY*sh4v_Lcq3nB#wv5 z?cmUxoDYI$bWEa2ObmWH7a3xIq*@ZWR|Z#EB%lyP$wOwhkHjfJq`FkD`-*%(=9KZ~ z%&kiYjoyr&Ms4}v-(g@-L=o`+7DP<+0g-_vH7wy`8)j##6ZVu1_yq5Dvf0&obZT6@ zswHanO$=9C<82Jhoa$L!yu>b^o6Sj4hY*zLm-{XSXmEk=NMv%ed;j6PnYB|BB*BZ& zcf{?a``{%`Gr7f+oFMdot)y|%y^pBPvg`eJjGcQzub%a5S{-RW;iKO*peObV+%-dT zr#so^zl^rBB--p|#sHs0&0G8#;U~E7%Fu?$NDzX{pk5DJj?d;4O z_j(g7-_UyKC7^HMmkU>J??dFOtFisg+|b_W9tD7;UK***A$_NncU6Fpew+B$RK;^? z3brs&5Vxq`7>Wuu>FU~cPT}^_(hs?L7skDLDxr&XoEh^Id9~Oe%p|0YD#{#~Jlk3o zZb7?+;K_aS4dkEYTatZ~^9%Wal8M5+)yQgiHI0afo zMnD07lWGJ3ykDBJ88*Q1zJUQOZxy4zZ~l^HgrLJgI~BA1-Z<0N@bRatxB_ z8QqcrtiRqP-s9$_3JaPwg)8;pagCxnHB|w`99~h7L*~|M~a}D@@4MrnOI7v~A2BJ#w?>;a=z6qm4>-L^x z7JLLn5pl2sWz%%Yg%&D^rKMJ$^7@i+4BbHkm?_oKbFX;Kj&dP}@#n<9F)fblLGBY0 zJqI+V+=g*h7NQcA2TruztE*CuERCn4UJ&aN(bk&4XqOzc#9(O5M#a~GlYszAd%Owz z6-0q4TL!1p>*>iAuf_03LpyG`IDJx+0@!j0#dsq_4;O=wG%Jge2`g%!S7aJ& zFA^;5@rEmI>c+f0>?N%%zTTaqMWZVoSncxFiP18oBXQ>}_RIA|W^XO{DWCM#UU8zf z&w1AheKBd4#^mQ`?PCvB>lz-dTwa(bU$yg%z>J5b?+_Ztf&wXRQDS}Vw9dtzaCGXg zB~rY3&}jCNFXyY|)}2NDkE_Rufzzh>r@{#kY}x4pqlKxCbKx<}vZIjwj{E>sL|BOm zf0;`i>TR8KBpCzV{FA|K>7QF1w?Gziu~dRT^TrUCgNY{OWgY_3P&JNMtx^PsVvvr) ztF{SG^?5jtsi8M=`gM+`i858^`RJyy+JRwp4QvTS_X40AAT#_5YW-R9JoNwZ#3X&h8> zDu8$1D`y?7LE|OewHY@JBJ}J*R4O@|n%_nG3$giG3ikEAH>wIJEqjtC(ybn$<|>d} ze60eCfQs$<-;s?}*+ubet;-i;m@5=t88M_jvr+A%Ft z0-f}%D$WKbnu0FXo`_dflW21WLvCCJjg^vw@e?Nm2Iq=>bjpUeyMJH$PY=914vr_8 ztq27}&&s#gZqRiLxC@3)kscltRe2n+MLFbh<{o?}Tlh2$pS9Z}>QYH#%N<>!GNhTK zDzpyV`q94gN!@K$e>hB(iTM|&tZYJbz$kibFXmjIgU^jG0A-t-rzKrvT1?nNJ1`HG z2n_ZHlsIgKC4+Pt$5SsscV5}>=aBI%ay^Nm{3{kWx2U~o%zZTln_oIiAlm@k*1wN1 z06dmWrUKuXjR)!1NCl9AahJ z#-4A{NUj726zJbS)5vDdM)N-2+;B4goLr)vsh}S|={@Qe7h5Wbo|%gdkln77_O(&+13TWzSehSOf3tWNrKn!yw3mYogK4a!aPC>H9~vZ* z%(H)^nBPg!bW@9@Utx(0j_K7V|mea>)Ul7r$MC#%;&s|+;!6YTDcil1M3Ur34KqlFZrLzAKFN>6yjVR*5kmNEd z;@jRx6F7*{KbK0`cmDVl&KsLnaiTB*RmDxVX&O}Gr%Q-4fYx1q^8ptwKojre;kA*Z z2WtNnP{sm;2np3@CJJe~wPo2NKK=0h=awAt^qfn&N$}9c$a9WC$cl_DZi(v1th|j35n@qhh$}^| zNdA=|Apm9@4F|lf^wERo;;itp>X`j&1Qe_q@MmnTfa{}nwX--tn0is21a2;`pqMLk zp9_gmTd9_(wor(gmo0m^qh##QRBj;ym_9Xsb10D}zoPtOt2bvQTydI^0_g*|L8w$Z zNn_79)Gnto^;ck|E84qG8Lu zJ`2;^g0Q4UE0j+|^j%`x3WGfjax6%2_eXLeZEJYiyqK|}Q{dYY_(y~*DH>_m( zVAfs(@>r-IZ#l+CvG`?1FYJ9h*dQ?x!@c zvrQ0gM`r{*etx2F0ZMS2<*y^|Xmtr5Fb+0^t3p2Hh0j8G`So2cUER%6sK5)~Cb=3C zY0ABzn}GCFa^@oveG^z8HBp17R1WNVHTSkx^90aPeBN_Egf4Ka+bEaX* zOzc-zL6ZVV1w5X_+o($EGwYHkIfb~d@1ppv@{JLVK!TC9aZ$y+JPG%nwVNI1$_2%$h2`O8bTNu_yrg;> z#^Xo-<1Yo#%iE+-pN6eWAPY+7D{Ax#=Ml%%%=RB-&BE31cSsLP(%Td%Zz#Jzos=5$ zYzk0M<5iQfTy;Z5xuCWlOS3kk;ViKoh_mg_8;)7u2KdO1vJ?A=&RtN*MVjKwu5IjG zqIaqN%Nz5%zU~i^LE6i(-OTFmt)Xg?c}8wh4f`Dti!bgRtQ?IfzQc8co}1AFMk8I~ z$ZA%Vq)V_5h?rH!hn}zOL~{xI2p(^Oz!(t{DkS#5g#{pMl=4`Su;0eKF?1{g_nzSE z(qqO-J#vg8(*Ym2-9r;G)CvCLIh|J1yp*e94yisSd~+U(LFoK_`TRD~MgIsp(?lrA z89X>s)Pm#Rm2{G(*HWb$tmZf=M05Gy5`!wfD#Gc7K=pj=>aUx(s|k_pUt&^AD00`X zDQW`+m&FyXQgMdmtEtYkVn&s^MHH2D1>uu!!zSs{4KAc9*jwrji>!;`2x??+`|jeI zjynl|1_Y>lFfIW(noL7}s#O9P)NcDmvH@<#m0#zZ6pYdz16oD$& z;VN?dB)xTQa@Akg>>4^)?Hk#bDsWZCGR|@6Q&ks>&`=%XhCV$8NOAh1W6aqRaiHOQ zFB{WH8AgU@i#;N0<@rYsmG0nvH^2pu&M~qjh(u4&ou9ZqRyHYI`5=sFbtL51aw9yj zks%K|ND{Wrqvk>VdKZfBuyeO&fX2?2@L0GSJYr*)awd18eF zSXC&aDOb)H#bpRcZm{72!Q!ooXb1k@U!3F;!k*CCgT{mTvMHYS5F+AExzj~CB_}%^#J)vH$crgM=<5fEM@DVwg*RSxaYN{Rs`8Z7RIYbKRDTf0Ua>|T-UBEfeN63h2|2Iq=7LkYzJg$(6$J$UPA13%C}+`73zkF1+cfPEe5k^i7- z;RMMTfW<{DgLTEa@mf;#Eb(rtZ12KrC0`_&7<8zBP|=2FIqAA@~&-6s>v6h4=n zZbg4%MJ8GQO|{1g^EOf^6||69r?I_K=aRa#jX+&b!^3rWWhY~Hm%SWym7b7=bYAo= z5&Z3GT6DS%^HRE8r^Lsdz>nL+_Tp-MHtct?H2@SVI%wP=zQs!+S} zSJyN8z&W1k8_i7!Ex!-Q(V9~m(=24>rB?kfYA#s~oWK>?#h;ax78?QAZbo$ZL~x^# z$LD~&u_y>b-Sc_ZDgw>WU%BM8lOFWfiR+s_lq?4LoA0c8baYy=oa~N-uV_XX8vwRX z={&hAoSW!IJc)~$lUNYbp9pY0_@1{u`D@-kF7Z3;Mq~{r?4|B_b*`0G=MVbe5fn7O z%M?RGZ>9o$!e^Gh7VhLhT}8SVD#!hj;X|TZ_jZlK--M!1w(Huc`Y%h_fH3?O3|rRN zK0woG1QUMI!PGWCWY*o!+05Rl}cxVL_ zU;YTmS9rB+Nkhg8oLhF0+Pa$ZOl#TfO}YI_yzb?TF}&+=chBi>`)lW1Z_L=Q_Do}M z$`VZ4{x#C^D^nPF1BI|gPoG~Cc`Y<(!0Sy+EN#EEKn`jx%+hrm%no%jj$U}LFZ+sx zBQ1|6dQg22p&tC>m{_N*-IcDGq68A7b?oq0SyLCpjMG6-p{IVMO>=qyO3(Vm?)_hm zLqwoBkEZ$<>dXRM>|=1-2F(Ye;Ek-cTH)tpy5!_2aDRP9nT7c)ta4KAnywKg^c+7^?c76a5*KNFrF1B^yS;zHk<- zJyBo}?@u4ocx-uge}fcvRREbJQk^u`kms#3DMz3emlTynm?oc`X3K<;Y@XjHo%okO zjlK5r%+;!`o(Pq|0gJgCcIeBR9+L=)uKMhuw@}uTLN@^=+?i&^L|p_vuv!BrP%>9n zfcQ7j-+BMI)s}deTdfp~`+mUUD2t5FhHX+liTn*g6JIM4@J71z2~%G`gkdUQAArNM z0Rf_c9p<3}D4?Gh9?sUY9<+eaM5^%vZ+q}4bqUw0*!alcyaEc78|bgN3oc#ZYwl{1 zI|(UQ;h?)$S)$3JyU;*+*C``DN;?<%9I++ zXCJ)oGS6e5J~^zcj|N37>7q(eC4{!KLbT41dr`Hs9ZhC?PeOKcrM1}iDTZpJFL(Bq zX4U+u#Q9D?5+&ZF@J&md)IC^((irDc)nJUhC&}qDWjRlJ>9s&I(lL~{$eEXjK&0-s zFQJnikTLN}nsvw(lTLDma@joCdlSfrWDNT-KJfFaF~n(kGqKzC6zPvJc=IY*w zapC(%&Pp`-^K3rH!#tgSxH-gKe5=KcA99KD_~xa{z@0y3FIIJ_;{zJf5)nY9LBkly zN$j4DMrHr(Mu2&_8v{R{j+Qth{b>>Zj#&_`guK`Iot6kSmMwHFkPRr@-CDUgJ+{D# zULDd|H5^rxC1gjQ>@I~HMRezKMKF%6oUs;-l=QXB=DM|_)I+@Nn~tf`Q?v6ZTmp~$ zeC>zAi~nMiOmrVmxR#c^)5x(llYCuq0g}F=_0kjl#&eRc23yW3%_`^CQ|{0$@NSkO!Gu3s$hnawlqBD%Sc|5nXhfvdCaDSW9+ZXZpCiUGgE-;DuwgW2gVD zcPDK->EIoCC5i0M!JJ^WAp2GjxqxXJEF7B~PjG#fE>qKMk3lJ1<}rPw za7TufEPJL<-$;e}&Z(gtfCLJ*y3%M;xLg0E#Tcq3Ne;?<%N0fx$k!(>f%~*GRhuAd z2!w=SbEQS%5>)dp{b-=LpM`!Gu=BMDj{e_Y|DWf9e zYEpA`B{1X{Xkpc9CkVK2p9gmP68efby$M`7tM0Qw+@Cp}h_Hzk)XuvgAd6$hFaIjeL!jSpFsCe`| zno`H3s86z2jimKA#A3EQEEVK&!nq5*{6bSs_D?6E4WbqjICKTkhxg``($0tLqvYS`;cfN_*h|(5Vei}tD+Vp9nxtq|6$gI$#g=g#eY~+4t zk*h92FVt*uIZVDPNA1)=F*bUHh8Wv^U~E9WOg_JsvMtm8%h*VfN^Eo-YFvm1k~<_7 zh!uzE#@KKcVfe`J7ux_??>uxePnOS4@Dh)iOIkIi-qCt=6E$S=j%me{DufDN&99*h z=Exv6(22+Q$Jq^4qF&-jxLA(^7vD_$JZ*-S;~cy!y8OnMJh>O{r`xh!2+2O}WHcgm zwGu6v$xqi(ZfHa?PK(*jm$n^Gbam*51P7Xxur143ei=dmJp2&NeF$((4l0YJr5ZV8SuzLy;C5R3% zytZxIwr$(CZQHtQd+*w|ZQHh;n}?(-l~iTk`*EtPXZn1VR<%DI>?C$uZi`b9jszcJQ3a{K8Nyj&x6~Br%r#E=mEl;FkK< z_OSp)n@oOKC^*)!ucrNaAF6c%UDZKl{LiOv)^+V#4gjpPg)7LnC!ZcGFu$C)PU#3n zc|xB}#IdGDQH;r)ZmRr%zbW(%-zc}wAI6ATTs4(0v>Ucnc&B!;~oOYjeC;@4;tH*I~HBOM}6)2iVG)q1z+y^~G}lc^0Rl_aS?b z?8C}1QVgI=E1~LyrJ>BBC}T%AZOHqMhj3A_)Bxx8Gsy5LzC)y-280NjJ;_9mS|$ zTud?z!OA~;FCDig2Iyde(Bq*C^sI(<>>HlGa7ZQ0L5sd9L|;S~HT4w?lMUxYAVr%i zk7})6Rn!jd_gBulWr6mG_d{`x4lMeawPX~n-Wg*{WJBHg3Qs)U^{pj6LFe zF-r7`NBEmssZ(EX&+|e+T2Y@m9(sPAc05k4@Y;@p#cpMDTG};SI2+O1QuF%=p3QjR zu?3mp@x`{R2q)l=7b%gftieoV9A+mrUZ{AE`*KeU(`v!j3DkvZlFUJl*e~GQ6VqUM z-a?-@Z(alKr47Y7$cORRz~AacR6h7n;kKj(VPF-7r`0(bqzh?5gkP;^{kg^EHip}M ziWAMToVV|*4pB>p0irN5m*XX4Rt?%z++lZeTgT>TN2*3Pme5f6U@RX@@&`rAAy2CH z6e%q1X`xTE&V{K7m{L>z%oISeEn^39Yb2_-QkqrsFyUe>{Su`>qIU{XdKdkmT8cnm z<%Enk@`1#bv5dw#B=q_#`}VyO$4=B%9$HZLBPrkx7TOGla~5-)jOL46E5C^H^*mzO zLPIz=*gMCW+J?Cfy;)&odK%)1cnag@OHB1f6VZDuuir_s0k-U*q+si<;jOgL0f1nS zT$b|U7gn?9QUf&7#Hsd3_V3N*i<<^_OzU|DGu~%oly<|N zoPI6IMupKKL!@dKm}};=N>s|3XvHA~W%jb_WOMMS++ChjJNz|^c}GXMyxqNPX&Ftv zMh^7gEa;b=TelCT7Pepd$cH{^#xbRSwpkoGb567w04IR!s7Xv_^jZLU=yVHdx3iN% zy%&PpUW;wH2d(=aSRj%1(;}#4%#K+6Q+&zR6esAyr!`vM5Mn-GKhapMx+Kji9fJf5 zL%nH+#;I*6-oq&8=keatcog**fh`zpN;w+gi?_?CvR}lp4DF`{oX#cQAz)rV_h)-7 z1JpZ=rwkcgKdPamkXE4VxUFhaUKTI~D#!W^D8wnJrcil1qoV!FotB@K$)G$_k~TAv ziV~tK3B6vHplJCdHo5Cxj(g3kpErPAbO9Ch7*gd@;vUWj<4x7{{(4K{H6%V9b7dLSe>uA2+`Y;DAoE5PvwH|Yk#!Z=}5jEk;S`gaF!FTkSiTr$x zito)6@rUBTy&cJ8d0R@U<13Y~gcp_K)1DZH9;pX6UQ_1Sx*`uGB;W5(d=ic#P!YYhECG-pqlFlbm+$Dkoo`alfJ z1%UxvV#Oj$bp2}Tz34nf%MvOg5S`a%Bo(POgoC=>;Fo&u09|y1OU-I6?LJ&_WoJ(PXy<7g$pwcz1vPV6UL;C-44lG#o`R z_uS19cP_qKxet{;CTD5~hrOsmCM&B0VZK6G0m7-05ofnFoknj{ymCLFAgrBwT?yNp z5v z)3;5X>RG@yrad2vww2;Msl)87T^Ew{Vt?YKn6^WAWh!|#a6_>%E9P0aD6v?D`v&P{ z)sbytK{Mm@5TDH}=}VZ}c^CeD_@Z!2Gan4P@>-r%4va~$weQaj9w1&I5Tu+y6t1&@ z5VFsugld_8ASBI=0=gdNokb#y_w$z6#H0u#j;$1;x@$i$o%v~?w~@a-9}7x`yV59h z)p;6MY`O|_hjh;IOnJI7QptAaieRsdb@F5Zz34J|4F?_>?arKUsR)r@Rrxxai7*<& z9@l!C-+jauYn;2v)w0X{f+*QqiFRd+F^ldc+r?-sj`Ty-BW`2+o1D^sjpAv?sZJ!7 zKD%r9EHTlEj`RhDHTg^fiXx@zf2xfQyZmqW#AFf#oUfY;5Ey8~BoG~(XS&Nxmd1Ev zx>ggI#@VN2ZgbsG+7#*RR^J3bQ}A(U@t5?6bpOHrw1YRq*GVuWnHISQ_XH*qB9 zGU=0b9&zLq`zj+fM`llDztMp?=p^CnQY(8L^^D`n)A@5m!wdh6dLg2eb5qWodFXJK z5b)Q+pdQ+@h2b0dwsNmfZyB1RuH4M z=z+qjJmK_2J@0qXFN4LNLFhRqxlK-s?^S2X$Ys_C)CR~#ptu6G$&o}b0`RGW`o$No zpp(P?>kaD>8r_Yjt$NwJcW)tH0nkaQ$NS+21%IliKx4;%X403--FobHad-Q!yA2^6 zaQ4Fvi(6znN>W+H5sB|LdSZXKctl=&K^_g3mQwmgL$;Ab5|w2&VU7s-;F3^@Yb?)k zNjYBk!99d`9gqsDzdOEhAH&swfQJZ0}d7G=(LHo+u^)Gc~W)nf}7nTII z2vjrTXza}#skV{4*q5j|LIeEilZ&ftD%W2)KJjBlx4M#dkAq6$$v`ah!SXbk0D{*e zj_oYyPSn--Vz=*WS&q^Y)o$|Dx2ge|9*=u+#%m|tEw+I8(c{X_R&GVlU z)aEyG%uQ92A8O}Msjf*?@j*<@LPM}jlp#*g6r<9pkoJ=PG2oClu?OfCnMnJ0SnEGa zns2;wgxoo(`@&z?a$l$0{Isy-$X(B6yvm>HA8Ei=;GXE_>HDN;bLe|1C|(TYV=xpN z`G{w`*w?)}p~XgrR&FC0GO2!f);IRSRwfUAJ>0>>ZWgve<#z$nY(elzBchUt zXj3raWF7Wgh)7Y}IKf~JITDHw0{&mM*di_u4>`*3`ym2luof4Y$oXg80v&_3^Kx{a z$3>G0a$eg3#bt$>#m{~5rk_8s4RsuTc0sX}B-$yGZREUIr6msQ;tE(YI6&q>H4n|E zZCqm@Y9iPU!l~9$gY1(l&ys&H4%~HkLgiF*x$Ux;BY~ibVW`}fXg1d}lVca?>w_*6 z&AsoSeFTq?RDjiJ$QWT40;Cm}WY)6Vx+7JO+q(W5XXC? zq-eG{UZ@4u%+(--$m?QxlrpB9y~OeM6Z)nN{@64ctW)w|b7SOZ9!onEjo#yU9X>x9 z)Ue)Bq?Hta<`dIRO#;lA`U&yX+<;6{#KE3ppsDK)($;=v1MO{mg#95p{*;5ygw2`@ zd(5t~__TBZIz^TR8PTmaC^VkM zPaTpF*aq@7C)ohdTHRonvM7xaIc3ZkInfc(d`8M2t~F)%#i7ziZ*#0dR5MV=9H90g zMBN{ouSOV)!6T_FxyR>qnp2KV`NFZ{O%_54RJEdZBU%)k+Pygfkl^_X*7WzB24bK| zPEu9U#%i_QMpv|zh7s*TdC_HGjv52l>)U0EM_jmIGUi*rD?8V*ku_t9*< zew|lPFOEm~OwyiL_Q7Uz*BiE}R0F{P$K!ORCo;&V8hY0cpBPbvzQPn<(HV;wFZ+&8 zcXyCY8E~-g%kKyh-Pwrh6H>qr9+5#$a8d1)LZ4!yF~HKl;m0gMpxw z!U~$r1gSWC!a7YU8}Q{WvTR7c0%;9uKW(S3+9j&9M}yL zA}&4R7a&)k+54%i32oIrdVX{pin4?j5xoNk9lAsCZz--R78-u7eG0lO*49#$gH3M< z_(wb|mnF2^RTgW=@>7gl@#Q6VebfU2REpDkU350}#cs4D$rXbk`@b1bqh3ok+2!)) z?p^f>u%|II?DbQ>$du7ay~wy|ty_{AM(JHgd|$8jfX&fVu#z)pW8au700Xr6uL31{&t>9h-D!2AjUF9UXS~umR{=8C4O3ZN6hM1GHe3 zI*(Wq#VVO|ycFn!Y3JTT62mg<9u9~KH74v>c`5nX;yGw=pGz%^I3*~aJ@|UVRDFNs z;cPl=r6@V~`(L+YN94S0))AaTFrJy12w5vi)vdDEbUIWt!Bg>%|NgKy zI&0^@bX}^A&01~OhBT3dsE_6%1;o~QvI`n*NZ%j)v<79y0T*#qe0fMrRCbs1)LEAb zTlHUJw=?NO+><8(b~<*exu7q&D!}5V&uw9??sB#(1EWeu`1!tCBhWa+*V1+qpAgKhOkrXOQ;2N(1Pe6G(e8^>Xv(7rsvFZLOnQeMe8EyHh?iId`Onh+?W*(F64)&=T(HRAiywPQ6 zD0YZwI@3a#FbE9X`ZD&&bp$53fo++xTrZ+p^H?K2%1qqFEgZ;EcB|!|25b6B45%C^ z(+nS@(++~VO6P6h*~uPD`AEDTkDg0a11t1fg=k3zHh-j+s)AJe@m6J*)*Yn!LrFj;%zXk?jAH7$rd9_&Wyzeu>8+ZbUHAJ7HlXR-)zwq_CnJ zSob4PI~T~7#Oyd#2UzuYWH6rQ2>UEmB9D2r*RT&$dA#IvhDiQc)KN?J5+<5i@^oj1lEP_3m0kaYc9w9b1k0lp zrB)QB08*!DiMbDtvl?|t_^HNlPL4fLZxaHghNGu(ZOND6kt9gVih5HG>LVJ$BV1!? zusM9@UbT9@kMu09fX*G6jto1thNyv|?5e}gK@woW1DbcLpwBZViE65J)~|Q>DB*nH z`#UCLk;45s>LACrnMah1?K*XV6SAybN{>yJW5ec}!*E#(A`c-t_~vKTcIYs7gC2#Z zbCtJbq*c`Ux_xaSDDIL`sl=I~x@LSQmq$2~+%8xq0#+9PqPs&d(QkcZ)Q@n}e9ro> zQB2TwkuT#V@6?p$|AC6IGyX4v>>nz^z{vhzbjUwcgqfB3zb*Lxfr_xO|6Bf_&;O5# z#6E*6=x#26LJ0>6JHWO${xd|}gEqz3Z*Fe-Y1_0Nf;vIm-QoMU@lSQe+joD}yVX0b zu30<8U$1hVpL9$_qNrSi$Xdh%9JR5@xyZc4>;fXP>&TFq0}>NMa}yIW<6>l%2OvSd z;&J0-aL@KE46O&h;lm<;=jP70$*j(vU(0LbX*;5K>(0fklsz@d$W zu>-OTk~!x-d_|3g5d?-;)_~5Ae)uUVJg0NAui7v%baZvkVXJY^ZE>gGDl7nN(Bw`4 zO!JB7`avy#-YQK4x(ZnDcB|(H69HAGX>op!73x`ComgD}fOcRBppElm54|HAV?T2|b`*ly6+%m9?3 z5fJhT=%jCtPDG#?ni$`sEg+nleB;?&7@GhvvAU6e=(Z6E=!!uYd~WY{zd5nEHP$#e z7r38n;e}&J}dbYp~3U-KYKcvzdjwRZESRHd47XsXl-O< zeys+F*5d@HM+SBz`VSF7Vmo@;vyjpj0~?p7=SW0*ZRK4 zf9$|Af1rEwdV@o;1+wmS{bT?}di{QV7k$;!BdcM@zTv-biOmvJ&=dclmAt!8{<=az zZ*~CkoUdsBxJ=o|0FaTP(E)&C6Zd`kKT=?6eRaZ(@YgG`m9_xX`2YFrk^iM!Ki$>iA3Iv$o7g{wmF=p}eXZZF{{oEz|{Z;uHaRe{{if;sn5utT&k3Nh35aToNB7pC0pKDNAO7BV%cs>Ze?ITO)r|M*_Py@E z?~)GN#MsLIWHOntxdjvi2N!VT9CoIpude~*%G@4W0J(f>4+DUCVQZJYBJ_DX?*J%k zgSYj{rR3oD5qzbc>qh|h5j=o90%3^!Msr{Q!W{S`UMn_)cUvD3$3~p^cYu0*0-^uT~ zFZ`c|p7aV2^KyTM1k(JU`d;MReR^GfK)UFk$+thxm^d=H0e&<@LPbhm=J47d^10#cu3b}s2)p@x54f@ohf6=@6QN#BSaF61gZTYO8e6xPIyiez2YBumEQ1EMs3 z((0C`jAmt{`+x4jnO-1lX6+SeQkO6a$bB0Jo+8_IusHDJH>u&y-ZL3^*7nTV~`|_ zKVvGg!80F5uE!DvR;8dv^FH`6RZQMDp&qAtJ>lj_z~}PMubT}HMP1cs=PyCTouPBT zp6e{9#eA_0HV105-8k*GEifa|BZ}ZaRnn_2_kA0`^csY!L6Z<1Paj)(YEj3~Tpa-? zPyB(ibNRaKeGU=dtH-y>xeLZuqGWU3xOy#RMZ@@_fh6xL184Ey2S|d*@-s|jHO^=; zAwPAF@3SM-G8SI4PoZTRKKs8^aa(ux2Vg%0;5Jg(Q11bPG4|sSn}H;lU$R=M+pQ;_ zgRm?WR<$+D_UPOWv(Lqjo!!ZsT-sO;?#?&A*sNj69+)1G|8i9D;Qd{^ZVFlWd zh^MV1XUJs?G22=b43D~X$`gFbrQrDwR`+6c^remCRa2#_fwOZSJVg>sr%XZ0uJ2qv z6%rA9dgWsHY%{>4C_gHhlY}LFr@ug)y=g`FFT}!{ugbz?>iET}YG6IhX^g413Kp{2 zzYYN@ajp?O8WHibS_ie=$RV3JIAXZj=*pTQFyIlxo)N`t{-HhW`02;Z^~vcm6LchZ z@jQEiDg2bFuaMu$9kSLy{JhL4Sk}cLQKfJ_dnpb<;6FYpc==0$RFGDf;*-H=+L<>p z{$$PE;?e|}BqRFW2Y;iL!0sF^biLBdYDUf%aJ&J6>z50f7ySnO!W!)IFY|ZS&NobG zg~)ZKRM3|TE9Gu#q_UPZQYBlg%f&dRt?j0s6G&Ml0SJ`HMnD4Xf{K<7X~nl`KBL4k0j$fR}E683#8ayqPX$BTWbu?92*;q zr_3LhIlx^7X8>AEm~mpqQl#_r@70^xV>|@UZAtl$4*dQJ%f?hscreyN*nDN+cfnXN zu`Dl;N5FBYP;fx>{ME(sfAroF+OYha;h`=%;88)))fzkyce-3HYL)W?m&Ec0O+sWgE zun*wR!cX@uFh%mxv%<^9RmR3#AG#;=Q%-BQZbrI(X{0<03$55o7R+V;QhATCeR!R4 zl#yIIqpvlv%(k<{#<6a35azPXAalRW;!)!?rF&ZY(-~2Cf&>JfxwN`{a_-G#Z!arD zjHjpBcTWs+8>2`f$`m^Qn`LqhOe$Is9=BFZ0ZhA+A}9Krx;O?!O$!VD#=%QA)$&2P zM$rAVg5gFx6UBg^Ge%G4y%1NdEC6J11z38^rE@n=0CN<++O~y;aCKH1B6F;uRk+$l zK+`vbry|wlUTpyuebJkKK4}-CTE!WfYlgNs@)7Sc<}I3kvs$j9Cjw9c>a|1*NqDG& zz>gk$AlsX32Ai~t_BOy7#o06AGT-6L-@<9py9=*yY@-4s=BA}Ng6eV7fvJG-J{1yr zc+j*=%g6c^jj+xgPxT%G zkALNDi@F|ND5|uPpwIp(+&pQ(k*Ot(dd_uSTN6r_a7)!;XbSF?SyDE{F_^gei*oTV zCb9M5)SyOT(*(%Z= zhDJlUX*#5L`GxszwLvXxTWP^Ont+QSDgQuyoxMn-HcA_bTf*o?F2h1ZQ%H0=5f+|! zsL-Yw;qaXMmi-r*iiu`j6jK@0thkx#_gWU9SUl*qRE8IKf zFDgWGZ>UkD+Jgz0VU9Ib0A1om!Q*&4Sj}Vx7_N%FQ{&`@!_t+a70o3^W`Jic6>P~g ztmZz`&pW3Fzmx#6&JUjwTyV$nqPwR=bfdE7BDM0pW|$G+n@`=mi1yLFqVFJMVfM28 z=0I<@i#-pJ%SJsD0rd*s>joX&iB$!*+~xy#GZ|eqEM`in>S5dM`Cz9Mvwqs};c=QqX_U+TbUAI_nDp>U zE0(X7V~Z-&%pgA)n9K#FTBf?UqgT~Oo^3McBSr@o^@rHC1zd{cchM{R4U$7iX!Zlh zjjQ0^dT2(x=XCc1>S$-*S+yMTyO^RWVtHQjZHTzXW4v~@+b^G2H)QHpvvpSh-K5yM zh|eqUuenX9^r4poX=Q+vfIz6%6UJ7SIXO>*CP$3(9rrBiA{-hjbCcND$()vH z1u5g>=e>{cbYqOCjOn=QcYzuG;`khrA%S#Bz9mj-ACE8SMc2jrt)sQ_E5tXdrG)@5 z5K(oVda#;X>M_{080BEb#IBf9;P;N-O(=5VyRS^9(xN(GyMd&Ywg*sMPjSLmhMUD$xp5Dyu{{&V^@8`d_edEx8^RC#xtq=ZLf5&8QM@F zrE_ZPyur>dZX^w-z5Ng?PVh%TRCu4bu& z*&}n1**j+sbGo?3LXsYp2}l@Tgj=@jL^Lc~oXXklW(2(|Wo@6qk-t)~TCJDW=41lD ziF2p4qTPD&q%=(Zw{!_L`TQ_&>m!*#A5+~qD#j#k2}L#7LrWahem@2x*b+EY#?&(w zMkwZQ?Z@mhn-(t}l$9Yn7NN`PQnSH3j5n$r=}lp)uDV?LE{lcpr^SfIznp+EnOCQZ zkNe!>SWEXjyAh*+-(aIL_P|ul8k*s6O<{7RH)wmT=*mTKwftij^uwACxzh>IjnJ#a zrt2g$`jh#W9Cz0JIEUt zN4y<022+ZRW#rYxzT2dvobN+F49D+YV2?U}b-K&t#5YbwFWSKPJ&W)zP~sp z(LP8v<2T9?R6zXE^-^EYmAR-A#V=F16{de+ZvP}$B~6to8q4u02Li(A!f{S_FSuj) zzVw|+P4;{jyJXA>QPHpEHBo4rh_D84(AHJyzgAokWL#v<5nHC7w_-X#*<9BN>N@FKrrVgILw@5L!!7ZBuacmcF|7PMe!aU^##|kqNe;Y0l3|QPw zan5iYKWLEq?e}}(I62v`?W&#@@ow}`e6#1`eu@G%;Zl%HA z>ftG+BD{Tj1;JWMX(se9K50lE4RmfDnWIn54OGt_#0hUBDn5&^tfXC4v}LVOC=dH= zmLm7cwPRxOLT#uFDZBZGp~A{P4%hED8iw6fJn0vug1b`fEY^}Q6yV({#}Ohr$95uW zKc;HbkzTs;;bAu9z6fy{Oe~%ht0ZpWJy0z)Sl@W0dhLE7f%hJ;2aLk*Au7mL%6-U8 zSooq0c&M0!#J~n5sSQ099KG&ukloVixS#K=coT;~hFs-a!7rO|_Z>6;Qt;y%P{em> zXiK3@gS7MB0u47=oe(+fjZWx|?$di>$9u{=c`Xz8e=pc(v{v^;=`Y0fEEzVvw5Z<^ zV{K8Ye=U4F_1fK@1bt0CPN+&|iBSuESm*jO<4niX3cfYsT4Qg(N^@c}DpP`3zag1I zep#_bOnlHsENAnczdrP9kiOe%GL0c_wRQM{4v3h3Ydiq?Enpy;gQGwTJ+-Ro=5|F1 z^HKtN7sH5oa+{1yJpT}Cv)PIuECq6>oww_pon<42R6a<|eEikyUC6*fgcz5vAPfY3 z@H!fvQPN|F7i6)2j46Q~y4$+jb0pKCnmhe-%zLG3Rl^Q7WCShW^Ok&?HtKUw-`xcq z!YQG=G1PAtb7nxnO@C*}u9ce$IN!Z`8S*5!20@-p9E=jHRrkDY{1IkiMwaKJ<$D<8 z24~7*HW|O{#3Mx4Z~sW-KVcqvw7nn&NETRzRtJtR@D)1?{zrR+`<+lXfdz(OKbsQ& zDITxi-Q|<>4)-A;0}I0fYor>kKG{ONe_ulpsE7BWiOg@0tC&X=RnFsIo89EhDSNxH z*EfsYv=O)0BP@C)xo%(=Jjx3z^+Mx;C2<3VDC=vg6azaMQCOn1PI^t4A)ByGcNtx< zAILnDT~Ng5=iP>aEUaxpYD;sd^4q#?06S?gKG>$7^tx|0Dp2$9JXLmK!`gEZ;%&JD z(na+u!ED;K$J<{yg|xO)BTU*6+Y>)RbQ~;DT7QBw40`>^9lg6wKr;@u4vC{zWi1i6 zY|~n4*6cwo+mn8!+0T>tZr@q!Z?3KgcgNs{jiyctdnNT@Dz~6RrtwSDh%?NbxN<6} z!vxt``xCQTj--4e0cEyxryB3fu8cdq!91>8=d9UP-TDkkEq^EPSecgk+EcnZDLx}IF7yF@4;yKp4@H;_X?O=w!-UqId^L4yIm}yA0(Q!l#cTN^62Fy(R+z8rU6?8 ziXlRz%Oc65-n@+h8KQdX;+@lCY{Cw^hl-+H2)EpM`>c&!Phh9v!wn1cOK*V-_pL*x zaC&8O(dGxl-A3&3no@@;gFd=&zDmoatoYFSQCcb&935V}8LJrP)iYY--O)f|FA0@A z9$=ay=hD$h{eRcoHlI~@BGTUS&Zc4P_@Nu6ar(Od&0CNo^1x?UTULNo@PL=Xn`}*i^rjifps0S@L1 zG1J6LyYj7&t2s=(yM*@0a>G?8v5v-#Pwr37Y7Kj%nm!?P)NXfZcy@`zVw|WH1?bhn zDBDWLFwI#(Oh*06U&kuM0}lCt0jS(-?xm$2te9*FCs!!sRLZ$+o-HL`tPj@=;^z%} zarBd%G$oeJBgkGxZ-ahwurxa(BoOx(#LFnKQmkp0gi7U-*cD^W>`D5H+!;q)w01l5 zUB3yAjW6{>vsyatp6t1}_(#RJK8xX3BdJg5p2n#}4#-$2v8V@*;Oy$Vz27I*q}nTj z&uGSV`>4&9Q@-mjVST;qjxJy4od2%@qf z%Al#|R>}>8$B#I4Z8N0pI}#TEX~4UIt$940&0q(wVR}4?Eb#rh_Q`s&Wb(ko-&sa% zU9vTI7xqkoCN-v+k<0>LFtPnE49J~GRbNeTV7<2EOb$*qE{SVebzS^$I2#93ziDPo zLKJb@7H&t&g}ESmdCNMrcnc-ZN@bQL*fO0wqVd8fBw3{>61m=v@v$#`UkM| zJI#k0N2X+Pm(3gZYG=1G|E}x`s?;7(H&a$_=!Br&ja}ghn8O8w>9T3d>VqSeTB{r% z^ey%bqxtDJZXY0Ghi^I+*JZ8W4Pv$1KBSXw<|c^&=3(|6aZyp&?q^fZrv+8 zk!Vwaa3KAuLLB4Qm6OK~nZIIxVQpJ=KyL&NLZIrM%`)^CMTYiTdj@P86rjP;JBEdn z&sZxzIB3dqS+6alGtqUkXcJd+E!F-Gj+0a8^MLUEsbaiI220D)tgUIbfqR!0{f5-o zPuZmp_UX2PV~wIobm&xo^v~-Ach*NM)hE_wK0TVyix|T9?AU$jE`|8l+l2hQnh(xz zruuio{yVyi*8xX_@gQ!zCT*u_iT|ud3=QlEDaq<2fpk(dGwh6^*x0|ixJEhd9(Kf; z&GvpYWq>XI4)(*z3GK4_Bep!CB2mgrF!5)Rp%oa~l(uCvst5uufTiAWOT;aDJ)VzE1KK40;pukM6$G8HZUXEs(7d z%@noGBOsQIg?v z{(3+7Ij%(sHKn-i+_P+YryAi$E16T`2h~(@GU#;M5JYIogc@3LE*mR`bQ%40I7az} z@5+0t5w=K9G~^ve>W#E_X*AopXo~9u-Bs28`hMb%r2Bg>*MiNnPD8L<8A~gU!2pR8 zvG|DV1q!W-?onkZ|7RTFIm~}^_Ja?{_D9fGL)U81qFObK`@YDf z>|;-7?R^z~E@Sp8a_Uc3P+F%mTQ|dPxKj~h4&vvf89NiP%2VNAD_uOw?H3SIn$TlE zawj18kI15CWM=x4KRR;{=)@xX;fDM@q^PDsTkpPtkvv{f*>*3yh+vQi)n+l_IZo98!GI2QQ70tyH?ZB5s-gu z7wLfK>IidA^wGNIFw8BpHG!6tk=i@Z4e}V*OE%XIJ~Z^MFrhz0vdWT*y%eGHe2^xo zCERnvZ6}t$xcnOZaZY5-l+b%!I0pC7#a|NVZ{?#qUBr#&5L3xa`$kGCIe;GNx9g%; zw^B@aCYHHNvg2I?ng~%>Z$J|#aV)I;bZlM|O^&{Fa3&RNfMvN zLZL7d!2Hwa#H2EVaNtwLU|FR=&2ox-XTr7P?VeHTtA3kE0D~0lxv!LxoSjMKb=&xx zn6@%T7VW^%a6p|zb#N&Ufc*xDQ=a!Hm)X6(@gOF*JK4{whmF^K{s6p@{$UQi*)}PUv;s*YR_SDocla8AceH_u&$a z1rJ9j-;83{xV65Cv@oSkXnT1%T=NMZ>NZd@fG$;kL;*w%v!fre_#Qy6&os@Dt54C( zo2>GNrV{z~d-7g~i=6Tu;Rk(Sy+z%;gac@CCEvrOx6UKg0x>e;jn}_lRSPc5PKMSB zAd(hu&Eq_kPXj1_7?E&nsrLKRm#td_sVq0`tXL_G{#t-X&?U0Qv;=sZ&TwB-j|B>h z75tmdeb;CTIdw#F&ly!FLICNgm;}$P?O$7mz7bl(tayRMicKnq8)8WXk-ZN|VCiv) z)AT!|?%*d?&$r9sbZkl)8Nx=<5^@$9F~czAp%(Ic1@S?^5vrh(d`x?#R^v(zTpdxU z&WGiS76=TMCAP3ctAy#oyLF{b`Ncx|mBeajt6u0#<)Z1bx;|Gm>E&Y4FP7f4KCnxv zUIKwgrJ#&MdApXL_P{H(k;A4hfI4O=R>OG5xC%72T%Y#c^D6;UOe?Fy_Nvxk8cge+3;eE<)*IfyNV&T|MIEGfKO}T_tjNZrwasjEO3UyWS6M zjQi76xgk|95OO0vV8R9(*0(QWi?i>S*-Dn zqo0G$lb&?k!k%l92mKQtf!s4g?Oz{#oY%YxsL5>(57{qlave2t649okF?mNvgACj8 z0a<4?7rR{dvutQXVioFp6jXXdO(~1YYJc7h7`QM@s!*?)t9|;z8MIlqq+~3%3EsgE zf8*jyrA%&F4y3J1wA5$S&C0C@yDVXKc)syBMZF-)){8KQbI+Xn4>zZNexehBI9o-6 z8X9tRYvMOiL&hFe+EfZLLy=k9wc<1lIx-rPp35d4mC+QAe%)3u}7kKWaGN1Tu9D{g1`dH=BU;#w}hDvF9$ycwJLWoUp)W;BUR_P`asy z2CYQ?)*qdhf`A2#)w||Tl|BLC&7*3wpADmJTKitRg1_rho@8!fU@6Fiu_nNY1^`FN zTl27YhB)(Xzc}a1)0F%zoH*aZu}pEw>#4?m+uhg^{xpSzSqe+hf0{}k=c5h43>#C| z?%S4=54AraqnbsZk~N9kj!!HmsfJdBz4zF{;5*I01f9FoEt+@I!v!XNo&T693Diaa zaXg+2>Ne)2Mys#BlECnal}`x6aRD^AmY6C<>9QDIrA2QFB7$Ia-lLC~Re-p8AbVBp zW5gc4&p1Ey&|i@fWv<|Ye{Bx{mKUTl3cfgQT8EbF1r<^3y#GY({fv4$PxDZj_D5<^ zeA&XptBQ9S+Kp6qkwrIEH>)=@tIP6F;rE6FcpNz7HP&#j`nVGa4=v(`30FV`t*eBe z%0^MS3ckOq@1}u|O^4KD3B+f?wdCca{T1G5c#ts6UTjIVb1wC@!!luIvStruYH~ZG0<&>vWY~I#{!V&iJ=vw6!8&Zg|L8EV-J!2^|b|-D~j3!3ZGy(edP0LhCX9K zTr!j<+SN#cHfop9mth>@uj;=ria={2Vc;^#d+&Pm4k5q9Hpt%A$e?psQBGVEVVy6)l@&?W9H9$WltK^5i zo2fI9vdpzqIxxw?d@J&H77#BfEU1BFz~EEJ5j03?7D$rgQ+J`EUd2@|^5Y zQ~6yeWszEH&nQ!8{1ZZloV-mx)}X5zQ^#&pnQ2D|pF!v0suKXNyQZ0#`LPGImX)yG znd{F%_cN6S?sD$sN&49UbF#wI?AxKNr~W?w@2wrgJdVL!jWOTNC-3>5!_8YnXx=f$ zqh9-I%jCTPIaya3|4!DGOVQdU&n(H+QLBa*N>`s9{+pNz7u9a1&m=08U(1Q0g_U4( z9Wz=KwZd`YpB{M`QSeORwQjR`d#rEBl-!7aVUKo#;#)SV9_WsVCtZz zql}T5*aLLNJjFB490@+i;EfSdL~$&l6?eVg1K>B~bwmlr#2;d<9I16bsKm^ifZ$0#4|w99QDC&Jy6za#8w)W*Lg`_56cmwDa8i&q2uggc_F&#M48HZs`<$XB zeU`H=EKQRYwYg}283WouvKN(zgku61F_=j_o|oBOnV*OK#qzG{LAbV5G{4m1~mS(bvm!2j^jLGofqc7`%CLW*zTQB}aHd9eg@ znZ&;z19c%?ZGBse$7af|1Ag`D)Y){&>pwegBaBCq#-evg0uSyeT%^35IR?vOYqdOn zA>Bhwb(4qb3m5I{gtJcwHm)L6obZ2BzJU&$o;!6sc7n+BC}Um0%Ful*pF6r{_@V?c z5ZZKKgyh*gxmRL1=Ewuy&<)y%MEf}65uQ7+Le0WvAr2@>b5*k#c&_g`LN`C(F39&= z$>Rw>CPs>``;c84%5`W3n@cuoP$^6e2e-6UL*%Ad)locE)Yz$faEVUUECa!-dpj+t zUsPHpbfmUg4Z0i#U4`@quI7SVoC~$(DF2YU;MO}7uZZ5?@-=b-FH_xo6O3%adjhSPf-i|=}LypJ|XRZ*WSsT-pn4QaF3lv9x-CYX_56#gDbT5-Nh_ed~RdI8y%Ch_sYq0 zso=>N->aWs;PIzrfx%K!9pq;}e!kpExUFy_hHc!y^1G{YQ&YYZ`GO4Vc~>;fFAK(NXx>q80ZosiQ1d z6GgdQ9ru$_Up_Dfm26b!-$*E$1#WWSD8tH(@5(Z@8n?vWo5EQ}`c$r7Efkyo-mq7G zs51C121t0$37A+XJQ)k9sM+6A<~=z`BUYWcf}};fKyFc=iJ&q9Yd(n-%AGQBip~z0 zZNIn%y=7xliD%tJyWz-75(pi9yf^UZ#K*&Eg`Bqb5T6bF@tb~?*MzY`0M1yPzr{bo zZ_;H%>~Pwuyl(0=#~pbUy%chC(ASX}pWAQhWlY5}U53Sk!_!oJruo2C4Ef_#csSxS zYC57%wu;h@;rTa^rt`Yq%!s*b)pM{Jb4@GT?;!+a-Ti?Fe2x6vXlT82;V)NJy;4rp zt8b`yR=+a=tA2(19z|5kd~%ehh*-clhlafL6iv=S!(mcAN{eCCf+Nh$r*D4XfP#cE zAHBHBV6lg+kfa-EmTsdMS)X-^_|V7M>=kYU{fG+OI=**#5);y^wL768ZjWET|0|$f zS;I2FCok|g7Aa%G#?>3=rmos(#w1~j3+VFW62?d2F#+tw#X3k2`-BQZI5h}JYmyEb zN2YF1#UY`)kW+kZd0043&~yIcmfV1ab`C+JMBBD4+qP|;vTfV8ZS$0M z%C>FWwr$&0uYUZv5x4Ogua{_KCv!)}USrIu2II=;>+`>&5Md$X?G09TN z!tYJ%%jomE2@{M)Fm`GL=`^{vWDn{Z?H9d!$FM$6Z#*UR;$0f+irB%kV5fU`$Pmrl zi;HG9m|I2((R-46c*nI!@C15uZ6Dxg8)l6t8FAwf*UdGW&Cd>1hDF_-NJ&%Y?N06c zuXbwT@1}&BUzPkLrbSF&sagDo|EB^FB0`4W@|5tGp#)7Qb^U=ravp2XntML6z1+Gx zC59HuX1C>=h3YHZM{il8HOSj&fQ&{@Mc#=c7V)%71^9yY`FWL^(!a96Vaivvg9|pJ zh(^e5@#m<*>g*b6BEGsFfF5|ZfJ^1EzP@?>mg7QEcP*4VJxWw!N}CI(1&;RBq6jfStR@ zYPP=TmzNXIf`}dtx!!g01D z*Bb5R-2jv)qEM(pmO$TG_}7LCtfIs5$OrIaBGR)n?Dc)^3UZ-?F>o+OJ#}THk!ti# z1|KO~IWs$=NRuM2uH7EO>f?gvMvr%#Q>;&W+`u$;Yhx?Tso_m2?;9Qh z4hpkzIdy8)!W(Ay#NU;O2t@iQF1ozf1*bcUPu5|o$mOrL7v7V3JW{B6pG#-3He0=6 z>D>e-IWr;mf=k0ANW?c&UsI#!JrCeXmt;GBM&Ja#+uLN4pqf}F#jdZ3{I(qRf75P) zBSG$cX>p&boo&42Q`{Kw`f|Avt_ZM5g87e$gPCw3rG^uTD_{GdciR5NQX?;ln)w7v5xXo5teqX_$}pm_;@AXli%A!Z=8EU9D=2TIX; zUWf=}%MQ-c105z+HhQFQm&=MdwG2(!dKsn1@OZM2DV>OFip%AnaN@_UU9mIYQC}u5 zCic%MAvJd`&u|Dcl*q^e(4x~$$x6zm;c}l^C5&soXmu{mzTP- zy`bk#+u*P-v)Xc{gHShk|7C)byR!icIa70eu)yopQx2D+Y-|i9^awG_yQO)ro5KU7 zH)R*5eN@@zen)&7W<-?GRH-+MCY89Dx*I+7&12YYwq~gjErDWX-vSxH)~*UtCDzhr z8&^PAmFqYN)h#S7#dKP&1jKp>0`3eA&S|t$Pf{G4vQRmtybz!1KXtJC9O^40N1TRj zX%zuid|#5vYjAUcNa}tuGYtZBV15+i@lAdrBrJX^kU$(FXew@Ib17Vy9QcLt)0%Yil)RY`SlFzXv7X_WRa{VkzMxRoL) z&RY=L_alB^cD~hD-Drd(^zU1%vRAE6ovM~$)Y2JH<$-Q7^u0iLQaWY_BI;kzIoz27 ziqKoJ12r9Mgz!dHvJ(?+f`;yMEm6j{SKqD4tKCmXhQWpp1E(wI*8ESyZhtdFDVBT8 zg6l$<6T1UBQfTbc9mCg=jG`$PdsutB8ByROn_zp*mgah-y0tZnS#z2Jv(XXkA!BNW(R)ABWIgfm^MyC1SS7Sq-3nnE|`4<}U&RGw+2) zV3)Q>Szf*W5bD-xRa7Y3*{6NuW6pMsLFU%h0!(?j=&9eZn(;~aqa59cbWjHmAD@Pp zQMN=MI-M28o}gxAZK@h(gKRqOo$7Iz7RLF?P8pllaPZ&WwvxFlv4(`1Vf|C%`DaC8 zG8oZOrDHgMUaiG20`2|?MJZ#n@)B(Tfzlvj*%6S~zHFLHq6YOhkA|seckJ*1*`rFP zrjpS|U;=4YK_9k$A$2?CxGJV?BVaagW=85;833HvLM@4D3MpwAFH42mM>HhwX@Cm~ zlRLh|-7L8+L{3Z2{@LS{uKf;u{qnh*39+7}al^^JamF?nGc2w?a#fq6*EkjLc}1?R zWcLJ@L+BWU=kp!TLZRRW6ZX&n2EUYq-8DauS;IC|H+d4Q*h(@UwQnHQ>1z7eNt%d?>qhmGRE+L9YF|8m`STtP6S;iAU&m5})wIZraHM$DFJ% zNShiD`r83!@aIotp)fX2mVL0VjFOj2XTA@bP=S8IA5OeQc@@IaL=e{y`11?Aj##4# z7-ZLdGXO5POis#~H-W{Y^!zkuC98aDsHHV9kS&ds;=hXk9KNk-Nl=8?eUPT1Ql8~J z<|b2)=(cAYH5t4@WQ*eX7`X&3+C@D;!b^rs!lyd(c!Nc7sK04235NfY9+gjtg*6F6 z+~@(wnw@>))nHd7W~DX)Pn~*e&QWZP*$s*fy*th-{0)J()5H1c1wdA;xLGteopwHP zg+^u!Q73!O%Yt&tB#wMXR)6HZWW{71Q@jr<5CYsN9`j2fUS6kwu)+1L6 z(3ELk#ZFC;#D}kTNeRvTs_lIwY%WP0W#@?^-<}tzz|aQ`-pMxHG=Ts@*nju z^EJGzOL^J8NBb$stNRV_(2#GaLly8!Qr)iVC-lLiLDj!Sr`_P(*UWBBS4 z>EAD|woX>tIQ%f7la+TzQc-xGZsF34t%+Fv5(kvCEYNxhawq|!GCAAjcl}}^L383) zt8ov_f+N2%>l}LmA-A_1LgGYY{VMVe-oc771`?=Sa_ed78{x1NGK)c5JwWaURyQIq z@f!1_YMyk}i1TYsw=dJz-7lOlHY$qaEW?D9_KMVROLI%%>c2iVXJraYaxCqQ<+(m_ zrWnnR4iG|9?S#IXjH3FOBl2>=$zM%>%(!$BjjihBxlqfwA%)_T@U4|SF6V}aqv5P) zvscD8;bVN}jmvl$J3r!pjnUYT86d9)2rtnlE+s-2FN=?z4 zT{?4qx6HKS#NJ~S)){6q0G4D~ml%IQvBDo1uR0q=yR%d2e?sKQXY!9H;feQQ#uvu0 zF1jPo^58jbEEgmHEdtSB!X8I^>G#x&NE11b_@~TX%x(UW&U)^7L`2=E(s3~`egRDk zS+~%+lCXicNa|md6$_2|65L#94cmOO6k(vW-lIkAWYN|jPdDqdQib9%z*X4iEMFBX zW6)*l0ZDvSb?hVE9fS2s5>lK09Q}3yifvkj=d&j3CjLQqFNi6G`@|}+fsOj3o#T~w z8CM$HOns{>s_TpyCtG2Wy5lF0_0>eIDhif^T-bgBtJ!HvX}DodI{Ct+fK1P=8nVmp z9ZJ6#e&y#cjIq@erQ4s$dd%J9`A%VBp=U1Gx9N=xK}dsF>UpQ-H3G&OGGinUMke(x z@1K?JU;86-p7!^1fVPLmmSi%<)64cVd!gmSi$df_ttH+19kO|W0WwKPH4M4Krp(?_ z$@Hfo$O}_#8KwKr$UgSZt~Dl7@J`OFPMdidA>Y!9r6c0nz*VIT#@qos?3F{6T4AA8 zAG$2mbpRPbrEPwn*eucpWi zo|5k@&-7Kk1f)&(!_wk4)ZZ{@(oy7+%{;W1q5cp9;RHEdFL*wc^0# z;n9N`zUNEIm*RChw)Y|LWW`r~eLE-=Pf<5t=gVoo`R5~o0RxNOlL#^QXBtgv zY6q;PU*YIuNzUjf4?{L#0~4*ahj8Uieg4RS zKuftDnXlK+Ey+oZ<-~=qf+N%toLV%GvwsBfprRA?ynEpF?@NDgge7-k&diK>)UU71 zd%_MC%R;kC{Gd->zm+48kTf|$ypL6|7@>lnl7Y#~MBTQtqw`xYJI-s58&s&nI7PRk ztVc}Xq6e%vDj3(`a(g*Hf4fg^ouO~YLg5ZPtdpv859hfe!0vUmmubG=qEM9MCq|ZT z#$IvsiFbfp4kI?5A&X$%V5Wh(ZgB;Royx<4tm5cEwVTKfE>jV9C0%+R8a5rrA1_sT z+AcuwcAJPjp8V_|9o|3Y*?&t8NpuI`S;x)CXsNAF(-JPDQ5LrfE)Xzkm|$>errA`+Dm#y>3o<%+VgGqe8Z-hZp2?CgJ7{+}rN ze^NzTK$VmHkXfb0gIL0$Xeg)Vx3cC531}{Xq%MhQa3!VOBqZEQ0_V4W4?!CU4Tc;H8~4+cTN;TSsaL84auX2=;`jvv z8{-g8%Tpu3$7`Gi3{$!(w_ilFDt?csi|r`f(3o0105>EqQA~kr zLpk{YW>A;f5bz-20Di;dWI#Atd*km2*bo*0jUz}t6}TXBDGFc#2(>;d1kkC?N|F0R zCP2?`J0z}mEaIG0{R576V`306`axgZeD3AV!ciS>vp4;AYItC-;U2!hHH8fHe{+HT zb+THY3})4;5m4WH#Kn=X{j6CLK==VDXa?aALHTt73Gh^#H+y1dADja}_YU7|L|ykT zu0Y&?)QPbJUInWNN9ncg(BrT{{Ow&sUOj&{?sgzj!oUGSH3C_vBrN-cjCf4 z2^z5WQ|z*sA21j79)9Mh;qV9I?MLbThUUku?#E8zZ#5j8AAA~#`O&;A}d3XqQ=)bk~UrNk= z>rZ|+8NeuDbAcWFem#Z&ncV!lKd*68rY5o8(X9j_Zza%&ft&1u_${y4LUCMAJERo7 zmAkt;6C>0F5C9xpLEH}UY_Y;X;)Db(C@^=gLhAswbQm}Rzc0?l6R7$?mV@6;eJ+B( z)^*DnJV~H%u3wx#gZ~E9wLi_1-Nen`w!WW0ZUEcSo?HNb>|aJR%Iy_im=2ijQ!fs` z_v-Wag3BAau(yD!;py$1JXv!09KNC)QftvMM(KY=h_sH^0(1E>1ePQ5KpT&zOo;E?6<6tU z_GV<%swj%Ewo9Lzx;mM8vUkdZ`hGg#cYXDGc1pX4a}Ad+BdNX7;tRDXQ*Muz`#JOu z2U`{4svlq?V#4*#xMd1)ZtHj$tNS_Ot0x5w`3ioHaEBtEk#IWk9e&m zNkPsF;Qc`Q%<7D%J!pTf{u#omigS(f1ymNoE%Su~%Q)r*yT_;S)Gpe_=$RTxk}2@3 zeQ~tfU{}8GPdzuEaK)I;FI+Mqh0r8eAFV1gL?LRZj*lM058gQ)ldC2YNa>m7u~+Puf#S50c}7Zx@NHJ zrs#dXMrQ4wG?9tCFheoVdAWc(e+a-CG0K)BsfpC~FVw z?heF5hqjfX6I|ZkA$_bjj8;xJx#njOP}i4#p$8O(l^-qa$I~G`0qczP44&!v2X*Gm z*yrHF8ia6xwTgtJ2AC)+*+igD8rkAXd>V~+t;(0Drd2*{gYw4gC%B0cH^h>xyRf^J zR>umU%AATRu=FouDcEVSSR=2R?0b})2l1}YorvL&Xx_(b1j}M(7#W`Uq-)3@9|SlI zDc5LTF@>xsf@Xk;ao`LDA1g|DZ==iX2Q};Y&O^#?B9%B~i8s7x-0>*L_;9X#6gZ{W zx)_<5yrnpvLntJ8ts*`aSA0FdJ1KrL#z6DPYe)$LgxE;H?5r%YWvF~wyFGz~DdB5W zzEwLxb33?H$v#67VL{bJGqPU&m|nT1J(>^PIxB66rs$5zp4GNQ z9i6D<=kR%FZ*XpvZ$Q9(Xwv$G^vLK;kUv?eviQN@$lOx=-biMMFd&UMsc zdHlG%iOZhNRBJEV%-wuoGZK1z%E6kQT|I`l;C@KE3e^r}qT-J6rm*FD^uRu z`PQ=13bkS~f7PRRxwYcXv%$;%iHK%!ja7KM&R#&Ja0A1l)0siMG)F?? z<#gDHuh~y_`V4B`X#YzQ>RY>)KZrn2M$>7P5wO^n0=$UI6hCr!g^2L}DH)adA%w&u zY>XI^1uw{qHo9bqQ4DOxLnZujCxMQvYq~e+hK{yjT!gg?WfVF7L$`Zck{4@A?DhiO zf@i(+fhM``^7FEci(PMe_%3M;U`eKAk$%NaIpxb;ZR_}0#9@5Ojeo&1Qcp3`l{^WOyv|93wlB^vDxM)!zsVIssO}acZn(Ro)6E3f19zANjZ8I zw%sxkfysS;Hqir;;@g;*C6R3dSdrE!p^kir&duyftI3+leo%{`Jkn1(y@2GSs%i5A zpi+>vc-bsD9=d4ti+E!8P4W6ua(lQm0BL41?#@z%v7twR#dM zdipftzp_;c>qw;`E>JRW@YUF3xxNk&RdG~V1nqhy+7R*H?Qw$4$~+r`eo7q?mKp0j z2`4cx?3QoOU2SbcQf~2s6g{-92*nO}B;V9IaSWR$OQE#@!=&bo!)6D9fD7*p`wnmAbI^ksd;Cm+gIWT*M z4f(sV=J!rSvM?F75rM#!+-unR{a%3_F%(C|)pcVr?*Y7FJ+5?~PkUtUOV(-S4Ls4b zL^DkKGO>IpSb4X`k2{XJsnqs9Y-}d!v%%zZmndeHMV15`GF#bggPQxuH0L#9&$@Tt z+f3+mfqh*-!3$eI1*y%d`83W%-M4rxm)u>OrYWj(Ug$3#!v2+GW;yVB9BE%4f$%;S zEp`FV=`dx6mm9~;-&T@`9V>y)mcTJ2U3X3`1IaNpstxr}g5V)S&5fjwpTO^&Z|{mq z$u)i_?=mtjfX!FpEx}jHGIm}NsV$%pB1j!dfkmw>ig_are$k+WQQ+~c#4#-s)nA$Z5SMqAf)zx!-t4`Xl%uvYUWC1lnpx5OqWnI5!CemWWmY1HF@PV^V&b3t1 zdVL&(JmBLEXGPjxX=F(&57+cLK+iL+*_$_;VklQ#yQC7KT*A z%54CtmPFSnx$>^O)IPpi^+%t$3SjX5A20h(f8#?fWua^caVEXFtlPJ{EFW1=R@@%hOS(^=m`YN|R3&!y`34iOmFe)rb6@(m5sOom7`2{5I)m;l#DU zt9!rGdHxx-QOvFoyXk5dUu4~QMyAA?wvS<}i0^jm@IRy81y9AKlz21eO6W59 zlZpusY835V$UMm>@I&J16b_?6>V&A{Q{t!2(K*RP^i&lzAZrO^`)+IU53bctAAn54 z#^8%>S4+7X>J`ai3hIg|faumd=YvSJLBfFGoT;Y3QszaE=Ya#ci12JFQ2~rKjSkOA zE!c)GadIS07+ZGHuJB%BU{#;SviEdvPI^Zp7oNhmo#=c^=Emm^cRxX*ufQWk}O`w4A+&#N;bm2*f$Bx|+<6JC9sZhzP-$P9pNCjh)21Xj>>qTz_f}sZ_ zeE*bHHwtp#x=s<|v+fu<)qb#nft#&h(VoAT=|rGh5|z$Nt;{Qm zD|ysRI&O6av>>Md-xBUN6%aF=+5h>@Ylq0x5|@tPZwo|eyalJj+{nT`vwIqKjE92E z&+_oA+4^yvA*`20nN#hrziXESzY3R*<7rcmQn;<>K~lx}iu9C~zPYTkJoOf{06G!B zS(bg@b2p}7ziVBlvwU8c2CI(x;$(v3DSad`KWZ}9z~rO07_E6SQg_*CE=b-#_me@1M0 z-9Oyd^9rP<8I0n^KBuaJMQ(mvK_e-9R@z({1Q@E%IJ_)s`G6?i*zwnTPA55mc8)#z!aaTQymO8C8D7d1Yq~WFQ%+YFc0T za8hTX8=_Mmt?`d&sS!v_V)_KOxQQcSa|M4%O02PZq0Wll#4Zhs++{-a@y43j$Iwl$ zUb;F^#i>nXu18)bmF|>5uwDX5 zP^u@Q`{VQYy)lqJj&r%^t}cV#V)&00$V-|M|3xa#nQ*t0$?Ht5+~7XqO-E4JN6YEe z(nN=L=!#6WV40b@@;$^DR*!g?vWMVvzwPtw2kzE+lA0#{9;g{(d|J4qOEWQkn z4ns7C$hh>$tfWTRh=VK;h;*7s2x!1@VipL-z&fNEcTxzM*yRb)(JJ7SZHTmMTJS4i zFnqNu4j*X;^yMoK!O_!Hji%( zjHHI=1dH*j7w}+JL9D2BPm-Ftq?XTj9$aC+a5ndCki|}8a>oAfgS9}^bvsJ>HBd$z z$JfS1q-6}6yRn+^qbJ=9VD|=VNObV6BT5e$)X^yX94&zuY}=5j_~p1`L(iGe!#5qi zA%`WuXcQ~#RpoM_y?a9MAror>JzhmBfV1hfHN6ww+_x@62QJUi(9S+ZX5A{P;@^$d z9l~AHC3jfb_1%qtGf^%)d&RgW8aX+xbLKk_^Eo&^0D33$x^aIl!ipkaRcMi(py4uq z0vc!~t}wfg;GwNNmMRH(V%+>wOj}}KY`P;851K|j)eej35_FVcSPKvwzG-Nt^jvh7 zoW@Gu=JI4b4eE%76Bk%S+a!ar+kbvy*QMC#7RQ>I4`=nbHo&=}weqRkc%&c}n2!Fm z%EDV+-2)-FE4E6Y-`CLN{m6@s#-Vf`9PG1cKD5=4zC1^d6)H=Kd~IVii+Fn3FxL%f zZ7com1Y;?1cAwmuBmEn%%+=XNRH$+$@I!fAXM9Z$$kM|f@Brmm6D+m-aHcjCuW6EM zfIE{BwdjU3XiqX5Xi#=dmAISK;2(9d|8zgwNosvoJvg1BN8UJde#!EXybYg9_P#2g zik8OsX*qx0juiuy3MhEhVdq2e6X%&WZV?V;>{8o28(V zGYR>mWKUkxb?%^Mtl^IYwaA+)2Yv*X`{YBnD=hZF@f-qP#Y!l)i-$hp;cVI*3{y1^TKI;te3?YEnR`S_xrMT;`Y#qpbs z;>0*$HAj|A3{>*{bcyxpsOK47hkGq&S}G#Jtpa6`fu+}m>PouL;?#MtMg}I z!x=?_3G(oyp>>dcLOUTxXrHKc%=*{Z@Po;pHPZ3>OHFi{M@!&_$JZpAG)$;Kr^TJX zPrRa@4u#=Do@74=QFfj?jy#RWYAd6yK2PL*vl?@5`0 zrPqsKyxtzT#HvhrlcsNVhCj46jd$%c%&??GbuZ()k7Kx~&QgCll-Qm@-Woo}T+fbN z{rqh?o;W!?5MjXy6yFl5&I&GZq0;ze*UN@}w>{i??DOgGrE z9}g?e&`FdB=z%E$`*p?=j_AAJ8Jd?G*l4F5HwMp+8|Zr>GS#8XOs?5#g)g(sRY7y6 z8|cd&p1VtlVtGk58tvMcJ!P9;7_*i5WQIp&?; zWQX5+9r%u;>WH5t>yuIlzo}^Lc&>n`r|lzKX%xIknZ+}#Y`=MYK&0ukhXH9bA16ti zTT{G{Vt;rSz=9`-V5l53lY+B{HgW6^AVR)u^RV&i3MON~fRhV5aTAr}z|Xw-1QUHG z3$=LgqcCm!0YZm=ETHFN_C;NJeW`e&Rj7_cQm9EUy2}>y{@ZJ3oh9Y4BOQf@igKQ( z_53Y4?y4t1PdiG-iJCmLCWzc%;gg$K?%q`*T(lSb?@~RKM8-l-AkVS93U8Z zAayoM2qVGTyY`H7|M~x@&whLc^{p(b6c!hd>IC_~)h#Z6R{G)yp})z6k7>ugD6+J9 zdVi>|30q1m7O%~9Q9?xWTZ>>(M2xkbsTO_G{-{jl&TA0Oc%{lcch!nf0 zxw1$x!-Zra8M_utsl{L~ zRT3jMoV(K^C?Fk-2?pBL!lGFnVEo|MtP<4SIm@@ujLVxZMYk@qsvwuN)JV?;VxS4T z`$8O<)NP{lh6d8z82K|n)UNs3N(GUYw{>>=-u1_tyA_RLQ{q6M#-*mhbIn*`nu-_o z^WXF_VX;c)uhhb3D+%Pxb8H@#g*7qj60TTH@(L~!SJwOCi45C32B;M2NQz#Zm&+vW zZZp1QV%vj$J|@`jS<5`8xONYZ+JArA=!H?vhcI_3Q)I$01WB-pDXbWL`LVlgWpL`d znmfu@=?T$^3Qs%wEh=meojlv8E-X0}rB+i^#OJ8y-YqH$w&wL!{oHGg!V<@ZYQb@6 zUpb9i-L9S$uZDsxziZX9=`c4Jp7cleoI8U9!dLV!)Dc{?&5xgmG#y>ioF>`W9?Q$^T7U* zqa}JH-Yzvgx#t$xc)UD!qtw1PvDkAa?0y(UK(qD~(BQ=m+z&BTBiHc`H@0Y&c+v^`<~4n5q=_@qY9$ zkPl$_M2z(~t4-jryG;yq=PVaVGd4L$p$-qpFRaiJ{P3r|l2Nb2P@A+@Na15YT<4JN zF|9c|-jBct=no(?y~f-^M}bzwBX5UT*1GyNiYpP=gXIaZP94a2LwW(_ai5Nj5-!pa z{1}=&&%?QGw?eqQFZ!WS1uxqK+?I|l;@3Y*$!kBH7oZ^4{lv8716%1~;@=@;)*U*x z=Si}*E_%@?kPox}nUFMPeyAKwhEyxfg;3F@Rkk{;k}^tg6^QcE6scEH0nFibd?pf} z%@xI!MyrI&jK#2Q_CxORJ5LEa`ES&$e`yLMH*mFjs zk6Iw_^L+pjaOoe@=?}oV61U0!M#KF1UuYO61~%sZ@GndR>}+i8|2g|_8is>|`Tysp z|6hXBlYeO#EA-N{YcNo-xamBhvuoQpKrjr;@VpLekTX&KB5V)~5RgKWLLtF+l(_EG zyUc=<9;>Ym)2cL&mxhNeFF$;q=ytS@VA4e#8fcf`I$)00U_eDGrgwfi0CaSCaCCGw zFrF?}5L5VXtr&qCXjg|2e%uhhg*ZpRApI963xrEu1<-Q{dFKXj01p6uUxQqK26S}) zj7X_dJCV{z27atVxH^zhdjOQY7=1MuPs-B76zIWqFjxGOn;rl%Xj1@radH2v5)S@; zz)PSy01hB!eg^E?0Uu%LI39jzOF+PZ&Tsp^$5k*eC#2)U$J^Uo0FG8iew|8@v^4-c zgj865LoM8fJ=+YqM(K+aSbJ*Iz z)gVC2`f(fvISg!oL-RKwMB^K%t`_jNAcALt2d|KvvLJwZBrJg0-@)#=QBYv@prlj4sB5`9Gt#bD)n&eXCWb-e&mPO%l_w*HkVjwSi#H=IdynJ(NZiE z%~mG6%P$jTs}Fjn$N54Oe=FdZG&F%*>`|Jqx6Woix|AF=C zotY~OQ1QXk>x)4Bo0uLNOFfDU=Wk z0JPc`^4bQ#ugk0J?+?J%dm|@yPB2;{?8~fb-xvrK{5}5io&P<(_O*h*@U@O$+MCm@ zocB@y4aV@rbvCT+t&R4g*ZXth@ndoChy8%B`<;{cy%S};b$R9ISlom19TtQ`@T}Xz zaxJz3>)HcGHTz*=|5;Ox_gb^10;napiSsRms-OGe5@+Ao{BuG?SY3}GS6jphVruZP zGWbcl@>XZ{j38Faxrlmya0a9g?&$Cpwnd*Bvh{^L_~c9DM|Au3{fVhKJO^a?W;ECO z_6kUVjvj|T?2~aL=M8|r`z5Lw$m0jcLlBw9Pl_qxyr8?Ki3i=f}MN zf&66(dWZyKujxyOXu8_b-_T z<@|m}+5H>%o3yhhfDg#w2hul|=ob1*ZlC*yw5RFN?Ou!^`zLN^bL(W+`N!4%GpDl6 z7r2KD80s6+_hINE^3%?;cV`TLJNR43SLmhe*M~KD$=H2w=;0f~=Q7wkcC>@~c-w4O z`}p{LkO2Yn3Z!K)Ey+V8%4=@QtJ_z&M;}wNI$|Hf^=&xrRi~Y?(Uka! z*hYv+x=+~`<^YC2R;4U5FUMOGnF2*_v0s&WeK;63-58|rYP%NYO=78j4zN2`izrrf z=x;opO_D_If$Y$C^Y*)LTE2`c;0}hJw4Tand!XacCo0ogQh$5#0qLk71 zsL;n;*=MU_>5nj?L42M-HT;XM(lh$qydE+KD3(!>;QYx%ca%pzO;o=a^LW+%Qhx64 z9Pc%O+x`m5(&7}4u}PUc1U(`XoF%Mwu~^UZ)b@COF+Z8%%1T|8F&U({;m@T79;QSV zF`eeI38(%rLYrpM#KHTfM3;60Dv9Rfz@Y(4K<4jSC84os>Eau$xFy31>*wWMFk%3KgMno0F5NCR#f zOK!tJAe)AJap5gUWe&kk;qMfycAnGHoweI@8}ds(>ams0m7oRMcnj3HuSfJWd<9=m zHrvZ5iKnmVS?Iyab7g{omb>vwMAsO~lI}3Oa%))`uVIP!v4=FM@%K`b^>P+xS=A;Kt9nj>*SS^x?}FKkTaoJG}8Id z^hn=+VTRZqhjj2_?8z?iK|S7UeJJyXOxX*p2!aE1(xSRz5hs_rHvK{sBZ zXm$W<^(t}Gc^rk4S)E`R?n;mM?Gt5lZcO97W9-3EdFT1|9|yHa1TNhuMiPu@Eaf64 z_EO_uHZ;v!jMj5Vr5a&p$yd+FO~d8|u(DMlL(LOBMG>;Fmu4zo2SrrsInGpbl7ATX zjP55XXbgn8oHLsfa9k#IOtgs#`b;|Fij4g_VBXeV4HY&|>!m&|2Yqob`^|FSK*iA6 zi!5#?VSQ?mGm2dzU!y}^N6M%W=&IOkh3MBpF{ta{%j*ft4aKUod6vQ=o=2$$?pNHB zk;{7L1h!&Y%rkxY@Y8h483Wlql5eu|-wE%VZ-4AXBaO`8L9GO-S3XMpM=DNgq_Ox~ zPgG^OatCa`)g;^~|>nH&tBrN^nXg7-A<{s6DX+ zS=E@jLz{Jcq!Pr|H3S(u+b32j@g(3biFJ=GZu>YC6*RrkULP;d&n~$*X7gRcK=L_0 z^&fu|->f8Zp7MdLC(fc-QEZ1A7RO!YsQvwqK{OY`72EhPsTAK!g3Zhim|Hg^Mx1s)TR#Gg-oB^yu=p*PFbLCO5e200 z+KyoMdgmNNai2lR&JgITiwjo7R9zL5N`*xQJd(?xvk&VcqvW^;Iv#-zvqSr#41Td6b|$CEiwjQxqVX(h0hwOL+6FZmiYzB?mvnW@-DcEen0YyGbd+e@P97c!Ciy#g& zn|DOiq_|=^podAT@M)ldA*)^vGiLc);zm{yC~Bpn1h0JMv6#OxwSHxEk6wu zkkw)U3h`yNIyzmIbs1V4seLYerZb?PXY%n*t`6bJ4AdtJRQqN?@taw7)7qiYZTOcy zrbSZSfjnp05JNa`tywcfthjy=8yP?^lvD#v=C7!55Pz1V`ekKv78U3V{D7ul@1}Wrm-=#?D z5`(7a&B+9IM40FtL2$#!s~1sEg{(IKc*!EeTrsT zsr}{@ms?rg6pK~vr~qkPjvOZ*O*hSA|IUQ+g+)p-pM@=CZnA_2VPFUV8LhLC+ilM9 zj-GeO%Om_t09T;^{%`StyETLxRP>2|+KZHClRS0>dZhA_>5O(Y zmj%6df8dGXp~@nRkGGiE!zUTspY`%uO!o(JlP?DohaD$5w-%2zMyLKhf}PcM03^gQ zrm{T}R^j=g&A!RIPkO$w3$WR`yi>IoknwQuL-_CM@0<~ZgD9xUjxCRt+|lKB`@>#= z*E7^!lfU4}E&BAmvF1*w=>#kSn=XWwYkP6lKSRYai0?`bR<(_q*utorgk1cLVOS5| zTl9JevZd?RMQp_btNg^q{BA90Cf1Z%D5J2bO|}UTSB9*N#TQCxh4NtSI(%To?(*Wa zLgGLJFkn?#OXLfGf7&%K!!PujYhT_ zhfcbp!HhBQz0vX~7h|p~!rB%j55B3)?|v5i*yxE=HtF^?UPJdu?$WH9D2We>HYH;j zWLcW34z?cj4~)^u{A zolp7c`PxHuT9r`B?h0Hg_1)@q;7e_Sv6ABkQ5=RR(Da+>cK2d~;D^R}QK0PhOLj?p z5lMw%`d9^j5oLX}z4l6cQ;znY;5R_-`r+YGQ6CD1^Pe41mx}+Ml@z|Ca@zwEp#vhj zT7Hru)(i zF#oh`%uT;MPn}OmZGHejGudv{TJH=Pu&mg^%6Y-Ed44&OYlH|Ma(T;`V*l)3#_L%# zqQ_%v*GXATu(e5voF4HPfJ2j38gjJ~H$l{j8WrLFmkRp{^R~$KAL@|o^$DeNLNl0L zBZegLqc3i5A9|C(&S(kN2*dM%b5DRx>lTl7+3l}e#V&?uEv5RmK+UJJvEK^r+TFt9 zeEf;P-W!NCE7|8Y5Jt)mV8< zbc8D_-sYHL5^`Tntn!p_+-x`0wk--bnoF~ecEL03KJsS#*%Ga8qXY+En~SUiK25;s zZK1M~srd3Cjb}BBiNI)gv2}mXheGp0%qGhP^g>P|@JN1|p_}=$+)@6zX*MO6A z`WT%F{ACW?U+8~aFWnDvOZErS>VL;3M}tBMb3uI(IQ8M6Y7lLz)DJG%KLuS!_mHmK zjQxBo1({eIe_H)lN8*%C)+gZQ#(BhyEdpsS@DS#B=QC`N+xTMn965(&2XDA2sE2?} zEgg|0w*G)q77!R(*m42@%=LgbHj?Vi6}E7H*WCH>hVl6rt(kfyE&Fc|6*)?Q4z|7J zCJzEfWNpkj8)||D+CIx%#fGLe&C!xatUoPmh|4SNSf&vFab;$Q7aL?OxUAgx#uUDs z2eMlg-ST76WO*G|sCx7iOvc?&H+n^IJZ5o{0_eKotjePY4AnUt5BIG3dtsqkwED!$ z3Le?0Khem8)wJiI5s)t zf2r5VO&^dW_$rYI_{Tep*V)|k-lw#%O>ek}JX6zhjX3VKtz#)==7c$nE zTC}=b-(_P+f)~LBEw?-bj=G!G4o9cd$}sAvagsxGGRg`pJ(06g4cSdV-n}gBw@JJE z*2MsRTrKp?+o^ikJy|b8M%icaGO?)#3*KRNt+~#Ms%_@59a^p3=^F;as8&`EV2C8|kWySan1?80xBH z6aD}6q!^;1S@V}TBJ*i1&Qs`#A)sF*NHM=~L)CC~+P3`h#N;s#O)6x#P?APLU&XY2 zDq{-Oo7~}kR>1hD*a&?wVs}->o_{^bkuZ4zUMhHNwn~*eZ;PLjUhzzD>N-<;I46+= zabWEd#vqZg3T4Qz^JEI|Y`k7OCyOvX!y}5ISGmM|JI=w8v8hFY3bp&aX7j?Lrkl4Qky~b)GgSN9!8AEh#JeoLAhViL~0qpl=3sT|T)#KC0^tR^MwMk#hSb-+esf_~xj zh?<2{dl+3y7n)GcW1>D9sO}n46xF&N=^B_llKU7x!njPWQmwK8YRZDN%-?tB|Z+GXAfj;sjQd zPyX=aT*H&m+4+S@%Q0R9GI)S)moQqM9(16Q{C#p3Z=vTQCbv*62nP$~<{04gA7FcT<^lgoB7##x+|6 zE6!gDjx`#VnJbNR(*^XcY2nrQ(Y9m$peQ2#KuTHI^zS^*{!{&kS7XO-TMjdv zG?hXXrT(Bdcvqip+@VB@zoJc=G)lnKlfA^ich^ltsaT$X9q=83oqWR(b~G0vv0c_m z(6?xoOLAgKlwras6SlK(|A$nxv;Q{&79IPR-6I3V!9rP%O&lwTRSkQPYJ$Ta=SiSlQ7U)h&eldN&2V#aPTr_o5$m&&b-mm&+Nbd zRNZrr@MD+y_}+En<{&e!>QT7Vptfp|P%Rhh+qWwvN=QY-{8AVN5XvwzJB78&W>bTw2L#xi2 ziS4<*T}D5gTUg^2uqlZr3ia*D(xbOcdSB!5lXSjt4P(ffdJVl#px`)lt(vMg*L2VS zPt{k2tM@ZVo)6~r61Tu{b?d&QXU`gfEDO?IGucKHVNH7^grS^HWZePLE9A}hodD-w z>xeSJx6_0NP^6W*Ake||u5Y@TR6~~h%fP*fP#;t|a8`_ty7N-_n%EIHl($dk3}r|N zkd4dz56jwX3RGv`uF|0~f%a^F7bs9tZ?;u=Yt}*8gtnPgc%L^QZFuiE8kOej@KF6W zy~r7-KH=xT4K&|#Io;QEo#Umy{6(YP!xSpByh!y3_vlnTe6I`C`|+2Xh&+$rBGcD7 zJ#Mv*|Yu&{-9Wa>36`N*b~*VV42#i1+U*U zVR>_hqK#%)p%_>=NS8y>?i zA}(-R3#on9c$<%X_;*}5rDyC6zJEEhP7ejf6sj5`cD>9y^8biX`Fw9&>O$>K-9Q(q zbWe2Fjk}j>SSEwjPWF2C$g(4zQtHDm9|aNWjnTqCv&`5PjH*{F)liwK%4=i{DypAB zn@HYI+9zg zBiSsmxc7z%NYZhKw8O}bpIW@zZBh~Rsy)TKSUHj_Qs7HwX3*T=`}Y4*rB+pZJemSvw+UlkA94OpQ$>>`WpqlD$ zdZhzrZV+7T+3w>;m0;1*(aw^7yRm5V0#>EyrVMFni;y3@L8js>Ua3jMF;r1Iw~LC6 z5hKQ1bQ8ivO!+xpD#CC!1wFKh+c1+Fn1}Jry*mWkj^aEj>a6+G=Bx8ZHH%88@xAt4 z7s?HIMFC1tZvC9H^TnvY2LHq&w-h5!_cL+wHiD&qWx5DHUtq;J<{)|BclxtN4t<7s zo-$T1is!<%{TS6%7XFRCOOg`m*^8Bugs_G+ug*jeE<%y-_9@TOYu+hn1=Ufl@txeX z;FkC8vbYE*h9XqKTz19@IaEFMi9KrE;lTS^p`5 zw%vwbEhyBQiV^JDU_%A0rN|3?sZnuz^A<~vhfiJK7r!Z~ywwUrTz~?DjfmSO zZ!ObKuuifLovn35F(qiFB6U;0E+5a(Eze~PMcDO>N`AFU#z@rVBfRJjLzW)F*!fw} zpKjWu-Tyw-`gd|Zhi&Ms>yv2m1)?N7-k#|3o*CbCp0ZG6I@-xn`usHUa(L)| zlnHWiisd~$UWGDf@$WdUi%A}ucRAPd1fLY=Kqb6xsdnNXc5_e;B`aJ7?j~P`lzrti zZ8!cu@ovxaPFE&%Pf`wN(D=>Z*2$pWX)f^<>ZXY5|8PPeUs&1{!zZ?BKhhAAYN+EZ zC!Y9)JRR{2A3|)pWonwdlc(yswvjg`h%{#d; zVuYiSFJN$RRF!k9o%lY@U%^z&t9CLl`;^nS?O{(uKB+$*=hdSS6b=GHJ}1 zZFf;=Fsr-WAvy3X2No@v>Uibo-V>A`)fmPGHHgOps1!4d8V5Wq+Ka(GyPH?xUOO+1 z2sM&*?$&8h&Qy9muZtA3JF_xwp1);b}Qf)YN`@HAa&0?spa-yUNI=?UFz? zTCvClp60r4Gbm;>vM4)d+j_7Lh90e1#F}DJe%Fh-=J}bS1bd29WfD>~nm)=+k7lu! z;Lg-=(r~RYJ_uor9Z^vecru5uNrXWoSWJEU{N=pZ0ZXs-`&oz_zlFp~u|(sTjaafX zOY2sGLz=Xmo|5h;gpV|pubyqA6sStM#Y40W-Cr>vRHYh^7eN-lufG@{@vMC(BCb`A zQ!Zdc#5Zw3e-NN)BtsKK+`PB+AJ)tnIC6Bl4zQYeqCTXj6+YH_BMPQvz$D;m381;R zx~bh)Z~2UWM}B=6OyipnV8QBobT z_`9TY?!cD!>``mKrVh8|%5Tfs8M0Li1;wI{9P|kvY(;s=T<_69jRQDm41BmV18Xin z)Tp-3$Ao+N?ohI;%F+kXl~QAm4!FdZjh(7lYwFf3kk#F zRdtE$u=%3)t{_y($CeuNj($xCLbEh%pne1!>kX%M1=&R2HZ2!YcqMQ@yIrm>Xx0m+ zqy^jn7QcV7`UK8EO`U6}SlkF)T7{F|eImD%2rNm;dld0^c%0Tuc`f;(hpN~n)w%8N z0T<)D-hGRLxw01y^vnxrwJg9H`qaGD$Y5{b)oH*6ZPiY(X8KN+@xNpkaVI_@{Dr^| z;6ZgclX$759$P)qH$+?=qJE_jT*JoGwuV6cHl7m~n(|DY+sUbHh!)cemPO{Yrz)=J zisZ}f(ymdJEZ~cB7Yb=|HLYII1r@_&tN;?6i8gd!9+twF>ZaizQytoKHu~jynt@2X4*Y1o6LafJ z+V??sdd)^0b$sI|PGSicSY+}94Ks2^YR{Z)*FA$nPV=-zbtgaZRK?2fq$R&vxhB#z z@jwGj$mC7P94bUvLXGZ73(%FX5^5X%gt5xQF#r&8sT`7GS%$q%uo>!U@j_&wxV5J* zM)p2y3r;?^#1v5? z(Pi}trd%>ynUv5;u@#-gFosIi6yZ$^>TXZ$ml24lSNg*l0$E^x6H1uE)qF$5A=MN6 zlerCP(gpfV8dabY58EET^p>!RK;aaWB~^v}l1c)L%wEiOeK5{T79_VYBfl0Q(Y_#0KkgabY)B|9i&N&uzny!M=c=`nJRU7D|6!`dO$NMSX zX;oE?5{kst75~l_oEsSTJy1}DzBY5aIrjI_M0_<-(fw)F1@l>bEeUYDway^7 zz6Aqc#}xiog^u%oROpzw+5az~6bBn8_y4NUadL2S{J%V@|34MFR&ce&Yg|r+=>H(b z*Hpkk_HNKpoW)5NvB0FQ4f9g4G7+Icp+v;nc_dO1Y(+#Q$sjT^-K+%O`MbY>+0XpE zCVxRq!`1JOo7?s^H+Zn4Yo%5vbhHJ1Atb1D5GtE0TpXBSV552_BsdI`!vhwv_OAY4 zn(_A7eJnbVu+)!?C=v(+_pyo8!W%AGdo+~7{e2K5Gzh3@Y3OL#paCFaCaniTQ8Wpd zLa=ACHQ?qTAb2#Cc=AIPu|NJyP>_bk-IGyH&02~ARz+-1EF$SjL1Q*@rMV{Zls%dAb&25`1{aJ z-~bNzxuDL$-*b4WQE(0wZFh$&F}6A-97JrEeY zC~;z6?jI(sNpyJe528c_Am30}JRs$HkWSyON6P&+Qr4ZJJZx18}=NcgV`%n#aO=iRGl@f?t^9;p)`lppU^^dut8 zXAt-X3$eX#w-5bS+$=a4h!<=c-w4)Ih-hNA_;A?ia~Dez7;X^P2w{|22?^-u{r%G{ ziZlx!=KR3b;pZ|{SmHy*vl;IF=ls1+Lm2oN{%*(|9SH>kA~H%EWSDFO=;s%{7*_m? z`p_`{LdqBIKP^B@JM*_{!zm%k-Iq49K|jFsywGVY4Ag73!T}fqe8|Z#`1fDv@A1R$ z*kgh6&#l_;Zn7Gmo?Za<-B-igFP4x#GJ^m>>mcX^cLY1EvjO{Fj|Q=-0r|z8!yX z=o!#*aig>)GER!`RDywo1{^FNFompz9?H3;fVq$0`ZbcYYf@Z*dm1b>=&r0a{7)9* z6b#}w0in%;$#P3PctrUz115g6=(kK=Vo=FLa8+JP4Gw6;s8GPn2(LI)Ox#&AVN;g3 z{gsggR7i+y68{vWzvT?EUeb6xAip}33W)4i^$9l$SP14+3Is@nM=}{G@xhP`0U}Us zHi-zR#3w!!nCRIxG^WBmei)eO+BI~l&^6u(n+T8;iUd>wh<9R!pG|@SGV_Xe;>XG( z)k9nClS0Wr^oe&0P@;ni3M6J?LR{^05hm92(uG5V@C@4Q`jw^oko?M-0UWo7fUJMR z9>}!(!iqaLTp_o^?h^(+5ZXkPBe`pCE7&2Y?9W1mksaEd&9NG~AdPwS- z&`u1)_OkE7OanAO{)3S4F}2HV0rZKuW`9BeJt%ulj$E;JJ|N&Jy{BrQ59#q}BP-(h`}TLVqoGzGOR?zU1q>~9c459{dX3SbY!LfYokHoL zO~;H5iLi3jVe2C$iHxY-$(jiw9K<#Zz&JwYEt#(;*u*0P~5ISM;cscBjZF_C^eUZ~g20x>}MV0`a7$)Yx zkPx@Dto^Vd&;s`BHQRs48wDB1C)CynNGQ4%@~?_-;bW*-pdaOZS-Mb|e)AFw5zXI; z9g#^53>+`LVO|)dW`AM%XzG1Sah*M*i?HO8uY?0!a0&M>1ciSX0(Z~g)~GVF#^@&8 zg37EFSn5BmNzvuubelq@%G#mDH$j7(eg-CoGhR8v7&vwqnaR~UQqn$`Ahk~DdCvlG z>~;aO$M4G?Yz1dQz@tTVReQk8O&9q&yNw;|+_s%kWXPk4Fm2JHCnbX332hdHr^svl z9iP2`OEZS%SNPuKX-U)(s_z5Wxw3Vr+sED}Ny__zU5kRWW%DS$3S2GrxZ?y2F(;4A zVL@vq2TKjVSRKk12F`YCQVHSp@|)qTIs$gchrZQmiitQdS7=-;&6#t7$JcJI`F)T7 z49eBffdBNf_H2a8syIg$OU<^2p%;HR*4O4OIOYE zSF*w@rJgDS>xd2120m|a1VMfq{JYRYCmCwN2BqW)mc-@_feQzJrTJw!SvQv5R*`mu z_d~$6F?LLt(HZ$Bt#QwDtG5yaad@0)XHG{+9gui#w|eS{KODfZcC5I*-&}-#A3PEA#{SHm&~@^Xk&9Bh3I)BKnI8Ys{Li&zyz|dS141>u2R};2 z)s0FKj+jOwDp znubq}njpn3hZ9(ptd#h5gFI7slM(4*2N72y<@F&jyYK0;%c9%SQo}e`#JVzdUC~q@ zMO`<|)*^>wb;^rFM{+k4O1^Bd>oBd6!5zwCRbA`Ot)K-gPz_>QJk@dwN8; zmb}1HSspu7ejcS-bIblXsMR74FkTe}fJ({=CZBZFl&Ci%>{=+SC!80g~{T z?kPU7u1MciaMffmkc&oKu=I$43*z+ojM9k?kbf7v?wcVTvX;b&m?pymk%mJgR8^pb$ zXum^TNkR>)KQPIVey5LDd7&bYAl4MqX;3z>7x&IDtF%pZhOor9ZWwJ!jK^(YG2_(Y z$1w_LwEi26XG#Kzh8mRvA4}nV&BeNa4ivCSi5&%O4-DV&-yO=+jZ`SD%9sZ)l0OBR z1O$1q$&7mB0e>&vg_$m8X>SJO9C{T=VehU8>&CZ&P3GLKuff@u)OcfuZaP>{NMvZF zf&Elzj$VfIJdf(|6ZArpDVw3Tv9fnpr;l@yH{5Jr;wRJKB%#8P7O_Ir+&t!ThqclP zMp94Yo4PkQ0^FxCA$Wb-Eyk%Puzao9*Mv5tBosZ&f0DJ$l-lZ{uhFAX`V?LA$V=x{ z0;nNw{r%}E#G^?Z#Ors4(wPfUSeKh`swqX@hR_7H>xC<$B98?5It#rL!UU+Ie%C!_ zrZY2zkyQ1Nz-<_64YHhM80v$`>6*Y8P|eSwUn7_6(ck8uxY%ys9HpG>z_h(}%(;cX zgU50D$_I}+O&e&V0Du4TOxns{>8$Gs6rkuad)bCkQ}ge%FI`_Znf{=kZu(6d-@>0u zQiAAGo_2Fhvss11J$D`dbrp#wVUBNutEvvEa0EBljg^{QNjpO3mN6KQWR_R&<^Kw= zw5weK=caVMJWqJ)osH?&%IQ+9DsOmxmo!|Xwo?>}`BX*+)dNGLgi@!SHIBab%4D(> z={;tcN;*?&cq^rZF1!511y2GYac+8K*eT1tQkeC<{+cYHCAF*DZRe(7kbrCIab6q< z#0%Xvn?E5aknj33FLNBt_|f^1Q+dCN#MZ^$u`l%?Pn>A^Fxp*P8OjI&OXw2<(eh_~ z9h`Z%xrTh=e2~|#$|w9KA}k}W%Vk&a&sNlt#@+vcCpE+nCCQ z?aVVK6tX|uB0L&h_ZW$JOEc%_{s_EiNQ(x8UPABzcubzea=@y^OpvLjMXYjrYbKa zA~fV#r_iBobA*b2^|vKG8t^@CcWdWnQk~?pcf9^&?r0d-O$oyqFbua-oG#5 z%0ExA{K$la%|G6aD#`~Pom3iT#3|mOF-#ffl`j+w<`jrQ^0Tx0wJ5K17rK{**XITJ zupSH^idVg?5hM)!c=Uh_)Ud?kc~d&44{9^4TDP<1SB8cMf@Q~jQ0Lj^KY_QsG(Q$6t;x0upLdp2(Hm`$S$ zC?GFqcVaQ%xr%l1tJ=?@{)LsnhwWw%LdiKtBj5FKrZaRFPQef7W1Yx=uc7o)eE=U( zaHobOsYHG-i^BqeR0{$#sWV{r@{JN*Jnw?EM5P>Bdt`J?7i95S{J{G&${(#qT>6fU zNe527rrNq;Ar_m`?ItL&z0)z&GRqhJOD!+5u1zb^FZnZW<2CXdz2O^BNh(Ngv3$$R z`xi7=+`P*u!FS#I9~xX{?Io#!ecBIkzentWhx9&0)^qCI z<7dz-NapK!BR}7bi-nhC9JC>aXs+T@b9*fa|!Q^U~*Y%YlscuZYWJa4&X}YE${!YPij% z9&fHL6iHyrLW>56ZRjW2FNeCmd+zf5d0^w4ZNjag0cCvSAy?A<4SLcXDogHFb5}wgnRQ{nU zmbT-~XYPffb>Svjd;#Pd)`Y)W?Ab_e^Lc_(p-2T6vXFIZ?jMml3srN3oakS-uD@3N z{dm)QNR7 ztW5kGI?(!iXpE?I<3IHmW=03Q5Xh455h80}MEwe_=e7(+uWIj^a^W(Z@3>$aL(SiG zwW~9M*Sj*-&Dr{Yz58+f3@b_+O)Rnx*A|lKzqQ4f!I}kpbB9T)uZ+dfT(luZ+;6jL z)P_3sVhA~Sx7+VW=+EvSA&qg8duh-I$<}ZUFMOvt2YWD!_5aIs=n<~x`!826bnwv; zzi$b10Q=ELhR7=B_T-A%A?3HTA))7RQDhbB-zoX$6FRSJ(lJHal<8+Wkm7$`6pEg# z+I(ELGr+pyV87}zmk68@xZ-&X>!?)^a{SSnwD|@;-d=cLrV1~Ho`>#E85pk38ROld zw7r<(OFL^wT-E=4V_cQGZ|IAUtlBD&mDS{fD~wU2GqmM2M>0Mz-L}Zp*2?CfHgRvp z5jMN9VDZBIo25HiA?$uSZd)3dnl5D36v#oyn?C?#w$I*7FJ^D+T+&E5<=GeW%A6VM>ZN8xqJAR3s9{z@tjVY^T|+8-PvN2+oju!kMBOFD z_b(bfvkt=)abYPc`%kpWf`)%&D4|A=&vBiWw=gTU#-?8xvmxl9JN!sc^ljpe+w{`FLn9Ei(>lI znB+LI-cFVnzo6MJO7984r_Iyme0AlFI&)t(oPlcGcJFxw} zcOVjO_fxbW71{57x3fgz^!A>CZgJQuKa->%Ae_(*P2>WlCP8R$!v*-! zGaVciZ_WAO{8nG`xbDad74=vBQ5;<+-Z^T*M+}eR$!1WyKyYcLzj`r20I9t8#X0?h z4ta}%gAqSkDeXY#Brh`L&mAeKDcMs!i4oBpt5RVgFg&>*WEBb&z!x(LX*$o1J(7f$ zq5EK-Pq4gvA;3_ysFi;zM+okRbMRwv<-^oY3Kmhe-Gq2?^nuVy3011IqFs&ET{?ep zVXx-ND4l2#Ljr?8vEjMRTp(~n02P?9l#$~QA0T@t^bz7&OHG}SICVY+%%0!*y*O3e zJ1DO@o1`OenU4JW*$>=f8C8a1gXz#}j)e8PqHYK4--%7a@Y~ZLvt*Vb z#HL`Tz&S`YHKw-Gj4GY(V!3dk=HTFw-XYd^rE{4BltN`Me%ZzBj9(|o?y7)R z`*9@W5m0uRQX5buB*I8z?*q4&_l;#O);+X6`!Fj|Rt3#s^Wo29Ho(MdJ>(JVR{HL; zd~C+U8mt{Ys>Xa-$>SkpEDwV{wH~30U3JI-t3tz&Q_(e zTaj5nIQJS29o;VT3RHmkh^dn0RKeB2jl&oHF=9A&Pk`xTDq-lR=s zT7!E`-5NERX#_l=3 zUgZ{0PT!rK`)YDNf69;rG&O4JMGwKa6zTW zbcVa`>RrO*P|g$~!Qt2Xm~^lvc0qPpM6``NRqX>+L^j)^{=)lSv|%gweUndrFI*|C zMt?SGXIRT4@STB{gI9AaEwZ2PgEs+lsWHZz^7o;ElG{uF9%d6q6pWP){vGnxp2{Cl zoDy_b09O8s$=TPQUrXz_e=Rwc`f|3@vOx9+zAd<2J^`FT0qSU`Xeq5@@)YOB-k=~M zis!o6VqA2va+PG~Gv;j9rsx*~MG2-`h^E)0BqNi;Gw6vakR>#QLl}D{KxK#JlkKs3 zA>c^+X_)sM)i6M#3yz=lVtVSts0!m2adE@D;n6g!b&=RKoq9QWh_NPDvvrcMD}y`} z^jMGAo|yDq<#TMqQMHMU6=4wVW(q?6!`HK_hR$Gy1xnv`mb-ncZWe!Jy~?9tUy8~d z50%h+d7e`AH8yKZOiA8Z%-GYGSU}-e7p-IG4$Tb0sj!-0Na0awW6mt@>}6wQeZrc}q!`qK$$@#9)x0Kf#*DR7zb~y_@2h6jjVW_O4n;{(8YW^A zb@Q^%U!2`m#N5Q#i=4>0epXCiqHQleVA`w3r16Mv&E3;x!(QaB@>e;pI0&y%89MHRnkg=VW0Nxi09KD)+k5z?8o7^%GOg?TgPj;=|mx#Mj7RnHMW z$?G8d^j9N??GQCud*5HJtcEl)bxa;IL#qk&WbDrYrm|Tp1;0Ap{4LM6_{*#2!vMWn z>sMOHo

|yNsz%cq9n4cMifUHW@A(QnClLuIx$Dd(|h+E4_E&SvA!pzivd1sKOg2 z^n4WyeZ5nEvC;jj5y|n<9bXi@2DU-oA1SuTcy9;1faM|*J3R|At=#PwT zm5pzc)@9JCwxsf;q@e+ZpM{y2GyA4G5?A9Qd~8${xFj4+g^eauF({0GYfB(G7x8JJ z_X4}0OnJ7~q0*aP2X=a87P!t7`opBV#YASDtlDZBAx+xO!DA91; zFHCRKVr16Sy27QmVEm1Ph#4K~Zq=`MA_3WbAZ%vRP;<5Z1xbHhp5YI#V2Yz{y0M;y z6-7L3H%l3nVcB+~`o}RBh;3aCdox7fX<%7PJQ$xpNO+5VY zg~#HPjD%x=3738PX!0G6^*CHm!oH|Rbw=vu#(6rU*lh189VN##QHt2Q*O1G<$Bc2~ zf&o)FFt=)CiV3^V2l1Zvm(7p1u~q{+H%#0+G_OrBXsoI|iA}dsI64m!8ypovQV{WJ-j5_^?}Iiz zA>xhS%Zg^1$?`pXH5rJ1J{DEZvw~H6=0S&(!*PaGwn-h*+cGvIpV+$0H=+-@=vM7! zIUcOLz&kj2DKJ@$v=)n^8uVb$fBR`^cQ$Al+f3mrsFaTa=g(%=?1Pk7>!Ul%fBQBaH?jkgZC#bhg?mt&%gfYp_%JD1K1j5 zYAw3TM_id@@5o_0i`MAwyDlVlhWKvw;}I`0(d}9AWLRU|A$nznYGa`DSyDKrY387^ z(cGs3HWjJ8jy&;k>*;?*?~{V00_kWYHfO^7$**IaV(+!e`~$j8s#~|l=tX@?aBu#7 zXfi`=z!Q+$f0rv5PUY3%&iI%j6$b^RiHxG!N@v%ZQOZcb!pey0uH)cOyS;rltPC|5 z7^RD4gB+jf8Yomrln;D(%*^qPDaC7Qemn9F$i|bNqMmPm9c_DK$@@LsXU}V%gYSx% zDDeme#8eWGB~WVGNTb+!bs?n&wEi9Nr6vnnS3y1Su;cVctzUpg%kd%}(<|Kn*UfJ1 z`zL}<@6AzK`)KZ&O*^Dnb=|OuJHr*Y&TE%Oyo4=k3IjIP0}0bdAk_u)lLYn7dW}BY zm?0M6y)4Jl-8bBH6L&Y7(~fnxs1MI-!8Fv9*UIyl7S$&TBOn0d>gHl@Y!BnL5%&tNl)JeA4u=YLgA&Y2 z*51|CWg867)Nd5R3q~pB1b+kO>6x*Iu?3B?^-X%3>+5>+`K!LGsmlIXeY4!t^=i;_ zi4DVI&JKZ$8i_20Vsbd%KR7-Oi=?WQXlx9@#M<=VGn+`1mC8f#YlMCqNR_REukibk zaCZRA!&kyWW0*NybN6B8Kn=j-JleooYe00l-E?~0)6+m278d!xNW?GQK+c7%YhZ=_ zP>Eq{fq02j!$hqPFGj4cV;Sy0k5GjiWx(}!cTV%a=mtwcF} z6Au8?GvHr4gut+*xd9ELz~mCX;^Hb&ejqE; zha9M8m%#2}(7Yfc+QNC*{knx9AZcWDpu5r`z=tbSE952*4--#dO~C8;6YtCvhwNHr zq;PeOFh@LsRNo~kDO?6P%y?{r>;e&B=^IY~ z@BjLI+@`L2C6FaA+&dK4rn{IL|V0{YF7Lw+F9M+*E%Sa8qc z&Wtnc)%p><{H{y<1+e_)9sjDI|F)4xQ_@!TeJue{e*j-Xw)JV7g0YzAJlwspK_Exw zSav^*>ab6*S2Tfg{R%6;tF(tue%O%6xJ{VSto8M*EKR@mki1gC`oa{GMv|tFeddpC z`iHOm+Clb0lSq(vx3nkZ(OK`mZw6)4YY)db&R+8;y9|XxQ{&t}?umWOXXfQUZ3xh~ zrjZl3=cdPdU_jT`K@L)k5x>D)Km>G*rZylh-?H046cV_Rhq6$6rIw6=)WZblufnb_ zK$&6zIX@D5KokwXB(<0&caYAYnP|T;?b<+cGyo*pKvCoFY=Jnrvv(@9&k&LGC}y3jAi!e;xA;U^)up4J^f^OSIW{P zxZTS&6R>;8i1H@tJpuZI=~prL@ZXJCl_0bMP5pl?QB>GB8j zix3){cYU+Z>Z)!XFuw}8Gi>9AI)Y)5$Sw%OdIZ-}18?3^i$v;VvP*avBB0#1YGR2! zxgh0wk&(lx9xE>`Wf(`7o_(#Cy3lQ=jo#QUshiI8wNp=7X>TxOPL#RHPQnqN5isn@ zj(={a@ZpTv0ZJ=PBa#`^HQI$OmBS04527+NS*el;x{+32{w7@sL;0(eEXz?Z-cVCq z#H3D;5h?k&8eVByJRkVMF$PYcJ{s;`@@vuVAXRj*>gn=j-zLS(aExX9Eea}|$v>QD z+}k)Cut|9&9G{8e2P$@Ob$6UCyKaSu4L%EL*uWQCQXhsW=M$r8jp9&=_HVjv7U5~U z{E(-88vamjNIRfo7sYggVLy^$-SXrrG@GsrGG%b-6?W8s*UE!3q_j&zhBK1hJOuQ3 z3!|)ya)luG2*q3={ux|pk#-o0FU{`zp|aHK`@jwdY+Fn{DX@cFI3h=;>DK(BU|Z55 zt<_B&pQ~o%BZ+sSTU?(B5Jg!yA&Hw32fvJ+t5y~?s`lALD4=*cIh6NJ{n=e3pXxGD z%Qt-jtI__c^PGITx>em}icvOzb9glA#O#TA`AqxIW!0VkJ-}8fU$eqDhJ9>*1J6Q? zD-=^G`^UbIpKTA8z*Kd-Yhh$2|6c|f`J6I^Qdo4>h$m)mJE?yn1{DX{smShK7wGF4 z=vf_*IN2tS=Nic|r(br;wMFjtde8V=@Z;0JzrpfRG6IcPDJaoEOes%fE%5mfYH zAiYqre7gZ<1bX#Z$SApgVG5H1>{yBXIefygy19|b7pC=lE+28j>v$J^Bz+iNCDZ?lH7q$I??gCbTDl+DxxAk3b{Z=KO{c7^o_F$#jyR$JiwpodJ3}C0V{ypYV z6bW*Rvq{mLEC<=su`IBp7zl1rom@tJI+21Pd2=Oh3!yo<65?Xmp7;KTAUe);FadVG zK>uK@*`Qe=)|IM!^S5z^lFO;uOFYkYd)}5*;dhU!Qi!Rm1pTuk=k_|TtK0q=SSO7& zrLm=Zvmwjes*Z_GZM|TYy(-&F;cn(G;74(_&VAv1_K4U0l;b(ebsKj~Vx3{}ezrBX z({CG*VcJow1F~~cDOc0^1OsyY5zE!4-8;U;9zSWU1OXE?YFS$hE^wQ}v2tIaHO?<4 zm!!*~rC+0jrKgp0X-xKL$MW=M>Co2#Hi-xz(dv{}Ayl=v$9f&1=x>;Si^`PF(7R(& zas1vffx&Ec&eXm@CK2=&dhaL(wU*+Ivvj2bT;F_@d#EdoWBM9bN$@|80Ub##A73u< zFsd*~!<64+MV-Sjmsn?HmZKuBUjNhs&(IRFt~px@^KSN?<7fQ)Z>Ow3`#et*a%ENw zPhK49)s}sk`r50lP3x-yfxQ~zUgm@T@<$#E4WB9r$67wfmLPc1Fq1`gvM)+oRHH3R zl3J#_(GGJr`|F8m%p4PL1SV|N6ZxMYGDL-5X5n-H73cs359){Q;B|`#R4bJchd>dH z;rxySvdP>xzx3}2In4BMmkRe`4?ZYa3G6_`0HphPs1O4^vd7TgU7l|3zb{{1JFfo% zCS?+%Ud1#;od1Whb7-(^ZI^AL(zb0|m9}l$wpD4{wr$%sR@%0CcI&pj#{C7e`_6bq zj0l6igkaa}ZvKx3^TVrvLP*UrHOI&nXh-?-^*J& zv#NhAVumBDl4S#g>Q{0)Sr-Ckj*_&c5G0D~Zr=xp6po&itSCw2V_cS%<4_f9)4E%P z&vwqbsx`#0vaE8Z+L1)(Zi5{)|Wfpm3dHQC=44>f%S2^e$`zVdEB)%FU;~v)!e}uTxrQ!8Y4ne?GNMzE)=6H=hK61#J1;#Yn{9tA&#(jS~RB`>2_8y06Sc z{+Ffws2-*pJCjpQH;AFGF4XA`!+#lB?@MZJeg2oA<(7*^h@J7!k+Fn^1aHhbJVBrH z0`PcP^I35xxc}(BZjI5ymQGM50ztvZYQ(Xo#yh9p{#>NoXFkLw;o50A<=*fmon}Q) zeX}W`vbIDj)nfV^ zT{3dskW*Z%CaX1cmd#{~K^zH!k=$1~{%u^=dZxu;$MM~U3YoO{m&nzhL&%;l`5Eu? zpL29DUO?GdWM+x+V=5t8GmH+V4)Z8d;dU;5iWYznv_=@xomYg@0+ED^PYuNYa!TiEHiCwhUU3+53!vTdU z#J07HPCddN`);K8VZp};ZH$GQ*h`J~9mwfUJR1}5zf^naJ2X_=7QI_$eBQo*PeuHL zhu`u@d49(c`QnGO4rN<2PB;97U~^Xuo}w+Jf%5tM4B&k323rh@Q5!JjWExevbV*PO zT!Zb|GeiO3^;gysJy35$qEk0^(dhGTOt_77LPp}?5)g1gB!a+LZjM5RRT|7+m0fS^ zf3?sQwLr4aPP~2*%0+z2;tG5-NWm0L+F68D2wwP(04Lvi1T?7(YXIy8*CC=9UHpV$ zO_{mUM$=(aPZnEM3D`rWaWaEemu?hqFwrB(?a2c#f}PPz-FZM6-I+0_YGUHM!1~(QW&)(581Np9_~mQ<+#+8#>{q|wh}ol&vF*uWI$y;85-1}l zwd=BI{i(J+(n;Spa2n&Sia0#aW!5vXb5v6^U)ONn_@J_c)v&Mc{Jw1$WMaY&!TU0K82IdMc9#oqjXK*rhm`^jbh1D-Dkuk4y3(f100CIdlkA{Rb zS{{IU0!1SI?+kis3}gl6Sp_e_zo4rvO&Mw4P0#ucj7dTU(FS7lzhi6+dn$mdb@CEG zprv`Z`6tSMqGPkc^|S^Kn-d)|t@KJX##_!}M$yM?_MN_-1c^>(2X)M2y0XtqKW8jU zP?nZX17uTI;ip%JcShasyU3rOrhiI{#x-ugS;M>(IcK zSCHydS3f=w(Fy$(3s;laj}eLSSsdpcVq}b-S8IpG*1LM}T6S1aNsOfdlvw=3fZhMt zQCiU;bUn5e7XN95Ci_8dWOswdEdi(M9T(9l9&MzUgJ~?xjusLkk!;!1K7vH9=k!GQ zJ=s<5(dXtalT+BgPpDt!ij=!^)Lrw;?bTowFZVVoP|qf+=XGk=>wNtIk$eo|=;l#Z zuEAbM$qXq*vMngM`>d@Hgy$&juIwAa4?DGl-L zmEkSB45P>#K_Tw^PRRCe;(ZstjG^u*gLhme#@F9>%f43B!g6+ zaY?YOQ9Yb!D)&n*B-3WM0SSsjBB%OBl(a}bAL8k0RcrYfR%M@dPTEGVscS#cY^`<= zMgTjY;Xy_yOlEQ}eb%u(7-Mgm5ftz?NBUwme z<_!<&m|j{oTEf?%4rkJ3HJvuj@<3>;m|8>*zYQH-vtcRk9-sx%$+8;UUEiO9G;(zn zIOGgnmH2jYvaw%cT`c70i#yNCrCrub2C@pEp}=L=?~{We`B=NPgTN*G-yY@2)}PD$ z^ZQohZd-a`%X5@=$$4%DC+A$g?Z$(Dl+HhQyXqc0b zTcph4lKWSdlMIOb80#Kx97oef1@`}TK71cNuJsOI;L^J$=+<~7AMP)C%%dUrJlwr= z(bnpS<&2H=%UL$s_)n5j38J1buiKtZm$&RSQxr5h^cnrZytu!j(bUnEP12TXwD|x? zi5~uyRxF-)zjprH58qCsqS5tQCpl%b%rlQ6%{SIUoVW}h?ULqjM2>#gdHcb}JzL3R zTSadtN$H6(DZCZ;e$%rW8s#5#7e`&p(CU|Vh6?%}jvE=M;k+~#fL(J)Oef^00ihu= z?n0wDCvEtIfF}3-w-~!aWfp9GB3rXP-%^r&6aiUJx|X-|ByJAyw9FnlQw227@Z;mv z@H=uLTR$aCg@IFN^+E0IS7BAcxzA#lq6fG{6BAVNcY~VaN&^3H|JR@2nqHeU*C6+4~Z#3vTVw@v-Gk91Y8j z$D6Ir$~i~36q@d$=y9&RYGO=XX zgt~1Y;ZjA)NY133ZQ(V|S3&Rl>v?vlp|Fro%ls7H%4A$=D7!Ef?L?Z@V6kPVwPU^) zB61HV<&3Fg9(WFlML*aqhvVDcKqx4GpEDGGVhO{o|JJEQ-UyF5gj#qUTUmVe3V?#p z9lPth)*9K}$`2^sCXugwY}OofwM*_UC#XHQvZqh&tev`>A)6{|`*^Z%mX4s^xxi8s zbL2*wj$W9yR`S=DV>#}v**FDKpPOeycg+%)ki{eqzw%3)P+sX(_l|rW!SCM@jB8WZ zvQq^P#J{0>^NVc69KM3q))Bs*B>9jOAv(`64^5x^%PhczP9{jhllZo#w*&4|#BZ#r zF;@MaGzlr{OieUITsVT_E=r{7u#UczpI!>bxd#85PBdh(^tiXQVJwj6Pk2*CU)w`^DBjdB4$Z`r1CB9GWmxv7{i%b?UVmH+uJ^ zT^K3lzm5M4`o-o=3!&%J;urWU6+jR>XvKBJ!UPhAT2n9|URf+ebfMKYw>0hEG!yO% zfL{txwZKWIC})r5Lw89^+!{R-?#KnLj(d=>gL4aKE5vg>+8$JS%M0Ut9dCwTjTbAr zA>CPio?yjy-kIN>DtAwW@b|=amCiumi}WSSF@Uk#@?2$QmtPxdD%8=LNxafKvAr5p znA|4u=SPebAfMHSL<@yNlMn=jivt}7$S69*_~M@Vn-k`FP>3v>{uA{c!{M3onXVi= zmin%W*hcS=$><764Zm+;fpF{`sz>@Y6=})smO^}Fx|Yq^GW^2T?WrdWPcQ^lVnyrt zBn{OMjr;jaR5dqd1$o$RFSLfEpK=4&;mkoQ$iv_{Kx=`vKQZ&_#_x;~-g9P|gd|Ne zo*1tx_&^7-v$wjm#U+znbg_+NI`*n!F8H6RlqkBcxRERtaoJ?7IrOj(1BtRQviql= z$&kRKt3i?-lFO$5JLQvpNdHsOsWEH+B%1t@t)mxy)2oDn6FL8*M*fIxtO=+zapNaE z9WEY_(;Dmw`!t-<^{0;GT0GIp+fJsWlm_&!x-c)RG0Vr8CX2~^AunPMd{fz?p_~=GE$F}t?VY1^u9fjS{rCgK?Epk4 zB0{3oR8#4u@PRO<9a!s3U07$K2C7w*_^#>bDp>Juzc$@YLznaU5U_Q9>}<1|VWL~i zaaS6K2CJN9!&l5!fwkEC=;R8}d^uUZJyaHB%6#)A1~E+b&y?_GlU18w&O>oNP?*|2 zI?D9MP!eVS&`7Q*r^p|sm-oj#ib<6U%V0R|4~rkZJ(Jsl{ZBg8gONTN5_>RIC&67~ z{1m8sxo9g~rP80^)saue6$|B7IQt7@JH~NhX-{kaP5j8BB& z@@{L(=%CFmfG2B}1i0yAan2?7$ek{kQSsw|)hw>>KLln^T%_{6!gcYI@UFPsiDnZb z@ypWylSSYdgZ_~t0z!h5C6M>r&6oDpYDnN=-R$wQXy8)h`d^VfwZ@hq%yQ|YXku=u zDeyZ725{%cbOTo4)Glhg^U~pNYaP#Oo28=xP2lv){5T&TA7q%PtH0-$@gr0>{N8Q30z5?jq80~4(pGEhNcclNOu7wWRMv`3BZ0;TUmj>1R z@>#@vJp?N9S&mP$WwRTUL|Aan7I@;8?IKD)VX%Kd`!WYv565wdl(oG3+llhLsS&2j zTW~tX2am{HWJO?>AdBTqwb09T5FNT#TbOS{DY&?u!aay^Ft^<1Bu9KA*RcldL2g|o z#&nSKKHW?%D5O7)HqnUe7u#uInH45+2}S6uhM81s5)ukf4`*DH@~ zR#-gAUQRgufL^SyObhFM4&j06qo>qs~HTPOcxFXu=}Gz-c9xlTU%I7wZ%N+>Wh~H z8l49gtaQgY1bf-xNe2z65_?|PIgC{B1vKP#L?UMP|Jv&?(wZ`H!SMFb!BW?8w=m7- zkcu=Az;TUNsnWf-r0aEj+%ffRLrb&Ds}w^dcwfvwuAZB9xjgHziaD8I_t4jcnm8_ec1|MkP3Z{&fG2aekK;D|yC90jn3zY^tJooOyb}sEp z2iQo!9?Jn2_H1*N*1lM{SNyjXI8KndgM~CzXk`bWulAG3x{$au(qLa(IxM5EAdLZe`IM@)-<_Y^)y@ka z0<72YT-ijf+|;9qwqV?zx~iA@899Amq3v^}$KT1u#QCjhBlweJYH*!?3*-(Rk?o;c z_$%^0)?B6%ALq=&qMXJPNg}bU)q}fWF5eiL=Hs8X%#u(tY5Qf`{#%W|?TVZ!Xl;AC z*7l;@sdl_vV(*ypPd z(LyjFk_j#U2@h(ToJQa(l`mZOJD-QL4M>Iry$4UsZH8p9uG@rVJdd0-Tl8^j}{lX9UXgB9o z%F`#%zZx;G&Mz#)wSQ}Yxx87=*bfRoVd&KH5_oY2j4_#~b*1vC4~t4xA-&7L&wIQJ zu6H!3U!bRFDdpI68FrBRkx9k4?^7}6ecJII7cL$J-ba=pjyfkB)VOr7gYv@YFHkr) zLSRi46LQcwPE_yW2+OV;E08LjFiaVNYtA1PwWDlV++~4Gu3yH3I zbbMid>AoBoJC?*r6}|U*^vG+&XM=dt%IeCvXEfJ^?r>p?SIC?(*%;0*u0B{h=+ob; zz8&3}#3XEU^XPhu0~aZ@L&LkGMSe`$OZUAy`^bfwv+w->$NdBi8170dpNpk(hjB~^s+t97^BNe7Pe*E|i5(+4+fkN~0yMXER zOdRVwBF!+qhe~E|0SM&X(&vhug7+%!j=tjuC1nl@Z<76+kyEF0_GIm>Jcxg%G&jgL z)3hY;^|?@xP5eSQ{e~cly3%ebkvN92y%a6;s$}%duo7gmOl7T)c5`hu%0)xeLd2Tw z)HC2rcjah_cZ}Bo?5M%qH6Z>qJlKsDX09td4IJH?DSL+uX#@`(8Lt}^7GlGE(Bt|Y zV_s?CmkP((8b094;M*IoOSz~@hxBGoHFijddRYAUw@zZY6%{=NtWCIk!@Mq#$pEW{ zS1YCBm~nHfbAc?%(&{rVq9ec7Yj4O=)nmg@l?o;Qu~8#LVp-i^9^HL&>&=hxOsg3e z^jEG`mTO+;C;{rA{Tp;s`L%h0(j5~?Or3h+SNO64UPqnCMl5N_e|D`x{)_M@@jWqQ z-PDt3b3_0$qhewsSl#6BSikF|h|LTH+>VQ_7vzon)sRr?NE}U4d5oDyCV;~b&csPB zdX<H2Rc!XN<|ZI>L(PWTXjbMfYz5`GX&5)$pqh+Nn|`A<$jl*-d1E zAn}Xrp;NGoeau|vzcM*n+U^0{hTrLg49PCGakayjeGxm4Yx!ZW94>`4A>3w z`_uUbulLR^6?sUkdH4D+H=RO2r`bqWv9eHqb=>DgNuC5uTKyWPIRCD3w*6{8+x6E7 z2z#3hF^q2eCN#_|V7m@m!`M+{c%0)yaai?h@X!7GF&t+(XDcaoe@z=fA^$^|lH)>& zp1&7NzT=ky&f!*fVWxfYT$>mG&IY0s@Vmx=z@0uuogL%Kb(+umE!5NUFWOu(U3=p3 zP!|RvT^cljR}mslgs!^Df;Vr*o*9)NTZ-m0S8m&No8zr(QiXPHv(Y$8=RGYyc-Rnb z*d9XpEzQ&$R0a*z5tBWdVORQXg;s_}X82u4ZHG?>1XvvQN>Y4bsXCKllvTxC*D_)1 z+Bqghi`*h;4@;D@evOry_?}D(ONmwV6aM~A zk)hpDt{ep%s#Qk`qkQzzR!jS=LjJIz#?JJyq6S3p4W8s!6BsocDyp-6_W3z+)LFEM z{_zp#rKUS>_2s8!Ba4L8#hJ#wFM6p;G2`|Mb4~8DXN<}S{hy__syM&I6)EV=+#eo+ zrB0g_hoLAVVYvNA?W%kd}*6rHn@J5 z-wxy!_UOz`-589^g}tiP?*jAt9=QiiL-=Hnxu3049#^Ph5c5FWxs-D|`cz%lUf={{ zZ&Z?qyqb^eS-tlI>Sv&CsFM#B>_kwa`u6^aX%b8n{DW!Zne~v+T|TR=RpA=6ml{G1 zem@)~@axlFX86$;Q*f3w`l52bPo3USRf-~vX==bqs-elhH)&NV^1imiYE@1N0z)=S zTxC%b|6FuD#X1b+1&T6fUVJ8jQQ4_P*+5xt+LF?D-5Y8rNDk9(dr`#VSUb&KkbRzH zO?nq40@wZ&or8M;h*4`-zeX|!IH+$guSGreS7;t(V7z$MjpxX&6fjk4^1&@r!b){Q zyl@;u;$o&g4g6cvV=kMct!mxNMI=7U{o2-4lJ6GW<lyI>BlR<4cZmyT(vvO{zlkHj1d*^o^j^h)#c{?xese?C+{h|?9C znu<+ELG*VT(~50I%%rT$WXeVzxTG8z+IRcbt7de@doEx%cm)X6} zuhDlj*R=_*-cL53*F?)%!!>g&OjY<*N#i6>G6S&F06`!>; z);Zbw%}}{s4D(w;F{?pb8BhGEB0UUY8SRZer7j_q*d%|9I~`~)g9mrOSCxOKa3`^xpal(1mlAvye|WJD+n*pdR0YE z0n{s1kQ7}-UD(Q#Sz)8xSUV88o1);R%+WU7lj#rt$pPRmSZ)n@PH$p#jyR>%? z+~xv3gU+XvFwd{+vPNLSY<) zk{v>Y>9f&bm*VG9gwyFzmxjAjqipVvIw`NxB?<0j-VD+_EPwve!XwiVWTI6?N z<$oeVOy3c{@WgZd@kV3L2+uy?g676QPnPzFS)$VM%pg536^!FIG)TwWX7p8E1j~|V z;z0$+5n>AvWG9k-El>f}T=^ur|HIZzVN^Q%O^CfKQkkbE zVOMlIGuW{nFToL2_f_c=*?b{qb|P^dc%|~V@&tWw64-s&V^HXllMQx)j$)f+`GR9Mm zGXPbywDa?s%L+^W4pOv>Uf9S-uHyEabK$GlAU##HeqPA=gN)wXa#HBmp7|;LlnHOw znZ&mU>m2`(28^vM;3yyZ6d|Frj48){aQ(slyNUBei}fk9Dc{9-Tl;*e-X_WIo!*Bj zj`93RhB=pDT-VQU`JW~ZPu*J&qP=$gvCChkQm=2l6al_FOgqxQ?HsEvOeo;vqw}l+ z4EM+7tKjTQIktbVD+)J76}QvEK)MAh`X1TvRgYiZ>KKz@#^cj?8AGc5%+T)+kiC#6 zUF^xccIdt%yI$yn@@JQIjXh;*W;r&p@{wY&5%u#01?N)f?QVgN#~X#9cwd5HWI^U6 zmTBqEH&@1|eetverE7<+GKCAL`+$Go{Lo+f4DKu zGkJU;iNH%ys`iO~#)qs>{ZsKgigHHna@?Z55e94Vr`DdE&KR;vuxrSRmy@#ga7RA~ zUoFvs_Wj2}9BmpvL%VUE*es}wKM&o){&K!C_uN}wJ9h066H!By4RVXpi&Z(vuuYYQ znwU!WxAR%|snSCmK%3blpk-ZBb@+xpNu?8Qt;4z144naMQaNHd8WZy>F7Ax-5gF;6 zr%&~xC3!T~vY_?mDk^xe_!xf|nA*c~ro)e~-en5-L=MlUNv&xfrg$EEq~z6O|DGlf9FY`3@Rg z|Jt0C>3vk{q-2yviJWi4yaz4CTYx-`MhZMD`wu0SB6{FDgpq_-rk2Yl_7w?CH=W%+ zkG*}QWxi$57@AoDj^n$u+M}Kr#e1?qp7U2L1YvnS^k>jwaI{Wh3b_&kWE;r_* zzQ-nM+|1}+Ih>Tn`G&Bd%95^G0{vNuJF8D@c5;8nFNC4~3)|@Jq{@M$7TblIM2@?$ zHI{K0>Bj{yNV~(tr~O^S*rlhlGfJ8tjLKo)IuKgU(h`VsZEZsvi5?)uwV-(zYCs_~Sle@$`i{ zTL_^VP48f1ML9|Vt9ga{{oqu!Sjo|&U2ZOk1}mBa{S}l6TpqX-VafrRik#)qIUDH) z*$)Fa9Q)n!C_UWbuZNQxTa0J5kG#nj6_UUwzHEol%rMTM_kIPy>#QVNQZ0E*Q!1^< zMWH4<_p_?~crx3*rJBMpj|Du8OXRz(;t3G;Wsy1K%D!~amKG~i#nC#|e!#&U0L?{@ zj>^|m9tG0MkIccu9D)>Y$oMhpV87JCgr%^51g9c0*RqIh(3*x+Js+m6C|X}V3tyGK z9_K04&z{+*r@hu$JSha325UB|YIWwX?%{aSQIBlj64iA(l8f-CeCo_Q<0;+bU6hu4 zYogbP#$~W)>9NoKvtoa8bDNl#$CWSufhZe$ca4KS94MkiGRgVl)V>DHbYUdQODpDJ zfx&+7y%{Eo1p;dL4OKY2h9u8gZbp@P=X7cEkp+j&SR$Y6a1RB*gw$thR(CI9;^liW zxjHoZA|$GZ&e>^gPY~2)0Dp(Ea}Ari7$R?v#QsktY0vFd0*-0t8d@ah4}7$M(u~$d zIa?fbe+-Lr!EQ+v3-a-!DBFo^C7nF0FAh&VFzYeD}0(YqLnjYN{zdR09ucEEbJ=AZ22t{iJc zUkgiQqv|>Io!amU#CQ5?dmC4$@c8x!VxsRb28qL2(h@J#xFuQ@%RS31S|1L6j9WO5 zo#3AfD+5IlBi#QOMSVV-vC^{Xejid`L+L=vzLX8_~}!hMy}*sSq!z20fPu z6wIx6s{HZMD@J(8)ljhU?hl13Xje$?dgyIi5b>MaZLCumza|tpLcdUCENun4s@cT3 zNY_Xla(9oOrk!Dw>Hs;}@i#2esfFE-pK$XuySlH-aTW3Wy-qF?BJFmd3^`M}Ya0$! z{2Vjcl%WF$S7O%K{uDM>h{0z;Y1Unv2)$;D{D>s`4#5*SrVjuYjd&TS8m_Q2)gc@M z6S5I!gQcR$f#({ik@=R?ej_o_=uzd|v@!QYdIEM6y8(2Z@rA*z#d`F~6#vo}<6#iB6 zVH=(>clNEINPrh(g!FK3fyKvrKC59f>YDOLW^FVJ#kw7BoKmm@v`qK7tYBIFvB5>m zEcO9}?mxzypaqH{s4P<#B^PnDNW|Fr`4@M@1(kF{A*kB z5uBV)857`B)ce}=+VlIXwcBP^vzy)X+Vr|H$2G@yHU0O4=K(PoP6Z5D{Qm9{gbXNB zOUsHFh)^LO0}_?c#GE6bAUof`18O5CUxEV@g#Mo3Kg=FASm-lZfRa@X1{k8eiyQb2 z4ET!}`Ku6FfKUJk67?4YF)$g3GLXjrF#w%G01r5<6RDAgSf@LIk=q;9E6bk_7}r1! zsIR@9^7Ymwpqm913N&aBhz@ZQ{~~$^3DybZjHI8Da`KaajI;PkkrD%nk567+UN620 zhXKTrVrT;HF1X+d*h_(fauF2zzfZ%?gL4W0G9HqdKwz#9ZT-AGBehb>BO*f!aAzAB zP;SBH?8Ao%Bmg~~0R4BT>Nm!q{6f%pL%!sa0akpK6Oo@V|rm|%ZS_b=S9Z=cUY+>@-UOvex74|i#Pz#Yh2 z;p-6+A~?t!SnwNg;aSKpf7Mxlfxj#8mwP4l7CP`A#Lqdpugveo`XK|b!xtNFc7Q+n zl32bf44A{0_R)!eAtC1X{x84uxBKL;{C;2Mmp$?CZK%ptPPShdm*3cL9^*LH$0T}f6{m_<*fu2G* zJSMDaLY>k55!_i1pV zaZCK43ZX$r@%qjbgtQ<)L%OVO`4+u6g{axQIf$M1?Cq|1nN9z06+BkKa9P1BdRM z5xU0h&Dh)Qmv>Dj4n0W;d9;X4fwk2=Nb$ZfPx#oXOrYJKTlW~O7Lnts(R%E-3E29L zM4BJO<5}j(w2RAbs>XNd+QfNex)D)sVGyULzQ!JB=q59WSc!_>TDk*1%}H2P%wgKA zNb<77^<-TgOqxD6)Kl=l!J{WH#kq^u0%ScsVjc^ej~Kwm@xA^9ikRD0epxE%bp(lq zoo^c=hrS?8+dojJZ&E%Pz`{mB;v58Pvc&rK7p#dA>tVPlj8+?9PnJK*iWq=!49XpaBG`P7U zP;jT-rEMhlDf`puQPD^FZZZS&Tq4z`l2ngtNrhFR1ljVLJZq}W?op7qw6WYT;t1nM zr{7o6Xs|ZYk}~cZ}ln>#YeRzRWaJ?P?6P9fEQDg?NJ4kDhMjF z=D0SA$BedUKYY&>GqY&|3U9M+>ypg)EO-Ov>29Slq=p~7kQ+iYoq7)lWgjE@{)VmbU&-sj0f-4f4x8n|Zt`r;Y zWkk!zeh3Q(()FpV_CcJ&z}|?G4D{p^&Hefu$c|ENQB0QMVoaICl=Af&Bu7nP+=9*2 ztxF!oMQdZYWb&{^j`x#-i4=GYQ(t>jPSnR=I)nC~#KsVLzqI)u@sLn|u;`1qII6OK_}qd+eVBhtt}?PFAqYke8hqk~Y!&Rhj~@(l5vIu&w8s2KoE^k*Gnx2+_fII%~TjN5fL z;MJAP+6M~c#A$}NKIM9TDPrb+2k|3OJ$idBu@0t%RS&|;c4Ig9ak`y_{87Q}k`49( zlMba!GpgE$qwTu$WHLAF8`gAsBw^$4^WyrQ;a1x2T=;O+2`*|o>&yL}5-njHSZz1F)ZlGBHV!LP&OL+I)nb|@H59rJ(j^<7 zvJLr`5bOaS$8{-$KE)jJ6Q8yO=}S@>o_I;B<~Ev#!ogX!)6mMM=OZN!X(~zO!dHQu zyX>Zc0Po7>6^q}>b+@|(_+^Jj=`E*_3kfSQYo%fhLy`bSlSvx!q+#6l3 z6F?ml@_CmKPNnprV%WRZxjmK@yzVy}rby?1ad~b_SDql(fmw($@B;IuDt}{A_RE+& zW>1dY{w!y@a*QhPU+tx8URlmR<~Kbz{e0=N{hR$jlX65xe#K#pr(036@fDOKIfj$- zu$`sfi(;qv>yYT{P83-jUmfC)gNla^=f-tr(B)1s)^aa1!!`Dq)TyV?c+_I`mr>u5b0aR=QDjSd7hc1=&w{}x zuq?%E=$BkuK1#P~`p$J2XMEG%witK4wS7ztIejOTyW#o7ff^6gO67+d`uh7*|cmq=8#=}EKVwWoV2C> zjQb?9P%BWO7)+U$eaca+>r8mk1vQvON@EI~*IBkm0DM%C8P-q5eRBhl#z-;yb4oSH)+6Cx-(Ad zIWw?v!PR~x*PgwSn#mn{=odIL_w6}+gkW7u>E}B4e>>E3RSS$ls|Vw&Tty@Xe9pi? z;ZqF(kAAtD&ahK69k*Ut%*MjQX3iO-MG=5D_{ZhCx4KajES>V`f34}=1Fkf}9dD5o zihLM=XO*btX8T=VDmz23Ns25OuKf;VtJr(Txf%j9z$&gX@7`#N6z5(fD=m$86#rZ< zef90v(`R^}$}Y>~n8)HZNvHC1>*X}cv#0G7QE^wgE`pHciZP$4 z??M)sNChiKJyFp0zN{Krn7q8y zH5VwfEhAxbk~JVq`(D}-^`aRfrf|H`r#o16KIm5~)#1g4g#k7wXFjQqh_Tr!twh+} z^`q80E)2odgOOOTnz!i(y)*n7voT)r1+k`1NHb8`%+zhG-wstEC5Oz2t}S0WvlD*9 zzP$tr;ZVh}Dr3(>20GMpF>uFrt&O$I<=!1c+Ag+YF%Wik3nf79n*7LwzG zJwb)9fc1PmBMZStg1x~y+Q3vQBNLzB=jCwPK6$^(9A6mE!8+X`eXWSU4Nm;V z=!#V|YgPf<8*oXb9lJ(#MFDP_|9zFq?5bkSAK=$P+>#)WY!YBu$_DUr^pX8_v6Cy{x_8HLXgv> zWFyQex;!#?vg`jQcm5yqj9tmETn|wPl%$D!$??i8ZBhAkbeGfa{^B|yciJTVBSL?a z1$%l~RX^PJ7P?{A0H==GfvaDd6#Z_fIMcnPhlbITo_9MO%8Cv$td96vX{C#ovqLIs zB?6;6ha9s8UUoWJ<}*bu_3sB2iVM?E7AnOJq4q`bG<>w--0vi0DLS58Z`Fht;_2JQ zrh|=x+%`_P9T(sw_Ywg!F?>~edjIsOiOooYlwyU z_OqA!Ry+DO(j0%m>$W8O)Y>%KP$D8{r#>idBUOUFD2k(8wyblBv_6(0)3+28&v}oY z*jKFiW5S&sf{bDS(+_`yIq*JNiHoYUdKbZSEdF|bL{2V1FO;B$zXfWn(f&SIpV!<% zS;3xBKXLVcBhXu1P|lv!8(ykTHypk7wT%l_kj2T-a{qc zGefa%->-{nXZqL-MdVv~s>jPsL?LO zA#7L8mx-wxnss~KrbPO1K`bO@8uvX2h*DOZ}Zg%F0AsAG`L zRoB>b_%6$QRriS%H<`DC8sL4Hn5!X5=5@H7T`uud5*$H+`uWMTQ$ zKNgRom2ogf8;{jg1>NFMaE+Z;qO%7Ft`rn6D+WVGb{5%AzR z3)lBkC_7&#=l*zioJl{h7a~&b zM3=^lM;gxH*N9)3qnp_jQ<&FT#1rDMp|cuoOrueSU{{(WAa3E$6p!YG#PK;c$DI&I zt*3IXs198>676BKpjOfY4ucgExhp)dDvs8O&F9YTbKSH=V!%;1*do;Kw6-P}*h%bN zk>1>GpDz~Fs-O)Fil@ZCwb^+QH<An`K0HMxVSsYS?-inq*P1q=G+ej18OGKgLefM>brr18RAmK`*E-!hg4#w~c$ONn`sV(P4_PcFXTp`5t~t1Swc;j>Yeo zKwVuB2wg23Ec6=UXbia;d4z<8O>OAAw8dBvAm%5}av^O?%c<_$j16<_)0s`s68NhZO<9I8QjeOb3zl(va#6A|Zx8ud z5c7_(6BHZ$y|9rG9gk$O`3WK#?PH*Em5B*=fTOjlfvn|j zkCXpHk^OU!kxMLO5uBbm=WM1J+k@hB*Vx6B^;E?*GJ5xBusscy>hdUqliJ(#`6Ga` zCAc%B<{TNxF5=9*1LV(oQ*(!iINv3;Ki@%z^j?ft*24wlhzD}G3q8UTe;Sc`?AIIT z;^afguOIQjG!TjL2Dc{YuJM_Z6`sd%^!0Kvo4*kyGeg`m2YM2F<`TFJ5`LKQXD)b; z_*FN#($9ubv_j4Id;-*K8gZo)x0+dgxJQeJc6L8Ry>D)cP*GgM+ESj-9edqAoib0Bp7P;M}{+(^COj4;ij!azqN`@K0WqHRnt%QyksQy(rK}o zs+RepR*ESu$&Wa8JpIV1myryP(|9BPRa+Pb66b*o5j;*K|bDC?5U3hZZ0OBA=pDj#v(U#w*Gv? z!Sx4!S!&-W2pP_{D^d`>9aE;Y`F-*J#XlQ^k`d#(3ffmZ2~ow2oZt>yV2^T?JNEh} zzadzuVXiB5^^<2&vacFEAMewWsF?^HPGw65UnkyaCq?sWIc*o!0LR_zJ9*DgR?}eF zem3Ccy~GP^f?FxnKslN!mnAPfMgsu_Wk8NwHdMcGiiLABRbGYHAC`&-4RObw;Znt7COUk)oG$T z6dQxNG-beq;0i^)gg)dIpZ4M1q3X=~HH8cQ(u4P6DnbnrK$0fCqG=!+l?OBgjdDt) zbJ%FPjmm3C6}Hym5>6A~r~I0*;QOWN2l~d6e{*nMzU4}l#@-tFmiUGV|^C>c@Hl-FKzDMhE{aRuZ$43x4KA-1x9<(fLD{ zGtDVa)s6fRj^AoRbc3K2Wrx1r7!|N(^?0$~gmAU}4T$`;L2_^7KK%r-N{N!rXw~!Z1<{St`9-fJpBv86q>@K4Lp>MEsnvNSJZXGhq~j-^ikNO3b+kPw(tl77 zCnT}j3Nx7P55F}py{>~|Ath6qdYe%U_CXXRJl%aRN14h!tu%cI!m(SiPV|ji^j3(| z+bNWlVB{|U_RSK#q?^h04-TGVi|pQHJ11B;!SGjAt4yd<%*xnt`m0+qRNru&#Au0g z8JGmVN-ZRAy!|mDmCCC~y)2g3+F}*K2rs@QT$BA{5{HT4>z6Z>)CN_);KQ+9o?1AuI_ld2d@^wyDDzO&dAaT19<=BvRG->&V5M zDJCCYpARe8BC!UZ9E;{DlGoRYb@a10MqQ0dN@5ec+e#i@wxzSy4IOWbd_VBQ(AXLVFkT>XM6)-^x0p z2?^S5U&-Way&EqXNTeqt9tQ-AF1MHcbJHG9S<72oMT2zAG6$SZCcXD7=-is^#2Z zC9oA1qQNRDrCvyoR;e2&BBDcqb@C8hCW881J7>_1cLd26q$UV1 zDAj(>qIHe3Ps)J(T!D?Hy$>H$s?$mNEAw*k`wF^o zjTt&oIcJ1L{YEiINx#lVr2n29^?D!q<5T5j>2`Zqz%CFp-({2hzwrbA)T%@d#@0Xh z`2NEPFcUFzaQ$EP>OT`J6EioH!lX3IK;W1|lI}P=O?{IW=-XQ#FDe z7ykSSA1eW7eS2eRXLa)QlnLwsJDb4*x%&F*nf4C>AHEWbTQ#Tn8ITm2j6QyI9&Jux z7yz|AjdOeqFrYpQt;xx`f?QwM)zj0GyE3d%{3T-qWgbx7nv5=l4*|~I6)+9jj|)YW zy&ed-ib0Qsx?7#Zc`4Tew>~(wK7;||!yZ^QCxW@69>O+8bcW#b#Va5#hf!>V76y>f z0;CL~zT7xK+|^(Dm%h=zc@x=>;|)<+Su1jTVTX5cjA0uZpn^eY7Nct9?d7LIP$S+Q zieRyze4{v>m>Z$8GX#(U726O*^kq;?UeKW{B9?`b_OMJOaXv4Z- z))vq~T!Zs|Ym`>kFf86Y?jCJ|ls0gIT_SuyFpSloF422(8N6G~Rw6a{Il|6K{z`eW zmcVs7VR;aHB0@$=LQ0Th5RlGHt;TP8;OY*+Q+V=s`+Ft0gMxPj|G;4-Y(jf0mW z466Ad7#J5fPjC-E@cPXmWONphshz_GEF*}nme>+#>dz8P2N+iPM~GKL5O z0DOO&-;pu8P(fS)kiO&Jo1|pU$1D5IKAMmEeGd;6IRhx+pfLkNgK=RDEi9nHJoEK? zfV{C)k zDfkoNCRe10^5nKESTPqIKK%2!1%4xqO(!{IjrHe+h|Zs)n;;zOFw5uE5O>SXoC9DN5ij1;eA^%#jeBK+ z$czDUhYrJ^At?Z19}td{eq=)40J&?zVNgRAAnv{3Naj~?-k~f|qTkz`6^Qu{27kjm zhG@_NzzL{Xd^5hKtiKrCQM0}gzLn^6jQ8)WgwFd5Gk|0t3C0R=8yTWztn|b1fpC=j z50)P@0EObpdH4YVK({aR*|<1`$9EH(Jo87wuQ75Mu+G5g`BRGm^B`dkcHtR~6=SkG zx@=Mr$+1d}O*}f%&@d`_eq~e%n}5NXOt>E>i;p{3i(wpglZS{J8&l1H^Ke_y+-`I+ z>ChH=)6mMCSmQD0%24;{#3$?B8tQJIMp}T^6t4;*T{&*u>jQ*J9|zQv=P5r#YS%39 z>(scaeZjw@J9bR*69EqlpxKnm#PS`=LEj}wy5nlv(eIib+~f?O=bm|GEN>|FY$*@= z)u=_!GRKsD+!V|G#UiV16Y%ZQLR*x>_7e(w3{62FrMfQ89#9XZ$FfRc+7g~waP(5u zpRInG2>2O99XY?W@z+6$+vC|6ER?;pe5v>!pRv)FB3h(s*_OkwJ0~cvKl{;7y7`J{$uNrZ+(9=l_mK5 zlKBrRfd2VSnr$b4x^LCRAbk(6FvbXNA2EsCl0_7X;w>&ba|W7e{yx9L_IEr8ypRS% zJr7}a6E-|_0sno8#Og7ZGjZ?$1<><}XrSjZ_|DGAUYb~2JM)$dVUI_7t3c0m60kR9 zzdh1Qt^Cdw$Re34t6B)FHASbxAEB@q72odze9`c$>m7^Vb{#o_Kc_PYK95~KHRt6= z$?cBr$-O-139cKK8F&{DS;$OHyRX6fEc_Z7{l4?@VlGx}_l+x$9w!eIuu7KIi5gtF zu`g>N14$jX!qRKbxH!mg$RJASbUwgXPU##Djpb_e!)`QY>w?M6nN{KnW`1%~a`URJbm=dSALssSN5i%BnWNg}8m#Np@E zZ_d?BF|0t5hB?l6;95GWMbS+?6ckEfXLoI9vfzpS@jXod%;C_Je~id13=-9H+pjv& z22WA&9$);$tX+|2txsAh*u({QF`_;qzEg^$=;CbY;E2Hi&Z2~raRP%U@1lg@RK=?G z&gbGkI`Lik;FlXMN?cJR&~P(k@8WQt3r#E4cXDczZOJTl$X7q1l#T^J`^ixBXJlWw zzPlw)^e>;ggT)WNbqXxISL1(0Mq-y}wzNTWl3J`VB6x;M3TnC23hMT40tN9V|Lzrv zsG{N1$~Dv9B?EO|44-|WF~_5htFU_tO(9pf&#$b5tv6KWr=R=r-p_|T*4sIibG=(D zo;pSs0cFCB3@phvjEU{XYDNxk=2Pp*&Tetw7a*<{LHpS9G%Vhsj)(9ePR1@&ex7sz z!PCv6ts1803opO-1wL5gf?V1u5Wa?{l=mp?m5P;|l2u1dN~jfP-cHwJg!t0>M#()h zzY>1DAc`kB+RwOK?cZFBCEVpD@qmstYh5wBL%D=s$)K7SZh-uFJ}!xrzemB}^D6Gi zI^GUrRMEH!de=7F+wJW!Vw-0`?Hobt6e|o-nYV+7gAZ&*Ry!(&gP`Z+uC?Lxec7`@ z)Ak8v_xN@boN$L5dpyLA5yupuoSPjaUT@SvoU^x@1f7kH-6NwEdlx@;kzw6A(ok6} z#7H$w(%)a?AK}WqM0CoQnTqEeT)`&a9aW#+jbcq+&LHKB}Sc^q|fIPYi%i_Q-<1G*( zhy!6MqXA7Eb(ya6liwUeNJFi}xMt<(J^chrkAshgQVLyKrGl&KE%P=w&X1O5I_DZB zb}+0A(w0vZFxoQiW00qqxFm+n$7jfr>A$6o=PIdQvY4|E=@4XH_=~v%sVTc~s_pM;Y=5q1m z5a&b~m|8uc3cq(P9h{Xv`QB(7a9E)+V z)JMGbl!TqRaz&(TvpSiS$8#OF|5|QR?2kXcSA8TLAL)gjmY*t%=(YB({SRv+&Yt?A zjFDWHdZHELry@An4#b+DU7wY~*^kmcew8Xp#)RTDQpDYCDXT)qMFFZ8FV&s6VTWTu z_N*D#sQOy9XJRH^wjV{@78HtV4!L(rBgB>X-U9)kc;Ju@!K%{U1d?D8IP%O0ZHKKX zpTiuMCuLz=%NuhJf9H!a)5K)95}`+2BB(5o$PQz{SYYW~(sRhcK6giKbS7TJd=yRj zb<4eMPR~StT&^WcrmGN=*hW;~7Gy8vu@W9smdJ4Mp~i*y``_#Pw(e-ztj1o@sjTlX zJY32`U0*yJ*c;^k#rs7;GGdkl6myzGXzZIj|B&4(@lGxaE%W=*yBejY;#bpe$##6t@6n);8u!28vW z_gogGMh`7DaHpxigr}+pL&=JcsVvJ5&7ouCkb3GC_kE#-K$@w#8S0#1iYq<3@ezOW z{dV3+!h9z2E`M*mxLj3oWaFJz>H1?8FYjH?^y$0Q2IkYAf-*$6H@sQ4RG&G>^ugPK z$1eXvXGhs}dAZ>vrkAfSD~H*J6rfRj+;RhH)BxJBzAW^E(qx^dry`ranW`sU=W~=q z$A13n?O5o6E_gB~LDP{Ex$Z@w)~c3DEO7s4L!cZbrsfXDE!5V`9x+3=qW>!a^fVi8 zg~*~0DM@a{5~9O{{hQ<}1CtG7y#!$nfAA!&t@@}ZEo>4E$*V|fNA;{P#Zk~maD6-) z8c*0t;Y7Q_#$qnJg#8#`YRwed)8QE(jdsG+{wVdL;ztD^~Dh zDxTP|T|wDQ^?O$$;EN ztuC+W$DD5s86PNct9McIrsILB8{vavi$3F>XdW#L8g%IF54oI_dfrZd#_UTIPmS{v zn!!A$D&d-IR9kZwyY%>1Te(2hrHhb+#N6lt%v+fQguiD|zvB4tr-YvcVfJrTZ~xNg$VY>|Y`-@6=Zs_Y!6BbcR?-Cw<4kaxmuEW~yAsl@?#~=HdWKB7E%-&P*MAAO5?6!t)9oj-43rCLag$mpEyu>!olT8*vuj8^^9OeADs>Jaf+_zMpom#}uEhe-&@CD{=-NJ!*A~ zMty(t{GGz%%GAWmhCaUzoJjKTkiBHBW>)r zrJNxGnysYagK+D}fK&a$y6QQ>Ai?|11MFMy&Y`wPmiX^!NjJ4Zs;}%KFd?=8?dHeM zY0UREnGI=}>+}U3tWZsIh-&iwob$f8_0&Cqt(K6rN>Z~OH-LJ9*p)~buG+uvF0)v* zPdC?3G8OL=L}jZ$c4>O z%~5tI+}Zei(o62AFS|tZC;Y{VB$6sa!Y!0h?yunxm-P6@dPYR|nQ09IgY@$uKjO%6 zS!?Kn&c?R}t{DczcZvcBD?!RZ%D9?TJiEz2r=mE1Q(nld^geROuW6Haw%Q4GoBFXY zM6RN4%q{;W>93T6E?PMVSjS>Y>Hg5>O`uXo`pp%ix&Pb36{4W#r``_M7$?@)Z0g@h zgq>{1<%AEmm_Z1Qi7#xV48Cb#A(z&}POvM2nPkQAQA5S^VcM?hk1DF6LZp0ulKar? zWEov|ZX1ZcP;+{AimpPP_VOJD-C8F}*4^WLZA|#^um)+WsqN`madu6(3Bd*YCF9T`qdyc+Bmapc*@w z{J1EYa~m|yy~I7pBh#YW+4Hs0O{r}Pxgw}-MI&rX+`c9z%-jYk3X617O`msycT#e( zf;HEoU!x9h0iLzuBI3 z=jWeYxEeVL>d9!h?&CpZ)axkZOF%m{m-R3!1Es)TJzczW87T=WB>3fdNHSo}(8AG` z6m=7CDIONl;Vn|ej0vXX6q2#jw~RfOl?$c7x7h{#EkDffp=`fBhq2*J@X(W~PcBS7 zVw$5je24k)W_?WfUicN|&+x*PE{||Og!{f|Y07BJN$nk>{l40z~vsubIsmRrTXx^Ti9 zg75Xysr`}8=4X%nE|YO`^;urko{^W{BBYKT_tqrAj&+8%(zt;@OonLT8p_&*XAIs( z>iTwQJ4s0N^gzh_XounLrxn9OmYBbPEdL$*rGt7~nRBLu6ztVFms0!7Z6k;Eo!LZ* zh=5ENp#TX%F*d*7n8kNwY;$3_@W|E7$)ZrHw|2I*zpmTJZlx3($l{sd84mNwU<+Nk zIf*y-E?MT>p6je29C{#*Fnp|i9Yb+}Do{Y+L71qHo;HQ44lRU40*~B3vc(<~mLN*1 zLmGM&pZI;U7wK1t7gT&MrKLUD78=~==!e_X$c26VE9i-K{5Nv3NK|bC2bC#L>LnI!SiNfg3cxh^=Z86-G!FjWJmEzGj<= zmsL3va>PS%-9(YeXrh<-AG|mp`VU*n#0QmmK%?jsx(dyeJOsY7X4Kjt>WV)-c6@df zmYQ4G1u`Qu(pv_$S2qD6>WMxLG5eb%O@ERg=czigQYr&d_q3;;bDPUAL5VcBRGOYX zLs-@hyaQ5JjOhVyf#>^FjP2~vQcc>eto@ph_4e@x4a`kx&lo8m(XdB?PxFEn%bu)z zL+UW+XR?^KHEO;H{<`OKuffZ5G%{?JoQV#4S69B228UYr?m$!LQHKC?wloua&Oi)G zh+FP6`VAx}f`qnZOIUs71A&sQ@Jg|jeA14yh|@_Fe)-IQC(LpYlNY-A$_NzJG>!?z z75tc;n;m%(FvHB1Am&yhXM(GpoeuKe{P_6puH%UTs`Y0&;HlUp0!L!m@!gNDS6s42 zh3B{WP>Y$EwB^8z+oE_H(E6u_bd4x~odhyAHceW~7a?ww3&rCqa|PImF%_AmVHcrj z5=P*&2nD}zPD0N+vJ11YObo-Vwm2L{SugNoo*IiY-5hZnwcF$87R+f>iavWFXU zRWh#lPnK?E^A_>5mC>lPr?i^3;e(C8oFv=Kxv8Q1Uk6FtAeGl%ae&t z%wfrDeyi_GzJ2S~<&Wk%0=3bQ>)?l!mGo3Mdg}(Ct@@h%CYy~+DY_*8ip3`s$efJR zR7h6Yj_}Y}Xb`4HAS-Os9f3b#G3GteqbN*92QeR70IT->=L8k43L~KQDF&Rv-S{hmU z!z$-eLwq;o8Z_FTdeK9)-`_`g=A4*PnuvpmX(Rk(fL-fS)$D`Z=<17_bt< zIrfYG&UI)sF4uPR*z}w$zx50W*>K)D#4xi!{+Xm>f5|ZhLG-w!!^Vi)%+a0Pft zkZ*KO&*v8--RFu@7no>{NY1aUYcn$nCAp6g&@9y;++uksf`=0)>gR29i#cVdPwgjD zKc^d`m-j>muW@E?l2;Q!qq4rcsly4lYU?Wc7pL<=%Wqqg#`v~zUmOyS*rv+~7cf~I ztRw_5DA^`)2k#D8eOC$X9-sPpblL(z!}oj424F{%Eq($Or_#}J?5Y}c>Q&Q-KrsIg zRykj9@m+dukGXcwKfQ;!5c<(P@biWk{IhEo*B$e-dioc8sO$LX!*DY7gc1fXWg^d# z$ZVKi&CQn;^l`a~d({^?akC4((zbr03o2>do%$Pk3BVUt>2iU^EG@Meuk-QCq#-nG z-Cti&YH89)VPN@*^PIPdg!4a>H2Mh^vd@~G;Ce;`SoHsD&aH)NwYYEVi#b{-x7yl; zo{UiTQLGCYPqP4H7;qWfj%VghRP1Hg$&b{oan^7I-PX;R38Z4U{;dkpwX4vl^1?YJ z+6GJR%-{YnE@9>H>8{NL+L7NMV$O;%g$I3OEvmbZ3QjIDvx zpIFSg$%;5)BK-4Fu%UVwwC`kd?zL6j-N_qjl)6BAnR*fUQ@vWxCco~}^EnLx-gxVi zkJVD=@H){4w$z<9tK`?bWzZiF`$5?=FHe{g#~*rE3x=flj10)b(*OJpOJmHgUPsEn4w4I8#~lmpjpGS+a^A5+m%d@ z#?4GmvqbQ^Zj=QniJBAu+ZDP8?5LNcNwsztBye5V_NFBBKmAmtKaH1v$%RWsa@5J{ zTL~6DAd{FQ4-;h-9o;X5-$l0t2XD%R{te(vY6P{#@8< zJJc;JsT|^Ax4Nrs-QSftG#721GH4caE4sp!w<{8!4KL_o=~_C1uTU&MOmlT_dv%^J z07uN0TQJ)BtAiJYcs6?vNI%j8Q47xU6N8qJZja$#jPK@xM}I@koKiyINYq^R&Jo=% z)dlk5Z67E=;=w5GZ)l`fFB7<)o(@oFjd0Fm*CT(tWyx3}nx=g#&}0@aF7csuwDE4` zTQ0Os$4cE}!b-3N-(xFNWMWF#&XVewV^4c_FO{pvOEO2CMsKNT9qaaOm-U0!M$+*A zP@V5v9ItbHj14~sHKL?{&#}?-=98SM2Dc}&t0~uu!JE2SCGo@Mm$4R-HV5>szt#O;rgZex+S0UKdo!L8wVo@aWI@m~j^OR?IHks3ymMbZI6h@gEi=8Wv zkgyo>m7zNsfu8d8VG}6MxeY|}V}1IuiCG4#Dbk4@0{7%}c}@uTO2Sd@==QRi7Mz`I zh0VP0&I9RY2_Bmjj;qIPW7~z40#^5ZY=N2N98KM0fu#gy7Vn6_CniF_F-~~cH{c<^ zz%i<{A}^Wl>=4}&sUn7}IJ&-mf? zrle?({oV%=WR^#k>wuTXO7Mci*eA61$+ z$8{$#x-3Qv*HiSY*YdrNIOVd0{iGZbG1zv|=EAsK{}&a;EU&JE1zGgV`#0XO7CuwK zbULY?22?B;N#vm%2j=L6SBR<*Sdm#wBdGXEFtVnF)OFt=XAHp2(K7t8%=k>#=r`r% z*XpB@9wUD>@p=stCs&9=O60AKlKJNdxfWr%ChK5wfyNaH)MwUMFzu zT0i%c=C76ekxt!4bCl$*xKpuMo(MFvn$P{CW9B`KC$Ety?rYd>(V0^I;pgGUEU9hE zX`c7C8Y+nmkZ<#9Bgx{@t6yJ=^fQ@F6DxdDF1(4oN{9d^?-cAr>0;!#4&+svQC&tXQjh=xPpDc7BluDVy|DOP>e!^&6RF{qRi)#8 z(02iP6d-TSuWpgDmgejSXpK=$mGhenJFV5}oe~#m&W$qm2PHt&r`lOGf!hGsddL~iadgM@j-ENPzF``?xeM!r^hw@~D4g11fbX9G{kFy5(& zK`lztb$utYmJZk1rTbMZ*y+_`joTr_`rW+V00`yK5n z=K$Jyt3z{#-NK{CweYuaOARrIW6aTzBh+4f&|SD=2$cw)0f?HpRYpN@B7G&7#SzCp z!^ekwtU*3n4v<3wVJ8cNgufAsJZjWm7B@*a$>d6Bq#%a@Uh{${utCvo*lt!Yo93F6Z{jIi8?7pFm5OfgYeMMK}WEDXJ2A#JpFqO zAn$8$M^Ot-!jtFx2W3b=V_eVqf%duQns#NB)A9WYX$U^ZmHDNmql?KG+YC%}I|QYa znxd&Q1Xcjr>iXCKFpT1;D~a=0kjX3)_6}qI^LCcIOW`aF`DP_Un@n@29b?sZ&%VQq z@jZiz&;D2T5A77}^zQ_W*zQPjgA(z8{SjzM?XP}t2WeQB_?e?+iF~(G z*&dv&hwSpQ<~B4_G49>u>y+-xK(e9gVe?FDjn6%#scwBpvy8v4uj$03RBqc$9gLlr zpFh_|_I)!LSFL}|ueB(AjJX*N<3UE-t$scqPoo`ZOzOpJA=4EbCXtoa})1|CRg~d@Ch0zBpqkLn3r4oqORSN*2xexQR)iNCMKx3dY?Jwt9UDyLZPxXk*eC~#_bLh<#)i%6&D1d zqc@e92GFn9x@D3{=(b%%{7b|P0WRT$4+s++RtZhB71yH3Kn@#Lu*Aa>d<5_`+$BA= z4$Bs#j@)7TJ&>!7K-h=xu2Ze?b&6Ddw+{S@{^HYbI`WKqe!S%I3ulwFfxWWajKN18tY z8Z}pN-!?r3v_#U1XsJ)92Ddi6lL;&JCC*8@6XVyr7Z5$Zyz?E3!^9VzScYaVJAI~ zdUmCTCeE9j{Ngx|sykTj5pfl{>*vyqtqsh}yWL4HO@dDB5zt{AYVbmn} z%PS|D)Fb!Q3X% z){{5>v(ElN6v_};_0P)RMdt>XNX(u5^{%Wp`OnI>9_k^F(hFu_!GjI-RuAnF-JFM| z6|1wa=u@70N@$;Mk6vzx;ct&*SBMg$9n@NAY~(N23HO*FFt{C%hNXI0DUO_2vZv~M zyq&^VmnA&r%9EASmA+JK`9BI0V*9n@|?%w|v^ zGBA;)-@N;u*};$r*Riv<80^8RSS$U|N&1p}`tX}nKo`7y?>0ye{y}RiLqDn4?)sz5 z)Iufv6WXIV><{Zdl_DA%B|k!#@R{@s%%WNnM32oYnwcyQ>eG0cwgKNXA5 zv)}j;v!L&%VR#XI7K3cfxn#fn6ujA*RYz%b0xm&pS zTkNIk&@$z}z2uc@#Pq10sv3dT-op`$O%py3!(1X~wINxCA?))!5Z}_ZeY4H9UV2g_*P%)L!8BQTj zRtt~Pu_R_G8=a4c#8dAG^O?GTs0M3xg*>QqJB>%Ae^HTBRc0q;cXh{b?>=kt8oCRR zu!C{~!0$hsoynzgtTa$cpMrz-9mEvv5tjfC_qL;|7k!KsOzAk`r9N)f=0e&u5K0AfA&isKksD>k4ViJ2 zIdlX0U^@#^FIYPqHjc-#gYtD4e_MAA2r9u`US?w!-lc>XF# zYs8XBeZSxCbh5jvDs=stvrOW9eC;H^y} z)2%hCnv**So6AIk)^I{GwVcSqj6(M_w&7{|T$$lSH<;|-F@R)DOe2n%+F$`BQu;Ky z=5Z7_t4;#wuX+76Cs+|2hQQ@_Y21z2%(!8*uadEQ!P9s;QvdqGP*(vuGW-M>YbxmH z=lRqca~du|RQetTqY_N+yPtlL``8|cveK*Q7NO(JMxUg9SAd~@73Q-}&^*6|(?>Py zARjOPerr$bom@ZvlbkLqRTgT+pzWgyBj~c=Xi^I%7KI90pU3E!iG&`_8m%Adyka%0 z>6Q+QE%zLri^}a{Ff2QiO&ac+sr<76tTzLe23(nHh%Q!8@pYgQyPoOYf5vG8tEH~|vcM{}cW8bb z68SgQ92DPgV^R;xiYAf%@S78QUrvKRDi$PVHs_c(I~M-_9m`#{w3-PFL*ZXK6c`Pt zD|G2Mp+;ZE9$uItfw)+fUw*4sdUXE5oB)3O_~hFuLHb|;gcf;$3H@&wU077S}c+y+qs$8<3XpyL;sT!lJ=QD88(`Fmq%Z+!|;^qwCN zB27vIf{KX=eQj_9LTpnI+?g1NAhbF#0dI+5%*N6HMzw{L37)$RL=8$>o1U16%MKh| zSxMa;*i77A9ZboO!q~UIF@;hD;{n6h4HykDfCN8=uL<4+Qj}AJ_YT241z2ONY4t%1G`UUHXalM1 zZ-#6=_h)f`w*aLAawF0V_?t{@1hrwn6nym_Z^qchNE8^z0_Um$=~KYHFksY!zs>_N zHzA`rb;ZDXvi}K4*c#Z{nffURRZ!~Y4u&64Lw^Qu3uv$8xw|b+g~Z9`)d4!xmL!9o z{S2{{tp(T>cNS-K;?8RhZcmI~-P*nD)O}n|)=b+4{Ai0i?axC8!M9`s%0Tnblgi95 z9l&T$^s5TZpM0f11ji=U-q)j=n43UjadBaF{0R<&7qJCVpqQt}0p9^=8-sxN#@3>a zLxRxE;TjrWf&gubu53Y|3Jr?-k$D4z-#8CJm?FL;ataVWV>>|L2?64GF(6QldlA?J zMEAIjAXsGnr0O8S%MK96>3~?FE0%ub2)!3hu*Rux2_pA*e`LxCg>z1@dupHrkwEGm z%y9V!ZXnh&P+XVD^p4RO^d4JtD-h#*&E&ZrLDKpSmpL#YI53g?=hKYQ;ginnL;ct7 zHBbXodh5(!80v?)sSRY-7f@1D%U`Od*1!DTh8!yf7(gVwe+yF(1`7N$FbsbPMIRYh zym71a{m|$EmAl$M^3CGR+QiZTAZ4kDr06H6LPbS=6g&*Na~L0efb0624LMKW=LFqi zbkVU07aR(PmjwnCy!Er1LdK3v@65tmK88a|zCa6-TJog%3n|{#00Ig|0ZMRZ?)Xu6 zAe#1OXZJ5s0ZC(^H(!4O>->E^=l-6Y5rDkK4GafY`#U^6^tt`epC0p5FblZp^6v)q z%uDs4KxP68#dd#-aVTeJ2<>d32k(a828bR23k8=dg7nPh!UIbYv0qB4oGxO?a#%SDx`<;&0{< zCK&Z8s+B?4@NUESVqf^RH+=^_XgfxpZ9H~VVw|eD^cYVSuO;i(EH2x_eGQSB1H}N1 z^X&p)Ts}PLgZ%Xt-i+-2GUF6?h|~|Z-WKwvp}H-+Yx+*@4!)&R#l$Y%QQoOni!chM zd*>u-q%Ggk=Ho8#tmchU1-WN1hLuW;+q<*6d$Psmay=+gBZ~vx`C?6Io_^bgab5Y( zn%`AJSL>1g{%ayStc`3Bpn{9!unN7w{|0r@F6~tA zkP}sCojNn-U6Oyn6q@($@oUL_yGVj^<%dS`ikZadb!02I#*iTz6z-0^v%ZYgPLC8v z0idkCI@AYXlgTxk^p7&kjcI?b6dw3>Z6%bPb{B>nTr)U4lLQKY`lx77Tp*ci8_`Z} zTR})Emdcy_%)Jnjdh%$IVKCszFMtp7;s<94C3MVed%(sPbQXCIh(FA4H1pPz@Je6P z8*g=(E|}KoEV_W`gKC=U#c?Oo(>*@QX!My^Kq{P;`ka5}wxIv$B~d_Vu%~E9IWR89 zOV)20&XuIFkG4B-4yXxGQ|__w=rg90ubQ68jaYOG5ziylzqSV+_mQs3ng^X_UT@3HZ@4;}x5QF>eSoHOQNu+6GpaTgKMqW?K6lzs-oUGMgF`Fa+wJfXp`e(X_Y&*QmfM&-rR!O zH;R@FY>6r*%G-O9`R<(kg^m1TjI!EMc0r@s9b%Bnv4o^6h>hnZ`F8`Nc<**wll7AP@&fx<~M_@J6gU|2`k^mK=ZTeHw0(r>o9=) zvOC)|u4qOGTi+UMHqMLuT~~zS{tK-Ko)t^IRo$Fsa>YH65#1?7szCyzW&u>1i*B9c z_R9NdFzakshMWyD4T*bL*mZk_>Q;$EpCUA&bXR>*l>TKkLNYd3iaRw(>B-YsXskiw zPx42#+>5L`!Q8CW^x+5)-hv8S0wbH#jU3rTCc?c}6_Nb0%ICRV?HGTLP(ef}WAU}} z?+lTtG2MNToY#pRcZ)#1U5A0B0WM3o<`kkfqu^6;ZFO~(G%D86{{THe!oSfM_{ouY zjESH(nhmA(rTr(Tn*uK@(=5SHKBtL039zNNNIdK*O^x0T(#}kWERU(GB4AMFshG7A zPUSUI)804k*o1R0K1PJ(+Uxe`e%j5=d#v)TF2q`Cdbg6zxmD-iDxWa=_l&}E8P^HQ ze#lDQ%VudZejSZ=@nm1ePMFia>j6MGWZ4g;lCa?L-9jd0sC?IyreBf9J{qFxqQw#) zmi9CV75OMEp4kRZNZ`Iqi5w>VKBR|Po^e_&se)ZnfsD-R@$lhmBV9b!hE^x`@eFWm zDEw{!7Zyi)be@8l+%&{sSqY>zePxRmTqGwjr<=*EX4TY)gCA0Tp`B0+MDUZ=DZvgssoSps~2?n2=!?5{+R?2Hn|j z13H)100d%4#X;CIHf+j2Tq#QEj;E_CGsQjbin)%k`3B#|?NE+Bw@N;l$vxE0dG5%g z0+5rLAZ1*PX00)x%gC&Cnae68(*v6rB^{QY|?&zssKo|ioXK*WTG6=@DrO^QL0gMh zJt4uSS$x`j8-gTa8xPWAcPcrCkIAv^YW`7Hlvbt{T^UP;-^(Lci5m|}XA@^f zv^Ssc4OkVKu&PFV0A*ZT_G$%vg51(T7dg@Pa9ME||Dl!b*0i#nkWs2E#0h{r(1&(d3I zN))fV-Ml#Tqa+kUv}!<`I%Cpb;dG||=}dFBy-4!#lb`2;*4JaGc8VO{wxx1C+YNG% zG1)NyWo{4$Rh>!9ZQ^X^AZZ<7`eGd$S?8waeqFbOGL=E1L+as!om6D!@}mnWgCHa} zoXaKO{1nrxd_ukuT!b9An9!}C)lK=+^3mv=_>H-X`Z~!qnUUsf3XKj zXoQ6bxu0Q$;5-|f1;#I5yB|-%pMiTj; zAFOtmYqrrg)Ju+`7(XsnV5`v9yETOp=u1`_(?&AI!qR%Hz%|cx@-fnp>l65U{q1r> zq!WiF^?Po)go2Yn$LZ^Vga#r(Xp=z1bX@}V)nE!{R#(&#D-VP{vKeOebF>=Q)!_aU zc`n1(yj>Fc!Ys7mG4&p5F;tyZhC+S!(g?+BxX_^lZN)F$cw*G0E9NSgmyrj$a)29S zy*yd{!2A$pa+Pm#&C(pvm9R8QDRU=U4h3mXgPPZUXs4R?K=0P-1$@MU@Y@B=PYMrL z@Z)0OsvmMse!fIpOiKrL&c2n1cwbY;5B^b6aQv<0;)WA>-p*@cdZ$(~6-O^c`%|{r zxJ?FPHO`^t`*NSL zrN!#jmoIcJ(+t7S>vymlF5A0 z9IS<2&m6y?clZDNVe@evk~*b@ujF>v@%q9x4c$=CGuC|$0hU-qgecq-%LtZU-S=bt z$vNR3BbE)qhM`@ssiQ)&F&W*I_D$vZOd5p@uU*F*)W)|~Xoy}-K54a_2M_c^y@~ZS zCgTGh?!_*FM4Ngw!X6dFpRz)(m<3#BT4A9fj()aY&wuLC05`}Z=ERxJw}ww#{)BDn zx=0KI4|~V4D+Z@2=&r2ea~Yfkky3tdWh*>)_%$AmC^5r@nDPFgAxtbG0C9Ew;jHAt zx`9?`fXSVL8>^p0a5je55sdm%Ezhzz;T-xqO*9e~;VZVqpHF*tn-bb2(`8!FcT9=n zDW^tka(7&%cKpm7QZ2&IKkFPBAkV_;O)0NR+%Obrk)8OpDz-Ss;>8{N8vVJ6l*qVr z*wHCMAFSOgsLbnd!d!+9ExK>ii^FAlm4tN(l!OheI*#4G>1EGrW^mWA$re?HQb zMn4aOL5pfBe_My=Tl~miksrL#x0plhy{4aVb}UMvj_)^Ex-+M!(L@FSurmkM_ zvMG98olhoae>6{|K4I15X|c5Mr?m@qU~hfb3Q=WjBRqe?fmMg1U2F($S+4IiRcA!9z6E}uWE3Cf8E?i|RBmK8O02FR7){L#;jD6Za2V3+2O_AfDIt4pebH5JIO=H z^(GQu=S|5JmL?cxc(5RwU)<{Y6eTYFU3x4(LPk$u!;q+i#i!hN+m09x7y)i8iST>$ z-TX_FbCs1j6P8I8OIE!+6p59jy!%V3RX>0+R3=k9VjgMw4Fe4Vx!aOPV1mjL6p6gA zP_1!iZ-6c~V4P_F8DatW+S_W?r7V3v4a$Xx-Q8Qaxi6<_&@+vQ^V}|=5(5k;WMAe! zZ!(y8v#ckk9gh?aY?FwWB%+k>zc-O}oPwDl(ok1@_I|plYiQK$t&7w}@SB+@w-_5B zmS{f@mzQ{j9U6-w(z~w@=Q;RPGycOjc1xfp7qls}@O9l#ojNSF2JCv7x6 zEtd6JysRKx2rBfO-%DC$Kl^S}6YthOoA#?bVxcc*pGrWnnk$n#hTbH{J@$;(AY{moLUFQk1Ds4G< zyHhsRo;kO~kL-5&;NE4*3O%5_{~>{xTKkLrBs3=fSLcI`UOI8^(9O$UkHE~}G>MPe z%ei#n;l69`*WdU789X>bxjm==dXU0#Yw(H&J>-Ki3A?C4~sCC`H==~u~6f~Nm1gvLHeUj;?Bt)5^AYsWe()dB~8LgSo{O1bBkpp0*dd8LI+Za zG-Z3C9ZfB;s7t7P*NJjDyJYMxHOjaunkb)1m$55kl3rQIi_Z21(!eI(-<;g`-1~}Q z8LNrQ%+b>9V>)7d6@SU!&}C>Wv9IlUGjs!P7SZ?i>;3&l!ml1dq9sm(h%C22)YP=B z1K9;ZehVsIbu;}P+1610*ZJI`SD#Jb#;Ka9)T~!hbF;=<@2MgYhp<7cew9I?!2<*n z>}QDNyto7fZyu;HlId3In`zSVSe5JsWU<=^?S0(mTiuy>NCI3)1fCSQPOl>+fT(tF z0Fs3B4Ew8M-}7Yh`wT^vK|>xl(#9wvmY+n*quiwyhA5}Y8)8)2^0N?2`N; zF*9~GNz^Hz!hI^ZAa;(mFZYT7qpZ=j%2>_&m8!*TLwyd~zm3(TNldiCEP9!K;hPEs zm98?>6dhr(jjQ)FEkfu=xyBC|lOo_(mA43*2$4!qz&elanVSoi*6-Tz^$Sj?FE5&# zZ2HkyVm^9lZe5XqkgAzp;qNu#>IOaqi3`3}oqNYFiJ(oC612Z^!~euRq^9=>F~mPx z$VDy5=#4pDr%mFyfB}2XqPpbKe>vp5BbIIgIl7o1e66rvJWTZ=CY1ASz>{i0`hzP~ z#f2$a*a(LG4EKhy1!+N3 zUBJg59*$nY0p5ANGPAYHXki81ekP@})~!X|LM-Rea~H}8%)NX#v2$AAj2jl>pQO^Y zSH58qmgE1xG&)(r_ItX2>jgdH)Na8v)t@G`@9+|aQPDY7@q#ld<d*_oFs= z;)~i^OiVg_@>7~(P_5R=8n0@X1~>kjfTd*tBbpoXjcT}4xt0}SWj3ymyTGn*;E|=7 zBt3Jz>EBEbR1RBLcXSO))catemnmzg$p8_q&|mKks4&7J;>k=9RzKd3K8K}Cv*J>Z`AgH`%&)2!DDNtSk5vej zioXx+#q3>q!1^}%ee}aQ^TMQr0!J5CCE=;&j`|Q?jo1+C2ie$pozy|$&s$k!s9-vm z%;da^O?z8Ddyr|hR=omNKYf?F7%_LONF)w__i8qsn9NXLkl;}XK8hSQAjL_Xs82p@Q&N(l#3 z-pD0=7i-1nyxK9gy}LK-6J2lz7io}SQMB3Gg&+0Xp&dmw)4~*?K!U69%K|gc@_Kps z2|TQIS`Yk8%1RebS`oTQSQ)xiIwu^dca|>I67Mf^K#&+ghA&}po_ldtH#<6Y^LBcv z2RaciTxDC(qA{ON-%2q;fm6MM09t6kC88l2;^Q~!(YCg_Lgu8ZGqj5SeGyF{*PE#$ zyo`@6FIQxX>U9*ZD3k#W{(=#)t;=A@QVrMc?Sj&|Hf*#V8QByo9y0*x(dI0q+nf8y zlChmtVPU%q$4LI;CS5L4#Lq}yR3^ zr;6SorN-(|M<01Gvz8d$-VDgFl3g+{i&aCH9lP=_=x-Hoa8MzCEz|2+L}biHmz?~0 zzVI=y#mb~9xpI}Q{d`0F;MD2NM~x3@xRqiBFFNl9eXE8=E$tO!P7@-0+vUR^m(d}I z+xjEuKil(t_qccKh_(FQnY|6bwurXg@_mZA6`PBPI$#@1yAvV>?#wCKLEAGM#OO^o zF1S$e&FRk(91i1=v?j5sLfhM)ZeVnjS`9C!+xho_aCS-7fVXS!Z$w(kMsU%BW+~)s z`$=i@TP0S63;EMH?3}b*Wk01ef| zV~%9n%#2qr*VpGkO1FbT?TZS$!q4R7C8BbIj(O`q{VDxs+|5PZpY+YxoZHT2Ml!~s z>H4~CpJt4<-gDy1gI)(!(wnT(qUd^rk%hd6c=Gy}(h1|;WCn=Y5?c(`^+a@!^}_#Zc4In{E4eRjOb zq;g~4)#$lgak!9*E)7eqA+HCeKiKOqcdtplmz58>c(e>$!xZ5$k(zw`)^&rwabOc!#)_hPY5_=JY>;vs8mlT0wD&>I3WKCY!R2bz)i>L;9UQ6iE zTua!`^$Ysz-Yd5Jw1ew169I?9g+GP;P+?rD4OGnDSsn_D|4^KIS9NRa>o^CDjRm6Rq*4pYEjaqvgQtamO50HKqLs(FaLdm{&t5Hg^fm-^E42G@Dh( z=pqy>JG>?C~+%MMzN zGdMf`(i3|@`(tl>ZUqT8jEjp1IkUjr%Gktn`m84SYm@IvBy|iN|tQRgt7y&X5@;juz0EO-Sc)otgsa# zq{k~Jvaq+DB=Ux2q1w*li8AmMUrZ<{~VYkie8r7yq;D7n)^$B{&qG+!;CDyZqASk!^r>k9Hrq%rTX7EqKn3 zc9{X;!|7-&TVHgvVno%aueNsW<}@L8geKYWafZCT@N1;27om@ppz4K zU1G!kwu|46vb)V`WQM?>Yo3LVG_@vU{fx$^&Tg}}5wo+44N5eaGsF!%QD*&hq)>1_ z_lJ4rzSJk}Mii_!@b(O)$7Ym^9$lgHM@)6}ft1CCn#pELZJDN+8dJd$R~68^qJjv* zhnnT~jb@v6^>tA>579B`M=WoOn*x-@j4R+9GcH2PHIEyYT*i$T!O+75)VJc(Q^Pkh z3ir`g3WM@0ATc=b9wKl>_P8SrD{^iehOoX|WRE5gKHz-?k zof}5}jCl3F|JlTE^-9Dy^`+VGU?xlkRx`0}iXb!E7ayB78fQLh5O~+>I*< zM~C0s>Toe^sd6i`i%?M5PSlJ7<>x%|-0tzs3tHZ|4lal*>A~*hXk@!!J}h|k{ra&J z-Z-T`6%vVFLj(iUN2l+FP&R3wLoJD3XA?R1NKBN}TsuPb9D%PfxknDWR%5{*689?r zp$}DEX`WUVJooX+Jv|9kOGRl1n^ag?jg;3n76+BiJ4{_IbXg}Zw+AvJ*6Q+oKfX6> zU!fg}X$C-=dUq>^&%h{H5j35V9#Bmp<5ZN3g6?0o3ySvVn+}p2@zF|?;r|a~3 zdsrgWmBDB~r%zzH7;o}9rKjR8Ap>3#4LV;*wDvt;wFK0%i6j2TQlj=$blJ%bIsXfx z&B|eCp}NPXGOwBI&_x8N*hf? zLcD?-ZHWNt3vilcfkb=44x`wf`2K#V=2S0{1YgV0_`nzk*Y`68DSS5D$kiqH8eupZ z$p*iY4tUdi85-N6JVmiJTlrXv^Y%k>bly{gY5NoKo2z#Vx=@Z{rYZtBR3|L7(1uU_ zfnOD-ss#=P;sGDr?%kR8h!nkw$6I!5>70fiZPN!Q<2wV+-}EiKo$Rr;l^1&X@Dye7 z7#ZU>jPH-DR6pXiKFHhn)iuhcV3d9CpGIC71>4PO@irdX`9dKnY}+RG*j~NR84tT_ zmB@jrPA+hcD1voYWILo#V8bx+DF;8qsz5LnF_R9=;x;;RGK$8|f_^g@o(& zxPg3n_7xFX$?Nosqw-nT55g#xv}_VeCEN9_>D_Q`Ioh&isNop5z(btNLD{}(KlM?0 zca&S+>Izwf-0ZcZ8ug%cN^qRy^n!-M05)!ex^Jz4Bze7Ic~cW~zC|8eS*p7%Y2U?K zIz-nYfpeN72~F?c$qb;Lkj zoZ*^LEhml*DYHCL-NB6JvIdeGS&L+}%6>O2+hh_xP}09{Kb`L80Eo}7MiyuhhLlK1 zEoEfZ+At)B$P+{cewv>YudnRFm4qF{a=O>)By59Add$a@TA+NsA^iSEb_SoC+)Y&uHtO8!$39F*O|Tor`gcoH zV*9eHRxfr8Hmef(CZ}=o+Y0MXB1!#K#fCw%)odkzYt>Sa;bcfHfisF28 z^bif>@kl&pW#4yXs4bGNJ^0kd%IRQ99pR(>8F{*nJAz#;-NST|^r;(K@icFVbVA{! zsBSpk7%53jZ)a)?lggd+L~IItd&@7Y+x6odb=tMJ80)gRm1G>`ZUE*d_TfE%@M$$Ch4xc`d-UP?BeG2>bX7PsI+)eGk;a` z{_G=WfAbB}GUCq7S9fDquqZ{@+v11nnjcSZ##lk@8;(nv$4AGEN=)gsE?3;fSsyYl z?~L{$Gy=zDj*M~ePRTMF*3IyK@%kV$8--afDe$S!qCG~%o}J?TV{|nY zz8iKn-1f(`1RlkuZ-gMvmPS?tj{|#Jqm3S#Mn>x3Bvvyzbp~Z|IE`Qp&NFa~@pra@ zT?D3BD6DX>{IJJ&1&v?PJ9%0Aosub_$OEC0Pg(_((IQ0zFVJJ{FjmKKl(SR{bu_3P zkY|Hc0?mV(YPeNQQQgH7^oV047z)_nKW?b~nIT!{99D2mccs>6O(N99|B*hhvuyIx-B~mzA1VNur1th;@0N_ZWam+GU z)j689aywSAgIvDX$HDfY!kgdPlUr{!lncU z#!ac+(3XKMx!b8e#$e&P1L*sgr(5fb>Cxv^ys0QG_ zo!>#HffQ~hZXcwn2R+@8CHZ9f;}EPX^w&@w;<|pDllpf@`2B-Y%FUi31~mRmB@-qX z39*XU9ch{$TZ3J?Qu1Lux6jHrq~M8%nmZMzYrA#2E3_bm&x&{i!OUc9XOuKlcC}OW z@0g)}6lEVl??S(Svh91^T(`tH&Xiwb*7$q~Ze48wqhvkG8F|5}fe|y|LVX;OA#dqh zGDYO$p~#WYI*ktGx@<?Oj|7q^dI=KMlnkH2?~v+rfsVyj(}eA+ zHT`a1W4MZzd3e=touWn#Dr~s$9`MiOc(~xRWp)ZiSTH_38oqV``c5hzK8JHk3(}hR zHX;s}c^{g?FqW9^+h;EJhVU}ywo>tsD%m31LRoUuyesD&L*I;2=lwE#^BA3+5gT%+eXUT?cXzNlkNq}E00&O^?y&494kZy- zD|MnXy#;_ETf-}`5@4SD7`8J|n#o5U*cEfRKlLt%V&& zVU;%JJkjATp4M!emSNqlmtDJ$m3s@9;0GPPZG=^UYQ+zsWZlqV#o>xFki~mKIegH6 z&ux%{E#MjDFmT2e)R+BZJ1T|eO}b(>?Z_Kl$)fw2r%r0SB)b**Va6^?qp$gUeO4E? zZN3^`oDbD9Nek;ur@m4IT)%^5VLDc&iU{yEGf7wE(8fs6V6VE9!CwsIX}dNRzpP5Ymo7Pz=z=W z(k7Z8IUMTu3Ktsp#c)Y89oQfK0AkfxdZ`z!mNRBt5UmKmD+FWsMRzsXvmh$dA?A-tn8(EY) zuUP7R`%3WJWBwvZ$?GHIjqs4i8?B*Y?l(W-3NYJVi%)q1wbqFAJD3!6HBq0^sYCIi zo`rMVX?JtA)iH7L)pa~}c*0)muJ=muFu8)TK9*}~O`;0R*ew@EDRvg~-4m z?YV=oaph1Q`j+nDKv3SqVixqwyDOrH(_YzjH4r%QPSg2zq^$P2#5wXxuBYwy_c(?A<3IRYu7SGcq3#fG+wg^ zak;Czs3I>jXebp2T2Bc-B*rZggNd&wD12G(BNNQKxU0Shm}K_}rDAAPtb6j~a8bYh zt{UWKYV3v(O#l@TOZNcTA6HaB-M&lXsowMblMOFS(3Z!8VS--&x*CJeSF?)wPg?ao zBf3sy-q@FV)F=8wCsU-`2!z76SaP{Lh*Gebb>N6rGRTil8VD_-CVD~$ou zzK%=|B6f>FEj=pTf(xy{jQ0_1?)qp6Ds-m<67MiEJ_% zkqS2^F}UU{2B^4(Iv!k9(iIn47`H3p*0`E3oQVdngSVT`n75sJ1Y)|5Ctg^8M1>U! zcX?-Rpq%oYsh(41BDIa%LgNXtRUk3KoQntdo~VyJSOj4XiZ(w9b{xbs*ss3&64&2g z+UM@hP4+Xuzaxuv{%+J`xk}ga1=w1Xq~|2NalAldPq5y74e+k>f0rzONPwq#=6&@e znOXwPy$*~fBL48GxEM0{rFtRCbN+T*m>p0AWg85Q30hTwmYf=sdJz$tMit93(2p-B+l`Bx+ ziN1Gv@QNoC`~8!540wWu!QKMQB#WDCeS2;a*3WJfGJG`f*m5LYS^vgsX?Sh{=aejF zCf@Z`eGPJ6SMji1h;6XKnFh@AC#0YWuIon)%Af1cQX;C_sn`%PD`(jD9t?A9T4hJ+ z$d;IVdrAVCCP=i%XJrr5=V^J>W~HI%eignf=GAOiDtGEaR;p)s9_Ox7vku&5=PL-P z)nBfc^`op#l73=al9{H(2pcq)J{s|9dUQS{MKucV3D#9-L?hXbi&4zgguG4FN_a9H zq;_sqU^0`bT-shEqHtDMLxA8qY);-7ak@UfLYZrwna6XAHbb9=6`3lY4mgNXP&8~8 zaDoLIsDCq2BLYml%kuP+e>=AXerR)F$6Px+z0gzr>?xEQuvs-jZckRiw(8=p&KCh+ zr6fRCs)RH^6*F3W(Y`|#kld~v9LE}Y`Bl9$4h6uM^|LCFyb!+W%e7w26Lsm!!-{yU zS2?UJDRVnhm^tRG`|wCF9G&r3=}>sD;1-ui?h_kb21DLF1@j+QhOt5u&bFv8G_j^F zg0s4q%j>P>a_w9f&dmgALuT6@S_!JS1ckjOnX zXXp@)ijIVtEw7XTzI~cYd?agyZ}>4uGhh<#s49X{DEZzgK|K+yP$s5-n?W*daGf5N zUnKcsev&%D~F5U;$N_32k8d}MI51T>wGa}4WuGD~S zhFzxOaZG6B{JAIh1f@2#ZL7r;!-Ln>EWGe$_ZZ(6NeOZrB`i*id8hHA_>L5ptEphgNVKR%D?}K@iAwF|a<@6qUXRSJC-@3+joNY1RTzyrZUMchnGCS7eg2kL{ zKTj1mT=nZcyRSGf^!RDz%YsCa?keUig|Ny$^<0~zYfz%3k$0(I8TGKZe6(JIR4k*- zj1gN#pR%%1o1HZ5`bnwP`^Z5f2E!6+lF!>l`ss79jG^d{s7dSI?aSls$#L1TAKUVu zofaP`fcppfZ|4WrRM?LJBZLLFkh~;~&Nyi}>kx>C_h+%X!cWghSjN^m93T6(aq$}VQ?rDmA{cX1OWrQhAnCKC8I=c!v}h31#3v2S(&AC6>~{H;-w7-> zVC@WF0R$@7Yw%>V%lubaf-2x%wcR0dFF4D4x+n63gaP!{B6IWBE~eqLWbcG{$xAQD zhohFGtx+Cx(uR0S0(YwQQLJJZ-klMqv?gSL-O@0Rm|28dhodr)Yxb$7{Xmz^SvDA} zBz8|CC|Dsjo1DPan3KF&DOP}#*|ka{^oW^yPi#lqCR}qIK<(0=0Je{?#{kS_^bksm z0O&7%2P}>OA{NE~vWPHKw>gMOrckDIaE2b|=pPKUt(*&uXDs>(tJM~$;N zsY6^+h=n`kQ(cR!F9EbslHAxQz?NpBIOWx#S$MR~`tEuka3WNrydUmfp=)x_N_`_8 zZw(%ze(7bn_G2J@J`mq?z8da+rQ3Ms!}=JRx;ETsOQzgi>>F`pr$W0;Be;`jz>pyA z?2D47vUh8U`ZlybU>9sSmjD1^B<-D~0I+#8awQ=A77{_n)ZF{7^@LB2JJj|rKCK3j zx^HNybS%_<8}_{9lT^8BartJ@`Rc8X%!Z{y@_R+07WTwy+ON8j^^9<0PWsKII{9IeZBrwg#>v>ChdUVk z?00A!MYm87%>%77&z2{oNA9S`^iVqU*Ss0=(E|!I_HFm>n5DG&A-yn*n0Te|Ht!ck|(2OC-7KWuN zbc^nJlUQ9}e89@6VGUpuUNd~CVy|MKT#KM?WEgdIL72_s_G@L)kDL(^C{tvoVeh*A zW?-rQm7UP{MWqT-m_5^+g*>?E+sZ_q;sC$2@8>x*dlBS;bR`}XCg)ZdvRnarGb;!q zZg@X}=3Vm+Oi53P6sI$YFy#RC1y}L0>6tJpHkev?S}u=J#H)mAP8+j=0k0j;fuF~> zP%VM|dqOS80i2Oo6VsJ~qutS?-ZIP4fQd!gNhoWNn zttM2?KWeRACbvS4zUwh#ig9omq(DnMf8$T@$PFb@pVmV=^e8|5bSIQiiwLy2ce@#= z!6Q)MeeEBROX|?*D^x3KQ^ZR}kq%NtLk7_JZp%W)8#f|;*My_v94yL!&f;QHXv_7y zCK4!-rj^fEfvYA*aaark1zr`8ehsuWtv7alG}m4paHv{ zYNb4Bkvf!?Wh=$PsDv8(ggkT6jrI2GtdvV|(lXQdh*E2ow7u?K-w@v;L16{F%eozM zOWD_C?Uvp0(gVC8eM=$d+cn`a9tB$en4fTt>|Nle?k#hqDE`tU-Viv3VCaHK$s7QU z7?b-TOtB-IMhFXoNnwuXzW2(mO_;ac{_ocd_dmZ^$1e5AAlX`v1TTYm%!6s%tflf^ z&Y16WY>+skR~j#~mKF0m=n2Gmn*A1VT}6|_)hd)gM%^%Cv#D}@^RVWHJsX#~o?bJL zu`)HcTb3YycSmwkKuW`c|MLd+vP}lY4FyJ^AvGXYxi1$rDGW1w#SKNBk_G+a?J8V% zZe#F=4_1*DSqw_GUJ$!PUlGYslw7}yLhQkMR@VfCh?)=ft#c}j>$h`#L-T$D;~_kK zEvh6m6xlEl5UidS>!s{ip;OioohIhcx2VO_LWBu)$lnIDN%O*AUuiF#U}{cqBQh1VYWP~fI;+qSP7f9``ApK5n2tlqqlj&;%Wzyz6o$!;PWl;{ z#QlrN%LIcd7Zhf!^8==hCBUyZ9@4}ak}4b~VkSqE_3&_z`SU~cILTe&3)NwH!!wwLgBbPiG##E&sGY<$4_5jm_ z_4&SRqZphJ%LnE*t*(7uz$R*ivjZdgu6_~7o6LeFCsy;E!X)+6IYJHtLh}ew>P69) zGQL4|HU@!HEf7q*xIviW_L1Ppg}ChF6!MxA0W)*90c{=%W`aXxCY#ROlKr$uCyuY+xn+~QB!2)$K|Fjo97qlBzqmPx9beYnuahGz^p@-zMZBK>Qo+Im0R3`6wi zuH=aVFTl{*fUbyq$o~mj8KmZcqx;g5y~!T26+h~>wDj)W2b4mq`I^3^M6l|L08u~K zxIoHd7XTiOsI>Plf?x1Kk_+E*U2}FUUuA7x{4G~htw84lbo-g(hs=Os;BD0R4O21b z>+q$){GSOdBccEm3u-}*FyvIHB~5Xwzsxx#jYCLAetA0d+ofc%$nUtvmlkxg8tus) zDr4dGn!A$j5#>6E@;&Ip$jh^B;X$zWlYM9WZ8s_jUCZzEmp zBF)MA%gH^F4%E1H;kAQub948G6)fVd@;88Fsl9e=ft)^X-pgbte$6O@V|-Qwl147= z+6R$yaGr^wgGklF6*5tzNvZW3+f>*R0I5RbLZ&EaQQ|vRBhhO1$b7Jy=SPwO+V2et?!Nf5qB)`ty4NY;IgFWfZ;Nkv-ZxN7i* zsz8X>BY7=Lgv&rf+BlLg_u_ViA(jKhcXbQCQS0PmKu$9}@LXm7pvG_f(&~19J;SS| zimM?C2&pWgKS#ntp#YRhYcc9;Lg%*HpNd*!oo`0LlUE_U_+bdl15IqMQ5+erU@}Swsr??Y-STcdUsuO` z8!YSOxlUWbK_%fJ%rXwzj<}ia(LErgQhU{pNH7gE2XmA-uS)^fa6-I9ijxju+d^sV)vFNGlfO+ojU#(>Br_`4Ue95z1fi$JA8m#+tB! zCW#PW?J7l8u*)`@su5lyjHuhPD~!2W=XI~)v`IN>wRm&9tp&=5CCMx_C3`l8^ar(K zUEb__Gv84c3bvWN+)x5(+31uxN`HKJfu7&(<~W-43zRqQa>r2|AOdP*P7k@w36I?< ziIYlFVYHZXxeBlY_>E{2pG)-zCTloE9wVvk{-T3Xk!6))#MRoImV47hgP*v84O0f7 zaXj9IDaD$<$>+CV(RY#j)?k-?>PDkKWTb#fJ}?ny1Ga}ID-avAmVpgKMgJloWE09h z@)6wrN}f!(m6Mrv0=rOvTRECpnsHFIv2h5%B_V8+z8_K^uV>{g^v)1>f&Paf zy%Qa5f-p%U%UR=W_e}P^FmgeqV99!oJ^!9FBcC{mQ&>a%8)On`V4-48dTP$_@eH`A zmjXKMMKR~QCCDP=Btj)dsdbGYjSEoxb+f4CM$l}Q4i(yy^qH4(pvzfz^)y`}@n_6Z zt8f*p#zcf`E;nJIk2MngXyq*L$#Ed3T3Ez$*irIDab6M9F-g+gha*ILZXu=c4XvKz=#Eq~!{5}*xl9Qx*p$0gq^-^Q+b zwYlZwKC+RR=4_T@1wtJPL_}k~&@T(&|4StWkb7qVWLywO0QQ_6rNVYX=I zd3`e;9YE~Zv&Jk@p+_5gqC8L<(>_3QPpQM)<35EM7DoFsffr=8)Y~EPD|MxH2W_tq z$#lzbSMtRt3+y~*TrHqTYEb;UQy~L1qr32f4+42l24($fqEC9FzZ-DpwaLMb{4W71 z-vl_UVGsVtel+o$MN-!R=auXofh-B6jiRsL`5JXY@T9GRJMVp{$$XkIBzp^sk7?VT z5s+ua;>J5qUio8ax4wm()3beU%&=Uc+{`L#;M7Aj*9u<;UeeUPw*Df^HO}LnbfvL_OZacrXXeIwp+(wiQVo)+SxfHMlKO=E9yx7Sjw{?YUlye) zsJ3>TFUJ9ccJF;bZ*UZG)ocE^XBg1}c(PyJJ8?=<6rHdKE{Eb75 zc3#plI9QSMeP0vrM>5NjieC(9BMMIn7yF8J?@g|+HU_Uh?+TSP$j$8-xFljahBV2gAX-SAMf?4jp2G7IvO46HMjnm# zayXC9bSr~Y_0wOkflSiA2|#yo7ImBDaDgRgvy_&waJEmCaG7j5un3gxM_W=f^11vWSGgA}lhDqOGxI5nk}4}yYDdp&e)vq$i55|s zXZNtRbsfGJ{B6XXE#ltCf+voOdL<6U=4P3Cha)w5s?K5ggqJxB$4W+h}opmi42YxUdY52NKa+QBud3-8IhwIAeGD7(JO; zY^-K%PLHSwB#HNEMcz(Q=JdSHob^{earYU74>kLReSlx|V>l1YLIB#41_ob(7xOB&Xy z6U=%!kCA(FAPIvD&q^5H)*FJ|;_HIzi)3Etj9VGxgK=wHGCz3t(gKcqH3yuvuHV%&HZs4xh$bIAi{CKlI~;Ur3B4>#VGl#N`3A1f@x zWD1cBOk-j>Hc7dF!IDkm9U4}`-e#(=gbD`Hgs+57!4n)rPc5pnt+>OAxyYEm) zz(xiq2IhVQ5t%u=`v(a@!LW$QjE!pco7{@1!M6aVBa^`R;_Dq|OxkkM*}c`q>2-2p z(AB$a8X|rRmEU9f>rB0k6w}f(pw*4j;;0kwAq}34g}HI7^Nw@tDEZ18_h^i-VtbiK zAjC(d3F%%@kRQ9-PFAx8Qa7lCa_ERVh6y+YG(K*Su)q77r03Jg+r~^5e|n~lJ+o!9 z_dxNtu%rvOqZT-~IlNDru#DEURUg#`L>-S;jjF;_FRry|@S*e!R*HG@P<_uvTLW*~ zJ)EC=R0j_{2GC{F5he0K;(GX4&%-Zjl@?4$tIi_?7oHc{+wsV;BxS5Wt^o@2@74xK z#~>jOOUcP2X{-GJ?;)M9*ECR8IQ*M0gS9aPw7Edgq-6nPHX^XMM0eRtv|vyP)eb`! zo?qr2tcgF++8%liZF7z#boxdISN1e-xj@n4bKgT0Qx_dhefZ7P>--B_x=0DZ7V0)L zTsQ>@U10j}!cm(GRx%a?8XIw%LJC&& z_LUhhb%DK0%|jR6x^8T(#axA~ssO`+N9WE-%eG5ie9=tuj7(`qV z&8jJ{vm}Pe7`v^U2l5gDQM z%pmvOxYE~*UT3Df%0|$&)OMS?y-$}x2Y^s{!W-C;__AjEa6G;0Ykb!kMfK4K?(JPs zY{NVDUrjYVR7AHwUh-Re#uX!0Dk>GNnn%h-5fm6_arnXm)U%q z?p;dRP2naFco3H+JqWZu@iSh~%6fQC{i!nA&D3Mc zRq)UV(y`gG=m$@+uPg?!j!vWl(WI|4P9FdSHjT^c8?$}W)Z7-ke2BT0y@@kKLZ9g! zINcj@4M(KEQi5vbm>XjWVcgOtIEF6HeG#&R!j$(E40g(^UFn&?&seM(^bKNi7eS1) z5&l48M&ih(KnX0$gxu0L==KIin;P(5ZCzSVM8?FFr}T6z1Hboe@NEwg6|U91xJb5* z_eh#@ytK&$)AT&rK{flOCn+|Glopl)mXUm<)IgJyw zrj#mkX%~LvQAV|}ZtwauTM-(`SR?k+0#UFujweB?Lm2|whNZTl+W}LkJFpg4QLWvw z75*RR`3(#z@+?t*I>d{F!1%+-w$@fj`NWo3zyn#`DSOf2=u9a(Vk|l z6ZwNbFs`UT?x%4R-}a7Bw>+7^$XR~zdsHl{<1&6=DImVg&~MWGQSacI-F??HF-4^c z+o$rODcbcZpFyL4)>8qmW>#9cI1_$%m*$y0p)wcarsm<_Ci9)FsoqHcxYmo<##EX4AnoXGW>4|_qY7@uGX2eXIY+?hlZ;8pOo^H)N7 ziPjJHXBdq$uiG1t>k zztXSFl+&?l9GFTx*l30U%Qx&uIgyrRKn zjNmhVL5Zqx)Vt_RWeg{UhWCiHQGgiZ*Hp)qCHm-xHAmz+&-jSM+_cT zjn$5wA&|%7io_o~Y{8-#ifBq>KC()bn2K}<%(gRlq*H;#>XJaNiy(L*5rx(PEF zO0Xewh%eC$*g{uFS#Q(t@NbIU$&$8vZe8rvOw$hS6ntMtENzjy@()0yb~B65R3jgN zQEYZR&feNl4X!^^ac0gE zc_WN<(69LyzI5SCOYp02&XBBi{&@e(tr$!hw5w$vaJCRT>Km78t+zK0T-mk)fUl@c zZ@T`ew%-s7);Vl~E$=b)BVX*ucVIJy{ppI%oG)oFp*BU0zDaM~2Q)b-&-NH+dXj+; zK}u6MY!D_$`@C zQqI2#CooI{h*%`}o@xKY_d3>vFD8XSHoFjN_TS6NcTz5#fGK*}vDF?;?6?nva)y&$ zrlSi4S8P)Ddeek1dK0FyQ_9_EJ;;$=g2KEL`J4Z?YKwnzdbal1MK0<~p$tIL8o6LV zjs@vQEnCu^zdTCP;{*tIoAy_+eTYwT^#~LkN`qei%Ive$*FFY_K@fnckN=Yz<0lkv zX$pDLAPyZtwSXI$<28I`vXqt;i%QXDK&kyTAaLl|iSgN_&}+hNFvt=qZmV=?$@vu{ z=Q?Z`E(mo8VCxs3?A4hs^+P^w^!!`bGMPR%mn0h|>h9KMsRJ{}L60Da7NFc+{5qA! z*XR;qYkaNDy0xAsmt0WC*ONHYXeV7Ld>nqW+|{BIK^2;Az5eK}Z2nEU{Y~?&`6Fz9 zV_TxzQt$#gt^5Oy8Q$bdMxxu%jLf2=y7X&it=CgTbjUcwi3kz5xS-P~Lrn#Yy2#FV zwY??HoFHv}Xt3>|_}$AAaVgm$kjI7G6uZkHub#6UH(Qc7d$)8`*X7ahorEJ_5HHt! ziX3IG0(@MG3oW;OwXoIUpeW7Ww~UaX2)SARv3@|jI)xFI^P3%7g6A>~XE%_-oB7+? z=n&pFBuc`4OJWI*WQn_W2vPXVwH6k9hb%T3gFfAJAilb8DzR!)+NNUw0oOeBC<4uJ zY9{L(ECW{i9DX(wv40ShZIuq9+Nft{K;nMqQ<+LQ8n2C!x_MeV%>h68ON-FSRg7x= z^Ol7yaZ|;V16{a4#BN9{KzL(=9`!LxLF|N7J>Tv{A>G8=Us}iwm55OjhGH}D=LAVI} zAgTG%0$k#dFr@U~4BhPi#n8>j#_<1@+)M-<>`aXRP0-EB&d%}w{M-ak^kRRk|C%}y z(2H3c{xuabHMTP`h2rCba{B9NYG?!Hwh`S5s*rV#L>JZRNzjL|wY|N~ieTagNCpE8 z6W9p?EoTpbw?)_{949b`pc4>^5Fi~V?ecnc!}+W4Y$v-s_4=28Ti>-;zE^cnqO@?9 z((2M0R>?7BfYZI*Z3y5Y!=uX!01wZH4iAryMobKt0SD+~GHTcYB%s|tJKyM+XlzhG z;H^*=5W@H950@~YftkIRY3E4;Fy|Hp0?1;{dKDbO0cpKHQx8GJr*=U!HFQ>ko-Nz)uFO zUuxv*?O$KfUpbJFA4Hg@dIuLrK%wq_1y4U*3?Lv2>Oc1V-Fr9y1WPaMh!74=K2hKv z0R0Gg&&2z&6aE0Cnz{gY_5HmYPL2Nlx_h=dwgzLjXzjkG?pX~)OKLmopU^rnV++X&OuzBLf*eXE(T@Q+qY!a+q!MA`3CB)aTNplN#e*W{A`{GI0R#Z zgTypc008Yk0(xw4TfK|eZk>KV_76X7{4RU9mj_osb)MEhNANAcygvr-9e}(7031`e zN4KALqrSv6dU}4eYhZA7VC#YT8owsKEP+=)L$RUoz@C6pZg|b3(0lLS@1Nseih3Ellq<{0vIr7(Zi1vBz%H`e)PA8R2u`16!_Q1blK(Rfe z&;O3$9y&d2H+%C5@clMt)^T6xdnx=j&+*4TB|?9o`Opr&=-<+Q_3OKY0Bqm*+wq0> zbAHYES5AKDDS-A~-oPJtOJ06TAH+-HAzsX%e5V&iaKSvgWPcPs5A%Klf7?0)2ZXRhTFn4>mF&a1L|pzGvbv3Z_QRx+;QSl5EBCnWIuA4-TO z+oy=Gvu_2hh&@EK8*D%6d$lJ;y34O!s@^3V;E_ea8(;&M(&RZ|OIayTak#BU)SgbngsC)(<1=ZNj~GN&nVDZ57Wgd?GhWs(0K zfVdRa4lCmpAH4Y@+**HBNgraZCZ;Ztp(S!(g;K7~9oVyBzUm2fTZ=IlP2&k$IfGaE zE+g)7W!E4m;ghp&!s&aqgX!An>|x}eHn6sYLe#FlnUYZHH!b&^QAHTK@h#Mp43*53 z!bi%@T$|i03GO+z(B<<9kjYwUR_i^7d`abaw@D`1ZulN(EvuR%!Dfh90_EYg<;<)! zG}6YM{%{nMHbA8~6ryFa#VhUBU+$o~d+xS+9`8;_9t)!0-ra-47lU>LTYs*74H8|L z{>33k1wB9Fli*p8^vuSl(u*&pL1+ly^R4JN9G3UMDH_vEZs*(XLJ%+Q+;dbf@yI1n zy^7mq&UU`b53}Wqx(w(Oz)bWrwE0)$6lW)(LDNr!>{)@m_o_j95WC7wCGrfPpX8;+ zycx&Ma`KSjZkU}xVF2=)Irns5!}da!wzFZ_(7$?98hzw5N zT$A+exs<|Qf89l$p!}J5D&A_Yt)ZLm)~v{*nR0)8D)SW0%QC-sPw|cKgjSF(^+BMJ zuW4}d=}cVlUq4)Cg}w&odv!d+ys2tm8i{zCk)P-0uNh9j8L6Agf4&->y8e-c90)tU1vn zk^mM1ZknlVC%sW=l;Z-f0T~+VMw&XR7&SnIH8Zsdu`F*P>pmq9p3Qid*)N-6rx9Ii zt`t)=HE)uMKG2hoFUe<(&xBEB`xX@Kk4_Sea-0=@)&L&XVsXfYY9R57c3UHl!_$_& zo$G*)g*Ho`nInD=JYyH(b3Qe@d5oXrZ-QB4p>F4c^qUvsuu`5|$<}ASHdr%mD8fY= z>Rux_mrfKO%~DU?h5ojRC-x#i=H$nVvWIBUIsloLC#fV^v!P1w5pKn+B2DlfXZd7i zF0Ds?sizjN2~;wHcTg$n zfk(F(L}bVtmIRzhvaKjx%BaSqG;0GH zV$0h_+H=d5j%?Qg7`k-jDeNZYjZoFYVveimCA5#GWaBqWe26GK+u^bmsHYooaol=e zv`PM-P#HoMW|^Mg=92L(5G<`lXZXR!soFR=Tz)aN!hAHI(p(#TD#x<$Fp_jGKaI|0 z6LU+4Z`*Ujl%-(fXGzSm9S48tB%dA+LeP34;AlJX#iNCTVEqa`r2_CoaS+(j$701D zRshKYTWJgjyam%B&^l8*1c_eAIuhRNy#$djK#bC65AN%}D<#hE@tfoWM%x2?J^F8t zC+s(T0C+N@xSCZEaSM}yuQ6_fBYK&saduP$IS)Szg z>+-;xVeUGc$a$?4!or!f!=!32SB~)z?9$U4ULpO(<5N9mB{)8I4)Yc6NX!B+&gi&H zo>A#)O}OXPwperVw{)5k@7*C@GiOTV4(>#5%_UC{+$aZu}6&%+l4B3k)ILQzX9k4JhyFH@P%ToMQA#R%t=P8W%Rl0T-@ z;%vZKuQbc1Cw8Cr!645koYNkfD3v{v74!F<;rRh;CeS^!=rQ|w89S-))E%srvcnv# z8!{>QP7buX()%J$qBB`0(&sMX|Hj&i;oMd2@S~bP1Qzc*hzD_xrLC@YqB+r(ZiIq$ z3bW?d7j)O!>8|vJWF8Gz;Or~jmubmTes|ol;Y<6f}?sGGnj(|3NDB=IQkni7*`{>#Sw+selTq%f|35O<$ zLdKVg-^c{8W2164Rv>qomS|0>MgCCG7TraUz%0Wl%u?6p-Yi$s>XzcM9b{JZjZKlY z9P%{n-O$cw^EiHA2!d)GjlTO#kXVImU>6?d-#J3NRrvJ=5>Pm(ic%x70wgepQHXWfrOVMPa|)PW{ne^aS{#wB3cVy)RqLiFc+yG6qp zKUmQV6koUAEaBC5X|8i;2KGPAw}gKMY@W7I(->MC+0|wl+f)-lLz%GJ{jC}_8sN+q z4M+TBwND~(`Y1UlgGcZziN{p zeeish$Owl1UNr>|z65e*OhcRDke17h=In#nEw|t@j*lC#Ii}t0J@Yw{h{~>juR=?t z@vf6%8t2YWnV?RKoQWFR5b`!1bwr_}HBU-s3w$P}f$&{$@`25KDK6~~dO_#=eEQCM zCEMbpgvM4WRvXNRa8Hrp!4^8b>+si64v1vS>ht|nxhVPfJo>|KWa<}vuN9ruHVYcvf zyRJj~o8yEMeDQQ|*qdr&13d}90x6}H4BCzL$dZ~Y>}Z)DEN}IIs^?v!LovdcV(_u(U-jsH8Gol_NXnCwOvz+>k#I}TizEYr zei~%i7P@Mtk%}2i8#K_a#0g}TWAU3FJY!Wjq2Fgir!%4;XXQh}#x~ILj1LmqDSa^d zuWY*43x9mXiLGRi6y!?k$iG1vgY%|pa_R7qq%JrAhS`-oGEn2uF4?eapxV6f{)?sV zjfX4~tp-!Ip-()>BUlt14x6U) zF`I2xlCo%%nqG22LXQyYG%4Pd7Z#)s&lIkQnn4^2w(&rVl(?S3yT0DZxFLnd56kDl z0c?^!X5Hz4p3tXeq3QUBveQFEPLW2H#6@S`uMxtT^37f04yrf$gYMaPz|UPk1Tr}R zu>ur3L^eaW%;qJs7Dsj?7LWYV10y3S~afe zw$36xyT31rkwK_=xDxqOZQoCk6*ZLB08MEyoO1gnyaj@4^y2&*`oW5yHs%-()jU;r z`h3e#dV}vK)Tn4Y(vXZ%>}Z~`QdfGap>a_WjodD;6ur>1C*{`eWK!qF9sTl`5CG?O z3({3&CFD7;jhY#!+S(MPo@f)la24mmKG}(Ozu2>t%#*U5<0IGrX6<$1?%)Qd2V?}{&VT+?cYJJznIy#Su=e+VvB7{ts)L+})p zkA_Bp?&U*yU-QC1Q$c6cAvnXh)4b|o7Vlp?)(n1|Jk-)m%A}f-SNrgw-{BYUuRP3n zS<)i!O{|svyY)g=1EJxpp1*63*q=FvWDDT7SL;xjuxPLuc}x0ev7z`eL;kIFP&y(L z1H1gH;@|N`y>yRLu#1!Bo@)nq9U&Ab)oA)&j7opd_5|U0e21{A&>Fa?U_%D;-6Suy zt_@p`iDjsq0F9^!xvVl5)H$LnSXrMW6!Q#wv!08_;2`)%YJUDb_f4r|T}wYnw*M?Y z*(&uP$o^-aE}>_iIpu8-lc$mDP>BW~dpnxjJi_~{0cHe?Jz9m8-Rf#>1!^$pLt=i^ z+NBbmmSmyf8Dx}~gST?Mh4udQkhoS}*b%xTqCMXzA!m@0fR-GjGK+Gzjix zTPfcT#lFwXJvdF=lpkZxpLAiE6aDpgvvS4(DV-Ya_f`|7Rgv2SY~2EEE#uF+A(yH% zp_({dWBj`sA7jt!l;(Q89*3fM(N(&n2L3pyk3?TDNw}pc-BV1ppo(hQquQ3^2Wjk< zz+1Di{;0wjJy4|EGGB6P{jg8@HQge^qy=7>vvFfRe`-3sy<^iOMKZc3CN2>i^yn}u zt36|Kcq;)6?x&v)QVKYl%b%J(&s?N}O2v5s9sQ$)z)cx5>c+_m^PSHG4SZ9NlD`~nIJR4bh7KxE&m@| z^_@e`^iUei!!1NW5 zES5ryas{@>k&bz0{k$=kSGkyMh|V$f6I9D21k}p$=7%hOgdFp8P#ttGUWo9}5miHv zGcQw8wVL+rt(AO(q1skv^QhGjaPW~^!$o(+qFXJ2~cKb-SA zz3+ZnE|xL_P1+L?Qoi5k(h4?aQ(N>eUXCI0AU(Ksref(jF|pti@yp6i@85(@*e~6A zd*x{@bz&+lbMu!a7dEm~IV&-DlV9}oBcZqRS^RT!*(2Fp&6tMC4k*}Z&RGShbW?zX zF=^n24w1Uh)43%7QeH3nDYA<=Q-Zf2e>KqM$)$G&*32N-L8A2Ay$r_&eJszUr!gOU z{!)q1MO>i7VI#|(cci5%`hhkr;5|BRM>WWbPwQ{L4fV>0^DOR;)ZIsaF4<`*-3~a|30sr$bHiNBbGu7N2~SQ_foNgP*w&o;iaq_TY4|BAAeNC`!};s&wzQH?!SiXE>fo+;6n4!mRG4 z*368H@`5TB(#eO(cA4s!>A(*g2ACdkyc&k{>M2O3%~GC7ceOrh@p0&BSHI2gaBOD| zSc;0ys+De%`kN70rojGr{gir`tZnHZxb!JgsUF_mx5kvMmExBg#kIUoJ4mebrXf2q z5{DAKNBO5HDl4qIBzN_ePC*T6GR>n9cWV|gjq8sI;vgo3k&ux&rrm*vjo#TFkFuG2 zO9b;<^Vi2s7p2!B_l1N!z2pQ7V8ASOQYmBmpR3t~)_^iC2{dh?$>^R65p$AkdcHpq z$Etc$-75DHKOZ=~#=ChwUL8gt^R)hryQ2JH)dlK3`FyjgFw`KLDofBNfo3)AhnK|q zp*Zto*VWr4{G-i-J+=aN&Q{OXcnDGN{fvy8@$ziamYL^&%0#~>c93~2JiW2on!K+y3)#Tucs~m$APuPS$TM*t49xzr7*`ad76^!TueVBH3J78;pNUI9 zDSN9+*?+L65=4HCz@A5;aC^8>bP9C7nx`u*s4iu-Nw&}OPvtDO{O#f#ttvWc>L87h z4EIQM z5~#RuU29P+m0Kx6yDKpdLip>@Uz(Um@1NT^10~cR@XS2F7CLU4cE??atPdlT{(7W= zU33c`AKI|%Rpq_WltPufK&k;>`=J~)-f4HG+IdHvx+W|t65UdRm z?n$CQ>KK(-7B?>9^#>{Y2=+8{IMaFmRV9R2R*p5KJ+gI9b7H4k?uK9ztK zRCel@z;$P%M-igH&|p@IYMLZo)Jo;zCT)<4xArz7|5ItSAtwCs`?=(HuNy+VUIe?b z-mYC?latTcWI%Uv&oD)Kj1QVv(+R=l{B=eE>n1`&INX(X_KZBdI_Raa8*n-b$V#~m z3U)Ku@Yy5^#gb0)C>nF=klw+L(=JgixU(1k@*X*C(o#IqUaXf1_t5+V){^A zW8^6EBk&T%xRkO5581q`toQZu2KxL})yVWS_modk!dE(1wg}&J&W|im_prQQ=n8RbT{pM%`albGUxB%IpG4@&sL@H8*0oXkvTpSoA=w-+ zZ#mU*dZSNinPL{IBRFe&Z75HSO)k2*%nb8`$}R=HWzxM8U2!nihD&|_irC@S=&1{X zx+?qZ(If4nJ<$?<}_ z=^Q^lxv8A&GJoxziqwo%8uVDIHl06bB*l2lfE~`;@AZ82ij@Zdu z4TI~tZFdZN=tE)_tbRkwIS{Lb%&0N-r(Tdp=Zk%4H>E@r)uwGoUtm4j-Gj_i#Ke#Sfe!fH zA|Lqc$`Uky3Txy|P9Vl7*%v^b z(vgO0` zN+%vx$wrQB5fVRXDDfGU;LI!W)X@&Rbx6Cw1XJteAkdG$7Wbz0mDJ|7) zccE4lUM19~AoC65dT(R-*Hi@U8O;VdjPp_D4GyG`6}W{G&KZ(3UHZ%`8oGTj%pm3> zg5VE4jh3>xZ`}chKL<-zYAvXcXysXArG&`R710JC(7>RAh&7Iu3Xn6w#%V zdzi|NmQ8T=i%c*3K43SJr6hf%gzlE@F}$+uJ47;qGTy*nF+TW>3A_CC)iN)fm7Ak9 zC773ZJ9;DgD38rojLIMIJ_Wf(;-`42{L`VposW;P-mNDYl^;21G9MimRUjo--p_P7 zcLlw%yN_bHPU-GAp>U^%#QG@pH*JNL?hKuTYWAnc`WgV4n_o>pHtj<99v^TG zsR(`+%Xy_-)4}u|uw@tyE1cM|(p{H1Cp!njIK7)Y*qZ7tJ7DHM6a54n)ToJNR&m z(4+hMum`J{s|p(WU?!?ARNfa#T89?2*2MU4)LI$n`(g&xPwq*y2( zSSKGh+5t&KQwI7p`^-p$kEt8^{59z=dup!zD=d_j9rBNL}=exBEQBkt3 z&ol|ZuTCOM8wkx5Rb1zk)?}|{thR=A{8f_NomWf8x=ka<_P*JVP1r}VTNg8r@k~*5 z-GMTf2cTsPbOZNmt_R0-r>}u*CBI5$j_tr`czTcsbGh+UArfu1BIp*}9FY zqjFbbXa9Xw%?VIQ{CUNJRhptXGyRnT`DdbBGTjeWAd&fNoBBU|+*Xel?{pQLr3cfw zvtgbGhmLmY;?>8Aq>Asgi|l>=`c_BM`~5qBJ|lip;53^j3i8Q^jU-OMoP+Rb0o_w^ zLXIV(t-vVeld{$Ki5<%AGCI9qFlf-NYD)7-An@05!TXU)G6+g$JWq4ys+7!d#(kGn ztn=lG)M&?^=!kH1tGaKn*Oix}HCCS}x!dbUt>7BnkO3aah{CtNFT|q3{%ePyx;n*Y zg(j0@rZa$3ht@SEU0RIl=?H4*OI-Tw4Hq$3aqh#4Z{lL{xkRq5fD8?MP+;WPok(3p za8W>K$gOeANBi(M{y?CFN=+GEsYueqU`dQ`b~+WuP1B^JuwwaU3+rG2KG;B?=mvO* zT{rmML}WP+#0pk5>q+W+uLl%>5qc>gc6ye0)-7ay@8QT@5)YPox1 z#2#AjL`^cHz4C|qGBtQ{xNv*lBMUY6{y3FM+P*fJ@Z-jMB!t*$EV4s7`6cvWy`dLL zb~f)M`&=rWPpx`j zu~#D?-SS_GdWIT?*FO-;XtR?jR*CauvpSz3S&b7XK*Y=ht#W4*ZQ1CgA{NSqi>KDm z8Ql|R4}=7&or-Dy?Ogq7UF%{*DGgHS#{+yLw^e!i<2eMT}!?e_8SGT3}?F!CBVxUzCh`gVakX@Q8ydw@!S^*t5&|C z7f(k)Rcl=oUE-csZMYS-zov8=1F(7~;!Q3Da_zVVwz1_>IMMNzIV$?U09i7c^~(dC zmfNzr+HRp2O)zBRhoD$D_GkpYzZ&8C`E7szIU3Dc-*uwh892KCf{T~0w){6zjq|^eYOEa0|6$Yqk!l>Q zEdN?PNwCxP>mnmMyG|yDtA&)|M11ts2GG1!?-38Y-xx!Kt|j z`Xxn>f#dsSXGbPyXCp_)$YCE?!v9Q0iIqaTxcK+w1^g08a0dF<$g};)yF``;1p}q% zSO?~41HkDD!0`&Wx&n~<_uemp;YPzrz@8-BPsY9N5ufLaU)AXgX9`ji+!HafbvpzCWq zJUklyaCB7+=2nVgW`5v9%V2qsE`Z#ffwX|V&|qaixP88ABN1ZYb1nXDUw>8uG}}D@ zvitqW19?F}LOOUv+XQL*XZ%Ws0kxne09eHtp5z-IazV`c^t%D=>m0wbZ)(qW!wKg2 z1N;dPruq>fo&yA`0o4#Z83bh2(wCPPlQ98;w0_8du5}IM?*&{5hVU%zMc#~01^lXl zzyRJ<_Vkb2{jvySYUrxy5I%QF8@}ZpmrOCsiczNe0b%}`a6Y^F|AaAPJT1Ai~>P z@UOaun8R{;@=@fAy0(ZS@S9oz{^Mk(+LwaB9{T%C)drM%A^>D*^XrODNY{WMUsudE zglh6ws`1lw`Gv>i34u}t=j8v@qY6NSb9ME5=$Szix4k&M|4=l>ud`R$|9(qqnn#d! zd<%Jav=0i9o$aq@aV0NwaI_ET=EM_SK)Ut_4-34ek^uCi1_#-c=<7e=%+8qC_tn7b^D}I&l zrMcfd{u&B~HDnke?X19mgLBqaLL0UfBoe$DE+Zl(=Ppl57@A$^*_+!wMug-{YGxqS zocfX^KIi?KI|+tuDEb9ncYM}0!fVl zJ(rJrM}^oH;JaT{%JFog9iY zm>oKiQ<_AUBl7Tm4CXf?!~2s;cMr;Vs{)-J+Nz>dOEYc86-hP%h)@I1v#g4@q|cqO8FAMZ>(<2ND?UH#oj?A?hO{Z4g+Tfxei62$)=f|-Csu* z<)~|WG=isY`G2a*2w5r-u%fW=jWwRsM`tM z86;C9`fDkpV&aLNcDoA4*LvnW1d_{awK}7uJ&!yPSq&9JeAR4&SFEz`T$?wo@G<;abmy@pQ}>cL!sWS8ogwx9jI6isR*}d~ zN```ZPu=X=*NXv9z?UNGcMq48-HjK;Ig<9EXN>3rRCy0{=hTyj|DNo~0zs}~yeyn( z9Bclr^Mwmh#kMKy5fpxGohO*bY~B=$+~3lb<4$R0;ev&Si)uEQ!b!~o6%^k*Yj|^# zMX~T$bRY#7lg-p`)RU72^Vb=s|K(eT1s|!OZt*xZwZU!*g~u@jtqN%9)@2p=i~8m~ zDAD+t%5+n90HtDt{zKBv-GRJtREMW*1o)lkQZU@Y(ZRtmetd0bl)HK_r2)0a85?-DR8WKvUC8O($lAYJr?WRdHK@W3UQG=?? z^{q693s-u?IV^6pDm*{uZ@!SN#Fj5zPYz2@y98x9yJuvZIqfRqpPrO#*3UIC^dG1H zUd+qZZ>Up&&q`SbUYLU(Apb|E}zLC5nYS0Ms}0ok~){B zIpfUL{ouqYx$A6h_QMEsfcEhj(D~-v52w5= zbZpy&P15_Zi5I#XMHN{mc`aeQ)EN{K?K#fCk@;x)b8=dsFLa(gkK zsCpvfc<)4<<)0(#FOmIDs^4W6L6W@%4HJ*;JKJx~-$S@_ZY3aHf6)@la=h=Y>rT!Q ztfXDOZo!{l6l~-sEmR;}fuJ9J)O`tO$U0uA`iA7^0an=IsKtLjMepxng3TwkpBR>h zGSOb%Kmu(Ix#M{K?>m?XUS1P5=>^-P_bqVM=@Aw2NC_tJ4z27i?NUfn)9EC1EmBb| zvVr(Ry98Ao9hMf&>gU9a2XaNPC9fYm)bD~FV;xCz47WW$oumI*$c_lue}y&GRU-~% zf*-N~=KJFbjIxws#xCUL^4U)OlNi{WaRI8Wy;q{21pVCm>Ilkz#$g983fFZmw&hw! zj`|$5cP!g2t#nMp*z4V=6#mMgQ^X-FH(SS@Gd=8iZyRCP%I4@5KZKVGv0~Xwqfj%Z zxYZq6h2PpKI^Jc0t-Vcg{6A@^0|aY>&IRIc$iNQ}e4o)_<1-VR*0H+ZlWLlF({Dxu z+4WeAC*tF-)hYSTmS&QWvz8Cr0y`|4PqZfdbE`Mhu*7s?a{}%<-`mcynmqW`;xmLf zU{SlCC|^&d+=d!O?!3Zsd`bKK+BFeVOo>d)U|yle6gv_mNvheo9T!%tMsEmGtQHmn*o?7~zKI3$*h} z;9ImR62wVhdtE#S5XoZ$9>X^Y*mm&2`sbKxQZ_(^2wABO0*Dpwu-^YmRs_qWP9%;nrpg+N|K|$^#8VIq@4NOam#X^n^F8iD$T@l_BE1{QsBsMzIiROHXXy5ons_*Ba&9ABp zzDuO@Sj!9=<9?S|;_CK;;|}M}dWBKTvdrD2JE;Ci?YabQQCw6$o0O&X*Tcv*%%txz zIV3ph!o>SVwdl!mh|l%L>qKkk5hATJt3fEY*<690D&OC3T_&Q^ zxsm$T;57mX5ti1aGG!Tnk^X3?J?n;VtlIlxne)UqHG53<6;HpYZzMlYJ6Ve}n+qGq z$vtA}PdGU0E5%9<9c&OXI(6EN@Pd6vJ=xN=B$Ltyl;;eGs>m~hKIO;Kr_A(HQ*#_$ zT3*DUsfF5*&WEGo9Dzz}Ttr&D zblr~ex*b2p1-W>rue7SeT7>+F@dR_tp7D*5O*A@VtJ)j|g}epNn-Ndt7@>%*!C(Xe z^JV>QadyNXmMrcEZvAmMqACAt%V8{&-(<#qt~BC*gF-M%a?RpB=o#?Yd&SuIm(Q|9 zTQW)qy(~=GwDN3wsG$DFfElsK05K@N)g|0tSkQvalwpIM_yt7GF7p|lI+NvaX!Wrl zKZveCbsgzw%GOG8Bplm(F2rMhncjmz`#pel$hTPMBvSsZ=`dh|$Tgk+g7i=^a_I=j z9sVnj>ga>eTzX_Oy+5J1Bb`e>IOd~KBJBQYAQhImMG&xj3>5Z>cELp2cfrOWdF)-p zStm3#9#}8jf~9^f8n5+AbN@^p-VP3G5Lp>}U zm3d$dt2RyfJF7?Sv*{KEh!+olplTqJD3(0e#B7xCYi%Evhb<}=4c}iw~4jhD=f6T9;-RZ3f=YSFtt1&6&r>;DScM8M^|mUqInsHf{}f3ZQNM7 z*BT}=DYzaHd|E@sw6imNeKo&v*1Sm~c%K_tmyT6w9hHLYBJ@AjRnh}bm>Md5gp2_y zxy_=wD26;jXQ4ZFy4Oq~cer`QesYJt7Z&d{-TramIKggAo}Vcm1(P;T!B-lA=l9JA z50B66W5<~7Fxm^^Z3-3H+lapqV-c*%IDw>)571-36)ez7ASR@>HlcJu<#IU=jS5JG z%y}e$-lvDf> zeT?iEGeqWO!L`+xifY%8{-Iko;u^oeO1K+iu9X@zdI>-Nv!c^~d~ue$YFzw5YQUf`{v7P|&t_F?t5iM@<)mh;zFn{|* zt*4D$&$j+Un^@&p3&{bH-c#-Zv@L$w{O!d)*eEKXIF2%i5L68@e9jaPW7mNhdj`EP z8W=NRca`YCpA#&6^w!G1)voQDA)!xfi5_@e-`?lfiroqYBb@+s1u5M2M{2vJMs`J3*ZbiQ#$&e`?6Tqym3u*Zkq5?c>-j6|PM@FpD zs*d@W21=aSSD6PN%WGSM}Lusd?tAHu!&2sjZ{K8uj1lCJwfjm--Ms#kx^0 z}ttQR6Q+F-E# zHF5FtMwQ%jVAm>6{-||dd*AXzZotgOp~OwuNI*=hBV35lj{oky!Z3hek+ z=LFh}%pma&)=KB6;-s*?41-%5*m*_Kw9Jz1kyco#%$90wUXez&{(5IhZp?;F@*-uG zWqYqU;VO$jpVS9bO`R~o6pe;Eag&(R8QZFiLcv7Y(^m1vDt_$ax5CXe2ZerP@mfOh ziEh@#Su`E7%M&X^=<#AW_4);xz6wJqo9KhUwiZpz(m$Bdew0OAXSAYF1c$8OqzsDE zus&d}YlI)7&XUB7siU?UU@Vq!RimgW(`@(%w6}^}H?8pMi!FPUeY_2kBrVy%S$iy~ z>4qcs5XNZiH6Tx})Xqh@*%saP<^zAE><7 z8M%Pg$*>WscAo1fyslJr;5^D9ZQ<~j)8!HfHI@K zBdQNEpE=$42d?3#&PS}M)yL6wc57-j`5B9@+pg>RZJQ=MV|e%AdJO@ZhhM3_?+pJ8 zD90Q*Nalz{U+zO!x4!48!0{I7!)=zn^sCg0y-;AnB7HZWl9{U<7M|)T+~iGD={~ld zv_%GrUevPix7>3?&cxz>Onv<3JhON8UN9=g!JIxW@!x^A*qZ9Vs5t=sQ&c%_8eA0? z9(JRsOt_d7sd}7YCoRadVx0d(gIPBsu>P46U?ksxbJ8TV;jZ~^$tO-JJpGvG_1JKn zT;b_*4}2-2^){D=+~N=hPtVP5kkn0wS`jT`+fU=NMeT@61jbctspm(V%v%$#2vr&+ zz0qs~PDz1`H2cEJ9Wkrjd#!RMPvw+R$Yo z@J)w9!x2tC2>Y)}a+BKN5$#kRAEnP);81Gq$CUUot;prqj-9u(eDVS6vHt6!u_`;` zP%H(^=s#gC-6EGrS*_QR6^}DBm4m%W1ou4MMVxd`U?5g|Mi6C0V`0EC!L~dHr9yF+ z;#h820lMQbFFwMV!5=V^Dbu~>)W@7z(Vg>rcb!!u^+yO%#dd&rHZq_4b$J_meQ>1E zuIc#Uv@`Z3?A7ujb?`NXfXEVDOB?h>O-$Ay!a!CdL3liZ!3Bo8_z2i{1U@w5}mcT4YKi!1aKjux=u?l3CWf0VbIh;S|&NLr)RbNf&m z4wjY?9P`sml~ci@m)FgG4_?;p+MZpYM^*0@gQq$I1Dvi9R~D=$C4WOOu)k;)Q7Ilj zfH}RI{1-AWoWGP3W&c*Cw={VrY@k+&9bwC#V zcxRb?1D;b{)rvF^-dLQVAF#x}=^^VW{Ae_s`P!$A}7)zBDaPRF2L@GwY8Gp9Kw%$4RC0@PzZDIKto z%4;<;!FyDXOFsR2;xCYZIdt%0%r^(>4|ez7Ixtue>jT zLR1i9Y8R8ivK$!VIf6~FIcHd>ejmOZzsDL*UgOzGZ;55XfLNCsV@A3AzZ^YoY(`-h zJn||FWn*CyI=`DD&K*wbW!Gi#wZJ~z_b2r(?VFm}=#7$Ll98d^1!;-WI(_p}{ZT_Z z({sIA&_O~T5Cpv0cIaco)fy!mYfvN?Fi-nfv#wm75w2YdDnOrMr!s%|KE6LSas@&q z1Pzco?Z7&ym<7|UcO%>W;7@O*(}y~E<07=;`IY49N@Ys6Lv=&Ek}l<3dL7J=f+(_V zssjD$S94>E(nCn%!1#&u+5jm&yXx75x5}r;OCc-Hw&P}0>5JbY2>8i_p!m{5m@O-= zocXwop6`ZgB5N47dZTG z0(rfJG*Jy9Y;O}6ohff+(DAGawEkOX4$27qB*;3eZ1SF@=s}z%L!j}+@DLoZh{t8O zUSno}#wH)n-wKKp#;4i!n~k}Dk@q{;^xS_-*>ijPrqrpkIpAE@h9eGdJxfBE_MJF7 zh>SIAXIQS4Fe#+CdQl_Fs2v?G#BY}Dw`I*pJVx48+7gVOzM6cTXSn=C4Y8F;5i>k8 z64mJpJEF3{Wo$7{BLZ0!!QkE-$TaAzmSom5ZMN!r7zZS)AmTPket@HtVVo;34 z+*G%$ zW-6JL$5fOzGmDVO2Zk-^fZoG&>}9yN`O2ZzRT>mc)-NgWxv`B3kMRJvFT%@X%qoqn z`j(6A*iX1J+XJoCbH1xAHF6HhY0SvxWhtrG=OZo}l-t&yd=zMr5ci_e(y|8$x~BRo zAX8jqhTH}sUEhTeZBT{?D53eY>5Edg)0Up$H3sC=guJQJBSiYcMAGp0TdZJ8WqS5H!q80i@!;h08`re?4=$BIAYo0NR*vFg<9fg!`2zeT(`!lDjxk`D&2 zclj;Lh5Eo2$r?)}C@72|gE_VJwGxVz$&)n+L1!2v8m8c`7UC$2Au|d?T)ylI!b^1o zy8Jczdwx=BhiN7t{^|EA-Eqz~`f+{y*s0_zz~S0toSOFGOH1gkWh_mi9c+>N#-7zZ z27PizqM}P$jq=uKzwbyDs%>_mN{aA29B3jGXEwofCPaExV?)J3)ZfIlHCgz(I0%u?5d>Poip+$lHbiuVhf%U%rBI6e!tr z&UCCuQi6i9#%f*NiLj9s!f#EVSQ8Bywo)8v8ttXZu9=>i1UNRhx@3_7>d1iwuO%hK zWTp%RVGA^>w2MkL2WLg%P)|3@s{D1DTP1pvBntIQ%!Za5;It@dzaun8D=Qtg?+YZL z?*-DpC-~2KSxFIg4TtL5j%hk4kfFu|UfEV|`mmfuY_Y>TmQ@k{nAn%+0O}Za-99s#8tV(O*+jJTxwFVz0cjf0OM zmzRyPeB!WF8vJPSrB;P;FyOliRMAGoW|h6)>%xa@2vm(O~aD1ltTJD!mrEKl1VbuL2U)Uc8gW&I5#L%JnH6gq;qyh16V@E z-G8+ zWm!gHie4|dU;WIhUk#@aQs33(HimFNbcn2h+9^6WS9vRNl6-Ruz+is;(Vf2mlQ;FU@_CuBRXFc&*MFiuO&$AuaQcwE+fb376;QLw>nW!cKR`C zmj-tV6XV!-p}Hc9fhTcibvL01j@{pY2PdkRUgOtfv;Le%}0u@ zv{oL(2@afnYcjF*3|dTgIBxc?(8d7ZYzy1g-JQ_0ADLX zw14{)7!Rd6$Sj*3uXBhy=h!fK`PH`J>kxY6G@isu;M08*MV2gb%3F*{6+ol_%P~*W_n~Y9yP`lfci58-Cnxh@$#ZNM?If zRhjcPryHx7`V2_-LxCbFgZRsXOVbsL(x9|$^W&{x_skJ=)&u+;*%uzo7k;m_DJJ{)ck-|GIlWDfdi#8gjEBq4n zbws#Lau#|s6k(LbFqd@>i74!g-~(!pZ70(nD#+l+XVCvpT*k}oKvc?&JLbmK~F|{vXZ$)#oe;doYFS5&o`T%sT9%3u1MA_FcQUne;i|~|8Q|0vHcq&^!wt|Mj zU=(#oBU4`L?09i?eA-%=`clyMXF-iTHl+H^z$H(DhfX~l;4P`Bxx-LDNNL$E-buS| z>Bi0-u{MJytJ=NvTzS5qn>X;m9NC*0P&%K65RdtuQ(hh4rtyBpw;SEG>=ST(chePW z_hLIa2Dn>+p?qWgK-zS3T>k8njWtFY+k`6y$5;S9(QS;g6YLw>)}a|%ZgsEOOxa`AOK&sFiqoY@^#-WHTl>zN;M$sj)* z_7EQRoTg)|W7;AZ5Rv|O5$zCVuC}+CGG+b?z^$9I2J^If!c0EoXyQt`G zrRQnV?MTu|21Lad=w;zn4SDF3BT`XkS&_j}ys9^>THmE~GwZChI;E2)#q8Rn zTq6}B5m0*Y-jN7cJc|>EfmMyPljWQ?S=#gwv4Sh)VL%xWzT8 zyM|-wRv_4;9m@8TE;yo8#q2KIjYHUv-b!3a@br4`qS2hfVceESdOnZ}D{dJ_sy!J* zPJDudjb>L3=3hghMLC~;EpA4?@M{|2OMjy%rNocADQSfLLV6%8h;}B=@<=!pOor0I z8Gkfi;IlsfeF4k+|H8&`GXAe@9OM7-wlNW~v#@ji4-of%vvC|OoUH%PY+M_t3d$uK zn@m}d1Ox@cu*A?j?BWh7DGWnD0y6{54kfK_5Q{`vO0z_iOBorkr~APA@F@floLcG&_IB0f`oB@m;(sK z0GxGPD_Dgypz?l01a+W)G}{}{fGsV;g?1lvi2X(*Q2U68h==bta0zZf1pm|wFa&U8 znu9qC?3#hNfm{yM6d)F_^a(YFZxSTT747Wc;o<4(lc~{h45=q30q+BdZUDFt)FB3O zjbPtZ=>&kUK|XXb&;b$tnS;Cj0ACH-Cg2%>fCK>H6sRF&P)`oPn!ySJD7XW=q^vuS;oAWJb`lkRwaC^V<;z^ z8mcxukds5eSWMkl_j6JJ8HQSMrN7-Xb`2QdHQ@7~WmCv#nW;mn-pT2BF;qZjk7(T1 zN27??$Dc+E0)Yq+ARshE1Q-SdcxY}s`bE{5o5Fn5o_K;5JGnbMf^i31|0fmjE@(?o zjt_*dUe65@Akr@Q?enYsU>_L}4sHP3A_PQ3*s6drz`vl#Fnk&xlf?sc3CRFh5HSV} z@bmfY%OvbLg$3vQ{5kgh=Fowvg8JgxvhI)m-6kalb_;oba108_;R!16pV1GIF96|k z|Lu-K%ivsJGvN0@HEg3FkjOtt^gkvJvg?o4H?0pX81?>61Iq!$m=GY%AHog_2|%-; z*W)+e@^|axFMg-5@LM0^x9@|Zos;W#weef&&%fD#yu4^l-wQ>5CxPO&YDf_q;7eaw zcs$=#HC#h@C+AnaDh8y;O#sX6>fIf=pcYC&KB5H;#nSXGoXX$fM<4nWB2=(>zjj_9 z9x5Oi9OM%p*Q%--M$k1^$ff|kQl;m2Ki+8r;G&U8~gy+VM{=fTVq#yQ=9@CY*jd~dO#q2xwz6b#&`!CHCU|WJ4tpp6~m z0sLKkLd^~W#OlCb8EGZ{Z@f<*9by>SNR)vexD5%qr4HJbyDri1e4yi3(Fm#CE@O7` zf;ry8y^CZ}*05$4N>4OLsto3JTlm#OE5BF$6q4)c${zA` zl;Tqix~=4DZ)uAocHZq^|{(#zxAEa$4u9| zNJ}C0zS1U$S&e^`rQ8H6!#tB$b|N77xOl+0%YR>z$JL3;li&O~O^!4$x8I&Tt!{kG zBbNQvXw$nxD1NOaIx2E9BMI#3_&5AvjE^b1f(qWuR}a00h_6^yxjEj)N$S*b+vGuS zZJtxy=kMW~(Lp68G%5)@S%#C#tVNY_p(2D2F`WO)K+<$Y`6FB*x`aC1jObZyNwFNR z%BV5JZz$<{0dJ(~W+nC^EIvp3F-gRSRDw}-8{@&1aZGr@{ryZdtCRBWk^iF6QmO~p zatc>B_pdq4O~;x4j3>77&Y zk86M|d}?#`zugl|4bncc9GHHg$dL^>nez(P(WSs;g&&O<<~xRqSo9;+$Svw)YZI9V z4_M2C>8D08^NY}(Y5^?tn9ss zriU$UC{Fkd59<+SreD&a7F%P?tGZ>QD?-l|I25@llXn#DG?yDNn9R0#_$qSmW;C`e zPk#3rRFSev1f3Fr&jmsO+AJnw^ zUgI^qE}7O3R!Ni-a6i zoScAwOPm9Al>hB<;&`1Vd*qpVhX?1i;RI8m22PHT+?Qicx*UWxVvSG|NV!&KlF1U= zd_Mytfjc&7bhi zSnf*N(bi9j!=gp3uwn{Is%V0Q(F%G~b;-GFz@;I4B#YKHT9!k7iWOb~?*rAu!{KL8`d+ z$tSkKP)q16ept zw#s6Y0Fa}Tl2x8Jp@_qD03Yc|&OX`M&iw#HK44ER!t)Ay1vme}rU!Q(<4_d7&05>s_ab=PEs(snNvOp#^9}2rRFpiK#zFE><~LCMm50 zVZqQ-db}X#Tu#zTy?5So_f^jIFL%YG-^xGIrj( zRI4yMe3vcAgbunpdu&Z$u4|X0Qzf;4<)W(ZGzY4!W--~?h&$`dr9Bc@Css`MQOAiwhGaeDx z>7TcoRc7Z>wKnQ*&?Pof{*r_}Mus*EE4#A&r^3(J+kvUPVJExiwK_3h*DKq@SVF;w z<<7`5_qSjk7vyR1J55}sY1g7VzYxx+-n9MH=D0a1qz+YvXsoDr$>6mQzHj}gcR)1r z=*;59-}|X{x|(ca%sBRj_FO*(Vo-D{?Kir>q`Wx}5oh~3Nl}(ZC3kX{Rmz35#%=s~ z3Ww1+3Hjk*oH3pw1RIGlL;chXD?Z`%^6-p9$p$F9ikHf6gpaoVb<7?y{623JdfA!V zF)h8s)ko(FrNBWbwJ*F{GUNCY`zVtw8ls3WqIm_<7yn)j;fpFyGeI`zTV|3 z=EtMFQsT9^6Ee+Scnt%Y=E@6|3;Raq8*Ia05+Qk*$YCp0LvNi>6;)MIR=_4yt z%lT{;2o@M+8H40*eWJS zQj2nGyA<%j&nFx@(>k}eQ0t(439GLKtuV^tOat3Qyi_lIM(#7dRa`)Avk+iKPte{N-d#hq^ez*6mf-DL&}SHRa#!#))8wti(y(KALevQN3cvxtKJ zjaKF*hw}unRrUgz$x?#w3ISFfT#hb%>sp(+DmjyWHI>BeaM?=;S1YyWRE*&u9We`P zBeBYQ8(N=mA%KJdB$Xt!lkhm(JwEzM;V%~ANyanAyUH6l4nP&|u{J~>&xX6qs^F1n zdkV#{kv2oE$X%cgSqkQqoAV^{A%#sE#|^qTPX3n4wNDQm`{AY5L70BKucNowNvG8< z0KOb^8&7n!lcDMSyolcBwmIky61)P@4-O{<=Cg@}%qN?HH7s6(SjeT`=~Ea8!7P$N zhmxFx0#nh`+eIeV-jd?~GXZ!sFU(*^eILNRos78!(GRS;&S(? z%Y*D8s*j^&4IY}I^Htum%xvAV?N`ou0kXS#XhlE^+E4kahmQF5{j(3znlF+lMWoug zss2c+f8}c!RB+D|_3;$q4vnT@B( z1`$0BHkn1yb5@`lg$#VdbHU!nn4uy4-4^5P+zQ5Yti;>5Bb|^o9DmQM1A4Z_E|^t; z9PR6=k~uj3b-EraIaLE6vW5d%L{LoA`FHJhHR)Hu)qFAW8*w4oDoH!bIIt*bL&9Wg z6su#ztfv2iU`Avt$Jd{26^AMP404)ASHdXPnAG%P%D4Jll zsQgJ6d&X>Idz61I!1Rs2m1x5UFIH5VjR1g4>VwQiT-U5N&(++A1kyU(>sL;y!gbEN zgm`f+ccoC+c5kRAACCL32Vr{$6<=!?$=B!>xOmzv7>Hp|)!rDERtR z&SH2|rsd^U7s>v%W^hWicaYWlF+`}94h;*{r6&C@GouQcx}@(imz|9lhwjP5!pGkx zbM|h|{x!v-)0Md4D27b8SV}~`+n37xyyOziOmJNw4k9$NQNDAv#00`M0w6Iid&M}d zhbd}Fa$YIZn@w`Z&@OI0aL&EgTArq_?Np!^j%Erc!tfSPQj?EfWX)L|j#ne2_1`z4 z54rJE^4#H8?VW74rk@8#E*=A%a80mIBh_6xMg^m$5%V<{;y6QaVp+I8i5P?|`F51H zsglFq9o|LLc;}m;mjva^;TEy|&%&`26eVwBS9&sGO}gTvRwNm4-mt|<@^*u3foHeu zK(*@8wKc3P<}jzok#I|Jo+1AGQTD7<VMIaN9O6dr!xcBG;DZpSzK!Va?(vr zLmPcfC*;(MPfi<5lilj^gRT=KNTx=5zcQ4-BO~?eml%O7%G;)OFG!9{F?>Gz-;1S% zcxj96-$Xg?M>`p0im%w0NayAP+A^(fQ^mNa4S6d1B~g1EH0@j@!EV-ZzrV3ssFihg z_9*x$QjurRbZIueP=)2T@l_r4CA<-NYDB-=FzzwJ40^PB6qh#ejl0V>csP2-T=rLg z8`2UYn+D|UF??mQxu-GM&kQXL8Y$>>Zv1)sy5bc2J_U={py)s}J0MHAVl^~!wA|)V zk_yZ)%&-40s`YKs$OUBie3N26cr}0fyzhOnh_7&j;`_rioVnwKXstTJb))+6$>f9R zVu*lptdT{{?&R~bLAfBn?SpSn(_^!)n{cz1F0$1OEjiyK2rc>5_#F<($@N5MpmEC1 z8fmx}x90)enI8F@%Wx*dgm^C<_@Vz{59kqZ9*1q|IAm5bMN;l0?@rxE@xwzcM5qF> zvF48XUjg6Cd2(_!Y0oBI1sJCNBYqRt5ixDY$EJzv?nz0L*_)(p(bRJ*d>na8o<*n` z!a+Et(`y}oi^wuJ@LCV`T0GF2=10U4^V{;4oMUtfmHvSj-*pG8!Kf_Fp;4wwO$UlL z_Ny-I*uwHureElni?`5lkQyTQ^DJs|+JO(@um%6IgQL!%7#@dexuh)WnGLOa^R>%0 zZ-6e>lJ#pvC{Oq8j0|F{`@D3QJdQGEh>3Q!D0S?JvKV-o@q$I{sJcT&m;q?^4VMq3EV zv|o4L;|hl~>8;Hj12nj(S%Vou9r%H};{Xq6hAJKWPp3=tn{Y5=Zg~1}&m^XO+v(-{ z3r^=gyh!CDx@e?2IIJu^(e_ctt)T~~6m$Z){qxKEuRs%HawED)&&`vM=4p#W-GdMT z|7M!8QVKga7qgK(VQVbN`;4vDu2G#8x~-Dg5_A6%OuT7_7X#0eBk)4gbW!5|wLzmr z>>+aS!p!D~dT7xiFq1p(e{HpA9!wKFTzPo+8%RidSax*lk(qJ}qG%^hLq_@@yIHgy z+oLRW(;ev2f2^2eWod(r-GaSmiyRcA4>wthS?-rlR~LtI4pn-_C`o4X^!{U;7?tK+ z*4G_1F6e-7!B2F2GnjX{V9xsO_^tn0b2!h-aI#%wryG@>ZPM3fx{FGRk1Qt1qJ2r}Vw_NX$=i&T~06iO3!wXo3T9l92$5iGV$TWZt4h^8kVuH z)RcIG+PY3M!+iVk6x$+4pOaH`*pArCSg?&^+}xxqh4wH!M=DLzv7dtdS08s@5_DSuGM=RL`D2#s$v4> zL-rNAV|lxZW*@{QzZXHP@uAPHxdlr?@ZAA|CNgsDgl6)>uPnD2Ic%_#!1i_+2aC3G z==tw#;-S%2GLA~~QnMwg4m_iNVuqnVWO9ZsaHw{jHU0MQ6@>*vVL9o$ScSanT!V=6 zW3;Qe3EBM!4+iC5-}2|l0ejoxYlQaPZ^s_LRq*;fiZ9lp=?1uxFgV&Fnu!dtsejXfOzC|XIZgH+Jsl$1+_d0WOiD&v$#%@%C;Qna^vJ+EM zelZT%qK3~MW!pw`#ds3wMSz8U*b8VP;TjkAN^rER1XfYQwRd_%^qI}nFhoZ+%vNVS zEa5uXK=U~~HGh_}(d$CPW%`ThdsT~tsG(<$CtQg=MBSd42My5pM;0n>F!m}W!vUbj z-?M%u^*oN0H^&)XghVPPv}Y0h&~?M=<<_tQ)j5>*M&idY?rijVIx=}WVG50 zGziT4WOYL1CZbD_vk z{aWHqwz%#Wh|p>=eLuRvr|>%T6(`HmC>h(3K=xad z3%p~5$8D)L65r&jC(uhT3Oq(_y)SGz0$HuV?D$?6&1_mjH zlq>^nLKo!Y=c7n8gkwU8$S=j&@#j=kP7^0YLL%GXa_xj-_i(#Fp8Kj%CfHoVSO_`L zOpx$-ylSE-AN4??X{rl*Ezq7zNO-YWwSXit=pK^K<#V6Y>UMMpnY;r%98k|2iCOM$ zw7*Pi8qJe~=jP#=BGAHOK_n#;5r1YF0^Fle~iNe`y-= z1zm?YQ%mfm+OajcOyxP^U&B$+yJ*Tqu^%AgpQxuVP?NZWvDXl?Y|2sz8dj-i1r~po zMu%c#uN*Ml_nyM*GoeyJ=y#6_O!eyVB*@^H`Ndo7f`u8dr0aQZaOmPI zCEra_thVkmI&dWg#La56c=C`#eSvI$o>o)Xx8c&XP%SCfM;pdp%LE&Dq6Kry>UNtmp4QfQLmZ-=SpY{aD{QhH2e-|*F3 za5QFceYLO(F*pq;F1bNUlPBN!1yHKD&O9_MOit_ zRdlQu*8&caD#LLCzX(6k(@-NiM!eb9-KE}IyV2-kJvNzSIiL(5PbNl6`9FekoAhu| z*tw`NuU>N1W>8XF>liA3<~4uJ==V)u)jNxN3iKX$A-Ut)0mV&Ipbl*Z|1g$>493O_KmO>O6YVOx1_m|7qO+-ZF>&drlAXcc6B#nJ-= z9FY$lL~LOROq6`NzU8?hM(+WcP;G~9gJKUB^29Cx+dt99e4$_EB9gt_QjgIk#vhuJrg)dTBoK^kVck-2-gsdR6zE>K0&R^0!MLGw)N>?0npZpE=Uz!~ z!cu$wQYgM^H(YN#(K`#i7Z2@7IHMBP34$-e(WB?ao2?=MMoLNR3PkO1VG~b*F+(K|)3#+a+2LbCDo&8>psjgFH zZxh1n3$7euSTxY}>Vf)noB8x#IW%HUI+E=R*dI)dJm@%ZOjVWqJeWa#KFJ`(&P*%V+DtXYw}t z!ML*NUg6s)hDR-$ZL#2{QZ(!$pH8GD??HX_F#9q**a7jZuEbX(nL?|AJSNq}gW}kN zLZW8IU`{$L48k{?lc(|<>$tCtN(0{#7xm(`(@jfl4GyZtSDRzToA9j_ST)JHg%!pH z|2&4sHxehBxjKfY96c{Q+V@-u>GIVn8P#Yg?U!|^%5y-~Ls+}We2&f}kjvbY53cpz z4C(iYwgPVLxHvwXf(6oOO+RitG^+9S9DEs@X8CanvXh+k22auQ0fds+xjGS_qdI@4 zal=0=;2GoClf>z4_I(k}5mL>*3zeVjOao%%&r!6Fc!BVyv4tT!nN{Ou?!+SX#=Hs^ z?1aai!A5OT{&h4pZ`*d{y^7y*de2?FiYeygF$XX^e|8W+uYX*P#f=_sF6KDC4i;p- zNJXhY2CKLVT>$c)3NUac2g_iY{aU(B$42BHw_geA>rQYFfe>YBb#Leczh8z4tA zl=bqEq2xVGvIZ-ikMfp6i-^;QDJs16jIP(B2ww>3@=fA5U3q*2Nr)Btq)mlMQVj50 zP906P$=@5i{Nt#fB2DpT>IF}xUrdm^I^Dj4r~T-EaVT7e6(?VJVVWuQ=Dpbnit=~0 z2d`pCM*8%{uI>JIQeX|V*s|Fsp4K`+I`e(C&Ms@aQhcZxMDTuMK6O?T^6wHWGKtxW z?2fT(ol%B%uIqtXB7uQwkb0xA*ea?I(0|<uK8ZP%BRJ;T&gvDJ7JS&Up!D z)Nvoz@z-f6N12;<7HB4lcy_|r%K@v4VjgeIj&I z5@?t`+O|wjn7Z?vSnkL{@pWi9X7<~Nuv=Z)EdOP;$tnX*IpqUk^cAWYUGm%f3}}-x zrHDV+?o$qS{s8%%LJa>mOyfWBg23L$3W|s4e^3lY0!B7=j{m8c2sjy;|4;RQV;YPM zOw9kk!|4BE*N3JWI*t$`VVCI-qZ;PEjUm_&sI1Wm&G7nnL4`;Sfk&@ zDgb;0;^+*h0pObo?QUZU{!z#vCnM&c!n$@Yua0aA>Bi~;0*D6)v4#WU;^}N3s_Bmd z7~2k*@lRl+;)U=eZ*;WA4g_J=HS(pZ2paY8EPLA3?QKL zKUQtu*51{ha_OKopK=KD<;?EF5Gph+gBR;da0`Wix*U$dr|P!$B5Mk_|HYnMj-27h zEkwI_kVm%xW=ROj)C@duAe+JOF%gVAa0=gUJNq)WWkblIMq!qJHbuWIF!mt-UjG=Q z&+ZTSdbkG&xYg_Dmm7s=HVFh4()MfgBkt6`v}D5S;=J}l@n*MNsm8$WPd*Cm3jhv} z&kis~+Xsu_&g1^;hQg|Jr$^KFd#~cJIRGH!m*CS?{EOiFUinGmM?2!w=QrvJ>y@RB z;D4M8$bNKk$maJ2@S8jO1)uucd;Wua{L8fWJ1M?`3G^;J`JnavJD;%;KzQSKj(@t0 z`NQ!^RW}Oj|5JO8J(qh~0n`A%z4=|M3TXS$2ArTkJ+_+);hF&289=ktXYX{$FMceq z{rMUw*ryPOH3j+gDF|o}(BA$l{@SK;(h?gRx_HR*lmD-?H|=YlE2@CdcMRzGh5S}Klg7=>#}xQm&lzj; z8T&O#3<1<0FvW;&YH&gnz{VOto2rtKRD-iwXs8smY4<1B$(@d)g-h?SfRwj(%DeT% zoiLqc?r-mxO6ak+Vf@L=qm~h_ri4m!ec4<+8N?oZuRO&lqroS>D9`xY^4=L_AJ)VAKPAJ5OL8*; zHS%K7&T6_^#UL=cZr&T1es3u6op=M_* z^;FKEe6I_^d`(&7D8Z{ zdtxln5RKWmbwpByNh20+r7YzcE*sTH8Nu+GlGw9YvWEjHW$p#h|H^UZcB-)h8RrTI zcjxjd_pB`pM+x`mt2(rcP#Gq9`7E%lJ|_7zx>X45JCA?QO!d4534g! z5hM&s2;OABt5z2Gtu*QN-^u5+BSy3h^Vrb>+8%Q>VDQGz96Lo%|SYtrWDv6>Q$ z2bLyV;NmZ5H0bR{Q8&Ujq*)%OGo`mL7jKw82S{frG+!x%jXcbR zttPEI2#|V6Y<^Am2f&Gy_ae=hb~zXcyVdPEOEjK2B|p66jqTMIoXKCU#1%$}gt{dj zmL1$rbgR(%i+yAi4t366EdkMpyH}QE<|vhVRtB4tp~75g+()en_^T=oW;UD_exA4O zsySUd{BcI$^ZJc?s-j2v$3EsC08>|7BzNJY?+X(x!ICf86+Reobg6?r4Ev!AXun#J z2yZUVin$A^bfvMlD*M023v)|!7!AmMjYrOR3?2xWJ`GYo%(ZllOcN2|elfB|gG%YO zbAMX9otG*<7}440y!Zy6Ocaf^_xjh+dS%;CCkCTzlNeyYHhfamR;#lh4zdFh9xTqr z!)FeOYLY02hd##WcI#3nS}pR%#)BQ=_Swhft#MeQLTAusXLLv}P=K}U(h(U|eZa)* zr{n6BiY#x8934222LU6e@a)5`3-g2c>IBb!w&Pk5U%51Iu!^?kWUd`$!mq6`azL}^ z{R>XegMu{?Mxtb zQiftHlXK!rtjm_VNu3#6z#GbOwwR!e`rrcH(CC!GYkz~{iR|Ui-e0$st$rkc)V;IJ z(J3)qVin<^?=fY@ke1Kvly4Vq@0$`ruB*|_O%lAF0v)9v$A{DSUqA%kJw9m^Cp^#whS~4s1)Sv>O;i$LemH9QDp!l{_T2&wnbmfWpG!)U}D*Xmn^Y@K^0&{(yObALox{)n+YSq+k;;LNmT zQ3z*WsbWfUsQs0L3QS(;a#OOkjD*O1a=>#pMVb3@H8gZU2ai`b&vMEWF}!$ebe;(3 zqgx|2v}*wZE*89L!0Yt3=P>ZqiXAwR&Upg8I^A`&&5WSV@g1+dyuS~(k39PQvuBlx zAQDmHMOcZP<4#Cgcu|7k9c@8urG{Ysou%!Thk6dYJmoGCtnVX$?=p1Y+i@{IJe{ zqXSXRwCAJ@cke2&%H>es7@x6C$EtKrhSD;z!*Ov2)!uiuqWCQagSWjdt4`DJr7CyJ zx^Md$8RQlmir1%Ag!x%v2J~b-hhVN;JwtD98 z(|uJcD`yLwi^B5wCyu#;nI6&w?<^|T8l*+fcmk&5EU%=vp5W9H6Q5eg{%9jY{0HML zhYxkOozQUq-P?2!?>qTf$(e1Zp&P@@28L!OW1*WIdtlWS@|~z)DN63P!h)0GksTbw zg;{LvD&3vldO@OP?2=wNTFZa=UGs%baY1l|vVLfL+ngo-T$;no7N$HmW{rl>Ow0D( z;RxRqgo|pJZ9E|3i=I**N3uqRLYN1j>(XjV44#A1gSf*&@DFIE@Fa@}I4%ayQ4dA8 ztX($VTUPO8RBifjZ;ip$x<8Ht{p%c8%`CKHU8Saacuqm9t}H1{*(8S+Q-{k<{n~s! zF;UNeA)}M?oD+eY7z-9{a%szj)|nW=r#XFGVw@J8_P3{?PQnmS{V|2RsTlov*sq(5 z78-rR{Y-1GH|t~DN0={U2HBbRGc(g5n$B61M}fs89JEb&_50GWksN;#&n~2VgW;dA zK6@D@37I{1-l3kIR^vhokpUJ6o+K9xeA8=weI2YhS+nREz*GStUrWs%ITERR=eg2> zGGnoXGp$yEo?xLeY@XY*q>kcQM?`$j1x8bkeQ8ZkMtAv;1$^gjk7~h-wYZp8Af&$_ zAIcls!#3LQ2`92uhawQe3AmwMOGLG$JeLXZ|@b6^0W@=ov03Ct3a}5l# za>ZBbYi3Y%V#u!C3k#a|FN8laCm$uq2!x`?q({!iCgg0lnto0vyp$LFT5X1^lz)Zw zG{G|tG+x3)v`&B2ZdjkJNmYgg-i1vT?M#Cv=KY7R>zbbM0Z%u()$OLtE245L#Sy30 z)rIB_L$9j8?_2keEr<$3>nG#U0|&sba`IVO4c#On+?fD*!0f1sGI@%C$Z^cOzPdF-kdP-L?>u1C0hIwpDa>1TC~!vu(C@&fY3gi+CB#pi?Q+Jt)C^ ztD}iPD!ld?rqNiRTjhOh7YLaB3?^BY8}iZ;gQl(6Bb+Q5c5UP4?58d@V_9= z@Hs8-ZFae%;Q%_P)@<+zUAsmk<`+P*$yFFLu& zJgt;SerAG`;ZSr>-yayi+N;&-KwiF>Be*hRI*M(=(J zt)wg=mf0)40>;nbPg1~XIo=am-k}(78dtsSugD6M=8PT4mQpjstGlz3*7Ne2n~wAY z%hpD!H?ROkwt$?Tb3YChI34W=0CJf4%AWf(g+bDxe9ac!SJDri8hS4J^yKAFAtCw{ zIY(4aT*S;jJ+F+T=tuVUck?~FVG5&fL21-)tJD1mZvKW`eecD$VhhL!{Fb@_80eX9 z`?kb;IQFw|Xkh0iP&n9;8G18s$CkswIq9c|qszyKZyj9Sh#A$`KE0bk8P9+?S{1jf z2PYqtzz-l*u-B-18`H+=X(a>9AB$zWV$jDOAc~!QMI!Oz(nVL>KGT2#Y_nVC*4P%N zAcetwcD6_fD#W--O;j|7;rch=UZije96jfpgp&{s7Ttm)Wz%AIvdE*gYIq8jUqllx zmK&GFk6PVgU{`3=(W3GWg!W?b4^EUB$yHPf`Z+#eiUTW*G9w{dW335opvQStiHCDz zSMA>IU&-ZC>01s^jTJx(Ynew}R<4FMQfAkyR<{NhQOlsf*fCE?1P%FHu;YmoIyyOG z+xmE|Y0D3sSzbU>nfPT7DnwX{u4^0?Q030(?a|K7o`3sKL)NA<4R1(P$GyL*y&Q4l z$7fSFXCx`Za=M8X(#QeCwb3zU*Xqcc>?y9(0(e4H=e~9>uKlTs?z|Ek8rvkue2?3k zQdkf&RgDXMW&_tnIc2swAd083Qcm_(zx7V{FoD@w6OG+ug`S3N%cj{vtqeH2c(xCE zG+p4C8D_3Nbb3;+CmJI2HS(9!y!aLm#abFe2Ci_QT&tchTpv8Lf&?zr&;r@j>uQOZ zCP&gn&8Q$XQs5O8=IZo~xHf{9-wXTKLMR)Of2By@tdgL}k7$(|g}&Dvqp@k9V^gCn zSO*i}zXe!C&TO@*b~FL0%u4p0KW;SzBae>Y4h)erCI_l=mT7|UEiBY92~Jg%f#K&l zu8Dy*9Firde!K0I$^jRNVDM-MsoYCo&DUvhGr`t1KD4wfm^|928kDns<+v5ocJJC^=#@$w=?(!U$f8i`a3kZcDuQGspqMl5QOvKS`I zp+&2djGQe6TO|FV$d^E?PHG@t9`%roxr)U!ZLv{}7%$8vL9rt%%crSD_ESI7Ua-2A zIJlt?j8#$9z0H+$B>@O?uFt?3~jNkXn?^^%$+qmCeBAm>P;Fw&nvecFfZ zm>%u!eN6o55K#7zN9Y!$3=K-B-vp;`%B{cQ7W8|mYTIH&-0siVoE)0@vlSU+U7JLz zUs`Z-yc)BHyQ_-@zDa&FWx!=feY4o@ADS$yf5SWylcEN=rrb4a0x z?-^8Lmi;uG$+YlYhnrdPlWYhc8XXX%_Ak1#p7ebb1y*kmm#2<~OGeuuDzjz#m)z8GQ z=~^LbRV$+G?`-7q@GhtB8DuFgVula(M6CGv=iO7-;hT6hX^l99v?B1 z3Ej8(6T)${OswdTkz0CL(&Yggo`*O!rMKKi5JK;_BTA7GKJ27A25mg7@G|zKYJ~>9 zFZX|k*E-^t4Xn7kgP-+GF8FDyOwg$L#u@lD+o{PkUqvK${_Ei?m`wlZChat=N8jgM zuV*mf+sP$-PXD08f;>@toFysAmWG}Yv^X>|XCjTP?EFNpXSR3KiHBXkMyP1~=own= zsO-DE+3myq5bcV6lKTDINwjN-lFB*{~ zG`=j*w>iE@MqukzG2>81jvfCrS6Af>nngUT?o3^#p<^Q3RcjZkE}5VjoP2Y&1XbydjCVwKqztN&0{=-2j2XqJFc z?gfhu89vqCiz19wJ;3!>gD1@A@~vQ0wP2|;X&)b%ZgUwJ{^9K8<0{|a^3==Zs6Pkx z9LaNjTsh1HCt61e=XuX}ae7I?H2j^gXeNYqR`k`s>^!p()!d0GM~p!WK6iHt9O zlgRW+E7n}2GwG70@S!fzgu9wULSWbS`>stnWydTz*o`jTe%Up`YyjVS)Mzt=Mb%mXIhDu~*en?Iz6so2=RF1`6qXf4(V&JU2OL7Ru!9@dQEy zSZrOjr^EE5$f^5z)@;$o2dj#?qHDLNn4o60H&OD&dQyJzvdvay$v6WeP!P%up>tqY z1+lUVz1MZ;__-d9p*h}*!c{a&7Vd{5i9J!(#f*&Omb7m7xYO+}h2n1=w&H`?E;(Ll zDw252W6Qh@%-r?)Jc5+@`v7_(_Ca_(8Z_zoYKkByOR`qa*H*W0*VDAj7vyPkmyi|e zpwjCp@nx`{%Q2O5Gd>Ho3s7)GWBOvcG4Z*4(GtsOjH%@%5Ky7aA0Q4fbi?mqi z{cJ-of%~6K8$Ls%vj1Cq;=*b@19K*xZ}SBccGl| zC-EFN;PC!8buE&Qoq9NLVQeOhKCxfn+LYK9K2oV|>eeA01ZHiRtLqDQy_|@m= zJj*UjKNye-I(qLVtfE;r#u%+&AlTu?{Jq=b0M&_#LGOzIywNWmYnK`SjJ&b(;V)6} zuF@iv`90^Z^T2!t;-N}-VnfFJpf{P14?7mQqp>&4-N)aTcBNr#mg{1`y2%r{Vf$p$ z-4tiB>JYVgL;n(mQ8}-WGpY#I2yzt6Fal7bml(uaTXS8I9*bA%Ei~;INscaCUc1z! zw1=9elkd*~HJM{1s#Ed(jWEPq1P4AinGp>?)ZMp-Zx7@59kOy zrreL9ZE}O2KO~wVcphZFc4eU%~)H=1dzqiV$52*N{#9}~M8)CpSQAGG|C9s@HC z$`Okq-AWJBtQca+o|)s&i)nMs_suUKYqKrNdu^TcpqLiPDr|a}~>G4Iuuevg2n%NxiZXM?Z0Cz8{ULNMFE-^-GwNVdh5by~m+i zN71@AwEO8IgY)fXY{WEAb9}v0@=KwOOMR*Llz@9eWzso52+|E=tvvS|vpV5w&guYB zmzp~KY;3s-ESqY8k8$Y9K)40>llAfdCddM!pBiajcbwjMpWfoG9LcgSuv;4;r`CXr zn06_>r%C!WObLqFubjT=TtRiXRA$z~aO{uXgZgAsQuV@=4AgGdrn0yCPBg^Kd%D{S zK1KQ#eRTrdeB-TKfzC+AQGb*hXv?<#f4wU1kgBUM3fb*#;UOq#J*twb-0mG6E<;`& zV$RKtihut28y&r8K4j%x`)@#LW6{5fkEA$*_@V ztCp~dF#Sph4CExptfM{oIFwBeQ;6_n_y@F30kY>lqbMh8uuy2PDYQ-&-8`^O3-q_D zt7Vd0iZmd*r7B&*`R-MUQG&f;uu52uO`{dEIv|EwW@80sJuT3uTdJtEv=i|V-GgkC!|jfYZL{guc{0hb!$bbxD|69W}_l^-m~Y)zvI<9 zDbPdD{A{w_H1a!$N0PhGO>iJEJ|Q-V_QjN}kP)pF#qxZF zDK{G1{}d@D28tE-OG_?4g*L$*ZP~_=;ABYclkbtcqb?x55z{`){Uk5Rm0bVx921em zmwa^JkuI1GyC{sgb6hS0DxI8QOB>+!np|p7 zag$q>&hl~utXs`|(i}xu$A}Lo$Xe$f*$-Iyl#@k94m`l~&HSYr;Kvp{_HG72o)7|W zAPF|8Y)GYYp@~Gv9fZ;g`)981+{z6-{h(+4;8PO)P3x=(bmwj<(8>1`pk1TaEEIo% zRUTve_*(r3gLx`@#?ps{F0i#VdT>-gO0~4nlwSl16{?PgT@Fxm_uIi zx^8lpUUD9VEO|~=G8Qv#{^~=fULGMp;6N|@W&KpyS7#YD>>qpXTu;q7I$3xL?nL5= zzat>crRJgPp{eCfOpiEZJX|t(cX;`m>p6DfRalrVpf`_oJsUY{`=TQ*J0u?rd5Ju! zilRdn^1f(&C>0?MZ93{0(s*KjQ0mz#A-ZwboFESajxsHE+tq*ju+%uQ?xgVlh&O8Y;WkBC~}*9M$8p z0mqv7_%5h_)h^-J5t7R2IV~9lSuPW;QutS_g4Q zt%BktwG#J-9*Q|A6)rG}lc3qMl>FD>WDeq(p-aCkEp3{Jr~-vKWxRj#F2)PdnOuD6 zTw8TnsNC+pkM+%6_zMUUC0J&_|3-RcwYhvqt&74Zp)jeWbeTL!%eoh8E6MUsZBKHeh z{U_BTOO|uRq%?zFOojkoj=gphIs-~XzTD!HWWoSm6R zls(RW#T=GBP#^Kc$L(RE*WSlDF@m_|w_k<96{tbCgJp4kci80}%F4|;J@Wz!9H2jd zw5RJ(+fbML^KrP)VWg{@_NroXe@}ccDYq$`8b2Fv=<=G=BwR#qv9tGjHr~lw<*iR* z=k{+VldI4|&M|tTM)hD~7i$8syJo}JW0oe=jDSDD2nTRvaG^o6w(Oa{d)}Jtk zz%rVG+3`w8w@I$vt`(`Y zOO-<^GmA0>;ex=xw^c~!VNU({s^UEMKp9h_J6~AUbtdBiqqb;xixss%+JVp5+s`$9TlX&1uaeU<=@Z!lERTaH z6kLZDK#}p&v5)REA$Y1YWLk9q$bIe}*nmunl>_HcVo^1^hsH(G;pemxHQnG7Aue=@ z=7;IU*M^&c8?E48q|8TQ>YXAjyPWwYP{?Tm?MeerH8U#n^n>}MXp91aBuF%2$DA%H`^>>p*}{S{*RcsCyLyXRQ;wB zAE4zUB-Wd2m?v1#eWtbFt@z9*ZJ*EDA%~B9{^CXI11=F!G0iWv6zC7eqnsCK|8V{q z>0iYX=xQ+zElvB_C=*Kv^`9;!tAoDh7317d)H>Z4Ujjtr-NPg_^n7cbdHP+Fd)Z&^ z^FrJ_x6+^O#zF_DgA^gzgUj-z9sDpDu!?qW-ScY-!vUGFknL8Na@qlhI;cUO)IOAF zh?I&9M6Cy^XE{n*q#CqiHyw$B@xh;(PI>54=O=M~L_(JnVtoQpj$0I^rBwN4OAY!z z=QVomskXfBx{joYK5mnW#``#nY?bonEUccVIWRb5xmo6svMl=IPQU#^cFIEg{niER zd#y6EZU7q}1^IU)BP2RQI_fK6ChEWEh-Q0`?QQo(idXF==8^Mfyg@*At*D^^r(J%# zIeOPAH-m~^nnOM9jwx!qK!&hFf;p8ChQT~NXNhaziC9jJ(Z~3iff_YUIQHeyP}r69 zQt}bLAoGsqdFvLsbkgYYTw`q*$FkaK0X=khx>`g$rpe=N>owIn(pCGM~C0p_rC;O9i_M`XCLbd(vK=?ieY97~e#fi>W7;r{;#Wd&y9Kq$U%W zIoA|7D|btD2#^TJi_1LPZ9LxZvz=HA(C3L3{|($F@Nb9PHO9KA$*BXf(GE}=Fk~I{ z3$BHP%DDZyoT^-mzb!|SO$&;cGx?>m3na7$f*HDsaV(d))_j zcIl&&@)?P}e{$`|uXXxta7hx}-CUIbYB3J9a8 zT-nP7RJT^q3(Z#ji!m70DeRfW8gfYOJ+@p-HBgzOPU5?tAAm_Vt}Z8}U!8>e#^CuC z>o5K}3DIOWIonbUA-U=z)ou~Er{5=iwH|70l1Rxbe#Iu^aA$nH@xhovvNtl*@9IZR zt?6gaU%oDY&|vi3i3-Z|I*doshJeFape|X88H?X0&X+r=J5EnT2ZoQ5%IUY5tv!Id za#gSDySmKuY?0xTZ2T5)anreqAX5CuH?THfhv-(#t$AcOKKR}IF!25_-jMbG;tg3? z{v(;l&cXD*xBuh~IXD>q|H(wxe_E)m6}AOJS{-37XE!%Dc3>EWAs8577}{c%g#{u? z9i%{(KxZk5aEVeNpuoHQTd&>E?ayDU@867O(;1JP?$`CtE3;hIswmIUt%n!}uR180 zh`p23{X_r?OYCsqw>J=vf5%=!Bborh?M{z^t`ZXC1~x#D^as5b0z3%eH4O>E!L9^0 z2#Cdd3-Butz!wqHR}qqr&mRCk_pKMkz#h^cX$<`UV(tXcyf07RPFqzpt&|_<;3}|< z|5#5NU@ic+kDiWh;&~L8;1)1c7)LlY3r z;Ku=slcSG^M^M2JVhM8(!~q=GS*6JxK>`FF0L10X2Ey?*bo(>NTM)r5?z_7`cSsNb z)x!titf!~9^3l~_m&dG0lLP1H}0!<|MM#dnAac&p!5@|uOET@?i=1Vk9`asMxf89uRq{7^KBNFj-S5| z@xUKoEhw8%VardvH>_XI@A{S-K8ye`#rt*O5d7}@=c}=yXElWw=Hlkp?va1`xOq;2 zZE5cCOX-e3DG&$-657DQ;t}xe9YhqM;5BmZH>vcZ> zccB;Q<-7BbLD{cj=pZ;#YX@H#;^W zw(}Do?Je_%Up)?dX#3ahN4J(Q-0RwE@P-`VW4EMauXjWR`wHUz{>@Gm7qBB2(4(yJ zlRp*WUNwNAKgJUwIA~Ju&pR~x53l|W0);yK3GDlK9zfgs``b@sXD$_Z>!oF*B zmcISg?l%e=@Eup*)@^KW*sl->V3%B+7ve84#1=3E{u{r49Ebnw59MboAiqEQJ`ngX zeef;bebD#%uXqO>pZ(i+-B0|Y5AE;9uLowIKFJ!O+dc7=Ak#uKVZ&jAT+T?Wmy@<< zsLSFLD7V`l(O34Y{J*)&%f{9n>l^(06MVPGB=$s~Q#)y>Ucje~torOu$wjLk`1TqZ zwv0{7A)QP@Z!X17svS<=VE!>%!Y0(mF{&}rN$AQ;o^;T2acV3^zz+3-bg!?9@u9$Q z>3k_Z`*W+MD9gPqRY^N?)M53&gsBGf_2UUeIs@XC^BN8bxx~QwBR(?;D6$(2)_7K1 zKR9F{X#iR-C{pbSkZMH~NLOdMdKnGH`P_`8Sm_!Nsw)!<#R>4FbjmJ0!Df*Z2Gm_U zQ)>HPcUKTcOF}S*xs)Ey-T7g;pIZ7w!1!2;okU;RYQOD=F|?T?Y1K_zZ1IRPbZ6kj zYiBOXD(5eTa|g%iA|0e$+b-a#zf2`7ho_@&(bZ{^&ip7eG!!d$+<4S{GQRmWk~bZ` z*CHmK!uQhIAO54$Y7WLrORl1AeEC!FiRHr{CFk(lnQi5FF(pBH375yEwpSjsE>isPVEjBN%2_e8k*qWB;!=_2 zN9>L+4Ve?4UGzRwY{eB4DAVNA3VSzGtv)6^S9=B$PbvHdqv0jQi+3f+{}xb0l4xdi zANTaf=g->XM>Ex+dbe7aW*qfmD6qA}G|Ph7yIL0cAI(~|vJ2FEoLxbb%FE1B`l8!+ zt%A4ahX`l0;X`sPGjLT7$w6OeLRDFHi%d%o#cluIG;Fci_b#jmJ+(^DSTBR`pki#WR;I;9zkUT<)x zDEXW?+egC0P960)37CGg+s0qyI&wODq%(EgYuY1zCD7dL3m3Xoy#fDAQN*t1Ooc#Y z)drrX<}~T)CGh&{?J8L6n?E)LdyCl}$)cU5PrTdWqSY~z)CM%1g99=PYQ0{LjU|h# zk->w0{sYFx;Og0MB@@&It1@|H165{lL-q3!G!8CF-w( zJNg>3f@!RiIzl;nR$bWKAG^kl%6NVg~pB(=Bt}|QT>JV z$^#zz7~n+XVK9S#UJ^Ka0)16TH+*G^L3>Zzpmy@8;k65ljt9d>;$6ZIfV^Z=EVxEi z#h@TvCw_tQwcAUk)v5Byc%Dw`t9ImPt|FneEhuNIXo9}*1vzt<%%o49FmCh7P0X-q zt-D9N$~u4uTINE=laFcS2EJ4}pR<4Ty%SUqjGZdtrS8P%rOr*85i0fj5pvnudf?G1 zXOhoA3L&xf*6V|SvByc}F=c4DrF_QOb=}IU$_>-}!xKK?J1<$Y3}BFZ+_jmxHlaMi z?KX&ab!3Uj1N3A>PQdl&=R~zs(!JIx{xeg$Lf){&2BYG*rUqF;6t%G8he)Xe&R1`P zr)5eR8LC|$w4PSzgSW_+IIc-03xhy|`mFr@-MX7LUT^I)y@kY|J)O!g(o4;_Zk_}a?>D)ie zZ{fNh3f{8S94cddt^1w7h_Y5ytPZrqd0M@g0aRqSTwVmc$qRFa}*d5{x(A1IWlVXU)$cNn=fV0}vkx2^c7|oROku z*sMTj1cuh3^i)#X;$6F+71%YPp}XRZi=X62{Z$mc*8dbocRDKOQrkd1WiHICa9e%M z*wlki9ITmJm6CrxUYXChHLjKLetxT38c^lVJ0c7b_dW$BgcXWyEm7-G(dx{$SCpa% z@f94RuAI`=Prhv^Cl7uy#R4*=eIrMoj$s>-2T=5u$KrcihJ86F8B>LN$cvfUcr8efZq$hiP`DR?cX*4=O7i(%dr`M2%OnZ%w z&Ieyux_s8Zb0v^s?YEp0B>{i9aI4lH@C6h#_ zHfhEEO*XY$>@NN}JPteUly6JL2-z*>?~o^{Q}Y-oVJROYo#t9$ZZm+47vhlHnr!3@HkCOD-qXwN>!-x_JV zAqz#)ozlr*$~txwo(M7oQX?70sI^R5++Ll=Al{^5q~40ZlunRas*?7|Y6K(82es{M zwJ%|S&y*^O8gC6JmsOyZ>8}dy&a6_yfkG>>X$P_7F&igfpU&9&GkrgFWdtfzxb zt}^-hyq*krgxFKvK?(FGZwC(SzR*@>?NhT3iLSV7f@^z1+DGZ1pQu3AtKJrpM-E>$ ze$N^+_O%52WZWl2g%^|s`9A%UgBes%;XZsc2yIhv0gvS2_of^t8SpUakCWWen0nKt z(H&PivplLUj(>@`Ud}1Y7qXzy(Vgg?gQ8ZRE8ri& zO&4-|lqQC`i$<82M4}Iip~gMOy`znI)=;KBs>~Vg{{^bb$-7bSP--my)W-0AjfmRQ z6jY_e@o%#k#y8v{y{>Do${el7`9`&N+i}wcl6h9t7UqhM{7QJ{eoD`|S||TOA8g1F zI=`luraH~oOC4FxTB?Sr|)w6E`DKYgGCeR9nxE|+wk?AZfX-M~`0c3zX zOT8KKgEr?NO*Jr{71BIGtFD1)v~k{D&|sWI^q_fw;6aXEiTfIp<4L7(Dz9I|Mx}<^eY{x^wA63& z7F4yMvVNKBc)1XNA)7Hp_jt)3$g8072*OZ8Rx;-_)YN`oh)eJZH}(|Rr~U&3rnwvG zxY1t|tzwDWNuIFW!enh=cwe`5ZfcSox7!l{BuFUwakSv91hqcp}hCkAs5RA3wk2kwc zy9#<-fX5nGliDI8{}wfwqBthMG{W6SUUt$fO10pPhhXE1!~!6u?8S11c*N}^@Vz!M za6Fr*3kd9a>Arapo}D$JDzQR>HT6GAceE z1d_*J8uN^hbM9_Dyy14tc`~Zhir@DG(^Q4pWrv1clSqj}%InTM5&+}GI3Xi*$r+py z!N)2bc!B2ja1DmzrB)QeTmF3`AcGu^?PAnUWW!381apTa6R){yqT*S*%l9dpy!-B? zfyP(sT-4Nr=4%N%>UQEcHg>DTvMkbTI%J-my#VoCaGNm-`v+1BwMyc>ogcdc& zR&7=rQp;JF?d18jr*|+JCUv@Bo^;N;D*4Y33N@wy^_*Sm1f^)b6YgkU=uS2||rDQRm zL`dyCP6Guhk0Q!&wmw;Gfe&@Yi+2MSwFX||YbzjDawppN@;E(R#7%t4H#q)#4ij=H zfmvLAZ3osF>Vf7v_$hfUKaguN&!q>*TEl2-xj~j0p3mijUP`v+K5w9VxO0gJyXUu{ zasC4ViuI_wZBJdsoHh-AZn3cZIQ5=N@=`-Z0{B{mK+xAKwh<1YfLU4c*6}7_lM_yo z^`iaj9rgZnmkG!tO{wMza=89fo%0hxwcFFN-?(vB2s8;hfLWgiv^$agtnWrXq zIY%5VLcYdGf#ILb32htChBXZeP_Ct_J=qd29jJ~jv_7&Qp7cU?9&)6S#!Q3f#XIwF z@aGdE&xH1l*#Q3Hbhl<2O1y6hKRz9|)pO$nk$NhzXrt?v)u0DvTr}8IsHj{8+S}Ry zDBY96l^W%9yDZyj)Reu?zx849r@MsNNyMcCusNakY0111(XjO0B=&>zL&Nd<;4)T0 z>3smho=s+UCf_c*SiVQ=2Vd4h)^3IU^C&Zlx`ojAnW=q;r?zJbpoom+Y3pwKkX;ya zD*H)5)^q2i9(-6VhV0^ifdjHPEDq<2QWu-Fe@dXlk!y|%3e~t=NFT6z1}<%oT1lFu zhr6lqcEnI+JjO*GDT=>X{0yW~xQIgvZ0QT%V68op*2vg3OsBEr)VQ94Lp79GVhHVA zZ%=390<0WsGX1?{rpT~uf@KFM;F1OVlA4emrfk7JiyJGyq%Mq(n7u%G#mhIMkuuLk zYB0qHdW3e{Wn)2kU`LKT;mR{SbqB$g@^zIht`+a~nYkwA!2&P&k3l(Hh;Uxhd)^Al z!uKe0OV#ln5zu00)z8j?spscxo@|-h6cUEfK^fz+%xxzjpd{I=%cp}6m)$P~#Ew!VWUafBEirE$>z=Gxo2s7O7kU6`*l$-m((9KCpFPRx zh1!p7nif6IDNHyj`bNjLUg0;mrp9`VWaYilqFjGih=uu*4J~uWDbe_nA5{<4&@~;fm%7X2Y z!dj1Jg-SA1bK961I5qzig7LQnrFe{{4;fkvrLH!UFL_|7@aqLK&6RpvmSmX^UR#Fl zfvzJQ1d@FQ6%*k3I7%urV|wfO+OP=LSd*wH{GBSJBu}ELK4}7JeTY+yHC`ukl_ppw z`oM!XLRi`{V0eu=gopn6OK$TselgR9%ccI=+ZeVVLwu^P2aW)02AL6iV%p$uyiwHN zVYDDN7aCX{?u0eirQzf<=w30T?@A*!mI>#4zpJlbfO!mVNs^QgT)+%mB?cVIwbn!O z*6OkioRcw+mSQ69so`C!#rJmsb1b*qkgKGfSCDZFSKm9Ba6OL=*5m?NN_sHh{)8JdkX8 zsF$}Dq&&Qk(S1q9Bw*C7_&)usjqGPrE!6Oqn>?s|7Hb3wuMyMjIL!>_kyNAg^I}zG ztG^+Hv79*g{Lo9)tDmY``^#g$I3pB9TXRP_B4@ahZSuVOq0lk<;gZsYfZobxbuV7T z{M`}WtEo~Se5lw6C~)&=7^#Z$WtG43&4iA5IX7jFNc~F7Zu=ia4F_ao&f)==j!mu&t;vACW|Geb+j8GU+*1F_{yjVg6yC8@`_~( zqTlJud+nkJWJRes;*oWuMz=+w!mHc{2_NP&FRtV{aoZ%VKUDJ3;Zb`}U6gG%O{XWo z#-j>BVR?FahoHFnu8lBq))~qheI$%(wV6x|^T_Gz?E`S=&*6`pd>H@O0Ay0GMfT2X z<iq|v+N^PM~-n; z_Q69Z>{Ge=GMIwdA<2^wuc9z@7m{$nrK0axr4QwtwFA8>X38p|bKHzo(B#xO9a2_r zzJE$Cn|g*n25tM8P@&^KqaHP}Y>Nx{sqQ|1|9A%=ALgcx0u|vW07e>n z)UhWc3bPq!vL_MddQ1J$MoVU$iom!v@hExNdls=G(s<@)+K6SsLZ@&^z0mfuR$ZAz zqj-{ct3I|aWrOo*B9|r+c_AF?(SKl&`__=#ZO!^%&8;l+ndpdjW_|`Jb!huj-da~+ zHyu(o@}aGYHA@WH@(M9peeR&~g>VwUU31+Ugj*W$^UMb`yk13;iXUsD0!n-!H-O|` zCf+1+^q15;^W93SEIm6&mfLe|Y+*vRYN$o@z$Q7Z^)(lZ@Y&6&AdU>PBCso4l~nl4Urjh{~$6nMA=|*R*j5n{m^I$ySZZF4@OX@}SX_s<3<} zp{tMs+csN;>Ud$7aI1{&$2~}JWh>?=`{xhy1dH~=^$aoy=f#K_q!pL5`5jRvqn#~)bEUsvm=0&A<>oJOPYgfUHmfXwd zW3MJ>W!HMW=^-W98GCNl3$sWmcBy!=#FQfzsO3RSJzlLrT`lwF6*AyWEf?hno8G7&Yq_)cm<@oz!pLXEGI*((f zU174zy{A9E=i3Nj+JjwkpFUoL;$c`OsX=HN!AWyMP}W(ap;ZaXYE=XH!xgQC*GYDP zgyc8{S@Z>(+qvOGef(y9Yq484c5Q4QtbkvnQZU`n?R|1n9&FQ{&YJteDRI@T(uIbo zF!S1DRIJ=#ZjIH$LxzGjgL=Gq6AT@imv^0nhyNgg+#I9@gJgyG$`~BVOc1>Ly}-5S zhanw8)4`v~RYr3z@JLYEYE3fIi}}osXST~J5|A3Zx~+%eSq-W8hndhgJ!m79g4K6_G@6ifa>EVW#tAL(=#;?ydo;TNO}eO+;Yav>G7&H zR{mI6Q{OP%_T3OdhAG^bd$uOYR;$)Y8obH-yx~9RyS%^z2tSL z(5C!ZK|ByznVw?MA(&~v+Ny#wv6c`@*2rXV^+Jjg(H5CLzA}(KYM~t5-D2_fkgp{n z)fA!Izi407!7`M=qzQ}db$WyV;j0?`KzSS$q6y)3hk!4a2gvZ&uOCWvzvgX5krPFh z%HV+hy-6mmOj)m}H$j1zTl)D6?5%d4+`tV_e?HFzVboD-*_DlwtG%a5(7|!OUtQ@| zKdFS$2s5HxJhGX%wlC-23kZh$op%m~m)gQd$DFlNd2dC`u-X3H`fV2JKp$KPt{ zA%U+(^jRCIGO{&3JB)a^vm|^GR}oh+HVMfH1_K6m)ciK#HYvnHo_|tP zld}Y6AOyre=H*`2?)KF8=Ja#MW4F<%MW=VS_fWHr=^XQcYOUXA1SZM z#+-}-009Bv1Q`Kgz{rF(kRX4r*MVCVnPC7IC{*GnH5ds9M!0~%gaC=O3^o*yg*y*G zz`#GRtSB$7$RB`ToS*-|PJlxYDG%l;cnz@W9RSN7V+}V}1@h)1$e)9QNWu5V7kUrC z0SJVYWXRpO5*S6h58~ekYz`bBqmP~>hJXOY5FA9HUo_h*Z7&=hu z#>+7vkdg?#2P*If2&V5wKbU+C?vC2TA8roxi=360Th%|Fc<7sc0Kqo)35ci<00kh# zzmLH!DFS>7E(##83m9g(8K9#^e@$;d(+~0v;0FbqV2u0?-^s7Z4>PdOml{}rpe>Rb z;RHB<6X1$ao`GLYB@+HT`Unufz_k}7K;Df*68{V`m_ML}B49Tk7_b8B1Au^Pkng=c z2mwK@h%1*1KM4Zj=%K=>U1_}e%8{Vj4%9zh=*kRXtCKO6$a4&RCb z!`e?RbHy)27<-=}0IP2xK!9HCZ&#zROd2i@*z>#Cms{jJ>eMm}N>bZz(HFj=0^$wq z-63iMz@20m6aWY)s0g5;A(6ko-{w59;Lp&#UdIK47YF}At-XTF2bb|IA9LTmnE(gi zZ%Z+-m<%08-~DVJA0h%GKz%{MF(r?3qAMVp{wD>YG)c3U07wO&aegGXp z*(^Tf(vc^Df>s`^*fr3Vp9p@?ucnSo9q!QJv7d$u2|_b06a)B@@FNuO5wiOmI-G-A zh>9 zAHRL4-Xs|b5flIs0zW>ta;*Y6qJJ)dCG~aRPH!k?-z<0#u>uu9}53I1jyFp3>p;ZCh;#J$S>iK<^66{-5maj-owCv-<%&b zG*lSSn@vF2FOd923j_hg7rl!B;6C5o??oXHNC06O73WuM;GSQYUuB-;SS-`e<;|Oz zCQL}X2S0a!JOd1CyWb(w0f4U;1y0Ocstsf~-&rp#bUyc=ua2MoFh6t!h-1Wvi=AEt zlrx|JkG5apzd+o1;$hSkrN59bg#P$ou5aJ#hj5@BTtCQ6{=29uFm1RO7vIP8H|&qK z`2ZdS2ow*mF9l>Lw~x1%7%(qjL3e1Udj#e7rK|hb=*>_~x?R{tYt)t5j1s2b^F-n; z@29>onjD<5CEF-ASGqg+<4am)VObfErNf`KtcHO6Ph?+()!H9}ZjB z0H$?8iyYEnCL>kxI3$;g$m{C*nsueTIh_#*mxw#w&&_Wgi$06mhTwZZ6geSOM@aO#t&X8v1e7QPSL)1$XkAiNQYxend1dxnnt0nY*{Yy#4xmH z!$rmb`m1ifUCTKEsmZyS76#tt5rdF0$Sog#Jbnkrc*!;7$Cz}$sCeJrLki09lKNeS ze(po5&z%7yUx!MVLl=|2cnN}|f^606y7H$uG%;Pz=gpHLPFB}#BP zxqLRqr!R=iZY8AKl!fD6{{1+mvzi(D8cHV!3iOulZkZ8NJb6HZPMiuS8xRf=C3zIp z%rw{d<2Fq~j1p)T205PfN`0p1Q-+4?Lx=n!N~XiDPH=a4MA*^rV@u?)y}|RHgRibC z(Gn))OQ=mf9VqK0mdS+c3VSq2BEBfQu$)q`?mU*iw&fUb5bY4hs^PJh2=w`u3t5^; z9t{p!0`)w9GMCm=bDqa~iC*}GdjbsUtYJs)=Eb$P$lkq-ML){`KW-h0F9F9Cn#y09 zfh3}t%nK_&grNlk(7YkHvq$79dYvijy9ceACB>r+@6fzqxx{Jzt#Mvb217tyGSz!Bu|kVtDo3q4WhDfLbw9tkqor*MZFWZ855x{!(txTPQuR17V} zZ!tcK2e)PaNA6R@9i#Po=$rdGn`h+1->D1-H_VDN!{fJDB~IX3ZBjCI%;n%UuEBm< zay$PVgzVYNq1H_IcdN_KlHbuNI?ID5d7Jfv$7)U}=TLw&!Kx|B`XuN6k(=-L-@D`+ zAn)$4CFhf@=V^T#yD2NJ>^%#U$aTG-$Lu7%;hc)}x!! zk>|xCM)AVKg|TRgvBv=T%0$JVTn4pobIIBK45qcg2NrorJ&OLRMK#xGYtdf6*Di|lepxKa`^K1KTiHLA%k6hWQ;>_Ay-&%*q7z2 zo1YdjYEkWr!h5%|>B~*%H}|)muH>@nC@o*w`tF6p65^34Riin1_l8GC zab^!Rvj9@S|FHY?mMw|zm@Uf+>Q(KwH1d7!9vbh!H8~y`1|O3B^Yl#1YEo=zbELd79s^#ZO%m9 zx<{$m-y)1Y#$I%L57&K$J)LnpoeTA|52>1${c6m$N3;Sk2jwmdSd8p13>UR$8S`rJ z*)Aq!FSZp&r%`~E$5Qe+a-R0drIX5f*^E18PKXiv9ozM9eZk#czU$mQb*zsdJ7|`y zvkOybtq$JC5=3w^a@uzPx)#vzw5gdZ-T5F9s9*dJ{x438cwwF&&CL@3vN@yp+0$E}0j0Gg9u6|#&bXCI=? z|!N$ zpTBI~kgh$T1)sXQwJM5sxQ!~U^tYV?1O_m7LrDS}6ljM>RU$+^%za_w{w>szr?FFd zm?PL~d{eHjyv8TsFk6-Jy(xvGFRJQ{q?vz-hX?GSO|G7xjc>-hW(na!Qo*CONM5Z~ zda-wyduV0c?Ly|?FTMb)_mYDM)4I-&(9$UEcSZ>>rRmK-p;{nD$aV2(M1e=+u*>$1 zqcc_*IW;dy?zCFcW#h0PJDFx5v>iLm`hlds7rn+dC!-t{9L8%{#g6D~-c76?Ld0e0 z>n%3q9?2}pM>(dnN_DOrG!cKLO?lZ$xio8|l-WAYrsIT9YsBx7-qJ1WSP?`M|I{E$5o z&jWld=mh#?1$s}4_6vem6ty~7Z2e?5<6P2`HSVez;wP&K4GXefTi_>t(h);dy&C)S z8on6SdUGIIRKQXkpLOhJ>Y{t_Ur+Wb?>3!rRWDoN-RvS2M$ItX#igE&R`^fkSSis& zx9=Zk8in*PmsxI|eYjOFLEE9MENXUe#m&uhI5b}hLbDVi*u6Sj6MaB*W7PaT)wdTh zEcdY>&q#d?E&GH)w+zfOY&#A|IC&f236e(x{0Pa6`&*%l%qfmeX%TgMU-HJ^>!%i8 zwOySUt03zwZdVvSxwkr{V%gfD0A6fxaddbT6w+GFd4|-ZZi6j4FF7gjmgxmBXQWFs|%yDL9v@hFE zqf%(C2@*tQtnPd*Q^zn1 z`3(Ry-ld<>Gi+{q?R|$ye^XjXnHWa-4e{LSdmy~iiGXyk$VHIh2g5Nq)vb_{wvLr@ zd&Pv@WlAGAJVFPv>mdWN;eXv zbsq{jrL8Al1Y1B^XI3IUiXx7u6>EEokTk0o18)XP{U==pek|3T-(DB=CSPWo8lTlt zj_5*W_LG8@cZj^v=|6K~GE>plM!}Q(g3ibK0(L%L$?ehPh(hX5yE!I&onKg5@a>u$ z=BRDwc?d|Bp3LXu*2r;Q&+Jp!*~jIxp#guj)G2FrDNUf%<6xR|Hk$h4B%b1o;^zfch$s^Dq*Mhto z;sq!lcDx;2n7$*@m?K5L;*wC)IGiBUKS>WZBW0KH`Ex&b}S>ceGG1diz@zCksf0l4` zBZ8d?!rrzwmeEvzrxKwawNRODQs&=9Xbq(jH@fq^+rfuJdC7s%)~Q7@NlPvC*`Zx7 zrD-xFiBIjLb9V%QMf(=139gTKNpLuZxIeI@KJ)VVt3!5Ks7thk9OX^)VSyPikv%&Z zCNu+B7J`TM^^M48>l5u&NN3=Q>$Ut3=E8b6diAXE?^3lC`CZgBbBBUr27YNe7eQvsF&%h2L~cf0GVv>7E;p zs2#VjtXa~^$qW zaj*OA?8t|WX_hqzT-V^FlI& zq_hs0N}aqyc)b9bpAl}8;ol{OsBX_R2j>A369J%(7ePTaWIA0x&?!Hn_Y#(AWNne>^nm<-SfgF=&4udV{(qp2SaxEiWFE;KocO3Tv#B?iDu(p=K)Cil$^H zl{#9~Qb|pq)@P!M0lV9_axLBJb~3eY|DmE0F`Zy}IobIaj~U!t(-*E|Q(O@%Axp5L z9a24)HOoU40B^`u1yoRjFtO`6qnGLZBkJeq*dxy%T#6c4kE~jjIzjeV7|9^ZgZm+Q z!P)(7-<>K)pkh5J@m;HX={Ui_Q#96WbZmdQTv5MUJ5^L2+b@Euv5Zl#+W(4-Z3OZ) zq2x!p4S@CWPI@_MN_Ncc)o#+uV8vYOo$e%gaojd8EBopCEQ!blmRl*I8FV*hR!qcc|BIEj>ziaBPw zm#w~@8jYRdd$Dlh8T9^Z$|i6C%i3l(8WoP5%2;D<1ImBzQyB5;Q@7^0&7_xi*RXWu7kB+kqZQ7jK8P?yM+dD)3UAi{~xEYY?wveUbdP`iejd>Lp92S8ylA>ch#k+PfH5vB7*V{sSQCR`7(NNQ0o~vhGA4(HE zM3LAghxJR3?AQZMd#=*ho5$dRA%%vwb$D}&9y4jeb(zI$3X(RJp$j;dm3oK9>w}^1 z58BuRZOxo}F@;_1H`%ORwp@M%L$O1N?L(^|J>fpXkpo$g)K!)lbMS)QTZ~&JL72$Tjef{>|G47P<=f z1Y13{bt}VQyK7yeMpK3!orcI*ebfT^v%6{y`8x1$GpSlLUQ`WcPFlHKh$JhD5b=8JdN6C4y=_X)0VAJkIaffDKI! z{m5K2jxUfh(7o3i%D3??;Z(zQ{$tl1t&Jal=ZqjVKBN32OabnXMD!NJ8JH@{FIt-C z%9$FPR&(2{_AkeM7jSg@_u@c@qg1Pm07U~aDMffrfwYCE(hZNvo&l{8Vl*d^S#m6I z9e$BtvD|LEk(#|NRAdsGpUXh2>Ul;R{=H8N5?_huwB1umabP|0GZV>>b}(1lW_Pr` zcxjY+dX9=4@2l`2s*|D&+UHO;=C$BoFPd|r6cEEq7PQe~(s2x0Hqt)!_gsky<;`lD z`UsCFXq=d>;WJJrU3`yv*eh8YkQ>mv)Lutlaj_Q+wwP9vXnNVHk1q<8B{4HrCEeb- zEpyxB4wY$Pv3txsihmOgBqc73&N$v-i``OIw`a49pAakTQk?47Ab`>bS5*{EMv1;N zi>w*KKkj+_8gvb!O*BMJyd+LsNu2!O(wEb7y{Y=rH|7aq!`c(f*yj6|oMG9@>n&eLI6Wp3u=vgN4 zEEv_}qO>8Cmwg;!2cgCX)|owT_tST@=Pa^1%Ltz3yt((JVvE|P(2Ief@x^cQa!iV} zjy*r8i>I6PgFvhLIp?5`H!;hvHSeFr#=S}<^gnpeY`S1{(|M(9H=Yy!HvhH^yFVkn zzUo1BTPg+-^hOC;;EQP0Ls1}Sx*1*)rg)1ieFiye>vjrG#p2>!ZpzJhjxh8vnSo|E zdR@VPDlv@vqWnLn{tQ^YsBHMmtXu2$nr;uJXl}Pl5gGMa_SF zw~^~cz$K3BZPdcnZaz4rpHkJ@Dwa zw9bYsHs*B?GKvpA*7{UE5qf25ebs;kp-)EIQK#QRvwH5Cl=~|Q)3tq~S#3{F#jaV{ zk6&s|$TsrYZHQj>mT+=bu?8ogaXjY&CX`utJ8+lJhouJff;2qDTYT`&6VgY)?sjQ% zl`5}~>}vpLLdYbJnJe{=bBuckvG50x@!fM^`tv`ocdSY)h!U;S;2bPL_&h9asnct%}b zbN=COubf}IQUQ|65DnKZpq5hRIHq>o}^yYq&kNSyzQ=mSN~INnOfnxpxGW!H72@VWRbE>KW!! znk=a94zmgWMZr$@_7=KLotJwj+!L*y9L9l^`^;+UqGi)wZcot8%jH|!YBz_D*O_2m zrKK}+$HU9CT(vCyvk3~cU(cXsvi-8w?Q0wh**bOz*@bnynSVxUBvP(in=Sq3L+JP8|ruI;YN(! zV)ulERIuRzj&H{Hr!~3S@}`7p#!eK(z*u2YqSjfKASfz{E-(ZjH-Qzz2oJ)}cx6*n zp>qqC!MzvJjZy5`{WI4EDJ+uaVPp+Y%U_Lv^_vPyr=9i@$D3SU z{SNLHy#c_4m_I(w{!d7+0%Gj@eY#OQHyp_n@P4s!M)duDw&arxXi>=@ENhyxOnpv` zxZejfJu1*KTH8z$fy}#r_F7p?XNl zce>??!#so5mGn*r5hj4dfXXJB%4yI{CQA+ii!j27<7F=NJ+6zn) z_MPNUzIuZUa-^P(HSR(nYgIL4>(~8syC}7KgDnzOSD0fcp6Wt({SeOQsC;HVP~?H) z^@_K%9PDLBIX?LTj%2?$b;Ansc5ll2@<6#sh4NsZtveU)v^?h9(zfXj+vlI9K+q5@$fZJ3xJZlhP$lX07SK|Q}yVw>*vBK z1j9r6*}yX^*vyZo_Y6m#$T4b8d)|4v(xWIYSR9IX3CbZ|S)SQi?^1hn_`{GR2UL0b z51)T+u{h>tt#3tqGotwNfXHsEvnERt3-a@jlcqxY2)rgkVtO;1Kn0mo5}Zkg(C`C7 z(k3m@6!t3n3%nIzG$B098^)KW(WC%6NpLw&QkgTeFQizDtUpS@FKo=Aw;uq7epk|E z*;I|j0f{-yv9hOLv<}{l0}iFWq?5WOxh%HHZ6w40Jbr4tRs4=JA48^JB52jsuOK^e znUZ$o!%JhPZsbybyhVSwLhFTC0n<9v zF%{P(#5!S&u8{B{UQ~mW!uxkeKOabax+6u&iH>xeoTZQ;gqa_;%3OQlGjnB)d*tNT z1pkaXd@T55)sl#;Ch~MYAcp+XjL&6 zT@BVEC%j_3x;45lD~CYzxB~TdOOUVtl#)oMUUFU- z9CjDqU(BM6C_^jS-OP?N&V5pNTLn>Lmfkhv%3Wc=<$XCI{o37kybi}K)+seq}hNtnqPlMrM`D$#c1v9A{I3iz{mE(4<9iC8rS~{mD z&SzR}@>qNeO=xmt<^J(FA3%~LG4dp?Uc`-7hsAQNW0St)gVu9S{D7Ln^vx^dt_#$S zlQL{>Rg`=?WU2#^IM&O!`?oN0cOAj&RvhBLXyQi`(L*M_whGaFh}vhHcV<|!!*2uu z;Wyq`P1DdjZ?l&7Pql^CE&=F6V)wbkg8E(X>MKRk>oCf^Z!%@hS#re%6yc2HBVyF7 zqPk1&XbmDLs3I+qmVsryvw&45J^jYwVza)fCaV?*;}V+G1l0EIsi%v7+6;D1sA_&n zTJyS{ATs@y-Mb0y*yAOg3O1(&j>oYl$pjT2O^*p+ zrpz|I!V8=+mGkWPc!aHiLrBXMd~P>aWqGfMWME%TjKutuWoya|{aUPH)%aIpA<@U# z>V$Kxy|zNyxyGIRO|YiK9;LKKn^injZzA(Ag91*1LcC>))f5~pW=>4{F<39s79xG= zM_z{S*lV|gSs~sgUn+~LYHb+@$pD>=oIqJGDlQ&AXY}gkruLQIm4m?N{IxlXfEDiZ z9bHTengko-M(Vw+17NfGpxAf8zc%T{r*0PjlLNAK@vff$woT{r`VMsqJ&^^CYvIk5!#(@o(^SD|rgjXu z;YJ9aMVb6iN0YU49~EXjH{6~OJ@1GlEOnTD@phB+KW#c=;_a6fBv!SoHcEg^R>9wI zXYB2Cm9zePY`4qZ<|RdI=Dyd16v!b_`Ny{Kac2;6fo@8qrjWNE8sHTx-D`5QOv8rb zHbrWRmh@c)dPcaG^;Cw&8F`wrBA<|BzB80%eR3NHbg@=)$8hEC=b?uyP&tG1JK{Vh zF!6sDNIPM8fJ09uDtvd$IP^Ko3ka+^g6?^9{~1eH)*y+IJh#P|yNI&t!47KsYwd#D zhmOvuk_+!;7W)|)5i(JU*CCvwrePag@J;wpAr*)X7P<5jF#oU@XXIpPC z4$g}IzLQ#%gBsaCS$+!$jGJB9v{d+PT3oY1XiE8z5HB7m*sW9$PgL+vFs`X8L zkhfchxcXsi(S#Aih?AW91kr~o7W8YFo!X&8Jo9jA_IhKdlHqZ4YX%JBcD%~Zja6SY!B_&t-! zfRHMd;^rzNo_4q(0ze>&_>ulVNY*Y0SO5`GseqiToQuT8EGYk>5Q$g{|M>Zx{xn<3 z(9ocMzv2DN@|x-P@}u_F{!3OcA>TwSjT=1>9vDF2;UAF`p3DLOk^m6Me}LlcU1E;| z^nxzkZw5E0zi*!Ogmo{GARX-Ve^;5@PhbM`mu81rGuYyax!f1^IX2fVoRv9s|sO7e~LK7@FbE zKmRArNM4N%i2n}whZS!H68N>xAV8htU^UFJcVbUY0~S<8 zfH?D}am9L(U{W3=IGY{xTlVeap{!~whzngn#O5R?MJ}u=!4~1L! zp8W)95U_~fabY2W2_TIe;NZP))JQw`R4dDxVL=FLEFW?1$<1o}8v_IS64L<^a zW(XUs&!9_R0PvURZWa|31IB+K+a5qH4H`$}-pz#@#_6YVM2{Ej2D%P#zZo3N-`D5o z+c-289VJ@u?OW#8r`Pa<>H@69bHI=6$L(qcw~3yBUm1yjikvbswXzL|UsM$f;c1rY zFT$Iij{lGBvLI(6prc>LaPC4c*2~Z359rUsUxK~d=BIi0`2heRKdUV?5>UqhzkuIe z$=~dUUdS)C^jE!r7XE4A z1JIxBZ?SY)T?`mqn0}Fs7V8BHMVWwK{^SF*2p;m1rAZ&4TOif(N-|9IE)fd)7#}FEX>Q z$8RpC;?`*AJhTXP(E9r(&T6NVH*>e9Cz6t?bs|akdWl`~9*Ah;Gn*kW`}xFztFV9@ z8z0HKj6ewihp%kEC+^Cm#xbVJC0E(ECz3Nz62an-XZ_wvtE*v82~IEzcW1bvT3!E8 zKS0(QG1R>aw1McWT6CHSrEm@yf|{w;?yYk^&_lnh$&rs?ofmbk0r$Yd#TIZb*!|G^lA`ql>{!(fe+hr`?k{=pM{Ic+ee1dUnS&`l|6d zkXG7$PAdso(Po0%&W!iTw}soeEgGS7Gj z){Ny;Bw!_EDwT*}me@8?06|^V0QIe$# z9|^&R^l@lu1vwOz?IxS3=jJruVI`@5cAx>y?sp9o+#bZ&`5Gf?(w}M z3>pC)1NPIOaGZQ1IIlx1v?|5Q@ukJuhTDKH@TnoQRj8X;j`w;7a=Y6mD3H$$Z?t>9 zv!c}bM4=cM5I08Y@NWy)MmHUL>HLrS)a}edX&iu;n)zG#b|sTitQ4bfI?s5FMd?VSAUA(BicClClLEo< zC^ks&5e(Z)4Gd7K`o|7duBaCXgT0MXx&?D(jb=Qp4h*!pVaNJfhNw$S5Dvyaa^MKx z1+r6w)k#u3wYzOfzPE7cnipxsw*TtcQ)(e$?)fv~6auI;oKUOEuX`f@@VrC<*Zm;O z`-PeQ042N&GpTnwTc|uP0drn~y)caRW9zL1sv;v1eMH5NcR)x)HyyQbOM4=h9^Erf zkFy)EpENl;-r7q{Nu1dbl!Mwq8h^20OvL`4Y2|pDIcR$B9!CUMtnfVaL?fCj>r(Wy z$1@K+ws*zbPmn#kQc5e}EdR59x04fvX;NgJz;wAmvApdsqV(KUC>392iE>;T#TG?4 zV=1p+X3cOwlzWDKDD~MVp+cJC!@Z+dRcrUrAr*wgI9t;K4F|x@g2t>$DZw|zP2ivl1B~~fpp5Uka zYwTgKM?eR&ZWJQLWJQwA5cVM8PoZ@#FC|tCzH?m?`V^_kn$Mh$U1-?~jM&m|EW)%Y zX38at1W5?h@0*vG9f`xWe}mJMTN}-m30J85fu_mjxTW!AKO<& zb6l^N1mk!F>1`&G=aXP3!LXvdP8ySqGm8z>ZxCJZ^h9>dbTA(woLDh6k6Bhk_?>~-aXFNe(-XD_8X7& z1!Ayxpj-h~U)4pa*}2JVO-(l?aWv4hb-2~0w6Y#+l7!of&OZ>cv|GGxFfb)>?M3m{ zw<0Tbo%m^`);tXi3TKTg!Qb8fC2h4;m+{qNM&868GDMlRs- z;M>_J?CaKAFRMiTLoEacOqPtp@V*(D0Sk}At-yH4S>2IJWoGLgPn`VO8G3O!kRTVx zD#-`kn;Oe6=Gx}U;$Eq(GrDYMtzoBk9U$NyJY5`FHH|sxMvUt$GSe1W4bnwy1NVw1 zjqQ4#0imCD@+l0$B};YfmX8UFz_ITP{VEOL;wEIgCH#m~KgmM*HgUP+Wlx6sVbYar9j}y!bUI$# zQg|+Ym&;*CaOD3KZp|kN-LgzC4I>DK?e7CUV;de|ns`5NLikjh-M+sBOy30oZalN`-wCcT*MOMJ(yS?|N%ZU))PD?mC+OmtT9 zH$NSGa2qJ41jBk)dtB*Xz|&CUsr8}@%15TZ2y9aY;yO}oX^2$uuJ8N9rrzBp1Z6CHxqZUH2aL3J)urI&6gqfCAQpQf#ieB zC2;Y>_Y!iPR<2SY7~r&5uJv>HQAsa>2&g0tFV{_3KtJrJ)Hcupu7k!yIMMv zoB2oHJmHZK7REU6_;%y*uxwPOQ4jB!-r|H2(^vLH_z}jlejCqjj11e`sSFY1tn#ss zJ28QGT6~pj#Ck-lw{9k}sBZR7iv!A$$VmlAfJ8Ec**Fnxg&U7!K>4ShW{)$hK(d(8 zbc9znuoQ7*EjDL#p_=iy4LzQ5qmZR$bx_P}IYourplrE;IP4Ubxfn_?c^>E~Vz@B* zEeduid(=rq{b+NWX&NB-vdA{t87#f3IW7mrjk_7jcN@^l)ugmXhdF18slM}!lW(gg zZ#Sy6`ZG#(%y4Q1$zuT#8au zoR%RA)y&IL>_*t5u8(rbY@alC%jCUd0*Qn1K}p zfy&{~J)liJAcWDV2!`c4x|YtL<=7{~R*Js3ps~*Qu+T%wPQ#tL7ayF1I+XO2_pkyRnY zBW>D1XJ>SdnPFw5X?zhO{_Lh9CWCL{bA{%zaQAZ0cDwbyO0v@lO>5x?5u^${0C!pO zt)yKaZF5D9>;$bAf|tT09B~91o<-|8a1sn3Ls1NN=|jw_Czd+o4z|kv!yI)eZY!6% zW*;6T!~|CUy>4E;T^(lAV-HUZkcTaR^-mqI=c;=Ik1#JU10>pyZZdCkTY^>$ATZE{Sd%&2e@h5WOl3-DSvl#2 z%H-U^5AnO^k*ONS2IyK(Q+mjKE4;v?3B@_&iAc@ufATXw+zCfkbepEDtu6AKy~Ovz zWlFOLqGRMIsL%VFPkH!WE7W%BhV;(Dpg4F0{vJl;SV%Wh2+hp&K#o{eu7WaRn3c50nuxIj z>zE;AguG&tg1A6r@?yZQ0C9JFC*RZQHhO+qP}nwq0r4wrzdc)zR^HbjQ69_dMf_Iyp9*Y^s0oU z!5251PXE0^^xZ>Lb9Ah+682aJ=(12aS_nJAt>a#?vYi^ey6@J)OvTKIa<}mkGIxDY z7wtZ;WvwvAy}dEXKi2-b(i&oZuU{$o^2%;T8-sd15R)u+V(-;bgDT0Do7>JQP_4)j z4mYp~@gS2)_i-}YBoz-yS32{bjLOSKT3DoTC& zlA)+72>$j; zd-t8Wl19GJOK=q@@fk|{N-C8=IO7eCKUQtD#Iu>_CXYGqRuP&O!<5B6^vl`;^cR0t zHSwCC_7~hCWo%i$52>AdqIKXSwODslJ+BOm{kpC5C20-|`sCtRNm4|K|CD|oAa7dF z8(A%qib4jBPR+fsG$bmXI><2T`m6|9*~ED`9(;L&DN)+ysu8N5-Ff-h46PQ$6*n zIfW#TYMsWnB%+tv?iyKnnz~QruS3#qOTkp^B5mgg->w#2pbo2=hh~84oBpPZ4{q;?6~})y2=Cfe%mYdI;HkMvk6Cz)YM{ z61-mNHhrhjL@7hviO|d=+l&i~gRAcUwKtduvr+UYxGJ`5BIRfErv=Oj*Bh$qw((;r zIYHjHQ6Pm{s33ndmG-thW*>*CX7bbAS;u#OX^MP^^8k4Mq#l#?sg-%gBaM`-UjV=a zd?S?PF2NOdw!=hDq9y-#v3#tx-PULNPbmR^&gMYZU2IF|gsGySMw-}8#@Qo{fNW(a zGK*Zn%V%AuGGFu`iTD|YyW^!td7Ev}&W~5Rz8+rtB=m$7nIIcE2rWJP+kiJd%u6t( zoLD&!7j(s!#*@|}V_S8ZbF&k&d05a-27h(ll9NBs^JyT8g2Ai9iDra(^XfBych9Y4 zx$A}WUMfpc6f?E4y2K!=oHoJp0`#!<(FmBqD66e6VTn6#{I}1 z^ivEyl8A(RpwrSj6=%*Jv!|L(wl3R`zo>NLHAVNI$a(4dl$1h-C`LCCz<})5GAao-k1p-0J?cnsBFL%;C zpHSGb(K?M9t=8d2H+)Un`uGH18iDao=!|Zng^g#<$di;3h0^qxGa85fQ{4JB4`aJLtZ%B}S&bMB$X8|Ow`V-us&{Sq zehNLq&dNUaSekm)7k*||c15emOl3VL*0HV%`E*s@9Hi~udqJJ{d~&){^T$ewQv$9{ zsBv+Bgn3FEe&dxNZlJfp8a&TZNPaOcgsszS%=r)oMj@C2-b_}jl0U4YkTE=b_oO5u z+OuznU1RbeKyt1*olEYFvIy%M)IUoxJf`g*PgAN@Bq4sL>Dst^Hgfy?L~)-oTl`*H z#3;O~JoWUJjb^mUT$H17t2F{88K#;Z@~+Tiy!pX@)eZmE;)dgDj2WHnnrYO6KXkMt z<{H#Jggy*{HhP?*L#^cSGmCVjM(I~nSBO~!4kwW@M40S7BrVGrsdxCJG zl?4-@xRBaY@{F2IxITrgRPXrIH_d&aklF7>*FYvRaFRy|q&k4g@>TSU(J8iZ2$7xL zyIU&oY~y%tjucQFF)4qbBM?-d^csP{ZPSbK+tisMLPrm3AbpGQ^x~ioH)!QXr|qz5 zMhAA?#&&n$`nHUQ$(l!1J4rmwj zfq?!Ol?)Saa(hW?B@D!ltZ9-Brw!LQ_52v)^|zeQwDTjYo%FbFujqGGgkEB)fg;)7 zc~m{Eo_fP->$42QEloI@2wew`S-8@+gY$mg&Yuab6p~+L+na7+*w-INlO305N^MHg zmgbU}aHl<=_bQ^UPrqsX>wE~1bM;y?1M{H`ZYmE)avf4>E6qlsFch2@#znpe+QPxQ zur#A#?PR+rzcj^+)p+kIL{T$txHQKA&$7!|S@|iaQ7KqC9Ns#&vD7H_*tj~OVJL99 zWZgqkftDq?jlj*WdCqCTdufmRW-kAfYFeB;Q2hUXZl4YSd3iG38k0Ojb819DtK5tl z-*{eqXWuWTR3z43XYPtgM$ya4^XfZGI{|m78`L+J6KiWpRt`<8<-(CSURR1+ybHLt zmRMuEoE;0zin+#EFM2K_n-~9;GBVRM{I`^mo%KIlkrAJjiHYq$)Bi^qnVA3Ql+ooM zW!zk$(TOJ1DTXW%CkxgUsdPSP@ed{DCx;>~c-@H-hfs+07e_(lU_M`n68|lLTuk2M z_M<+-^V4w~bH6i&KK@$6vAW@P!?HR<VOvW7b?QPzmXqBhX}?3ADtTf zSC9yBn=J;B!%R4zK|hTWD0q}`k?{|j09cU!!5xDNIsELRNRhwh%?$rhNT0 zbXa7tAQJ#-Awwg-N;$+I_$4slmN{}zRC_6~>x&qH4X(Yr$**t7qmX-G5o6r_{Gh>if;#d4wNe1v0>|LQukAVzHRH@6MG64j1Dg@U2K?iUTMG7| z;Ng1M=EW5tOHLyBzDX{=NT30JGvMUE{=Ca|@U8Q~5GeE|7SN+_45LIoh!$Q2xQd&B z%HP()L!O2pfeI?zbqhY^Y`*!cANAY|7 z5$Sil2>I`3XZ>=k?_UCo6lQjQ=KP-3)`o<)x0Lnv+75p7Cnn74^6TQ!(aDL42!N4) zC!_*NN{j=2|LBO~MSeBG-SKr~l5;W3pS;@Mk3PM|@&M5NUuW&_fPZu@aWQW-LE~TX zlC%Oy`su&Y#(vtC{Yt)eu>nmJKa)p4Jq2AiGc$eqJ9=+Fz(P9lGdq5e?u(s=cOdyu zBXPhNeHEtRyFyh_{zTh40IcO9f%~BR;KtD`4RK*?P}CnBF~eKJ9z=T|V)&E0O~$@M zQa-V1j0nNAqK2_NHyB6FNn`(C} z+D^I^s>8U}&bITyP*s9r!V(W|t1lYAWs{?3*q3i1kGfy=07;BpW##x}EpDgKwkFkW zD^O_Q3QUTh77geA1CfK`KlEZ%xKjN!)DHO%+$<46_Zd>4uhe_7$1Q&0*+jA%;g+g#qBpoBUNjnfg;B;ebVne4TU+&072xj^f*U@^8@sJveG`y2J z;d#0%U&qO-%!v$d(KCsni6|c{Ix?_!g~%2sOSN#SAkfEaJtnWU0&lK8mV5GLnPQd_ z++3Ut*26qTYMk+5#k)Crh265BB7O1jFV<#>|9Hx4 zucU7EEKGerUFy3vEMK>S$7zgSnL#~o+Lw(3VgOVYZCxRJeTVhc$CGj??c#ki9|aL> zeL(}J_Pi?OcQb5x39%Ja263+RyeYeE+mN>~FoUK?6quxOpeMP*3h+Cx{<`FvLos8p4DJOC*xZrN9!aS6ina~zQbDm^M_k?P zHS}RE!i5se(*nDn{w=h1oB`B#^)Th!R6eTso_EZuIJ8Y_Bi=N-fiIZOQSdPYQTkv` zr$!XWr19wH$o^FLlzG5A>mz8>!kgDx6{H^ZfL0y^nCRNe*!;8ici7%%v+q;(2>H)q`XYl zH4PHKZQX49*Hi~9u#gqysDLTt5zlQJSFsUgyK*l;#Ywqf~<+e=_l|*g=itOMdE>fQPDh&jdDZxKkycOU7)?N zj;Rmen@-E#FsY059x$A)Hzg;1Dd4DhNMoo0cjR80h!UGoIxVdp^u8|SIh^Hj5nC#U z@M&)5)4c({@@42*-x%0QSgonWvy@aBC7(o9&xz7+UMaFlt^6r+sR2;>@gOImMWvuL z8yXyE5*u2cihB6R0%Jw8Y4_D4ecqvs<8Q7F@puQLj;mIFjdFQw7y`T zL+VFuFb2|#dE0P0w#+JeXQahYJ z&|1ZKm9!PL(%;@YMonV!sec263tNe&Rv*VY=yT&|hghc*kp@k_g=#98FOgMIX*W?r z-EuwHOdF~|NcP$u5-V1l&0cKCe35Tgdx8)BLvAU9K3R#$C2d5?}9LpwIlx<@Xu3Tca`Q=8a&8tdBDv z;)|h4HSPVH!$Z`8Z>`7nD2<1yq=qZ86Wv$@)_v3YeLrrL$aD|_1{k8#t0UBzbXlVJ zmmTCHh_a=?Z9hqEB&%rjv^T~ zHvwEc<0UT6t%Rb?6DKh&`Z@8eGEy?OF`E{Z(L=3(NpJEb6rn+EM8T9c((+FvTis@Jcp<4eY9oTiANj&-sy{**4gwnxP zxr)MF1~(h%6-Z4~;CH;>lX9bNzBrmXHTHlr?7*#(gq?ikeZ8)0xQlF`JbBDV)tfg+s z<6jqo!|d0TU~&9iuHpV2G|P}&PtdsIT+;D^NNYHIz{SQ|Sy)Ha00iAGo0~==pLW@j zv`j%eh&+Xo5UC-Tbzd@19agtx3IsjXO= zW4tpT>prJKEHFH+-Ujcob~-^occK_A!rzcE!fPFeew^p6O$|kv&>*;zeCDw zeUQ|V%uV3i=@}Wy{w(E!$>#L->?o?9GEI-iwUS#}kV$F6;RjQ$f)Yc4U9EW0pen(@ zR07PvHRfeK;z@J4zz*0Su-^zis zwAb?_vHY@Zl5Q^8yN|Wj?nnv$fH394)25hCrw5xJYw09GCa%_Du~X`rOgo`k(MG;` z%B62v0s2BXSL~l@c-q3j1_loiV^5u?qG=$ zVRyN6rg>Q$QWL@HQ!Utqr`)^7krzGr6Azpr&X$gW47lQ01Kdsj#4uQ|qZOInx}?eD zv`~sK+l@MU-&IyT1Cg}$&^oyhWM#0}LGQ*g9}CW@v06dnybyHMrZUUp+kmbJZ3Dvh z`q7D;(v6|gtM#Li<7=szf}DNSy2x_oh;lijqHH~%$CEhJp0Atba@9LAVbJdLuHuO? zY&*x0DlnM-*E#zEqMo*W-E#w&)opHI{&a8Nh?4Ht8EHY|UaX zH>=w!OM5tjC|D!iM9`KPWccI5xA19yYG)&+Q_u4`2)N;#VQgCOBihs;V~{0v$^@5C zp^ellhLiZB*|txQ!p3+2jol>-$vC80D-=~10^4N3q$z|hqIEZier+67l~8h z#{Tc%gyGJJG{MRy#rIL8AmQc34er&oJ{j&cC`+CdnYd=nTDo}Ay3k=Js5Twu^@>|A zY1(FC5|vX-&|?z$IpV}QJ?|$9W%f%y7Ua_T%xo2RAc2s09!p}@s&j%23OdOCO8*f? zlqzZ2%u1IWbBG-n?v{W4LytZ6CSyDPd_nos$j0o5<`3lqC6gdh%zq;D6gG?Zzx0~C zl(Uis=1F#eKZ9JiVmGNu=2dvBB~S0AVh+`UqDwDLO4iunpsTaYzrh@~n6JpeYxf>? zl)$WJYf`0Hv5#T4aNa9<-x-u!Ul8<@i8P&*O8E|-V#Vz;~%B~hCOOT$oruDXo zNw0_IsnclKS`PQonNMXqvtlqWaSk+(hYnN{^W)ddbwY9|9miE95-%%O}*US zpUx4gKh+|woAlI}i+II+OxoY64XpFx-xrP5)XsNYj7(PDtbpeAnO8RDB?A>wJe~El zt%sXKJlr;&fS*h71Alp0 zLM%TOXt}URxh4tTUx%;5o z-xKAm92egI8QhjSm%{|dqGU;*C53OYI>@^-Uw7}L_wNkl6ZDv-g-oErbNNTr7@k}0r* zS6K2I6AAVZd};V_FtMsbEW0#)?bj6PRHeX)H`R#A={`}`zX)p=83{AMC2*k1;tFnZ zwQ#6H4vRg?Mo_}c;qg(*yF^&bEV%S`d=QMlBWiy|=>mfxXWu}WDXLSPhc#LOmcHww z&qTi-sf(uA-ZcDMCWIh`zXdaGxR4KPXxnnrTv-Y<8HHbjFJEtSrz!N@Nyx9^xFyB; z=87|_q3igdJm;Sm-Q0ezhr`85cTfbAv_-!DcRNn*^7S?fQ#bpWkDqmB4ER)TAoBV} ztXm&2lR#ctxV-XZM#f-p3Zbgbg!6ps_rgL4>5qF8lFV>Svfr1Dbb$8408@bn} z?MZqW9*rHJ^5kGcVReSf;mix3^ca~PoR*}`%528qaOg}h;TCS?=`Jb@{Ihawq z5f`ES+`D*y4T$Wf{juk4RI8`74brV#4=9#Q>*g{df#yaokmXGUFVT-;=MqFh@xwmR0OwuIbj@Qo z_C0MBjK#t7-v=TNzWR70Q%+pyrYc`>&$i@jcl+HeZ7&^p*}2X}32BICpF6>T?eqB? zQV<493ZkS=6!VK+g#3+vtp=B8Og-L}QI$dxUb6|x9sI(&a-2(@i+aSrQa?ePs$w1{ z)1z%CmnWCpfm`h&e3Efp(&mU#Uk&+*?Fh28`pzb&>c(VSs%iJLz}mf1bgYbEWMp{%c&=Y&y1#$a{3oGzB6N2Z4R>=5QnL5 zGFv0E#yYLF5BKgZn}xql-6@Q4*_#>d$vKqwQ*&vhS$|a^73~Cai9$@vGM(M4iIU`hmloi@2?+qCH} zCcvAg;7BH)gb#PWMPD}4VE^_70A0(lARQ|(IZrH}zl*Y;K=3;TB5_#)6 zEsW+gVt8REeq4EPC!P3(+M8fNoOgxI*h=$v-G*HzXU@%qRpa&ePQJGT7;yg(n9Zu! z&lU2oyv`WXoSIFvBL=Ko3bmjoGd4B4bxM}&6_ljk#<~iyEOsaSpQ@|9-cB1drp0!w zd@XcF7i+vyU>RzgM&soL)sVrGeGTmA?#O(eC1;_`I1)bjsb8&jpW`vM4csdphfeSj zE%fNiOQ{QNnq5|=E;(uSA3N{k!#1r=OGIF|$=C1X8i_4o`~;1elSM1w4k(V?1$qre z*kIWzD6(3*bVqtTHCY);T|fIgKh>jD?$;lRyCeE?`<8cUxiRLVzO=vVk^j|av_Onb zfJSO3BAG(m>W1}vG&aX{P?^1}tjNc7W-o)#J`nEeJ+}CQcBJiYdVd;aPforpht}c> zCB>22UF^8~JC8+CBAkyt5>uz(ZPycR>=u~c#AFNlRTb?WEaisisggRzNRd}oc%erZ z*<|#fhW50lUb-?v74a)-8)i?AsktU}(K19NR+cgHS>72%$_ly7&>C~*Tn$8SsZ^Z7 zWkcEhtLM!Oy#ZZ@gLv>>@^fZ+W52p751n!OSp=pcA(ebZ(~>xPa8%vb5?nXq^}c%` z&ugH3aCE`srK>~eKsc1f#|eDeX&4|fK$+r>KUow>s|AE+P##$J$(?*yCiJ!rn}g6b z%(0F0G@(LJvc)~5xz*lmr82v|bM9Gw((0%Y5zkU}PuPi7Z8Z=8wkO~XtZauFDTbko zAKI@fKW|`CfwCF|UrZ*3))^(F5VT%>n5Pogcxqn>hTSI&x#&MGa5^THol z&ovO#Q4pMEa1{F75S~zIvC8%@b{gd`;n>-2H9l7;7#1gn^!^pn0aA7^bhjAP@Z>5y z5lJwW`+j#~8E3OBtqItrIZ^3dzG33UcT(>z+&V$!dr99?(B2b^pkyd7LaEeRU?H<$ zt$h2Aknk{BC81P|G!ojBWD!s9QP#3ej8cAqd8=o_{6b^lo3?}!S;Y_!K-t}}J2wZTkU z&YaCm;bE7zuLSgn=h1!j9PFkCU2xo0SgSsb4!i_3pR9YmdZ`BkRWh-Y_r`=9ttO6Y zAML+|K>Et~ePXCkAQJ2I_a6*ue5ccrv7dNom?lz`hOn>erjo&S)DlK2w)Nj&({g~P zg4D*n-aJpdOQnNeM%sA@ZA|ZYxM{9Na&1;k~GS$J7(kB^6wxHt!B-*51#gi_Pc0N=C!0-2Dl3npG$#ch)Ml z50zI6t=u&q7iPdAD?0nED}`S`2Go;gdg}pm}+rotzy_3~Zp?H=>`xY;#$Q(BJJ*MY39v#G7EvBj5`G+S-q`+vp~%3b_x^|i?2`}wGebplLn z?HDPT+Sr6l$PoDlwt@R+p!83F>z|_N8-du@H{Ab>&W)=8;hUTo{IeaI0+X```0Eo} zN|2e^scBhZwY72oc!14m%z>=Ezk6f=j^PpAKsz@y(*uAeOl?{DN86%NP2quL$Y8Yc zvtECK^N|`IoSabgO`e~gj2WCjo7g)vqvn`^xox(sfiU^$=axatq28hx`G==|zu8$* zi!TAuU}@d$Ld%d*vB@#1;qS@p>01GV2JC8Y38eC?^=rBMmv;Z*U&es^*i=8a10n72 z%L36iGx)J<_w)Ke8AE-dGh>2*ArmuWif^MC!_+sq1OhFeAa7{*=wJYz;!pL%$mH

S1gAKtHaSTEv$WClwJP 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 b)63k$%MUu&Km&sKc?9{;7#U^MWYPWyKdWyH literal 0 HcmV?d00001 diff --git a/libcrux-ml-kem/src/kem/kyber/ind_cpa.rs b/libcrux-ml-kem/src/kem/kyber/ind_cpa.rs new file mode 100644 index 00000000..6552e2c0 --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/ind_cpa.rs @@ -0,0 +1,510 @@ +use std::usize; + +use super::{ + arithmetic::{to_unsigned_representative, PolynomialRingElement}, + constants::{BYTES_PER_RING_ELEMENT, COEFFICIENTS_IN_RING_ELEMENT, SHARED_SECRET_SIZE}, + hash_functions::{G, PRF}, + matrix::*, + ntt::*, + sampling::sample_from_binomial_distribution, + serialize::{ + compress_then_serialize_message, compress_then_serialize_ring_element_u, + compress_then_serialize_ring_element_v, deserialize_ring_elements_reduced, + deserialize_then_decompress_message, deserialize_then_decompress_ring_element_u, + deserialize_then_decompress_ring_element_v, deserialize_to_uncompressed_ring_element, + serialize_uncompressed_ring_element, + }, +}; +use crate::cloop; + +/// Pad the `slice` with `0`s at the end. +#[inline(always)] +pub(super) fn into_padded_array(slice: &[u8]) -> [u8; LEN] { + debug_assert!(slice.len() <= LEN); + let mut out = [0u8; LEN]; + out[0..slice.len()].copy_from_slice(slice); + out +} + +/// Concatenate `t` and `ρ` into the public key. +#[inline(always)] +pub(super) fn serialize_public_key< + const K: usize, + const RANKED_BYTES_PER_RING_ELEMENT: usize, + const PUBLIC_KEY_SIZE: usize, +>( + t_as_ntt: [PolynomialRingElement; K], + seed_for_a: &[u8], +) -> [u8; PUBLIC_KEY_SIZE] { + let mut public_key_serialized = [0u8; PUBLIC_KEY_SIZE]; + public_key_serialized[0..RANKED_BYTES_PER_RING_ELEMENT].copy_from_slice( + &serialize_secret_key::(t_as_ntt), + ); + public_key_serialized[RANKED_BYTES_PER_RING_ELEMENT..].copy_from_slice(seed_for_a); + public_key_serialized +} + +/// Call [`serialize_uncompressed_ring_element`] for each ring element. +#[inline(always)] +fn serialize_secret_key( + key: [PolynomialRingElement; K], +) -> [u8; OUT_LEN] { + let mut out = [0u8; OUT_LEN]; + + cloop! { + for (i, re) in key.into_iter().enumerate() { + out[i * BYTES_PER_RING_ELEMENT..(i + 1) * BYTES_PER_RING_ELEMENT] + .copy_from_slice(&serialize_uncompressed_ring_element(re)); + } + } + + out +} + +/// Sample a vector of ring elements from a centered binomial distribution. +#[inline(always)] +fn sample_ring_element_cbd( + prf_input: &mut [u8; 33], + domain_separator: &mut u8, +) -> [PolynomialRingElement; K] { + let mut error_1 = [PolynomialRingElement::ZERO; K]; + for i in 0..K { + prf_input[32] = *domain_separator; + *domain_separator += 1; + + let prf_output: [u8; ETA2_RANDOMNESS_SIZE] = PRF(prf_input); + error_1[i] = sample_from_binomial_distribution::(&prf_output); + } + error_1 +} + +/// Sample a vector of ring elements from a centered binomial distribution and +/// convert them into their NTT representations. +#[inline(always)] +fn sample_vector_cbd_then_ntt< + const K: usize, + const ETA: usize, + const ETA_RANDOMNESS_SIZE: usize, +>( + mut prf_input: [u8; 33], + mut domain_separator: u8, +) -> ([PolynomialRingElement; K], u8) { + let mut re_as_ntt = [PolynomialRingElement::ZERO; K]; + for i in 0..K { + prf_input[32] = domain_separator; + domain_separator += 1; + + let prf_output: [u8; ETA_RANDOMNESS_SIZE] = PRF(&prf_input); + + let r = sample_from_binomial_distribution::(&prf_output); + re_as_ntt[i] = ntt_binomially_sampled_ring_element(r); + } + (re_as_ntt, domain_separator) +} + +/// This function implements most of Algorithm 12 of the +/// NIST FIPS 203 specification; this is the Kyber CPA-PKE key generation algorithm. +/// +/// We say "most of" since Algorithm 12 samples the required randomness within +/// the function itself, whereas this implementation expects it to be provided +/// through the `key_generation_seed` parameter. +/// +/// Algorithm 12 is reproduced below: +/// +/// ```plaintext +/// Output: encryption key ekₚₖₑ ∈ 𝔹^{384k+32}. +/// Output: decryption key dkₚₖₑ ∈ 𝔹^{384k}. +/// +/// d ←$ B +/// (ρ,σ) ← G(d) +/// N ← 0 +/// for (i ← 0; i < k; i++) +/// for(j ← 0; j < k; j++) +/// Â[i,j] ← SampleNTT(XOF(ρ, i, j)) +/// end for +/// end for +/// for(i ← 0; i < k; i++) +/// s[i] ← SamplePolyCBD_{η₁}(PRF_{η₁}(σ,N)) +/// N ← N + 1 +/// end for +/// for(i ← 0; i < k; i++) +/// e[i] ← SamplePolyCBD_{η₂}(PRF_{η₂}(σ,N)) +/// N ← N + 1 +/// end for +/// ŝ ← NTT(s) +/// ê ← NTT(e) +/// t̂ ← Â◦ŝ + ê +/// ekₚₖₑ ← ByteEncode₁₂(t̂) ‖ ρ +/// dkₚₖₑ ← ByteEncode₁₂(ŝ) +/// ``` +/// +/// The NIST FIPS 203 standard can be found at +/// . +#[allow(non_snake_case)] +pub(super) fn generate_keypair_unpacked< + const K: usize, + const PUBLIC_KEY_SIZE: usize, + const RANKED_BYTES_PER_RING_ELEMENT: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, +>( + key_generation_seed: &[u8], +) -> ( + ( + [PolynomialRingElement; K], + [PolynomialRingElement; K], + [[PolynomialRingElement; K]; K], + ), + [u8; PUBLIC_KEY_SIZE], +) { + // (ρ,σ) := G(d) + let hashed = G(key_generation_seed); + let (seed_for_A, seed_for_secret_and_error) = hashed.split_at(32); + + let a_transpose = sample_matrix_A(into_padded_array(seed_for_A), true); + + let prf_input: [u8; 33] = into_padded_array(seed_for_secret_and_error); + let (mut secret_as_ntt, domain_separator) = + sample_vector_cbd_then_ntt::(prf_input, 0); + let (error_as_ntt, _) = + sample_vector_cbd_then_ntt::(prf_input, domain_separator); + + // tˆ := Aˆ ◦ sˆ + eˆ + let mut t_as_ntt = compute_As_plus_e(&a_transpose, &secret_as_ntt, &error_as_ntt); + + // pk := (Encode_12(tˆ mod^{+}q) || ρ) + let public_key_serialized = serialize_public_key::< + K, + RANKED_BYTES_PER_RING_ELEMENT, + PUBLIC_KEY_SIZE, + >(t_as_ntt, &seed_for_A); + + // Need to do the following otherwise it violates invariants in NTT (the values are expected to be >=0 and <4096). + // Maybe we can remove these reductions later if we make those constraints looser + for i in 0..K { + for j in 0..COEFFICIENTS_IN_RING_ELEMENT { + secret_as_ntt[i].coefficients[j] = + to_unsigned_representative(secret_as_ntt[i].coefficients[j]) as i32; + t_as_ntt[i].coefficients[j] = + to_unsigned_representative(t_as_ntt[i].coefficients[j]) as i32; + } + } + + // We also need to transpose the A array. + let mut a_matrix = a_transpose; + for i in 0..K { + for j in 0..K { + a_matrix[i][j] = a_transpose[j][i]; + } + } + + ((secret_as_ntt, t_as_ntt, a_matrix), public_key_serialized) +} + +#[allow(non_snake_case)] +pub(super) fn generate_keypair< + const K: usize, + const PRIVATE_KEY_SIZE: usize, + const PUBLIC_KEY_SIZE: usize, + const RANKED_BYTES_PER_RING_ELEMENT: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, +>( + key_generation_seed: &[u8], +) -> ([u8; PRIVATE_KEY_SIZE], [u8; PUBLIC_KEY_SIZE]) { + let ((secret_as_ntt, _t_as_ntt, _a_transpose), public_key_serialized) = + generate_keypair_unpacked::< + K, + PUBLIC_KEY_SIZE, + RANKED_BYTES_PER_RING_ELEMENT, + ETA1, + ETA1_RANDOMNESS_SIZE, + >(key_generation_seed); + + // sk := Encode_12(sˆ mod^{+}q) + let secret_key_serialized = serialize_secret_key(secret_as_ntt); + + (secret_key_serialized, public_key_serialized) +} + +/// Call [`compress_then_serialize_ring_element_u`] on each ring element. +fn compress_then_serialize_u< + const K: usize, + const OUT_LEN: usize, + const COMPRESSION_FACTOR: usize, + const BLOCK_LEN: usize, +>( + input: [PolynomialRingElement; K], +) -> [u8; OUT_LEN] { + let mut out = [0u8; OUT_LEN]; + cloop! { + for (i, re) in input.into_iter().enumerate() { + out[i * (OUT_LEN / K)..(i + 1) * (OUT_LEN / K)].copy_from_slice( + &compress_then_serialize_ring_element_u::(re), + ); + } + } + + out +} + +/// This function implements Algorithm 13 of the +/// NIST FIPS 203 specification; this is the Kyber CPA-PKE encryption algorithm. +/// +/// Algorithm 13 is reproduced below: +/// +/// ```plaintext +/// Input: encryption key ekₚₖₑ ∈ 𝔹^{384k+32}. +/// Input: message m ∈ 𝔹^{32}. +/// Input: encryption randomness r ∈ 𝔹^{32}. +/// Output: ciphertext c ∈ 𝔹^{32(dᵤk + dᵥ)}. +/// +/// N ← 0 +/// t̂ ← ByteDecode₁₂(ekₚₖₑ[0:384k]) +/// ρ ← ekₚₖₑ[384k: 384k + 32] +/// for (i ← 0; i < k; i++) +/// for(j ← 0; j < k; j++) +/// Â[i,j] ← SampleNTT(XOF(ρ, i, j)) +/// end for +/// end for +/// for(i ← 0; i < k; i++) +/// r[i] ← SamplePolyCBD_{η₁}(PRF_{η₁}(r,N)) +/// N ← N + 1 +/// end for +/// for(i ← 0; i < k; i++) +/// e₁[i] ← SamplePolyCBD_{η₂}(PRF_{η₂}(r,N)) +/// N ← N + 1 +/// end for +/// e₂ ← SamplePolyCBD_{η₂}(PRF_{η₂}(r,N)) +/// r̂ ← NTT(r) +/// u ← NTT-¹(Âᵀ ◦ r̂) + e₁ +/// μ ← Decompress₁(ByteDecode₁(m))) +/// v ← NTT-¹(t̂ᵀ ◦ rˆ) + e₂ + μ +/// c₁ ← ByteEncode_{dᵤ}(Compress_{dᵤ}(u)) +/// c₂ ← ByteEncode_{dᵥ}(Compress_{dᵥ}(v)) +/// return c ← (c₁ ‖ c₂) +/// ``` +/// +/// The NIST FIPS 203 standard can be found at +/// . +#[allow(non_snake_case)] +pub(crate) fn encrypt_unpacked< + const K: usize, + const CIPHERTEXT_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_LEN: usize, + const C2_LEN: usize, + const U_COMPRESSION_FACTOR: usize, + const V_COMPRESSION_FACTOR: usize, + const BLOCK_LEN: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, +>( + t_as_ntt: &[PolynomialRingElement; K], + a_transpose: &[[PolynomialRingElement; K]; K], + message: [u8; SHARED_SECRET_SIZE], + randomness: &[u8], +) -> [u8; CIPHERTEXT_SIZE] { + // for i from 0 to k−1 do + // r[i] := CBD{η1}(PRF(r, N)) + // N := N + 1 + // end for + // rˆ := NTT(r) + let mut prf_input: [u8; 33] = into_padded_array(randomness); + let (r_as_ntt, mut domain_separator) = + sample_vector_cbd_then_ntt::(prf_input, 0); + + // for i from 0 to k−1 do + // e1[i] := CBD_{η2}(PRF(r,N)) + // N := N + 1 + // end for + let error_1 = sample_ring_element_cbd::( + &mut prf_input, + &mut domain_separator, + ); + + // e_2 := CBD{η2}(PRF(r, N)) + prf_input[32] = domain_separator; + let prf_output: [u8; ETA2_RANDOMNESS_SIZE] = PRF(&prf_input); + let error_2 = sample_from_binomial_distribution::(&prf_output); + + // u := NTT^{-1}(AˆT ◦ rˆ) + e_1 + let u = compute_vector_u(&a_transpose, &r_as_ntt, &error_1); + + // v := NTT^{−1}(tˆT ◦ rˆ) + e_2 + Decompress_q(Decode_1(m),1) + let message_as_ring_element = deserialize_then_decompress_message(message); + let v = compute_ring_element_v(&t_as_ntt, &r_as_ntt, &error_2, &message_as_ring_element); + + // c_1 := Encode_{du}(Compress_q(u,d_u)) + let c1 = compress_then_serialize_u::(u); + + // c_2 := Encode_{dv}(Compress_q(v,d_v)) + let c2 = compress_then_serialize_ring_element_v::(v); + + let mut ciphertext: [u8; CIPHERTEXT_SIZE] = into_padded_array(&c1); + ciphertext[C1_LEN..].copy_from_slice(c2.as_slice()); + + ciphertext +} + +#[allow(non_snake_case)] +pub(crate) fn encrypt< + const K: usize, + const CIPHERTEXT_SIZE: usize, + const T_AS_NTT_ENCODED_SIZE: usize, + const C1_LEN: usize, + const C2_LEN: usize, + const U_COMPRESSION_FACTOR: usize, + const V_COMPRESSION_FACTOR: usize, + const BLOCK_LEN: usize, + const ETA1: usize, + const ETA1_RANDOMNESS_SIZE: usize, + const ETA2: usize, + const ETA2_RANDOMNESS_SIZE: usize, +>( + public_key: &[u8], + message: [u8; SHARED_SECRET_SIZE], + randomness: &[u8], +) -> [u8; CIPHERTEXT_SIZE] { + // tˆ := Decode_12(pk) + let t_as_ntt = deserialize_ring_elements_reduced::( + &public_key[..T_AS_NTT_ENCODED_SIZE], + ); + + // ρ := pk + 12·k·n / 8 + // for i from 0 to k−1 do + // for j from 0 to k − 1 do + // AˆT[i][j] := Parse(XOF(ρ, i, j)) + // end for + // end for + let seed = &public_key[T_AS_NTT_ENCODED_SIZE..]; + // ρ := pk + 12·k·n / 8 + // for i from 0 to k−1 do + // for j from 0 to k − 1 do + // AˆT[i][j] := Parse(XOF(ρ, i, j)) + // end for + // end for + let a_transpose = sample_matrix_A(into_padded_array(seed), false); + + encrypt_unpacked::< + K, + CIPHERTEXT_SIZE, + T_AS_NTT_ENCODED_SIZE, + C1_LEN, + C2_LEN, + U_COMPRESSION_FACTOR, + V_COMPRESSION_FACTOR, + BLOCK_LEN, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(&t_as_ntt, &a_transpose, message, randomness) +} + +/// Call [`deserialize_then_decompress_ring_element_u`] on each ring element +/// in the `ciphertext`. +#[inline(always)] +fn deserialize_then_decompress_u< + const K: usize, + const CIPHERTEXT_SIZE: usize, + const U_COMPRESSION_FACTOR: usize, +>( + ciphertext: &[u8; CIPHERTEXT_SIZE], +) -> [PolynomialRingElement; K] { + let mut u_as_ntt = [PolynomialRingElement::ZERO; K]; + cloop! { + for (i, u_bytes) in ciphertext + .chunks_exact((COEFFICIENTS_IN_RING_ELEMENT * U_COMPRESSION_FACTOR) / 8) + .enumerate() + { + let u = deserialize_then_decompress_ring_element_u::(u_bytes); + u_as_ntt[i] = ntt_vector_u::(u); + } + } + u_as_ntt +} + +/// Call [`deserialize_to_uncompressed_ring_element`] for each ring element. +#[inline(always)] +fn deserialize_secret_key(secret_key: &[u8]) -> [PolynomialRingElement; K] { + let mut secret_as_ntt = [PolynomialRingElement::ZERO; K]; + cloop! { + for (i, secret_bytes) in secret_key.chunks_exact(BYTES_PER_RING_ELEMENT).enumerate() { + secret_as_ntt[i] = deserialize_to_uncompressed_ring_element(secret_bytes); + } + } + secret_as_ntt +} + +/// This function implements Algorithm 14 of the +/// NIST FIPS 203 specification; this is the Kyber CPA-PKE decryption algorithm. +/// +/// Algorithm 14 is reproduced below: +/// +/// ```plaintext +/// Input: decryption key dkₚₖₑ ∈ 𝔹^{384k}. +/// Input: ciphertext c ∈ 𝔹^{32(dᵤk + dᵥ)}. +/// Output: message m ∈ 𝔹^{32}. +/// +/// c₁ ← c[0 : 32dᵤk] +/// c₂ ← c[32dᵤk : 32(dᵤk + dᵥ)] +/// u ← Decompress_{dᵤ}(ByteDecode_{dᵤ}(c₁)) +/// v ← Decompress_{dᵥ}(ByteDecode_{dᵥ}(c₂)) +/// ŝ ← ByteDecode₁₂(dkₚₖₑ) +/// w ← v - NTT-¹(ŝᵀ ◦ NTT(u)) +/// m ← ByteEncode₁(Compress₁(w)) +/// return m +/// ``` +/// +/// The NIST FIPS 203 standard can be found at +/// . +#[allow(non_snake_case)] +pub(super) fn decrypt_unpacked< + const K: usize, + const CIPHERTEXT_SIZE: usize, + const VECTOR_U_ENCODED_SIZE: usize, + const U_COMPRESSION_FACTOR: usize, + const V_COMPRESSION_FACTOR: usize, +>( + secret_as_ntt: &[PolynomialRingElement; K], + ciphertext: &[u8; CIPHERTEXT_SIZE], +) -> [u8; SHARED_SECRET_SIZE] { + // u := Decompress_q(Decode_{d_u}(c), d_u) + let u_as_ntt = + deserialize_then_decompress_u::(ciphertext); + + // v := Decompress_q(Decode_{d_v}(c + d_u·k·n / 8), d_v) + let v = deserialize_then_decompress_ring_element_v::( + &ciphertext[VECTOR_U_ENCODED_SIZE..], + ); + + // m := Encode_1(Compress_q(v − NTT^{−1}(sˆT ◦ NTT(u)) , 1)) + let message = compute_message(&v, &secret_as_ntt, &u_as_ntt); + compress_then_serialize_message(message) +} + +#[allow(non_snake_case)] +pub(super) fn decrypt< + const K: usize, + const CIPHERTEXT_SIZE: usize, + const VECTOR_U_ENCODED_SIZE: usize, + const U_COMPRESSION_FACTOR: usize, + const V_COMPRESSION_FACTOR: usize, +>( + secret_key: &[u8], + ciphertext: &[u8; CIPHERTEXT_SIZE], +) -> [u8; SHARED_SECRET_SIZE] { + // sˆ := Decode_12(sk) + let secret_as_ntt = deserialize_secret_key::(secret_key); + + decrypt_unpacked::< + K, + CIPHERTEXT_SIZE, + VECTOR_U_ENCODED_SIZE, + U_COMPRESSION_FACTOR, + V_COMPRESSION_FACTOR, + >(&secret_as_ntt, ciphertext) +} diff --git a/libcrux-ml-kem/src/kem/kyber/kyber1024.rs b/libcrux-ml-kem/src/kem/kyber/kyber1024.rs new file mode 100644 index 00000000..b15c6ec1 --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/kyber1024.rs @@ -0,0 +1,160 @@ +use super::{constants::*, *}; + +// Kyber 1024 parameters +const RANK_1024: usize = 4; +const RANKED_BYTES_PER_RING_ELEMENT_1024: usize = RANK_1024 * BITS_PER_RING_ELEMENT / 8; +const T_AS_NTT_ENCODED_SIZE_1024: usize = + (RANK_1024 * COEFFICIENTS_IN_RING_ELEMENT * BITS_PER_COEFFICIENT) / 8; +const VECTOR_U_COMPRESSION_FACTOR_1024: usize = 11; +// [hax]: hacspec/hacspec-v2#27 stealing error +// block_len::(); +const C1_BLOCK_SIZE_1024: usize = + (COEFFICIENTS_IN_RING_ELEMENT * VECTOR_U_COMPRESSION_FACTOR_1024) / 8; +// [hax]: hacspec/hacspec-v2#27 stealing error +// serialized_len::(); +const C1_SIZE_1024: usize = C1_BLOCK_SIZE_1024 * RANK_1024; +const VECTOR_V_COMPRESSION_FACTOR_1024: usize = 5; +// [hax]: hacspec/hacspec-v2#27 stealing error +// block_len::() +const C2_SIZE_1024: usize = (COEFFICIENTS_IN_RING_ELEMENT * VECTOR_V_COMPRESSION_FACTOR_1024) / 8; +const CPA_PKE_SECRET_KEY_SIZE_1024: usize = + (RANK_1024 * COEFFICIENTS_IN_RING_ELEMENT * BITS_PER_COEFFICIENT) / 8; +const CPA_PKE_PUBLIC_KEY_SIZE_1024: usize = T_AS_NTT_ENCODED_SIZE_1024 + 32; +const CPA_PKE_CIPHERTEXT_SIZE_1024: usize = C1_SIZE_1024 + C2_SIZE_1024; +const SECRET_KEY_SIZE_1024: usize = CPA_PKE_SECRET_KEY_SIZE_1024 + + CPA_PKE_PUBLIC_KEY_SIZE_1024 + + H_DIGEST_SIZE + + SHARED_SECRET_SIZE; + +const ETA1: usize = 2; +const ETA1_RANDOMNESS_SIZE: usize = ETA1 * 64; +const ETA2: usize = 2; +const ETA2_RANDOMNESS_SIZE: usize = ETA2 * 64; + +const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = SHARED_SECRET_SIZE + CPA_PKE_CIPHERTEXT_SIZE_1024; + +// Kyber 1024 types +pub type MlKem1024Ciphertext = MlKemCiphertext; +pub type MlKem1024PrivateKey = MlKemPrivateKey; +pub type MlKem1024PublicKey = MlKemPublicKey; + +/// Validate a public key. +/// +/// Returns `Some(public_key)` if valid, and `None` otherwise. +pub fn validate_public_key(public_key: MlKem1024PublicKey) -> Option { + if super::validate_public_key::< + RANK_1024, + RANKED_BYTES_PER_RING_ELEMENT_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + >(&public_key.value) + { + Some(public_key) + } else { + None + } +} + +/// Generate ML-KEM 1024 Key Pair +pub fn generate_key_pair( + randomness: [u8; KEY_GENERATION_SEED_SIZE], +) -> MlKemKeyPair { + super::generate_keypair::< + RANK_1024, + CPA_PKE_SECRET_KEY_SIZE_1024, + SECRET_KEY_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + RANKED_BYTES_PER_RING_ELEMENT_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + >(randomness) +} + +pub type MlKem1024State = MlKemState; + +pub fn generate_key_pair_unpacked( + randomness: [u8; KEY_GENERATION_SEED_SIZE], +) -> (MlKem1024State, MlKem1024PublicKey) { + generate_keypair_unpacked::< + RANK_1024, + CPA_PKE_SECRET_KEY_SIZE_1024, + SECRET_KEY_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + RANKED_BYTES_PER_RING_ELEMENT_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + >(randomness) +} + +/// Encapsulate ML-KEM 1024 +pub fn encapsulate( + public_key: &MlKemPublicKey, + randomness: [u8; SHARED_SECRET_SIZE], +) -> ( + MlKemCiphertext, + MlKemSharedSecret, +) { + super::encapsulate::< + RANK_1024, + CPA_PKE_CIPHERTEXT_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + T_AS_NTT_ENCODED_SIZE_1024, + C1_SIZE_1024, + C2_SIZE_1024, + VECTOR_U_COMPRESSION_FACTOR_1024, + VECTOR_V_COMPRESSION_FACTOR_1024, + C1_BLOCK_SIZE_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) +} + +/// Decapsulate ML-KEM 1024 +pub fn decapsulate( + secret_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, +) -> [u8; SHARED_SECRET_SIZE] { + super::decapsulate::< + RANK_1024, + SECRET_KEY_SIZE_1024, + CPA_PKE_SECRET_KEY_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + CPA_PKE_CIPHERTEXT_SIZE_1024, + T_AS_NTT_ENCODED_SIZE_1024, + C1_SIZE_1024, + C2_SIZE_1024, + VECTOR_U_COMPRESSION_FACTOR_1024, + VECTOR_V_COMPRESSION_FACTOR_1024, + C1_BLOCK_SIZE_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(secret_key, ciphertext) +} + +pub fn decapsulate_unpacked( + state: &MlKem1024State, + ciphertext: &MlKemCiphertext, +) -> [u8; SHARED_SECRET_SIZE] { + super::decapsulate_unpacked::< + RANK_1024, + SECRET_KEY_SIZE_1024, + CPA_PKE_SECRET_KEY_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + CPA_PKE_CIPHERTEXT_SIZE_1024, + T_AS_NTT_ENCODED_SIZE_1024, + C1_SIZE_1024, + C2_SIZE_1024, + VECTOR_U_COMPRESSION_FACTOR_1024, + VECTOR_V_COMPRESSION_FACTOR_1024, + C1_BLOCK_SIZE_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(state, ciphertext) +} diff --git a/libcrux-ml-kem/src/kem/kyber/kyber512.rs b/libcrux-ml-kem/src/kem/kyber/kyber512.rs new file mode 100644 index 00000000..8edce7f4 --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/kyber512.rs @@ -0,0 +1,158 @@ +use super::{constants::*, *}; + +// Kyber 512 parameters +const RANK_512: usize = 2; +const RANKED_BYTES_PER_RING_ELEMENT_512: usize = RANK_512 * BITS_PER_RING_ELEMENT / 8; +const T_AS_NTT_ENCODED_SIZE_512: usize = + (RANK_512 * COEFFICIENTS_IN_RING_ELEMENT * BITS_PER_COEFFICIENT) / 8; +const VECTOR_U_COMPRESSION_FACTOR_512: usize = 10; +// [hax]: hacspec/hacspec-v2#27 stealing error +// block_len::() +const C1_BLOCK_SIZE_512: usize = + (COEFFICIENTS_IN_RING_ELEMENT * VECTOR_U_COMPRESSION_FACTOR_512) / 8; +// [hax]: hacspec/hacspec-v2#27 stealing error +// serialized_len::() +const C1_SIZE_512: usize = C1_BLOCK_SIZE_512 * RANK_512; +const VECTOR_V_COMPRESSION_FACTOR_512: usize = 4; +// [hax]: hacspec/hacspec-v2#27 stealing error +// block_len::() +const C2_SIZE_512: usize = (COEFFICIENTS_IN_RING_ELEMENT * VECTOR_V_COMPRESSION_FACTOR_512) / 8; +const CPA_PKE_SECRET_KEY_SIZE_512: usize = + (RANK_512 * COEFFICIENTS_IN_RING_ELEMENT * BITS_PER_COEFFICIENT) / 8; +const CPA_PKE_PUBLIC_KEY_SIZE_512: usize = T_AS_NTT_ENCODED_SIZE_512 + 32; +const CPA_PKE_CIPHERTEXT_SIZE_512: usize = C1_SIZE_512 + C2_SIZE_512; +const SECRET_KEY_SIZE_512: usize = + CPA_PKE_SECRET_KEY_SIZE_512 + CPA_PKE_PUBLIC_KEY_SIZE_512 + H_DIGEST_SIZE + SHARED_SECRET_SIZE; + +const ETA1: usize = 3; +const ETA1_RANDOMNESS_SIZE: usize = ETA1 * 64; +const ETA2: usize = 2; +const ETA2_RANDOMNESS_SIZE: usize = ETA2 * 64; + +const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = SHARED_SECRET_SIZE + CPA_PKE_CIPHERTEXT_SIZE_512; + +// Kyber 512 types +pub type MlKem512Ciphertext = MlKemCiphertext; +pub type MlKem512PrivateKey = MlKemPrivateKey; +pub type MlKem512PublicKey = MlKemPublicKey; + +/// Validate a public key. +/// +/// Returns `Some(public_key)` if valid, and `None` otherwise. +pub fn validate_public_key(public_key: MlKem512PublicKey) -> Option { + if super::validate_public_key::< + RANK_512, + RANKED_BYTES_PER_RING_ELEMENT_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + >(&public_key.value) + { + Some(public_key) + } else { + None + } +} + +/// Generate ML-KEM 512 Key Pair +pub fn generate_key_pair( + randomness: [u8; KEY_GENERATION_SEED_SIZE], +) -> MlKemKeyPair { + generate_keypair::< + RANK_512, + CPA_PKE_SECRET_KEY_SIZE_512, + SECRET_KEY_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + RANKED_BYTES_PER_RING_ELEMENT_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + >(randomness) +} + +pub type MlKem512State = MlKemState; + +pub fn generate_key_pair_unpacked( + randomness: [u8; KEY_GENERATION_SEED_SIZE], +) -> (MlKem512State, MlKem512PublicKey) { + generate_keypair_unpacked::< + RANK_512, + CPA_PKE_SECRET_KEY_SIZE_512, + SECRET_KEY_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + RANKED_BYTES_PER_RING_ELEMENT_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + >(randomness) +} + +/// Encapsulate ML-KEM 512 +pub fn encapsulate( + public_key: &MlKemPublicKey, + randomness: [u8; SHARED_SECRET_SIZE], +) -> ( + MlKemCiphertext, + MlKemSharedSecret, +) { + super::encapsulate::< + RANK_512, + CPA_PKE_CIPHERTEXT_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + T_AS_NTT_ENCODED_SIZE_512, + C1_SIZE_512, + C2_SIZE_512, + VECTOR_U_COMPRESSION_FACTOR_512, + VECTOR_V_COMPRESSION_FACTOR_512, + C1_BLOCK_SIZE_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) +} + +/// Decapsulate ML-KEM 512 +pub fn decapsulate( + secret_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, +) -> [u8; SHARED_SECRET_SIZE] { + super::decapsulate::< + RANK_512, + SECRET_KEY_SIZE_512, + CPA_PKE_SECRET_KEY_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + CPA_PKE_CIPHERTEXT_SIZE_512, + T_AS_NTT_ENCODED_SIZE_512, + C1_SIZE_512, + C2_SIZE_512, + VECTOR_U_COMPRESSION_FACTOR_512, + VECTOR_V_COMPRESSION_FACTOR_512, + C1_BLOCK_SIZE_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(secret_key, ciphertext) +} + +pub fn decapsulate_unpacked( + state: &MlKem512State, + ciphertext: &MlKemCiphertext, +) -> [u8; SHARED_SECRET_SIZE] { + super::decapsulate_unpacked::< + RANK_512, + SECRET_KEY_SIZE_512, + CPA_PKE_SECRET_KEY_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + CPA_PKE_CIPHERTEXT_SIZE_512, + T_AS_NTT_ENCODED_SIZE_512, + C1_SIZE_512, + C2_SIZE_512, + VECTOR_U_COMPRESSION_FACTOR_512, + VECTOR_V_COMPRESSION_FACTOR_512, + C1_BLOCK_SIZE_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(state, ciphertext) +} diff --git a/libcrux-ml-kem/src/kem/kyber/kyber768.rs b/libcrux-ml-kem/src/kem/kyber/kyber768.rs new file mode 100644 index 00000000..7d9f5b13 --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/kyber768.rs @@ -0,0 +1,178 @@ +use super::{constants::*, *}; + +// Kyber 768 parameters +const RANK_768: usize = 3; +const RANKED_BYTES_PER_RING_ELEMENT_768: usize = RANK_768 * BITS_PER_RING_ELEMENT / 8; +const T_AS_NTT_ENCODED_SIZE_768: usize = + (RANK_768 * COEFFICIENTS_IN_RING_ELEMENT * BITS_PER_COEFFICIENT) / 8; +const VECTOR_U_COMPRESSION_FACTOR_768: usize = 10; +// [hax]: hacspec/hacspec-v2#27 stealing error +// block_len::() +const C1_BLOCK_SIZE_768: usize = + (COEFFICIENTS_IN_RING_ELEMENT * VECTOR_U_COMPRESSION_FACTOR_768) / 8; +// [hax]: hacspec/hacspec-v2#27 stealing error +// serialized_len::(); +const C1_SIZE_768: usize = C1_BLOCK_SIZE_768 * RANK_768; +const VECTOR_V_COMPRESSION_FACTOR_768: usize = 4; +// [hax]: hacspec/hacspec-v2#27 stealing error +// block_len::() +const C2_SIZE_768: usize = (COEFFICIENTS_IN_RING_ELEMENT * VECTOR_V_COMPRESSION_FACTOR_768) / 8; +const CPA_PKE_SECRET_KEY_SIZE_768: usize = + (RANK_768 * COEFFICIENTS_IN_RING_ELEMENT * BITS_PER_COEFFICIENT) / 8; +const CPA_PKE_PUBLIC_KEY_SIZE_768: usize = T_AS_NTT_ENCODED_SIZE_768 + 32; +// These two are used in the hybrid kem. This could probably be improved. +pub(crate) const CPA_PKE_CIPHERTEXT_SIZE_768: usize = C1_SIZE_768 + C2_SIZE_768; +pub(crate) const SECRET_KEY_SIZE_768: usize = + CPA_PKE_SECRET_KEY_SIZE_768 + CPA_PKE_PUBLIC_KEY_SIZE_768 + H_DIGEST_SIZE + SHARED_SECRET_SIZE; + +const ETA1: usize = 2; +const ETA1_RANDOMNESS_SIZE: usize = ETA1 * 64; +const ETA2: usize = 2; +const ETA2_RANDOMNESS_SIZE: usize = ETA2 * 64; + +const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = SHARED_SECRET_SIZE + CPA_PKE_CIPHERTEXT_SIZE_768; + +// Kyber 768 types +pub type MlKem768Ciphertext = MlKemCiphertext; +pub type MlKem768PrivateKey = MlKemPrivateKey; +pub type MlKem768PublicKey = MlKemPublicKey; + +/// Validate a public key. +/// +/// Returns `Some(public_key)` if valid, and `None` otherwise. +pub fn validate_public_key(public_key: MlKem768PublicKey) -> Option { + if super::validate_public_key::< + RANK_768, + RANKED_BYTES_PER_RING_ELEMENT_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + >(&public_key.value) + { + Some(public_key) + } else { + None + } +} + +/// Generate ML-KEM 768 Key Pair +pub fn generate_key_pair( + randomness: [u8; KEY_GENERATION_SEED_SIZE], +) -> MlKemKeyPair { + generate_keypair::< + RANK_768, + CPA_PKE_SECRET_KEY_SIZE_768, + SECRET_KEY_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + RANKED_BYTES_PER_RING_ELEMENT_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + >(randomness) +} + +pub type MlKem768State = MlKemState; + +pub fn generate_key_pair_unpacked( + randomness: [u8; KEY_GENERATION_SEED_SIZE], +) -> (MlKem768State, MlKem768PublicKey) { + generate_keypair_unpacked::< + RANK_768, + CPA_PKE_SECRET_KEY_SIZE_768, + SECRET_KEY_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + RANKED_BYTES_PER_RING_ELEMENT_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + >(randomness) +} + +/// Encapsulate ML-KEM 768 +pub fn encapsulate( + public_key: &MlKemPublicKey, + randomness: [u8; SHARED_SECRET_SIZE], +) -> ( + MlKemCiphertext, + MlKemSharedSecret, +) { + super::encapsulate::< + RANK_768, + CPA_PKE_CIPHERTEXT_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + T_AS_NTT_ENCODED_SIZE_768, + C1_SIZE_768, + C2_SIZE_768, + VECTOR_U_COMPRESSION_FACTOR_768, + VECTOR_V_COMPRESSION_FACTOR_768, + C1_BLOCK_SIZE_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) +} + +/// Decapsulate ML-KEM 768 +pub fn decapsulate( + secret_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, +) -> [u8; SHARED_SECRET_SIZE] { + super::decapsulate::< + RANK_768, + SECRET_KEY_SIZE_768, + CPA_PKE_SECRET_KEY_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + CPA_PKE_CIPHERTEXT_SIZE_768, + T_AS_NTT_ENCODED_SIZE_768, + C1_SIZE_768, + C2_SIZE_768, + VECTOR_U_COMPRESSION_FACTOR_768, + VECTOR_V_COMPRESSION_FACTOR_768, + C1_BLOCK_SIZE_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(secret_key, ciphertext) +} + +pub fn decapsulate_unpacked( + state: &MlKem768State, + ciphertext: &MlKemCiphertext, +) -> [u8; SHARED_SECRET_SIZE] { + super::decapsulate_unpacked::< + RANK_768, + SECRET_KEY_SIZE_768, + CPA_PKE_SECRET_KEY_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + CPA_PKE_CIPHERTEXT_SIZE_768, + T_AS_NTT_ENCODED_SIZE_768, + C1_SIZE_768, + C2_SIZE_768, + VECTOR_U_COMPRESSION_FACTOR_768, + VECTOR_V_COMPRESSION_FACTOR_768, + C1_BLOCK_SIZE_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(state, ciphertext) +} + +#[cfg(test)] +mod tests { + use rand_core::{OsRng, RngCore}; + + use super::{ + kyber768::{generate_key_pair, validate_public_key}, + KEY_GENERATION_SEED_SIZE, + }; + + #[test] + fn pk_validation() { + let mut randomness = [0u8; KEY_GENERATION_SEED_SIZE]; + OsRng.fill_bytes(&mut randomness); + + let key_pair = generate_key_pair(randomness); + assert!(validate_public_key(key_pair.pk).is_some()); + } +} diff --git a/libcrux-ml-kem/src/kem/kyber/matrix.rs b/libcrux-ml-kem/src/kem/kyber/matrix.rs new file mode 100644 index 00000000..a4908eaa --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/matrix.rs @@ -0,0 +1,158 @@ +use super::{ + arithmetic::{ + add_to_ring_element, barrett_reduce, montgomery_reduce, to_standard_domain, + PolynomialRingElement, + }, + constants::COEFFICIENTS_IN_RING_ELEMENT, + ntt::{invert_ntt_montgomery, ntt_multiply}, + sampling::sample_from_xof, +}; +use crate::cloop; + +#[inline(always)] +#[allow(non_snake_case)] +pub(in crate::kem::kyber) fn sample_matrix_A( + seed: [u8; 34], + transpose: bool, +) -> [[PolynomialRingElement; K]; K] { + let mut A_transpose = [[PolynomialRingElement::ZERO; K]; K]; + + for i in 0..K { + let mut seeds = [seed; K]; + for j in 0..K { + seeds[j][32] = i as u8; + seeds[j][33] = j as u8; + } + let sampled = sample_from_xof(seeds); + for j in 0..K { + // A[i][j] = A_transpose[j][i] + if transpose { + A_transpose[j][i] = sampled[j]; + } else { + A_transpose[i][j] = sampled[j]; + } + } + } + + A_transpose +} + +/// The following functions compute various expressions involving +/// vectors and matrices. The computation of these expressions has been +/// abstracted away into these functions in order to save on loop iterations. + +/// Compute v − InverseNTT(sᵀ ◦ NTT(u)) +#[inline(always)] +pub(in crate::kem::kyber) fn compute_message( + v: &PolynomialRingElement, + secret_as_ntt: &[PolynomialRingElement; K], + u_as_ntt: &[PolynomialRingElement; K], +) -> PolynomialRingElement { + let mut result = PolynomialRingElement::ZERO; + + for i in 0..K { + let product = ntt_multiply(&secret_as_ntt[i], &u_as_ntt[i]); + result = add_to_ring_element::(result, &product); + } + + result = invert_ntt_montgomery::(result); + + for i in 0..COEFFICIENTS_IN_RING_ELEMENT { + let coefficient_normal_form = montgomery_reduce(result.coefficients[i] * 1441); + result.coefficients[i] = barrett_reduce(v.coefficients[i] - coefficient_normal_form); + } + + result +} + +/// Compute InverseNTT(tᵀ ◦ r̂) + e₂ + message +#[inline(always)] +pub(in crate::kem::kyber) fn compute_ring_element_v( + t_as_ntt: &[PolynomialRingElement; K], + r_as_ntt: &[PolynomialRingElement; K], + error_2: &PolynomialRingElement, + message: &PolynomialRingElement, +) -> PolynomialRingElement { + let mut result = PolynomialRingElement::ZERO; + + for i in 0..K { + let product = ntt_multiply(&t_as_ntt[i], &r_as_ntt[i]); + result = add_to_ring_element::(result, &product); + } + + result = invert_ntt_montgomery::(result); + + for i in 0..COEFFICIENTS_IN_RING_ELEMENT { + let coefficient_normal_form = montgomery_reduce(result.coefficients[i] * 1441); + result.coefficients[i] = barrett_reduce( + coefficient_normal_form + error_2.coefficients[i] + message.coefficients[i], + ); + } + + result +} + +/// Compute u := InvertNTT(Aᵀ ◦ r̂) + e₁ +#[inline(always)] +pub(in crate::kem::kyber) fn compute_vector_u( + a_as_ntt: &[[PolynomialRingElement; K]; K], + r_as_ntt: &[PolynomialRingElement; K], + error_1: &[PolynomialRingElement; K], +) -> [PolynomialRingElement; K] { + let mut result = [PolynomialRingElement::ZERO; K]; + + cloop! { + for (i, row) in a_as_ntt.iter().enumerate() { + cloop! { + for (j, a_element) in row.iter().enumerate() { + let product = ntt_multiply(a_element, &r_as_ntt[j]); + result[i] = add_to_ring_element::(result[i], &product); + } + } + + result[i] = invert_ntt_montgomery::(result[i]); + + for j in 0..COEFFICIENTS_IN_RING_ELEMENT { + let coefficient_normal_form = montgomery_reduce(result[i].coefficients[j] * 1441); + + result[i].coefficients[j] = + barrett_reduce(coefficient_normal_form + error_1[i].coefficients[j]); + } + } + } + + result +} + +/// Compute  ◦ ŝ + ê +#[inline(always)] +#[allow(non_snake_case)] +pub(in crate::kem::kyber) fn compute_As_plus_e( + matrix_A: &[[PolynomialRingElement; K]; K], + s_as_ntt: &[PolynomialRingElement; K], + error_as_ntt: &[PolynomialRingElement; K], +) -> [PolynomialRingElement; K] { + let mut result = [PolynomialRingElement::ZERO; K]; + + cloop! { + for (i, row) in matrix_A.iter().enumerate() { + cloop! { + for (j, matrix_element) in row.iter().enumerate() { + let product = ntt_multiply(matrix_element, &s_as_ntt[j]); + result[i] = add_to_ring_element::(result[i], &product); + } + } + + for j in 0..COEFFICIENTS_IN_RING_ELEMENT { + // The coefficients are of the form aR^{-1} mod q, which means + // calling to_montgomery_domain() on them should return a mod q. + let coefficient_normal_form = to_standard_domain(result[i].coefficients[j]); + + result[i].coefficients[j] = + barrett_reduce(coefficient_normal_form + error_as_ntt[i].coefficients[j]) + } + } + } + + result +} diff --git a/libcrux-ml-kem/src/kem/kyber/ntt.rs b/libcrux-ml-kem/src/kem/kyber/ntt.rs new file mode 100644 index 00000000..85d819e4 --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/ntt.rs @@ -0,0 +1,339 @@ +use crate::hax_utils::hax_debug_assert; + +use super::{ + arithmetic::{ + barrett_reduce, montgomery_multiply_fe_by_fer, montgomery_reduce, FieldElement, + FieldElementTimesMontgomeryR, MontgomeryFieldElement, PolynomialRingElement, + }, + constants::{COEFFICIENTS_IN_RING_ELEMENT, FIELD_MODULUS}, +}; + +const ZETAS_TIMES_MONTGOMERY_R: [FieldElementTimesMontgomeryR; 128] = [ + -1044, -758, -359, -1517, 1493, 1422, 287, 202, -171, 622, 1577, 182, 962, -1202, -1474, 1468, + 573, -1325, 264, 383, -829, 1458, -1602, -130, -681, 1017, 732, 608, -1542, 411, -205, -1571, + 1223, 652, -552, 1015, -1293, 1491, -282, -1544, 516, -8, -320, -666, -1618, -1162, 126, 1469, + -853, -90, -271, 830, 107, -1421, -247, -951, -398, 961, -1508, -725, 448, -1065, 677, -1275, + -1103, 430, 555, 843, -1251, 871, 1550, 105, 422, 587, 177, -235, -291, -460, 1574, 1653, -246, + 778, 1159, -147, -777, 1483, -602, 1119, -1590, 644, -872, 349, 418, 329, -156, -75, 817, 1097, + 603, 610, 1322, -1285, -1465, 384, -1215, -136, 1218, -1335, -874, 220, -1187, -1659, -1185, + -1530, -1278, 794, -1510, -854, -870, 478, -108, -308, 996, 991, 958, -1460, 1522, 1628, +]; + +/// Represents an intermediate polynomial splitting step in the NTT. All +/// resulting coefficients are in the normal domain since the zetas have been +/// multiplied by MONTGOMERY_R. +#[inline(always)] +fn ntt_at_layer( + zeta_i: &mut usize, + mut re: PolynomialRingElement, + layer: usize, + _initial_coefficient_bound: usize, +) -> PolynomialRingElement { + let step = 1 << layer; + + for round in 0..(128 >> layer) { + *zeta_i += 1; + + let offset = round * step * 2; + + for j in offset..offset + step { + let t = montgomery_multiply_fe_by_fer( + re.coefficients[j + step], + ZETAS_TIMES_MONTGOMERY_R[*zeta_i], + ); + re.coefficients[j + step] = re.coefficients[j] - t; + re.coefficients[j] = re.coefficients[j] + t; + } + } + + hax_debug_assert!(re.coefficients.into_iter().all(|coefficient| { + coefficient.abs() + < _initial_coefficient_bound as i32 + ((8 - layer as i32) * ((3 * FIELD_MODULUS) / 2)) + })); + + re +} + +/// See [`ntt_at_layer`]. +#[inline(always)] +fn ntt_at_layer_3( + zeta_i: &mut usize, + re: PolynomialRingElement, + layer: usize, +) -> PolynomialRingElement { + ntt_at_layer(zeta_i, re, layer, 3) +} + +/// See [`ntt_at_layer`]. +#[inline(always)] +fn ntt_at_layer_3328( + zeta_i: &mut usize, + re: PolynomialRingElement, + layer: usize, +) -> PolynomialRingElement { + ntt_at_layer(zeta_i, re, layer, 3328) +} + +/// Use the Cooley–Tukey butterfly to compute an in-place NTT representation +/// of a `KyberPolynomialRingElement`. +/// +/// This function operates only on those which were produced by binomial +/// sampling, and thus those which have small coefficients. The small +/// coefficients let us skip the first round of Montgomery reductions. +#[cfg_attr(hax, hax_lib_macros::requires( + hax_lib::forall(|i:usize| + hax_lib::implies(i < re.coefficients.len(), || re.coefficients[i].abs() <= 3 +))))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::forall(|i:usize| + hax_lib::implies(i < result.coefficients.len(), || + result.coefficients[i].abs() < FIELD_MODULUS +))))] +#[inline(always)] +pub(in crate::kem::kyber) fn ntt_binomially_sampled_ring_element( + mut re: PolynomialRingElement, +) -> PolynomialRingElement { + hax_debug_assert!(re + .coefficients + .into_iter() + .all(|coefficient| coefficient.abs() <= 3)); + + // Due to the small coefficient bound, we can skip the first round of + // Montgomery reductions. + let mut zeta_i = 1; + + for j in 0..128 { + // Multiply by the appropriate zeta in the normal domain. + let t = re.coefficients[j + 128] * -1600; + + re.coefficients[j + 128] = re.coefficients[j] - t; + re.coefficients[j] = re.coefficients[j] + t; + } + + hax_debug_assert!(re + .coefficients + .into_iter() + .all(|coefficient| { coefficient.abs() < 3 + ((3 * FIELD_MODULUS) / 2) })); + + re = ntt_at_layer_3(&mut zeta_i, re, 6); + re = ntt_at_layer_3(&mut zeta_i, re, 5); + re = ntt_at_layer_3(&mut zeta_i, re, 4); + re = ntt_at_layer_3(&mut zeta_i, re, 3); + re = ntt_at_layer_3(&mut zeta_i, re, 2); + re = ntt_at_layer_3(&mut zeta_i, re, 1); + + for i in 0..COEFFICIENTS_IN_RING_ELEMENT { + re.coefficients[i] = barrett_reduce(re.coefficients[i]); + } + + re +} + +/// Use the Cooley–Tukey butterfly to compute an in-place NTT representation +/// of a `KyberPolynomialRingElement`. +/// +/// This function operates on the ring element that partly constitutes +/// the ciphertext. +#[cfg_attr(hax, hax_lib_macros::requires( + hax_lib::forall(|i:usize| + hax_lib::implies(i < re.coefficients.len(), || re.coefficients[i].abs() <= 3328 +))))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::forall(|i:usize| + hax_lib::implies(i < result.coefficients.len(), || + result.coefficients[i].abs() < FIELD_MODULUS +))))] +#[inline(always)] +pub(in crate::kem::kyber) fn ntt_vector_u( + mut re: PolynomialRingElement, +) -> PolynomialRingElement { + hax_debug_assert!(re + .coefficients + .into_iter() + .all(|coefficient| coefficient.abs() <= 3328)); + + let mut zeta_i = 0; + + re = ntt_at_layer_3328(&mut zeta_i, re, 7); + re = ntt_at_layer_3328(&mut zeta_i, re, 6); + re = ntt_at_layer_3328(&mut zeta_i, re, 5); + re = ntt_at_layer_3328(&mut zeta_i, re, 4); + re = ntt_at_layer_3328(&mut zeta_i, re, 3); + re = ntt_at_layer_3328(&mut zeta_i, re, 2); + re = ntt_at_layer_3328(&mut zeta_i, re, 1); + + for i in 0..COEFFICIENTS_IN_RING_ELEMENT { + re.coefficients[i] = barrett_reduce(re.coefficients[i]); + } + + re +} + +#[inline(always)] +fn invert_ntt_at_layer( + zeta_i: &mut usize, + mut re: PolynomialRingElement, + layer: usize, +) -> PolynomialRingElement { + let step = 1 << layer; + + for round in 0..(128 >> layer) { + *zeta_i -= 1; + + let offset = round * step * 2; + + for j in offset..offset + step { + let a_minus_b = re.coefficients[j + step] - re.coefficients[j]; + + // Instead of dividing by 2 here, we just divide by + // 2^7 in one go in the end. + re.coefficients[j] = re.coefficients[j] + re.coefficients[j + step]; + re.coefficients[j + step] = + montgomery_reduce(a_minus_b * ZETAS_TIMES_MONTGOMERY_R[*zeta_i]); + } + } + + re +} + +/// Use the Gentleman-Sande butterfly to invert, in-place, the NTT representation +/// of a `KyberPolynomialRingElement`. The coefficients of the output +/// ring element are in the Montgomery domain. +#[inline(always)] +pub(crate) fn invert_ntt_montgomery( + mut re: PolynomialRingElement, +) -> PolynomialRingElement { + // We only ever call this function after matrix/vector multiplication + hax_debug_assert!(re + .coefficients + .into_iter() + .all(|coefficient| coefficient.abs() < (K as i32) * FIELD_MODULUS)); + + let mut zeta_i = COEFFICIENTS_IN_RING_ELEMENT / 2; + + re = invert_ntt_at_layer(&mut zeta_i, re, 1); + re = invert_ntt_at_layer(&mut zeta_i, re, 2); + re = invert_ntt_at_layer(&mut zeta_i, re, 3); + re = invert_ntt_at_layer(&mut zeta_i, re, 4); + re = invert_ntt_at_layer(&mut zeta_i, re, 5); + re = invert_ntt_at_layer(&mut zeta_i, re, 6); + re = invert_ntt_at_layer(&mut zeta_i, re, 7); + + hax_debug_assert!( + re.coefficients[0].abs() < 128 * (K as i32) * FIELD_MODULUS + && re.coefficients[1].abs() < 128 * (K as i32) * FIELD_MODULUS + ); + hax_debug_assert!(re + .coefficients + .into_iter() + .enumerate() + .skip(2) + .all(|(i, coefficient)| coefficient.abs() < (128 / (1 << i.ilog2())) * FIELD_MODULUS)); + + for i in 0..2 { + re.coefficients[i] = barrett_reduce(re.coefficients[i]); + } + re +} + +/// Compute the product of two Kyber binomials with respect to the +/// modulus `X² - zeta`. +/// +/// This function almost implements Algorithm 11 of the +/// NIST FIPS 203 standard, which is reproduced below: +/// +/// ```plaintext +/// Input: a₀, a₁, b₀, b₁ ∈ ℤq. +/// Input: γ ∈ ℤq. +/// Output: c₀, c₁ ∈ ℤq. +/// +/// c₀ ← a₀·b₀ + a₁·b₁·γ +/// c₁ ← a₀·b₁ + a₁·b₀ +/// return c₀, c₁ +/// ``` +/// We say "almost" because the coefficients output by this function are in +/// the Montgomery domain (unlike in the specification). +/// +/// The NIST FIPS 203 standard can be found at +/// . +#[inline(always)] +fn ntt_multiply_binomials( + (a0, a1): (FieldElement, FieldElement), + (b0, b1): (FieldElement, FieldElement), + zeta: FieldElementTimesMontgomeryR, +) -> (MontgomeryFieldElement, MontgomeryFieldElement) { + ( + montgomery_reduce(a0 * b0 + montgomery_reduce(a1 * b1) * zeta), + montgomery_reduce(a0 * b1 + a1 * b0), + ) +} + +/// Given two `KyberPolynomialRingElement`s in their NTT representations, +/// compute their product. Given two polynomials in the NTT domain `f^` and `ĵ`, +/// the `iᵗʰ` coefficient of the product `k̂` is determined by the calculation: +/// +/// ```plaintext +/// ĥ[2·i] + ĥ[2·i + 1]X = (f^[2·i] + f^[2·i + 1]X)·(ĝ[2·i] + ĝ[2·i + 1]X) mod (X² - ζ^(2·BitRev₇(i) + 1)) +/// ``` +/// +/// This function almost implements Algorithm 10 of the +/// NIST FIPS 203 standard, which is reproduced below: +/// +/// ```plaintext +/// Input: Two arrays fˆ ∈ ℤ₂₅₆ and ĝ ∈ ℤ₂₅₆. +/// Output: An array ĥ ∈ ℤq. +/// +/// for(i ← 0; i < 128; i++) +/// (ĥ[2i], ĥ[2i+1]) ← BaseCaseMultiply(fˆ[2i], fˆ[2i+1], ĝ[2i], ĝ[2i+1], ζ^(2·BitRev₇(i) + 1)) +/// end for +/// return ĥ +/// ``` +/// We say "almost" because the coefficients of the ring element output by +/// this function are in the Montgomery domain. +/// +/// The NIST FIPS 203 standard can be found at +/// . +#[cfg_attr(hax, hax_lib_macros::requires( + hax_lib::forall(|i:usize| + hax_lib::implies(i < COEFFICIENTS_IN_RING_ELEMENT, || + (lhs.coefficients[i] >= 0 && lhs.coefficients[i] < 4096) && + (rhs.coefficients[i].abs() <= FIELD_MODULUS) + +))))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::forall(|i:usize| + hax_lib::implies(i < result.coefficients.len(), || + result.coefficients[i].abs() <= FIELD_MODULUS +))))] +#[inline(always)] +pub(crate) fn ntt_multiply( + lhs: &PolynomialRingElement, + rhs: &PolynomialRingElement, +) -> PolynomialRingElement { + hax_debug_assert!(lhs + .coefficients + .into_iter() + .all(|coefficient| coefficient >= 0 && coefficient < 4096)); + + let mut out = PolynomialRingElement::ZERO; + + for i in 0..(COEFFICIENTS_IN_RING_ELEMENT / 4) { + let product = ntt_multiply_binomials( + (lhs.coefficients[4 * i], lhs.coefficients[4 * i + 1]), + (rhs.coefficients[4 * i], rhs.coefficients[4 * i + 1]), + ZETAS_TIMES_MONTGOMERY_R[64 + i], + ); + out.coefficients[4 * i] = product.0; + out.coefficients[4 * i + 1] = product.1; + + let product = ntt_multiply_binomials( + (lhs.coefficients[4 * i + 2], lhs.coefficients[4 * i + 3]), + (rhs.coefficients[4 * i + 2], rhs.coefficients[4 * i + 3]), + -ZETAS_TIMES_MONTGOMERY_R[64 + i], + ); + out.coefficients[4 * i + 2] = product.0; + out.coefficients[4 * i + 3] = product.1; + } + + out +} diff --git a/libcrux-ml-kem/src/kem/kyber/sampling.rs b/libcrux-ml-kem/src/kem/kyber/sampling.rs new file mode 100644 index 00000000..f4d1fbfc --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/sampling.rs @@ -0,0 +1,240 @@ +use super::{ + arithmetic::{FieldElement, PolynomialRingElement}, + constants::{COEFFICIENTS_IN_RING_ELEMENT, FIELD_MODULUS}, + hash_functions::*, +}; +use crate::cloop; +use crate::hax_utils::hax_debug_assert; + +/// If `bytes` contains a set of uniformly random bytes, this function +/// uniformly samples a ring element `â` that is treated as being the NTT representation +/// of the corresponding polynomial `a`. +/// +/// Since rejection sampling is used, it is possible the supplied bytes are +/// not enough to sample the element, in which case an `Err` is returned and the +/// caller must try again with a fresh set of bytes. +/// +/// This function partially implements Algorithm 6 of the NIST FIPS 203 standard, +/// We say "partially" because this implementation only accepts a finite set of +/// bytes as input and returns an error if the set is not enough; Algorithm 6 of +/// the FIPS 203 standard on the other hand samples from an infinite stream of bytes +/// until the ring element is filled. Algorithm 6 is reproduced below: +/// +/// ```plaintext +/// Input: byte stream B ∈ 𝔹*. +/// Output: array â ∈ ℤ₂₅₆. +/// +/// i ← 0 +/// j ← 0 +/// while j < 256 do +/// d₁ ← B[i] + 256·(B[i+1] mod 16) +/// d₂ ← ⌊B[i+1]/16⌋ + 16·B[i+2] +/// if d₁ < q then +/// â[j] ← d₁ +/// j ← j + 1 +/// end if +/// if d₂ < q and j < 256 then +/// â[j] ← d₂ +/// j ← j + 1 +/// end if +/// i ← i + 3 +/// end while +/// return â +/// ``` +/// +/// The NIST FIPS 203 standard can be found at +/// . +fn sample_from_uniform_distribution_next( + randomness: [[u8; N]; K], + sampled_coefficients: &mut [usize; K], + out: &mut [PolynomialRingElement; K], +) -> bool { + let mut done = true; + for i in 0..K { + for bytes in randomness[i].chunks(3) { + let b1 = bytes[0] as i32; + let b2 = bytes[1] as i32; + let b3 = bytes[2] as i32; + + let d1 = ((b2 & 0xF) << 8) | b1; + let d2 = (b3 << 4) | (b2 >> 4); + + if d1 < FIELD_MODULUS && sampled_coefficients[i] < COEFFICIENTS_IN_RING_ELEMENT { + out[i].coefficients[sampled_coefficients[i]] = d1; + sampled_coefficients[i] += 1 + } + if d2 < FIELD_MODULUS && sampled_coefficients[i] < COEFFICIENTS_IN_RING_ELEMENT { + out[i].coefficients[sampled_coefficients[i]] = d2; + sampled_coefficients[i] += 1; + } + } + if sampled_coefficients[i] < COEFFICIENTS_IN_RING_ELEMENT { + done = false + } + } + done +} + +pub(super) fn sample_from_xof(seeds: [[u8; 34]; K]) -> [PolynomialRingElement; K] { + let mut sampled_coefficients: [usize; K] = [0; K]; + let mut out: [PolynomialRingElement; K] = [PolynomialRingElement::ZERO; K]; + + let mut xof_state = absorb(seeds); + let randomness = squeeze_three_blocks(&mut xof_state); + + let mut done = + sample_from_uniform_distribution_next(randomness, &mut sampled_coefficients, &mut out); + + // Requiring more than 5 blocks to sample a ring element should be very + // unlikely according to: + // https://eprint.iacr.org/2023/708.pdf + // To avoid failing here, we squeeze more blocks out of the state until + // we have enough. + while !done { + let randomness = squeeze_block(&mut xof_state); + done = + sample_from_uniform_distribution_next(randomness, &mut sampled_coefficients, &mut out); + } + // XXX: We have to manually free the state here due to a Eurydice issue. + free_state(xof_state); + + out +} + +/// Given a series of uniformly random bytes in `randomness`, for some number `eta`, +/// the `sample_from_binomial_distribution_{eta}` functions sample +/// a ring element from a binomial distribution centered at 0 that uses two sets +/// of `eta` coin flips. If, for example, +/// `eta = ETA`, each ring coefficient is a value `v` such +/// such that `v ∈ {-ETA, -ETA + 1, ..., 0, ..., ETA + 1, ETA}` and: +/// +/// ```plaintext +/// - If v < 0, Pr[v] = Pr[-v] +/// - If v >= 0, Pr[v] = BINOMIAL_COEFFICIENT(2 * ETA; ETA - v) / 2 ^ (2 * ETA) +/// ``` +/// +/// The values `v < 0` are mapped to the appropriate `KyberFieldElement`. +/// +/// The expected value is: +/// +/// ```plaintext +/// E[X] = (-ETA)Pr[-ETA] + (-(ETA - 1))Pr[-(ETA - 1)] + ... + (ETA - 1)Pr[ETA - 1] + (ETA)Pr[ETA] +/// = 0 since Pr[-v] = Pr[v] when v < 0. +/// ``` +/// +/// And the variance is: +/// +/// ```plaintext +/// Var(X) = E[(X - E[X])^2] +/// = E[X^2] +/// = sum_(v=-ETA to ETA)v^2 * (BINOMIAL_COEFFICIENT(2 * ETA; ETA - v) / 2^(2 * ETA)) +/// = ETA / 2 +/// ``` +/// +/// This function implements Algorithm 7 of the NIST FIPS 203 standard, which is +/// reproduced below: +/// +/// ```plaintext +/// Input: byte array B ∈ 𝔹^{64η}. +/// Output: array f ∈ ℤ₂₅₆. +/// +/// b ← BytesToBits(B) +/// for (i ← 0; i < 256; i++) +/// x ← ∑(j=0 to η - 1) b[2iη + j] +/// y ← ∑(j=0 to η - 1) b[2iη + η + j] +/// f[i] ← x−y mod q +/// end for +/// return f +/// ``` +/// +/// The NIST FIPS 203 standard can be found at +/// . +#[cfg_attr(hax, hax_lib_macros::requires(randomness.len() == 2 * 64))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::forall(|i:usize| + hax_lib::implies(i < result.coefficients.len(), || result.coefficients[i].abs() <= 2 +))))] +fn sample_from_binomial_distribution_2(randomness: &[u8]) -> PolynomialRingElement { + let mut sampled: PolynomialRingElement = PolynomialRingElement::ZERO; + + cloop! { + for (chunk_number, byte_chunk) in randomness.chunks_exact(4).enumerate() { + let random_bits_as_u32: u32 = (byte_chunk[0] as u32) + | (byte_chunk[1] as u32) << 8 + | (byte_chunk[2] as u32) << 16 + | (byte_chunk[3] as u32) << 24; + + let even_bits = random_bits_as_u32 & 0x55555555; + let odd_bits = (random_bits_as_u32 >> 1) & 0x55555555; + + let coin_toss_outcomes = even_bits + odd_bits; + + cloop! { + for outcome_set in (0..u32::BITS).step_by(4) { + let outcome_1 = ((coin_toss_outcomes >> outcome_set) & 0x3) as FieldElement; + let outcome_2 = ((coin_toss_outcomes >> (outcome_set + 2)) & 0x3) as FieldElement; + + let offset = (outcome_set >> 2) as usize; + sampled.coefficients[8 * chunk_number + offset] = outcome_1 - outcome_2; + } + } + } + } + + hax_debug_assert!(sampled + .coefficients + .into_iter() + .all(|coefficient| coefficient >= -2 && coefficient <= 2)); + sampled +} + +#[cfg_attr(hax, hax_lib_macros::requires(randomness.len() == 3 * 64))] +#[cfg_attr(hax, hax_lib_macros::ensures(|result| + hax_lib::forall(|i:usize| + hax_lib::implies(i < result.coefficients.len(), || result.coefficients[i].abs() <= 3 +))))] +fn sample_from_binomial_distribution_3(randomness: &[u8]) -> PolynomialRingElement { + let mut sampled: PolynomialRingElement = PolynomialRingElement::ZERO; + + cloop! { + for (chunk_number, byte_chunk) in randomness.chunks_exact(3).enumerate() { + let random_bits_as_u24: u32 = + (byte_chunk[0] as u32) | (byte_chunk[1] as u32) << 8 | (byte_chunk[2] as u32) << 16; + + let first_bits = random_bits_as_u24 & 0x00249249; + let second_bits = (random_bits_as_u24 >> 1) & 0x00249249; + let third_bits = (random_bits_as_u24 >> 2) & 0x00249249; + + let coin_toss_outcomes = first_bits + second_bits + third_bits; + + cloop! { + for outcome_set in (0..24).step_by(6) { + let outcome_1 = ((coin_toss_outcomes >> outcome_set) & 0x7) as FieldElement; + let outcome_2 = ((coin_toss_outcomes >> (outcome_set + 3)) & 0x7) as FieldElement; + + let offset = (outcome_set / 6) as usize; + sampled.coefficients[4 * chunk_number + offset] = outcome_1 - outcome_2; + } + } + } + } + + hax_debug_assert!(sampled + .coefficients + .into_iter() + .all(|coefficient| coefficient >= -3 && coefficient <= 3)); + sampled +} + +#[inline(always)] +pub(super) fn sample_from_binomial_distribution( + randomness: &[u8], +) -> PolynomialRingElement { + hax_debug_assert!(randomness.len() == ETA * 64); + + match ETA as u32 { + 2 => sample_from_binomial_distribution_2(randomness), + 3 => sample_from_binomial_distribution_3(randomness), + _ => unreachable!(), + } +} diff --git a/libcrux-ml-kem/src/kem/kyber/serialize.rs b/libcrux-ml-kem/src/kem/kyber/serialize.rs new file mode 100644 index 00000000..c31d893d --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/serialize.rs @@ -0,0 +1,626 @@ +use super::{ + arithmetic::{to_unsigned_representative, FieldElement, PolynomialRingElement}, + compress::{ + compress_ciphertext_coefficient, compress_message_coefficient, + decompress_ciphertext_coefficient, decompress_message_coefficient, + }, + constants::{BYTES_PER_RING_ELEMENT, SHARED_SECRET_SIZE}, +}; +use crate::cloop; +use crate::hax_utils::hax_debug_assert; + +#[cfg(not(hax))] +use super::constants::COEFFICIENTS_IN_RING_ELEMENT; + +#[inline(always)] +pub(super) fn compress_then_serialize_message( + re: PolynomialRingElement, +) -> [u8; SHARED_SECRET_SIZE] { + let mut serialized = [0u8; SHARED_SECRET_SIZE]; + + cloop! { + for (i, coefficients) in re.coefficients.chunks_exact(8).enumerate() { + cloop! { + for (j, coefficient) in coefficients.iter().enumerate() { + let coefficient = to_unsigned_representative(*coefficient); + + let coefficient_compressed = compress_message_coefficient(coefficient); + + serialized[i] |= coefficient_compressed << j + } + } + } + } + + serialized +} +#[inline(always)] +pub(super) fn deserialize_then_decompress_message( + serialized: [u8; SHARED_SECRET_SIZE], +) -> PolynomialRingElement { + let mut re = PolynomialRingElement::ZERO; + + cloop! { + for (i, byte) in serialized.into_iter().enumerate() { + for j in 0..8 { + let coefficient_compressed = ((byte >> j) & 0x1) as FieldElement; + re.coefficients[8 * i + j] = decompress_message_coefficient(coefficient_compressed); + } + } + } + + re +} + +#[inline(always)] +pub(super) fn serialize_uncompressed_ring_element( + re: PolynomialRingElement, +) -> [u8; BYTES_PER_RING_ELEMENT] { + let mut serialized = [0u8; BYTES_PER_RING_ELEMENT]; + + cloop! { + for (i, coefficients) in re.coefficients.chunks_exact(2).enumerate() { + let coefficient1 = to_unsigned_representative(coefficients[0]); + let coefficient2 = to_unsigned_representative(coefficients[1]); + + let (coef1, coef2, coef3) = compress_coefficients_3(coefficient1, coefficient2); + serialized[3 * i] = coef1; + serialized[3 * i + 1] = coef2; + serialized[3 * i + 2] = coef3; + } + } + + serialized +} + +#[inline(always)] +fn compress_coefficients_3(coefficient1: u16, coefficient2: u16) -> (u8, u8, u8) { + let coef1 = (coefficient1 & 0xFF) as u8; + let coef2 = ((coefficient1 >> 8) | ((coefficient2 & 0x0F) << 4)) as u8; + let coef3 = ((coefficient2 >> 4) & 0xFF) as u8; + (coef1, coef2, coef3) +} + +#[inline(always)] +pub(super) fn deserialize_to_uncompressed_ring_element(serialized: &[u8]) -> PolynomialRingElement { + hax_debug_assert!(serialized.len() == BYTES_PER_RING_ELEMENT); + + let mut re = PolynomialRingElement::ZERO; + + cloop! { + for (i, bytes) in serialized.chunks_exact(3).enumerate() { + let byte1 = bytes[0] as FieldElement; + let byte2 = bytes[1] as FieldElement; + let byte3 = bytes[2] as FieldElement; + + re.coefficients[2 * i] = (byte2 & 0x0F) << 8 | (byte1 & 0xFF); + re.coefficients[2 * i + 1] = (byte3 << 4) | ((byte2 >> 4) & 0x0F); + } + } + + re +} + +/// Only use with public values. +/// +/// This MUST NOT be used with secret inputs, like its caller `deserialize_ring_elements_reduced`. +#[inline(always)] +fn deserialize_to_reduced_ring_element(ring_element: &[u8]) -> PolynomialRingElement { + hax_debug_assert!(ring_element.len() == BYTES_PER_RING_ELEMENT); + + let mut re = PolynomialRingElement::ZERO; + + cloop! { + for (i, bytes) in ring_element.chunks_exact(3).enumerate() { + let byte1 = bytes[0] as FieldElement; + let byte2 = bytes[1] as FieldElement; + let byte3 = bytes[2] as FieldElement; + + // The modulus here is ok because the input must be public. + // XXX: The awkward code here is necessary to work around Charon shortcomings. + re.coefficients[2 * i] = (byte2 & 0x0F) << 8 | (byte1 & 0xFF); + let tmp = re.coefficients[2 * i] % 3329; // FIELD_MODULUS + re.coefficients[2 * i] = tmp; + + re.coefficients[2 * i + 1] = (byte3 << 4) | ((byte2 >> 4) & 0x0F); + let tmp = re.coefficients[2 * i + 1] % 3329; // FIELD_MODULUS + re.coefficients[2 * i + 1] = tmp; + } + } + + re +} + +/// This function deserializes ring elements and reduces the result by the field +/// modulus. +/// +/// This function MUST NOT be used on secret inputs. +#[inline(always)] +pub(super) fn deserialize_ring_elements_reduced( + public_key: &[u8], +) -> [PolynomialRingElement; K] { + let mut deserialized_pk = [PolynomialRingElement::ZERO; K]; + cloop! { + for (i, ring_element) in public_key + .chunks_exact(BYTES_PER_RING_ELEMENT) + .enumerate() + { + deserialized_pk[i] =deserialize_to_reduced_ring_element(ring_element); + } + } + deserialized_pk +} + +#[inline(always)] +fn compress_then_serialize_10(re: PolynomialRingElement) -> [u8; OUT_LEN] { + let mut serialized = [0u8; OUT_LEN]; + + cloop! { + for (i, coefficients) in re.coefficients.chunks_exact(4).enumerate() { + let coefficient1 = + compress_ciphertext_coefficient(10, to_unsigned_representative(coefficients[0])); + let coefficient2 = + compress_ciphertext_coefficient(10, to_unsigned_representative(coefficients[1])); + let coefficient3 = + compress_ciphertext_coefficient(10, to_unsigned_representative(coefficients[2])); + let coefficient4 = + compress_ciphertext_coefficient(10, to_unsigned_representative(coefficients[3])); + + let (coef1, coef2, coef3, coef4, coef5) = + compress_coefficients_10(coefficient1, coefficient2, coefficient3, coefficient4); + serialized[5 * i] = coef1; + serialized[5 * i + 1] = coef2; + serialized[5 * i + 2] = coef3; + serialized[5 * i + 3] = coef4; + serialized[5 * i + 4] = coef5; + } + } + + serialized +} + +#[inline(always)] +fn compress_coefficients_10( + coefficient1: i32, + coefficient2: i32, + coefficient3: i32, + coefficient4: i32, +) -> (u8, u8, u8, u8, u8) { + let coef1 = (coefficient1 & 0xFF) as u8; + let coef2 = ((coefficient2 & 0x3F) as u8) << 2 | ((coefficient1 >> 8) & 0x03) as u8; + let coef3 = ((coefficient3 & 0x0F) as u8) << 4 | ((coefficient2 >> 6) & 0x0F) as u8; + let coef4 = ((coefficient4 & 0x03) as u8) << 6 | ((coefficient3 >> 4) & 0x3F) as u8; + let coef5 = ((coefficient4 >> 2) & 0xFF) as u8; + (coef1, coef2, coef3, coef4, coef5) +} + +#[inline(always)] +fn compress_then_serialize_11(re: PolynomialRingElement) -> [u8; OUT_LEN] { + let mut serialized = [0u8; OUT_LEN]; + + cloop! { + for (i, coefficients) in re.coefficients.chunks_exact(8).enumerate() { + let coefficient1 = + compress_ciphertext_coefficient(11, to_unsigned_representative(coefficients[0])); + let coefficient2 = + compress_ciphertext_coefficient(11, to_unsigned_representative(coefficients[1])); + let coefficient3 = + compress_ciphertext_coefficient(11, to_unsigned_representative(coefficients[2])); + let coefficient4 = + compress_ciphertext_coefficient(11, to_unsigned_representative(coefficients[3])); + let coefficient5 = + compress_ciphertext_coefficient(11, to_unsigned_representative(coefficients[4])); + let coefficient6 = + compress_ciphertext_coefficient(11, to_unsigned_representative(coefficients[5])); + let coefficient7 = + compress_ciphertext_coefficient(11, to_unsigned_representative(coefficients[6])); + let coefficient8 = + compress_ciphertext_coefficient(11, to_unsigned_representative(coefficients[7])); + + let (coef1, coef2, coef3, coef4, coef5, coef6, coef7, coef8, coef9, coef10, coef11) = + compress_coefficients_11( + coefficient1, + coefficient2, + coefficient3, + coefficient4, + coefficient5, + coefficient6, + coefficient7, + coefficient8, + ); + serialized[11 * i] = coef1; + serialized[11 * i + 1] = coef2; + serialized[11 * i + 2] = coef3; + serialized[11 * i + 3] = coef4; + serialized[11 * i + 4] = coef5; + serialized[11 * i + 5] = coef6; + serialized[11 * i + 6] = coef7; + serialized[11 * i + 7] = coef8; + serialized[11 * i + 8] = coef9; + serialized[11 * i + 9] = coef10; + serialized[11 * i + 10] = coef11; + } + } + + serialized +} + +#[inline(always)] +fn compress_coefficients_11( + coefficient1: i32, + coefficient2: i32, + coefficient3: i32, + coefficient4: i32, + coefficient5: i32, + coefficient6: i32, + coefficient7: i32, + coefficient8: i32, +) -> (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) { + let coef1 = coefficient1 as u8; + let coef2 = ((coefficient2 & 0x1F) as u8) << 3 | ((coefficient1 >> 8) as u8); + let coef3 = ((coefficient3 & 0x3) as u8) << 6 | ((coefficient2 >> 5) as u8); + let coef4 = ((coefficient3 >> 2) & 0xFF) as u8; + let coef5 = ((coefficient4 & 0x7F) as u8) << 1 | (coefficient3 >> 10) as u8; + let coef6 = ((coefficient5 & 0xF) as u8) << 4 | (coefficient4 >> 7) as u8; + let coef7 = ((coefficient6 & 0x1) as u8) << 7 | (coefficient5 >> 4) as u8; + let coef8 = ((coefficient6 >> 1) & 0xFF) as u8; + let coef9 = ((coefficient7 & 0x3F) as u8) << 2 | (coefficient6 >> 9) as u8; + let coef10 = ((coefficient8 & 0x7) as u8) << 5 | (coefficient7 >> 6) as u8; + let coef11 = (coefficient8 >> 3) as u8; + ( + coef1, coef2, coef3, coef4, coef5, coef6, coef7, coef8, coef9, coef10, coef11, + ) +} +#[inline(always)] +pub(super) fn compress_then_serialize_ring_element_u< + const COMPRESSION_FACTOR: usize, + const OUT_LEN: usize, +>( + re: PolynomialRingElement, +) -> [u8; OUT_LEN] { + hax_debug_assert!((COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8 == OUT_LEN); + + match COMPRESSION_FACTOR as u32 { + 10 => compress_then_serialize_10(re), + 11 => compress_then_serialize_11(re), + _ => unreachable!(), + } +} + +#[inline(always)] +fn compress_then_serialize_4(re: PolynomialRingElement) -> [u8; OUT_LEN] { + let mut serialized = [0u8; OUT_LEN]; + + cloop! { + for (i, coefficients) in re.coefficients.chunks_exact(2).enumerate() { + let coefficient1 = + compress_ciphertext_coefficient(4, to_unsigned_representative(coefficients[0])) as u8; + let coefficient2 = + compress_ciphertext_coefficient(4, to_unsigned_representative(coefficients[1])) as u8; + + serialized[i] = (coefficient2 << 4) | coefficient1; + } + } + + serialized +} + +#[inline(always)] +fn compress_then_serialize_5(re: PolynomialRingElement) -> [u8; OUT_LEN] { + let mut serialized = [0u8; OUT_LEN]; + + cloop! { + for (i, coefficients) in re.coefficients.chunks_exact(8).enumerate() { + let coefficient1 = + compress_ciphertext_coefficient(5, to_unsigned_representative(coefficients[0])) as u8; + let coefficient2 = + compress_ciphertext_coefficient(5, to_unsigned_representative(coefficients[1])) as u8; + let coefficient3 = + compress_ciphertext_coefficient(5, to_unsigned_representative(coefficients[2])) as u8; + let coefficient4 = + compress_ciphertext_coefficient(5, to_unsigned_representative(coefficients[3])) as u8; + let coefficient5 = + compress_ciphertext_coefficient(5, to_unsigned_representative(coefficients[4])) as u8; + let coefficient6 = + compress_ciphertext_coefficient(5, to_unsigned_representative(coefficients[5])) as u8; + let coefficient7 = + compress_ciphertext_coefficient(5, to_unsigned_representative(coefficients[6])) as u8; + let coefficient8 = + compress_ciphertext_coefficient(5, to_unsigned_representative(coefficients[7])) as u8; + + let (coef1, coef2, coef3, coef4, coef5) = compress_coefficients_5( + coefficient2, + coefficient1, + coefficient4, + coefficient3, + coefficient5, + coefficient7, + coefficient6, + coefficient8, + ); + serialized[5 * i] = coef1; + serialized[5 * i + 1] = coef2; + serialized[5 * i + 2] = coef3; + serialized[5 * i + 3] = coef4; + serialized[5 * i + 4] = coef5; + } + } + + serialized +} + +#[inline(always)] +fn compress_coefficients_5( + coefficient2: u8, + coefficient1: u8, + coefficient4: u8, + coefficient3: u8, + coefficient5: u8, + coefficient7: u8, + coefficient6: u8, + coefficient8: u8, +) -> (u8, u8, u8, u8, u8) { + let coef1 = (coefficient2 & 0x7) << 5 | coefficient1; + let coef2 = ((coefficient4 & 1) << 7) | (coefficient3 << 2) | (coefficient2 >> 3); + let coef3 = ((coefficient5 & 0xF) << 4) | (coefficient4 >> 1); + let coef4 = ((coefficient7 & 0x3) << 6) | (coefficient6 << 1) | (coefficient5 >> 4); + let coef5 = (coefficient8 << 3) | (coefficient7 >> 2); + (coef1, coef2, coef3, coef4, coef5) +} + +#[inline(always)] +pub(super) fn compress_then_serialize_ring_element_v< + const COMPRESSION_FACTOR: usize, + const OUT_LEN: usize, +>( + re: PolynomialRingElement, +) -> [u8; OUT_LEN] { + hax_debug_assert!((COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8 == OUT_LEN); + + match COMPRESSION_FACTOR as u32 { + 4 => compress_then_serialize_4(re), + 5 => compress_then_serialize_5(re), + _ => unreachable!(), + } +} + +#[inline(always)] +fn deserialize_then_decompress_10(serialized: &[u8]) -> PolynomialRingElement { + hax_debug_assert!(serialized.len() == (COEFFICIENTS_IN_RING_ELEMENT * 10) / 8); + + let mut re = PolynomialRingElement::ZERO; + + cloop! { + for (i, bytes) in serialized.chunks_exact(5).enumerate() { + let byte1 = bytes[0] as FieldElement; + let byte2 = bytes[1] as FieldElement; + let byte3 = bytes[2] as FieldElement; + let byte4 = bytes[3] as FieldElement; + let byte5 = bytes[4] as FieldElement; + + let (coefficient1, coefficient2, coefficient3, coefficient4) = + decompress_coefficients_10(byte2, byte1, byte3, byte4, byte5); + + re.coefficients[4 * i] = decompress_ciphertext_coefficient(10, coefficient1); + re.coefficients[4 * i + 1] = decompress_ciphertext_coefficient(10, coefficient2); + re.coefficients[4 * i + 2] = decompress_ciphertext_coefficient(10, coefficient3); + re.coefficients[4 * i + 3] = decompress_ciphertext_coefficient(10, coefficient4); + } + } + + re +} + +#[inline(always)] +fn decompress_coefficients_10( + byte2: i32, + byte1: i32, + byte3: i32, + byte4: i32, + byte5: i32, +) -> (i32, i32, i32, i32) { + let coefficient1 = (byte2 & 0x03) << 8 | (byte1 & 0xFF); + let coefficient2 = (byte3 & 0x0F) << 6 | (byte2 >> 2); + let coefficient3 = (byte4 & 0x3F) << 4 | (byte3 >> 4); + let coefficient4 = (byte5 << 2) | (byte4 >> 6); + (coefficient1, coefficient2, coefficient3, coefficient4) +} + +#[inline(always)] +fn deserialize_then_decompress_11(serialized: &[u8]) -> PolynomialRingElement { + hax_debug_assert!(serialized.len() == (COEFFICIENTS_IN_RING_ELEMENT * 11) / 8); + + let mut re = PolynomialRingElement::ZERO; + + cloop! { + for (i, bytes) in serialized.chunks_exact(11).enumerate() { + let byte1 = bytes[0] as FieldElement; + let byte2 = bytes[1] as FieldElement; + let byte3 = bytes[2] as FieldElement; + let byte4 = bytes[3] as FieldElement; + let byte5 = bytes[4] as FieldElement; + let byte6 = bytes[5] as FieldElement; + let byte7 = bytes[6] as FieldElement; + let byte8 = bytes[7] as FieldElement; + let byte9 = bytes[8] as FieldElement; + let byte10 = bytes[9] as FieldElement; + let byte11 = bytes[10] as FieldElement; + + let ( + coefficient1, + coefficient2, + coefficient3, + coefficient4, + coefficient5, + coefficient6, + coefficient7, + coefficient8, + ) = decompress_coefficients_11( + byte2, byte1, byte3, byte5, byte4, byte6, byte7, byte9, byte8, byte10, byte11, + ); + + re.coefficients[8 * i] = decompress_ciphertext_coefficient(11, coefficient1); + re.coefficients[8 * i + 1] = decompress_ciphertext_coefficient(11, coefficient2); + re.coefficients[8 * i + 2] = decompress_ciphertext_coefficient(11, coefficient3); + re.coefficients[8 * i + 3] = decompress_ciphertext_coefficient(11, coefficient4); + re.coefficients[8 * i + 4] = decompress_ciphertext_coefficient(11, coefficient5); + re.coefficients[8 * i + 5] = decompress_ciphertext_coefficient(11, coefficient6); + re.coefficients[8 * i + 6] = decompress_ciphertext_coefficient(11, coefficient7); + re.coefficients[8 * i + 7] = decompress_ciphertext_coefficient(11, coefficient8); + } + } + + re +} + +#[inline(always)] +fn decompress_coefficients_11( + byte2: i32, + byte1: i32, + byte3: i32, + byte5: i32, + byte4: i32, + byte6: i32, + byte7: i32, + byte9: i32, + byte8: i32, + byte10: i32, + byte11: i32, +) -> (i32, i32, i32, i32, i32, i32, i32, i32) { + let coefficient1 = (byte2 & 0x7) << 8 | byte1; + let coefficient2 = (byte3 & 0x3F) << 5 | (byte2 >> 3); + let coefficient3 = (byte5 & 0x1) << 10 | (byte4 << 2) | (byte3 >> 6); + let coefficient4 = (byte6 & 0xF) << 7 | (byte5 >> 1); + let coefficient5 = (byte7 & 0x7F) << 4 | (byte6 >> 4); + let coefficient6 = (byte9 & 0x3) << 9 | (byte8 << 1) | (byte7 >> 7); + let coefficient7 = (byte10 & 0x1F) << 6 | (byte9 >> 2); + let coefficient8 = (byte11 << 3) | (byte10 >> 5); + ( + coefficient1, + coefficient2, + coefficient3, + coefficient4, + coefficient5, + coefficient6, + coefficient7, + coefficient8, + ) +} + +#[inline(always)] +pub(super) fn deserialize_then_decompress_ring_element_u( + serialized: &[u8], +) -> PolynomialRingElement { + hax_debug_assert!(serialized.len() == (COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8); + + match COMPRESSION_FACTOR as u32 { + 10 => deserialize_then_decompress_10(serialized), + 11 => deserialize_then_decompress_11(serialized), + _ => unreachable!(), + } +} + +#[inline(always)] +fn deserialize_then_decompress_4(serialized: &[u8]) -> PolynomialRingElement { + hax_debug_assert!(serialized.len() == (COEFFICIENTS_IN_RING_ELEMENT * 4) / 8); + + let mut re = PolynomialRingElement::ZERO; + + cloop! { + for (i, byte) in serialized.iter().enumerate() { + let (coefficient1, coefficient2) = decompress_coefficients_4(byte); + + re.coefficients[2 * i] = decompress_ciphertext_coefficient(4, coefficient1); + re.coefficients[2 * i + 1] = decompress_ciphertext_coefficient(4, coefficient2); + } + } + + re +} + +#[inline(always)] +fn decompress_coefficients_4(byte: &u8) -> (i32, i32) { + let coefficient1 = (byte & 0x0F) as FieldElement; + let coefficient2 = ((byte >> 4) & 0x0F) as FieldElement; + (coefficient1, coefficient2) +} + +#[inline(always)] +fn deserialize_then_decompress_5(serialized: &[u8]) -> PolynomialRingElement { + hax_debug_assert!(serialized.len() == (COEFFICIENTS_IN_RING_ELEMENT * 5) / 8); + + let mut re = PolynomialRingElement::ZERO; + + cloop! { + for (i, bytes) in serialized.chunks_exact(5).enumerate() { + let byte1 = bytes[0] as FieldElement; + let byte2 = bytes[1] as FieldElement; + let byte3 = bytes[2] as FieldElement; + let byte4 = bytes[3] as FieldElement; + let byte5 = bytes[4] as FieldElement; + + let ( + coefficient1, + coefficient2, + coefficient3, + coefficient4, + coefficient5, + coefficient6, + coefficient7, + coefficient8, + ) = decompress_coefficients_5(byte1, byte2, byte3, byte4, byte5); + + re.coefficients[8 * i] = decompress_ciphertext_coefficient(5, coefficient1); + re.coefficients[8 * i + 1] = decompress_ciphertext_coefficient(5, coefficient2); + re.coefficients[8 * i + 2] = decompress_ciphertext_coefficient(5, coefficient3); + re.coefficients[8 * i + 3] = decompress_ciphertext_coefficient(5, coefficient4); + re.coefficients[8 * i + 4] = decompress_ciphertext_coefficient(5, coefficient5); + re.coefficients[8 * i + 5] = decompress_ciphertext_coefficient(5, coefficient6); + re.coefficients[8 * i + 6] = decompress_ciphertext_coefficient(5, coefficient7); + re.coefficients[8 * i + 7] = decompress_ciphertext_coefficient(5, coefficient8); + } + } + + re +} + +#[inline(always)] +fn decompress_coefficients_5( + byte1: i32, + byte2: i32, + byte3: i32, + byte4: i32, + byte5: i32, +) -> (i32, i32, i32, i32, i32, i32, i32, i32) { + let coefficient1 = byte1 & 0x1F; + let coefficient2 = (byte2 & 0x3) << 3 | (byte1 >> 5); + let coefficient3 = (byte2 >> 2) & 0x1F; + let coefficient4 = ((byte3 & 0xF) << 1) | (byte2 >> 7); + let coefficient5 = ((byte4 & 1) << 4) | (byte3 >> 4); + let coefficient6 = (byte4 >> 1) & 0x1F; + let coefficient7 = ((byte5 & 0x7) << 2) | (byte4 >> 6); + let coefficient8 = byte5 >> 3; + ( + coefficient1, + coefficient2, + coefficient3, + coefficient4, + coefficient5, + coefficient6, + coefficient7, + coefficient8, + ) +} + +#[inline(always)] +pub(super) fn deserialize_then_decompress_ring_element_v( + serialized: &[u8], +) -> PolynomialRingElement { + hax_debug_assert!(serialized.len() == (COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8); + + match COMPRESSION_FACTOR as u32 { + 4 => deserialize_then_decompress_4(serialized), + 5 => deserialize_then_decompress_5(serialized), + _ => unreachable!(), + } +} diff --git a/libcrux-ml-kem/src/kem/kyber/types.rs b/libcrux-ml-kem/src/kem/kyber/types.rs new file mode 100644 index 00000000..fda123be --- /dev/null +++ b/libcrux-ml-kem/src/kem/kyber/types.rs @@ -0,0 +1,156 @@ +macro_rules! impl_generic_struct { + ($name:ident) => { + pub struct $name { + pub(super) value: [u8; SIZE], + } + + impl AsRef<[u8]> for $name { + fn as_ref(&self) -> &[u8] { + &self.value + } + } + + impl From<[u8; SIZE]> for $name { + fn from(value: [u8; SIZE]) -> Self { + Self { value } + } + } + + impl From<&[u8; SIZE]> for $name { + fn from(value: &[u8; SIZE]) -> Self { + Self { + value: value.clone(), + } + } + } + + impl From<$name> for [u8; SIZE] { + fn from(value: $name) -> Self { + value.value + } + } + + impl TryFrom<&[u8]> for $name { + type Error = core::array::TryFromSliceError; + + fn try_from(value: &[u8]) -> Result { + match value.try_into() { + Ok(value) => Ok(Self { value }), + Err(e) => Err(e), + } + } + } + + impl $name { + pub fn as_slice(&self) -> &[u8; SIZE] { + &self.value + } + + pub fn split_at(&self, mid: usize) -> (&[u8], &[u8]) { + self.value.split_at(mid) + } + + pub const fn len(&self) -> usize { + SIZE + } + } + }; +} +macro_rules! impl_index_impls_for_generic_struct { + ($name:ident) => { + impl core::ops::Index for $name { + type Output = u8; + + fn index(&self, index: usize) -> &Self::Output { + &self.value[index] + } + } + + impl core::ops::Index> for $name { + type Output = [u8]; + + fn index(&self, range: core::ops::Range) -> &Self::Output { + &self.value[range] + } + } + + impl core::ops::Index> for $name { + type Output = [u8]; + + fn index(&self, range: core::ops::RangeTo) -> &Self::Output { + &self.value[range] + } + } + + impl core::ops::Index> for $name { + type Output = [u8]; + + fn index(&self, range: core::ops::RangeFrom) -> &Self::Output { + &self.value[range] + } + } + }; +} + +impl_generic_struct!(MlKemCiphertext); +impl_generic_struct!(MlKemPrivateKey); +impl_generic_struct!(MlKemPublicKey); + +// These traits are used only in `ind_cpa` for kyber cipher text. +mod index_impls { + use super::*; + impl_index_impls_for_generic_struct!(MlKemCiphertext); + impl_index_impls_for_generic_struct!(MlKemPrivateKey); + impl_index_impls_for_generic_struct!(MlKemPublicKey); +} + +/// An ML-KEM key pair +pub struct MlKemKeyPair { + pub(crate) sk: MlKemPrivateKey, + pub(crate) pk: MlKemPublicKey, +} + +impl + MlKemKeyPair +{ + /// Creates a new [`MlKemKeyPair`]. + pub fn new(sk: [u8; PRIVATE_KEY_SIZE], pk: [u8; PUBLIC_KEY_SIZE]) -> Self { + Self { + sk: sk.into(), + pk: pk.into(), + } + } + + pub fn from( + sk: MlKemPrivateKey, + pk: MlKemPublicKey, + ) -> Self { + Self { sk, pk } + } + + pub fn public_key(&self) -> &MlKemPublicKey { + &self.pk + } + + pub fn private_key(&self) -> &MlKemPrivateKey { + &self.sk + } + + pub fn pk(&self) -> &[u8; PUBLIC_KEY_SIZE] { + self.pk.as_slice() + } + + pub fn sk(&self) -> &[u8; PRIVATE_KEY_SIZE] { + self.sk.as_slice() + } + + #[cfg(feature = "tests")] + pub fn into_parts( + self, + ) -> ( + MlKemPrivateKey, + MlKemPublicKey, + ) { + (self.sk, self.pk) + } +} diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 2a431fdb..a2908ab6 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -64,6 +64,7 @@ mod hash_functions; mod ind_cca; mod ind_cpa; mod invert_ntt; +mod kem; mod matrix; mod ntt; mod polynomial; From 7f3e42e44df9f4f9de428dc75bbe6194a2f24d05 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 20 Jun 2024 18:53:48 +0200 Subject: [PATCH 09/53] WIP separation of verified API --- libcrux-ml-kem/Cargo.toml | 1 + libcrux-ml-kem/src/kem.rs | 33 ---------- libcrux-ml-kem/src/kem/kyber.rs | 2 +- .../src/kem/kyber/hash_functions.rs | 2 +- libcrux-ml-kem/src/lib.rs | 63 ++++++++++++++++++- libcrux-ml-kem/tests/nistkats.rs | 14 ++--- 6 files changed, 71 insertions(+), 44 deletions(-) diff --git a/libcrux-ml-kem/Cargo.toml b/libcrux-ml-kem/Cargo.toml index 5198a6e5..0cc033e6 100644 --- a/libcrux-ml-kem/Cargo.toml +++ b/libcrux-ml-kem/Cargo.toml @@ -27,6 +27,7 @@ simd256 = ["libcrux-sha3/simd256"] tests = [] # Test utilities. DO NOT USE. std = [] kyber = [] +pre-verification = [] [dev-dependencies] rand = { version = "0.8" } diff --git a/libcrux-ml-kem/src/kem.rs b/libcrux-ml-kem/src/kem.rs index 16dbfc0f..247eaed9 100644 --- a/libcrux-ml-kem/src/kem.rs +++ b/libcrux-ml-kem/src/kem.rs @@ -1,36 +1,3 @@ -//! # Key Encapsulation Mechanism -//! -//! A KEM interface. -//! -//! For ECDH structs, check the [`ecdh`] module. -//! -//! Available algorithms: -//! * [`Algorithm::X25519`]\: x25519 ECDH KEM. Also see [`ecdh#x25519`]. -//! * [`Algorithm::Secp256r1`]\: NIST P256 ECDH KEM. Also see [`ecdh#P256`]. -//! * [`Algorithm::MlKem512`]\: ML-KEM 512 from [FIPS 203]. -//! * [`Algorithm::MlKem768`]\: ML-KEM 768 from [FIPS 203]. -//! * [`Algorithm::MlKem1024`]\: ML-KEM 1024 from [FIPS 203]. -//! * [`Algorithm::X25519MlKem768Draft00`]\: Hybrid x25519 - ML-KEM 768 [draft kem for hpke](https://www.ietf.org/archive/id/draft-westerbaan-cfrg-hpke-xyber768d00-00.html). -//! * [`Algorithm::XWingKemDraft02`]\: Hybrid x25519 - ML-KEM 768 [draft xwing kem for hpke](https://www.ietf.org/archive/id/draft-connolly-cfrg-xwing-kem-02.html). -//! -//! ``` -//! use libcrux::{kem::*, drbg::Drbg, digest::Algorithm::Sha256}; -//! -//! let mut rng = Drbg::new(Sha256).unwrap(); -//! let (sk_a, pk_a) = key_gen(Algorithm::MlKem768, &mut rng).unwrap(); -//! let received_pk = pk_a.encode(); -//! -//! let pk = PublicKey::decode(Algorithm::MlKem768, &received_pk).unwrap(); -//! let (ss_b, ct_b) = pk.encapsulate(&mut rng).unwrap(); -//! let received_ct = ct_b.encode(); -//! -//! let ct_a = Ct::decode(Algorithm::MlKem768, &received_ct).unwrap(); -//! let ss_a = ct_a.decapsulate(&sk_a).unwrap(); -//! assert_eq!(ss_b.encode(), ss_a.encode()); -//! ``` -//! -//! [FIPS 203]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf - // hacspec code: don't let clippy touch it. #[allow(clippy::all)] pub mod kyber; diff --git a/libcrux-ml-kem/src/kem/kyber.rs b/libcrux-ml-kem/src/kem/kyber.rs index 89c31082..5191be4d 100644 --- a/libcrux-ml-kem/src/kem/kyber.rs +++ b/libcrux-ml-kem/src/kem/kyber.rs @@ -45,7 +45,7 @@ use self::{ }; /// Seed size for key generation -pub(in crate::kem) const KEY_GENERATION_SEED_SIZE: usize = +pub(crate) const KEY_GENERATION_SEED_SIZE: usize = CPA_PKE_KEY_GENERATION_SEED_SIZE + SHARED_SECRET_SIZE; /// Serialize the secret key. diff --git a/libcrux-ml-kem/src/kem/kyber/hash_functions.rs b/libcrux-ml-kem/src/kem/kyber/hash_functions.rs index 3bc9feb2..f4b4d78c 100644 --- a/libcrux-ml-kem/src/kem/kyber/hash_functions.rs +++ b/libcrux-ml-kem/src/kem/kyber/hash_functions.rs @@ -1,7 +1,7 @@ #![allow(non_snake_case)] use super::constants::H_DIGEST_SIZE; -use crate::constants::G_DIGEST_SIZE; +const G_DIGEST_SIZE: usize = 64; use libcrux_sha3::portable::{ self, diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index a2908ab6..90796b17 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -53,32 +53,91 @@ pub(crate) mod hax_utils; // was stolen. // // This is being tracked in https://github.com/hacspec/hacspec-v2/issues/27 +#[cfg(feature = "pre-verification")] pub(crate) mod constants; /// Helpers for verification and extraction +#[cfg(feature = "pre-verification")] mod helper; +#[cfg(feature = "pre-verification")] mod utils; +#[cfg(feature = "pre-verification")] mod constant_time_ops; +#[cfg(feature = "pre-verification")] mod hash_functions; +#[cfg(feature = "pre-verification")] mod ind_cca; +#[cfg(feature = "pre-verification")] mod ind_cpa; +#[cfg(feature = "pre-verification")] mod invert_ntt; -mod kem; + +#[cfg(feature = "pre-verification")] mod matrix; +#[cfg(feature = "pre-verification")] mod ntt; +#[cfg(feature = "pre-verification")] mod polynomial; +#[cfg(feature = "pre-verification")] mod sampling; +#[cfg(feature = "pre-verification")] mod serialize; +#[cfg(feature = "pre-verification")] mod types; +#[cfg(feature = "pre-verification")] mod vector; +#[cfg(not(feature = "pre-verification"))] +mod kem; + // Variants -pub mod mlkem1024; +#[cfg(feature = "pre-verification")] pub mod mlkem512; +#[cfg(not(feature = "pre-verification"))] +pub mod mlkem512 { + pub use crate::kem::kyber::kyber512::decapsulate; + pub use crate::kem::kyber::kyber512::encapsulate; + pub use crate::kem::kyber::kyber512::generate_key_pair; + pub use crate::kem::kyber::kyber512::validate_public_key; +} + +#[cfg(feature = "pre-verification")] pub mod mlkem768; +#[cfg(not(feature = "pre-verification"))] +pub mod mlkem768 { + pub use crate::kem::kyber::kyber768::decapsulate; + pub use crate::kem::kyber::kyber768::encapsulate; + pub use crate::kem::kyber::kyber768::generate_key_pair; + pub use crate::kem::kyber::kyber768::validate_public_key; +} + +#[cfg(feature = "pre-verification")] +pub mod mlkem1024; +#[cfg(not(feature = "pre-verification"))] +pub mod mlkem1024 { + pub use crate::kem::kyber::kyber1024::decapsulate; + pub use crate::kem::kyber::kyber1024::encapsulate; + pub use crate::kem::kyber::kyber1024::generate_key_pair; + pub use crate::kem::kyber::kyber1024::validate_public_key; +} +#[cfg(feature = "pre-verification")] pub use constants::SHARED_SECRET_SIZE; +#[cfg(not(feature = "pre-verification"))] +pub const SHARED_SECRET_SIZE: usize = kem::kyber::constants::SHARED_SECRET_SIZE; + +#[cfg(feature = "pre-verification")] pub use ind_cca::{MlKemSharedSecret, ENCAPS_SEED_SIZE, KEY_GENERATION_SEED_SIZE}; +#[cfg(not(feature = "pre-verification"))] +pub use kem::kyber::MlKemSharedSecret; +#[cfg(not(feature = "pre-verification"))] +pub const ENCAPS_SEED_SIZE: usize = kem::kyber::constants::SHARED_SECRET_SIZE; +#[cfg(not(feature = "pre-verification"))] +pub const KEY_GENERATION_SEED_SIZE: usize = kem::kyber::KEY_GENERATION_SEED_SIZE; + // These types all have type aliases for the different variants. +#[cfg(not(feature = "pre-verification"))] +pub use kem::kyber::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; +#[cfg(feature = "pre-verification")] pub use types::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; diff --git a/libcrux-ml-kem/tests/nistkats.rs b/libcrux-ml-kem/tests/nistkats.rs index cf3a1c84..1441b89a 100644 --- a/libcrux-ml-kem/tests/nistkats.rs +++ b/libcrux-ml-kem/tests/nistkats.rs @@ -85,10 +85,10 @@ impl_nist_known_answer_tests!( mlkem1024::decapsulate ); -impl_nist_known_answer_tests!( - kyber768_nist_kats_portable, - 768, - mlkem768::portable::generate_key_pair, - mlkem768::portable::encapsulate, - mlkem768::portable::decapsulate -); +// impl_nist_known_answer_tests!( +// kyber768_nist_kats_portable, +// 768, +// mlkem768::portable::generate_key_pair, +// mlkem768::portable::encapsulate, +// mlkem768::portable::decapsulate +// ); From e346e99ddb2d80e998a8e754adeb1b159f2c1870 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Fri, 21 Jun 2024 10:22:08 +0200 Subject: [PATCH 10/53] Integrating pre-verification and verified testing --- libcrux-ml-kem/src/kem/kyber/types.rs | 5 +- libcrux-ml-kem/src/lib.rs | 9 + libcrux-ml-kem/src/types.rs | 6 +- libcrux-ml-kem/tests/kyber.rs | 3 +- libcrux-ml-kem/tests/self.rs | 676 ++++++++++++++++++-------- 5 files changed, 489 insertions(+), 210 deletions(-) diff --git a/libcrux-ml-kem/src/kem/kyber/types.rs b/libcrux-ml-kem/src/kem/kyber/types.rs index fda123be..36ced680 100644 --- a/libcrux-ml-kem/src/kem/kyber/types.rs +++ b/libcrux-ml-kem/src/kem/kyber/types.rs @@ -53,6 +53,10 @@ macro_rules! impl_generic_struct { pub const fn len(&self) -> usize { SIZE } + + pub const fn size() -> usize { + SIZE + } } }; } @@ -144,7 +148,6 @@ impl self.sk.as_slice() } - #[cfg(feature = "tests")] pub fn into_parts( self, ) -> ( diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 90796b17..eb708247 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -100,6 +100,9 @@ pub mod mlkem512 { pub use crate::kem::kyber::kyber512::encapsulate; pub use crate::kem::kyber::kyber512::generate_key_pair; pub use crate::kem::kyber::kyber512::validate_public_key; + pub use crate::kem::kyber::kyber512::MlKem512Ciphertext; + pub use crate::kem::kyber::kyber512::MlKem512PublicKey; + pub use crate::kem::kyber::kyber512::MlKem512PrivateKey; } #[cfg(feature = "pre-verification")] @@ -110,6 +113,9 @@ pub mod mlkem768 { pub use crate::kem::kyber::kyber768::encapsulate; pub use crate::kem::kyber::kyber768::generate_key_pair; pub use crate::kem::kyber::kyber768::validate_public_key; + pub use crate::kem::kyber::kyber768::MlKem768Ciphertext; + pub use crate::kem::kyber::kyber768::MlKem768PublicKey; + pub use crate::kem::kyber::kyber768::MlKem768PrivateKey; } #[cfg(feature = "pre-verification")] @@ -120,6 +126,9 @@ pub mod mlkem1024 { pub use crate::kem::kyber::kyber1024::encapsulate; pub use crate::kem::kyber::kyber1024::generate_key_pair; pub use crate::kem::kyber::kyber1024::validate_public_key; + pub use crate::kem::kyber::kyber1024::MlKem1024Ciphertext; + pub use crate::kem::kyber::kyber1024::MlKem1024PublicKey; + pub use crate::kem::kyber::kyber1024::MlKem1024PrivateKey; } #[cfg(feature = "pre-verification")] diff --git a/libcrux-ml-kem/src/types.rs b/libcrux-ml-kem/src/types.rs index 6d1d11e1..13142c29 100644 --- a/libcrux-ml-kem/src/types.rs +++ b/libcrux-ml-kem/src/types.rs @@ -56,7 +56,11 @@ macro_rules! impl_generic_struct { // } /// The number of bytes. - pub const fn len() -> usize { + pub const fn len(&self) -> usize { + SIZE + } + + pub const fn size() -> usize { SIZE } } diff --git a/libcrux-ml-kem/tests/kyber.rs b/libcrux-ml-kem/tests/kyber.rs index de4d220a..7f22ba03 100644 --- a/libcrux-ml-kem/tests/kyber.rs +++ b/libcrux-ml-kem/tests/kyber.rs @@ -1,8 +1,7 @@ -use libcrux_ml_kem::mlkem768; - #[test] #[cfg(feature = "kyber")] fn kyber768() { + use libcrux_ml_kem::mlkem768; let key_pair = mlkem768::generate_key_pair(hex::decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f").unwrap().try_into().unwrap()); let public_key = key_pair.pk(); diff --git a/libcrux-ml-kem/tests/self.rs b/libcrux-ml-kem/tests/self.rs index ae4aa72e..d25a7e55 100644 --- a/libcrux-ml-kem/tests/self.rs +++ b/libcrux-ml-kem/tests/self.rs @@ -1,239 +1,503 @@ -use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768, MlKemCiphertext, MlKemPrivateKey}; -use libcrux_sha3::shake256; -use rand::{rngs::OsRng, thread_rng, RngCore}; +#[cfg(not(feature = "pre-verification"))] +pub mod default { + use libcrux_ml_kem::{ + mlkem1024::{self, MlKem1024Ciphertext}, + mlkem512, mlkem768, MlKemCiphertext, MlKemPrivateKey, + }; + use libcrux_sha3::shake256; + use rand::{rngs::OsRng, thread_rng, RngCore}; -const SHARED_SECRET_SIZE: usize = 32; + const SHARED_SECRET_SIZE: usize = 32; -fn random_array() -> [u8; L] { - let mut rng = OsRng; - let mut seed = [0; L]; - rng.try_fill_bytes(&mut seed).unwrap(); - seed -} + fn random_array() -> [u8; L] { + let mut rng = OsRng; + let mut seed = [0; L]; + rng.try_fill_bytes(&mut seed).unwrap(); + seed + } + + macro_rules! impl_consistency { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); + let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); + assert_eq!( + shared_secret, shared_secret_decapsulated, + "lhs: shared_secret, rhs: shared_secret_decapsulated" + ); + + // If the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; + } + + fn modify_ciphertext( + mut ciphertext: MlKemCiphertext, + ) -> MlKemCiphertext { + let mut raw_ciphertext = [0u8; LEN]; + raw_ciphertext.copy_from_slice(ciphertext.as_ref()); + let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); -macro_rules! impl_consistency { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); - let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); - assert_eq!( - shared_secret, shared_secret_decapsulated, - "lhs: shared_secret, rhs: shared_secret_decapsulated" - ); - - // If the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. + let mut random_byte: u8 = (random_u32 & 0xFF) as u8; + if random_byte == 0 { + random_byte += 1; } - }; -} + random_u32 >>= 8; + + let position = random_u32 % MlKemCiphertext::::size(); + raw_ciphertext[position] ^= random_byte; -fn modify_ciphertext( - mut ciphertext: MlKemCiphertext, -) -> MlKemCiphertext { - let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); + let ciphertext: [u8; LEN] = raw_ciphertext[0..MlKemCiphertext::::size()] + .try_into() + .unwrap(); - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; + ciphertext.into() } - random_u32 >>= 8; - let position = random_u32 % MlKemCiphertext::::len(); - ciphertext[position] ^= random_byte; + macro_rules! impl_modified_ciphertext { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); + + let ciphertext = modify_ciphertext(ciphertext); + let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); + + assert_ne!(shared_secret, shared_secret_decapsulated); + + // if the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; + } - ciphertext -} + fn modify_secret_key( + secret_key: &MlKemPrivateKey, + modify_implicit_rejection_value: bool, + ) -> MlKemPrivateKey { + let mut raw_secret_key = [0u8; LEN]; + raw_secret_key.copy_from_slice(secret_key.as_slice()); -macro_rules! impl_modified_ciphertext { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); + let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); - let ciphertext = modify_ciphertext(ciphertext); - let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); + let mut random_byte: u8 = (random_u32 & 0xFF) as u8; + if random_byte == 0 { + random_byte += 1; + } + random_u32 >>= 8; - assert_ne!(shared_secret, shared_secret_decapsulated); + let position = if modify_implicit_rejection_value { + (MlKemPrivateKey::::size() - SHARED_SECRET_SIZE) + + (random_u32 % SHARED_SECRET_SIZE) + } else { + random_u32 % (MlKemPrivateKey::::size() - SHARED_SECRET_SIZE) + }; - // if the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. - } - }; -} + raw_secret_key[position] ^= random_byte; + + let secret_key: [u8; LEN] = raw_secret_key[0..MlKemPrivateKey::::size()] + .try_into() + .unwrap(); -fn modify_secret_key( - secret_key: &MlKemPrivateKey, - modify_implicit_rejection_value: bool, -) -> MlKemPrivateKey { - let mut raw_secret_key: MlKemPrivateKey = secret_key.as_slice().into(); + secret_key.into() + } - let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); + fn compute_implicit_rejection_shared_secret( + ciphertext: MlKemCiphertext, + secret_key: MlKemPrivateKey, + ) -> [u8; SHARED_SECRET_SIZE] { + let mut to_hash = + secret_key[MlKemPrivateKey::::size() - SHARED_SECRET_SIZE..].to_vec(); + to_hash.extend_from_slice(ciphertext.as_ref()); - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; + shake256(&to_hash) } - random_u32 >>= 8; - let position = if modify_implicit_rejection_value { - (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) - } else { - random_u32 % (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) - }; + macro_rules! impl_modified_secret_key { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); + + let secret_key = modify_secret_key(key_pair.private_key(), false); + let shared_secret_decapsulated = $decaps(&secret_key, &ciphertext); + + assert_eq!( + shared_secret_decapsulated, + compute_implicit_rejection_shared_secret(ciphertext, secret_key) + ); + + // if the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; + } - raw_secret_key[position] ^= random_byte; + macro_rules! impl_modified_ciphertext_and_implicit_rejection_value { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); + + let ciphertext = modify_ciphertext(ciphertext); + let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); + + let secret_key = modify_secret_key(key_pair.private_key(), true); + let shared_secret_decapsulated_ms = $decaps(&secret_key, &ciphertext); + + assert_ne!(shared_secret_decapsulated, shared_secret_decapsulated_ms); + + assert_eq!( + shared_secret_decapsulated_ms, + compute_implicit_rejection_shared_secret(ciphertext, secret_key) + ); + + // if the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; + } - raw_secret_key + impl_consistency!( + consistency_512, + mlkem512::generate_key_pair, + mlkem512::encapsulate, + mlkem512::decapsulate + ); + impl_consistency!( + consistency_768, + mlkem768::generate_key_pair, + mlkem768::encapsulate, + mlkem768::decapsulate + ); + impl_consistency!( + consistency_1024, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + + impl_modified_ciphertext!( + modified_ciphertext_512, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_ciphertext!( + modified_ciphertext_768, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_ciphertext!( + modified_ciphertext_1024, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + + impl_modified_secret_key!( + modified_secret_key_512, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_secret_key!( + modified_secret_key_768, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_secret_key!( + modified_secret_key_1024, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + + impl_modified_ciphertext_and_implicit_rejection_value!( + modified_ciphertext_and_implicit_rejection_value_512, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_ciphertext_and_implicit_rejection_value!( + modified_ciphertext_and_implicit_rejection_value_768, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_ciphertext_and_implicit_rejection_value!( + modified_ciphertext_and_implicit_rejection_value_1024, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); } -fn compute_implicit_rejection_shared_secret( - ciphertext: MlKemCiphertext, - secret_key: MlKemPrivateKey, -) -> [u8; SHARED_SECRET_SIZE] { - let mut to_hash = secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); - to_hash.extend_from_slice(ciphertext.as_ref()); +#[cfg(feature = "pre-verification")] +pub mod pre_verification { + use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768, MlKemCiphertext, MlKemPrivateKey}; + use libcrux_sha3::shake256; + use rand::{rngs::OsRng, thread_rng, RngCore}; - shake256(&to_hash) -} + const SHARED_SECRET_SIZE: usize = 32; + + fn random_array() -> [u8; L] { + let mut rng = OsRng; + let mut seed = [0; L]; + rng.try_fill_bytes(&mut seed).unwrap(); + seed + } + + macro_rules! impl_consistency { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); + let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); + assert_eq!( + shared_secret, shared_secret_decapsulated, + "lhs: shared_secret, rhs: shared_secret_decapsulated" + ); + + // If the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; + } -macro_rules! impl_modified_secret_key { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); - - let secret_key = modify_secret_key(key_pair.private_key(), false); - let shared_secret_decapsulated = $decaps(&secret_key, &ciphertext); - - assert_eq!( - shared_secret_decapsulated, - compute_implicit_rejection_shared_secret(ciphertext, secret_key) - ); - - // if the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. + fn modify_ciphertext( + mut ciphertext: MlKemCiphertext, + ) -> MlKemCiphertext { + let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); + + let mut random_byte: u8 = (random_u32 & 0xFF) as u8; + if random_byte == 0 { + random_byte += 1; } - }; -} + random_u32 >>= 8; -macro_rules! impl_modified_ciphertext_and_implicit_rejection_value { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); + let position = random_u32 % MlKemCiphertext::::size(); + ciphertext[position] ^= random_byte; - let ciphertext = modify_ciphertext(ciphertext); - let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); + ciphertext + } - let secret_key = modify_secret_key(key_pair.private_key(), true); - let shared_secret_decapsulated_ms = $decaps(&secret_key, &ciphertext); + macro_rules! impl_modified_ciphertext { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); + + let ciphertext = modify_ciphertext(ciphertext); + let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); + + assert_ne!(shared_secret, shared_secret_decapsulated); + + // if the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; + } - assert_ne!(shared_secret_decapsulated, shared_secret_decapsulated_ms); + fn modify_secret_key( + secret_key: &MlKemPrivateKey, + modify_implicit_rejection_value: bool, + ) -> MlKemPrivateKey { + let mut raw_secret_key: MlKemPrivateKey = secret_key.as_slice().into(); - assert_eq!( - shared_secret_decapsulated_ms, - compute_implicit_rejection_shared_secret(ciphertext, secret_key) - ); + let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); - // if the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. + let mut random_byte: u8 = (random_u32 & 0xFF) as u8; + if random_byte == 0 { + random_byte += 1; } - }; -} + random_u32 >>= 8; + + let position = if modify_implicit_rejection_value { + (MlKemPrivateKey::::size() - SHARED_SECRET_SIZE) + + (random_u32 % SHARED_SECRET_SIZE) + } else { + random_u32 % (MlKemPrivateKey::::size() - SHARED_SECRET_SIZE) + }; -impl_consistency!( - consistency_512, - mlkem512::generate_key_pair, - mlkem512::encapsulate, - mlkem512::decapsulate -); -impl_consistency!( - consistency_768, - mlkem768::generate_key_pair, - mlkem768::encapsulate, - mlkem768::decapsulate -); -impl_consistency!( - consistency_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); - -impl_modified_ciphertext!( - modified_ciphertext_512, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); -impl_modified_ciphertext!( - modified_ciphertext_768, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); -impl_modified_ciphertext!( - modified_ciphertext_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); - -impl_modified_secret_key!( - modified_secret_key_512, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); -impl_modified_secret_key!( - modified_secret_key_768, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); -impl_modified_secret_key!( - modified_secret_key_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); - -impl_modified_ciphertext_and_implicit_rejection_value!( - modified_ciphertext_and_implicit_rejection_value_512, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); -impl_modified_ciphertext_and_implicit_rejection_value!( - modified_ciphertext_and_implicit_rejection_value_768, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); -impl_modified_ciphertext_and_implicit_rejection_value!( - modified_ciphertext_and_implicit_rejection_value_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate -); + raw_secret_key[position] ^= random_byte; + + raw_secret_key + } + + fn compute_implicit_rejection_shared_secret( + ciphertext: MlKemCiphertext, + secret_key: MlKemPrivateKey, + ) -> [u8; SHARED_SECRET_SIZE] { + let mut to_hash = + secret_key[MlKemPrivateKey::::size() - SHARED_SECRET_SIZE..].to_vec(); + to_hash.extend_from_slice(ciphertext.as_ref()); + + shake256(&to_hash) + } + + macro_rules! impl_modified_secret_key { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); + + let secret_key = modify_secret_key(key_pair.private_key(), false); + let shared_secret_decapsulated = $decaps(&secret_key, &ciphertext); + + assert_eq!( + shared_secret_decapsulated, + compute_implicit_rejection_shared_secret(ciphertext, secret_key) + ); + + // if the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; + } + + macro_rules! impl_modified_ciphertext_and_implicit_rejection_value { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); + + let ciphertext = modify_ciphertext(ciphertext); + let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); + + let secret_key = modify_secret_key(key_pair.private_key(), true); + let shared_secret_decapsulated_ms = $decaps(&secret_key, &ciphertext); + + assert_ne!(shared_secret_decapsulated, shared_secret_decapsulated_ms); + + assert_eq!( + shared_secret_decapsulated_ms, + compute_implicit_rejection_shared_secret(ciphertext, secret_key) + ); + + // if the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; + } + + impl_consistency!( + consistency_512, + mlkem512::generate_key_pair, + mlkem512::encapsulate, + mlkem512::decapsulate + ); + impl_consistency!( + consistency_768, + mlkem768::generate_key_pair, + mlkem768::encapsulate, + mlkem768::decapsulate + ); + impl_consistency!( + consistency_1024, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + + impl_modified_ciphertext!( + modified_ciphertext_512, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_ciphertext!( + modified_ciphertext_768, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_ciphertext!( + modified_ciphertext_1024, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + + impl_modified_secret_key!( + modified_secret_key_512, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_secret_key!( + modified_secret_key_768, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_secret_key!( + modified_secret_key_1024, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + + impl_modified_ciphertext_and_implicit_rejection_value!( + modified_ciphertext_and_implicit_rejection_value_512, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_ciphertext_and_implicit_rejection_value!( + modified_ciphertext_and_implicit_rejection_value_768, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); + impl_modified_ciphertext_and_implicit_rejection_value!( + modified_ciphertext_and_implicit_rejection_value_1024, + mlkem1024::generate_key_pair, + mlkem1024::encapsulate, + mlkem1024::decapsulate + ); +} From cb11230892d9b5720cc140906c57fd122df2f827 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Fri, 21 Jun 2024 10:22:34 +0200 Subject: [PATCH 11/53] Integrating verified ML-KEM in `libcrux-kem` --- libcrux-kem/Cargo.toml | 1 + libcrux-kem/src/kem.rs | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libcrux-kem/Cargo.toml b/libcrux-kem/Cargo.toml index e59c608a..a9ef7160 100644 --- a/libcrux-kem/Cargo.toml +++ b/libcrux-kem/Cargo.toml @@ -21,6 +21,7 @@ rand = { version = "0.8" } [features] tests = [] # Expose functions for testing. kyber = ["libcrux-ml-kem/kyber"] +pre-verification = ["libcrux-ml-kem/pre-verification"] [dev-dependencies] libcrux-kem = { version = "0.0.2-pre.2", path = "./", features = ["tests"] } diff --git a/libcrux-kem/src/kem.rs b/libcrux-kem/src/kem.rs index ec03433e..ffc57baf 100644 --- a/libcrux-kem/src/kem.rs +++ b/libcrux-kem/src/kem.rs @@ -481,7 +481,7 @@ impl PrivateKey { .map_err(|_| Error::InvalidPrivateKey) .map(Self::MlKem768), Algorithm::X25519MlKem768Draft00 => { - let key: [u8; MlKem768PrivateKey::len() + 32] = + let key: [u8; MlKem768PrivateKey::size() + 32] = bytes.try_into().map_err(|_| Error::InvalidPrivateKey)?; let (xsk, ksk) = key.split_at(32); Ok(Self::X25519MlKem768Draft00( @@ -787,7 +787,7 @@ impl Ct { .map_err(|_| Error::InvalidCiphertext) .map(Self::MlKem768), Algorithm::X25519MlKem768Draft00 => { - let key: [u8; MlKem768Ciphertext::len() + 32] = + let key: [u8; MlKem768Ciphertext::size() + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; let (xct, kct) = key.split_at(32); Ok(Self::X25519MlKem768Draft00( @@ -796,9 +796,9 @@ impl Ct { )) } Algorithm::XWingKemDraft02 => { - let key: [u8; MlKem768Ciphertext::len() + 32] = + let key: [u8; MlKem768Ciphertext::size() + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; - let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::len()); + let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::size()); Ok(Self::XWingKemDraft02( ct_m.try_into().map_err(|_| Error::InvalidCiphertext)?, ct_x.try_into().map_err(|_| Error::InvalidCiphertext)?, @@ -818,7 +818,7 @@ impl Ct { Algorithm::XWingKyberDraft02 => { let key: [u8; MlKem768Ciphertext::len() + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; - let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::len()); + let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::size()); Ok(Self::XWingKyberDraft02( ct_m.try_into().map_err(|_| Error::InvalidCiphertext)?, ct_x.try_into().map_err(|_| Error::InvalidCiphertext)?, From cfaeac06119360741a984df2f997629971cd2701 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Fri, 21 Jun 2024 10:34:30 +0200 Subject: [PATCH 12/53] Format --- libcrux-ml-kem/src/lib.rs | 6 +++--- libcrux-ml-kem/src/types.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index eb708247..aed2937b 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -101,8 +101,8 @@ pub mod mlkem512 { pub use crate::kem::kyber::kyber512::generate_key_pair; pub use crate::kem::kyber::kyber512::validate_public_key; pub use crate::kem::kyber::kyber512::MlKem512Ciphertext; - pub use crate::kem::kyber::kyber512::MlKem512PublicKey; pub use crate::kem::kyber::kyber512::MlKem512PrivateKey; + pub use crate::kem::kyber::kyber512::MlKem512PublicKey; } #[cfg(feature = "pre-verification")] @@ -114,8 +114,8 @@ pub mod mlkem768 { pub use crate::kem::kyber::kyber768::generate_key_pair; pub use crate::kem::kyber::kyber768::validate_public_key; pub use crate::kem::kyber::kyber768::MlKem768Ciphertext; - pub use crate::kem::kyber::kyber768::MlKem768PublicKey; pub use crate::kem::kyber::kyber768::MlKem768PrivateKey; + pub use crate::kem::kyber::kyber768::MlKem768PublicKey; } #[cfg(feature = "pre-verification")] @@ -127,8 +127,8 @@ pub mod mlkem1024 { pub use crate::kem::kyber::kyber1024::generate_key_pair; pub use crate::kem::kyber::kyber1024::validate_public_key; pub use crate::kem::kyber::kyber1024::MlKem1024Ciphertext; - pub use crate::kem::kyber::kyber1024::MlKem1024PublicKey; pub use crate::kem::kyber::kyber1024::MlKem1024PrivateKey; + pub use crate::kem::kyber::kyber1024::MlKem1024PublicKey; } #[cfg(feature = "pre-verification")] diff --git a/libcrux-ml-kem/src/types.rs b/libcrux-ml-kem/src/types.rs index 13142c29..c5ffd59f 100644 --- a/libcrux-ml-kem/src/types.rs +++ b/libcrux-ml-kem/src/types.rs @@ -59,7 +59,7 @@ macro_rules! impl_generic_struct { pub const fn len(&self) -> usize { SIZE } - + pub const fn size() -> usize { SIZE } From d86006b18cb2e463d441be50333d6029876c34a3 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Fri, 21 Jun 2024 10:37:24 +0200 Subject: [PATCH 13/53] Test portable pre-verification ML-KEM 768 --- libcrux-ml-kem/tests/nistkats.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libcrux-ml-kem/tests/nistkats.rs b/libcrux-ml-kem/tests/nistkats.rs index 1441b89a..1d547d0c 100644 --- a/libcrux-ml-kem/tests/nistkats.rs +++ b/libcrux-ml-kem/tests/nistkats.rs @@ -85,10 +85,11 @@ impl_nist_known_answer_tests!( mlkem1024::decapsulate ); -// impl_nist_known_answer_tests!( -// kyber768_nist_kats_portable, -// 768, -// mlkem768::portable::generate_key_pair, -// mlkem768::portable::encapsulate, -// mlkem768::portable::decapsulate -// ); +#[cfg(feature = "pre-verification")] +impl_nist_known_answer_tests!( + kyber768_nist_kats_portable, + 768, + mlkem768::portable::generate_key_pair, + mlkem768::portable::encapsulate, + mlkem768::portable::decapsulate +); From 8cdead9d4e2f022fbe794f5b3dd59c5df3ff0797 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Mon, 24 Jun 2024 17:07:23 +0200 Subject: [PATCH 14/53] fix C extraction --- libcrux-ml-kem/src/ind_cca.rs | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index bb32cfdf..9fa3f88a 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -1,5 +1,3 @@ -use libcrux_sha3::shake256; - use crate::{ constant_time_ops::{ compare_ciphertexts_in_constant_time, select_shared_secret_in_constant_time, @@ -134,12 +132,12 @@ fn encapsulate< const ETA2_RANDOMNESS_SIZE: usize, Vector: Operations, Hasher: Hash, - Scheme: Variant, + Scheme: Variant, >( public_key: &MlKemPublicKey, randomness: [u8; SHARED_SECRET_SIZE], ) -> (MlKemCiphertext, MlKemSharedSecret) { - let randomness = Scheme::entropy_preprocess(&randomness); + let randomness = Scheme::entropy_preprocess::(&randomness); let mut to_hash: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&randomness); to_hash[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(public_key.as_slice())); @@ -163,7 +161,7 @@ fn encapsulate< Hasher, >(public_key.as_slice(), randomness, pseudorandomness); - let shared_secret_array = Scheme::kdf(shared_secret, &ciphertext); + let shared_secret_array = Scheme::kdf::(shared_secret, &ciphertext); (MlKemCiphertext::from(ciphertext), shared_secret_array) } @@ -187,7 +185,7 @@ pub(crate) fn decapsulate< const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize, Vector: Operations, Hasher: Hash, - Scheme: Variant, + Scheme: Variant, >( private_key: &MlKemPrivateKey, ciphertext: &MlKemCiphertext, @@ -239,8 +237,8 @@ pub(crate) fn decapsulate< ); let implicit_rejection_shared_secret = - Scheme::kdf(&implicit_rejection_shared_secret, ciphertext.as_slice()); - let shared_secret = Scheme::kdf(&shared_secret, ciphertext.as_slice()); + Scheme::kdf::(&implicit_rejection_shared_secret, ciphertext.as_slice()); + let shared_secret = Scheme::kdf::(&shared_secret, ciphertext.as_slice()); select_shared_secret_in_constant_time( &shared_secret, @@ -249,36 +247,35 @@ pub(crate) fn decapsulate< ) } -pub(crate) trait Variant> { - fn kdf(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32]; - - fn entropy_preprocess(randomness: &[u8]) -> [u8; 32]; +pub(crate) trait Variant { + fn kdf>(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32]; + fn entropy_preprocess>(randomness: &[u8]) -> [u8; 32]; } pub(crate) struct Kyber {} -impl> Variant for Kyber { - fn kdf(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32] { +impl Variant for Kyber { + fn kdf>(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32] { let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext)); - shake256::<32>(&kdf_input) + Hasher::PRF::<32>(&kdf_input) } - fn entropy_preprocess(randomness: &[u8]) -> [u8; 32] { + fn entropy_preprocess>(randomness: &[u8]) -> [u8; 32] { Hasher::H(&randomness) } } pub(crate) struct MlKem {} -impl> Variant for MlKem { - fn kdf(shared_secret: &[u8], _ciphertext: &[u8]) -> [u8; 32] { +impl Variant for MlKem { + fn kdf>(shared_secret: &[u8], _ciphertext: &[u8]) -> [u8; 32] { let mut shared_secret_array = [0u8; SHARED_SECRET_SIZE]; shared_secret_array.copy_from_slice(shared_secret); shared_secret_array } - fn entropy_preprocess(randomness: &[u8]) -> [u8; 32] { + fn entropy_preprocess>(randomness: &[u8]) -> [u8; 32] { let mut randomness_array = [0u8; 32]; randomness_array.copy_from_slice(randomness); randomness_array From 847136a88b20d4bb6da9a563a0f2686b5bcdd44b Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 08:21:55 +0200 Subject: [PATCH 15/53] Fix typo --- libcrux-ml-kem/src/ind_cca/instantiations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrux-ml-kem/src/ind_cca/instantiations.rs b/libcrux-ml-kem/src/ind_cca/instantiations.rs index 66bfb56c..322321a5 100644 --- a/libcrux-ml-kem/src/ind_cca/instantiations.rs +++ b/libcrux-ml-kem/src/ind_cca/instantiations.rs @@ -47,7 +47,7 @@ macro_rules! instantiate { >(public_key) } - /// Portable encapsualte + /// Portable encapsulate #[cfg(feature = "kyber")] pub(crate) fn kyber_encapsulate< const K: usize, From 32af120a9cfe0c1bfb9acd6f8e598533d092763e Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 08:25:57 +0200 Subject: [PATCH 16/53] Give more accurate test names (`kyber...` to `mlkem...`) --- libcrux-ml-kem/tests/nistkats.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libcrux-ml-kem/tests/nistkats.rs b/libcrux-ml-kem/tests/nistkats.rs index cf3a1c84..e52cedc8 100644 --- a/libcrux-ml-kem/tests/nistkats.rs +++ b/libcrux-ml-kem/tests/nistkats.rs @@ -6,7 +6,7 @@ use std::{fs::File, io::BufReader, path::Path}; use libcrux_sha3::*; #[derive(Deserialize)] -struct KyberNISTKAT { +struct MlKemNISTKAT { #[serde(with = "hex::serde")] key_generation_seed: [u8; 64], @@ -36,7 +36,7 @@ macro_rules! impl_nist_known_answer_tests { let katfile = File::open(katfile_path).expect("Could not open KAT file."); let reader = BufReader::new(katfile); - let nist_kats: Vec = + let nist_kats: Vec = serde_json::from_reader(reader).expect("Could not deserialize KAT file."); for kat in nist_kats { @@ -64,21 +64,21 @@ macro_rules! impl_nist_known_answer_tests { } impl_nist_known_answer_tests!( - kyber512_nist_known_answer_tests, + mlkem512_nist_known_answer_tests, 512, mlkem512::generate_key_pair, mlkem512::encapsulate, mlkem512::decapsulate ); impl_nist_known_answer_tests!( - kyber768_nist_known_answer_tests, + mlkem768_nist_known_answer_tests, 768, mlkem768::generate_key_pair, mlkem768::encapsulate, mlkem768::decapsulate ); impl_nist_known_answer_tests!( - kyber1024_nist_known_answer_tests, + mlkem1024_nist_known_answer_tests, 1024, mlkem1024::generate_key_pair, mlkem1024::encapsulate, @@ -86,7 +86,7 @@ impl_nist_known_answer_tests!( ); impl_nist_known_answer_tests!( - kyber768_nist_kats_portable, + mlkem768_nist_kats_portable, 768, mlkem768::portable::generate_key_pair, mlkem768::portable::encapsulate, From 11355daae369565d6175d0669a04e8f83067045b Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 08:28:17 +0200 Subject: [PATCH 17/53] Avoid unused warning when testing --- libcrux-ml-kem/tests/kyber.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libcrux-ml-kem/tests/kyber.rs b/libcrux-ml-kem/tests/kyber.rs index de4d220a..7f22ba03 100644 --- a/libcrux-ml-kem/tests/kyber.rs +++ b/libcrux-ml-kem/tests/kyber.rs @@ -1,8 +1,7 @@ -use libcrux_ml_kem::mlkem768; - #[test] #[cfg(feature = "kyber")] fn kyber768() { + use libcrux_ml_kem::mlkem768; let key_pair = mlkem768::generate_key_pair(hex::decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f").unwrap().try_into().unwrap()); let public_key = key_pair.pk(); From 0aa89eb699c7ccf50d7b7e233559f728164e4b92 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 08:39:24 +0200 Subject: [PATCH 18/53] Use `Hasher` trait to select best KDF for Kyber --- libcrux-ml-kem/src/ind_cca.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index bb32cfdf..12bea55a 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -1,5 +1,3 @@ -use libcrux_sha3::shake256; - use crate::{ constant_time_ops::{ compare_ciphertexts_in_constant_time, select_shared_secret_in_constant_time, @@ -261,7 +259,7 @@ impl> Variant for Kyber { fn kdf(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32] { let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext)); - shake256::<32>(&kdf_input) + Hasher::PRF::<32>(&kdf_input) } fn entropy_preprocess(randomness: &[u8]) -> [u8; 32] { From b4e4d13ad100d0071f4212bb5bf872afadd6f01f Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 08:51:01 +0200 Subject: [PATCH 19/53] Document differences between Kyber (Round 3) and ML-KEM --- libcrux-ml-kem/src/ind_cca.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index 12bea55a..cb10caa7 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -247,12 +247,22 @@ pub(crate) fn decapsulate< ) } +/// This trait collects differences in specification between ML-KEM +/// (Draft FIPS 203) and the Round 3 CRYSTALS-Kyber submission in the +/// NIST PQ competition. +/// +/// cf. FIPS 203 (Draft), section 1.3 pub(crate) trait Variant> { fn kdf(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32]; fn entropy_preprocess(randomness: &[u8]) -> [u8; 32]; } +/// Implements [`Variant`], to perform the Kyber-specific actions +/// during encapsulation and decapsulation. +/// Specifically, +/// * during encapsulation, the initial randomness is hashed before being used, +/// * the derivation of the shared secret includes a hash of the Kyber ciphertext. pub(crate) struct Kyber {} impl> Variant for Kyber { @@ -267,6 +277,11 @@ impl> Variant for Kyber { } } +/// Implements [`Variant`], to perform the ML-KEM-specific actions +/// during encapsulation and decapsulation. +/// Specifically, +/// * during encapsulation, the initial randomness is used without prior hashing, +/// * the derivation of the shared secret does not include a hash of the ML-KEM ciphertext. pub(crate) struct MlKem {} impl> Variant for MlKem { From 1d9e38d3ef5242f7a1a61604a72e033df144766c Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 08:52:17 +0200 Subject: [PATCH 20/53] Inline ML-KEM/Kyber variant differences --- libcrux-ml-kem/src/ind_cca.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index cb10caa7..d8086eec 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -266,12 +266,14 @@ pub(crate) trait Variant> { pub(crate) struct Kyber {} impl> Variant for Kyber { + #[inline(always)] fn kdf(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32] { let mut kdf_input: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&shared_secret); kdf_input[H_DIGEST_SIZE..].copy_from_slice(&Hasher::H(ciphertext)); Hasher::PRF::<32>(&kdf_input) } + #[inline(always)] fn entropy_preprocess(randomness: &[u8]) -> [u8; 32] { Hasher::H(&randomness) } @@ -285,12 +287,14 @@ impl> Variant for Kyber { pub(crate) struct MlKem {} impl> Variant for MlKem { + #[inline(always)] fn kdf(shared_secret: &[u8], _ciphertext: &[u8]) -> [u8; 32] { let mut shared_secret_array = [0u8; SHARED_SECRET_SIZE]; shared_secret_array.copy_from_slice(shared_secret); shared_secret_array } + #[inline(always)] fn entropy_preprocess(randomness: &[u8]) -> [u8; 32] { let mut randomness_array = [0u8; 32]; randomness_array.copy_from_slice(randomness); From 00e62c0b378c74527cdc57afa569c711ca90730b Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 09:15:00 +0200 Subject: [PATCH 21/53] `kyber{512,768,1024}` top level modules --- libcrux-ml-kem/src/ind_cca.rs | 2 + libcrux-ml-kem/src/lib.rs | 27 ++++++++ libcrux-ml-kem/src/mlkem1024.rs | 110 +++++++++++++++++--------------- libcrux-ml-kem/src/mlkem512.rs | 110 +++++++++++++++++--------------- libcrux-ml-kem/src/mlkem768.rs | 110 ++++++++++++++++---------------- libcrux-ml-kem/tests/kyber.rs | 9 ++- 6 files changed, 203 insertions(+), 165 deletions(-) diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index d8086eec..57fd2606 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -263,8 +263,10 @@ pub(crate) trait Variant> { /// Specifically, /// * during encapsulation, the initial randomness is hashed before being used, /// * the derivation of the shared secret includes a hash of the Kyber ciphertext. +#[cfg(feature = "kyber")] pub(crate) struct Kyber {} +#[cfg(feature = "kyber")] impl> Variant for Kyber { #[inline(always)] fn kdf(shared_secret: &[u8], ciphertext: &[u8]) -> [u8; 32] { diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 2a431fdb..abf3b7b1 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -77,6 +77,33 @@ pub mod mlkem1024; pub mod mlkem512; pub mod mlkem768; +#[cfg(feature = "kyber")] +pub mod kyber512 { + //! Kyber 512 (NIST PQC Round 3) + pub use crate::mlkem512::generate_key_pair; + pub use crate::mlkem512::kyber::decapsulate; + pub use crate::mlkem512::kyber::encapsulate; + pub use crate::mlkem512::validate_public_key; +} + +#[cfg(feature = "kyber")] +pub mod kyber768 { + //! Kyber 768 (NIST PQC Round 3) + pub use crate::mlkem768::generate_key_pair; + pub use crate::mlkem768::kyber::decapsulate; + pub use crate::mlkem768::kyber::encapsulate; + pub use crate::mlkem768::validate_public_key; +} + +#[cfg(feature = "kyber")] +pub mod kyber1024 { + //! Kyber 1024 (NIST PQC Round 3) + pub use crate::mlkem1024::generate_key_pair; + pub use crate::mlkem1024::kyber::decapsulate; + pub use crate::mlkem1024::kyber::encapsulate; + pub use crate::mlkem1024::validate_public_key; +} + pub use constants::SHARED_SECRET_SIZE; pub use ind_cca::{MlKemSharedSecret, ENCAPS_SEED_SIZE, KEY_GENERATION_SEED_SIZE}; // These types all have type aliases for the different variants. diff --git a/libcrux-ml-kem/src/mlkem1024.rs b/libcrux-ml-kem/src/mlkem1024.rs index 49767d18..d1107b02 100644 --- a/libcrux-ml-kem/src/mlkem1024.rs +++ b/libcrux-ml-kem/src/mlkem1024.rs @@ -271,33 +271,6 @@ pub fn encapsulate( >(public_key, randomness) } -/// Encapsulate Kyber 1024 -/// -/// Generates an ([`MlKem1024Ciphertext`], [`MlKemSharedSecret`]) tuple. -/// The input is a reference to an [`MlKem1024PublicKey`] and [`SHARED_SECRET_SIZE`] -/// bytes of `randomness`. -#[cfg(all(not(eurydice), feature = "kyber"))] -pub fn kyber_encapsulate( - public_key: &MlKem1024PublicKey, - randomness: [u8; SHARED_SECRET_SIZE], -) -> (MlKem1024Ciphertext, MlKemSharedSecret) { - multiplexing::kyber_encapsulate::< - RANK_1024, - CPA_PKE_CIPHERTEXT_SIZE_1024, - CPA_PKE_PUBLIC_KEY_SIZE_1024, - T_AS_NTT_ENCODED_SIZE_1024, - C1_SIZE_1024, - C2_SIZE_1024, - VECTOR_U_COMPRESSION_FACTOR_1024, - VECTOR_V_COMPRESSION_FACTOR_1024, - C1_BLOCK_SIZE_1024, - ETA1, - ETA1_RANDOMNESS_SIZE, - ETA2, - ETA2_RANDOMNESS_SIZE, - >(public_key, randomness) -} - /// Decapsulate ML-KEM 1024 /// /// Generates an [`MlKemSharedSecret`]. @@ -327,31 +300,62 @@ pub fn decapsulate( >(private_key, ciphertext) } -/// Decapsulate Kyber 1024 -/// -/// Generates an [`MlKemSharedSecret`]. -/// The input is a reference to an [`MlKem1024PrivateKey`] and an [`MlKem1024Ciphertext`]. #[cfg(all(not(eurydice), feature = "kyber"))] -pub fn kyber_decapsulate( - private_key: &MlKem1024PrivateKey, - ciphertext: &MlKem1024Ciphertext, -) -> MlKemSharedSecret { - multiplexing::kyber_decapsulate::< - RANK_1024, - SECRET_KEY_SIZE_1024, - CPA_PKE_SECRET_KEY_SIZE_1024, - CPA_PKE_PUBLIC_KEY_SIZE_1024, - CPA_PKE_CIPHERTEXT_SIZE_1024, - T_AS_NTT_ENCODED_SIZE_1024, - C1_SIZE_1024, - C2_SIZE_1024, - VECTOR_U_COMPRESSION_FACTOR_1024, - VECTOR_V_COMPRESSION_FACTOR_1024, - C1_BLOCK_SIZE_1024, - ETA1, - ETA1_RANDOMNESS_SIZE, - ETA2, - ETA2_RANDOMNESS_SIZE, - IMPLICIT_REJECTION_HASH_INPUT_SIZE, - >(private_key, ciphertext) +pub(crate) mod kyber { + use super::*; + + /// Encapsulate Kyber 1024 + /// + /// Generates an ([`MlKem1024Ciphertext`], [`MlKemSharedSecret`]) tuple. + /// The input is a reference to an [`MlKem1024PublicKey`] and [`SHARED_SECRET_SIZE`] + /// bytes of `randomness`. + pub fn encapsulate( + public_key: &MlKem1024PublicKey, + randomness: [u8; SHARED_SECRET_SIZE], + ) -> (MlKem1024Ciphertext, MlKemSharedSecret) { + multiplexing::kyber_encapsulate::< + RANK_1024, + CPA_PKE_CIPHERTEXT_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + T_AS_NTT_ENCODED_SIZE_1024, + C1_SIZE_1024, + C2_SIZE_1024, + VECTOR_U_COMPRESSION_FACTOR_1024, + VECTOR_V_COMPRESSION_FACTOR_1024, + C1_BLOCK_SIZE_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) + } + + /// Decapsulate Kyber 1024 + /// + /// Generates an [`MlKemSharedSecret`]. + /// The input is a reference to an [`MlKem1024PrivateKey`] and an [`MlKem1024Ciphertext`]. + #[cfg(all(not(eurydice), feature = "kyber"))] + pub fn decapsulate( + private_key: &MlKem1024PrivateKey, + ciphertext: &MlKem1024Ciphertext, + ) -> MlKemSharedSecret { + multiplexing::kyber_decapsulate::< + RANK_1024, + SECRET_KEY_SIZE_1024, + CPA_PKE_SECRET_KEY_SIZE_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + CPA_PKE_CIPHERTEXT_SIZE_1024, + T_AS_NTT_ENCODED_SIZE_1024, + C1_SIZE_1024, + C2_SIZE_1024, + VECTOR_U_COMPRESSION_FACTOR_1024, + VECTOR_V_COMPRESSION_FACTOR_1024, + C1_BLOCK_SIZE_1024, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) + } } diff --git a/libcrux-ml-kem/src/mlkem512.rs b/libcrux-ml-kem/src/mlkem512.rs index e0e6447d..b2c5e057 100644 --- a/libcrux-ml-kem/src/mlkem512.rs +++ b/libcrux-ml-kem/src/mlkem512.rs @@ -265,33 +265,6 @@ pub fn encapsulate( >(public_key, randomness) } -/// Encapsulate Kyber 512 -/// -/// Generates an ([`MlKem512Ciphertext`], [`MlKemSharedSecret`]) tuple. -/// The input is a reference to an [`MlKem512PublicKey`] and [`SHARED_SECRET_SIZE`] -/// bytes of `randomness`. -#[cfg(all(not(eurydice), feature = "kyber"))] -pub fn kyber_encapsulate( - public_key: &MlKem512PublicKey, - randomness: [u8; SHARED_SECRET_SIZE], -) -> (MlKem512Ciphertext, MlKemSharedSecret) { - multiplexing::kyber_encapsulate::< - RANK_512, - CPA_PKE_CIPHERTEXT_SIZE_512, - CPA_PKE_PUBLIC_KEY_SIZE_512, - T_AS_NTT_ENCODED_SIZE_512, - C1_SIZE_512, - C2_SIZE_512, - VECTOR_U_COMPRESSION_FACTOR_512, - VECTOR_V_COMPRESSION_FACTOR_512, - C1_BLOCK_SIZE_512, - ETA1, - ETA1_RANDOMNESS_SIZE, - ETA2, - ETA2_RANDOMNESS_SIZE, - >(public_key, randomness) -} - /// Decapsulate ML-KEM 512 /// /// Generates an [`MlKemSharedSecret`]. @@ -321,31 +294,62 @@ pub fn decapsulate( >(private_key, ciphertext) } -/// Decapsulate Kyber 512 -/// -/// Generates an [`MlKemSharedSecret`]. -/// The input is a reference to an [`MlKem512PrivateKey`] and an [`MlKem512Ciphertext`]. #[cfg(all(not(eurydice), feature = "kyber"))] -pub fn kyber_decapsulate( - private_key: &MlKem512PrivateKey, - ciphertext: &MlKem512Ciphertext, -) -> MlKemSharedSecret { - multiplexing::kyber_decapsulate::< - RANK_512, - SECRET_KEY_SIZE_512, - CPA_PKE_SECRET_KEY_SIZE_512, - CPA_PKE_PUBLIC_KEY_SIZE_512, - CPA_PKE_CIPHERTEXT_SIZE_512, - T_AS_NTT_ENCODED_SIZE_512, - C1_SIZE_512, - C2_SIZE_512, - VECTOR_U_COMPRESSION_FACTOR_512, - VECTOR_V_COMPRESSION_FACTOR_512, - C1_BLOCK_SIZE_512, - ETA1, - ETA1_RANDOMNESS_SIZE, - ETA2, - ETA2_RANDOMNESS_SIZE, - IMPLICIT_REJECTION_HASH_INPUT_SIZE, - >(private_key, ciphertext) +pub(crate) mod kyber { + use super::*; + /// Encapsulate Kyber 512 + /// + /// Generates an ([`MlKem512Ciphertext`], [`MlKemSharedSecret`]) tuple. + /// The input is a reference to an [`MlKem512PublicKey`] and [`SHARED_SECRET_SIZE`] + /// bytes of `randomness`. + + pub fn encapsulate( + public_key: &MlKem512PublicKey, + randomness: [u8; SHARED_SECRET_SIZE], + ) -> (MlKem512Ciphertext, MlKemSharedSecret) { + multiplexing::kyber_encapsulate::< + RANK_512, + CPA_PKE_CIPHERTEXT_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + T_AS_NTT_ENCODED_SIZE_512, + C1_SIZE_512, + C2_SIZE_512, + VECTOR_U_COMPRESSION_FACTOR_512, + VECTOR_V_COMPRESSION_FACTOR_512, + C1_BLOCK_SIZE_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) + } + + /// Decapsulate Kyber 512 + /// + /// Generates an [`MlKemSharedSecret`]. + /// The input is a reference to an [`MlKem512PrivateKey`] and an [`MlKem512Ciphertext`]. + + pub fn decapsulate( + private_key: &MlKem512PrivateKey, + ciphertext: &MlKem512Ciphertext, + ) -> MlKemSharedSecret { + multiplexing::kyber_decapsulate::< + RANK_512, + SECRET_KEY_SIZE_512, + CPA_PKE_SECRET_KEY_SIZE_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + CPA_PKE_CIPHERTEXT_SIZE_512, + T_AS_NTT_ENCODED_SIZE_512, + C1_SIZE_512, + C2_SIZE_512, + VECTOR_U_COMPRESSION_FACTOR_512, + VECTOR_V_COMPRESSION_FACTOR_512, + C1_BLOCK_SIZE_512, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) + } } diff --git a/libcrux-ml-kem/src/mlkem768.rs b/libcrux-ml-kem/src/mlkem768.rs index f7b01846..ae076d38 100644 --- a/libcrux-ml-kem/src/mlkem768.rs +++ b/libcrux-ml-kem/src/mlkem768.rs @@ -272,33 +272,6 @@ pub fn encapsulate( >(public_key, randomness) } -/// Encapsulate Kyber 768 -/// -/// Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple. -/// The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`] -/// bytes of `randomness`. -#[cfg(all(not(eurydice), feature = "kyber"))] -pub fn kyber_encapsulate( - public_key: &MlKem768PublicKey, - randomness: [u8; SHARED_SECRET_SIZE], -) -> (MlKem768Ciphertext, MlKemSharedSecret) { - multiplexing::kyber_encapsulate::< - RANK_768, - CPA_PKE_CIPHERTEXT_SIZE_768, - CPA_PKE_PUBLIC_KEY_SIZE_768, - T_AS_NTT_ENCODED_SIZE_768, - C1_SIZE_768, - C2_SIZE_768, - VECTOR_U_COMPRESSION_FACTOR_768, - VECTOR_V_COMPRESSION_FACTOR_768, - C1_BLOCK_SIZE_768, - ETA1, - ETA1_RANDOMNESS_SIZE, - ETA2, - ETA2_RANDOMNESS_SIZE, - >(public_key, randomness) -} - /// Decapsulate ML-KEM 768 /// /// Generates an [`MlKemSharedSecret`]. @@ -328,35 +301,64 @@ pub fn decapsulate( >(private_key, ciphertext) } -/// Decapsulate ML-KEM 768 -/// -/// Generates an [`MlKemSharedSecret`]. -/// The input is a reference to an [`MlKem768PrivateKey`] and an [`MlKem768Ciphertext`]. #[cfg(all(not(eurydice), feature = "kyber"))] -pub fn kyber_decapsulate( - private_key: &MlKem768PrivateKey, - ciphertext: &MlKem768Ciphertext, -) -> MlKemSharedSecret { - multiplexing::kyber_decapsulate::< - RANK_768, - SECRET_KEY_SIZE_768, - CPA_PKE_SECRET_KEY_SIZE_768, - CPA_PKE_PUBLIC_KEY_SIZE_768, - CPA_PKE_CIPHERTEXT_SIZE_768, - T_AS_NTT_ENCODED_SIZE_768, - C1_SIZE_768, - C2_SIZE_768, - VECTOR_U_COMPRESSION_FACTOR_768, - VECTOR_V_COMPRESSION_FACTOR_768, - C1_BLOCK_SIZE_768, - ETA1, - ETA1_RANDOMNESS_SIZE, - ETA2, - ETA2_RANDOMNESS_SIZE, - IMPLICIT_REJECTION_HASH_INPUT_SIZE, - >(private_key, ciphertext) -} +pub(crate) mod kyber { + use super::*; + + /// Encapsulate Kyber 768 + /// + /// Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple. + /// The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`] + /// bytes of `randomness`. + pub fn encapsulate( + public_key: &MlKem768PublicKey, + randomness: [u8; SHARED_SECRET_SIZE], + ) -> (MlKem768Ciphertext, MlKemSharedSecret) { + multiplexing::kyber_encapsulate::< + RANK_768, + CPA_PKE_CIPHERTEXT_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + T_AS_NTT_ENCODED_SIZE_768, + C1_SIZE_768, + C2_SIZE_768, + VECTOR_U_COMPRESSION_FACTOR_768, + VECTOR_V_COMPRESSION_FACTOR_768, + C1_BLOCK_SIZE_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + >(public_key, randomness) + } + /// Decapsulate ML-KEM 768 + /// + /// Generates an [`MlKemSharedSecret`]. + /// The input is a reference to an [`MlKem768PrivateKey`] and an [`MlKem768Ciphertext`]. + pub fn decapsulate( + private_key: &MlKem768PrivateKey, + ciphertext: &MlKem768Ciphertext, + ) -> MlKemSharedSecret { + multiplexing::kyber_decapsulate::< + RANK_768, + SECRET_KEY_SIZE_768, + CPA_PKE_SECRET_KEY_SIZE_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + CPA_PKE_CIPHERTEXT_SIZE_768, + T_AS_NTT_ENCODED_SIZE_768, + C1_SIZE_768, + C2_SIZE_768, + VECTOR_U_COMPRESSION_FACTOR_768, + VECTOR_V_COMPRESSION_FACTOR_768, + C1_BLOCK_SIZE_768, + ETA1, + ETA1_RANDOMNESS_SIZE, + ETA2, + ETA2_RANDOMNESS_SIZE, + IMPLICIT_REJECTION_HASH_INPUT_SIZE, + >(private_key, ciphertext) + } +} #[cfg(test)] mod tests { use rand::{rngs::OsRng, RngCore}; diff --git a/libcrux-ml-kem/tests/kyber.rs b/libcrux-ml-kem/tests/kyber.rs index 7f22ba03..da3c1b09 100644 --- a/libcrux-ml-kem/tests/kyber.rs +++ b/libcrux-ml-kem/tests/kyber.rs @@ -1,8 +1,8 @@ #[test] #[cfg(feature = "kyber")] fn kyber768() { - use libcrux_ml_kem::mlkem768; - let key_pair = mlkem768::generate_key_pair(hex::decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f").unwrap().try_into().unwrap()); + use libcrux_ml_kem::kyber768; + let key_pair = kyber768::generate_key_pair(hex::decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f").unwrap().try_into().unwrap()); let public_key = key_pair.pk(); let secret_key = key_pair.sk(); @@ -18,7 +18,7 @@ fn kyber768() { "lhs: computed secret key hash, rhs: hash from kat" ); - let (ciphertext, shared_secret) = mlkem768::kyber_encapsulate( + let (ciphertext, shared_secret) = kyber768::encapsulate( key_pair.public_key(), hex::decode("147c03f7a5bebba406c8fae1874d7f13c80efe79a3a9a874cc09fe76f6997615") .unwrap() @@ -37,7 +37,6 @@ fn kyber768() { "lhs: computed shared secret from encapsulate, rhs: shared secret from kat" ); - let shared_secret_from_decapsulate = - mlkem768::kyber_decapsulate(key_pair.private_key(), &ciphertext); + let shared_secret_from_decapsulate = kyber768::decapsulate(key_pair.private_key(), &ciphertext); assert_eq!(shared_secret_from_decapsulate, shared_secret.as_ref(), "lhs: shared secret computed via decapsulation, rhs: shared secret computed via encapsulation"); } From 366c761dedcc1b732d578fedcabcd8430f27eda4 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 10:51:12 +0200 Subject: [PATCH 22/53] Fix `kyber` feature in `libcrux-kem` --- libcrux-kem/src/kem.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libcrux-kem/src/kem.rs b/libcrux-kem/src/kem.rs index ec03433e..578c7e86 100644 --- a/libcrux-kem/src/kem.rs +++ b/libcrux-kem/src/kem.rs @@ -41,6 +41,9 @@ use libcrux_sha3 as sha3; use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768}; +#[cfg(feature = "kyber")] +use libcrux_ml_kem::kyber768; + // TODO: These functions are currently exposed simply in order to make NIST KAT // testing possible without an implementation of the NIST AES-CTR DRBG. Remove them // (and change the visibility of the exported functions to pub(crate)) the @@ -386,7 +389,7 @@ impl Ct { } else { return Err(Error::InvalidPrivateKey); }; - let kss = mlkem768::kyber_decapsulate(ksk, kct); + let kss = kyber768::decapsulate(ksk, kct); let xss = x25519_derive(xct, xsk)?; Ok(Ss::X25519Kyber768Draft00(kss, xss)) @@ -404,7 +407,7 @@ impl Ct { } else { return Err(Error::InvalidPrivateKey); }; - let ss_m = mlkem768::kyber_decapsulate(sk_m, ct_m); + let ss_m = kyber768::decapsulate(sk_m, ct_m); let ss_x = x25519_derive(ct_x, sk_x)?; Ok(Ss::XWingKyberDraft02( @@ -594,7 +597,7 @@ impl PublicKey { x25519: xpk, }) => { let seed = mlkem_rand(rng)?; - let (mlkem_ct, mlkem_ss) = mlkem768::kyber_encapsulate(kpk, seed); + let (mlkem_ct, mlkem_ss) = kyber768::encapsulate(kpk, seed); let (x_sk, x_pk) = libcrux_ecdh::x25519_key_gen(rng)?; let x_ss = x25519_derive(xpk, &x_sk)?; @@ -607,7 +610,7 @@ impl PublicKey { #[cfg(feature = "kyber")] PublicKey::XWingKyberDraft02(XWingKemDraft02PublicKey { pk_m, pk_x }) => { let seed = mlkem_rand(rng)?; - let (ct_m, ss_m) = mlkem768::kyber_encapsulate(pk_m, seed); + let (ct_m, ss_m) = kyber768::encapsulate(pk_m, seed); let (ek_x, ct_x) = libcrux_ecdh::x25519_key_gen(rng)?; let ss_x = x25519_derive(pk_x, &ek_x)?; From d0740e30c31b8e5ca82f36f6a07d4438b82d0918 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 11:28:31 +0200 Subject: [PATCH 23/53] Rename NIST KAT files for ML-KEM --- libcrux-ml-kem/tests/kats/generate_kats.py | 4 ++-- libcrux-ml-kem/tests/kats/{kyber.py => mlkem.py} | 0 .../kats/{nistkats_1024.json => nistkats_mlkem_1024.json} | 0 .../tests/kats/{nistkats_512.json => nistkats_mlkem_512.json} | 0 .../tests/kats/{nistkats_768.json => nistkats_mlkem_768.json} | 0 libcrux-ml-kem/tests/nistkats.rs | 2 +- 6 files changed, 3 insertions(+), 3 deletions(-) rename libcrux-ml-kem/tests/kats/{kyber.py => mlkem.py} (100%) rename libcrux-ml-kem/tests/kats/{nistkats_1024.json => nistkats_mlkem_1024.json} (100%) rename libcrux-ml-kem/tests/kats/{nistkats_512.json => nistkats_mlkem_512.json} (100%) rename libcrux-ml-kem/tests/kats/{nistkats_768.json => nistkats_mlkem_768.json} (100%) diff --git a/libcrux-ml-kem/tests/kats/generate_kats.py b/libcrux-ml-kem/tests/kats/generate_kats.py index 7dd7530d..743532cd 100755 --- a/libcrux-ml-kem/tests/kats/generate_kats.py +++ b/libcrux-ml-kem/tests/kats/generate_kats.py @@ -3,7 +3,7 @@ # This file is a modified version of: # https://github.com/bwesterb/draft-schwabe-cfrg-kyber/blob/main/kyber_test.py -from kyber import * +from mlkem import * import hashlib import json @@ -87,5 +87,5 @@ def read(self, length): else: output_suffix = "1024" - with open("nistkats_{}.json".format(output_suffix), "w") as f: + with open("nistkats_mlkem_{}.json".format(output_suffix), "w") as f: json.dump(kats_formatted, f, ensure_ascii=False, indent=4) diff --git a/libcrux-ml-kem/tests/kats/kyber.py b/libcrux-ml-kem/tests/kats/mlkem.py similarity index 100% rename from libcrux-ml-kem/tests/kats/kyber.py rename to libcrux-ml-kem/tests/kats/mlkem.py diff --git a/libcrux-ml-kem/tests/kats/nistkats_1024.json b/libcrux-ml-kem/tests/kats/nistkats_mlkem_1024.json similarity index 100% rename from libcrux-ml-kem/tests/kats/nistkats_1024.json rename to libcrux-ml-kem/tests/kats/nistkats_mlkem_1024.json diff --git a/libcrux-ml-kem/tests/kats/nistkats_512.json b/libcrux-ml-kem/tests/kats/nistkats_mlkem_512.json similarity index 100% rename from libcrux-ml-kem/tests/kats/nistkats_512.json rename to libcrux-ml-kem/tests/kats/nistkats_mlkem_512.json diff --git a/libcrux-ml-kem/tests/kats/nistkats_768.json b/libcrux-ml-kem/tests/kats/nistkats_mlkem_768.json similarity index 100% rename from libcrux-ml-kem/tests/kats/nistkats_768.json rename to libcrux-ml-kem/tests/kats/nistkats_mlkem_768.json diff --git a/libcrux-ml-kem/tests/nistkats.rs b/libcrux-ml-kem/tests/nistkats.rs index e52cedc8..1e3a3360 100644 --- a/libcrux-ml-kem/tests/nistkats.rs +++ b/libcrux-ml-kem/tests/nistkats.rs @@ -32,7 +32,7 @@ macro_rules! impl_nist_known_answer_tests { fn $name() { let katfile_path = Path::new("tests") .join("kats") - .join(format!("nistkats_{}.json", $parameter_set)); + .join(format!("nistkats_mlkem_{}.json", $parameter_set)); let katfile = File::open(katfile_path).expect("Could not open KAT file."); let reader = BufReader::new(katfile); From 2af99c3c00b088062889910db07170f4a8281221 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 11:51:00 +0200 Subject: [PATCH 24/53] Include NIST KATs for all Kyber parameter sets --- libcrux-ml-kem/tests/kats/README.md | 5 +- .../tests/kats/generate_kyber_kats.py | 92 ++ ...enerate_kats.py => generate_mlkem_kats.py} | 1 + libcrux-ml-kem/tests/kats/kyber.py | 326 +++++++ .../tests/kats/nistkats_kyber_1024.json | 802 ++++++++++++++++++ .../tests/kats/nistkats_kyber_512.json | 802 ++++++++++++++++++ .../tests/kats/nistkats_kyber_768.json | 802 ++++++++++++++++++ libcrux-ml-kem/tests/nistkats.rs | 38 +- 8 files changed, 2865 insertions(+), 3 deletions(-) create mode 100755 libcrux-ml-kem/tests/kats/generate_kyber_kats.py rename libcrux-ml-kem/tests/kats/{generate_kats.py => generate_mlkem_kats.py} (97%) create mode 100644 libcrux-ml-kem/tests/kats/kyber.py create mode 100644 libcrux-ml-kem/tests/kats/nistkats_kyber_1024.json create mode 100644 libcrux-ml-kem/tests/kats/nistkats_kyber_512.json create mode 100644 libcrux-ml-kem/tests/kats/nistkats_kyber_768.json diff --git a/libcrux-ml-kem/tests/kats/README.md b/libcrux-ml-kem/tests/kats/README.md index 17024363..80f539a2 100644 --- a/libcrux-ml-kem/tests/kats/README.md +++ b/libcrux-ml-kem/tests/kats/README.md @@ -1 +1,4 @@ -In order to regenerate the JSON KAT files for all parameter sets, simply run `./generate_kats.py`. +In order to regenerate the JSON KAT files for all ML-KEM parameter +sets, simply run `./generate_mlkem_kats.py`. + +In order to regenerate the JSON KAT files for all Kyber (Round 3) parameter sets, simply run `./generate_kyber_kats.py`. diff --git a/libcrux-ml-kem/tests/kats/generate_kyber_kats.py b/libcrux-ml-kem/tests/kats/generate_kyber_kats.py new file mode 100755 index 00000000..f423b731 --- /dev/null +++ b/libcrux-ml-kem/tests/kats/generate_kyber_kats.py @@ -0,0 +1,92 @@ +#! /usr/bin/env python3 + +# This file is a modified version of: +# https://github.com/bwesterb/draft-schwabe-cfrg-kyber/blob/main/kyber_test.py +# It generates Known Answer Tests (KATs) for Round 3 Kyber. + +from kyber import * + +import hashlib +import json + +import Crypto +from Crypto.Cipher import AES + + +class NistDRBG: + """NIST's DRBG used to generate NIST's Known Answer Tests (KATs), + see PQCgenKAT.c.""" + + def __init__(self, seed): + self.key = b"\0" * 32 + self.v = 0 + assert len(seed) == 48 + self._update(seed) + + def _update(self, seed): + b = AES.new(self.key, AES.MODE_ECB) + buf = b"" + for i in range(3): + self.v += 1 + buf += b.encrypt(self.v.to_bytes(16, "big")) + if seed is not None: + buf = bytes([x ^ y for x, y in zip(seed, buf)]) + self.key = buf[:32] + self.v = int.from_bytes(buf[32:], "big") + + def read(self, length): + b = AES.new(self.key, AES.MODE_ECB) + ret = b"" + while len(ret) < length: + self.v += 1 + block = b.encrypt(self.v.to_bytes(16, "big")) + ret += block + self._update(None) + return ret[:length] + + +for params in [params512, params768, params1024]: + kats_formatted = [] + seed = bytes(range(48)) + g = NistDRBG(seed) + + print("Generating KATs for {} parameter set.".format(params)) + + for i in range(100): + seed = g.read(48) + g2 = NistDRBG(seed) + + kseed = g2.read(32) + g2.read(32) + eseed = g2.read(32) + + pk, sk = KeyGen(kseed, params) + ct, ss = Enc(pk, eseed, params) + + Dec(sk, ct, params) + + kats_formatted.append( + { + "key_generation_seed": bytes(kseed).hex(), + "sha3_256_hash_of_public_key": bytes( + hashlib.sha3_256(pk).digest() + ).hex(), + "sha3_256_hash_of_secret_key": bytes( + hashlib.sha3_256(sk).digest() + ).hex(), + "encapsulation_seed": bytes(eseed).hex(), + "sha3_256_hash_of_ciphertext": bytes( + hashlib.sha3_256(ct).digest() + ).hex(), + "shared_secret": bytes(ss).hex(), + } + ) + + if params == params512: + output_suffix = "512" + elif params == params768: + output_suffix = "768" + else: + output_suffix = "1024" + + with open("nistkats_kyber_{}.json".format(output_suffix), "w") as f: + json.dump(kats_formatted, f, ensure_ascii=False, indent=4) diff --git a/libcrux-ml-kem/tests/kats/generate_kats.py b/libcrux-ml-kem/tests/kats/generate_mlkem_kats.py similarity index 97% rename from libcrux-ml-kem/tests/kats/generate_kats.py rename to libcrux-ml-kem/tests/kats/generate_mlkem_kats.py index 743532cd..ac2f7bbf 100755 --- a/libcrux-ml-kem/tests/kats/generate_kats.py +++ b/libcrux-ml-kem/tests/kats/generate_mlkem_kats.py @@ -2,6 +2,7 @@ # This file is a modified version of: # https://github.com/bwesterb/draft-schwabe-cfrg-kyber/blob/main/kyber_test.py +# It generates Known Answer Tests (KATs) for ML-KEM. from mlkem import * diff --git a/libcrux-ml-kem/tests/kats/kyber.py b/libcrux-ml-kem/tests/kats/kyber.py new file mode 100644 index 00000000..55e611fd --- /dev/null +++ b/libcrux-ml-kem/tests/kats/kyber.py @@ -0,0 +1,326 @@ +# This file is: +# https://github.com/bwesterb/draft-schwabe-cfrg-kyber/blob/main/kyber.py + +# WARNING This is a specification of Kyber; not a production ready +# implementation. It is slow and does not run in constant time. + +# Requires the CryptoDome for SHAKE. To install, run +# +# pip install pycryptodome pytest +from Crypto.Hash import SHAKE128, SHAKE256 + +import io +import hashlib +import functools +import collections + +from math import floor + +q = 3329 +nBits = 8 +zeta = 17 +eta2 = 2 + +n = 2**nBits +inv2 = (q+1)//2 # inverse of 2 + +params = collections.namedtuple('params', ('k', 'du', 'dv', 'eta1')) + +params512 = params(k = 2, du = 10, dv = 4, eta1 = 3) +params768 = params(k = 3, du = 10, dv = 4, eta1 = 2) +params1024 = params(k = 4, du = 11, dv = 5, eta1 = 2) + +def smod(x): + r = x % q + if r > (q-1)//2: + r -= q + return r + +# Rounds to nearest integer with ties going up +def Round(x): + return int(floor(x + 0.5)) + +def Compress(x, d): + return Round((2**d / q) * x) % (2**d) + +def Decompress(y, d): + assert 0 <= y and y <= 2**d + return Round((q / 2**d) * y) + +def BitsToWords(bs, w): + assert len(bs) % w == 0 + return [sum(bs[i+j] * 2**j for j in range(w)) + for i in range(0, len(bs), w)] + +def WordsToBits(bs, w): + return sum([[(b >> i) % 2 for i in range(w)] for b in bs], []) + +def Encode(a, w): + return bytes(BitsToWords(WordsToBits(a, w), 8)) + +def Decode(a, w): + return BitsToWords(WordsToBits(a, 8), w) + +def brv(x): + """ Reverses a 7-bit number """ + return int(''.join(reversed(bin(x)[2:].zfill(nBits-1))), 2) + +class Poly: + def __init__(self, cs=None): + self.cs = (0,)*n if cs is None else tuple(cs) + assert len(self.cs) == n + + def __add__(self, other): + return Poly((a+b) % q for a,b in zip(self.cs, other.cs)) + + def __neg__(self): + return Poly(q-a for a in self.cs) + def __sub__(self, other): + return self + -other + + def __str__(self): + return f"Poly({self.cs}" + + def __eq__(self, other): + return self.cs == other.cs + + def NTT(self): + cs = list(self.cs) + layer = n // 2 + zi = 0 + while layer >= 2: + for offset in range(0, n-layer, 2*layer): + zi += 1 + z = pow(zeta, brv(zi), q) + + for j in range(offset, offset+layer): + t = (z * cs[j + layer]) % q + cs[j + layer] = (cs[j] - t) % q + cs[j] = (cs[j] + t) % q + layer //= 2 + return Poly(cs) + + def RefNTT(self): + # Slower, but simpler, version of the NTT. + cs = [0]*n + for i in range(0, n, 2): + for j in range(n // 2): + z = pow(zeta, (2*brv(i//2)+1)*j, q) + cs[i] = (cs[i] + self.cs[2*j] * z) % q + cs[i+1] = (cs[i+1] + self.cs[2*j+1] * z) % q + return Poly(cs) + + def InvNTT(self): + cs = list(self.cs) + layer = 2 + zi = n//2 + while layer < n: + for offset in range(0, n-layer, 2*layer): + zi -= 1 + z = pow(zeta, brv(zi), q) + + for j in range(offset, offset+layer): + t = (cs[j+layer] - cs[j]) % q + cs[j] = (inv2*(cs[j] + cs[j+layer])) % q + cs[j+layer] = (inv2 * z * t) % q + layer *= 2 + return Poly(cs) + + def MulNTT(self, other): + """ Computes self o other, the multiplication of self and other + in the NTT domain. """ + cs = [None]*n + for i in range(0, n, 2): + a1 = self.cs[i] + a2 = self.cs[i+1] + b1 = other.cs[i] + b2 = other.cs[i+1] + z = pow(zeta, 2*brv(i//2)+1, q) + cs[i] = (a1 * b1 + z * a2 * b2) % q + cs[i+1] = (a2 * b1 + a1 * b2) % q + return Poly(cs) + + def Compress(self, d): + return Poly(Compress(c, d) for c in self.cs) + + def Decompress(self, d): + return Poly(Decompress(c, d) for c in self.cs) + + def Encode(self, d): + return Encode(self.cs, d) + +def sampleUniform(stream): + cs = [] + while True: + b = stream.read(3) + d1 = b[0] + 256*(b[1] % 16) + d2 = (b[1] >> 4) + 16*b[2] + assert d1 + 2**12 * d2 == b[0] + 2**8 * b[1] + 2**16*b[2] + for d in [d1, d2]: + if d >= q: + continue + cs.append(d) + if len(cs) == n: + return Poly(cs) + +def CBD(a, eta): + assert len(a) == 64*eta + b = WordsToBits(a, 8) + cs = [] + for i in range(n): + cs.append((sum(b[:eta]) - sum(b[eta:2*eta])) % q) + b = b[2*eta:] + return Poly(cs) + +def XOF(seed, j, i): + h = SHAKE128.new() + h.update(seed + bytes([j, i])) + return h + +def PRF(seed, nonce): + assert len(seed) == 32 + h = SHAKE256.new() + h.update(seed + bytes([nonce])) + return h + +def G(seed): + h = hashlib.sha3_512(seed).digest() + return h[:32], h[32:] + +def H(msg): return hashlib.sha3_256(msg).digest() +def KDF(msg): return hashlib.shake_256(msg).digest(length=32) + +class Vec: + def __init__(self, ps): + self.ps = tuple(ps) + + def NTT(self): + return Vec(p.NTT() for p in self.ps) + + def InvNTT(self): + return Vec(p.InvNTT() for p in self.ps) + + def DotNTT(self, other): + """ Computes the dot product in NTT domain. """ + return sum((a.MulNTT(b) for a, b in zip(self.ps, other.ps)), + Poly()) + + def __add__(self, other): + return Vec(a+b for a,b in zip(self.ps, other.ps)) + + def Compress(self, d): + return Vec(p.Compress(d) for p in self.ps) + + def Decompress(self, d): + return Vec(p.Decompress(d) for p in self.ps) + + def Encode(self, d): + return Encode(sum((p.cs for p in self.ps), ()), d) + + def __eq__(self, other): + return self.ps == other.ps + +def EncodeVec(vec, w): + return Encode(sum([p.cs for p in vec.ps], ()), w) +def DecodeVec(bs, k, w): + cs = Decode(bs, w) + return Vec(Poly(cs[n*i:n*(i+1)]) for i in range(k)) +def DecodePoly(bs, w): + return Poly(Decode(bs, w)) + +class Matrix: + def __init__(self, cs): + """ Samples the matrix uniformly from seed rho """ + self.cs = tuple(tuple(row) for row in cs) + + def MulNTT(self, vec): + """ Computes matrix multiplication A*vec in the NTT domain. """ + return Vec(Vec(row).DotNTT(vec) for row in self.cs) + + def T(self): + """ Returns transpose of matrix """ + k = len(self.cs) + return Matrix((self.cs[j][i] for j in range(k)) + for i in range(k)) + +def sampleMatrix(rho, k): + return Matrix([[sampleUniform(XOF(rho, j, i)) + for j in range(k)] for i in range(k)]) + +def sampleNoise(sigma, eta, offset, k): + return Vec(CBD(PRF(sigma, i+offset).read(64*eta), eta) + for i in range(k)) + +def constantTimeSelectOnEquality(a, b, ifEq, ifNeq): + # WARNING! In production code this must be done in a + # data-independent constant-time manner, which this implementation + # is not. In fact, many more lines of code in this + # file are not constant-time. + return ifEq if a == b else ifNeq + +def InnerKeyGen(seed, params): + assert len(seed) == 32 + rho, sigma = G(seed) + A = sampleMatrix(rho, params.k) + s = sampleNoise(sigma, params.eta1, 0, params.k) + e = sampleNoise(sigma, params.eta1, params.k, params.k) + sHat = s.NTT() + eHat = e.NTT() + tHat = A.MulNTT(sHat) + eHat + pk = EncodeVec(tHat, 12) + rho + sk = EncodeVec(sHat, 12) + return (pk, sk) + +def InnerEnc(pk, msg, seed, params): + assert len(msg) == 32 + tHat = DecodeVec(pk[:-32], params.k, 12) + rho = pk[-32:] + A = sampleMatrix(rho, params.k) + r = sampleNoise(seed, params.eta1, 0, params.k) + e1 = sampleNoise(seed, eta2, params.k, params.k) + e2 = sampleNoise(seed, eta2, 2*params.k, 1).ps[0] + rHat = r.NTT() + u = A.T().MulNTT(rHat).InvNTT() + e1 + m = Poly(Decode(msg, 1)).Decompress(1) + v = tHat.DotNTT(rHat).InvNTT() + e2 + m + c1 = u.Compress(params.du).Encode(params.du) + c2 = v.Compress(params.dv).Encode(params.dv) + return c1 + c2 + +def InnerDec(sk, ct, params): + split = params.du * params.k * n // 8 + c1, c2 = ct[:split], ct[split:] + u = DecodeVec(c1, params.k, params.du).Decompress(params.du) + v = DecodePoly(c2, params.dv).Decompress(params.dv) + sHat = DecodeVec(sk, params.k, 12) + return (v - sHat.DotNTT(u.NTT()).InvNTT()).Compress(1).Encode(1) + +def KeyGen(seed, params): + assert len(seed) == 64 + z = seed[32:] + pk, sk2 = InnerKeyGen(seed[:32], params) + h = H(pk) + return (pk, sk2 + pk + h + z) + +def Enc(pk, seed, params): + assert len(seed) == 32 + + m = H(seed) + Kbar, r = G(m + H(pk)) + ct = InnerEnc(pk, m, r, params) + K = KDF(Kbar + H(ct)) + return (ct, K) + +def Dec(sk, ct, params): + sk2 = sk[:12 * params.k * n//8] + pk = sk[12 * params.k * n//8 : 24 * params.k * n//8 + 32] + h = sk[24 * params.k * n//8 + 32 : 24 * params.k * n//8 + 64] + z = sk[24 * params.k * n//8 + 64 : 24 * params.k * n//8 + 96] + m2 = InnerDec(sk, ct, params) + Kbar2, r2 = G(m2 + h) + ct2 = InnerEnc(pk, m2, r2, params) + return constantTimeSelectOnEquality( + ct2, ct, + KDF(Kbar2 + H(ct)), # if ct == ct2 + KDF(z + H(ct)), # if ct != ct2 + ) diff --git a/libcrux-ml-kem/tests/kats/nistkats_kyber_1024.json b/libcrux-ml-kem/tests/kats/nistkats_kyber_1024.json new file mode 100644 index 00000000..fbe8c2db --- /dev/null +++ b/libcrux-ml-kem/tests/kats/nistkats_kyber_1024.json @@ -0,0 +1,802 @@ +[ + { + "key_generation_seed": "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f", + "sha3_256_hash_of_public_key": "8a39e87d531f3527c207edcc1db7faddcf9628391879b335c707839a0db051a8", + "sha3_256_hash_of_secret_key": "ed1f6cb687c37931ea2aa80d9c956f277a9df532649661035c6e2f9872132638", + "encapsulation_seed": "147c03f7a5bebba406c8fae1874d7f13c80efe79a3a9a874cc09fe76f6997615", + "sha3_256_hash_of_ciphertext": "3b4a9eca3917a8f4b16ab748352c74d76d06fa30efc033973d841de84ad89387", + "shared_secret": "b10f7394926ad3b49c5d62d5aeb531d5757538bcc0da9e550d438f1b61bd7419" + }, + { + "key_generation_seed": "d60b93492a1d8c1c7ba6fc0b733137f3406cee8110a93f170e7a78658af326d9003271531cf27285b8721ed5cb46853043b346a66cba6cf765f1b0eaa40bf672", + "sha3_256_hash_of_public_key": "c9ede13be3dbb0edc3ab08226cae11771ff4c0b04a564b64a0d9ff10e373e986", + "sha3_256_hash_of_secret_key": "9b5876610793ae42f683d94f736d8d7e0e033bee588bab07a31c9cdb4ab99a5d", + "encapsulation_seed": "cde797df8ce67231f6c5d15811843e01eb2ab84c7490931240822adbddd72046", + "sha3_256_hash_of_ciphertext": "c89606e13bf52c34b2adc63474b6b3faec439e2a991873386d1e6ebf8768666e", + "shared_secret": "3aec4fc396e413b401bd85b5a7cf59c11cbe1e582e72dc5a1ddc76f78d395711" + }, + { + "key_generation_seed": "4b622de1350119c45a9f2e2ef3dc5df50a759d138cdfbd64c81cc7cc2f513345e82fcc97ca60ccb27bf6938c975658aeb8b4d37cffbde25d97e561f36c219ade", + "sha3_256_hash_of_public_key": "ff2546623aee72025fb6746fba736bae0e80e257e66edbf09d8d4dc11049cda4", + "sha3_256_hash_of_secret_key": "57155298b53d3af5d6db214dfa91a9e16f8d5de570bbff5dba5f4cd84098f255", + "encapsulation_seed": "f43f68fbd694f0a6d307297110ecd4739876489fdf07eb9b03364e2ed0ff96e9", + "sha3_256_hash_of_ciphertext": "695b1cd029f46716b6d5e932c2a333a8f73606699028378fb1712969ba0a73b0", + "shared_secret": "bb28dbed58aa9c42cdc40466cfd4d4043ded1b5f9def472ee328624e83553e4f" + }, + { + "key_generation_seed": "050d58f9f757edc1e8180e3808b806f5bbb3586db3470b069826d1bb9a4efc2cde950541fd53a8a47aaa8cdfe80d928262a5ef7f8129ec3ef92f78d7cc32ef60", + "sha3_256_hash_of_public_key": "25b786a67de17d61b2fc0e85a13924398aab931896b6174089569f08b7260687", + "sha3_256_hash_of_secret_key": "d188a2637dfe80dbd0fc25165eb4898923888a82c10f6ff0b8ddb5bf251c0650", + "encapsulation_seed": "ea74fbc3c546500ed684bed6fe3c496d3b86d2d6dfaf223969b942e9a8c95e85", + "sha3_256_hash_of_ciphertext": "a1e2a68bcae572cf0090bf7509eaecfe9111d6e4fbec293b005f33859c0c4cb2", + "shared_secret": "d9a0fb7050dad6fd23ba5ca15adff77a1f208c5b1964c244f9ba94b73a6d9c69" + }, + { + "key_generation_seed": "66b79b844e0c2adad694e0478661ac46fe6b6001f6a71ff8e2f034b1fd8833d3be2d3c64d38269a1ee8660b9a2beaeb9f5ac022e8f0a357feebfd13b06813854", + "sha3_256_hash_of_public_key": "d35e259a200d16048302df38d8e7f9e1c3352502c43f086fe166325048fdce9c", + "sha3_256_hash_of_secret_key": "020ba30e5832867a6db83cdb1e60ddf0b0a88fb33919edb84b246a345d11da6c", + "encapsulation_seed": "64efa87a12cb96f98b9b81a7e5128a959c74e5332aaab0444fca7b4a5e5e0216", + "sha3_256_hash_of_ciphertext": "40c577a3dc5556e2136de8886a9fc07341c96723b1024f5729e9c25a11bcd57c", + "shared_secret": "953b8fb7c2158df7534b5c466c6d100a3e14d46e647ec3c5bf563a96509a94ff" + }, + { + "key_generation_seed": "7ec408f52c9aa723d0c41d9987682a5f4ce6c9da7cd0215af60bbaf5484ab353a08ccf451b049fd51d7a9ad77ae14a81569df8c9bd3a8f1ebea86fdcfb823082", + "sha3_256_hash_of_public_key": "5a5db7d619be642bd87294527b3f859372b279a1e6074824d9632b5d7f616e42", + "sha3_256_hash_of_secret_key": "630f093cb1ff96bff76ede70e970a009a9e5d28fed660e68127d31c3b6dbdb2a", + "encapsulation_seed": "8a95d71228acaa5f9ae6f9d9ca8ae55fde296463b41083a39e833e37c4c90f88", + "sha3_256_hash_of_ciphertext": "1ca741e01300de795f093c1dde012da4e65a0b2318efc91120562271d0936a6b", + "shared_secret": "207a91bdd7c5e7f1fd578fde767622c8eef3da5fb22e01efdac9027702bc0127" + }, + { + "key_generation_seed": "c121915bfef6abdfc177dae2f5a24218f9abda2559afc6741b08e0e61ab433eb84ef52db5eaa6df8ec3a0bc5ffa730db0dde8c5f38f266d5c680a78d264a7b96", + "sha3_256_hash_of_public_key": "f0d1acd4fe1bd3bad938c23ec5a7f320766e01005e32769724abb4ebac578def", + "sha3_256_hash_of_secret_key": "664f3632f56ebc5c509931ff3b7e1845265e42a76e20550b683527d7d24e8df8", + "encapsulation_seed": "90d79d75d0bbb8921cf70d46bab497022a8e750efdc99e5f1bae653275441c7b", + "sha3_256_hash_of_ciphertext": "163d09ce875cc8045874854c728b6b176af9ac546726981447011c0a25333d55", + "shared_secret": "3085c3ad1416cc4ca4776b4f30ceeb60f3d1bb0695123fffb976a41ea9395d8e" + }, + { + "key_generation_seed": "d86634ecf96cc2603761e284c0e36734cedec64e7ff486469e38539c71141c5a99daf37400cfe59841afc412ec97f2929dc84a6f3c36f378ee84ce3e46cd1209", + "sha3_256_hash_of_public_key": "7008db565f7ab9c362dc38dcd3e30e5da873c559e9a9222710e8d2e7f6417ce6", + "sha3_256_hash_of_secret_key": "9e774cb57c18575de3ec6a9677e40626c2026e47c389c7a3dc5422d8a83b747b", + "encapsulation_seed": "be8a32f97b9a8d596382c02fa2a0eeebc15c083e970ddaa4f2622b91d6718663", + "sha3_256_hash_of_ciphertext": "4f335ef7b857979b27688be8386a664146767cc307dc98eee652531af49052e8", + "shared_secret": "dee2922d92d0f5ca0c3ce2d0e61c5dc9320d300e965ab48c44d467762c2f4e38" + }, + { + "key_generation_seed": "0610678ff4dc3128e1619f915dc192c220f8fad94da1943b90aaec401683a492da1804ddb5aa9b1c6a47a98f8505a49bae2affde5fe75e69e828e546a6771004", + "sha3_256_hash_of_public_key": "143b9c53320cdb1b7e8d71efd1f0a1ad5ad1e1ce84dd9fe7c92f19c926388e3c", + "sha3_256_hash_of_secret_key": "63707e33c30114732374ac21fd5be61e6dfa7dd85a36eef2e2bae6b3d0599a71", + "encapsulation_seed": "da2cfaf69e25b2a89ff2557bbb6f69e01d8e2e7bb27a7a1ce7e40fead16f33b2", + "sha3_256_hash_of_ciphertext": "3cf63f83ef3097c5485b56ab626953961a32df3721f8f3c02ad13861393c7bc0", + "shared_secret": "d26ea5a6a80f60c0f08438d9ea0fe654c0fff45c2018c95731f4f41172dc2d69" + }, + { + "key_generation_seed": "d322d56d8ef067ba1f24c92492b9c56df3a6ef54a304adc1b69913766a1ce69756047447b810cc094d400ab204cf9ae71e3afa68b88586ecb6498c68ac0e51b9", + "sha3_256_hash_of_public_key": "f2d009cde4abd55a2c7417c9341792e60eaa8e26b53a3aae805746401c4c446f", + "sha3_256_hash_of_secret_key": "2a53faa8053fa21b7b07a96ea259c052ef78746c5d53e2857e9f30bd20d3f2b6", + "encapsulation_seed": "511c2ab40782322c06111e144e505328c4e5bfc890a5980a2bbc44aeda4c738b", + "sha3_256_hash_of_ciphertext": "647eac1faf615a441833584b7d94960e7f443de126be077caf09f7904c15e6f1", + "shared_secret": "c15d1490ddc18f7cea71acbed11b3dd3b8fe7bd348d96cbc1bdc64a26e8583bd" + }, + { + "key_generation_seed": "2f1d8a3bebb34540324b9485fdf3d5be3b858f544abc3fc641b5728cafab03ba8d6c42e7270ee2b77b6045385f3d175984a0e260363166c73b0c70c971644363", + "sha3_256_hash_of_public_key": "1f06190bdfd692cf499be99bacc4beccf048c89926769f1b254cca9a9a44089a", + "sha3_256_hash_of_secret_key": "faa641eaff01077bd2fc261ccb91d5c3b468a940e25e8d5d794d564b663315c3", + "encapsulation_seed": "dca92dbec9b260dd97e8886f876862d6effc3b91fcf3fbc986cf56ab93ae79a2", + "sha3_256_hash_of_ciphertext": "c3cd179bebe14d52c58bba015717d6663701cb3ecd3488b06367cae41f0de2b9", + "shared_secret": "dc5895ca7269fe3b6385d062d0004777360d6daa7cccc10f6829e13900958892" + }, + { + "key_generation_seed": "31beda3462627f601cbc56f3ddf4424e1529c04737ef0ef2af6d7401f653b8a1812083bfa3b670e3eaf9b443702fb6db16ac1197656bbd61a8e25ed523b8d1e5", + "sha3_256_hash_of_public_key": "cc20155074cd7cbd43ec2380dc6a71b3a88c9a4bf168ab2bf426a899706fa597", + "sha3_256_hash_of_secret_key": "6084f1eb2fe4b9055d6004bfccadad7bd64f623595dd0b5e0c0100d647313279", + "encapsulation_seed": "57c170e691d7a914a901b9a11c62b8b569b3806427557a9dbac9faa720ec3641", + "sha3_256_hash_of_ciphertext": "d4a5e470764634f50f693c2d6e31c3bcbd19ba9905134568dd4402fff049d3a5", + "shared_secret": "6bd2d8e04aa7d13a4471e47f19b57680c69e07ceef5f8a3742cb12f685344567" + }, + { + "key_generation_seed": "cbdff028766d558af4466ef14043a1a9cf765f7748c63cc09dceb59ab39a4e4d8e9a30597e4b52ffa87a54b83c91d12a5e9c2cd90fcac2c11b3a348240411a4c", + "sha3_256_hash_of_public_key": "77fbe004761fc37fe7597638e5dae8b44bd44c8d6efa2893a0a84b104ace6ac4", + "sha3_256_hash_of_secret_key": "608099f3fa437094212b3aa2696d592a9ba45f697b9c1020b69ec1d6e178b76c", + "encapsulation_seed": "6b5a14e1473abf5a33d44975ca2088bd8fa6fddcb3f80e8fd5c45b9d90c24a5c", + "sha3_256_hash_of_ciphertext": "9fc1c57ca7c3ccb766c98f18c49ad03ee0d41ffa5655c6c8966b82f9e0835027", + "shared_secret": "31368c4d4868ab3f70c39958f6fd1fb362fda25d2036adb6eee383415bb4b157" + }, + { + "key_generation_seed": "4c04310bea66305c6ca8ba6b8f61ca96257a67663afc11761f13fb5c7b324b6b8aec87a9a79204cee2986867a2906eb851b734b8b22b91d6749b1a5f07c44e3b", + "sha3_256_hash_of_public_key": "49cbe8daa7dac02d7795e907b037e2ae56624fdc8d7c6320f9e1e69dd0f6286f", + "sha3_256_hash_of_secret_key": "de7838a99458b56d0f1de343315d1a7d460269ded85551f70335b1e002742b5f", + "encapsulation_seed": "40e593754e6eddb7f9cf176ba2d5fd1087c90ad377556d0b0f686537b1a3165e", + "sha3_256_hash_of_ciphertext": "6264e96d3a3159899d31d16508860587da7e61d579031ae28944387c46e58e33", + "shared_secret": "ee9ac7935801b07c6e475e293ecbb2fdc0fcb1843665a53025c643c48465d7a3" + }, + { + "key_generation_seed": "38a0d5f41d7dc1896efd1b45b0485634cef149828751b96087a0a6dd81b4d58aa2acf359556df4a2abaeb9dcee945829beb71185b4d6bd18b76e5668f253383a", + "sha3_256_hash_of_public_key": "a333d474be9bacbea4c301148be2ddf13c3c25d7e4f52447a549a27b6d12710d", + "sha3_256_hash_of_secret_key": "731e7c1597fcea477249114301154b9fda1050e71617827da0c9cc149c1cb99b", + "encapsulation_seed": "c152523abd8248bed40c3827bcf0f8e8127037a55c780695e2c28ea3e041a44c", + "sha3_256_hash_of_ciphertext": "13c02865e36cc827a5d8c3b07c0a0984533c84317c0a7e28f59419794523b07c", + "shared_secret": "b396f9ae0b1beec31e7a52be8d8795f690a4280b823fc06dd42d3d7ce3134c52" + }, + { + "key_generation_seed": "97b5665676e59e3538ebadaa8cd50df1f9fda1502d9894c616a946078e56b621df05318b5f655efe36f1b678cf4b875108a18db2fa312261caf839f84bd956c5", + "sha3_256_hash_of_public_key": "35d109f57ea2764642ea3473a4f192cedfbe153a37f131cdf447b60e92310eea", + "sha3_256_hash_of_secret_key": "0420ee0853629da644872d3e2a9b0a89c9dece1a6748247d2f8f39721af21e12", + "encapsulation_seed": "ad6466dd59f26b762fb02b19eedf5f79964da68bce0459b91c3a6ee5a7e01183", + "sha3_256_hash_of_ciphertext": "e5cb51dd1417b1510bcb7f1a52c14b071d97251eda2de0c29abc7ab1d8aa9d6d", + "shared_secret": "d1ff41379220844ae81b2192809078c2a9d3f49ff9141df683647b08916359a4" + }, + { + "key_generation_seed": "ef99224a03a85a46ef115474ec5b5d620da6795d6efcca4c9135d19958a9de62df7d92dda83e6b2ef4cce08c9134563063068a196d7b1a1a13623e48ae12528e", + "sha3_256_hash_of_public_key": "cd65fd07a78e48c1a02e235ec76fdb509cf9903a4f5a850c51d9d3fda383cc67", + "sha3_256_hash_of_secret_key": "951cf21e37dcba710b581e49a6df1c75c65186e9672d647e9cd7239eb4bb975d", + "encapsulation_seed": "1a4d5dff5847cfb48333e33bb00ca7301b144aa89dcd412ff5a3b1081d775b7f", + "sha3_256_hash_of_ciphertext": "8e5ee4dd6c1d3249c4e0cacf72d4b97e929c860669730ad3d3a1764212dada98", + "shared_secret": "bc0e3780c03425d7733c6f4fdf9d55a2d81e8d7e79e35b729000865b40cb2c3a" + }, + { + "key_generation_seed": "b12f6fd965ea9c5b947db80fc60c83d5e232dca82e7263027c19bd62e5a6ff550f6aa3e88f7fa8a96067f8cdaeceeac90c2d0b5e277e56e9c405ec9420c30252", + "sha3_256_hash_of_public_key": "376f022313718aba325ef4c3b720e2c3ab314ace74e983948ba2e43ee3a6ebde", + "sha3_256_hash_of_secret_key": "e697899409d15ce13113a2ad86448157a248ff0701b40eec11fb4afac7b9f2fe", + "encapsulation_seed": "34f44ec2092eeaf686f2ea170591a98527cbb03a4fa9477a7aef6b41a54feeb2", + "sha3_256_hash_of_ciphertext": "9b52835107c934d358599c3de0099bd45570d38ed4910ade0bac2de1bc9f9a54", + "shared_secret": "b24bc6d331106d8e3f565c8790420ac92b1d23dd6a271a4ebfd635dc3728ee5d" + }, + { + "key_generation_seed": "9f52af92ca165fdc38788f2b59ba02e01c8281ff7c1e60504688043a5fe814b04f3029e1be4e1c0258c3a22ff5b50b2674cc094ba7018da2a61569845c17d26f", + "sha3_256_hash_of_public_key": "7944e5d79dabf7b7259df5ced02669c81b7dc4590e0b10764729d812f6bd85d7", + "sha3_256_hash_of_secret_key": "301fb18a9ec0d975414abc4d41ed0c553e2b9aa2b03bf2765476e3288f760ee7", + "encapsulation_seed": "6250c81126572eec2da330271db36ee591f060fc7e53eeefe2e1c476c675fa33", + "sha3_256_hash_of_ciphertext": "5695c2bc334c888637c8c79d6bd05f3c7a015e6cdca204c5308571cbbdb82e41", + "shared_secret": "1168ef9238147a97f768ee253ab2a4a4df9969d4ff8551b39bde166bc26755e3" + }, + { + "key_generation_seed": "851ea90fd3854cbf28fe39fb81f68e4b14345cf0d6eee7ec4ce772513df8410d1c0ec046899a777655233e4e1b5ca44e9afbdc67964bfd5d5e3dbb45e60d03cf", + "sha3_256_hash_of_public_key": "692176b38737a053dce0551b63e3eca81884bbf95e1d8975671a2f7f1dfae251", + "sha3_256_hash_of_secret_key": "1ae55a55d87ea8d58b51f842c7d6990a1ae6932eccf5c39e97f56bb481a16b7d", + "encapsulation_seed": "35d470bcc5880872754810dfb3f2796da2fd7f397537146f6488c27804072b34", + "sha3_256_hash_of_ciphertext": "a22d48f06df9f98e77e3fc64ca1355de735adcc29a37891b5e36777dbe33b0a6", + "shared_secret": "65d7e1e9e3dc7b7d771f1431bea4369363f637876b44cf216e48f6727cd28fad" + }, + { + "key_generation_seed": "d304c9389cc973477f169788abcb9d511f843219d246a9b587822f422a70c2386590a2e5c7ed86cf2c5c2a898662bc9a81418720bbb632ef9cf0b845ed052d73", + "sha3_256_hash_of_public_key": "2f54bedb19919171eca777186dd743b11ec9489aea09534c157faa75adf1c77c", + "sha3_256_hash_of_secret_key": "4bea180ffc80875ac731f18365224bd3eefc8d11fad63c7376adc1a37adc67bc", + "encapsulation_seed": "8d667921c5db401a86fe1c35dfcf164a6bb2ab7400fd6a0b67eafd4a0ed11940", + "sha3_256_hash_of_ciphertext": "1eee3c3fdbc3a6b9a70390e4622162bcdbf81407a21fb7f8cc2f320d1a4e79ed", + "shared_secret": "dfa5f13aa7a56c3ed635a7cbec48809c249ba3afbcaa011f3a025695d2932a93" + }, + { + "key_generation_seed": "89a6e3be304a3518fb82b18ca730f0b359cd6ba90664a493fb4f8edaf965b9c3b6591121e25d64010c25a18676033e1d7278ac5f2d0b43a31f3a4156ae710465", + "sha3_256_hash_of_public_key": "7a9232085a0222b9c863931ec3bdbdd51be3f16d6cab3009c138e0c8cb692563", + "sha3_256_hash_of_secret_key": "a01d03ab913ef4672c49664d2c95fecdd98fcfc19e8d8b839e79a8f6fb9bdf42", + "encapsulation_seed": "ec750b3939385a3f8df868119dc76f77ca845567ef068de6ada5478a56bc78b6", + "sha3_256_hash_of_ciphertext": "b008f548e3fbb6ab4d9a10bedada76495e821011290afef063dbc201dd73f9ce", + "shared_secret": "c9902be6478ce7163a27b1ce28a24cf6f07d6c5600a6acf50faf96ad387c186d" + }, + { + "key_generation_seed": "d569b935ce015c85f792f8f7fb0d83c4f53b492959361dd4f75fb764d656450176eae84d11c4528382828f7a689a0d5cff87b8ca0bba97feacb39b935a8788cb", + "sha3_256_hash_of_public_key": "1642d52117145ea2956bd5e446b895609be84a9344ff0f5cd1ec62af9ea9e3c0", + "sha3_256_hash_of_secret_key": "e2d190c6c423252af301186a3e49892da8c22e4c0fb61586d119119fb7b07447", + "encapsulation_seed": "74f1d52af09b12c36eb062ea7528550cb4c18a3ce8e4f4ea9fac43ae383bc925", + "sha3_256_hash_of_ciphertext": "d77c9d3ab74bcdb2f5015264a6537606dc4941924d31cd4bebf2dedca4e72baf", + "shared_secret": "1104d6f33bea854d9265b80561bdbf67e81c2fd90912203f04d7e833e1b2e9b3" + }, + { + "key_generation_seed": "5cbb141c2763425c274f7404fe530d9116e08c33f9f200a20b011cf563a28990fc9ebbe336dc464489861db8253606971bd0a9008a433ed17752d04023781552", + "sha3_256_hash_of_public_key": "0163017a26dba83777c4c0f46f31375ba02680ffaba588a9fe91f97ccb99c445", + "sha3_256_hash_of_secret_key": "5d101bd4f51fad047a1161e7a95197f6307e7cb88e57fcf9fb28a2be43e9f4a0", + "encapsulation_seed": "4b3a70d85f640d1a2a852fb6fe96704af56a7415a8ee4282e9207bc3a2dc116a", + "sha3_256_hash_of_ciphertext": "bdd1c2f26d438576136c92a92397d4654a2bdf4962584752169c59796167e291", + "shared_secret": "67dc4e3d4eb4585613202d538edcfe5d518117d2efbafa083a27713f60822c73" + }, + { + "key_generation_seed": "293abb6d1c207927945417cf84883ef010823e11b487ed55239e466e83696d0cff8563038aad865a817cab9ce98846ba75be9363718ecf5fea538aea90b2a558", + "sha3_256_hash_of_public_key": "fb21cf5cc9a8a47a07cb2a154f73676d39a98a7d12a4abbd37378595c6332f46", + "sha3_256_hash_of_secret_key": "3c5041ff25ab5e854e792eccf12721be4f820020ed7895d5ccb7b1ba4bb7b193", + "encapsulation_seed": "26e38ac804fb5b4d59ddf747715e7e6041d875f99c7b638024b4af82d622da60", + "sha3_256_hash_of_ciphertext": "fda640c9a9002cee1068e78200396885ab74fec7ac428412b9d191bfd5990a3f", + "shared_secret": "d008c11b4327b0d63319a59190909a2c98d71c3fcd0a47e9417b93af6eb66478" + }, + { + "key_generation_seed": "74d87c7556f2671f2d666854a4d6e073e69f35421e6e1a428cccea49c37f972ce1fb7456ac0aa1b97068f452cba64ebdc138bcf5d36b0a0fada2a3b374141eb9", + "sha3_256_hash_of_public_key": "591aa9c81277503a34441fbd6cb59c6d1ecd5e00298fa56be9df562576250c52", + "sha3_256_hash_of_secret_key": "2e9c26235e0db1383671ad4ef147c1cbe3724bf800be90e356a5a381e3d9aa12", + "encapsulation_seed": "a319d2b8f114f1acd866478bcdeba6fd164dc4e37b0adfa8d8034afb3e197376", + "sha3_256_hash_of_ciphertext": "e23e0b671fe8dc8b38963e5dbab1af524144761d3e4218777cf9c62ef7319537", + "shared_secret": "22986ae60ee717cdd419998306b2da0457e110bbbfb9a2759fc03b8b0d161b2f" + }, + { + "key_generation_seed": "013bab0212d04ecd54b478daf72748003a25e2cb060ba6cc50bf95c292b8206b9da0c5da5f195b80fbb99c2e8b06926074f3f604b3f6195b5a5b9737876bba72", + "sha3_256_hash_of_public_key": "1c6c4009e28f6a20aad0c0b14b7cc0a01aeca507c366913ba5cadefe6656881b", + "sha3_256_hash_of_secret_key": "a9d3487d20af12309fb8d12b71a3fc3ad9109a9cc2720a0fa409ec5a491943b4", + "encapsulation_seed": "ff646071b2509e6b75790917e08e4f0b0d9f0116ec6291c0b59eaa4b583ad830", + "sha3_256_hash_of_ciphertext": "4993e4f6ea933144d7bf87c31bc79a92f3419411e0305e7cef56a7e5c7c24c89", + "shared_secret": "3f34cd3501e04109a0ffa0adc0cc672069f2aa1537faa068ad2b7c2dd0ed5fab" + }, + { + "key_generation_seed": "ccb073c4b90be0ad746e26fb093b60c70110bd1dcbcddb566a8cffb7b3caf80e71600a8982c350df524cde514431ded7aec23576530894bcbf0ec0bfef0bb64f", + "sha3_256_hash_of_public_key": "4576536d1bace29aa7c31f7681222ddd15a3cf6ea6bbd3528d2ec8610d68d134", + "sha3_256_hash_of_secret_key": "0f1d74d5cd2fd6a9aa7022a0f06bdb6272a0bc23f115796d6e04692aa44de4ab", + "encapsulation_seed": "0584270ec26f3b9818e4af074d17b2d51037cc8dfdcbe3b140fa4fed5deebc54", + "sha3_256_hash_of_ciphertext": "7e6726f4bbe0b0cc6b18a7efd867bfd988b8dd23ff2470d612278db1a77f4242", + "shared_secret": "170505edc8b03388021abd5ed71722f30e62e576cd987cab139d3f5220947ae2" + }, + { + "key_generation_seed": "2e889f44e28901e9ac7ca6b2fffcb124c8979401b17064d7e1d51a7e3c3adbfa0e145e44aae52cfc609e6f47fd7a6f6af877190ff52256d0ac5b05b89c3f449f", + "sha3_256_hash_of_public_key": "eea5db7a82254d19c0a0c552ccc92db9c3eef74cd73a9937b7b7298171313f12", + "sha3_256_hash_of_secret_key": "d4d3196a516686b8da051e915241f141b04af55e83effb968c52f23a19ccf79d", + "encapsulation_seed": "51e05c7b4ca3079781e8293f4eccebeeb2f8c8b4c59468eddb62a21bcb4ab8a3", + "sha3_256_hash_of_ciphertext": "ef8ca2b7c36fd3f069098d94bb5ce143afa2e82a3976c7bccb35f9607208712f", + "shared_secret": "e2fda1a40d6e1370c60514b2eddf7297bfeb6b4f191f12a19e5c9b2e51470e53" + }, + { + "key_generation_seed": "174aaa36410566dc15a5e62874218d7abdde0b2c0f30d877bb80b1abd5f5a0a450a7a2354f7e5cefa6f4a4e9a1c411eb9364506e9e1204a8acb3cb77fbd2c4ed", + "sha3_256_hash_of_public_key": "72998cc3abc79487ca0a4db5b17514e9961916d30ab9b500430ba748c5c79226", + "sha3_256_hash_of_secret_key": "362b40ba4e015b703f639f4c784fa9f114f2cf65de5f6645e8f9d37fb33fd044", + "encapsulation_seed": "9eca0fe36c80fc5eba171c3ae66a5b1c923faa50b4521bb055e7bf51005c93df", + "sha3_256_hash_of_ciphertext": "b25c8a294a071677e6a53f0cc9a8c516bacf73b196cd8de8490a2a536a0017b5", + "shared_secret": "9b914b57afc8bd71637a6c65c1052610715ff70a9c06ddc2574a45502c75b1ae" + }, + { + "key_generation_seed": "351fe4313e2da7fac83d509f3103caf7b4c64a4d458fefdf636785ac361a1390f072d9b5a99f9c7a0a011e4dc10f6b600d611f40bba75071e7bee61d23fd5eda", + "sha3_256_hash_of_public_key": "e9631b6d4237dd6884ae3647dd8622fc13d1cc689f3c8ed94ec6bcd4bbdb6980", + "sha3_256_hash_of_secret_key": "96736bf10a73d079e56f5812f65e3465957b8228423fdae4059feaf918fba361", + "encapsulation_seed": "0c5719261caab51ae66b8c32e21c34e6d86ee4aa127d1b0195663c066497b2e9", + "sha3_256_hash_of_ciphertext": "0fa08baebb3961a88e535bd943badd601670d41499048321d5a4a92dedfa75a4", + "shared_secret": "f95c6e4a06a4d5234995e4ff44a4d5a5761ded0019d920b87a33d3278ac1cc92" + }, + { + "key_generation_seed": "9bc5315580207c6c16dcf3a30c48daf278de12e8c27df6733e62f799068ad23d5a4d0a8a41c4f666854e9b13673071ceb2fd61def9a850c211e7c50071b1ddad", + "sha3_256_hash_of_public_key": "847db13de94d97a88d5a3deae31c246f5f04d0c7d7f337859e024764337a08f2", + "sha3_256_hash_of_secret_key": "7fc950abb115ea2236036c300c95c76015606539ddd2409ff1b39a99b86a179f", + "encapsulation_seed": "0e59f6f9047c784c1f00b24454aa4f1bd32c92ae7e626549972f86fab90e7e89", + "sha3_256_hash_of_ciphertext": "f4be0269cc8da29550303f174f25b6a8be0b2bcabf8fa84e1e894540a9112179", + "shared_secret": "2be43591adc5cd2f992823123e497907fd235cbfff86339de365ac045db694e0" + }, + { + "key_generation_seed": "d8b907b34d152ff8603b73051f772daa71eb902c47b7e2f070508269d757e02e36b817736cbc5f7b1dd6eef5fe6332fb1a598f3871e5470d440fd2ea631da28a", + "sha3_256_hash_of_public_key": "f122b76b83c343de27054985634387fb7138f6f6f105cd4cd3f5b02698a964b0", + "sha3_256_hash_of_secret_key": "620b4d0dc53a26e175c69ae7a8f2d749d4adf1d0429852b84839d334e024ab06", + "encapsulation_seed": "a3963ade17d69debbc358dda82c7bebe2c39d25b36813058e7a161542e3f8c2b", + "sha3_256_hash_of_ciphertext": "5efb276bc704d163e858138ab836bbf15cff2a1f575286cc90ed90e98ed43510", + "shared_secret": "589b27be9d14aac5ecf7bfe7c79ea45bab8d5efeca465ca196d465ed34bd6665" + }, + { + "key_generation_seed": "684a29e4e5480a5f2533e1526b5fac8cdf5927f3d85087c71f928c59690eb56575d12195ec32a8686d0600e45d4a7f54219b0d7a3826d193a51b9156ecf2edd6", + "sha3_256_hash_of_public_key": "4c3182ca7a48afe60eb85790dcb50b8005b568921dbc724130b0ce83f1278454", + "sha3_256_hash_of_secret_key": "44b1c2b3487cdda8a8e9205d95dca710093e981e7bf2ea30d1d2502b164375fd", + "encapsulation_seed": "97beafabf2c8575586487c7a80e8af5fc50f94b6051c1bc66a5ae9f66be3cea7", + "sha3_256_hash_of_ciphertext": "fcab4491c00769c4d306a8c825900e178a4b78664fb0e8d4d900ba19cc4d4597", + "shared_secret": "2b4baf07f9e610e5c0265c51b5ba491ec5893bff7a3995c2d690ab7e15cc4454" + }, + { + "key_generation_seed": "d76b3573f596eb286ab5231feec7499686b13021be36cb126c7ebeb9d7030daf248c0a21ea0bb6d6f56f12300e8584d8e9a34e0e6f52227281151ae4c305fb8f", + "sha3_256_hash_of_public_key": "4359601c371b50b50b5306de33cfd476d3b5f811700dc4918beb345840244e3a", + "sha3_256_hash_of_secret_key": "6f2d2c913b4a19bb07b531d74edb549659a35d1330b1ddd62c74dac4bc5f061c", + "encapsulation_seed": "75461decd34c50d6a094b4a64fb75e5e9479f8f9250d82bb7d729dedeb2d4b65", + "sha3_256_hash_of_ciphertext": "88b652c98f58813ba290facd042d403cf500fd7d65e862eca6b2283e914a96d4", + "shared_secret": "f11f5bab28d73428bbb6c025aadce95ab7eeec3393c5a6ea4d6949b5be86b34c" + }, + { + "key_generation_seed": "b87439fde81c9e39eebe7cf741c685785532c1dd23e8ef868b9ce7a541010f3d1646460817a0fce5836bdfe124a7448e7adf7b8ecc2652ac6d280e986682df71", + "sha3_256_hash_of_public_key": "e1f6c5a99a49d6b1b4aa18089439bb4c56ca465785bb36594ef2ebd3af20d564", + "sha3_256_hash_of_secret_key": "fcc14cdacdcebc6d1933f1ec9d430c643ff5fdbd78d2fe053a8880e6ee8ef129", + "encapsulation_seed": "2607dcf4fd6ca1c614c21b5e37c24981c32b91c8c3e6955777da8a3f5d9c9335", + "sha3_256_hash_of_ciphertext": "d87c8a19140ea024bdc3015e8c9a84127d8e07c265db181acafb717565005a80", + "shared_secret": "802e384b54ea191c7ed1f6c3c6db5a88f9115994858a1c1b9cb3f604e0935f99" + }, + { + "key_generation_seed": "056661b38038da4fdd7426f32a81576c73ed84843b305168a374f934e27a4e1b79238a80dcfd7c992d84b2dffa67493e669243d4fa38c46b090bdf86bc548411", + "sha3_256_hash_of_public_key": "b8aa8568431ffc4681caacecd4475c838cf7348402a06413e7a9590ba405ea5e", + "sha3_256_hash_of_secret_key": "f1e4bb0178d949637c06e252493235480d3ed16687e9a1c36df0721b29a7573c", + "encapsulation_seed": "38c89bbe7145c29e9a831c11431eb9929cb24fb4992db20737e4687d397fd732", + "sha3_256_hash_of_ciphertext": "61e77e2a20c5882adc9fb369e47ac23fea52a31a2aea4c775bcc28f0eff0f776", + "shared_secret": "c139ba708b0161bc7ab3f9b96186cf08ede5bee39c86b519937ef265543b3270" + }, + { + "key_generation_seed": "a1b52d871612a1c611ae0944f9e71858f35d3bd14f20e96a931720668bdf0a6b1f135cf64b6403e103afae34da038613e2853bbfc36baafa3c6a95347193f37c", + "sha3_256_hash_of_public_key": "984f4c4ef2371654067ce0f22bbe4648dc9d87eee23842f31affcdc36328e8db", + "sha3_256_hash_of_secret_key": "240fe3ab98047b1985b22240622da9669f7ecec81801861ea0859704f3263f6c", + "encapsulation_seed": "b2c35e33c72d90182791f0e12a0324f5b216efcab2c8da1bee025dfbe13f4152", + "sha3_256_hash_of_ciphertext": "1b096928204d7f2595801113d8a15d6c7d341cbbb0eede43d74416bdad31ccb2", + "shared_secret": "9be0c520666feaf2932e12b7178b26fc54633b1ea32074056759661700f65592" + }, + { + "key_generation_seed": "952b49c803d6d6fba69f4375adce8594847a00bcae2179da49af2aed0423250262d7033947ae42ca53522a65fbafe18d3bc3e0cb66164e9a094fe4b44d8977ed", + "sha3_256_hash_of_public_key": "74841a59db1202eb2e3744bb36b9c5a229a33cf9eeafca4b3d02d155d870b6bf", + "sha3_256_hash_of_secret_key": "e808e7b999c5bedc14a1763428a3f2b3eb9c3f90743f8a1922c87b5874acd79a", + "encapsulation_seed": "afb7d6dc2b7eb6d84acc080c1be63c98afe7b07786b5801f716444a3e8e64800", + "sha3_256_hash_of_ciphertext": "a4c04032d6fc71606f6a7055ad7d9c2784f7dc9254aeb89e4d6c9f8d6cdb37a2", + "shared_secret": "b21993d37cec0783b0bd10aa4db79733ebee78bc3d1d362dc328eb328e68047f" + }, + { + "key_generation_seed": "3c815e57e9233e975fa1630208aab206b71ae0db37a7a8789ac683d9f9b2d29801c8e376fdb140ee343106c093af7cb149b316ba79446ceb4e5e0cedb9b164f9", + "sha3_256_hash_of_public_key": "f7243d71bcbb46b9a423431b3b30947eda5fd81b526cce79a36730d8ee1be42c", + "sha3_256_hash_of_secret_key": "b1e6993caef04e00ffcf42c81ae97c6d89c5c19bc3b3e1235c48829151f8b4cd", + "encapsulation_seed": "28f5e9dbda122b2cf8f3754fe9e0c73a84ad4b0c093522e0b62cf815d60bbc3c", + "sha3_256_hash_of_ciphertext": "fd3c3dfada2fbb87dc522d773dc3e89a7cbf3f54d524b3074c42267597fecb54", + "shared_secret": "e1aa7fa8a3e874ea0ed429fdf2aba8ee91fff9f5ec99fd81af82cc16ed8195dc" + }, + { + "key_generation_seed": "588760826dcfbd36d9abe6ae44a669bb3ebba6a218eab69e30f18a3bd536576e0e860576285483bb5fd36e2f944d32c4317bebc1e441470c1372046a790d79d4", + "sha3_256_hash_of_public_key": "4092d5afa2f038f879184f7344800ea49a63543be9600bdc2b18420744588290", + "sha3_256_hash_of_secret_key": "18b8bfec268d6e1d6edd376689f2bc5ffbcdc859cee0a26ccf550fb42863d57d", + "encapsulation_seed": "b0d713cbef0bb1df70cbb425d1e9373e9f7790fdc7980cc96a240dfc53f1e8e2", + "sha3_256_hash_of_ciphertext": "ce94ef74ba48ec48556e950a0d6dfae433b7fdebc77ad05f56d8885837b3e7d4", + "shared_secret": "85e65c7a43f95e355bb62793fd9ff5e0a3c0f881fc8ce6b815e7f951730d5cb4" + }, + { + "key_generation_seed": "47550e9edacb6ddce3d9ab81f6b61080dd4f2693854acb05e0ccc7a4fb6390fbf89d7d99d5c3e0d10d6ef9af054d842375f695abb28e3b8eb495100f04306e92", + "sha3_256_hash_of_public_key": "ad7166f31b2650d125c8ef23b5825fe11afe25d0cda306fa6c7a824b4c2d31d4", + "sha3_256_hash_of_secret_key": "0124d8202fcb0c40d7a6cbc1570df65602f376854abd55ea664f66e3923b3d56", + "encapsulation_seed": "32bdcdb7059fe27f6409901980c080308951ffd90deffa8317b4d213a5f04495", + "sha3_256_hash_of_ciphertext": "3241cd305f4d966217bebba6ae23ccb082dc5617a1f49f1f4243d2c4f466c704", + "shared_secret": "31d6f79da3364c96f9018ca27b246664791c0298a2c40a9df0d6bd34d64a5496" + }, + { + "key_generation_seed": "610afb64be8cc1df288cfb016ee2f44c6c07113de7f6fee071fe0c3fe31c6215cd292e4c5f9e1a55e0489bceffb204d672a6215f4f3980a646d9f880817c52dd", + "sha3_256_hash_of_public_key": "37933cfd8c0e61085f2ae264d85c4ae05f8bd40bf29976c6d52e4f1c7ff709cc", + "sha3_256_hash_of_secret_key": "e9a6c0af326ca00c7f8ee0b6ef5661be3a84c39165ff60fea5510cb219b8f788", + "encapsulation_seed": "4ed7c92d83bd03b2a25b567f17ae55542e2f6a4308ec0f3fe69f8ba5ae24331b", + "sha3_256_hash_of_ciphertext": "82ac8cbc21994315a3e60a0948e6b6684171fac229efb23d534f3ceee64d8246", + "shared_secret": "c3ff72eb1114344fa5d98aa74748b41969eab37294549def838be8ae19c446f8" + }, + { + "key_generation_seed": "e1953800acaa85ac02a906c72cb8e8d704e8d27820345f88f71e89c1f549afcc8c64c049c6dfc0f1476cffd520b055756162f7ec94243de6b14ac0b9e5fb366c", + "sha3_256_hash_of_public_key": "ae96ec4edc7ee08108fe6c0411a96f48731066ae4be12edeb7fc667039c9c1de", + "sha3_256_hash_of_secret_key": "7110c8c6d14a3cf5dba3e5f2ecda1ed1490e62b032f798139b779054da20985b", + "encapsulation_seed": "060ea5d2ed1dd88144a9885e79278590821c22917b55a48920f96b53ebe0e689", + "sha3_256_hash_of_ciphertext": "6d2073b4c1a798af03da8eb9eaf0907cc4817808d5268b11591fbd0adf52b6ce", + "shared_secret": "38b3b33fc6be0f25028865627cf3f9b60139e30b0623b70377aaa6c603f3e571" + }, + { + "key_generation_seed": "c719f9b2d16399b7326ce4eca30dabefe8fdaab18e9f6df888b0a134ef355570e40771856eb77e4633504899fcb86c6a3d433d0b8d60e26f07bd61f1d4ed69bd", + "sha3_256_hash_of_public_key": "4e23909b028699d6677eabe6bac4bc4e8437acbc52b0b17f1df5760c0455c2b5", + "sha3_256_hash_of_secret_key": "63ace19297953d106cbc1df1a25143a15772197c05aefb070825ef568eafcf23", + "encapsulation_seed": "10ef9426f8c4a13b52325c5bb4ead4596ecf2c6b5bd2d37d8350e90d4164fdd9", + "sha3_256_hash_of_ciphertext": "0c651d8e460ceb4d895618184c0b48e5130a01364be008c85ce6c06da3946320", + "shared_secret": "2255d629619de2e544267385edf2f0cf366d83909ffcf7132568726c85e7afef" + }, + { + "key_generation_seed": "e9acbb774be970206c3a738e243b420805a509fa59fa902044be2f0d013650d2ded5edaec5de3bf5b4d7c2f2e18e87f499c1968993eff196753db8045e2c8ba8", + "sha3_256_hash_of_public_key": "513906f5bef81445bd210d63fc4c9b9ef0b61c17b0cd5b229a45908fcbaddcec", + "sha3_256_hash_of_secret_key": "11added546dd697edc51e8ed16ca3ccc9da9629c4ce0c8404d04de1aa8b8114c", + "encapsulation_seed": "a4bd30a64cbf29a4e290fa1cc1dfb99e68348713041e4409a1af23c5d80c15c4", + "sha3_256_hash_of_ciphertext": "21906df021021e33c801c45b67d8d0425db03ec3e4eac8ba722250cf96f9e598", + "shared_secret": "17e56d297d325d3af453c1e27482b904e2462b166231e194788244c063bf7b5c" + }, + { + "key_generation_seed": "c1b3cbffad4b306f9af0cdd3028876486dbe858875c9b6497fe20172a986c82b1c96249919cedc2369d8d739ab125e0d2ccb82dfebcd90240a545cdfe07511f2", + "sha3_256_hash_of_public_key": "4f8b3e9ae47d3b5b95c080d4f18440c24b0691c19f06f5547554697bdfe97b01", + "sha3_256_hash_of_secret_key": "cf4be19205cf0c2bd0eb0c1e7aabd40e265792bfc302bb0f28716c406585ca37", + "encapsulation_seed": "f4b66a7d3b65b896dfe100b2cad24b175a1168cfd2ae11fd704b835f6bcd311a", + "sha3_256_hash_of_ciphertext": "57d051505fcba8f74b2154be8fd6dcc22cb5e4b615153976979a39f64139441b", + "shared_secret": "b2c21f10ff58773d24d46aaa3bd18bec534b9c6cd52ab7ee5850309b06251248" + }, + { + "key_generation_seed": "ff7495b8575b5a98e4fd21fb4c3e58cbb60f14bef21aa74cf8802e3153f14807bdc370460375a778d1a31d01c42b66367ed8d9e8f84551002f552f0e52102b5d", + "sha3_256_hash_of_public_key": "c1b4fdc4929c2c7e4501ba7a9feb0be571e27c43fa96f9a7f934636ed9a86110", + "sha3_256_hash_of_secret_key": "5b475ff0aeb273c017d1e7d7cd380e41d50e634840e443a762608c09282f3007", + "encapsulation_seed": "1d7b03d3c5eefb8ae5799dc569aa668f1bcb8c86607b089d3530cf61d6380147", + "sha3_256_hash_of_ciphertext": "96a03461c156401f3cb6473050fa83ea82ae0dd3cba1c58ab74e7a75ac6d7535", + "shared_secret": "7e59320c0e79e27fa0abfca4411bc4eb686e8606597203545f88958cb16eb82f" + }, + { + "key_generation_seed": "bdc3fba1c32751139fc45bacffb3ea97f26573d804a5f27a459293d95190ed8efd5a08f656a6eb8cd20679930a31caa6a6331c4b133a6838c223ef9f769f6246", + "sha3_256_hash_of_public_key": "df4f164c11041dbe981d8ff2008757b7e694f564a298b92cd182129ade5e72bc", + "sha3_256_hash_of_secret_key": "1f836ed803ea8abe63224c016dc15468719599e06564c11e9f641eeb3634350c", + "encapsulation_seed": "554f3385b382f4a46314de37ee3885addfc5332bd4038785094e0a832e9e8c2c", + "sha3_256_hash_of_ciphertext": "5134f522dd92cfb775d86c37d6dc5a4624d1d81166119fc37f8f2b126151b7ad", + "shared_secret": "29f28098cfa280a87f7093d33aedc7588d5f53bc4e3e6c464ad2382842dc50ed" + }, + { + "key_generation_seed": "447f6076a627bbc5ad7773fbfeb14b4ba9ac43a0f8b99fb6dcd5e452aa3c47ec20a7237801f470fcc2bd9fd7bea8322859b850f7882d362947432913dd068c01", + "sha3_256_hash_of_public_key": "ed722667caf175df48a3a346ec7cb1bcc37d67d3137ff7b7c70a07f202893a33", + "sha3_256_hash_of_secret_key": "272df80631771996565e673a4dd92318e87e625097f74fae14c688a24b558216", + "encapsulation_seed": "38bf0033b779edf5367d9ebc01c988af90904c560970815837380650e4749eea", + "sha3_256_hash_of_ciphertext": "97079a593b9e7f23246a1c35082034a57f2a66db15f4f19c58d95902ea55ae41", + "shared_secret": "aa11bff01186992b29074a4f6b5770dab9ac55ebf904207369b9f5b19c202654" + }, + { + "key_generation_seed": "2d5df64d62cb07fe630310bb801c658dbf3d97993e68626745de39d37fbfc2b27b534537addaba4ecf14f02ab317d36cb9f0f50222ced7cf029dff8a0d3d2fd9", + "sha3_256_hash_of_public_key": "0c4dc82d723965476a518ea0915c1554bcc61c814c80ff120c37e7e8ed6d5c40", + "sha3_256_hash_of_secret_key": "d9e7fabffb14d620ccf618a1e25375d4cf58875c38ecc73587cd09b17621ade4", + "encapsulation_seed": "048ea516d0ebbd9f709b47eaac66f344c571cf50f0d01c9466aa061a50b66a24", + "sha3_256_hash_of_ciphertext": "4e0c0a62a751c44827b62dd201e60b72d2b7df5e06991a4be270925f8d9d208d", + "shared_secret": "05e6848b937984d705db636a3b6327ef9d375765cde16013ba0d203459dd2743" + }, + { + "key_generation_seed": "25056d1b8113bb362dd979d98643d7a7ac9c4f95994c0ba060609b6d07002ff3f48a9254dd40b117941fa35a66bb50296327b725525deef70e128ca8045ec451", + "sha3_256_hash_of_public_key": "c934c11e2eaa7c3c4e764863e436ff12fc9f517c79df6344ab98611f57fe7296", + "sha3_256_hash_of_secret_key": "4f502a9abdfece85347362ac4c7e2beedb137e29a4b638c9bfd710de432b5e5a", + "encapsulation_seed": "686c921c9db1263e78ae753b1c9c2e7936b8229dca48c0942c56c6bca4f10917", + "sha3_256_hash_of_ciphertext": "1ae907d458718ab894eb222ff0b0ef79bfe322f88b26cec52d0952848b12700c", + "shared_secret": "b285300e7f7859a1904d35ebf346b16d5860f0ebc4709e41c90c19d321196811" + }, + { + "key_generation_seed": "e4d34e12982aeeb1d62fd488d9b9e28557ed3429292239fb4f76fa9098009acae6c45c7fc62329b13c8d29844405db8ff6860de474bf727ecd19e54e6e1a141b", + "sha3_256_hash_of_public_key": "5b07c8359e6ec4989c34b31293f4df965b5d95802afa5836beabb001d5cd4dae", + "sha3_256_hash_of_secret_key": "73973aaa43538874f8b16d44faefbd26dee5389a05fad2d4f966662ea9eb1df3", + "encapsulation_seed": "2387772e50059cabda53cb93ba24b19ae529496c03b36584169451525c4a0e7e", + "sha3_256_hash_of_ciphertext": "55cedaba113fae50c4ed3847fece6fed690cd097c5602b6ad1ff47d1daf8d26c", + "shared_secret": "6e2e99d7b70682d8ca3093cd45645eabd5bb720b9aa8f2324251f70da1bfaaac" + }, + { + "key_generation_seed": "cd6a99396eb3539ca663a51e42063a3a262cc1c5a5fce1566f0597b52ad9fa325a3407f591791a5db4578b5972093a95bec3b8e70c1d542c9b5c9789729f8922", + "sha3_256_hash_of_public_key": "37f1d7e636b4ab366dd5725957b9e5d2498e4ee1929f2213f9d05c882d96a106", + "sha3_256_hash_of_secret_key": "1b150644ef3edff5c406fc9a85e16fbc87cfcf8a6ac726284483947cc2fffd63", + "encapsulation_seed": "155c29c5f0378df0cd0e847a80a07143cf7522fcd880c9229eb9feb1ce340cd2", + "sha3_256_hash_of_ciphertext": "7d6154876fa353e216b9ced00f3712e5a616f3eef5b96eba30ffd391e361f186", + "shared_secret": "c7c4eb7f531a9ce048c04f27c69725d55850157d4974990eaa88ec61045cf39e" + }, + { + "key_generation_seed": "6c8c53ed6f65e6b2e324b84364e10de42d1c26a106d4d1c99eee79c78586fb55b9402bf02481ce4b27a52e87feb92c4399c7f2988d40e942e7496ad15ad2aa88", + "sha3_256_hash_of_public_key": "a5383897314d60ae0ab1a8b50d6f5de454a2eb8b0502d57001e6e19223a82ef2", + "sha3_256_hash_of_secret_key": "38e8404120bbd346e0483ff7eeb758bd655ed94f6c02e427468f0c5fdbd957f5", + "encapsulation_seed": "a9cb9a61a3324b1ea5afe693b32784e2871096b2ca14a11acc9577c52359a241", + "sha3_256_hash_of_ciphertext": "6e82ae413d017162710a201b3413e9ed691d6bac22f0cf5b326a5e25e32ec497", + "shared_secret": "2595157f5c64d440776940b49c3e63605797e777f451a911c4b33178962aefeb" + }, + { + "key_generation_seed": "2107204cd995f1df14314d5381f8c5440f09a347502e161cffc0a2ec3dcfbc7324c3da70fe850e80aa818301d60c70f3038153866dcd5d179e22db59b8991bb4", + "sha3_256_hash_of_public_key": "500dd7b94b28b5b650d90962962bb9a3ae96e70d35723217f3f178cbe5659051", + "sha3_256_hash_of_secret_key": "5930b10cb88d66ad1ec117d2b134f921fe4ec980ed9c351951d47d33510585bf", + "encapsulation_seed": "e99fbae8a024ebbbdcef32ce213f6aa942e3eca925e5da4c09975d773b33a175", + "sha3_256_hash_of_ciphertext": "b79a9363bc18077bb64d9e05bc072d20b3965540c2bbaf1b62f9ab5184ea9523", + "shared_secret": "06b1a7d712f84ff30448190f2c445ee751808c72ba109ef8e49842180d2302e8" + }, + { + "key_generation_seed": "63a925685a8ac5bbd918faa33ac397d1ffbcf99135d9da7c3d6ff7aa4c50af3d3afdb8a246a56ee71465591831c371f2eb87467b0559dedd776ba063ee6d2f93", + "sha3_256_hash_of_public_key": "3c4467b507971523509bf97d2bdd733ad9eb94f312e4226d036e8fe827a20533", + "sha3_256_hash_of_secret_key": "76e696d5d7ebb4e2035507601f66f38d74db35d3c76b3622678a2c65ec7b0f69", + "encapsulation_seed": "67a216f37d67f5e74f782f1badbce1cc8c80a6130aec305b421899a4faa0a6c3", + "sha3_256_hash_of_ciphertext": "533b9903f91c9531896040e89b94782b874257194de4d66f049623cc6c47ab6a", + "shared_secret": "33a9ce6514da7c60b120c623101d494ac1bd1bfe390b6ea9ee87585e7a9adc6e" + }, + { + "key_generation_seed": "6a1aee5e708c1b47f02bdacce4f56c860f74fc7cfec1ef3b58285b1c8ad7fec2230e05b7114ff0395cc6634db1eae8258072d09c09f291e92d6620b177dc50d7", + "sha3_256_hash_of_public_key": "69ffbf2275f12c29cbb69f90a8c881721ce39b49dbba550ab93a2c4c94bfc669", + "sha3_256_hash_of_secret_key": "76d6db646c55687ff9eeb3f359093a7105a7ef711bd60a4ef7f1a1bbd70ea24a", + "encapsulation_seed": "52b19fea232c9154a3e431e9d69cda40013cf2d485c3cd027ad24e645420420b", + "sha3_256_hash_of_ciphertext": "3e30a2208670a37511e41163a9894b15a48aab3b7138d566596b5b0faaaeca29", + "shared_secret": "f250a12d405bd1dca852db3cbbe1ab43c09ac9e319fe61f6cbf2d19af0a968f6" + }, + { + "key_generation_seed": "6396b328b100e4c7f4bcae69875edea1a1982421558c608c13c592bf7b5d0fef1100ced48add211a5c937b8d6079d8e271af3f949edc61f70e60453aef20dea9", + "sha3_256_hash_of_public_key": "41bbd3f5c241a6d65b510dee6662e2a8f35757b0403dcd375e7a15991a7873c2", + "sha3_256_hash_of_secret_key": "256673d5b2a0225515bee64da0105c167d031405098819b6992d01c3cc711bdd", + "encapsulation_seed": "64440adb05db3308b189bf999f9ee16e8ee3a6ccbe11eebf0d3ae4b172da7d2f", + "sha3_256_hash_of_ciphertext": "4acfa485b4289ffbcdec4d91715214e953fb51d674b4e88e2fd3f00f1ddbd76c", + "shared_secret": "35865737dec963379a8ac738d66b3ddfcc2d4864bed603f6fbf03b48e51222be" + }, + { + "key_generation_seed": "a453bcacdd2b0d4646009e5ed451c3c45f08fb827ef733db3c517a9dc1af93e67a3cc8aa3239d4c52ce4c95afdeff6efbfacac10d294edc0e7cf4535059bfdba", + "sha3_256_hash_of_public_key": "290261ff6a1d2fabc75feab002d16cdc44bdbdd0967c728ebef0e9814c60b5e5", + "sha3_256_hash_of_secret_key": "beb5d2dc34b1dba8c87e4ca2659ed8ebec2d93be0e2d78285efeb9fd998f5805", + "encapsulation_seed": "c8bb46b3a7344ad170c2052fb042b5a3b62e0590562ee82577b1081f6f114d16", + "sha3_256_hash_of_ciphertext": "f061b51dff6c4e9443cabf450061a3fcab0135117a7f5c3ffbfc2b52b9de74eb", + "shared_secret": "43691c8dbdd6f1668d600615ffa5187f59d58168a2e7ba426b0f131baeed55ae" + }, + { + "key_generation_seed": "47ca2b77c5b717f423222c2730ca5cb9c856bc951d01b2b2c80bd76ccb5539b78f1481d7cab000e33fa07de8dc9627a85e76fabb4428a3376e66300cf12a0787", + "sha3_256_hash_of_public_key": "7ffefda144195d79e581c91cdf0247f4346e811f890f54f25226b4ab835871a4", + "sha3_256_hash_of_secret_key": "7b85555898660cb43a060e367d9a97112b48e3b8f99d437161cf6ba44b5c6922", + "encapsulation_seed": "2e2b70609f3fe029a14d09d5d659871ac776ce2797a0355f16e2eb68f5613fd1", + "sha3_256_hash_of_ciphertext": "cc2efe3a9d95e4f5ed4a89ed317ed1563fd4770eb0d55261a2790d8342c43203", + "shared_secret": "43ded3b7e86938f54c6df02230811f74dbdaf1bb4129b58642ca440f51602754" + }, + { + "key_generation_seed": "aaf6eb40e596a5e3e8218871e708b089240dcbe7fd3641f0e5e41e071ce49107e2f8d320ac3cb0c52efdc753282f092bc39baf4a18783a48ea031a191865eb78", + "sha3_256_hash_of_public_key": "13dd780ec5347c512cfabf4c2e6a44cb2b17993c7c746f93c1400a5db9f12511", + "sha3_256_hash_of_secret_key": "7732b2a074d1c0aa93106ca84711edcb7b8a369f3873cf89fbcebf0d32176f1c", + "encapsulation_seed": "4725dd8fb314bfd8ee23731c2341dbe114606d9abe6434c471b5573e7df193bb", + "sha3_256_hash_of_ciphertext": "cc9ce2f2ce5992ae5c9bfc18ac36969c73b06113e4b20a6e3cfdf76b2521f889", + "shared_secret": "e24f527de7da7e7dded6b5b0bee5546db496ef5baa7e83c219022562478f38d9" + }, + { + "key_generation_seed": "6500f32c93415cfdbc0bd31d78d5be95cb9060c8cfa2013955b56f8b6868b322393308641a9a4647f230201e1389624a296b55192a9819fcb19ab77c25f95445", + "sha3_256_hash_of_public_key": "d5acaf411ccb64500879102d9cdf6d9fcad673d874a4153383806fe174b2fc1e", + "sha3_256_hash_of_secret_key": "e5c3fdb9d8e92c42ad48684f0fe13aece244d116f8a6d09a764aaa090b3375f2", + "encapsulation_seed": "818d3bb8ebfb32bf464775f7139bac0a5bddce80ec5798595992f9403002cd5d", + "sha3_256_hash_of_ciphertext": "b4c465240ebd65712db7808b56787088d1df2dfe2a0c3058fa932abe506870f9", + "shared_secret": "e3570dc33608be251bdf8a7101e897ee900ed004ce96fe29c2e9a9314dc723a5" + }, + { + "key_generation_seed": "7643cef2d62cc5aaeecf754653ea62294cd2208e5bf3ddeea209e3dc45373d49eac9d531a532770837a854b4f5531f6e0c8d6c10183b30d3435498c2dd142951", + "sha3_256_hash_of_public_key": "152641a683dd690d4ac3edf0261200cd9244ae7dab962eca2f3d22a554d0802e", + "sha3_256_hash_of_secret_key": "7afdb84b3806783db52ef1f5f0ff89ccdb051704cfd19eec3e2f0830c3b27550", + "encapsulation_seed": "c92aa5fb91c980d9cade9ce99d4c75b2ffa7d6a6ff9bd59def1aa701f2a0992b", + "sha3_256_hash_of_ciphertext": "cb1c509eeea8ea062644d344926d1f39d91797dc842242b0e9249da88a844dd5", + "shared_secret": "c6d9ac793ef53afe26bbe0fd153e0e14bbcb5f47cdc0b25234510ead56f3e464" + }, + { + "key_generation_seed": "f8ee95521060c03bb8dacc79f7eb7db640f545f315613a35d447a09e504cb4e13fc3d8392cb53f36ed647364a04e37278a0e0a45b720f4a75c580c9920eba98d", + "sha3_256_hash_of_public_key": "9cc95efe512c84010ccd7118a92522cead44cff28d6e223f76702a47694c8f05", + "sha3_256_hash_of_secret_key": "d9a18ebc4b027c9590d0e4eeed88705aaf5d166cc016cf6e0baa07f678f1f0d1", + "encapsulation_seed": "7e8086a01dc5b3bb9eda25bcc45d27f99874841b97237968495800e007696ac5", + "sha3_256_hash_of_ciphertext": "185696a8333ce642a905aea6e09b8a2a9d3838e2d8b83f2139eff92323bc3bf9", + "shared_secret": "9658a1ab1f44049650124a669d72eb6bd2cba3f39637c7f8559c68044242c3e5" + }, + { + "key_generation_seed": "b8bd0493a882e3a49b4e0f6256fb1fea0912562fd9ba26ec3d6c9cc12c8973abd7e4b5d8021c486b9c3114d7cbbeb7cd49eba8a61bc2bcae1f1bef30a1daf76d", + "sha3_256_hash_of_public_key": "8b12f00bf09aec2b492cf53686beb31c558d0493cc7b2b9a9dc7265fa9edb685", + "sha3_256_hash_of_secret_key": "9979de3ecfacdc04e1229773f36d7b4bdfd731ea0f1fc2f9d56ee1d07e9bb075", + "encapsulation_seed": "bb321ef14d44d8698df879fd52450567657f52a2df8d111185dcd7d4f30a72d4", + "sha3_256_hash_of_ciphertext": "180ee6c7ff6672397f744a5febd30cf0026f88586c035ada99a9d01726268356", + "shared_secret": "e50d8305695844b9d2becfb7d260a879e11767925c3f279a66c245ce8e48417a" + }, + { + "key_generation_seed": "c0407e41ddf48d333978b89bcf2db01e4613425b456249e76a6f25b8a2827bf5b2dca81e3f5f748d23c9d356a2209f6b2d60247b2e45c9808de497f64f124643", + "sha3_256_hash_of_public_key": "3c98fa4af17fd014a60d11ca5e929e4fa2524f7db289ce0947ad90657990c153", + "sha3_256_hash_of_secret_key": "2c370afe3301b0481b50ae72e21cbb1be37d2877cd802a1d40e05d9b4e6be502", + "encapsulation_seed": "210a423dadd899b810f011794b79aa7f860823ac1962370e791287d3a1afa384", + "sha3_256_hash_of_ciphertext": "6268416162e82e827c39f02f45784d421b22b9e69bcb98058546bd28a20e6fc7", + "shared_secret": "cb697a878ceaec9484266727e6f96ce24f11d01d1ed56428a8a016655f3eae13" + }, + { + "key_generation_seed": "334382d39164d1989696a2ff77b25a28af8bead9883b5365eb6fcca7c1781cc9aba5068af837be962f439f233593d193ce5e08f7d66efb3389885927b89d2523", + "sha3_256_hash_of_public_key": "091210fb4f6fac00a24167d9bd2761e601db0a3734e3c835d1e9c5865b1e379c", + "sha3_256_hash_of_secret_key": "fb4bf08e0cd8d2f31969f75b420578f8d6dcd845824e427a6261931f1e1b820f", + "encapsulation_seed": "bc856afe24213e3d14c3d6f9b89223bbcfb2c890722d770fa3492c1e46d1c302", + "sha3_256_hash_of_ciphertext": "8b8bd3b7af53ca293dc31386756c6b1c7f5e727a68d1fc92f05c8b8925f389f1", + "shared_secret": "53cdf36f6da6045c9bbfa9fd3a8c525e0a775299490b61cc2eab45001050ae71" + }, + { + "key_generation_seed": "6995143e8eb8a6e93840f76eec844f67d2b5f75b1839a5040337e61f9806764a0f4dff8e56f68440836a072412a30d851ace2c7c6f02d60e7a8420001a63e6c6", + "sha3_256_hash_of_public_key": "6c206507b89f46c6e9cd5e78b6cc78fb3677ee609cc090cf3782c876fd5f941b", + "sha3_256_hash_of_secret_key": "c9123a2bac61c5fc4304da90862d8cb544a31da2cc8b8126ca16a71278f461e7", + "encapsulation_seed": "5fc00f89563e44b24cd67d0ce684effe5731619fd08e7d72e2406eb016afb66b", + "sha3_256_hash_of_ciphertext": "49db6462a8abc0874542906c195246af6a794d0ab41d1ee78e422a33b63e8461", + "shared_secret": "ccd0ae3af0a25b563080c0bb9b107c8ea0adaf8e775407915a0a12cb8279ab5d" + }, + { + "key_generation_seed": "995eff7e0d195c6d0533f3dc194d47e60f9ad14696144cde694d60a95f3e96b4b28f7e7a15a005f92400ce33db073d49b53871594a88fc45e0f94207b5f0f2dc", + "sha3_256_hash_of_public_key": "0560200b8d070d1db2cbeedf3cb322ebbab3edb80cf474b4178633c210b2fc74", + "sha3_256_hash_of_secret_key": "a2424d9992c7e999a5b18e638a22d65e1e5d5029e5fac62a5091095897b3543c", + "encapsulation_seed": "ea22a76065db4b565ee1807fbd813b43bde72b0e08407fb867c6a18995025e50", + "sha3_256_hash_of_ciphertext": "1ffebb5e518ef3bece64597c32281e2ab833a797ba50b364be2c5334c872ed65", + "shared_secret": "dac2c554310dfd43c22fd2c2e1b26892f169c18eca56c7fac335385910445fb9" + }, + { + "key_generation_seed": "3e809ec8dd0fec0d911a4e3fac20f70fbb128c5de94dc7184ca7310ae9157a98d8128601c28b1def8d393a0db283229f7c7383152a814e7cefe8ef9d9768c473", + "sha3_256_hash_of_public_key": "3a2484828bce833f9262405b562bcade9ff04877838558409d2b60f1b689d137", + "sha3_256_hash_of_secret_key": "610db3251ec079ce8003a49d64ec03dd49d89e82ae9f12d26d50938f4a3992d9", + "encapsulation_seed": "e9602b34fe73ad57f4bf6ead99743d645641553a5b9b9bf2e7016629e3e9bd76", + "sha3_256_hash_of_ciphertext": "46f334d2465d64e9b7ec04c25bdbf8119ee6f82602f6bce14b66fee4cb03bbfd", + "shared_secret": "aadfd151e1d8a0f6d8c81f02dafab4fa4507ee05326f8eb6ba86a08754df47bb" + }, + { + "key_generation_seed": "dbf1c465fff3d9f783bd9ee61a573715e45691147b8904439b5ffaa64f94ff7bb6d75eac6c76ced1b0a025b40a55440712ad8424672e761e9bc400d63812006f", + "sha3_256_hash_of_public_key": "bb8615509158b63be5f5e51a0e690f2ad6fd0c56fa886bd85902abd52598bc81", + "sha3_256_hash_of_secret_key": "3a4a1360d366376a56362fee0aa22756122e3c40226c770797c0baa82192bfa5", + "encapsulation_seed": "f72b9080a6c051bbdb9b0abc1949034be0f89a9f73fe277ec4d4740c78d04a83", + "sha3_256_hash_of_ciphertext": "1794fcb78cd1e19545d08f567de8f7795d03432b2e2c29b17ef8b3e6dc55e4bd", + "shared_secret": "3cf685398c6d7be5276e43b1e8dee668cfb7569c8ef89ad63f6dcfd78e1a343a" + }, + { + "key_generation_seed": "1f7cfd2b70863154e8a69d1758532e86c20cfc763d67c758bd10a13b24e759b5273b38bddc18488024ec90e62a4110129a42a16d2a93c45439888e76008604c6", + "sha3_256_hash_of_public_key": "5cf14252096e4988d8ecc4ac6d29ff09c55d666865863d03a68db523728910a8", + "sha3_256_hash_of_secret_key": "404e6febba9802464a188007c2137fc25a4c437611babc8fa8248a0e42e45357", + "encapsulation_seed": "f1e5542190db8ecf4b8d617a04fd3783ad0df78bf8dab749afb57db8321d151b", + "sha3_256_hash_of_ciphertext": "3bd58c926214ebfab7f034a2fc402403be692f0a06fe733de8462f1800d36d1f", + "shared_secret": "d8f625c25326ffde75ad8a731ad675a60d0cb37eabe8c1ca1e2c7ca1226c446f" + }, + { + "key_generation_seed": "3a19577908efd37697b8edc7fdaf47d1bd3ad01a1b77faf794bee5b9c3192a6fa3729672816f3eba84c9638a79676eeac0f22c8a48e0c5d50a26ff0844c66b99", + "sha3_256_hash_of_public_key": "345118a7b9bcc773f0ec10c3e353eb4365d2bbff3b812df4635d5c8265b5d8c5", + "sha3_256_hash_of_secret_key": "2eff0ff04aa2f95d9d2a877d2c3b4a09255fed2413da76e63506d0def33f42ff", + "encapsulation_seed": "74efa414ae171bf60b6f884cb7e5ce12028f49365daccfa23e845d551711660b", + "sha3_256_hash_of_ciphertext": "ab0ffc4104e0aba316f3e9f28b5a5a17ba9d7ab5110ea768de46221db22a1f9d", + "shared_secret": "984c3eea7d9eca750e6100abc664aa23605cfa9d40e6e690d51937f3dde17f7f" + }, + { + "key_generation_seed": "ae0f65e29f38804a6759f70f4d01e2aaff7fe1c91ebc4f892dd0de3ab2e68ea5e03ff73e02a217659f53d8c47556bf3d8c94040f630d63605e2d0f923579370c", + "sha3_256_hash_of_public_key": "772f50f7047714627bf76bc098e0b919145fcd8df6922ebac383e5c556738390", + "sha3_256_hash_of_secret_key": "c48cd8eced0093133d3d083baae0f69ebc3e239c373a41db9557c1a46a40d480", + "encapsulation_seed": "0b4c3cffb2ba4380ead13dc0d8acad2356b448a810da1df29f264c44aab6d24f", + "sha3_256_hash_of_ciphertext": "04b7c6114f33676fc11b0b709860c89911914c04b8f84fc9f8bcd91cd024475d", + "shared_secret": "14cf9129961a5fbb00ee9bf444bb2ee7424f50bd8eca98b21bdada82b2f47fed" + }, + { + "key_generation_seed": "6084a235f79dd093ef6d185b54e69df33dacee73a9bf2f379004421a10e3a79d9f684fb055ece19459eb464e91e126a7a6e3ed11ccee0046da234d964c985110", + "sha3_256_hash_of_public_key": "a9f015f625356a6bacbb5e565c70184940891589309a571b7166c2ee713b8fbb", + "sha3_256_hash_of_secret_key": "924859759e33e4100a02afca0ad0f0e631eeef3b4a70444267e921b0b6eb334d", + "encapsulation_seed": "1c82471dcdfca3a6942061ab4f3d5bf0d197321437c706d9cccccce449447002", + "sha3_256_hash_of_ciphertext": "5f1076136020f6df9856c101cb559bd48ee2aef5f8864c14811d07434b75421b", + "shared_secret": "de78ccd2a757a9a4c09763b2d9da4da0d40cadd7741e76ae22b2b472d823840c" + }, + { + "key_generation_seed": "acd1c0217fad5caa4235544dd9de153ab1880ccf4c76f16f236fae4e4bfda04cf03a8abb0a5010f400ae5722a75bdf5a2f6d5b546b34d73857cb1bfc7e587aa7", + "sha3_256_hash_of_public_key": "655d6f749b0a013bec99e017f5e13bff76680a2f9386f2ac6938d7950d5fa1f9", + "sha3_256_hash_of_secret_key": "0511490e76eaba3b276ebadd300c394490589dec54468855977e96a33025e06f", + "encapsulation_seed": "46fe60a18124125ab93e0c578f1c02f1bd1301595013001c7f3c2fa56cde294e", + "sha3_256_hash_of_ciphertext": "6e7cadb1730196ea0e7268940ab8608acc35a7d19f4fbbd61907ddc26a7b41ca", + "shared_secret": "90ea2a8181e75f6e5d3314b381bd802cca5654de0ad12ee59cf0c3c2204c587d" + }, + { + "key_generation_seed": "241191401a63afa750f05662e354dddbc683c776ce3222beb83e3cf913d7ed7ca59b3bd23b49a95bc1fad20070fec930b6060bd827d742b077092e422268e15d", + "sha3_256_hash_of_public_key": "1c3c2aed0ff6944819c93f9a9fe77d14a16a385f644de118099fd4f7f57db9a0", + "sha3_256_hash_of_secret_key": "0fb711641d1830a3eb4ae1a4bc2fc610ea9a811fdc5274488dd31f9cf52ec04e", + "encapsulation_seed": "52fb7cb6a633fd2e83f2892bd9441b48fe59ecee6d026f5246fa7f2a5e55ee3b", + "sha3_256_hash_of_ciphertext": "b5ec392e0a92dc861faa7e02036c051a00f2af87d4e62b767bccd2fce7f69c11", + "shared_secret": "d66f413dc141daedd5349a5489c7be71b1cc912408736a95c4b87a7007865451" + }, + { + "key_generation_seed": "b9a6b0c05677e957d41a34ba03bd06f2a9092e31f63389397d7e70fde6409d18e99c0e7b82be89bc3c1eaee6680aa4efd394e40c2b3f30523c8117f7c26a8969", + "sha3_256_hash_of_public_key": "357d61586f671648188f070899d2eb3408158adf5e8056ef37ab6d8817cd8275", + "sha3_256_hash_of_secret_key": "b22e39d960d7079015d70fba54ae860285f3c182bd5fc8d84c255f5e0f86f800", + "encapsulation_seed": "0f81a5f97082121244403da3feeb734f6084b314b8d94beb11627aa6ad1914e9", + "sha3_256_hash_of_ciphertext": "02295796f4e9cfb85255ecc15fa1b15b4863bd794515530b64a6437c0aa9d9fc", + "shared_secret": "5efe1d64250ac29ddc3cd9ee87cc12e16592cb848090ae527aed99cdc7bf97a2" + }, + { + "key_generation_seed": "28a96c71577ba00c94f99fe965bc595a26db2b3ca6ab5cf8e443cdd8462b17929c35d165453e5fcdc6f9df64526d9de698f2bd3e6bac6c7fdd86601b9ba5f4a5", + "sha3_256_hash_of_public_key": "ef07b1f4886b895a3246241ddc084379eeb0f0ed84bdcd318fe72c9b546413be", + "sha3_256_hash_of_secret_key": "132633e3d33bcbc61ff70504e34bb033c92db5086bd924eab4ecbb8e4be983d5", + "encapsulation_seed": "31af9345365549ea0360169ed57daf98cc5444799d4c75d9f1f5d615e9df8a91", + "sha3_256_hash_of_ciphertext": "822b6b40825fc0cd00dbc970e39725e790397b74d0042086e534e34bc4285fab", + "shared_secret": "4ab06661f996ad3d290606c820304bfc95fa22adbd96819b1b73ee3b53182204" + }, + { + "key_generation_seed": "c08ba2ef8c3a0a043afad931652d7a19e6e8cb670f840de5f1fa03309b2ca9ec5fe6141a25f7ab9f875f79e0a82d6ea5cde5a017ab637d5fdb7c42646a1d71df", + "sha3_256_hash_of_public_key": "1a2d9ea0d2280249d9d756975c6979a8770bf4b5f6addbd76d045a816bc1be38", + "sha3_256_hash_of_secret_key": "23678549b4e6e050b57ed1ad078705d33fe76ac976a9f70312b9cb45be554b0c", + "encapsulation_seed": "774ae54093d694ef40b63b62c73e6c98295f606feb8699807eda1d030ffb996d", + "sha3_256_hash_of_ciphertext": "ddbf1b8a7d9e1d76eac0b8737d73af77f0206eede2b263067988d1f647e701fe", + "shared_secret": "ff09355cf1bea871cc8f1417a0027ee49df46fe80482462c3290813b7a383dec" + }, + { + "key_generation_seed": "0e3b30e102d707538c2671060f603bb0b8a014103f132d63b09ece07e4a4c75b11eafeca9e810796c34e8cfce9d59342884456007b01ddd12edce6d10ed87e4c", + "sha3_256_hash_of_public_key": "a57b333a2f41fda2ea72ea11d8bd642d911f6afe90e60492ebeefdc17a932192", + "sha3_256_hash_of_secret_key": "b59171816497ec0c34b963be3ef6366eb051cdebdb145fe445e16b72aa37356f", + "encapsulation_seed": "9f27a47604ab5146caaf0aafe6d149424f8d66e39ba3baf5e6c73b19221b7e21", + "sha3_256_hash_of_ciphertext": "d72184d1e05bea3601c029dd7dcb425afad5604069e1f88690d8d6b46644d8d1", + "shared_secret": "27a33edd638dc744cc6a5c8e3d53b2b1a3d90de2b95a649d47d1dfc2f5090bb7" + }, + { + "key_generation_seed": "2478f7d3de6041e7e5cd11c5e2ef483d1aa6218eb126444091535f6ae532fa7311136e2681df2ef881b51a092a9badbe72c9772c169808521c47149578621e28", + "sha3_256_hash_of_public_key": "d3cd2febe168b1ddf776b954e96085a7d475e3c8cbde68f7c80ffc9fa46b0d43", + "sha3_256_hash_of_secret_key": "b41a159ad0a89e7a771ef11e68efc9d79e6add05b261d0e40620a6b667a6c6bd", + "encapsulation_seed": "90044031b7597b5e60a4f946b713e8996d0426d2cb013243d9b7d8f8ef159a0f", + "sha3_256_hash_of_ciphertext": "601f8004324c0804c2cc4d11409ddb5ae963843fdbed0071d886d369026826c9", + "shared_secret": "1ec0fc29652419d0f7d3df73ed40a21af5ba0ca0ec4cb6f8c736205169646225" + }, + { + "key_generation_seed": "9d405d3ebdaf35fa8722de431b669722acaaea2fd10b814310b17f78b66147d16ceb14f7662be0c42779459f69a145c0e2ce9f0bd9a0cd1bf32ed5694cc9ae32", + "sha3_256_hash_of_public_key": "9499c1b006a0ec2c299c41c3f728c3bb7848957fb2bbbcd05b65233b89a2b1b1", + "sha3_256_hash_of_secret_key": "bdf5c3beb39ae62a6e29e858962c322fe525a307a163d68f765779b7848bec3f", + "encapsulation_seed": "a7a31e140891ea37d2b6424b59b1f84f89220f32dcb73e037eb912b389d34a48", + "sha3_256_hash_of_ciphertext": "890918b992401af1eea4e026a54ca03d7deebbd52ac7c7e35a97b33df838df50", + "shared_secret": "f18bc196547734f8b08eb44867fa7f6e5d7887286a7f7e30b5b95d74b60593b9" + }, + { + "key_generation_seed": "9a86490f0615f3edf789cb0654066e9ee339cc59f968281f3b89213f83c692edfaeb2ef44d2f608621e831187ce79b2d2f4a20f1568bbe76b0d3d5af36111714", + "sha3_256_hash_of_public_key": "aa14ea531df0a7f93225de1c75ace0d2692bc750b1b538cfd0d860ae9c5a8c13", + "sha3_256_hash_of_secret_key": "155cff081ef58459a00ae63a6ee0ed2698bdbd99c67b4c9dd09f8b0fc3de0120", + "encapsulation_seed": "70eb3f791faa91f1f982fa477dbcddeb2c55691c07f93b04cd31b37544c94b42", + "sha3_256_hash_of_ciphertext": "6fde6e51e91a1917e916b3a37f82beb19087dd25a64dd96bea2cbb95cec06edc", + "shared_secret": "736e053b8a5f4dbed37b5560fe586b198686500f118247c8a2640cacbf0b0035" + }, + { + "key_generation_seed": "6dfd9b575872560c7bdc2732c4a28dac4db04e535eb8e402c3dffd145c09ce47a2985c1c4d203778597947d710dec806e36b0cd949fe460ef141213bfc525e5b", + "sha3_256_hash_of_public_key": "e0013ff7eb7b8266ee94659f3372f5981ce1d87584cb1f0e80da2c0c95c16b4e", + "sha3_256_hash_of_secret_key": "7eece78f3f97759d0cfc8a69481271a425c56e540704b2fdaab8b2d920d19e21", + "encapsulation_seed": "30f4095015ba88b6d969672ca3f438c395dacf7d476ea7a9e805ce932d270a13", + "sha3_256_hash_of_ciphertext": "c1786531f7a95f63cc168489030a259e91074222475c204054fc8c127830c6f5", + "shared_secret": "6bc564ce6b2a8b0247a3732edb9002415184bff0893c899fa9f91b7477916b99" + }, + { + "key_generation_seed": "6fca9f4e384d8418075cc064c70730801bdb8249899d456a77130d5beeb3662cce7683f8a03d3cf04e46970ff7d6a12494ae12558346dfc8fd9370bf944a0102", + "sha3_256_hash_of_public_key": "b503f8ec36d39fc7b4b8ada1cbb933b9db9ee118bf081ed75dd5dba7590f6c8c", + "sha3_256_hash_of_secret_key": "65d28565658fe991b77136b89255ec2d1cf65368e06f2b30bcedab87ffe39550", + "encapsulation_seed": "cf31220f44de862e1719570e1b26e897790159366a385452334fe24cdcae28ba", + "sha3_256_hash_of_ciphertext": "84c928f1b368a0d08f8b1224bc3dbeeeb7e08cf9c745bc15f59b5abb4b9fa8db", + "shared_secret": "633677961351d862d0f685050ce89f79fed7397d7f598e84243e0e23372e0025" + }, + { + "key_generation_seed": "e58f71bf175c0550a67e00e0f7b3b7fc36bc2707bf0c93044a492626de36301a7f7054814869cf7625e45647bc1547aff288dbb90699b2ad84893f3b755d9722", + "sha3_256_hash_of_public_key": "03341657b159925cedc8967872a45a3c1f0122979af87a878a2019b3f17c8ba6", + "sha3_256_hash_of_secret_key": "6bb236b9c7a818f9edec1e5da339755dcb7ca1b663a5a208c38c75e7ad7dc12d", + "encapsulation_seed": "bb5e65669a44e5d5c709bafa98c16ccba6ac2c4ae923334f69a11543eda64f5d", + "sha3_256_hash_of_ciphertext": "f8e7898cab6ea08fbc4505b0c90313961568ef175ab04c7707a9dbd44bfe2d85", + "shared_secret": "003fde9f0ecebec91441b3783fbb693e73abd497d99ff9e2497bc1cdc280acb1" + }, + { + "key_generation_seed": "e3fc575ed51513e62aba655d24cd9c8f1c6c848aaffa946c49a53ac3ea59e474d82c2f1bf2e6aebde5660fa73356982e12999d8fdafbb3cb186341d0386dead0", + "sha3_256_hash_of_public_key": "60c001172c4734a620c248654c58f1c10135657083de776116a6acf8a55f3610", + "sha3_256_hash_of_secret_key": "b10663e90392d6387c16dcad565bbe1fbc05f32495cf9878706bd0d61d289147", + "encapsulation_seed": "9ddb3aa9c7905d1a438c93bcf78e3e321813580371ab4e1289e2dbf3701972c2", + "sha3_256_hash_of_ciphertext": "d9b3766e8edc16871ef047b3a68f49ad80f99cf6dc5ffde0f58e191079d0937f", + "shared_secret": "ec6895b41d5f0c5a70708799952c8ce8b33389210c348993b8e8056254b04462" + }, + { + "key_generation_seed": "470b4943f0fe7fd0d8ec5185aba0d1db09d112934e4fb4787e2bbc6b88466e7b8b2809fd40008be70a6b184981101724bc3d5ec5e1956b510b82fd5ad0668a5a", + "sha3_256_hash_of_public_key": "647a136f20b22c63afd2b88d14fe7677cf5c2b78223a587068377021f6edfe9b", + "sha3_256_hash_of_secret_key": "e70be83a7585618e7b91bc9930a581625e2441962c823a27eda9f6dfff8528ee", + "encapsulation_seed": "26d90b190a6c3d0d9a86cf66005154e7086749e966e7187c249ccb9329fd3b8b", + "sha3_256_hash_of_ciphertext": "d3bce36f49874ec7cfc3a956d1fe97c5a52ed1e3bbd3ff9a7ac411e99d333d66", + "shared_secret": "be6e32a8b24fcb029b152385bd4011746a4895566e86c1784a6a631b8c1e9dd9" + }, + { + "key_generation_seed": "6df4385db978d27b27d2aa5e452e4152b36f097503d9581ac3390105c5727e7dc95fa08ed106ce84660e8a4c90bd2b22634e40769aa0090a101c5dddad45edc5", + "sha3_256_hash_of_public_key": "1cde599b2dfc69d59036434cc0423337513fb9506452bd8f42bb82661ad0065a", + "sha3_256_hash_of_secret_key": "aa80a266176a7ef8fb22fe21fcf3d3762cfc36734d8b6db3c6e1d4df1eecc1a3", + "encapsulation_seed": "7db6d1a129d6123f1f805b79ad3b413012ea86aed42a05e98e7b1f32f9fbbdec", + "sha3_256_hash_of_ciphertext": "ef4df34d6bc31236777e1868cde6ccb6e74b537adc6acfdf260fc2f4eeb12aa0", + "shared_secret": "3a98887b355a4ee269b50a208bc1cdc9492c40cf3dce5b21c4a73863da114fc4" + }, + { + "key_generation_seed": "dbacba825728444921b227cdba54446b3f6881b47be9cd02832f78b023b1bee0e15274a8e2bc08fe818b117ba28c5dfae74d54fcdf6f20052f79be333edc8dde", + "sha3_256_hash_of_public_key": "2a50c7a070b3dc7e107eb1e8b96d62305c13327d729bf9d97c69f1fe6eed2b52", + "sha3_256_hash_of_secret_key": "6df052019662b83b16b4da0a85b17f2fe56ad269b294438c8ad298d2e2269d2f", + "encapsulation_seed": "1d129b27be7384c359d04311fe5c44917d1fde4bfb57314f483ac617edd5ac49", + "sha3_256_hash_of_ciphertext": "a5f7372d959dfbb0f0619c26d95fa38559b82aa6ee9d2339a779e573d161d635", + "shared_secret": "dfa6f29a270a006ea674d811b262d7160bb90bbdf2afba74f0f41fd9376c409d" + }, + { + "key_generation_seed": "690eb71fd7052b906eaec09937a8ed374e0b02afa27c2f14399932be5839fad281c38c2cb5cfafac81b96a810ab749b61806b6d54c9f8cf4bf1be0192423288f", + "sha3_256_hash_of_public_key": "5f166082ad3ab0c739cbf0a6bbe2707741d9b5f53a0e16199280a2376c9e5a17", + "sha3_256_hash_of_secret_key": "391b71e679b9a0a23a1aeba042ec7df439fa0a18c6442dbfe2bbe05d4fdb5fd6", + "encapsulation_seed": "bbc773ebd2df42c36ae05952d6a64c63a5dfb82ceb3ef4f8d4df3a30ec8c0467", + "sha3_256_hash_of_ciphertext": "a87c85571888b00e42198ff1507b9229e05bd6da58e692c69f25312dfdcef396", + "shared_secret": "4b3a62eaeca3d21a68a3090a9c3ad0ad84fdeec7c27da50c00773baa12c7d9d3" + }, + { + "key_generation_seed": "32e0ea9089fa928482c0770da545af1bb871a03ce38604138b0d08ea2a10ca2bc06c5bef7b6508409daf847a64c8d30d0974fd3ba7476dc76c46b458a036d884", + "sha3_256_hash_of_public_key": "40b3a72c164432e6ca838693ef25b30013e5cf56c1e6142828107a10cabdd169", + "sha3_256_hash_of_secret_key": "6f970259ae97422f8698120bfa8e53f4f89589773243db6e7a1859c94181a3f6", + "encapsulation_seed": "5b17a6adad541efcbf5ae4b0c0452cd2ce32e4f0f8701801c5b63e197c1fcbf4", + "sha3_256_hash_of_ciphertext": "c19d31b91d8813395e147d4a688a1b3af95db3896f1acdfeb75316a461fc8e67", + "shared_secret": "f3c45beca2b790978e935f9c29788779f13cd4445a2540638bc14d8e3669524c" + }, + { + "key_generation_seed": "6fb2ec719f2a0dea152bf3f64b9d148f8ab8ba88f64e61f5db53e12d59f525574f797c007e4061f95c7d56cfc7ee5c49e849dde3fea8f25e7876df2a18515c34", + "sha3_256_hash_of_public_key": "f475da2ec982c47d91b24bb5ec6c51910530eec26f38541b173b38927d23c568", + "sha3_256_hash_of_secret_key": "f8c836ce8a42d6d07f1ff40e2dbf16d264bb6ecd1cc0227ebf792a6bacd327ec", + "encapsulation_seed": "61ab87659525de9656af41246f20e1dbe85c24e335e7ecf9493f46168bc14e94", + "sha3_256_hash_of_ciphertext": "50f1e9743ffe1183af71b2a52e49f9229c70224f0991c34accd2a66eea934fdc", + "shared_secret": "e47de232504ea6dfde948d8d46ea93885b2868158f901bb822d9fffc4810955e" + }, + { + "key_generation_seed": "527fb88c8bd9a4d6031dad15e63878abd2b559e7e08d61f69e8e78fca964ee6ae32d432b4f9f751bde0496c580a181ffed762aa35454a02d3f1f47ee0394c89c", + "sha3_256_hash_of_public_key": "2b22f73a770cbdb80da84f97f27a14c5df5b3372d52503d3a20c3cb2bea8b404", + "sha3_256_hash_of_secret_key": "a111bb1797a3baeecc223e4fc4accf093d2e069cfd40d45346d2aefc09acb358", + "encapsulation_seed": "eca2adc3da1fb15f34033405ec08ef2f46163df4bfcccf8842c600ce0bc2026c", + "sha3_256_hash_of_ciphertext": "ffce3befc418928a0f9199590c141712015e1404d43573820e649062012a760d", + "shared_secret": "270ffecb37cbbb1b6fc3bdfff6c2fe3a9236ec243dec61e051fe42ab9e43e757" + }, + { + "key_generation_seed": "ac6fcfaeeef795b6ef9e062f02bf42975fa01e7d91ba832f74e05269a72684d05aeda108ea4d6c6bc0fb958286850422bc357ca67b83c986048e0d0087fa11ec", + "sha3_256_hash_of_public_key": "3d8fe8354d81146fd65af657da08926bd3a6ecbc2f81cb58d1aaacfe5b6e686f", + "sha3_256_hash_of_secret_key": "d1c524a715b2d05abc8e8729204b620f4551815cdeb00662b487d58e99c0ac7e", + "encapsulation_seed": "c4f15bec2d7701339d0ade4835193bea3632edcf89e74992620d9eb623a0d0d4", + "sha3_256_hash_of_ciphertext": "079876699837ea78010b31edfea5b93d47f29e9fd49a1c7a064756155f67f472", + "shared_secret": "398c68a21c6e05a360b83a29ded91b729551e99b829ecd5e523116973aec7c68" + }, + { + "key_generation_seed": "ba2fb9318d4dbe7488057c33e95e6f054583a2800c41bb83083c330a914a12cfe63f8ffda3565c2424c89b20974b748a65a5aba75133fcb3156dfb6626a83bab", + "sha3_256_hash_of_public_key": "36fc15e2340175a2a64ca1cf31a4b38ed5f797aaa8acb0c3d2ed9c19c7099f27", + "sha3_256_hash_of_secret_key": "0741ce5533316ef689bd966721b1ee57a272d5eb557dfa6fab6de770a2e7afa0", + "encapsulation_seed": "28878249e2ac2b6263422993923a0c8bd05ce56e385ed13c943b03d226856947", + "sha3_256_hash_of_ciphertext": "a551717155bdcd97e228f2452ac922d3b37ba2ecdd58c5943f9ea9181a5dcf8a", + "shared_secret": "15bdb7f1c08496639c18283bd3f2dc9d1470d0d800a52435145e1c6351e6c1be" + }, + { + "key_generation_seed": "aa6dd1e5799cdf7af9c4fc632b3eb9d51d66e85c8e0a21ec98664fc51ab63c7dfda268813efab5204efa60f78bf81d320d01ac09ac06244f7afbd2d80fd356d9", + "sha3_256_hash_of_public_key": "26a1b77ae8a807e9de16a9ede5da5aec3ca5f23f5ea00e455d4a091467e6ac6d", + "sha3_256_hash_of_secret_key": "2bb0f5318208eba32bfba206dfe174f976431dc12421bc7b3705fc7c0b4a06cd", + "encapsulation_seed": "17fc65f7fbd7c75ceec421dee84dff5a8cb22764a182db17e0ebe857f54d60eb", + "sha3_256_hash_of_ciphertext": "a6c67a806470122a6bbf97d7b62d21865f7d4d7bdc049d992462f767477521d2", + "shared_secret": "54390804b9263d9de67f3ff064f6d3c8318a8fb06305abe835c23c778368d680" + }, + { + "key_generation_seed": "195d6c86a3df4c21e3007d7f2768b43c74cb3060e0eca77f0a5d3271542b9a84ae77e0f9f21eabd8c0c6eea7767f4e10fde5c2d79b8400bf96b19014b457ec21", + "sha3_256_hash_of_public_key": "2460170e6cf1da1e7b92037f51b4e7674d9abf74f5c225c5c6ce16a971691284", + "sha3_256_hash_of_secret_key": "a364a1f435a2d2a341b59a1886af0d0f3580e56306869bbab819de741ac9f642", + "encapsulation_seed": "fa0489f3730100609488e951e6aaa15c0f193bc1dbcfcd013bc418d6c507b176", + "sha3_256_hash_of_ciphertext": "44601ed238793bf4ee4a78021af90206d8b0d4f529d6ea144796289646f29b34", + "shared_secret": "d24fb4e358a5176ae303c88b9bafec3eee2d20723d42a4e487a1b75f8abc1d43" + } +] \ No newline at end of file diff --git a/libcrux-ml-kem/tests/kats/nistkats_kyber_512.json b/libcrux-ml-kem/tests/kats/nistkats_kyber_512.json new file mode 100644 index 00000000..2f14ebd0 --- /dev/null +++ b/libcrux-ml-kem/tests/kats/nistkats_kyber_512.json @@ -0,0 +1,802 @@ +[ + { + "key_generation_seed": "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f", + "sha3_256_hash_of_public_key": "7ffad1bc8af73b7e874956b81c2a2ef0bfabe8dc93d77b2fbc9e0c64efa01e84", + "sha3_256_hash_of_secret_key": "26e1b5ea0f48b3c87d7ce87113b6a93a49d9f7ede7c5cb15b41382bd3243715a", + "encapsulation_seed": "147c03f7a5bebba406c8fae1874d7f13c80efe79a3a9a874cc09fe76f6997615", + "sha3_256_hash_of_ciphertext": "2b5c811b5a5d62b1fc79fcafb1623e81ae164e3d71f75278dcc17a448f106a23", + "shared_secret": "0a6925676f24b22c286f4c81a4224cec506c9b257d480e02e3b49f44caa3237f" + }, + { + "key_generation_seed": "d60b93492a1d8c1c7ba6fc0b733137f3406cee8110a93f170e7a78658af326d9003271531cf27285b8721ed5cb46853043b346a66cba6cf765f1b0eaa40bf672", + "sha3_256_hash_of_public_key": "13f0970c03d32967b06cca4cf58e87559128d14cb3f876a1ed10eadfe03fc1a9", + "sha3_256_hash_of_secret_key": "9c613d0d3313af8169e65295e8c4f21f0b5d3e78de031e78a12ec864d71b6548", + "encapsulation_seed": "cde797df8ce67231f6c5d15811843e01eb2ab84c7490931240822adbddd72046", + "sha3_256_hash_of_ciphertext": "0ab731b2a90f44cdd88aa183be7460177cd6bda0e6738719313dabe6d5ada8ce", + "shared_secret": "ced6ec70083226b02057b7f47e40943320b3d10dd4ad07efe0f007ec8c06b3af" + }, + { + "key_generation_seed": "4b622de1350119c45a9f2e2ef3dc5df50a759d138cdfbd64c81cc7cc2f513345e82fcc97ca60ccb27bf6938c975658aeb8b4d37cffbde25d97e561f36c219ade", + "sha3_256_hash_of_public_key": "083553153f7d65cd5cbe201e681245eda61e1ec2c7ee6b91a9ccdeb6b76943b7", + "sha3_256_hash_of_secret_key": "b4148d4bba0430ddca173618456704ddf440b9b5bdfd61ee46bd79590dd78ff3", + "encapsulation_seed": "f43f68fbd694f0a6d307297110ecd4739876489fdf07eb9b03364e2ed0ff96e9", + "sha3_256_hash_of_ciphertext": "54552c015591d1b598afeeb6cdcc00cd1752f26de95c31663ddf8bb08ca82de1", + "shared_secret": "6f21df33b8398bfa65c9c243214e22d0beb5f0d801e4f9e71d476f8b7e3a9688" + }, + { + "key_generation_seed": "050d58f9f757edc1e8180e3808b806f5bbb3586db3470b069826d1bb9a4efc2cde950541fd53a8a47aaa8cdfe80d928262a5ef7f8129ec3ef92f78d7cc32ef60", + "sha3_256_hash_of_public_key": "9df5746a44b10c1886f62b068d18152a85792781160e1a1a19a25b5ca00555f4", + "sha3_256_hash_of_secret_key": "75a93307372e001d4fb028125dad61c4412ac864bf7eac7a213ad3dca6599981", + "encapsulation_seed": "ea74fbc3c546500ed684bed6fe3c496d3b86d2d6dfaf223969b942e9a8c95e85", + "sha3_256_hash_of_ciphertext": "2f13118bf54758dbcd116ab20f28cbac8e58fc25c2fbc88243e47989266218f2", + "shared_secret": "960b57f0feb34aa25d29a42a94565f697a8133aa1b7407bce017c8bb4a6ecca8" + }, + { + "key_generation_seed": "66b79b844e0c2adad694e0478661ac46fe6b6001f6a71ff8e2f034b1fd8833d3be2d3c64d38269a1ee8660b9a2beaeb9f5ac022e8f0a357feebfd13b06813854", + "sha3_256_hash_of_public_key": "9415ce164fadececacd75fdad3284af20c52fa576699029d6e0ce77bf347d520", + "sha3_256_hash_of_secret_key": "97f1f85233dba2a50848add15f8f0e60f4ccf3542dc6da5f59e06f6b27c59c67", + "encapsulation_seed": "64efa87a12cb96f98b9b81a7e5128a959c74e5332aaab0444fca7b4a5e5e0216", + "sha3_256_hash_of_ciphertext": "a1e6ce10b56dc14c5afa18fcda0554b0f59257cb4fc1b6fe65d44b9f7d7244c0", + "shared_secret": "dcd0210cc9f2b15b448b7591c54f94deb65ac30c9f2de59109bef5cd4ce34d96" + }, + { + "key_generation_seed": "7ec408f52c9aa723d0c41d9987682a5f4ce6c9da7cd0215af60bbaf5484ab353a08ccf451b049fd51d7a9ad77ae14a81569df8c9bd3a8f1ebea86fdcfb823082", + "sha3_256_hash_of_public_key": "ca2232297ba8b986dacd401896cb6239f557720d91a2cfb7a73274bac7a0f6de", + "sha3_256_hash_of_secret_key": "17446e8436a68423ba4e22a57135d470c7e91fbe0a4da065bdc34897fda89b2f", + "encapsulation_seed": "8a95d71228acaa5f9ae6f9d9ca8ae55fde296463b41083a39e833e37c4c90f88", + "sha3_256_hash_of_ciphertext": "eff68ff781fc3c7f149ee83810e5071d71529eb7c6e73ace8763b03302db7401", + "shared_secret": "eb0a5a154a1e9a97633929cd64b3c7e61b58ff6eae29c994dcbed1bf2708e99e" + }, + { + "key_generation_seed": "c121915bfef6abdfc177dae2f5a24218f9abda2559afc6741b08e0e61ab433eb84ef52db5eaa6df8ec3a0bc5ffa730db0dde8c5f38f266d5c680a78d264a7b96", + "sha3_256_hash_of_public_key": "34486689b387ba25dd0e9aedbc53034924ea4ef9497b5772f10ca4d091e9e846", + "sha3_256_hash_of_secret_key": "94419fc5d865a97586b71a3414721f04473d4d30e5a8d6a1c438752f19504209", + "encapsulation_seed": "90d79d75d0bbb8921cf70d46bab497022a8e750efdc99e5f1bae653275441c7b", + "sha3_256_hash_of_ciphertext": "86f9c7b65f3393470fd495de39f39dac434f3cfedd5cdb6eb796708c542022dc", + "shared_secret": "ae285bb95fc5f0ee80e7fc232c952062e5bfb8af0889ea344ab3717ec1a2c6ec" + }, + { + "key_generation_seed": "d86634ecf96cc2603761e284c0e36734cedec64e7ff486469e38539c71141c5a99daf37400cfe59841afc412ec97f2929dc84a6f3c36f378ee84ce3e46cd1209", + "sha3_256_hash_of_public_key": "39d1850f7acb36ed2a35e9af6f94a06c31afadaae3545a069f892ecd8929f766", + "sha3_256_hash_of_secret_key": "98a2ef35596f2fbc7e462d5ee536f30d8bc3a5272d78cb14c0ce816fbb180396", + "encapsulation_seed": "be8a32f97b9a8d596382c02fa2a0eeebc15c083e970ddaa4f2622b91d6718663", + "sha3_256_hash_of_ciphertext": "eecf23918145c2891d94561ba207817d52da5b5405661dab4c8be5a26275fd45", + "shared_secret": "74c903fb47ce2b1e24b37136bd96cb5fa2d39681fdedc4b8b0c6e9c7d1d6402c" + }, + { + "key_generation_seed": "0610678ff4dc3128e1619f915dc192c220f8fad94da1943b90aaec401683a492da1804ddb5aa9b1c6a47a98f8505a49bae2affde5fe75e69e828e546a6771004", + "sha3_256_hash_of_public_key": "edc8db1ca35744a75ca14516abe07472d0d1b723f70ca8cf0e5c9341fd2e8c26", + "sha3_256_hash_of_secret_key": "fa6de16f50b0c04b8be10d3262005227715f69de5089f0f6bafc1fe26603e525", + "encapsulation_seed": "da2cfaf69e25b2a89ff2557bbb6f69e01d8e2e7bb27a7a1ce7e40fead16f33b2", + "sha3_256_hash_of_ciphertext": "74ebfdd5e3a3cba21da6ed1e27d2f18ade4255f2196bcad52831d76687bbf0a1", + "shared_secret": "df09f5512a04278a474d26b15ebc89f7258a3902895f7282f1aa5141bd45efa4" + }, + { + "key_generation_seed": "d322d56d8ef067ba1f24c92492b9c56df3a6ef54a304adc1b69913766a1ce69756047447b810cc094d400ab204cf9ae71e3afa68b88586ecb6498c68ac0e51b9", + "sha3_256_hash_of_public_key": "b1eef6e8c88ff8da9cc4a9b01d4c08b6b585beb5bb9e084c6c47a717b51feea3", + "sha3_256_hash_of_secret_key": "bce9d6b2e45918ea5798910aa9baf289b04d8a5bcfa7e08235dccfc8b9479f55", + "encapsulation_seed": "511c2ab40782322c06111e144e505328c4e5bfc890a5980a2bbc44aeda4c738b", + "sha3_256_hash_of_ciphertext": "4890731ec669a749b6b29fef58534111e8b74a8e66748a911fd22ad75ad641c4", + "shared_secret": "07d4fe5265fe82cbaaba139893ac89a4535b4f97f94da29282478f16266f483e" + }, + { + "key_generation_seed": "2f1d8a3bebb34540324b9485fdf3d5be3b858f544abc3fc641b5728cafab03ba8d6c42e7270ee2b77b6045385f3d175984a0e260363166c73b0c70c971644363", + "sha3_256_hash_of_public_key": "f581c2fec9055830b38cb68fb506aa927443b1afd1b2b6faa6f92a325985c6ce", + "sha3_256_hash_of_secret_key": "9567f27ef67c3ada92a02cf25d8ee4a6db69744d3f6de5a0026dac023d04f37c", + "encapsulation_seed": "dca92dbec9b260dd97e8886f876862d6effc3b91fcf3fbc986cf56ab93ae79a2", + "sha3_256_hash_of_ciphertext": "6391dc58f54bed05980ffaee42503d1fcde4923b9d79a8ad9403448716eac944", + "shared_secret": "fd481cd0902efd9a163377000994ad86e154bcb2b6458ae72cc7cafc125db981" + }, + { + "key_generation_seed": "31beda3462627f601cbc56f3ddf4424e1529c04737ef0ef2af6d7401f653b8a1812083bfa3b670e3eaf9b443702fb6db16ac1197656bbd61a8e25ed523b8d1e5", + "sha3_256_hash_of_public_key": "f12f3ecad62bd327f1c44ae86c0be6e7f15112b7f6f6d5ec7b13f4dfab718965", + "sha3_256_hash_of_secret_key": "32a666c02a41f7b9408c570a3304a80e947a1be650f5f164e376b8b34b72254b", + "encapsulation_seed": "57c170e691d7a914a901b9a11c62b8b569b3806427557a9dbac9faa720ec3641", + "sha3_256_hash_of_ciphertext": "9c0dd336b9670319d3f21fea39273506ee797a1b3fcc49c4a113823b5698c0bb", + "shared_secret": "bb711ea4b517003b1b1c893b5a84e52c7e5b85c02703e7e909621a8e3dcfcb6a" + }, + { + "key_generation_seed": "cbdff028766d558af4466ef14043a1a9cf765f7748c63cc09dceb59ab39a4e4d8e9a30597e4b52ffa87a54b83c91d12a5e9c2cd90fcac2c11b3a348240411a4c", + "sha3_256_hash_of_public_key": "4cae8b58e0434fb1475312355a8b40145043bed4b269aaddd654d2e562324bc7", + "sha3_256_hash_of_secret_key": "53793d47a6e9e527f109b7611f33063dbe0b8a1423ac02178934f59c3d47ddb2", + "encapsulation_seed": "6b5a14e1473abf5a33d44975ca2088bd8fa6fddcb3f80e8fd5c45b9d90c24a5c", + "sha3_256_hash_of_ciphertext": "7cf46d048d56cedddb954d66c4fba4c6b665f080e21d9c1ba1ec90b83c6a737a", + "shared_secret": "3cf9e85c71f1e4965a26d588d3f2ca74d4ddbf2d83dc15033b1566b7672f0bf7" + }, + { + "key_generation_seed": "4c04310bea66305c6ca8ba6b8f61ca96257a67663afc11761f13fb5c7b324b6b8aec87a9a79204cee2986867a2906eb851b734b8b22b91d6749b1a5f07c44e3b", + "sha3_256_hash_of_public_key": "b899475c1802b1dd76a9783d93b4225dc558eea558ddc598cdc45a898b7bbfb3", + "sha3_256_hash_of_secret_key": "278b448b48a14a9be1ed211228cfab37d07e5f1e502478e3ad059c83a7c83894", + "encapsulation_seed": "40e593754e6eddb7f9cf176ba2d5fd1087c90ad377556d0b0f686537b1a3165e", + "sha3_256_hash_of_ciphertext": "28efc6f97bb20ff7ca5e5bb1ec91f15bc4cdfc43c37fb0499b6de6b1927c3f85", + "shared_secret": "82b4f6cf697d27168ad2a66041f86c6586494c39db2ee32181970ecd82a1cdaf" + }, + { + "key_generation_seed": "38a0d5f41d7dc1896efd1b45b0485634cef149828751b96087a0a6dd81b4d58aa2acf359556df4a2abaeb9dcee945829beb71185b4d6bd18b76e5668f253383a", + "sha3_256_hash_of_public_key": "1a7e0760c345cb5875303e20e4c72076c794e56ab75231750a190b45f374d979", + "sha3_256_hash_of_secret_key": "eb53a36a9f50baac64b4c7bcb97fecae54d3f66b8311b5a67c5daaefaa63f209", + "encapsulation_seed": "c152523abd8248bed40c3827bcf0f8e8127037a55c780695e2c28ea3e041a44c", + "sha3_256_hash_of_ciphertext": "5b9bf47edd293d4ee9d22da1d60f34e0ce0a6af7aff645b0ba83dcf786f91750", + "shared_secret": "0146eef9ba45c59a7915db7431f20308f6b230a5a459540261a5be425c84cb56" + }, + { + "key_generation_seed": "97b5665676e59e3538ebadaa8cd50df1f9fda1502d9894c616a946078e56b621df05318b5f655efe36f1b678cf4b875108a18db2fa312261caf839f84bd956c5", + "sha3_256_hash_of_public_key": "0f96fb9e146a1c22cc5d23e9108af0dc5e13b7810b8f5598bbd5f8d4b54c8af7", + "sha3_256_hash_of_secret_key": "d494ee913886be1398be54856ebc83eb8cd7aab4268b976583be2e097edc2d64", + "encapsulation_seed": "ad6466dd59f26b762fb02b19eedf5f79964da68bce0459b91c3a6ee5a7e01183", + "sha3_256_hash_of_ciphertext": "8113b92fb620228cfaed30cb0533624694b841550bf968f6d2f6f54d3572e551", + "shared_secret": "d1446f073de8866970b868a0282c2865682765ced8e3e2adb6d09821f69ec64f" + }, + { + "key_generation_seed": "ef99224a03a85a46ef115474ec5b5d620da6795d6efcca4c9135d19958a9de62df7d92dda83e6b2ef4cce08c9134563063068a196d7b1a1a13623e48ae12528e", + "sha3_256_hash_of_public_key": "0bb63b48b8cdd1c7242bd4f017c519b43502656e23817bfd683150488f8b0b44", + "sha3_256_hash_of_secret_key": "195207c9e44942d5cfbf338fb9f20317d3ae8be85dac5f10dd60abd802a3caa9", + "encapsulation_seed": "1a4d5dff5847cfb48333e33bb00ca7301b144aa89dcd412ff5a3b1081d775b7f", + "sha3_256_hash_of_ciphertext": "4ec91f151989a1dd66a3c64b8f5e51397c057e42df7bf52f2e751c758cf56a43", + "shared_secret": "ed8f55fba251d1f3090f77823ffb0d91c7028c66cddfc340bf9945d9a56d917a" + }, + { + "key_generation_seed": "b12f6fd965ea9c5b947db80fc60c83d5e232dca82e7263027c19bd62e5a6ff550f6aa3e88f7fa8a96067f8cdaeceeac90c2d0b5e277e56e9c405ec9420c30252", + "sha3_256_hash_of_public_key": "2d19bf7937eeab0d2a7570d43cf965547542a519be85bdd4921f7d710747ec6f", + "sha3_256_hash_of_secret_key": "cd59ca5c7954d87bc8d025683563aab0f9272d6c12cc03914220aa6ee392e6b3", + "encapsulation_seed": "34f44ec2092eeaf686f2ea170591a98527cbb03a4fa9477a7aef6b41a54feeb2", + "sha3_256_hash_of_ciphertext": "ec50a4e6e09d3426a521ac9ea3c1d00378a48c21fc57868b82a5dbe89910ee34", + "shared_secret": "5451fefaf1146809cc45bbb88dc3726dd4754bdc9b25b31b2f7e1e4d35785ffd" + }, + { + "key_generation_seed": "9f52af92ca165fdc38788f2b59ba02e01c8281ff7c1e60504688043a5fe814b04f3029e1be4e1c0258c3a22ff5b50b2674cc094ba7018da2a61569845c17d26f", + "sha3_256_hash_of_public_key": "6907e1096410ab332e10f37c93d86d9b4657159eac1faffcd1688d182d127844", + "sha3_256_hash_of_secret_key": "250d27ac4dc4447520c4c1193ac57d239857ecbeac2b1009dc08dca2114299ed", + "encapsulation_seed": "6250c81126572eec2da330271db36ee591f060fc7e53eeefe2e1c476c675fa33", + "sha3_256_hash_of_ciphertext": "47f62e4c1d7358ecc33b194c4fba1f51e863083933195285fe79388d95dac887", + "shared_secret": "ec2df494562866bfbce748ae941330435364f6b9aca579b73f00d576fdb9f967" + }, + { + "key_generation_seed": "851ea90fd3854cbf28fe39fb81f68e4b14345cf0d6eee7ec4ce772513df8410d1c0ec046899a777655233e4e1b5ca44e9afbdc67964bfd5d5e3dbb45e60d03cf", + "sha3_256_hash_of_public_key": "379c9176059f3a7ddfe021041301bcebbc91e997a0d5bf2ed1d9d125a7129834", + "sha3_256_hash_of_secret_key": "57df17dd8b9b1411af66d82f61dd61c4f5235f48d503c164ad0da02a598a69b2", + "encapsulation_seed": "35d470bcc5880872754810dfb3f2796da2fd7f397537146f6488c27804072b34", + "sha3_256_hash_of_ciphertext": "41f346ea5b300716d44b2ad6d5a075d80db7e8fbb10f3ef4a113c22c82300280", + "shared_secret": "6613e6135f8bc9f03a2e1207c85cb568e4fbb7ac5cb525e2c9951b040294d360" + }, + { + "key_generation_seed": "d304c9389cc973477f169788abcb9d511f843219d246a9b587822f422a70c2386590a2e5c7ed86cf2c5c2a898662bc9a81418720bbb632ef9cf0b845ed052d73", + "sha3_256_hash_of_public_key": "f5515b23187af5dac6d1d090bc7bc01df34ec781561e3d3b8b62164f74946802", + "sha3_256_hash_of_secret_key": "2ab40ea093450e534152efb278b45038f1f2cccf13a654f1c5c27b8c389f6129", + "encapsulation_seed": "8d667921c5db401a86fe1c35dfcf164a6bb2ab7400fd6a0b67eafd4a0ed11940", + "sha3_256_hash_of_ciphertext": "9c6c6acc0744a45b0ac072c8beb467fc5390e5f73024ac40567771feacdd9f59", + "shared_secret": "54cfe9697319a1d1b34e8e9a80d019ab5f574655763c9e36da4777f0a971bfc1" + }, + { + "key_generation_seed": "89a6e3be304a3518fb82b18ca730f0b359cd6ba90664a493fb4f8edaf965b9c3b6591121e25d64010c25a18676033e1d7278ac5f2d0b43a31f3a4156ae710465", + "sha3_256_hash_of_public_key": "9dc0d69094efe63d751e6f9c1e92d2107a7b45fabb820222d30b11595c351643", + "sha3_256_hash_of_secret_key": "00f4a04ab804f2fa3ed80a0fa4530fd45ebff8afadf5f5b7d46a672c690ac3ac", + "encapsulation_seed": "ec750b3939385a3f8df868119dc76f77ca845567ef068de6ada5478a56bc78b6", + "sha3_256_hash_of_ciphertext": "613a54d8f61f528a3d7c4d346aa63699da6bd97030a8b32e7a5c5c0a853893cd", + "shared_secret": "2765ee1de38d074f1086469bf13fe168cfdeb6e609a47d37dc9b8415265d953e" + }, + { + "key_generation_seed": "d569b935ce015c85f792f8f7fb0d83c4f53b492959361dd4f75fb764d656450176eae84d11c4528382828f7a689a0d5cff87b8ca0bba97feacb39b935a8788cb", + "sha3_256_hash_of_public_key": "16829a8aa9f8c4e949d4e6388448c2c4ec6a977f8c5fb80bd75d93a723bc9bbe", + "sha3_256_hash_of_secret_key": "659cb66f989532fdf5a741fd03862fb142a05a0fb43ae20bffc5116de1a66d57", + "encapsulation_seed": "74f1d52af09b12c36eb062ea7528550cb4c18a3ce8e4f4ea9fac43ae383bc925", + "sha3_256_hash_of_ciphertext": "9d820c8a0bd7b3cfaae0906ef2c60e494e20437312f164d797d2d275a55a4415", + "shared_secret": "5323406c537e4300c70220c866666848970d29759983065ec5de317b372cc265" + }, + { + "key_generation_seed": "5cbb141c2763425c274f7404fe530d9116e08c33f9f200a20b011cf563a28990fc9ebbe336dc464489861db8253606971bd0a9008a433ed17752d04023781552", + "sha3_256_hash_of_public_key": "90fe22b38a4fafc045cdbe0c9689745fb45760cb2f0f94f7d13cf8c834c4df3c", + "sha3_256_hash_of_secret_key": "10a89c990c7676890a65e1c776cf892ef1431d56fc115ef3115c0b8f91db0690", + "encapsulation_seed": "4b3a70d85f640d1a2a852fb6fe96704af56a7415a8ee4282e9207bc3a2dc116a", + "sha3_256_hash_of_ciphertext": "fe9bf0efd8389fe0a17a3a515c3b59db6b5afec136bea671eefdd3db328e002b", + "shared_secret": "38f766601ccacb7fc75a27d16dbb585cc3a33d21f39f9a284dc389ce998e85e4" + }, + { + "key_generation_seed": "293abb6d1c207927945417cf84883ef010823e11b487ed55239e466e83696d0cff8563038aad865a817cab9ce98846ba75be9363718ecf5fea538aea90b2a558", + "sha3_256_hash_of_public_key": "c277a9588d9a781ddff6aa9ea8d259e5599d0adaba2f459598ebd5bc72786023", + "sha3_256_hash_of_secret_key": "40609cf26d205ce694ca8baa097bc1342d2462a26678eab90893da147e389d3e", + "encapsulation_seed": "26e38ac804fb5b4d59ddf747715e7e6041d875f99c7b638024b4af82d622da60", + "sha3_256_hash_of_ciphertext": "eb1bb3dfc58f01caf3086472f4c0b6fc4d930d9ba8b2691a8b028a6201a410bc", + "shared_secret": "5b052804906cd6a9c2469f8a813c652d47013e11200f1c894dc1650222a75eeb" + }, + { + "key_generation_seed": "74d87c7556f2671f2d666854a4d6e073e69f35421e6e1a428cccea49c37f972ce1fb7456ac0aa1b97068f452cba64ebdc138bcf5d36b0a0fada2a3b374141eb9", + "sha3_256_hash_of_public_key": "d3c8cc315c4054d09deac08c6d5d364fd5d47a3c09041bee42c561f978e2d98f", + "sha3_256_hash_of_secret_key": "3e1b23ca9dc111c4a3cb0a585c7f4e5d1f27a71533eaa5347e285c7c35e81990", + "encapsulation_seed": "a319d2b8f114f1acd866478bcdeba6fd164dc4e37b0adfa8d8034afb3e197376", + "sha3_256_hash_of_ciphertext": "ed4f13168cf424c1b7020f739850d313e703e026dbf3bf849e9d8947a2959f55", + "shared_secret": "7dc822f6f29c56ffa58e7adf1d98d179a48a8cf4d4c021479ae02da889225615" + }, + { + "key_generation_seed": "013bab0212d04ecd54b478daf72748003a25e2cb060ba6cc50bf95c292b8206b9da0c5da5f195b80fbb99c2e8b06926074f3f604b3f6195b5a5b9737876bba72", + "sha3_256_hash_of_public_key": "dd1a07043fa0c6452500249601f25de742ab44213e2718cf0ddc5ff6a2a9aa6a", + "sha3_256_hash_of_secret_key": "2cfeaf5c1b4195f0374256027d3a888e9a093de8ff9181296d5b1b94048de38a", + "encapsulation_seed": "ff646071b2509e6b75790917e08e4f0b0d9f0116ec6291c0b59eaa4b583ad830", + "sha3_256_hash_of_ciphertext": "5c6c65c50828cf5b218c5405a542871890e4d9db1463c88f7ae8c43c3bace143", + "shared_secret": "7d97af269e4cca8bfd59d6f7602b7d9dd49935f914e64e72e8e4a755daa2bbdb" + }, + { + "key_generation_seed": "ccb073c4b90be0ad746e26fb093b60c70110bd1dcbcddb566a8cffb7b3caf80e71600a8982c350df524cde514431ded7aec23576530894bcbf0ec0bfef0bb64f", + "sha3_256_hash_of_public_key": "f2a8cad42c743eb61aa338049ce917616899c803358541de1e58cbbdcf3c6328", + "sha3_256_hash_of_secret_key": "7a9ebb792c7193ffefe6e4760ebd0dec6f67c3f3b0fddb5abb4b7e931ee827e6", + "encapsulation_seed": "0584270ec26f3b9818e4af074d17b2d51037cc8dfdcbe3b140fa4fed5deebc54", + "sha3_256_hash_of_ciphertext": "05b31d4049fb6f315229d0bea9cdafc0c20d52ff6f39be7c9ae4592068ea973c", + "shared_secret": "310980f43e8bf63480d0dc26864a664390977ae920b2596abac62eaecde95db4" + }, + { + "key_generation_seed": "2e889f44e28901e9ac7ca6b2fffcb124c8979401b17064d7e1d51a7e3c3adbfa0e145e44aae52cfc609e6f47fd7a6f6af877190ff52256d0ac5b05b89c3f449f", + "sha3_256_hash_of_public_key": "3394e8401245fd6348bfa697f6990b6671577ec7b35a45b0101730a801942643", + "sha3_256_hash_of_secret_key": "3ecbb219e90e2250ad5ba87f53975439cacc030c3e1641b87ba8c5b3d89a4aba", + "encapsulation_seed": "51e05c7b4ca3079781e8293f4eccebeeb2f8c8b4c59468eddb62a21bcb4ab8a3", + "sha3_256_hash_of_ciphertext": "cfae9e2e3665d0118a35dc83d3fd14ae0e6191d7ea3de8b32a34b481e5c7e332", + "shared_secret": "3763c0093e1aa763cee3645ea950cc2e14bd17cfbe5a0c91f1a08e2ae2037ba5" + }, + { + "key_generation_seed": "174aaa36410566dc15a5e62874218d7abdde0b2c0f30d877bb80b1abd5f5a0a450a7a2354f7e5cefa6f4a4e9a1c411eb9364506e9e1204a8acb3cb77fbd2c4ed", + "sha3_256_hash_of_public_key": "ec9c0d68c84cf3804f14e8daffdd1e28c28d3d55ee782c98c498b0d9bd4ebb23", + "sha3_256_hash_of_secret_key": "24a2b3c3efd979a1406e92d5c504d5004079965b5fd0492469f1b4250f7023ff", + "encapsulation_seed": "9eca0fe36c80fc5eba171c3ae66a5b1c923faa50b4521bb055e7bf51005c93df", + "sha3_256_hash_of_ciphertext": "e45badadb492fe0455e4cf2f715a25905b2485ea775d68174b8fc24c74b762a8", + "shared_secret": "88d2d42138ed5b56ba4c57e7edf322147206083b80fa313233ab6b9ae0bc7634" + }, + { + "key_generation_seed": "351fe4313e2da7fac83d509f3103caf7b4c64a4d458fefdf636785ac361a1390f072d9b5a99f9c7a0a011e4dc10f6b600d611f40bba75071e7bee61d23fd5eda", + "sha3_256_hash_of_public_key": "a9d7d5a52aa2dc226832f6e4603322f60b1dc21207e3360712f9c6445d37e64d", + "sha3_256_hash_of_secret_key": "2e5342a1c2f58a48e044a26673799c63f88656f6d350a0d7e57bbf8811b2a5e9", + "encapsulation_seed": "0c5719261caab51ae66b8c32e21c34e6d86ee4aa127d1b0195663c066497b2e9", + "sha3_256_hash_of_ciphertext": "e48092d2cce99e49b51d91d1e5e4dff42c976c1d9476e33ad28a639087aacb8b", + "shared_secret": "13fb6a49481d54cf39c2b0303561b262a605b0310d939e6a531f62db01118d06" + }, + { + "key_generation_seed": "9bc5315580207c6c16dcf3a30c48daf278de12e8c27df6733e62f799068ad23d5a4d0a8a41c4f666854e9b13673071ceb2fd61def9a850c211e7c50071b1ddad", + "sha3_256_hash_of_public_key": "fa7ba132b5dfa2e3ce67b64bc72d551f3290d428cfbd45ec026f44c8dc28334d", + "sha3_256_hash_of_secret_key": "34306d06720216257691fc65054ed32decd609312f5c5f061e7763ae73fe0aba", + "encapsulation_seed": "0e59f6f9047c784c1f00b24454aa4f1bd32c92ae7e626549972f86fab90e7e89", + "sha3_256_hash_of_ciphertext": "7a841a9f2c657ef29492a5002bc33a1e676f4d27b096453603b2995c7fd4aae6", + "shared_secret": "7e68f0d508a62784f2da4957e8dc092c19e523876202121379e03498b6bd6a22" + }, + { + "key_generation_seed": "d8b907b34d152ff8603b73051f772daa71eb902c47b7e2f070508269d757e02e36b817736cbc5f7b1dd6eef5fe6332fb1a598f3871e5470d440fd2ea631da28a", + "sha3_256_hash_of_public_key": "29f8a01ba71d04d6831c03d1ff294fb58ef6f4041772cc071074829c32a3ac9d", + "sha3_256_hash_of_secret_key": "95f9b4063bf05f89ca9f99e393b11c0f2105eafe40abb313f345b58e10519955", + "encapsulation_seed": "a3963ade17d69debbc358dda82c7bebe2c39d25b36813058e7a161542e3f8c2b", + "sha3_256_hash_of_ciphertext": "f6135ea3dd3fcf41c05957caffe20e6f2124e99ada7fbceba6dd6e13c0bb1fc7", + "shared_secret": "d26602625ccd72777515c2161999b332022bb25e0f9310312e605597c3d8d4a9" + }, + { + "key_generation_seed": "684a29e4e5480a5f2533e1526b5fac8cdf5927f3d85087c71f928c59690eb56575d12195ec32a8686d0600e45d4a7f54219b0d7a3826d193a51b9156ecf2edd6", + "sha3_256_hash_of_public_key": "357376de9843d74252466888727f9dc1ef48d028c0f52c902aa0dfc3de374c83", + "sha3_256_hash_of_secret_key": "b8d675ce213c73f9792f328448850047f4410fc500212939ab2e234b619c9104", + "encapsulation_seed": "97beafabf2c8575586487c7a80e8af5fc50f94b6051c1bc66a5ae9f66be3cea7", + "sha3_256_hash_of_ciphertext": "c7dd4f838ea168ea97c03233578805b5947d4ba33db0e3d11e3e86dd011c4110", + "shared_secret": "7880372c71846216f925e718ffe2b65124a09e4b40d636f7908fd26b2e5d7cbd" + }, + { + "key_generation_seed": "d76b3573f596eb286ab5231feec7499686b13021be36cb126c7ebeb9d7030daf248c0a21ea0bb6d6f56f12300e8584d8e9a34e0e6f52227281151ae4c305fb8f", + "sha3_256_hash_of_public_key": "30382cb59feee1b6b0fc129fecb8c74034da92987249bc20cc8ad4a2cfc1bfe0", + "sha3_256_hash_of_secret_key": "2600203271549828d0979adea52e2e976b7d9f85bfa6931d6c79e14137fad51c", + "encapsulation_seed": "75461decd34c50d6a094b4a64fb75e5e9479f8f9250d82bb7d729dedeb2d4b65", + "sha3_256_hash_of_ciphertext": "10ab9f39a7a92db8e0dcc1065fd4acf0d4a564ac5d29198b4f50a0a2baa60ebe", + "shared_secret": "cbb85ba073be238cbf61c5a04f0b8ecbbd1ecd19efdc1aa3d55778ef7e9ae537" + }, + { + "key_generation_seed": "b87439fde81c9e39eebe7cf741c685785532c1dd23e8ef868b9ce7a541010f3d1646460817a0fce5836bdfe124a7448e7adf7b8ecc2652ac6d280e986682df71", + "sha3_256_hash_of_public_key": "f4e474fd64a6d945e85eb4ee7509cc99fd4054de99f819fdbbb05c54ca6e36da", + "sha3_256_hash_of_secret_key": "d8a3a0edc73fee057281add9e7cb328566fb22c5082978c69088d76e98ffff90", + "encapsulation_seed": "2607dcf4fd6ca1c614c21b5e37c24981c32b91c8c3e6955777da8a3f5d9c9335", + "sha3_256_hash_of_ciphertext": "477b322b89c74242f03ff99991aa6af2dc2202b746c3b83726f596925b527f6f", + "shared_secret": "98c0fa44e2a053c1a84a984d8e0acdfbe1c17fa07f5f8f0c9290337da969e07c" + }, + { + "key_generation_seed": "056661b38038da4fdd7426f32a81576c73ed84843b305168a374f934e27a4e1b79238a80dcfd7c992d84b2dffa67493e669243d4fa38c46b090bdf86bc548411", + "sha3_256_hash_of_public_key": "50688de263a82386f39a7b82592247bf5499f1836a3a941413c75f6331ce4031", + "sha3_256_hash_of_secret_key": "ff207007724ca5d696ba44cb106f525858111d55323c9fc0fb98d64d4f8de8d8", + "encapsulation_seed": "38c89bbe7145c29e9a831c11431eb9929cb24fb4992db20737e4687d397fd732", + "sha3_256_hash_of_ciphertext": "67927c10c08db1437d0dd05b43c0f57d3ad4024b80bdc81d8da72caf045a9c61", + "shared_secret": "48afe1582c88f7e89caea5d594665c0592140f0615715d158b7fa9ae1544c6f5" + }, + { + "key_generation_seed": "a1b52d871612a1c611ae0944f9e71858f35d3bd14f20e96a931720668bdf0a6b1f135cf64b6403e103afae34da038613e2853bbfc36baafa3c6a95347193f37c", + "sha3_256_hash_of_public_key": "1a29c0f2dc4089a85db6865ec90faf2f4ddd25f210eb56e49741866bbca8cf81", + "sha3_256_hash_of_secret_key": "477dbc28e4f21587f274e7a3b673f743840da1501c35f0e9ceb8972970de6f86", + "encapsulation_seed": "b2c35e33c72d90182791f0e12a0324f5b216efcab2c8da1bee025dfbe13f4152", + "sha3_256_hash_of_ciphertext": "3f4ad369a64a954a2538fbe6edf8b47d79fec8b429850cea2eba84bce857f87c", + "shared_secret": "bbc34eb1e6888d28a44ea5eaf8a85490e8a1e79df5ccadc0836d86a0dc86b867" + }, + { + "key_generation_seed": "952b49c803d6d6fba69f4375adce8594847a00bcae2179da49af2aed0423250262d7033947ae42ca53522a65fbafe18d3bc3e0cb66164e9a094fe4b44d8977ed", + "sha3_256_hash_of_public_key": "3fffc419d3d8a887ff789eb661b2af1ee5b32a302ca267b33eac2ea7e3340b97", + "sha3_256_hash_of_secret_key": "0f42068d2885e1a44b2ce4042675118f4fa35f58c1206b965b57ccb52c4f25f8", + "encapsulation_seed": "afb7d6dc2b7eb6d84acc080c1be63c98afe7b07786b5801f716444a3e8e64800", + "sha3_256_hash_of_ciphertext": "063bcb3b4eb26ac9789cc5107689cebd6904188f2203c6e8e06f8d784c3dc739", + "shared_secret": "abde3e45f9ce3c4e18f9e224d77f24cb1661b4aa4850f517b402bb4edc8e50e8" + }, + { + "key_generation_seed": "3c815e57e9233e975fa1630208aab206b71ae0db37a7a8789ac683d9f9b2d29801c8e376fdb140ee343106c093af7cb149b316ba79446ceb4e5e0cedb9b164f9", + "sha3_256_hash_of_public_key": "f1de70b1072881eb659a5e890a92c9313c7378d2e960a060b9c918260d4c2458", + "sha3_256_hash_of_secret_key": "ecd9d757d80352b4fb51c71976d7b2ddeb927052f9f7a7cc61fa67662d4dc86f", + "encapsulation_seed": "28f5e9dbda122b2cf8f3754fe9e0c73a84ad4b0c093522e0b62cf815d60bbc3c", + "sha3_256_hash_of_ciphertext": "e8af1ac63796d2c1d5a622e4937a42a2411603cb777c2f184b8b125f155a04bd", + "shared_secret": "dab67f76598e58e51bed06884ac65105a9051a2e4dd876671b0ce67fe49ddecb" + }, + { + "key_generation_seed": "588760826dcfbd36d9abe6ae44a669bb3ebba6a218eab69e30f18a3bd536576e0e860576285483bb5fd36e2f944d32c4317bebc1e441470c1372046a790d79d4", + "sha3_256_hash_of_public_key": "b0c77b5407577a9a9cd8864efb80974aae107fa2801b6ccaf341d5456a86621f", + "sha3_256_hash_of_secret_key": "0feade68babcf09673bf843c59379520c19081f2bc33940a8dfcee07832ec66d", + "encapsulation_seed": "b0d713cbef0bb1df70cbb425d1e9373e9f7790fdc7980cc96a240dfc53f1e8e2", + "sha3_256_hash_of_ciphertext": "e19701f9fe758727a47ee5c8e128028a0e56daa8663fc73f58201ea593bb7872", + "shared_secret": "23d0479e4b6cc2d32a1f73c2f1657be561482bb0e3f79ca988faff2ee74dd1b6" + }, + { + "key_generation_seed": "47550e9edacb6ddce3d9ab81f6b61080dd4f2693854acb05e0ccc7a4fb6390fbf89d7d99d5c3e0d10d6ef9af054d842375f695abb28e3b8eb495100f04306e92", + "sha3_256_hash_of_public_key": "255d2e2fe01c87cf70bc30703644fc255f83fb47cc5cc5ae2c0e49d6198cae03", + "sha3_256_hash_of_secret_key": "1b1050f38bdb785ed43daa264b60c7946d93f135c65e93c95c39fd1f2d7b5311", + "encapsulation_seed": "32bdcdb7059fe27f6409901980c080308951ffd90deffa8317b4d213a5f04495", + "sha3_256_hash_of_ciphertext": "0e168eadb14ab8fad671a8d1ff467e8463bac9fc42b80aadf5679fd0f250f61a", + "shared_secret": "13d8358c95077d991ccece97f8c4a33ac938a847eaed64e04fa8484f3d27ed4f" + }, + { + "key_generation_seed": "610afb64be8cc1df288cfb016ee2f44c6c07113de7f6fee071fe0c3fe31c6215cd292e4c5f9e1a55e0489bceffb204d672a6215f4f3980a646d9f880817c52dd", + "sha3_256_hash_of_public_key": "63b304a19162abdc4234e6046109f99f955695580a8b782017e107e45575bd78", + "sha3_256_hash_of_secret_key": "19aba21e57d4b3aca7209fd5cbd15f9e7cb9f6777960d9452fed866e9e9234f0", + "encapsulation_seed": "4ed7c92d83bd03b2a25b567f17ae55542e2f6a4308ec0f3fe69f8ba5ae24331b", + "sha3_256_hash_of_ciphertext": "478c8f05eb8faf6f7e4d545df141d8bc0e170c1765872ab950d83949c5c9f1e3", + "shared_secret": "9f2292ef064bff3c7c2d576eb668c3adfc7ffcba3635bb871493479250373bbc" + }, + { + "key_generation_seed": "e1953800acaa85ac02a906c72cb8e8d704e8d27820345f88f71e89c1f549afcc8c64c049c6dfc0f1476cffd520b055756162f7ec94243de6b14ac0b9e5fb366c", + "sha3_256_hash_of_public_key": "3c598a48b06d7474da19ca85aff6b2b3303b5d25b96088c52a08cc7f1e87c5fd", + "sha3_256_hash_of_secret_key": "03c563426eb21d277421a30ca8980d4de86f7aedead9ab9aefb3d7362104ec50", + "encapsulation_seed": "060ea5d2ed1dd88144a9885e79278590821c22917b55a48920f96b53ebe0e689", + "sha3_256_hash_of_ciphertext": "265077ac3d5228c3822a5d3940fb676bd5b40a0d03fa03fd7ad5f8c363d462c7", + "shared_secret": "29631b1d85f23a69dd1de78c0d931741bd4a4d7d6b95f4baf74bee91813220c6" + }, + { + "key_generation_seed": "c719f9b2d16399b7326ce4eca30dabefe8fdaab18e9f6df888b0a134ef355570e40771856eb77e4633504899fcb86c6a3d433d0b8d60e26f07bd61f1d4ed69bd", + "sha3_256_hash_of_public_key": "9911b6283fc6dee66e16d411fe39bbc9f53c30bb54f05044b96c740ca051c61c", + "sha3_256_hash_of_secret_key": "06751acd0a50beca92428cf8c803af429068d4e5c4f74cc59e6d3275ea6da737", + "encapsulation_seed": "10ef9426f8c4a13b52325c5bb4ead4596ecf2c6b5bd2d37d8350e90d4164fdd9", + "sha3_256_hash_of_ciphertext": "ca7be35b1cd8500eccb6e301ce8031b1daa27b69466d4a4e14a33c67d5655763", + "shared_secret": "5e1d34e184996e029a175b7af798fcf94d39253a2596e41f37ce50369bb0bc82" + }, + { + "key_generation_seed": "e9acbb774be970206c3a738e243b420805a509fa59fa902044be2f0d013650d2ded5edaec5de3bf5b4d7c2f2e18e87f499c1968993eff196753db8045e2c8ba8", + "sha3_256_hash_of_public_key": "e78d350d2836d1d17e6ec375a0cbe0d6b2afe1ac036272dd41f8aa769c9d0668", + "sha3_256_hash_of_secret_key": "f74b8f9343146c1551a3cf9fb3d4e88febba4e98db745f36678d854230a8d7f2", + "encapsulation_seed": "a4bd30a64cbf29a4e290fa1cc1dfb99e68348713041e4409a1af23c5d80c15c4", + "sha3_256_hash_of_ciphertext": "9e2a6f7970c4bcd2f7628f2a94dc8990091d0fb274019eda8478e6015bef66af", + "shared_secret": "80314e9c9dad51e4d2f57677e88949df9d190ad5e413e01be5e0aed4a1abe38c" + }, + { + "key_generation_seed": "c1b3cbffad4b306f9af0cdd3028876486dbe858875c9b6497fe20172a986c82b1c96249919cedc2369d8d739ab125e0d2ccb82dfebcd90240a545cdfe07511f2", + "sha3_256_hash_of_public_key": "5820c7564d087683c0a4864844335bcbd62afa1ee542c3c1dcd8b72c80824b50", + "sha3_256_hash_of_secret_key": "11212a895ad32958d25d2ad32e917bd5bfda9dfcf08e316f733b74479469f9b2", + "encapsulation_seed": "f4b66a7d3b65b896dfe100b2cad24b175a1168cfd2ae11fd704b835f6bcd311a", + "sha3_256_hash_of_ciphertext": "f3bae33be1b49ed77d5c444e28290ca6efe9d142002bd2d62c9e53cb92650654", + "shared_secret": "d10f6702018ea779ef0455f748100f6f60266fd6678c691cdbb79b6ef2f37d2c" + }, + { + "key_generation_seed": "ff7495b8575b5a98e4fd21fb4c3e58cbb60f14bef21aa74cf8802e3153f14807bdc370460375a778d1a31d01c42b66367ed8d9e8f84551002f552f0e52102b5d", + "sha3_256_hash_of_public_key": "c56eb5880e9d9d0fe7901747f75eca1996c722ac47b76f34a4dbaaee0ef8a611", + "sha3_256_hash_of_secret_key": "8a90ed45b5910904e2e9f6a6e410d4caf024ef6436fbb75fdd179eaf09f6f362", + "encapsulation_seed": "1d7b03d3c5eefb8ae5799dc569aa668f1bcb8c86607b089d3530cf61d6380147", + "sha3_256_hash_of_ciphertext": "a3a36838ce39123da15151c24e61b9eeac5623d7a29030857bafd351c175f63c", + "shared_secret": "37b36cf73590028aa9323b401df00067c8fe925968ca3c30c2b0e5d5c75ee296" + }, + { + "key_generation_seed": "bdc3fba1c32751139fc45bacffb3ea97f26573d804a5f27a459293d95190ed8efd5a08f656a6eb8cd20679930a31caa6a6331c4b133a6838c223ef9f769f6246", + "sha3_256_hash_of_public_key": "717823f0b58cdfacafc795aea529561d11374f02964cf635c27848671043766c", + "sha3_256_hash_of_secret_key": "f3c47ab6b2f2a0962faf49bbc31f3101d6f4b867952aa3bbee32408c1b88ee82", + "encapsulation_seed": "554f3385b382f4a46314de37ee3885addfc5332bd4038785094e0a832e9e8c2c", + "sha3_256_hash_of_ciphertext": "b1980f9e4d3d0a349bc4a1b0d31f022c985c7e32be5e3554a4be94291dac791b", + "shared_secret": "4f5be9127b3fbe127c44c6d599a034dba15372208240f5e2a0ac8c630db550a2" + }, + { + "key_generation_seed": "447f6076a627bbc5ad7773fbfeb14b4ba9ac43a0f8b99fb6dcd5e452aa3c47ec20a7237801f470fcc2bd9fd7bea8322859b850f7882d362947432913dd068c01", + "sha3_256_hash_of_public_key": "7a13afefbba39ad59c088825380398f43f1251b83b0ca9debba0102f902d7190", + "sha3_256_hash_of_secret_key": "da94e15b824e73150a408df01cf1c5e4128739524831a4c2f45d0724144010fa", + "encapsulation_seed": "38bf0033b779edf5367d9ebc01c988af90904c560970815837380650e4749eea", + "sha3_256_hash_of_ciphertext": "206fc7f355eba8df4dc298efd19a035a5f3dc0d41b77aaa8eb6caebae7667e07", + "shared_secret": "aff62b941fb62cfa04821eab4ba287013221f8656e6a9aee849a65bbefa13baf" + }, + { + "key_generation_seed": "2d5df64d62cb07fe630310bb801c658dbf3d97993e68626745de39d37fbfc2b27b534537addaba4ecf14f02ab317d36cb9f0f50222ced7cf029dff8a0d3d2fd9", + "sha3_256_hash_of_public_key": "dd4cfbc29de3568663a3a044c3f897714363b0fdd3b6ee55f796292d34c7c79b", + "sha3_256_hash_of_secret_key": "6142d02fd4501c7bffac124bb8f26813009d2bfb91023a3fadea9506a40e1467", + "encapsulation_seed": "048ea516d0ebbd9f709b47eaac66f344c571cf50f0d01c9466aa061a50b66a24", + "sha3_256_hash_of_ciphertext": "0fb2ab871913334a719332efb2797351e4e6dd24e01e76ee77968fef042e43e9", + "shared_secret": "920b95d4ae5698ac7280b6e95814bbf9669ecc36543f2c581d4e2474fa9bbff3" + }, + { + "key_generation_seed": "25056d1b8113bb362dd979d98643d7a7ac9c4f95994c0ba060609b6d07002ff3f48a9254dd40b117941fa35a66bb50296327b725525deef70e128ca8045ec451", + "sha3_256_hash_of_public_key": "9ca90d64e28a5bbc54c36053ed333c530f72549c2afd77b10c2944fc833408fa", + "sha3_256_hash_of_secret_key": "510f84cae4d4307d7848f4c9665061657ae81526139a8b6a4076ad3df919abfb", + "encapsulation_seed": "686c921c9db1263e78ae753b1c9c2e7936b8229dca48c0942c56c6bca4f10917", + "sha3_256_hash_of_ciphertext": "b14cc3a7bcb4f57236d6ae9c6ba3e064eed7c5ec3e014fdaa5d844dae8e74aeb", + "shared_secret": "5e4e609cb40f37f28706f7892d5662509d8859cc28dd586d81f80dfb2d1eeeac" + }, + { + "key_generation_seed": "e4d34e12982aeeb1d62fd488d9b9e28557ed3429292239fb4f76fa9098009acae6c45c7fc62329b13c8d29844405db8ff6860de474bf727ecd19e54e6e1a141b", + "sha3_256_hash_of_public_key": "da073c98794493ec169c78eb75a39c1594ccfa635b8707325e0ab6cb8576e30c", + "sha3_256_hash_of_secret_key": "7829ef884941abc63f66889c3d44381f5450de1b95c6b6f79f909d74b27125a3", + "encapsulation_seed": "2387772e50059cabda53cb93ba24b19ae529496c03b36584169451525c4a0e7e", + "sha3_256_hash_of_ciphertext": "78189e1067717d260dc35ff67efe1b47d7073f60dd31fa315ef2e2889167f42d", + "shared_secret": "b86cb3a712c8802b28c25580052cb039e6dd4a71d01fd04b76839ceacc4fbbe5" + }, + { + "key_generation_seed": "cd6a99396eb3539ca663a51e42063a3a262cc1c5a5fce1566f0597b52ad9fa325a3407f591791a5db4578b5972093a95bec3b8e70c1d542c9b5c9789729f8922", + "sha3_256_hash_of_public_key": "c2aa254714dac09b9e712572b24154be391063afd3cd8cf4cc4ed8ef21f0cfe5", + "sha3_256_hash_of_secret_key": "2e552fd01c00cf43110aacac37d01c02e5f59c87133e3769d3b2bf0fd2e4431d", + "encapsulation_seed": "155c29c5f0378df0cd0e847a80a07143cf7522fcd880c9229eb9feb1ce340cd2", + "sha3_256_hash_of_ciphertext": "170e6695bd4212d00354f9a461a1e72a2129d735586efa70d87e1a227d0431f8", + "shared_secret": "1b4914e23b4b81dfe9a3bf8925c4a075c0b50b932c2fc53060ff4c9906183ef1" + }, + { + "key_generation_seed": "6c8c53ed6f65e6b2e324b84364e10de42d1c26a106d4d1c99eee79c78586fb55b9402bf02481ce4b27a52e87feb92c4399c7f2988d40e942e7496ad15ad2aa88", + "sha3_256_hash_of_public_key": "8aaca951e0573f28d50831960a28dd11126f0eb080afc55f394e8eaf6379f6eb", + "sha3_256_hash_of_secret_key": "45592f0d94666d8201247fad4d0acdfdb4635a5e4fa85b7e25b2391639451bdf", + "encapsulation_seed": "a9cb9a61a3324b1ea5afe693b32784e2871096b2ca14a11acc9577c52359a241", + "sha3_256_hash_of_ciphertext": "f5773c1740aa6324b525ce5aac66d39372392ec7674d85442c1c410e9a950a3b", + "shared_secret": "1c657d7ccf0d7cbab51df5e5934548efedd2b91fa7a4cc8b20288f78c20b507e" + }, + { + "key_generation_seed": "2107204cd995f1df14314d5381f8c5440f09a347502e161cffc0a2ec3dcfbc7324c3da70fe850e80aa818301d60c70f3038153866dcd5d179e22db59b8991bb4", + "sha3_256_hash_of_public_key": "f15a8fc937b12ff78c54fc273fcd7dd5611e5835472ed377652ae64495f9cf52", + "sha3_256_hash_of_secret_key": "dcdb853d17884fb04396dc10d34bc84d594343ceadda564fcdfa9b4d47dd4e3b", + "encapsulation_seed": "e99fbae8a024ebbbdcef32ce213f6aa942e3eca925e5da4c09975d773b33a175", + "sha3_256_hash_of_ciphertext": "0161cd775ffb9677a493ce237fe4d50f189c59be85eb63bb399b2c38618b9f42", + "shared_secret": "fc8ebd9f44c6517d7aa5ba22496c6b59704c7b0a2926cad8c4bb002c43a75eae" + }, + { + "key_generation_seed": "63a925685a8ac5bbd918faa33ac397d1ffbcf99135d9da7c3d6ff7aa4c50af3d3afdb8a246a56ee71465591831c371f2eb87467b0559dedd776ba063ee6d2f93", + "sha3_256_hash_of_public_key": "ef7ef8d7d81aa907fece4c1920c7ca9dda3bb9d57f09193487bb89d6422f10cb", + "sha3_256_hash_of_secret_key": "2bef3558b547044290d1232a580a6a473cfcd8d87ced6305f996d4db4f46e6af", + "encapsulation_seed": "67a216f37d67f5e74f782f1badbce1cc8c80a6130aec305b421899a4faa0a6c3", + "sha3_256_hash_of_ciphertext": "428e49654d6437df731f15f848319a6bb6c051aa97b39760219c966bf604fec8", + "shared_secret": "c75891d0cb9fc28e10ec5ec79553f51e2e7d0d03be452c468cb430253f664b12" + }, + { + "key_generation_seed": "6a1aee5e708c1b47f02bdacce4f56c860f74fc7cfec1ef3b58285b1c8ad7fec2230e05b7114ff0395cc6634db1eae8258072d09c09f291e92d6620b177dc50d7", + "sha3_256_hash_of_public_key": "99b151aa6b4654589afc36b8343fcbdc09a3e5255b378d6ee5629cd8b3cfd555", + "sha3_256_hash_of_secret_key": "b7a7d95034017d523ae23e29fc400e9a0b320f9778ba1587b69dd012f2aa47bd", + "encapsulation_seed": "52b19fea232c9154a3e431e9d69cda40013cf2d485c3cd027ad24e645420420b", + "sha3_256_hash_of_ciphertext": "4dfb28787aa1e30d2c90a0c8a8020fa74e1274de7e4733943a157d038d8639bf", + "shared_secret": "f30d3ba1693369d091d378a9f94c301ff3b7892e98b9491efc35d24cc6ab2f5d" + }, + { + "key_generation_seed": "6396b328b100e4c7f4bcae69875edea1a1982421558c608c13c592bf7b5d0fef1100ced48add211a5c937b8d6079d8e271af3f949edc61f70e60453aef20dea9", + "sha3_256_hash_of_public_key": "339ba63f705606d8c7fbbd6e66dadbf23f532d5423802c836f2105a636e9e6da", + "sha3_256_hash_of_secret_key": "60aa684e7cbf79e9c70504608a4c0f2cf8dc207f71b1d0ef5e3a99013ee866cc", + "encapsulation_seed": "64440adb05db3308b189bf999f9ee16e8ee3a6ccbe11eebf0d3ae4b172da7d2f", + "sha3_256_hash_of_ciphertext": "7570702b8a220fd8051858c3c4145f32295dcccfb1a07c0a04bdd812bfe3745e", + "shared_secret": "9f9bdb590d6835231fe5ca098f03a0e44d448aa43714bbf98b8bd8ec2cfd3237" + }, + { + "key_generation_seed": "a453bcacdd2b0d4646009e5ed451c3c45f08fb827ef733db3c517a9dc1af93e67a3cc8aa3239d4c52ce4c95afdeff6efbfacac10d294edc0e7cf4535059bfdba", + "sha3_256_hash_of_public_key": "1f9e26333b637ef9beb8881c63f9412b07c47a276af0e242062a54026bcee2bd", + "sha3_256_hash_of_secret_key": "f7f38ae2caba6d7e87b7bee8b127a9aecbc0b795345952d65bb4435e3720f89d", + "encapsulation_seed": "c8bb46b3a7344ad170c2052fb042b5a3b62e0590562ee82577b1081f6f114d16", + "sha3_256_hash_of_ciphertext": "23089ff0910af8dca0540c8c0b13366fd54867738ab0f314301f48e5d075e6e7", + "shared_secret": "6036d4043821cb758cf9df9659e5852b922906057b4d8640bb3d6b0ff7d848d7" + }, + { + "key_generation_seed": "47ca2b77c5b717f423222c2730ca5cb9c856bc951d01b2b2c80bd76ccb5539b78f1481d7cab000e33fa07de8dc9627a85e76fabb4428a3376e66300cf12a0787", + "sha3_256_hash_of_public_key": "64b9f8198bab9b3b2f2a1704cd4ddf6b3cbc216ddc0f062a72ef40115917fd21", + "sha3_256_hash_of_secret_key": "a3cf5841bedd9be95061b910333190834063e5cbcf0fd32673f8cf3f6b548d17", + "encapsulation_seed": "2e2b70609f3fe029a14d09d5d659871ac776ce2797a0355f16e2eb68f5613fd1", + "sha3_256_hash_of_ciphertext": "5754725d6213669b27cc418d2d1a3aad30efeba3296750dfd7aec0f83f3c181b", + "shared_secret": "ed4dbb163e97ef686ba77b2bd2c0a872405dbaaadf0d33d0f125d9e35fb0fc59" + }, + { + "key_generation_seed": "aaf6eb40e596a5e3e8218871e708b089240dcbe7fd3641f0e5e41e071ce49107e2f8d320ac3cb0c52efdc753282f092bc39baf4a18783a48ea031a191865eb78", + "sha3_256_hash_of_public_key": "de4ce515b882c849717a1ab34f2ac0238c868f415630c1155bcfb302d346dc91", + "sha3_256_hash_of_secret_key": "4b917d9daddcdc932fe0448063a24a592edbb0e6e40b5b53812f20a4cff7a0a3", + "encapsulation_seed": "4725dd8fb314bfd8ee23731c2341dbe114606d9abe6434c471b5573e7df193bb", + "sha3_256_hash_of_ciphertext": "e0f91001a8df37fea9c61a89e056cd5c5b0f9f7d0fe28c6c3ab93c8c72cd44a7", + "shared_secret": "68577551f44198a0290f814efb2313fb1158173b5eb1ea75ea907944abe4e25a" + }, + { + "key_generation_seed": "6500f32c93415cfdbc0bd31d78d5be95cb9060c8cfa2013955b56f8b6868b322393308641a9a4647f230201e1389624a296b55192a9819fcb19ab77c25f95445", + "sha3_256_hash_of_public_key": "93b60f0d00c09af885b5a0cbe942fde6afc4841428104710823bdcc12319eb35", + "sha3_256_hash_of_secret_key": "953ab28bf8cf18e86b8c80efae0bb47582d720e787fd2af27d9789c1ffb7ea1c", + "encapsulation_seed": "818d3bb8ebfb32bf464775f7139bac0a5bddce80ec5798595992f9403002cd5d", + "sha3_256_hash_of_ciphertext": "dd26722c1c551e97106d933d141bdc2ef06a1fa2e796feb3cc870105eff38076", + "shared_secret": "963f6853aa0ac3a40c397395fb0b4427b9e7ac48dada3b758b11d6a9556eb14d" + }, + { + "key_generation_seed": "7643cef2d62cc5aaeecf754653ea62294cd2208e5bf3ddeea209e3dc45373d49eac9d531a532770837a854b4f5531f6e0c8d6c10183b30d3435498c2dd142951", + "sha3_256_hash_of_public_key": "167a2fec4d72cac2ffd844246eebabdac0c074e4f984433744e31d299faa389c", + "sha3_256_hash_of_secret_key": "9afc4ddea68ca10e36d9b12d3c34595912eaafed49d8ffce01cbed09501f7527", + "encapsulation_seed": "c92aa5fb91c980d9cade9ce99d4c75b2ffa7d6a6ff9bd59def1aa701f2a0992b", + "sha3_256_hash_of_ciphertext": "79457db315d313b34a236a2e2aa166c01d749ca432b5250ba28c4ec3c5dacd0d", + "shared_secret": "27c47462115122e2c24cf7030c0f9e270e023714306242c7276f8b1e72a4c008" + }, + { + "key_generation_seed": "f8ee95521060c03bb8dacc79f7eb7db640f545f315613a35d447a09e504cb4e13fc3d8392cb53f36ed647364a04e37278a0e0a45b720f4a75c580c9920eba98d", + "sha3_256_hash_of_public_key": "955468734662471c953fa516b35b3a53053ff396b7e2798fe07a2ecd549d6c06", + "sha3_256_hash_of_secret_key": "8bbc886fcb7516e7888880921abfaa72823ace9d50cf0afc2f68c4a7c3dd2e53", + "encapsulation_seed": "7e8086a01dc5b3bb9eda25bcc45d27f99874841b97237968495800e007696ac5", + "sha3_256_hash_of_ciphertext": "5149b2c28342da4d9313a0abde239cce24cb5dab1957f4461a89f2fd3bde6413", + "shared_secret": "18a159d28bd8ccbfc5e3e6ebc473179a7b411d7829d618869e773142366bf0b8" + }, + { + "key_generation_seed": "b8bd0493a882e3a49b4e0f6256fb1fea0912562fd9ba26ec3d6c9cc12c8973abd7e4b5d8021c486b9c3114d7cbbeb7cd49eba8a61bc2bcae1f1bef30a1daf76d", + "sha3_256_hash_of_public_key": "f7310c0531060051469ffcd2f88e3200bec6c721bca1fa4c9e7bf1773d7ccb19", + "sha3_256_hash_of_secret_key": "16c976495bbd05ee6715f30a9323aa41ecc320e2e63479148ab3a51132afd7b5", + "encapsulation_seed": "bb321ef14d44d8698df879fd52450567657f52a2df8d111185dcd7d4f30a72d4", + "sha3_256_hash_of_ciphertext": "872c2dc976c8e61b1f2870d542560ac0f504def811af0ba660a2f6f7093420e5", + "shared_secret": "6f5f733e336bca237f9da083de1978e6e6b80d0d25191ed1b502e315cf0ef2bf" + }, + { + "key_generation_seed": "c0407e41ddf48d333978b89bcf2db01e4613425b456249e76a6f25b8a2827bf5b2dca81e3f5f748d23c9d356a2209f6b2d60247b2e45c9808de497f64f124643", + "sha3_256_hash_of_public_key": "152c13a9a4dfbade0f98e8a5136358f69c93f0722addc008952cf72e1bf350b1", + "sha3_256_hash_of_secret_key": "b93c3fb9dbddaa560dd52c6a1c37f6aeb2111e46b7b746419e3c27fa43a27211", + "encapsulation_seed": "210a423dadd899b810f011794b79aa7f860823ac1962370e791287d3a1afa384", + "sha3_256_hash_of_ciphertext": "c133d369a3ff3cdb9de50d778bf00656123ce24294b51ca5398ca5727d82cf50", + "shared_secret": "8b62b88d64af1fa3441c71c8d94af6fa8247e05429acee7c4e9b085829d913a9" + }, + { + "key_generation_seed": "334382d39164d1989696a2ff77b25a28af8bead9883b5365eb6fcca7c1781cc9aba5068af837be962f439f233593d193ce5e08f7d66efb3389885927b89d2523", + "sha3_256_hash_of_public_key": "97e5b18cff525ef46fd8a6aa6e5e4b8d953fe1e67b5771d1b99ff18e754553be", + "sha3_256_hash_of_secret_key": "55102f3a620209b46e41531919a1b6f091c86bbcc5bdcb52b18f9a070680bd66", + "encapsulation_seed": "bc856afe24213e3d14c3d6f9b89223bbcfb2c890722d770fa3492c1e46d1c302", + "sha3_256_hash_of_ciphertext": "9a48d477153601aa1a74739c0e8872786c105f0adac5e6d7c03a4559a48cd0fc", + "shared_secret": "61cf302ae28614b03f8b1ef1ee98447e9a7d7fb7d48a9634e6556c4fddebb3dd" + }, + { + "key_generation_seed": "6995143e8eb8a6e93840f76eec844f67d2b5f75b1839a5040337e61f9806764a0f4dff8e56f68440836a072412a30d851ace2c7c6f02d60e7a8420001a63e6c6", + "sha3_256_hash_of_public_key": "7b5c67fa6e0ff374f691540fff0b4d14d4ed8a8a8c48b14b2a35facb413a5ee6", + "sha3_256_hash_of_secret_key": "449e7b1644520512fa25ea48f468ce9f866ea08178e814f11561efd4e4aad792", + "encapsulation_seed": "5fc00f89563e44b24cd67d0ce684effe5731619fd08e7d72e2406eb016afb66b", + "sha3_256_hash_of_ciphertext": "6bbb43bb830187cf5d26e49dbd95622aa065e3bd59bd449d3d6920d5406359d7", + "shared_secret": "813311404f3e913ab4f7fff6a7ca639e0fd2ffea9a5113c3fb00f1c910c34ef6" + }, + { + "key_generation_seed": "995eff7e0d195c6d0533f3dc194d47e60f9ad14696144cde694d60a95f3e96b4b28f7e7a15a005f92400ce33db073d49b53871594a88fc45e0f94207b5f0f2dc", + "sha3_256_hash_of_public_key": "8e49b73bae3b0285bbe1676eb6fad2641e7354e4c0a4feb0b74bb16708b01351", + "sha3_256_hash_of_secret_key": "23a598fad0141bdf07257c662d22549343a01d75eea9c1ebcdeb4a138c6e215c", + "encapsulation_seed": "ea22a76065db4b565ee1807fbd813b43bde72b0e08407fb867c6a18995025e50", + "sha3_256_hash_of_ciphertext": "7f7b18146f3485f3be3dc49b157dbb1a642ea85bdade49a32d147138827ec468", + "shared_secret": "c3157b5efc9d3c22ff09adf984741b70b71c2e351cdc9156cc83967de7e2e39e" + }, + { + "key_generation_seed": "3e809ec8dd0fec0d911a4e3fac20f70fbb128c5de94dc7184ca7310ae9157a98d8128601c28b1def8d393a0db283229f7c7383152a814e7cefe8ef9d9768c473", + "sha3_256_hash_of_public_key": "f5de62d662f480d4ed8ba235b4aaa4bfff19edebbbfbd96e5a9b7c4e89365c3e", + "sha3_256_hash_of_secret_key": "583ad55aa14bd6a4310d3ab7aa619cf59c93906251f5721a0bf880a866517f70", + "encapsulation_seed": "e9602b34fe73ad57f4bf6ead99743d645641553a5b9b9bf2e7016629e3e9bd76", + "sha3_256_hash_of_ciphertext": "25d303ae10e2b4a710aa3d2a484114f7dbb24049e473640dffaa83d0b46aa936", + "shared_secret": "4dfe50eefed4dec70edd72ee2fb3e5ffa99bac13e8b4130a15b75dd793c5bb56" + }, + { + "key_generation_seed": "dbf1c465fff3d9f783bd9ee61a573715e45691147b8904439b5ffaa64f94ff7bb6d75eac6c76ced1b0a025b40a55440712ad8424672e761e9bc400d63812006f", + "sha3_256_hash_of_public_key": "ec2fc5834e128c5e1460d8cb0c35ab340d706a6c8b52070a7e41a6405fada53f", + "sha3_256_hash_of_secret_key": "954a43f78ef0b5a279c0d020c08d930cc5e83a385c09afed508f9ef6f1a27920", + "encapsulation_seed": "f72b9080a6c051bbdb9b0abc1949034be0f89a9f73fe277ec4d4740c78d04a83", + "sha3_256_hash_of_ciphertext": "f81d26622a659f73fdd2a692909db6310b7a29fdaf4e046dc3a17061a8a13296", + "shared_secret": "e6bebd8623388cbc483ec4d1b3d10e55ee88367df8784884660f63043ace7353" + }, + { + "key_generation_seed": "1f7cfd2b70863154e8a69d1758532e86c20cfc763d67c758bd10a13b24e759b5273b38bddc18488024ec90e62a4110129a42a16d2a93c45439888e76008604c6", + "sha3_256_hash_of_public_key": "5e7f49b87bb2319dba8d3485fe814aedb0b43173bc48f3a793554c3e8bf90c17", + "sha3_256_hash_of_secret_key": "74eb7c05fedc78406453b8f021f8a71cce4b3ad0c4d38bc8d581000a38908574", + "encapsulation_seed": "f1e5542190db8ecf4b8d617a04fd3783ad0df78bf8dab749afb57db8321d151b", + "sha3_256_hash_of_ciphertext": "48ff650e82343e63826ab5b0f4c4ee74300d61a2fde6a5b3fed48239c6ff26ac", + "shared_secret": "a92a8a587b84cddd75a3e58aa6e88f8f80cd79ebef496ddb8a67e11b4ddfbc2e" + }, + { + "key_generation_seed": "3a19577908efd37697b8edc7fdaf47d1bd3ad01a1b77faf794bee5b9c3192a6fa3729672816f3eba84c9638a79676eeac0f22c8a48e0c5d50a26ff0844c66b99", + "sha3_256_hash_of_public_key": "e3f73c56254fac37209f5a59818fbaabf5abff3320b0b3ee00e20679b5728c12", + "sha3_256_hash_of_secret_key": "1e1cff1c4e09318bdc174bff8ef0817d6e7414355adf930bb35e71a7a0b95abf", + "encapsulation_seed": "74efa414ae171bf60b6f884cb7e5ce12028f49365daccfa23e845d551711660b", + "sha3_256_hash_of_ciphertext": "2b9bd68b68390ea0e71128da8c2100a3fda08cf4aa35141e4b0bc4b15e7f0611", + "shared_secret": "a566d12cf0fcb1cab51be0b38365bef5908bb1c93ade17780ccb988f8fb03e1c" + }, + { + "key_generation_seed": "ae0f65e29f38804a6759f70f4d01e2aaff7fe1c91ebc4f892dd0de3ab2e68ea5e03ff73e02a217659f53d8c47556bf3d8c94040f630d63605e2d0f923579370c", + "sha3_256_hash_of_public_key": "bc0a40ba03d27bbbfb91654fdcfab2dfb3e94d9607b99c1d7da1f2663bfa2598", + "sha3_256_hash_of_secret_key": "dd55c195b92ff410b9ea37577ddba0385bbf067b3053b0a678e8106c07b98c9e", + "encapsulation_seed": "0b4c3cffb2ba4380ead13dc0d8acad2356b448a810da1df29f264c44aab6d24f", + "sha3_256_hash_of_ciphertext": "ad30184b10e62dcf0bc385c98125126593dc77c830671b8754d0e22a8cd4e66b", + "shared_secret": "48ac7c3e8787032f08cdd6e918d694c04468a8f07e3c35d46345ec29d5c0f005" + }, + { + "key_generation_seed": "6084a235f79dd093ef6d185b54e69df33dacee73a9bf2f379004421a10e3a79d9f684fb055ece19459eb464e91e126a7a6e3ed11ccee0046da234d964c985110", + "sha3_256_hash_of_public_key": "e16da7f99bb7bceb75a6468a921ab9fe53aab2972ca616ee10697c204df1e350", + "sha3_256_hash_of_secret_key": "2db70f5bb4e8927fd7696a4d802817fa58c43f9b2618ed27c7584cce8acf3506", + "encapsulation_seed": "1c82471dcdfca3a6942061ab4f3d5bf0d197321437c706d9cccccce449447002", + "sha3_256_hash_of_ciphertext": "721e380b527efd9256013d4f991490a6b8e0d92f5d447e454a219c09de7c8c03", + "shared_secret": "098bda430eaa259763846c94d9f888c8e07fec084e549851998f700156573e04" + }, + { + "key_generation_seed": "acd1c0217fad5caa4235544dd9de153ab1880ccf4c76f16f236fae4e4bfda04cf03a8abb0a5010f400ae5722a75bdf5a2f6d5b546b34d73857cb1bfc7e587aa7", + "sha3_256_hash_of_public_key": "fb80edf4f67823ff4e53a8963a9c9937fa9f8e014b750e11b4c4bb1a361d6484", + "sha3_256_hash_of_secret_key": "fe67beff69ea75d4953d71c038559591b2a0349ddcdfeaf7596dcd02f57db2b9", + "encapsulation_seed": "46fe60a18124125ab93e0c578f1c02f1bd1301595013001c7f3c2fa56cde294e", + "sha3_256_hash_of_ciphertext": "ff41e11bd3d39c14d3afc34ca8cac207b35b4c68d0b181a40dd23ba480771f0b", + "shared_secret": "a350b71c1675b96fe62fdb6d37658d9ed8c200ef4732ec6768dabf931d4a5f76" + }, + { + "key_generation_seed": "241191401a63afa750f05662e354dddbc683c776ce3222beb83e3cf913d7ed7ca59b3bd23b49a95bc1fad20070fec930b6060bd827d742b077092e422268e15d", + "sha3_256_hash_of_public_key": "d9f630c3838eb161374710d9f01bc70d4ef928fcb1c38bed93e30f3633a05e01", + "sha3_256_hash_of_secret_key": "ca4a4ab954c3a4c8b960fdfb7dd7cf5e8d103f7936f31e720e5043010926829f", + "encapsulation_seed": "52fb7cb6a633fd2e83f2892bd9441b48fe59ecee6d026f5246fa7f2a5e55ee3b", + "sha3_256_hash_of_ciphertext": "9a3d708342633646fb2015f87a2eec0ebde9d4e74249d6a169df3741018d9c3f", + "shared_secret": "77e15c4859466b3735debb83fda8b2117cce56668b1f8d8ba62074299dc4f5bb" + }, + { + "key_generation_seed": "b9a6b0c05677e957d41a34ba03bd06f2a9092e31f63389397d7e70fde6409d18e99c0e7b82be89bc3c1eaee6680aa4efd394e40c2b3f30523c8117f7c26a8969", + "sha3_256_hash_of_public_key": "5c27fa929adc826f98fbf0a7fdce33c8f215b34e70450da0767240741894ffa4", + "sha3_256_hash_of_secret_key": "0116eb35f3138aa7371a058661a92a4bde258f823747b70ad40767c27d7bc7f4", + "encapsulation_seed": "0f81a5f97082121244403da3feeb734f6084b314b8d94beb11627aa6ad1914e9", + "sha3_256_hash_of_ciphertext": "792eac29d3b3bda1091428ec4ce8a75e7db11988bddb203e6ae9a6f89778e949", + "shared_secret": "6662374cea4ec0cccb6b76cb75abbe9fcf0a66a0e5bda1a84832769ffd5804f9" + }, + { + "key_generation_seed": "28a96c71577ba00c94f99fe965bc595a26db2b3ca6ab5cf8e443cdd8462b17929c35d165453e5fcdc6f9df64526d9de698f2bd3e6bac6c7fdd86601b9ba5f4a5", + "sha3_256_hash_of_public_key": "dd8aa653122eb5e3a4c3c877e95e8ecfcfef1ac9e0e6af92cce8ee89d09188fa", + "sha3_256_hash_of_secret_key": "8a5fbb715cf44c86b736227e56b53d91ebbea432fb1f1d6d7cafe42da8457b2c", + "encapsulation_seed": "31af9345365549ea0360169ed57daf98cc5444799d4c75d9f1f5d615e9df8a91", + "sha3_256_hash_of_ciphertext": "8e08a9a364f171a1aca3888c6babae0882f8a132698b92dd843f425259231055", + "shared_secret": "41109e0d793d6e7bba39c5bae4cf180bd65bef2d045c516b905cbd5dd8079b5f" + }, + { + "key_generation_seed": "c08ba2ef8c3a0a043afad931652d7a19e6e8cb670f840de5f1fa03309b2ca9ec5fe6141a25f7ab9f875f79e0a82d6ea5cde5a017ab637d5fdb7c42646a1d71df", + "sha3_256_hash_of_public_key": "b7c80e434104e9838cb08529592a5f81b0e8ead186663db8facc569b09e75c9a", + "sha3_256_hash_of_secret_key": "c5f84c36f3b8af4b4d90a040d929b116b402840f487d437f9b330f6ff3ec36fc", + "encapsulation_seed": "774ae54093d694ef40b63b62c73e6c98295f606feb8699807eda1d030ffb996d", + "sha3_256_hash_of_ciphertext": "24e6b9111a3fe89989d21d47f1f3a6f6f637ce35d0505936ac5cf886d9531b37", + "shared_secret": "d8007499f94463b8a804be5bd1b3f529cdd134b568f07f646b96ccdf5edce5c9" + }, + { + "key_generation_seed": "0e3b30e102d707538c2671060f603bb0b8a014103f132d63b09ece07e4a4c75b11eafeca9e810796c34e8cfce9d59342884456007b01ddd12edce6d10ed87e4c", + "sha3_256_hash_of_public_key": "e619285c692532735f1582d227b9a9e77b1eae4aab9eaa79f6ce7ac2fcac8318", + "sha3_256_hash_of_secret_key": "2d4ae4f98c61bd104fbc1ef512b946202f95ecaa0ad7353a686141be5fe18116", + "encapsulation_seed": "9f27a47604ab5146caaf0aafe6d149424f8d66e39ba3baf5e6c73b19221b7e21", + "sha3_256_hash_of_ciphertext": "83fba7f75836f5789ba98f94c053b928eb1f87164182674835b50e1d3a2fa5f8", + "shared_secret": "52739ee9de88e8aed33b910c0f65091785fa0076ebc97e4fde190bedd6b369f9" + }, + { + "key_generation_seed": "2478f7d3de6041e7e5cd11c5e2ef483d1aa6218eb126444091535f6ae532fa7311136e2681df2ef881b51a092a9badbe72c9772c169808521c47149578621e28", + "sha3_256_hash_of_public_key": "dd3761c0e96678a959f30997e96d6a59858528c5e10234398e2da2e50ffcc517", + "sha3_256_hash_of_secret_key": "c6f5f9285f93d2ee6d180353799df5fea713870ca06de901e9c12e8a01ead6b6", + "encapsulation_seed": "90044031b7597b5e60a4f946b713e8996d0426d2cb013243d9b7d8f8ef159a0f", + "sha3_256_hash_of_ciphertext": "7126e43303e6fe9f7b144b02ed2a9ad0ded908df3e59852786ac0d339b778329", + "shared_secret": "17abac927855cefc72c77653716b862f9e5b7699215104b8f77a9891a726cbf5" + }, + { + "key_generation_seed": "9d405d3ebdaf35fa8722de431b669722acaaea2fd10b814310b17f78b66147d16ceb14f7662be0c42779459f69a145c0e2ce9f0bd9a0cd1bf32ed5694cc9ae32", + "sha3_256_hash_of_public_key": "6d9e513a7cd137583507ad7256844bcb9775ca82ef5f411331a7c37ce451181f", + "sha3_256_hash_of_secret_key": "1dd2623a7413ff14549690b642fe90ce16ebe7acea38be795a4936b8d86b93aa", + "encapsulation_seed": "a7a31e140891ea37d2b6424b59b1f84f89220f32dcb73e037eb912b389d34a48", + "sha3_256_hash_of_ciphertext": "9dc037ef3e313534ecfee79a172509f9cb9997c255dcc0bc4204c3b05623b446", + "shared_secret": "753c6406cf394990867a10d3148c9b6a54d0183315307abe36161a4f981950da" + }, + { + "key_generation_seed": "9a86490f0615f3edf789cb0654066e9ee339cc59f968281f3b89213f83c692edfaeb2ef44d2f608621e831187ce79b2d2f4a20f1568bbe76b0d3d5af36111714", + "sha3_256_hash_of_public_key": "b252e5abf757e116a92518eb72df9f9ce66b07edf4d31be225585a6a827a35b8", + "sha3_256_hash_of_secret_key": "45ac74f2a699f1e3559e2d1442638290029688cec3da96c58ea697e1ed1d4178", + "encapsulation_seed": "70eb3f791faa91f1f982fa477dbcddeb2c55691c07f93b04cd31b37544c94b42", + "sha3_256_hash_of_ciphertext": "cb491bd740972bce9a0ccb2785aa4d23d7c3c3ddecc035a198c5ba15423080ca", + "shared_secret": "02bf5aee55676047e4a452cd71c99389f4dc8d519eed5e6b4ad25709eb35727e" + }, + { + "key_generation_seed": "6dfd9b575872560c7bdc2732c4a28dac4db04e535eb8e402c3dffd145c09ce47a2985c1c4d203778597947d710dec806e36b0cd949fe460ef141213bfc525e5b", + "sha3_256_hash_of_public_key": "18c081231277f424c5f3f1f6b4db91958611fa28bcf09ccb2573da64547e1958", + "sha3_256_hash_of_secret_key": "f32167b39e19dbc0db58a5eb79e735337ffe154c75b0f2c091e009d0cec366d2", + "encapsulation_seed": "30f4095015ba88b6d969672ca3f438c395dacf7d476ea7a9e805ce932d270a13", + "sha3_256_hash_of_ciphertext": "9cc18127425ae09ab26201de4fdc120d49e97f2050ea782f0514b9de5895829e", + "shared_secret": "bf20a2d204a1823b132381ef2c8fd4ed1cbaff50098e7b3eadad33785c9e98ad" + }, + { + "key_generation_seed": "6fca9f4e384d8418075cc064c70730801bdb8249899d456a77130d5beeb3662cce7683f8a03d3cf04e46970ff7d6a12494ae12558346dfc8fd9370bf944a0102", + "sha3_256_hash_of_public_key": "0ac7db13184d6ae6e21a14a63a2ab3d6d5d1ee7f4a6011413a0295b752fd2c28", + "sha3_256_hash_of_secret_key": "f69bacdf5992e64369aa4325b70af9f0e8a399cadafe48d854c288cc4eec627e", + "encapsulation_seed": "cf31220f44de862e1719570e1b26e897790159366a385452334fe24cdcae28ba", + "sha3_256_hash_of_ciphertext": "070d05059079935b70f221e3bda5289671ce70bad2467d1cd72abe9fcbf16e76", + "shared_secret": "eb70267c2cd618ededda12eb62ca541a2e0988a207ed15dd796431dd052b1b55" + }, + { + "key_generation_seed": "e58f71bf175c0550a67e00e0f7b3b7fc36bc2707bf0c93044a492626de36301a7f7054814869cf7625e45647bc1547aff288dbb90699b2ad84893f3b755d9722", + "sha3_256_hash_of_public_key": "27ea5a76294070ab10a6edc502d82be3d240672e5fa61377e73e5e19d11f64a3", + "sha3_256_hash_of_secret_key": "33161a2b269ff022ff4699b05ac7fac1374d733e46800447164d3e528ff89dc4", + "encapsulation_seed": "bb5e65669a44e5d5c709bafa98c16ccba6ac2c4ae923334f69a11543eda64f5d", + "sha3_256_hash_of_ciphertext": "f65b7d0ccb75422e40ca5d091eebee0c0ea49365eeb2ed9001c441486cb32672", + "shared_secret": "3536d3945b89b73f69efecbe99c26a89cf7d7919e13f3f2bbd4caf33dbf92000" + }, + { + "key_generation_seed": "e3fc575ed51513e62aba655d24cd9c8f1c6c848aaffa946c49a53ac3ea59e474d82c2f1bf2e6aebde5660fa73356982e12999d8fdafbb3cb186341d0386dead0", + "sha3_256_hash_of_public_key": "9898462f05bea461adb40faacdfdde363c06f58bc756f0a8417df63a66d3a544", + "sha3_256_hash_of_secret_key": "e10192b72796b2da465303c0bbe16f1e23e08f9680ba92fc22d568ac84352113", + "encapsulation_seed": "9ddb3aa9c7905d1a438c93bcf78e3e321813580371ab4e1289e2dbf3701972c2", + "sha3_256_hash_of_ciphertext": "6017cebfc3dd2be0880789c412b8b8b58e1c3dc974b80ccfe9b620615ae96c22", + "shared_secret": "0b684bb1dd742f660ef898b9a7c10a012f12b34c889c8a5bd36822618a60cd96" + }, + { + "key_generation_seed": "470b4943f0fe7fd0d8ec5185aba0d1db09d112934e4fb4787e2bbc6b88466e7b8b2809fd40008be70a6b184981101724bc3d5ec5e1956b510b82fd5ad0668a5a", + "sha3_256_hash_of_public_key": "a24e6203d9b1aa5cd06c44f048da7225e33952617f12b4289494b3969857c2ff", + "sha3_256_hash_of_secret_key": "61f1e3b3a9ce59d25480d88dac106cebc81272c0c9449c9b22048f67419d940a", + "encapsulation_seed": "26d90b190a6c3d0d9a86cf66005154e7086749e966e7187c249ccb9329fd3b8b", + "sha3_256_hash_of_ciphertext": "cf1222c0ccb284eea4558d81e942600adcd4f4381f28aae7c812fa5550340a25", + "shared_secret": "0d5443b3bef02d9032963b2cf16a3c52e4a8c23b5dbe33df592acecf37cec0b6" + }, + { + "key_generation_seed": "6df4385db978d27b27d2aa5e452e4152b36f097503d9581ac3390105c5727e7dc95fa08ed106ce84660e8a4c90bd2b22634e40769aa0090a101c5dddad45edc5", + "sha3_256_hash_of_public_key": "cb2e9159ab5225a75d02268af2dac89a0afb33fe83a45f552e2bf542868c0683", + "sha3_256_hash_of_secret_key": "d2ce7cdfbe3ac715b2c87b1231fe46d5385a77caab367570a955bb562d23183c", + "encapsulation_seed": "7db6d1a129d6123f1f805b79ad3b413012ea86aed42a05e98e7b1f32f9fbbdec", + "sha3_256_hash_of_ciphertext": "17f9aa45f0057664ec9a4af86573e64221a29d99dfa3a8d2616a07ed20df0b8a", + "shared_secret": "b4677fbf9553296d425365d1d4dbe02ea20bc901e12744e78deecde03638afac" + }, + { + "key_generation_seed": "dbacba825728444921b227cdba54446b3f6881b47be9cd02832f78b023b1bee0e15274a8e2bc08fe818b117ba28c5dfae74d54fcdf6f20052f79be333edc8dde", + "sha3_256_hash_of_public_key": "7f8d36076b3a8aa13b633650726f7e907806a0573402ef3af129f611def1a813", + "sha3_256_hash_of_secret_key": "0b38e04daf35259696487ffaad947f481756bc3e94dd1a73b81bf8a6da4a43c3", + "encapsulation_seed": "1d129b27be7384c359d04311fe5c44917d1fde4bfb57314f483ac617edd5ac49", + "sha3_256_hash_of_ciphertext": "eadeaa59c73c8120e5eb7807b96fd2f668fae86c157a268c6d2d4086f2e97876", + "shared_secret": "8f8727cd74add8d53f613c56a81e77d446acbe52be9241edc9cfbfd44e771fda" + }, + { + "key_generation_seed": "690eb71fd7052b906eaec09937a8ed374e0b02afa27c2f14399932be5839fad281c38c2cb5cfafac81b96a810ab749b61806b6d54c9f8cf4bf1be0192423288f", + "sha3_256_hash_of_public_key": "ff2044ee6a3bfd4f7033dc4bbd6283b534cd3fbbf1c4af072fea1ba37d3262d5", + "sha3_256_hash_of_secret_key": "ed62dbd78c007d385c786f2607715a69a44804c4e88111861d175875bc0b09ee", + "encapsulation_seed": "bbc773ebd2df42c36ae05952d6a64c63a5dfb82ceb3ef4f8d4df3a30ec8c0467", + "sha3_256_hash_of_ciphertext": "6dae1804aa498a974643cc22e5c2bf8bf963f6fc7fc8a4d1a5a504a30f5361f8", + "shared_secret": "a66dbcfee5b9980c4378ad4e58ab6e37307b03869b5bb8bd169af2d77ad6462e" + }, + { + "key_generation_seed": "32e0ea9089fa928482c0770da545af1bb871a03ce38604138b0d08ea2a10ca2bc06c5bef7b6508409daf847a64c8d30d0974fd3ba7476dc76c46b458a036d884", + "sha3_256_hash_of_public_key": "c7ca6ebbe17f30f8ce49e15c40c1ea5456f43624148eaecc9f3018f7beb96bdf", + "sha3_256_hash_of_secret_key": "7886dadfd208ab926afd2376dc11a004d8b793d7a30623df27109f9a4d4b0916", + "encapsulation_seed": "5b17a6adad541efcbf5ae4b0c0452cd2ce32e4f0f8701801c5b63e197c1fcbf4", + "sha3_256_hash_of_ciphertext": "d751d4cf94c6f32b3fd4144a4abd8437f604a203684929b762f0a0b4a86fb012", + "shared_secret": "75888a3f7603f185984fbc3532a67d2e939539e324a4867cf1421f259bc07050" + }, + { + "key_generation_seed": "6fb2ec719f2a0dea152bf3f64b9d148f8ab8ba88f64e61f5db53e12d59f525574f797c007e4061f95c7d56cfc7ee5c49e849dde3fea8f25e7876df2a18515c34", + "sha3_256_hash_of_public_key": "61fb6cfc0f388e34fb28ed783c2733453005eea03d3fee4b01bb6364abc01c30", + "sha3_256_hash_of_secret_key": "b724f25cf64bdaab1cd29c9cd1f8ee6cf4104c26fa3caf53b77d61cb5c35222e", + "encapsulation_seed": "61ab87659525de9656af41246f20e1dbe85c24e335e7ecf9493f46168bc14e94", + "sha3_256_hash_of_ciphertext": "13117481f624a9b4a9456b9a8e5135f7e170b0c9201e97cad7d39d09f62e0830", + "shared_secret": "87ae8b4af711828997d80711eeff79e912e73f789a86fcea151dc52ae9565b5e" + }, + { + "key_generation_seed": "527fb88c8bd9a4d6031dad15e63878abd2b559e7e08d61f69e8e78fca964ee6ae32d432b4f9f751bde0496c580a181ffed762aa35454a02d3f1f47ee0394c89c", + "sha3_256_hash_of_public_key": "9333445958cf50f9cfba453f058f562158bc253e535e4e2f07715531a1c6289e", + "sha3_256_hash_of_secret_key": "9bb80f6928e0d09847b4c7e77ba6bf2cd0f75bdd147e884b92d3c3f2e9d839d6", + "encapsulation_seed": "eca2adc3da1fb15f34033405ec08ef2f46163df4bfcccf8842c600ce0bc2026c", + "sha3_256_hash_of_ciphertext": "4a12846bb5c46bafacf893d61a6fb6d653ad98430ed44fc2e3de3d7322639881", + "shared_secret": "8e5426f9409f456d3f98d2c909abf19c75bb3df268b482181683c19b759206e2" + }, + { + "key_generation_seed": "ac6fcfaeeef795b6ef9e062f02bf42975fa01e7d91ba832f74e05269a72684d05aeda108ea4d6c6bc0fb958286850422bc357ca67b83c986048e0d0087fa11ec", + "sha3_256_hash_of_public_key": "ee6cb12a54341aeedc99f1040b01603c35f07c5487ffac7b4fc1925f49026916", + "sha3_256_hash_of_secret_key": "4e498a0606b1f9cd72b9d2493428730712bdaa4a7fed8099b15d9e2873bbdf7e", + "encapsulation_seed": "c4f15bec2d7701339d0ade4835193bea3632edcf89e74992620d9eb623a0d0d4", + "sha3_256_hash_of_ciphertext": "9a3e2792b900978cf6d1d15eee7f787cfab6bff3afe5c56af129e1556b4ac107", + "shared_secret": "9d7254f23dc3df7821eea7db99758b3a66e8af9229c59783bdec5e2896764f43" + }, + { + "key_generation_seed": "ba2fb9318d4dbe7488057c33e95e6f054583a2800c41bb83083c330a914a12cfe63f8ffda3565c2424c89b20974b748a65a5aba75133fcb3156dfb6626a83bab", + "sha3_256_hash_of_public_key": "42ad42d6d3b13c72b16287909bc4c0da04900536a1e48a1a28db4f5ee2d2e771", + "sha3_256_hash_of_secret_key": "d6f909b6679487a8718c843c4b894785ee046c4d86ad2794c22ee912113dad1f", + "encapsulation_seed": "28878249e2ac2b6263422993923a0c8bd05ce56e385ed13c943b03d226856947", + "sha3_256_hash_of_ciphertext": "1b9e81dde694488b9004feaa16040df9fd298d93c87b2384fc0f04ec857ae54d", + "shared_secret": "78492b7b31cbebcf47ce753e8a578751c7cd060158a82918d78286baedd8a81b" + }, + { + "key_generation_seed": "aa6dd1e5799cdf7af9c4fc632b3eb9d51d66e85c8e0a21ec98664fc51ab63c7dfda268813efab5204efa60f78bf81d320d01ac09ac06244f7afbd2d80fd356d9", + "sha3_256_hash_of_public_key": "5b70c5bb1b7af3b643588aa7c20567d4259dbe6abd7617a61b48185de8f21e1c", + "sha3_256_hash_of_secret_key": "f03297b8577b131e39946a288f7ca9070e70c1e00e6ff126543556f60dbafead", + "encapsulation_seed": "17fc65f7fbd7c75ceec421dee84dff5a8cb22764a182db17e0ebe857f54d60eb", + "sha3_256_hash_of_ciphertext": "646c1d7d1204c4d52b65bcfd08f44c1ad6eb36113e4fa598f9627b659fc6e774", + "shared_secret": "bf5106b2fa08dd74a6069b58a6e52aa724179225630d2e368a05db3888567730" + }, + { + "key_generation_seed": "195d6c86a3df4c21e3007d7f2768b43c74cb3060e0eca77f0a5d3271542b9a84ae77e0f9f21eabd8c0c6eea7767f4e10fde5c2d79b8400bf96b19014b457ec21", + "sha3_256_hash_of_public_key": "01782fce09e644e310c9286f1e381be9ea8c54a1804e61f2958c1f975aec185a", + "sha3_256_hash_of_secret_key": "3d1b220e747de4ca99a9882a00860ed00abcf2e6eea60cba5194977f97c87770", + "encapsulation_seed": "fa0489f3730100609488e951e6aaa15c0f193bc1dbcfcd013bc418d6c507b176", + "sha3_256_hash_of_ciphertext": "0d1a4344fdc8a778bb48b98c1db758e6a0271db6d65005e60c313877698e1a24", + "shared_secret": "d181d65623e3a59950e40aa86a1452cde8bf98f409d0f8cecdaaecbccc864a35" + } +] \ No newline at end of file diff --git a/libcrux-ml-kem/tests/kats/nistkats_kyber_768.json b/libcrux-ml-kem/tests/kats/nistkats_kyber_768.json new file mode 100644 index 00000000..d6c90b10 --- /dev/null +++ b/libcrux-ml-kem/tests/kats/nistkats_kyber_768.json @@ -0,0 +1,802 @@ +[ + { + "key_generation_seed": "7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f", + "sha3_256_hash_of_public_key": "d4ec143b50f01423b177895edee22bb739f647ecf85f50bc25ef7b5a725dee86", + "sha3_256_hash_of_secret_key": "245bc1d8cdd4893e4c471e8fccfa7019df0fd10f2d5375f36b4af5f4222aca6a", + "encapsulation_seed": "147c03f7a5bebba406c8fae1874d7f13c80efe79a3a9a874cc09fe76f6997615", + "sha3_256_hash_of_ciphertext": "962242140e9b3492476c62847a250a5e425a41ceec123ce0158d601e7af4139e", + "shared_secret": "914cb67fe5c38e73bf74181c0ac50428dedf7750a98058f7d536708774535b29" + }, + { + "key_generation_seed": "d60b93492a1d8c1c7ba6fc0b733137f3406cee8110a93f170e7a78658af326d9003271531cf27285b8721ed5cb46853043b346a66cba6cf765f1b0eaa40bf672", + "sha3_256_hash_of_public_key": "2cedad700b675e98641bea57b936bd8befce2d5161e0ef4ef8406e70f1e2c27c", + "sha3_256_hash_of_secret_key": "0a84cc895da138b944accbef3ff1a0004b8a0d8af5d426d2b82ea4c0e585cc6a", + "encapsulation_seed": "cde797df8ce67231f6c5d15811843e01eb2ab84c7490931240822adbddd72046", + "sha3_256_hash_of_ciphertext": "5c292a0b3e0f411d1d52ea30126d6c21e83f0bb5781cb4418795d4568ded5e77", + "shared_secret": "fe8aaa6558fd8087dd7cab54b4bce50fc625a369ecace58b2ec36f3bc5bb4f5a" + }, + { + "key_generation_seed": "4b622de1350119c45a9f2e2ef3dc5df50a759d138cdfbd64c81cc7cc2f513345e82fcc97ca60ccb27bf6938c975658aeb8b4d37cffbde25d97e561f36c219ade", + "sha3_256_hash_of_public_key": "3dbc65b722a8982d058e27d409f04f744551ecde9015b62607cf67bb8ececbb8", + "sha3_256_hash_of_secret_key": "0ffced333b5d13fff22b81e66d57b6e2a6dba0285fe2a82d5537df51a8d3eac3", + "encapsulation_seed": "f43f68fbd694f0a6d307297110ecd4739876489fdf07eb9b03364e2ed0ff96e9", + "sha3_256_hash_of_ciphertext": "0d21bf3200a154ba18b488794d8fdcb17a7796b0b0cd98cedc882a55764cada4", + "shared_secret": "86435ab2aff9cea1dc653ce819721a56933841f29330869b63e36604a6ceaff2" + }, + { + "key_generation_seed": "050d58f9f757edc1e8180e3808b806f5bbb3586db3470b069826d1bb9a4efc2cde950541fd53a8a47aaa8cdfe80d928262a5ef7f8129ec3ef92f78d7cc32ef60", + "sha3_256_hash_of_public_key": "94391b7a41175a41c15cd995ebc69c83b29e4bcea6c186611dc4a79578e37f4c", + "sha3_256_hash_of_secret_key": "e3904266e186b34a397014c95f6d314cd6e1c813348b02e977d0fd21d9bb681b", + "encapsulation_seed": "ea74fbc3c546500ed684bed6fe3c496d3b86d2d6dfaf223969b942e9a8c95e85", + "sha3_256_hash_of_ciphertext": "9bdde47293bfd0a5b054c7ef58d2d9baf78aa47685941f315e771595b15c99b9", + "shared_secret": "f9a2d73f0a81b5829e7c7cad8fcf5f1ad55b384b2427c288bfbf4c29540f1db6" + }, + { + "key_generation_seed": "66b79b844e0c2adad694e0478661ac46fe6b6001f6a71ff8e2f034b1fd8833d3be2d3c64d38269a1ee8660b9a2beaeb9f5ac022e8f0a357feebfd13b06813854", + "sha3_256_hash_of_public_key": "c5dbd68b3a8c148b2e7ac049bb986e14dd1cebfa1cbf3edd6bae85a4d2dda082", + "sha3_256_hash_of_secret_key": "b3fa7958f4b7ccb68712ae948c3f08740c8b89a69e53ad4e9959234e6869d8fe", + "encapsulation_seed": "64efa87a12cb96f98b9b81a7e5128a959c74e5332aaab0444fca7b4a5e5e0216", + "sha3_256_hash_of_ciphertext": "b898e6fe8eec252f9d2b16894f9e29425514eccca8aea8ad7ffc693e57124c4b", + "shared_secret": "83e562482fcf5157c75d3d2f0a35da861689a1009104a071a7bfb10bc4d8cd02" + }, + { + "key_generation_seed": "7ec408f52c9aa723d0c41d9987682a5f4ce6c9da7cd0215af60bbaf5484ab353a08ccf451b049fd51d7a9ad77ae14a81569df8c9bd3a8f1ebea86fdcfb823082", + "sha3_256_hash_of_public_key": "62e0447f7b5ae8a806b741ca5c302230b555c3786c11f3eb43894a8f45e3f7b1", + "sha3_256_hash_of_secret_key": "1a3249c268754c86d2e02ba9d87c2b60b220bf2406b71037cfaf6b089477ffb4", + "encapsulation_seed": "8a95d71228acaa5f9ae6f9d9ca8ae55fde296463b41083a39e833e37c4c90f88", + "sha3_256_hash_of_ciphertext": "f37074f0b62febb653bc6a39f3a242c03572ec4e7b0bdac6a1a807e74044c3ec", + "shared_secret": "445b60a142d4853702a102f9cc37fdfb1d0b14a9a7e210c7d290f9402f0a2f40" + }, + { + "key_generation_seed": "c121915bfef6abdfc177dae2f5a24218f9abda2559afc6741b08e0e61ab433eb84ef52db5eaa6df8ec3a0bc5ffa730db0dde8c5f38f266d5c680a78d264a7b96", + "sha3_256_hash_of_public_key": "0c1d832af7b7282d8bd81a2237107ee60d81e28eb64d6a153ae0eaa1a25797c2", + "sha3_256_hash_of_secret_key": "fd6b5d3f120ca009871ca24552a6118917ea882f12f30dc8097f6614d9d36080", + "encapsulation_seed": "90d79d75d0bbb8921cf70d46bab497022a8e750efdc99e5f1bae653275441c7b", + "sha3_256_hash_of_ciphertext": "c68b7acf4074d1ae2ff4055dc420e5c4e808255623874082f31118c212b079c2", + "shared_secret": "71156980b8970fed7f2213594630ca825ea8eade58cc8225df8111460412b762" + }, + { + "key_generation_seed": "d86634ecf96cc2603761e284c0e36734cedec64e7ff486469e38539c71141c5a99daf37400cfe59841afc412ec97f2929dc84a6f3c36f378ee84ce3e46cd1209", + "sha3_256_hash_of_public_key": "2b757ac0425152bef72ed852ab1eb44f4359499407bb6a020ff843a31657c5fe", + "sha3_256_hash_of_secret_key": "27dbbc7918c31e9ab57808f439c4f4189cc318a62422457f4fed733be959c816", + "encapsulation_seed": "be8a32f97b9a8d596382c02fa2a0eeebc15c083e970ddaa4f2622b91d6718663", + "sha3_256_hash_of_ciphertext": "2f7dd9b6567b3c2c8be065e42e3a709339e26dfaebaa6d1d85c88e1ddc214694", + "shared_secret": "eff5e4ce44fe0d0b77cf8109d46c8a888399d1608ad9e2248181bd205a0b23d9" + }, + { + "key_generation_seed": "0610678ff4dc3128e1619f915dc192c220f8fad94da1943b90aaec401683a492da1804ddb5aa9b1c6a47a98f8505a49bae2affde5fe75e69e828e546a6771004", + "sha3_256_hash_of_public_key": "53b9d62e64f9069d9fb94ea2c0806459b201531f4fddd708d162981cc1fb3757", + "sha3_256_hash_of_secret_key": "f4b964b7ab3e09fdf3d91527da06a4d29ef28344709a41739ef56f18bd5b984b", + "encapsulation_seed": "da2cfaf69e25b2a89ff2557bbb6f69e01d8e2e7bb27a7a1ce7e40fead16f33b2", + "sha3_256_hash_of_ciphertext": "db93c9936569e81c7ed2e9c9a29ecedefddd06f793ec869f6dd0b88148e7c43c", + "shared_secret": "25c35f5858d03291c0132c970e6e072d8a7b33419b984b391a12891f878d981f" + }, + { + "key_generation_seed": "d322d56d8ef067ba1f24c92492b9c56df3a6ef54a304adc1b69913766a1ce69756047447b810cc094d400ab204cf9ae71e3afa68b88586ecb6498c68ac0e51b9", + "sha3_256_hash_of_public_key": "9cfeca12dfe978bf0b7ad7271487cf61b2b8f7c60f389f33fc18439a95bcbb63", + "sha3_256_hash_of_secret_key": "a2e37a55c9b80fb423f40585180b011f32402d0320259285b6e278df6c20ba60", + "encapsulation_seed": "511c2ab40782322c06111e144e505328c4e5bfc890a5980a2bbc44aeda4c738b", + "sha3_256_hash_of_ciphertext": "758e2189cd55f9d9fa80fbcfa433bce052cf402cd53ee060f930356f780ecd62", + "shared_secret": "f9eb1c87813c712cc3054109acb5f219fc1e29db10ff33d093a5cd67df995015" + }, + { + "key_generation_seed": "2f1d8a3bebb34540324b9485fdf3d5be3b858f544abc3fc641b5728cafab03ba8d6c42e7270ee2b77b6045385f3d175984a0e260363166c73b0c70c971644363", + "sha3_256_hash_of_public_key": "9aa64a30bed5aa8300772066ef577f79bf4813e3315a15f2c28b2665e4dc7e2f", + "sha3_256_hash_of_secret_key": "837eb6ce037f235273d7686fd9d01bea14026e0a0f5f943884f18409cc4bc70a", + "encapsulation_seed": "dca92dbec9b260dd97e8886f876862d6effc3b91fcf3fbc986cf56ab93ae79a2", + "sha3_256_hash_of_ciphertext": "8a8d7f3524c3ef9c1dd37d62969e9a829f61409b132ff5b2732286e22bd08af8", + "shared_secret": "a2b1d4028af3777be109a51fab5b7014681b0be94a7c06e8c2100565667f21a7" + }, + { + "key_generation_seed": "31beda3462627f601cbc56f3ddf4424e1529c04737ef0ef2af6d7401f653b8a1812083bfa3b670e3eaf9b443702fb6db16ac1197656bbd61a8e25ed523b8d1e5", + "sha3_256_hash_of_public_key": "241e5c7b836862d7482d507973ae3fd8dae96eec4ecebcedb68fbda75e04b401", + "sha3_256_hash_of_secret_key": "95c79c2a867b3e8a4e4e545ff626cd49893b8e87eb188ed1516b159a24736c97", + "encapsulation_seed": "57c170e691d7a914a901b9a11c62b8b569b3806427557a9dbac9faa720ec3641", + "sha3_256_hash_of_ciphertext": "731f4dcf933a93ab333df3632b48b059b0bcd6fe8956435756ea53d67b539ddc", + "shared_secret": "4a2bac4d2a30597aa5b528d0e20b1630b20a36e8d747b5ec41eeb57950375a5d" + }, + { + "key_generation_seed": "cbdff028766d558af4466ef14043a1a9cf765f7748c63cc09dceb59ab39a4e4d8e9a30597e4b52ffa87a54b83c91d12a5e9c2cd90fcac2c11b3a348240411a4c", + "sha3_256_hash_of_public_key": "6ad1d739f1598a16c608a240cd13dfaf8263d74866315e2898a3431cf19e4685", + "sha3_256_hash_of_secret_key": "1ef733faa4f2cb53cb5d8975aa6797b5f37fd918aeda02178a40584475cdf667", + "encapsulation_seed": "6b5a14e1473abf5a33d44975ca2088bd8fa6fddcb3f80e8fd5c45b9d90c24a5c", + "sha3_256_hash_of_ciphertext": "7e5fcf6be83e2dd9962f842b8f7879d6b0f61c31d0fc12cdce7eaea33bb9b0cd", + "shared_secret": "e09c8d7e5d104c0a42b47f031efe22a79ba1008efdfb80ffc7532f40fc9b3a94" + }, + { + "key_generation_seed": "4c04310bea66305c6ca8ba6b8f61ca96257a67663afc11761f13fb5c7b324b6b8aec87a9a79204cee2986867a2906eb851b734b8b22b91d6749b1a5f07c44e3b", + "sha3_256_hash_of_public_key": "9510a2a0b4fcbd414fc61aff04a8df579660d14b13c40ec0470c45f639b65a58", + "sha3_256_hash_of_secret_key": "0bcfa8078582f60e218047d0016437601da8431f34ae6da12921f53958f32819", + "encapsulation_seed": "40e593754e6eddb7f9cf176ba2d5fd1087c90ad377556d0b0f686537b1a3165e", + "sha3_256_hash_of_ciphertext": "f71047763708b3af8d9487f2b293b7e58faf7ed988642ab901eb3968b59f7aa8", + "shared_secret": "1f8d087b541b57a9d85f0737c39e73fde01db5bbe539834d8f918426a57df9e5" + }, + { + "key_generation_seed": "38a0d5f41d7dc1896efd1b45b0485634cef149828751b96087a0a6dd81b4d58aa2acf359556df4a2abaeb9dcee945829beb71185b4d6bd18b76e5668f253383a", + "sha3_256_hash_of_public_key": "cfbe9649d9d1c384baad67b91b2f3e21f2fadd6bb582a0b9cb016051dd82c75a", + "sha3_256_hash_of_secret_key": "09b118f7c4d059baf27284d127d4e85d55b84e4c92bf3127eeb318d2f5765401", + "encapsulation_seed": "c152523abd8248bed40c3827bcf0f8e8127037a55c780695e2c28ea3e041a44c", + "sha3_256_hash_of_ciphertext": "cebd6e1e4a16d53cf241c686a5516319bf7ba7ae1248368a874484e270fe56d2", + "shared_secret": "0da3b9b56fa25f4ca356d3206b99ac83fe84a09cf7fd55a33268c122a8fb51ab" + }, + { + "key_generation_seed": "97b5665676e59e3538ebadaa8cd50df1f9fda1502d9894c616a946078e56b621df05318b5f655efe36f1b678cf4b875108a18db2fa312261caf839f84bd956c5", + "sha3_256_hash_of_public_key": "a19c2c9c907b129d01cc44a95949121c39534cc98b6d105e60fe519a000cc2ae", + "sha3_256_hash_of_secret_key": "f1c00070780a7a2ac5b57ff3ff765ca75278bb661d1635cac92792f9454fe8ba", + "encapsulation_seed": "ad6466dd59f26b762fb02b19eedf5f79964da68bce0459b91c3a6ee5a7e01183", + "sha3_256_hash_of_ciphertext": "602b24bff7f990322b92fe715ed2fc790821ca44f1f83b1c1f8416dfd99ac106", + "shared_secret": "806390146332daf2ac2ce5499d2abec128137cf7db02c27fb457663c18a0d7b0" + }, + { + "key_generation_seed": "ef99224a03a85a46ef115474ec5b5d620da6795d6efcca4c9135d19958a9de62df7d92dda83e6b2ef4cce08c9134563063068a196d7b1a1a13623e48ae12528e", + "sha3_256_hash_of_public_key": "e4174b6e7542fbe80ab2bc06dfb802f691aff147ff90332d5ea739216c18d872", + "sha3_256_hash_of_secret_key": "f3f3a292f5cf01d6f7266461c9e8cd44bfc8f17e16035ab8d10af8177f389b86", + "encapsulation_seed": "1a4d5dff5847cfb48333e33bb00ca7301b144aa89dcd412ff5a3b1081d775b7f", + "sha3_256_hash_of_ciphertext": "0e184e227d7499f0a5acdadc353e8e83ad8ce17b836ba41980bc7662b0c21bcd", + "shared_secret": "5c32a0ecc8fd7e70c1b389fe25c91899c37ce4ce672e299a41c7732f4f0d03b2" + }, + { + "key_generation_seed": "b12f6fd965ea9c5b947db80fc60c83d5e232dca82e7263027c19bd62e5a6ff550f6aa3e88f7fa8a96067f8cdaeceeac90c2d0b5e277e56e9c405ec9420c30252", + "sha3_256_hash_of_public_key": "2006a70fa33ff4a65b00553734c5bd8cca0a65eb3a115d96b8aa90f8fdc5f8f4", + "sha3_256_hash_of_secret_key": "7334d4a1755e1e639b3e9eadb5996cd910b55d1de5790469f229231d3bfb1528", + "encapsulation_seed": "34f44ec2092eeaf686f2ea170591a98527cbb03a4fa9477a7aef6b41a54feeb2", + "sha3_256_hash_of_ciphertext": "cc7108f8cf530f939b4babfb6d10d61a8f1077c96fef8c2d74eceb2659a172f4", + "shared_secret": "4fc71b4d0a7cd5d80824e137b93f8356aeda6a13a55c0515aa74eef21447caca" + }, + { + "key_generation_seed": "9f52af92ca165fdc38788f2b59ba02e01c8281ff7c1e60504688043a5fe814b04f3029e1be4e1c0258c3a22ff5b50b2674cc094ba7018da2a61569845c17d26f", + "sha3_256_hash_of_public_key": "631e1de2556ae65d57e600c21e8e355a4ed586d667177ca0b7545cb5a23d669f", + "sha3_256_hash_of_secret_key": "3d4d2c680a1e6aa83861ad95043ded260e720ae80060320feffa309b4281ba3d", + "encapsulation_seed": "6250c81126572eec2da330271db36ee591f060fc7e53eeefe2e1c476c675fa33", + "sha3_256_hash_of_ciphertext": "8f755c36d1f19cf4b1d72ce3295fd7fc4b5d74165a19397bde4f8980d2cb72ee", + "shared_secret": "5a864018c4c8c17c01c5ef38d7154668d9099994d92ed2ef55f02cf6b3623fd1" + }, + { + "key_generation_seed": "851ea90fd3854cbf28fe39fb81f68e4b14345cf0d6eee7ec4ce772513df8410d1c0ec046899a777655233e4e1b5ca44e9afbdc67964bfd5d5e3dbb45e60d03cf", + "sha3_256_hash_of_public_key": "87f3829eff562789b3e19fafec92e4b5f95b45f3786f12d9c24915ca484a49ce", + "sha3_256_hash_of_secret_key": "9aa6c0546cf02085e2b3af65a7d7fd32d0f6d8080e1e7fbff6c39bcf3086ece4", + "encapsulation_seed": "35d470bcc5880872754810dfb3f2796da2fd7f397537146f6488c27804072b34", + "sha3_256_hash_of_ciphertext": "bd1de588978206a5d400f38cb7be532e93839fd59fb52dae97053163667a4895", + "shared_secret": "c8b9932975c3ef329424392da29b103f367fff38cf402b40a0299bcd2cf10fca" + }, + { + "key_generation_seed": "d304c9389cc973477f169788abcb9d511f843219d246a9b587822f422a70c2386590a2e5c7ed86cf2c5c2a898662bc9a81418720bbb632ef9cf0b845ed052d73", + "sha3_256_hash_of_public_key": "699fb2f061a75f111f4a7a60195d9045dc01716b6502cc107cbcedf122e8f619", + "sha3_256_hash_of_secret_key": "421f16805b1ceffcd64128b1296521ef812d3a8f4c5e3875a049f8de456b021a", + "encapsulation_seed": "8d667921c5db401a86fe1c35dfcf164a6bb2ab7400fd6a0b67eafd4a0ed11940", + "sha3_256_hash_of_ciphertext": "eb84a0b49f4d5e7b64227d4c1ebb34272eb4adfc61c8292f9eb035bb3a7fea71", + "shared_secret": "578e4e308f2b426a7b1ed7d80c72396a914ce77a4a7a6d16b26e4af3d59b491b" + }, + { + "key_generation_seed": "89a6e3be304a3518fb82b18ca730f0b359cd6ba90664a493fb4f8edaf965b9c3b6591121e25d64010c25a18676033e1d7278ac5f2d0b43a31f3a4156ae710465", + "sha3_256_hash_of_public_key": "d3413880d082f26986fcf452a84a8da934ed06198b290ada1789e74d9081a9e7", + "sha3_256_hash_of_secret_key": "7b546a42ffe6b65cd9c5b8857c2518f4f8e0bf835c894a68d1743691fc9aad9d", + "encapsulation_seed": "ec750b3939385a3f8df868119dc76f77ca845567ef068de6ada5478a56bc78b6", + "sha3_256_hash_of_ciphertext": "a2d61450626fbc4167a67ebc41aff6de662cd1b9d97b798b0a82adcf688ceaf2", + "shared_secret": "70080e3baab3fa55e8a308e84fe9abae780be8c09e211651f6ebf6053f8f264e" + }, + { + "key_generation_seed": "d569b935ce015c85f792f8f7fb0d83c4f53b492959361dd4f75fb764d656450176eae84d11c4528382828f7a689a0d5cff87b8ca0bba97feacb39b935a8788cb", + "sha3_256_hash_of_public_key": "e6eec2929feac2a86c9dacfa6214e2e353fda2d547c3829f5678025ff8418a1a", + "sha3_256_hash_of_secret_key": "5fac243c82807d7357a61023226a7c270525d96932162ca5c09fc8f7b9ec6cb3", + "encapsulation_seed": "74f1d52af09b12c36eb062ea7528550cb4c18a3ce8e4f4ea9fac43ae383bc925", + "sha3_256_hash_of_ciphertext": "4f7808244313ad693062e2e2a6419261801aad59bf06350dc1fac1ed50a5739b", + "shared_secret": "f804333e26c5981eb749e8e9fecbe8f8886e493cf8013a6760a1bf5d4a37200e" + }, + { + "key_generation_seed": "5cbb141c2763425c274f7404fe530d9116e08c33f9f200a20b011cf563a28990fc9ebbe336dc464489861db8253606971bd0a9008a433ed17752d04023781552", + "sha3_256_hash_of_public_key": "c74f3b7fa6e2ef8ce99508c89cf3c71d666ab065a262581a5fb01b2c9b9444fa", + "sha3_256_hash_of_secret_key": "5c6998a20960109a4c9808f8f8575697b2b8d18c44c7e9dff97585ae43e6004c", + "encapsulation_seed": "4b3a70d85f640d1a2a852fb6fe96704af56a7415a8ee4282e9207bc3a2dc116a", + "sha3_256_hash_of_ciphertext": "1ff8bc41435803d1931fc2a758d9f386083e183e2ce14394e9833a120a9d2ddf", + "shared_secret": "eb9b44605e6b8ff3a59e567c1c16c6f96b6079f8e2c4d70f706d30df82f09902" + }, + { + "key_generation_seed": "293abb6d1c207927945417cf84883ef010823e11b487ed55239e466e83696d0cff8563038aad865a817cab9ce98846ba75be9363718ecf5fea538aea90b2a558", + "sha3_256_hash_of_public_key": "7378ef967195c977d43a50d03205044006715a6a8a8263d717f40170b49e6bd0", + "sha3_256_hash_of_secret_key": "30bd5f16c3f242248a4c4cddc43508bf54535958657bda4dcf105216ddf47eb0", + "encapsulation_seed": "26e38ac804fb5b4d59ddf747715e7e6041d875f99c7b638024b4af82d622da60", + "sha3_256_hash_of_ciphertext": "4d6f027097a767ee92937a06e618dbe1a2707b974d6fe8e4fe0c72d90772d44c", + "shared_secret": "5635fed1a43168075134d0e6dd4c9cff6e85f3860b3e9f1cac06b249d62892de" + }, + { + "key_generation_seed": "74d87c7556f2671f2d666854a4d6e073e69f35421e6e1a428cccea49c37f972ce1fb7456ac0aa1b97068f452cba64ebdc138bcf5d36b0a0fada2a3b374141eb9", + "sha3_256_hash_of_public_key": "16fe956be4601573d72306a251f69bc2181253e2417e178341fd6553303ac189", + "sha3_256_hash_of_secret_key": "873c94f8bee9fe37265d5dc0c5d3bc1c706057c7efb3cd2cd5ca9ba45498d0d1", + "encapsulation_seed": "a319d2b8f114f1acd866478bcdeba6fd164dc4e37b0adfa8d8034afb3e197376", + "sha3_256_hash_of_ciphertext": "b84605835fbbbfdadef1ce96daa0dcf97d2f20310a45b4cf8eef2e4878cdc5bc", + "shared_secret": "a920df59ab127d563d7e7e96afe8075d8a7242b0ad88d72f367545fac6daa4c5" + }, + { + "key_generation_seed": "013bab0212d04ecd54b478daf72748003a25e2cb060ba6cc50bf95c292b8206b9da0c5da5f195b80fbb99c2e8b06926074f3f604b3f6195b5a5b9737876bba72", + "sha3_256_hash_of_public_key": "633bee89571e8fc16151491ea71234ab83289426559f90c67903a36e4afaa6f4", + "sha3_256_hash_of_secret_key": "3c3cff5f49a802cec693efbfc264f6a385210b1eed20f7bc5b07b51839961d14", + "encapsulation_seed": "ff646071b2509e6b75790917e08e4f0b0d9f0116ec6291c0b59eaa4b583ad830", + "sha3_256_hash_of_ciphertext": "85b2c2d105917e9c47c7f1cb5355fba0c5c90115da1ea850f8dc520980d8233e", + "shared_secret": "462f8ae0143a9173e7fb5a0b476adac03f2600fff5779cc1df9dcad9b1e7ab84" + }, + { + "key_generation_seed": "ccb073c4b90be0ad746e26fb093b60c70110bd1dcbcddb566a8cffb7b3caf80e71600a8982c350df524cde514431ded7aec23576530894bcbf0ec0bfef0bb64f", + "sha3_256_hash_of_public_key": "3217d034b472a846cd317681c0f36feea187bd40e546dc4ad69c2e67fd9d8303", + "sha3_256_hash_of_secret_key": "1503bc141825d523c9505d34f50dc0a01d7bc91cdaee6b99f4a85a24ce800496", + "encapsulation_seed": "0584270ec26f3b9818e4af074d17b2d51037cc8dfdcbe3b140fa4fed5deebc54", + "sha3_256_hash_of_ciphertext": "4a88fe4d98d08230a339829a486d94c328e7eef83df2336db6ab82da74b3ba43", + "shared_secret": "bad63432a274bec85e9c361191a3431d6f211f1fcc69173b9fb00c0517ac3b3c" + }, + { + "key_generation_seed": "2e889f44e28901e9ac7ca6b2fffcb124c8979401b17064d7e1d51a7e3c3adbfa0e145e44aae52cfc609e6f47fd7a6f6af877190ff52256d0ac5b05b89c3f449f", + "sha3_256_hash_of_public_key": "d1756ecfaeb695001ac490f36c4638151bee98d367fb7adf0e06a470844068af", + "sha3_256_hash_of_secret_key": "a21acea0fd4354eb0c78d47caaf93c9f2434f1cf2d6b2194871ccd98f9522ced", + "encapsulation_seed": "51e05c7b4ca3079781e8293f4eccebeeb2f8c8b4c59468eddb62a21bcb4ab8a3", + "sha3_256_hash_of_ciphertext": "2d8dccd1c8907f15a0f5b521a10849f836fe822729c4bbe91bdd4c631c6ad80f", + "shared_secret": "50cd9d6042e7708f347b3d187430d070f0d8712e0bf68350ab47f4b50f04962e" + }, + { + "key_generation_seed": "174aaa36410566dc15a5e62874218d7abdde0b2c0f30d877bb80b1abd5f5a0a450a7a2354f7e5cefa6f4a4e9a1c411eb9364506e9e1204a8acb3cb77fbd2c4ed", + "sha3_256_hash_of_public_key": "1b1b0a8682caf72df2e0a48513a7358edbc77a615d6be6fe2a7145be66b7c509", + "sha3_256_hash_of_secret_key": "3e214f25fbf4d1bb670a87367399e1b2a9da3491cac5a22a2c18dcc44f3f1bae", + "encapsulation_seed": "9eca0fe36c80fc5eba171c3ae66a5b1c923faa50b4521bb055e7bf51005c93df", + "sha3_256_hash_of_ciphertext": "b0e274894823b30ec50f790c7658c7b7e79d4e269c7e4a66790f635d265f72e1", + "shared_secret": "2e610015c6b440280d6f28d5e3ced35cbf65a70a171151363c4cc882d7899e0e" + }, + { + "key_generation_seed": "351fe4313e2da7fac83d509f3103caf7b4c64a4d458fefdf636785ac361a1390f072d9b5a99f9c7a0a011e4dc10f6b600d611f40bba75071e7bee61d23fd5eda", + "sha3_256_hash_of_public_key": "2c54df6e9020e1e44b11b471dea97a382a2fe8d1042565bcd51ef21cc0884d68", + "sha3_256_hash_of_secret_key": "c6bc9c9e797a02684d3ad8de47919b8d8fdbee09258d084c7a9dc963c80401ac", + "encapsulation_seed": "0c5719261caab51ae66b8c32e21c34e6d86ee4aa127d1b0195663c066497b2e9", + "sha3_256_hash_of_ciphertext": "ff01837c1bfb9790421dfff41272144b4c95498207ffb6b9a29f0b3db24da9af", + "shared_secret": "91961efe34b53285433fa9f780a04b8e47261e7a6ef77d46658e7671d800e2f2" + }, + { + "key_generation_seed": "9bc5315580207c6c16dcf3a30c48daf278de12e8c27df6733e62f799068ad23d5a4d0a8a41c4f666854e9b13673071ceb2fd61def9a850c211e7c50071b1ddad", + "sha3_256_hash_of_public_key": "bdcaf7b417da8b8933279b33068f6fda313826c2eec500b224cbe046abeb37a7", + "sha3_256_hash_of_secret_key": "c96e176b19f4135add434d0dd219024587d49fdb649bf470e84d9518bbfa2879", + "encapsulation_seed": "0e59f6f9047c784c1f00b24454aa4f1bd32c92ae7e626549972f86fab90e7e89", + "sha3_256_hash_of_ciphertext": "93199c23b5751ae8e1278d9c4792eb898d51db9b4a98dd532c5005da9c86f0e6", + "shared_secret": "e4983d6021d6c10e71f474d76650f7b5e23e02805f755f57a1012882daa77abe" + }, + { + "key_generation_seed": "d8b907b34d152ff8603b73051f772daa71eb902c47b7e2f070508269d757e02e36b817736cbc5f7b1dd6eef5fe6332fb1a598f3871e5470d440fd2ea631da28a", + "sha3_256_hash_of_public_key": "61e27e954728e2e2e230c94ff009417d7372938e2c29c38af22184eed530fa1f", + "sha3_256_hash_of_secret_key": "8baa58b1d3fab8ec5cee8841c9012506cad40bf58a677adac88f1a6400506d40", + "encapsulation_seed": "a3963ade17d69debbc358dda82c7bebe2c39d25b36813058e7a161542e3f8c2b", + "sha3_256_hash_of_ciphertext": "e9831b8bf3683bdb258faf38f7ab1772dac3851bfec7890d65fc0cdcc4bd3ed9", + "shared_secret": "807703887ad9601806d0bfd5f9d9b6cb01bee01f82500f525cf4cca6e4b21fd6" + }, + { + "key_generation_seed": "684a29e4e5480a5f2533e1526b5fac8cdf5927f3d85087c71f928c59690eb56575d12195ec32a8686d0600e45d4a7f54219b0d7a3826d193a51b9156ecf2edd6", + "sha3_256_hash_of_public_key": "672e53b28d579974d268132187e7bd72238639c6f2ca154d50d98c74096ec330", + "sha3_256_hash_of_secret_key": "4c72f0a7ef5c3274c49365cca5e6770bc709ef12bdbd4fd7c2eb5faa296cdfe8", + "encapsulation_seed": "97beafabf2c8575586487c7a80e8af5fc50f94b6051c1bc66a5ae9f66be3cea7", + "sha3_256_hash_of_ciphertext": "1892658d3ba82460b22d0b062da2a2a2e2b1756f877c718d6ab64ee2ed2312bf", + "shared_secret": "9d28091b20946b5507ae42bc4355a71acd2b5ead20d4181b22a5031ec53ca00f" + }, + { + "key_generation_seed": "d76b3573f596eb286ab5231feec7499686b13021be36cb126c7ebeb9d7030daf248c0a21ea0bb6d6f56f12300e8584d8e9a34e0e6f52227281151ae4c305fb8f", + "sha3_256_hash_of_public_key": "b86d5b13bb8b72a9fb81245ab712f0d10f0e2e09b222143c420e3f2c3acea27b", + "sha3_256_hash_of_secret_key": "c25f2e16a0e6fbf0729e5ee89fbbdd71f00ff9a1abbb00cb47f26e9989eaf678", + "encapsulation_seed": "75461decd34c50d6a094b4a64fb75e5e9479f8f9250d82bb7d729dedeb2d4b65", + "sha3_256_hash_of_ciphertext": "c4b79295e9561bf7d5143d27ed021b4e751a92b8bf22035124a5f7e2c5a13ec7", + "shared_secret": "98498206d1f4d3c94a054c3c3a6087760b210d2f3628c71ccf3f0ade9694ed7a" + }, + { + "key_generation_seed": "b87439fde81c9e39eebe7cf741c685785532c1dd23e8ef868b9ce7a541010f3d1646460817a0fce5836bdfe124a7448e7adf7b8ecc2652ac6d280e986682df71", + "sha3_256_hash_of_public_key": "85441cbd71c18717e9de7359b920a9a3bb7f32e619806f4e4718c585085be624", + "sha3_256_hash_of_secret_key": "93b65d2df33d3e3ab0d53c1d0a21f3752e2c5962f7d960b888b2a8c495b1b133", + "encapsulation_seed": "2607dcf4fd6ca1c614c21b5e37c24981c32b91c8c3e6955777da8a3f5d9c9335", + "sha3_256_hash_of_ciphertext": "869f16ec6c5c47a2ff2283f166616f16926d0fe805333e70945ad6fd1e9a701a", + "shared_secret": "c93350d1f27f771801b7c3e03a2e7672146809d37f33ba262e9e0ce7809b2187" + }, + { + "key_generation_seed": "056661b38038da4fdd7426f32a81576c73ed84843b305168a374f934e27a4e1b79238a80dcfd7c992d84b2dffa67493e669243d4fa38c46b090bdf86bc548411", + "sha3_256_hash_of_public_key": "065fb6156acaac591f1bf3ce71c4a046be8c6c55eb9a84d29569bd2b144c73e2", + "sha3_256_hash_of_secret_key": "0121afcc6aeb8be9f1c5b06d5b65cc1c03e9366ed7b85fc511d853c5eee230cc", + "encapsulation_seed": "38c89bbe7145c29e9a831c11431eb9929cb24fb4992db20737e4687d397fd732", + "sha3_256_hash_of_ciphertext": "4cc25957859ee2a08070380f4a5301601dcd4a756784c9719de99d09c12fd85e", + "shared_secret": "387e023a733bba407f35d4456a9edec3922b151c3b49c67bf3541bbee5bda18b" + }, + { + "key_generation_seed": "a1b52d871612a1c611ae0944f9e71858f35d3bd14f20e96a931720668bdf0a6b1f135cf64b6403e103afae34da038613e2853bbfc36baafa3c6a95347193f37c", + "sha3_256_hash_of_public_key": "ced77d358342759291c2bd225b0bd82d659d28a24bbc5eda8f47975b780cd129", + "sha3_256_hash_of_secret_key": "16e06287bd8d71c78f1657bbd6d5d12c22f6bad7658e68dd849d7751da950860", + "encapsulation_seed": "b2c35e33c72d90182791f0e12a0324f5b216efcab2c8da1bee025dfbe13f4152", + "sha3_256_hash_of_ciphertext": "78e964378f328246da5cf23098e6b5311f4a6dd018faed91dcc6fd5c107ab366", + "shared_secret": "4d91655d2bd77339bb81f82916a1a77329071b3919cfb35cc1d1655c2da5a2f7" + }, + { + "key_generation_seed": "952b49c803d6d6fba69f4375adce8594847a00bcae2179da49af2aed0423250262d7033947ae42ca53522a65fbafe18d3bc3e0cb66164e9a094fe4b44d8977ed", + "sha3_256_hash_of_public_key": "2fdb7c7e39ce1625c20a13a1c91aa5909d8b03b064d00877dce2415020370c72", + "sha3_256_hash_of_secret_key": "ffdb52b23a9ca4b71ec882031ebcb33a0ecc6731c13c817b24f3a06e48273778", + "encapsulation_seed": "afb7d6dc2b7eb6d84acc080c1be63c98afe7b07786b5801f716444a3e8e64800", + "sha3_256_hash_of_ciphertext": "64e3d0d521f46ff42772a91a33368013005d6dcdb72310dcfc1bc53d6b6dd524", + "shared_secret": "3d0d1ad5e2825db1f539515af2392f0d212e8166b34f3d8cf2ebe97e51785ec0" + }, + { + "key_generation_seed": "3c815e57e9233e975fa1630208aab206b71ae0db37a7a8789ac683d9f9b2d29801c8e376fdb140ee343106c093af7cb149b316ba79446ceb4e5e0cedb9b164f9", + "sha3_256_hash_of_public_key": "86bb11e7d9c1368fbba34ce3a2f169c2464ef5fbc11f73843c456467b6cdbd4e", + "sha3_256_hash_of_secret_key": "5d46659798d268f1314ad1e7c1735c480301f5877773403966e928bc3fd33d1b", + "encapsulation_seed": "28f5e9dbda122b2cf8f3754fe9e0c73a84ad4b0c093522e0b62cf815d60bbc3c", + "sha3_256_hash_of_ciphertext": "1002639fbd0211ab78f332128acecb9d75f7af4eb0d255a24ab19d7058012b99", + "shared_secret": "ff9a0d1ae64c97e4c51512b315d044c14ca34771df320ba0c16c8531d6a40d78" + }, + { + "key_generation_seed": "588760826dcfbd36d9abe6ae44a669bb3ebba6a218eab69e30f18a3bd536576e0e860576285483bb5fd36e2f944d32c4317bebc1e441470c1372046a790d79d4", + "sha3_256_hash_of_public_key": "29253478090cb4d580bc2a912645bc685061e5d4437b3811eda69c865ea9923c", + "sha3_256_hash_of_secret_key": "aadce411f3708e9727e4a7e4e198781e1ef5e8f4c4c14add1e25f5758649e265", + "encapsulation_seed": "b0d713cbef0bb1df70cbb425d1e9373e9f7790fdc7980cc96a240dfc53f1e8e2", + "sha3_256_hash_of_ciphertext": "8e8019b55e3bebe889ef989277dbeddc8632824845dca75b43144d32fea9f78d", + "shared_secret": "0e40bef57dc97b87ef89e5308f9db94fff59a475dc35ead3f2d5b6b89d24ca2d" + }, + { + "key_generation_seed": "47550e9edacb6ddce3d9ab81f6b61080dd4f2693854acb05e0ccc7a4fb6390fbf89d7d99d5c3e0d10d6ef9af054d842375f695abb28e3b8eb495100f04306e92", + "sha3_256_hash_of_public_key": "286de7dc142efe935e84b0aeebbd32d050fd9d8b008a94e59454b19ea401611d", + "sha3_256_hash_of_secret_key": "a6b53edf9efd7fa67a478456a5b6a379876c248f623ea45f4b541a8db00c524e", + "encapsulation_seed": "32bdcdb7059fe27f6409901980c080308951ffd90deffa8317b4d213a5f04495", + "sha3_256_hash_of_ciphertext": "12767f1cc2278778a66d808ae6a230428c0bd48e61fca54aad631a95e4547242", + "shared_secret": "6134219801b78f6fa5a998377643f828c19ab6fee69e7dba03c7b8e20915de13" + }, + { + "key_generation_seed": "610afb64be8cc1df288cfb016ee2f44c6c07113de7f6fee071fe0c3fe31c6215cd292e4c5f9e1a55e0489bceffb204d672a6215f4f3980a646d9f880817c52dd", + "sha3_256_hash_of_public_key": "029a2e12c3e6aa668afb5be8a82576813fac7b8e61c5a88aff94ecc2770c585e", + "sha3_256_hash_of_secret_key": "413ae41ee83e17b74ac654c2aca57abe8f8ed0409acf7cc8b301e3d6bb049cfe", + "encapsulation_seed": "4ed7c92d83bd03b2a25b567f17ae55542e2f6a4308ec0f3fe69f8ba5ae24331b", + "sha3_256_hash_of_ciphertext": "fdc158261cb75522352cf6e3208d27d0f2213a33b40522271811b2ee201683b6", + "shared_secret": "787ed075f818be6a0eae99b113dba31002097e0b85a5480003c505a40793403f" + }, + { + "key_generation_seed": "e1953800acaa85ac02a906c72cb8e8d704e8d27820345f88f71e89c1f549afcc8c64c049c6dfc0f1476cffd520b055756162f7ec94243de6b14ac0b9e5fb366c", + "sha3_256_hash_of_public_key": "e3ec3671cc7675a321af8584a0961101c04a432772431e77f5740ba3b2ef488d", + "sha3_256_hash_of_secret_key": "93bf696bf0671c3845c4b246f29701a0978eec5b49de81589009e235903061e0", + "encapsulation_seed": "060ea5d2ed1dd88144a9885e79278590821c22917b55a48920f96b53ebe0e689", + "sha3_256_hash_of_ciphertext": "b07b1e1a4fa74d847910d0769ee7a8daeeab56174051037279d371be2470c0a3", + "shared_secret": "b81e1ea69c6a6e1737c78fe18c36cfdcd26cef62deb805f22a92c49df6596c0d" + }, + { + "key_generation_seed": "c719f9b2d16399b7326ce4eca30dabefe8fdaab18e9f6df888b0a134ef355570e40771856eb77e4633504899fcb86c6a3d433d0b8d60e26f07bd61f1d4ed69bd", + "sha3_256_hash_of_public_key": "79836213a513bd4cfd42ed281304e3ee4560e4e0c60fa53781f83d5bd2bbea52", + "sha3_256_hash_of_secret_key": "65deb55fea451375ef335e7faac73917d32220fc70c95f371fdb16e712beeb26", + "encapsulation_seed": "10ef9426f8c4a13b52325c5bb4ead4596ecf2c6b5bd2d37d8350e90d4164fdd9", + "sha3_256_hash_of_ciphertext": "06bdd1883161221c5e66dfdeaf63ee8f526d63d8a0a2cd33487412b4413d51dc", + "shared_secret": "5d014fdcc992fcfcbdf3af29e8dbc9e5024f2ac41e71a3ef0ea43a063bf44e79" + }, + { + "key_generation_seed": "e9acbb774be970206c3a738e243b420805a509fa59fa902044be2f0d013650d2ded5edaec5de3bf5b4d7c2f2e18e87f499c1968993eff196753db8045e2c8ba8", + "sha3_256_hash_of_public_key": "0c2e803c2872400c49e1bb10232946ab939319e84ff32cd354dc15d082cde5a3", + "sha3_256_hash_of_secret_key": "d37f172803739d074d71a2be32125eb1ba4250128342e34b882fcba38b259248", + "encapsulation_seed": "a4bd30a64cbf29a4e290fa1cc1dfb99e68348713041e4409a1af23c5d80c15c4", + "sha3_256_hash_of_ciphertext": "0c7b5071b20477a398e4db3d83c18204c2a5dfb030f61b0d1b9434a255dedcd8", + "shared_secret": "80548d4687da93177d06d98c1e2def33fe85e770f8b871d2f74cae533f654692" + }, + { + "key_generation_seed": "c1b3cbffad4b306f9af0cdd3028876486dbe858875c9b6497fe20172a986c82b1c96249919cedc2369d8d739ab125e0d2ccb82dfebcd90240a545cdfe07511f2", + "sha3_256_hash_of_public_key": "5818ac8d7a38c781e3a0bc43d088e6d391d1d67d9639b260bb6f58a19a57150d", + "sha3_256_hash_of_secret_key": "280e4774d1b2401580216fa70fb24c2c214ac5dc7f3841710a42e14d6aa09663", + "encapsulation_seed": "f4b66a7d3b65b896dfe100b2cad24b175a1168cfd2ae11fd704b835f6bcd311a", + "sha3_256_hash_of_ciphertext": "aa39d64b106590c57b817f1958dff22fe0e3266c8d4e40a194930a4c32d2beb9", + "shared_secret": "2f2f58e23dba54d8a44ba11aa4546ee3f1819c6243e986249b7102019de3a777" + }, + { + "key_generation_seed": "ff7495b8575b5a98e4fd21fb4c3e58cbb60f14bef21aa74cf8802e3153f14807bdc370460375a778d1a31d01c42b66367ed8d9e8f84551002f552f0e52102b5d", + "sha3_256_hash_of_public_key": "172cf4f8dace8a96b8f70da966080a5e3f132873ca7544343377a99b65e8147f", + "sha3_256_hash_of_secret_key": "31136804b6c14f3a0a00a3295a5fed8d606369e64d272d432c59d7fe0ccc3e47", + "encapsulation_seed": "1d7b03d3c5eefb8ae5799dc569aa668f1bcb8c86607b089d3530cf61d6380147", + "sha3_256_hash_of_ciphertext": "9c7b7cd8cb42ab4bc9fb532405c4673f28cd41751458d7549597ed2f5d993115", + "shared_secret": "0936224ef45e29dfe9263c6237a22798e94e81a932796174271ceccb78188554" + }, + { + "key_generation_seed": "bdc3fba1c32751139fc45bacffb3ea97f26573d804a5f27a459293d95190ed8efd5a08f656a6eb8cd20679930a31caa6a6331c4b133a6838c223ef9f769f6246", + "sha3_256_hash_of_public_key": "268b6356f92c57da6dd34494b927e8764adf0ad519612ef0d1b8951e50966c2f", + "sha3_256_hash_of_secret_key": "3bf02cee24670ca40b7280d8047fa147b24c5e286dcae9c24bace9465bb19f61", + "encapsulation_seed": "554f3385b382f4a46314de37ee3885addfc5332bd4038785094e0a832e9e8c2c", + "sha3_256_hash_of_ciphertext": "12a71af24c3174eab460a2a2d2e3d27316becaae5f714e333a562dccf84b987b", + "shared_secret": "2073cea69b598292f44ebf4af3f7035e1738afb7203ad67531a7140150176e5e" + }, + { + "key_generation_seed": "447f6076a627bbc5ad7773fbfeb14b4ba9ac43a0f8b99fb6dcd5e452aa3c47ec20a7237801f470fcc2bd9fd7bea8322859b850f7882d362947432913dd068c01", + "sha3_256_hash_of_public_key": "4c6d304e0494d88d83b5e3aa5761df3b299551a24f28994d2747b2b08945bead", + "sha3_256_hash_of_secret_key": "5de91ca73756eee74da3cac78a1fb329a02f8587f212bb9bc0b29e0e654a5795", + "encapsulation_seed": "38bf0033b779edf5367d9ebc01c988af90904c560970815837380650e4749eea", + "sha3_256_hash_of_ciphertext": "b83891ce96450ac05aa2f7373675fa1dda337ab61e60098d18e8ec910d63175d", + "shared_secret": "633d9672d83a112a260b9d4c17812359b5591900a3b80424b3590b403a5dfba9" + }, + { + "key_generation_seed": "2d5df64d62cb07fe630310bb801c658dbf3d97993e68626745de39d37fbfc2b27b534537addaba4ecf14f02ab317d36cb9f0f50222ced7cf029dff8a0d3d2fd9", + "sha3_256_hash_of_public_key": "72be2f5cd569e6229f00014854633f7b278e90af4ea593411909467a03e29cfb", + "sha3_256_hash_of_secret_key": "a68ca31b91491a129af9f280cb4c60c046e7a7ccddf41c9bd98663f8512ca34b", + "encapsulation_seed": "048ea516d0ebbd9f709b47eaac66f344c571cf50f0d01c9466aa061a50b66a24", + "sha3_256_hash_of_ciphertext": "b8f3a0ec2b0827718d736ac715dcf10b514771c8b80dc27b283e6636ea598417", + "shared_secret": "7efdc40486793dcbc7c030273f8edb4178075955edbfbbf0f21b793206a172d4" + }, + { + "key_generation_seed": "25056d1b8113bb362dd979d98643d7a7ac9c4f95994c0ba060609b6d07002ff3f48a9254dd40b117941fa35a66bb50296327b725525deef70e128ca8045ec451", + "sha3_256_hash_of_public_key": "0831c75b153fa17d336a79ff6e88ddf485daf7b1b0bcf39d8df15319d52ac67e", + "sha3_256_hash_of_secret_key": "2b983d7cb50880cff761441b6a2c66b7a41642cfd2a8cc297a5df53f0ed1947f", + "encapsulation_seed": "686c921c9db1263e78ae753b1c9c2e7936b8229dca48c0942c56c6bca4f10917", + "sha3_256_hash_of_ciphertext": "df0f1e8526b97933ad6cae8d4059d2d90b292a2e084c2ef2833c89146777546b", + "shared_secret": "a33bbcff1ec8c4d3e3229aec78463ffead5b96c6c1fa857921f8907a9180af07" + }, + { + "key_generation_seed": "e4d34e12982aeeb1d62fd488d9b9e28557ed3429292239fb4f76fa9098009acae6c45c7fc62329b13c8d29844405db8ff6860de474bf727ecd19e54e6e1a141b", + "sha3_256_hash_of_public_key": "b30cedc4316b63d75b641fbad2f33241a3fc47ab8b3ee1a3ed597e5b04f77c68", + "sha3_256_hash_of_secret_key": "a49a7533c671e533deec55af218ee511c57014070e138c7059853e08c34b0a78", + "encapsulation_seed": "2387772e50059cabda53cb93ba24b19ae529496c03b36584169451525c4a0e7e", + "sha3_256_hash_of_ciphertext": "563edf14ab8095cc468c400fb06476bdcae5236e8ae7336715e8feeb7bc3969e", + "shared_secret": "bbc0b0a4782e2bb9eb19257f5b80338d1e239aa6a08710cbcba0adb974d7dc64" + }, + { + "key_generation_seed": "cd6a99396eb3539ca663a51e42063a3a262cc1c5a5fce1566f0597b52ad9fa325a3407f591791a5db4578b5972093a95bec3b8e70c1d542c9b5c9789729f8922", + "sha3_256_hash_of_public_key": "ee044dbdf6787ff038dbf9c133557169c62fc1ce2580739369aa87df00b49648", + "sha3_256_hash_of_secret_key": "9e865967f0d1e7d3f6a49f2bb623ced2a7b1408a945e02adbdca35846b70e7b9", + "encapsulation_seed": "155c29c5f0378df0cd0e847a80a07143cf7522fcd880c9229eb9feb1ce340cd2", + "sha3_256_hash_of_ciphertext": "8cc9b0e48193e9da7cb75bae6a63f83caaab5dc7ac67c5554d46c3fa1db1e647", + "shared_secret": "3eea7528610dae3539f5f81efd9beedda4d45ef0b9ff91d3d4f3561b4981d286" + }, + { + "key_generation_seed": "6c8c53ed6f65e6b2e324b84364e10de42d1c26a106d4d1c99eee79c78586fb55b9402bf02481ce4b27a52e87feb92c4399c7f2988d40e942e7496ad15ad2aa88", + "sha3_256_hash_of_public_key": "e965ac6995d525e324e8252d8e2c2da909a29b24baca8b68daa5122cb539a474", + "sha3_256_hash_of_secret_key": "91051a381626e9465fc7ab20a1944eca64be461330bda53e7d1838a74597392d", + "encapsulation_seed": "a9cb9a61a3324b1ea5afe693b32784e2871096b2ca14a11acc9577c52359a241", + "sha3_256_hash_of_ciphertext": "3d06ab179441a0fea2b05281871e6d19578a63fd1e161aa8c4b0ef7281cde2d6", + "shared_secret": "c5e2f0c1ee4f13fa8fbf2d09a78b04a5e2069aafa978598f96424acbcf41ad44" + }, + { + "key_generation_seed": "2107204cd995f1df14314d5381f8c5440f09a347502e161cffc0a2ec3dcfbc7324c3da70fe850e80aa818301d60c70f3038153866dcd5d179e22db59b8991bb4", + "sha3_256_hash_of_public_key": "a3d8a85f38cfda38c66ae39b2f9186ef7bc1e0c98e8976a6cbc6c4875d73d7fb", + "sha3_256_hash_of_secret_key": "cf7e797f8f7229a08206034737e54fe46645ab2fabdbfc8662b45a2604876b65", + "encapsulation_seed": "e99fbae8a024ebbbdcef32ce213f6aa942e3eca925e5da4c09975d773b33a175", + "sha3_256_hash_of_ciphertext": "4d2a2c762d4fc69191a3a936f0d918a9891ccb72d4a0bfd2de80d27283cbe88d", + "shared_secret": "0b642d9427caaab926dfc155993bcb41bfbfb91e6c6d1c4165d8750222cc3688" + }, + { + "key_generation_seed": "63a925685a8ac5bbd918faa33ac397d1ffbcf99135d9da7c3d6ff7aa4c50af3d3afdb8a246a56ee71465591831c371f2eb87467b0559dedd776ba063ee6d2f93", + "sha3_256_hash_of_public_key": "aa73b40dedd61e6fdaac86971965c03ab14ae69e8130426fdf830bd57d0974ce", + "sha3_256_hash_of_secret_key": "1e7f3f1e5632d1df538b564304f56689742d1f652d8d32f019b45183af68a20e", + "encapsulation_seed": "67a216f37d67f5e74f782f1badbce1cc8c80a6130aec305b421899a4faa0a6c3", + "sha3_256_hash_of_ciphertext": "4c4ecacde036488a6b2361b1b976b86e9b63294bb7df100e35dd3246d423965a", + "shared_secret": "79462708f754bf842716f900e850c228b00996b0e3801b43f6a928bfd4aa9e50" + }, + { + "key_generation_seed": "6a1aee5e708c1b47f02bdacce4f56c860f74fc7cfec1ef3b58285b1c8ad7fec2230e05b7114ff0395cc6634db1eae8258072d09c09f291e92d6620b177dc50d7", + "sha3_256_hash_of_public_key": "cf754f2ee43694865a09ca7beb0deda9b1328fd0abdf30ca5c338e27e8be04b5", + "sha3_256_hash_of_secret_key": "928592604aa44df8f2072f26e9511129f61da0b7f57acb3f6896635a9764ea87", + "encapsulation_seed": "52b19fea232c9154a3e431e9d69cda40013cf2d485c3cd027ad24e645420420b", + "sha3_256_hash_of_ciphertext": "e7c673bdc9d9dc543754e0673e9aa66ae3f4ee7b1efb5f4fdaed89794ea77fb8", + "shared_secret": "bf535eebd3721e4d832fa4c11369808a154faed4602220b4070b78900b008358" + }, + { + "key_generation_seed": "6396b328b100e4c7f4bcae69875edea1a1982421558c608c13c592bf7b5d0fef1100ced48add211a5c937b8d6079d8e271af3f949edc61f70e60453aef20dea9", + "sha3_256_hash_of_public_key": "3a842153dee9e035299d7e268c9492d71188f9fb24bdc2dd20c1ddca647a1523", + "sha3_256_hash_of_secret_key": "28ee987bc4ae5a321d2669950dbf87596fc4b35c29f192836005064aa3dadee1", + "encapsulation_seed": "64440adb05db3308b189bf999f9ee16e8ee3a6ccbe11eebf0d3ae4b172da7d2f", + "sha3_256_hash_of_ciphertext": "4fcc1ca889f0792f716e9ed77d2794b9fe34531dbfda86b01dc6088c21e5c87a", + "shared_secret": "3602269c7af9fe28ea1019208dc3ab33ba09239d435c509903ca67345717e845" + }, + { + "key_generation_seed": "a453bcacdd2b0d4646009e5ed451c3c45f08fb827ef733db3c517a9dc1af93e67a3cc8aa3239d4c52ce4c95afdeff6efbfacac10d294edc0e7cf4535059bfdba", + "sha3_256_hash_of_public_key": "da43cae3c4da51d69a57eb87094a03cd3a9c3e6b4ed864cc691a60f0509cc646", + "sha3_256_hash_of_secret_key": "b204cd1c3122b29a3d99cb77e11427fc102375699928c5a6fe816f96bb212627", + "encapsulation_seed": "c8bb46b3a7344ad170c2052fb042b5a3b62e0590562ee82577b1081f6f114d16", + "sha3_256_hash_of_ciphertext": "d60b51f94c4de5c221af1e05e7603296ed365913f90e061c686c6174aacaa891", + "shared_secret": "5e039d591cfb128e51d0804e0993084fc92b0bca9c0f2d84e24f5fea5efb3b8b" + }, + { + "key_generation_seed": "47ca2b77c5b717f423222c2730ca5cb9c856bc951d01b2b2c80bd76ccb5539b78f1481d7cab000e33fa07de8dc9627a85e76fabb4428a3376e66300cf12a0787", + "sha3_256_hash_of_public_key": "6533c524a32345eefdadc74a3c6ad7e981832797faf1068955b79f118dff9358", + "sha3_256_hash_of_secret_key": "b9dee52055b1f9a2b25a0c1be4d9f30d2ecd7c5a09f0f5294de2d49a55ac9fe0", + "encapsulation_seed": "2e2b70609f3fe029a14d09d5d659871ac776ce2797a0355f16e2eb68f5613fd1", + "sha3_256_hash_of_ciphertext": "9319ad69d886668892dfdd31b359f6abfdcac75ee600875ec47389d1d63d8c49", + "shared_secret": "eae95e643381df7a1ca1954eb0d529db88a8001b8c1ed98a4b055936bbc6c038" + }, + { + "key_generation_seed": "aaf6eb40e596a5e3e8218871e708b089240dcbe7fd3641f0e5e41e071ce49107e2f8d320ac3cb0c52efdc753282f092bc39baf4a18783a48ea031a191865eb78", + "sha3_256_hash_of_public_key": "e2f60f27da7f318eb94a74b437f8e0bc9513e9bcc38dad99c174c1d75e0145f1", + "sha3_256_hash_of_secret_key": "68eaa8143a71bd5f6df29b128781e3f2a5fbc5d20534afb223ddcc64bc767f5a", + "encapsulation_seed": "4725dd8fb314bfd8ee23731c2341dbe114606d9abe6434c471b5573e7df193bb", + "sha3_256_hash_of_ciphertext": "fca5c4beeee972f426128385dfa08f2ad7491e42bb9f414def44f0f9d3fa962d", + "shared_secret": "dfff52ca2afc33401b4f72f5e6ab5d9bc21c08a6843ffb2ced24775d786b5a0c" + }, + { + "key_generation_seed": "6500f32c93415cfdbc0bd31d78d5be95cb9060c8cfa2013955b56f8b6868b322393308641a9a4647f230201e1389624a296b55192a9819fcb19ab77c25f95445", + "sha3_256_hash_of_public_key": "d4bf608793939ecba27dff5889d4d921c583999a57e20a48085ac549573e6abf", + "sha3_256_hash_of_secret_key": "5f9a14a9c41fc228306d79417015408f31bc9c3d97579616bd68a3d3444f9bd2", + "encapsulation_seed": "818d3bb8ebfb32bf464775f7139bac0a5bddce80ec5798595992f9403002cd5d", + "sha3_256_hash_of_ciphertext": "bf911b0acdaf3ba97192e847cf8327696378bd4aee452751432763e7e531aa8c", + "shared_secret": "c870a7be3dc7bbf5836727e5bd82cf977b1332e7db276473e4029ed95204acda" + }, + { + "key_generation_seed": "7643cef2d62cc5aaeecf754653ea62294cd2208e5bf3ddeea209e3dc45373d49eac9d531a532770837a854b4f5531f6e0c8d6c10183b30d3435498c2dd142951", + "sha3_256_hash_of_public_key": "65f03add3941d22c80d50659f501f8cca1b448d84462ccb93d5f065889484bc0", + "sha3_256_hash_of_secret_key": "e4513cfd1dd2153d30d15b023421cb8e8456e6a40e612847e1713e915a29a87c", + "encapsulation_seed": "c92aa5fb91c980d9cade9ce99d4c75b2ffa7d6a6ff9bd59def1aa701f2a0992b", + "sha3_256_hash_of_ciphertext": "66d912705b35909a378354e283482cedd6e3391f78985e9e75e7639efa3268eb", + "shared_secret": "3a14474e05df3ff59c6105b1f2af004a8b8164dd049eb6929b9c9881a873ab08" + }, + { + "key_generation_seed": "f8ee95521060c03bb8dacc79f7eb7db640f545f315613a35d447a09e504cb4e13fc3d8392cb53f36ed647364a04e37278a0e0a45b720f4a75c580c9920eba98d", + "sha3_256_hash_of_public_key": "b8a3b8cf4709204a2fdb19889b0022ea655dfd58ff27e17d530510e1eef45793", + "sha3_256_hash_of_secret_key": "1f7cdadf3d4707efe1b7a6173d8f7b8a9f864ab388c3271d79ec424d9da3e896", + "encapsulation_seed": "7e8086a01dc5b3bb9eda25bcc45d27f99874841b97237968495800e007696ac5", + "sha3_256_hash_of_ciphertext": "02f5530dd9feb48f4013f496bb9ea98d70ce40f75862ca68cfd1b68e2da13a4a", + "shared_secret": "2d26f4da925e01caaeaf4a89f5ce81148a000f7a36dfee74e059a933d973ddbb" + }, + { + "key_generation_seed": "b8bd0493a882e3a49b4e0f6256fb1fea0912562fd9ba26ec3d6c9cc12c8973abd7e4b5d8021c486b9c3114d7cbbeb7cd49eba8a61bc2bcae1f1bef30a1daf76d", + "sha3_256_hash_of_public_key": "46fe6c37136273736ccb11df5b6d55debbc087de802404b72a003c5e8c809719", + "sha3_256_hash_of_secret_key": "3177ed170e84ff15fa1e744adc9ce806e431a68f15a7a026c6092bf593dec6a1", + "encapsulation_seed": "bb321ef14d44d8698df879fd52450567657f52a2df8d111185dcd7d4f30a72d4", + "sha3_256_hash_of_ciphertext": "d65323bd9209bc4e9e6b6ad73beaf3871707b3af1a5cb460000f1cfd47c823f1", + "shared_secret": "5012217b85a1e5dba62a2476d7a441411d8ecddbe2d3a291f658b7dc1d1197e9" + }, + { + "key_generation_seed": "c0407e41ddf48d333978b89bcf2db01e4613425b456249e76a6f25b8a2827bf5b2dca81e3f5f748d23c9d356a2209f6b2d60247b2e45c9808de497f64f124643", + "sha3_256_hash_of_public_key": "a074ed1f76e97d68434ba4af2af0e549204222679e9e643580c35af3cdd247ce", + "sha3_256_hash_of_secret_key": "8f9b3f631d0fb04477846ae09aea725f1cc65b2cdefe2108cdb399c36db9b487", + "encapsulation_seed": "210a423dadd899b810f011794b79aa7f860823ac1962370e791287d3a1afa384", + "sha3_256_hash_of_ciphertext": "bfcb6519e71a36787ec2f499db9c29a491e67c1a9765aa1824a454f77b1cd7b0", + "shared_secret": "0dcecac51c5261e34023d2e04146ccea10a0b39ae7edc50736127184fecfc8d8" + }, + { + "key_generation_seed": "334382d39164d1989696a2ff77b25a28af8bead9883b5365eb6fcca7c1781cc9aba5068af837be962f439f233593d193ce5e08f7d66efb3389885927b89d2523", + "sha3_256_hash_of_public_key": "26659f74fc9ec372fe18be4ed6aa28b7cd84ad1c0f0115dad011a11d20fda9ed", + "sha3_256_hash_of_secret_key": "5e3f83cb08ff80183879af9ade3631bed2a468e429ad027a5afeafd9a6f66362", + "encapsulation_seed": "bc856afe24213e3d14c3d6f9b89223bbcfb2c890722d770fa3492c1e46d1c302", + "sha3_256_hash_of_ciphertext": "e3abb3ac5b54dcad2611ca640bd314a976ae0ded1a8110dfa0cea536ead85372", + "shared_secret": "0d403f00c22fab72899d302cb536854b934446b62f9da6d9d6cf1c0f7abac2e6" + }, + { + "key_generation_seed": "6995143e8eb8a6e93840f76eec844f67d2b5f75b1839a5040337e61f9806764a0f4dff8e56f68440836a072412a30d851ace2c7c6f02d60e7a8420001a63e6c6", + "sha3_256_hash_of_public_key": "2ca3d8ad2dab1dd8a2f4320658fe6eacabf70d907920593919119cf374516336", + "sha3_256_hash_of_secret_key": "2798448395f6ae3223550e7d5255e6a605b430229f5809b6efd0683a6b9ca402", + "encapsulation_seed": "5fc00f89563e44b24cd67d0ce684effe5731619fd08e7d72e2406eb016afb66b", + "sha3_256_hash_of_ciphertext": "547cda0ec8f19690d1a8bdfb7bd8b822872ffb0c321ff096e280abe1faaa45ef", + "shared_secret": "8c0346216cc65f95d2e0caaeec4bffaaccc49132cba2dee8f2a6ce1f922e6db4" + }, + { + "key_generation_seed": "995eff7e0d195c6d0533f3dc194d47e60f9ad14696144cde694d60a95f3e96b4b28f7e7a15a005f92400ce33db073d49b53871594a88fc45e0f94207b5f0f2dc", + "sha3_256_hash_of_public_key": "de62eff56f6b49a156d065d85eaf0aa21ca229a20fa4e1372a410ab1c4ab6e7e", + "sha3_256_hash_of_secret_key": "6766cef3fe644a233caddf208074b58e6e83f8a78aecd00911c29a08f6f0b0f3", + "encapsulation_seed": "ea22a76065db4b565ee1807fbd813b43bde72b0e08407fb867c6a18995025e50", + "sha3_256_hash_of_ciphertext": "f1d6c83633f244e683ea018c1d70818cb923c2c312cf03ad81884d4de4d29cdc", + "shared_secret": "35151c059e5220d4abab9380fb0ebfa061148e6096d8f5678e4308cba0226261" + }, + { + "key_generation_seed": "3e809ec8dd0fec0d911a4e3fac20f70fbb128c5de94dc7184ca7310ae9157a98d8128601c28b1def8d393a0db283229f7c7383152a814e7cefe8ef9d9768c473", + "sha3_256_hash_of_public_key": "66f161d27dc34e1a2f4b98b14a2b221d7eae26a593bfe432487d9994cb480656", + "sha3_256_hash_of_secret_key": "2237f6cbb452d375878b82c474a7c948ff587a5f3ed02bbba1459fa7ff8ef802", + "encapsulation_seed": "e9602b34fe73ad57f4bf6ead99743d645641553a5b9b9bf2e7016629e3e9bd76", + "sha3_256_hash_of_ciphertext": "a4d6fafba699c00c8fc8e453ef1eaf47a7432e9c7f413468e126b24b458d6450", + "shared_secret": "fa4c0c7c5bbb803acd4ae91e49cb8cc659a94490e8b786cabfd9b92e949fbb0b" + }, + { + "key_generation_seed": "dbf1c465fff3d9f783bd9ee61a573715e45691147b8904439b5ffaa64f94ff7bb6d75eac6c76ced1b0a025b40a55440712ad8424672e761e9bc400d63812006f", + "sha3_256_hash_of_public_key": "7537e68ccf14e8b7e57090d8f648529dc461ca3950288879e88116acaf57b4a2", + "sha3_256_hash_of_secret_key": "bd8e44337eef01251217c4702c99232c001b33870953473d83a7486fd25484cf", + "encapsulation_seed": "f72b9080a6c051bbdb9b0abc1949034be0f89a9f73fe277ec4d4740c78d04a83", + "sha3_256_hash_of_ciphertext": "013f4b782480c4647feafa3bbfc91e84fb391e0545168d17a0a7845e5ad3f0bf", + "shared_secret": "b7a8e7b3c6d244b6b0dcc45947dc91f795ed21a5b5ad545205cd5b210df37325" + }, + { + "key_generation_seed": "1f7cfd2b70863154e8a69d1758532e86c20cfc763d67c758bd10a13b24e759b5273b38bddc18488024ec90e62a4110129a42a16d2a93c45439888e76008604c6", + "sha3_256_hash_of_public_key": "82f68b15681cca5c2852c18d6e88bcb102a059c1d21936582adb71790cc0a335", + "sha3_256_hash_of_secret_key": "fd483ddc211c5c27f453bca56158e1f8084f075a7b06f5098cc3204427bf8197", + "encapsulation_seed": "f1e5542190db8ecf4b8d617a04fd3783ad0df78bf8dab749afb57db8321d151b", + "sha3_256_hash_of_ciphertext": "3c150f0cf10ad27bca07c75961d5dee46dc8db458fa6b79ddb3de58e50433017", + "shared_secret": "70cf00481198a97f14e0870c268ca55b6ef787d130a4c32314eb7c0a531cd188" + }, + { + "key_generation_seed": "3a19577908efd37697b8edc7fdaf47d1bd3ad01a1b77faf794bee5b9c3192a6fa3729672816f3eba84c9638a79676eeac0f22c8a48e0c5d50a26ff0844c66b99", + "sha3_256_hash_of_public_key": "104fbf09445794c0ea0654f5caf70ee09d51c8386d4e1f467b10633c710ac2a4", + "sha3_256_hash_of_secret_key": "73fb93953ae666a9df1bf933ba56b8655ea9e319c0110c78d49f8480ae1aa3fd", + "encapsulation_seed": "74efa414ae171bf60b6f884cb7e5ce12028f49365daccfa23e845d551711660b", + "sha3_256_hash_of_ciphertext": "24cbafde848a7049b17fa7b911a925de796344a95eb13e0c4bcbf239c28ca964", + "shared_secret": "2e8ff9c053137ca6b6c31ce8ba7f14135a7e102c211e68eb99de12b94273f9e2" + }, + { + "key_generation_seed": "ae0f65e29f38804a6759f70f4d01e2aaff7fe1c91ebc4f892dd0de3ab2e68ea5e03ff73e02a217659f53d8c47556bf3d8c94040f630d63605e2d0f923579370c", + "sha3_256_hash_of_public_key": "0f353d6a29813d354471eb8b4c38df93939eb3b1db80ddd1cdd6558a9f2687a3", + "sha3_256_hash_of_secret_key": "8a9edd6278707108652f3a5bc244592cb7a82c24634583ed2d3eb6a176b216b8", + "encapsulation_seed": "0b4c3cffb2ba4380ead13dc0d8acad2356b448a810da1df29f264c44aab6d24f", + "sha3_256_hash_of_ciphertext": "5137ec9d55a3187cdcd24ba553853cb6182fbd07d39d288cbde158788c23270c", + "shared_secret": "ffe9448fe824ec92022890969f1fa8e2fa87e5b3e95a9a155839177cd3c8e359" + }, + { + "key_generation_seed": "6084a235f79dd093ef6d185b54e69df33dacee73a9bf2f379004421a10e3a79d9f684fb055ece19459eb464e91e126a7a6e3ed11ccee0046da234d964c985110", + "sha3_256_hash_of_public_key": "12e89c47142418c26396ef0174c02f69dc00022d56494d31af935490edee6385", + "sha3_256_hash_of_secret_key": "bc13b19f01d4cab36dac2154e0fd8fb7d2fa012596363942847f1b0bb3715f90", + "encapsulation_seed": "1c82471dcdfca3a6942061ab4f3d5bf0d197321437c706d9cccccce449447002", + "sha3_256_hash_of_ciphertext": "855b06dfc24eb530c82c7a70f12b04748027d7fa29de97d7d3b73247b16dfccc", + "shared_secret": "e3f110e7d74400cb476b0e34141a107d874986a3732ecc103d9bdfe76bd492f1" + }, + { + "key_generation_seed": "acd1c0217fad5caa4235544dd9de153ab1880ccf4c76f16f236fae4e4bfda04cf03a8abb0a5010f400ae5722a75bdf5a2f6d5b546b34d73857cb1bfc7e587aa7", + "sha3_256_hash_of_public_key": "2fac52ca60594e514333ead02cb1bfa5cd1d9ecda4a0b25ccdfc47ad3f632a85", + "sha3_256_hash_of_secret_key": "2743b7a9dd83a6b9bb5c2685f28b5629b2e31132ac64788a0929557d3449dfc0", + "encapsulation_seed": "46fe60a18124125ab93e0c578f1c02f1bd1301595013001c7f3c2fa56cde294e", + "sha3_256_hash_of_ciphertext": "d9997372e3853eb89c704d0673a526c464b1f46c27d33a445df1f6ae5a90511c", + "shared_secret": "e26737292d1a1fc6772d9c14f9d74f0f4e830c0ba04253aeea21e69830a3a360" + }, + { + "key_generation_seed": "241191401a63afa750f05662e354dddbc683c776ce3222beb83e3cf913d7ed7ca59b3bd23b49a95bc1fad20070fec930b6060bd827d742b077092e422268e15d", + "sha3_256_hash_of_public_key": "3eb856043b822df9d60b55fccb537afa3cacca9ef50433bde1dd9831e534d192", + "sha3_256_hash_of_secret_key": "398ae3423ba5c6bb05920e83e8939a104c3e4ad91647edc7db1667efe438cbfa", + "encapsulation_seed": "52fb7cb6a633fd2e83f2892bd9441b48fe59ecee6d026f5246fa7f2a5e55ee3b", + "sha3_256_hash_of_ciphertext": "dd3e23a09b448da3e15af8cccef9eec6de397b91e34e07b23171a3a93535709c", + "shared_secret": "1d8db19740e2f6ba7c8c04216cf2398fe9221b2404addfef8996a03ec72ead37" + }, + { + "key_generation_seed": "b9a6b0c05677e957d41a34ba03bd06f2a9092e31f63389397d7e70fde6409d18e99c0e7b82be89bc3c1eaee6680aa4efd394e40c2b3f30523c8117f7c26a8969", + "sha3_256_hash_of_public_key": "306aed2a804a1c9bad4ab9e59f6126ad7c8633cdd0c2dd9d4c6f639d312ed47b", + "sha3_256_hash_of_secret_key": "88b28cf6fe19424ff82fc2bb096423b71f0cb8cf985af31bc15ceb4ed18a5e62", + "encapsulation_seed": "0f81a5f97082121244403da3feeb734f6084b314b8d94beb11627aa6ad1914e9", + "sha3_256_hash_of_ciphertext": "2183395e1b660eae184599967416ea85e0ccbbc7e993b384063f1e91086b27cc", + "shared_secret": "cb0026c186440c0744c1c1c708d8fbf2b7aa1126792a7363576bcb2e64384117" + }, + { + "key_generation_seed": "28a96c71577ba00c94f99fe965bc595a26db2b3ca6ab5cf8e443cdd8462b17929c35d165453e5fcdc6f9df64526d9de698f2bd3e6bac6c7fdd86601b9ba5f4a5", + "sha3_256_hash_of_public_key": "9bb3963cc1c5cf2b2d1c6ca76226328ab765a79999ccc71fe98d5bf3b34f51b1", + "sha3_256_hash_of_secret_key": "d8c2492023fb1175a84c19b3ce20f03dd12b1c26b65176d5582c319124bc0e24", + "encapsulation_seed": "31af9345365549ea0360169ed57daf98cc5444799d4c75d9f1f5d615e9df8a91", + "sha3_256_hash_of_ciphertext": "7f8fc45748528ca80816473c46b88d268bd8c31d556cf211ef41e362e63dffd1", + "shared_secret": "f855334cde90e9e858863dbaed7bf4c45bf189861750eaa59355a3648b1ca1cb" + }, + { + "key_generation_seed": "c08ba2ef8c3a0a043afad931652d7a19e6e8cb670f840de5f1fa03309b2ca9ec5fe6141a25f7ab9f875f79e0a82d6ea5cde5a017ab637d5fdb7c42646a1d71df", + "sha3_256_hash_of_public_key": "6d029bb2121c788b5b6ead7226df664490dae362c4befb615717d81c656b3273", + "sha3_256_hash_of_secret_key": "0f2c7bd16d9289c3c27136df0cb6ebc624e80144cb92e6f0c897f58a53617ac3", + "encapsulation_seed": "774ae54093d694ef40b63b62c73e6c98295f606feb8699807eda1d030ffb996d", + "sha3_256_hash_of_ciphertext": "fdfbcedd46fbe70f8892f641c4e84f9b48d1c33ddba29e126d4236df17448ddb", + "shared_secret": "3030433313514ea95b5d6a2fdfb64d4225fc84eb70336323507aed63c5755481" + }, + { + "key_generation_seed": "0e3b30e102d707538c2671060f603bb0b8a014103f132d63b09ece07e4a4c75b11eafeca9e810796c34e8cfce9d59342884456007b01ddd12edce6d10ed87e4c", + "sha3_256_hash_of_public_key": "64c819d9bf66855f6ae70627f04da8378547e5867e2eb9759fe0971efd601c4a", + "sha3_256_hash_of_secret_key": "e85b62236d5c6c691a9076dc58bd5da80999eccc8df973c7d0e7e65d8465ea7d", + "encapsulation_seed": "9f27a47604ab5146caaf0aafe6d149424f8d66e39ba3baf5e6c73b19221b7e21", + "sha3_256_hash_of_ciphertext": "a38d236d52672c9bfb9533ad1e106544b0e52436ff622a633a1439bcf06fcf6c", + "shared_secret": "b8b9f3af55e8c616d07c7042ccc26bb4b83d20fd502ba5cc7b72310990ec50ec" + }, + { + "key_generation_seed": "2478f7d3de6041e7e5cd11c5e2ef483d1aa6218eb126444091535f6ae532fa7311136e2681df2ef881b51a092a9badbe72c9772c169808521c47149578621e28", + "sha3_256_hash_of_public_key": "db315cafbaec2f8a0142f45affff65289e826c9244ab1cb03f9f65df3e3cbcf7", + "sha3_256_hash_of_secret_key": "be98d62e4724c0d960ad4839298d4571f9871033b63bdf10d3b0e589db376ffa", + "encapsulation_seed": "90044031b7597b5e60a4f946b713e8996d0426d2cb013243d9b7d8f8ef159a0f", + "sha3_256_hash_of_ciphertext": "4b32c8d47f6ea3114114f8569dedc246e5b7ce78944273848f24eb8a5e2a3b7c", + "shared_secret": "2e4139c499a24caa334754e10c6bbddc7a0830499ca65e941af8d87ee022d483" + }, + { + "key_generation_seed": "9d405d3ebdaf35fa8722de431b669722acaaea2fd10b814310b17f78b66147d16ceb14f7662be0c42779459f69a145c0e2ce9f0bd9a0cd1bf32ed5694cc9ae32", + "sha3_256_hash_of_public_key": "c8d853e65b5b118e28b7cb6f0d5d6f282e0ea20fd72f3690a6b232b20a8a55ec", + "sha3_256_hash_of_secret_key": "7a5e854bad628be7b99f524f52a97b0959c0ee67a7a10ad24b970e6e3aeeeb80", + "encapsulation_seed": "a7a31e140891ea37d2b6424b59b1f84f89220f32dcb73e037eb912b389d34a48", + "sha3_256_hash_of_ciphertext": "24cf6d09fadeca5a23052d0239f954714bcbc47973086d778a5d2f3c47964e82", + "shared_secret": "e412f3aac1c0284d999d5a7f8344b4053d10965fcbe1638f7ef666ef29c521d2" + }, + { + "key_generation_seed": "9a86490f0615f3edf789cb0654066e9ee339cc59f968281f3b89213f83c692edfaeb2ef44d2f608621e831187ce79b2d2f4a20f1568bbe76b0d3d5af36111714", + "sha3_256_hash_of_public_key": "f69bd52cb1d071f1cc7720f949d44f66f40c917eb30f3a4b0eb519ecad2d03dc", + "sha3_256_hash_of_secret_key": "b6ef04e6acbcd1bb072d1cd28412cdb00ee40d04ce5b39442a2efd6756292167", + "encapsulation_seed": "70eb3f791faa91f1f982fa477dbcddeb2c55691c07f93b04cd31b37544c94b42", + "sha3_256_hash_of_ciphertext": "0044243b64d889050a71bbc15d8d7e619f443d0d6c3b28bf05f7811873434749", + "shared_secret": "4f9de6e4cbd9948d2de9250654d5db97ffe24cf222f68ba51d6261f02f4dc5e7" + }, + { + "key_generation_seed": "6dfd9b575872560c7bdc2732c4a28dac4db04e535eb8e402c3dffd145c09ce47a2985c1c4d203778597947d710dec806e36b0cd949fe460ef141213bfc525e5b", + "sha3_256_hash_of_public_key": "10e01965f9c196d2f5f90ce3ce8f552f8a0d76ba8f5345365392febc50560012", + "sha3_256_hash_of_secret_key": "2b5c6d5fe9b09ab5a027522e699401223ae9d304ac912f1b15f0f647dd9a0a7f", + "encapsulation_seed": "30f4095015ba88b6d969672ca3f438c395dacf7d476ea7a9e805ce932d270a13", + "sha3_256_hash_of_ciphertext": "1464bf8d08a52ae4b5b5ce35eacdbccbc845350d2586d17d1ca3ded460b36e98", + "shared_secret": "da6373247f33971b39d955418425ef1d1a233fae7fb1985c0126f541ab8d58d7" + }, + { + "key_generation_seed": "6fca9f4e384d8418075cc064c70730801bdb8249899d456a77130d5beeb3662cce7683f8a03d3cf04e46970ff7d6a12494ae12558346dfc8fd9370bf944a0102", + "sha3_256_hash_of_public_key": "7c3991fa7983d0dd6e7157cfb152538466e9d5c3998a2b8ed862162b91ca851c", + "sha3_256_hash_of_secret_key": "72e786018ae9ab8293fa51cb7ca3ff0435e7cccbd5ae02b4680b92c148590265", + "encapsulation_seed": "cf31220f44de862e1719570e1b26e897790159366a385452334fe24cdcae28ba", + "sha3_256_hash_of_ciphertext": "feb0875261b62b026e02265b31a433c75a4330a8af26d3e5f4a8fc2e6bd3a482", + "shared_secret": "037452d74a46b60f415dad3498adbac608dcabe4edc7070a358e7325c72ce76f" + }, + { + "key_generation_seed": "e58f71bf175c0550a67e00e0f7b3b7fc36bc2707bf0c93044a492626de36301a7f7054814869cf7625e45647bc1547aff288dbb90699b2ad84893f3b755d9722", + "sha3_256_hash_of_public_key": "8aacd8940ff6fc27f175342be74d48075f8ae9320cae20a41c879c27c1bf815d", + "sha3_256_hash_of_secret_key": "f7399dbf35fcc57a9bff87b0087755faa75267788cd0921b9ebc5cde8b656271", + "encapsulation_seed": "bb5e65669a44e5d5c709bafa98c16ccba6ac2c4ae923334f69a11543eda64f5d", + "sha3_256_hash_of_ciphertext": "8009fb9c48aef553011af0576568351db3776b01def04198874e1155059c3006", + "shared_secret": "2cfcf5fa2b4c0aaa85c6069616e19e6715fec913592d6b8f57eba9cb4e3b162a" + }, + { + "key_generation_seed": "e3fc575ed51513e62aba655d24cd9c8f1c6c848aaffa946c49a53ac3ea59e474d82c2f1bf2e6aebde5660fa73356982e12999d8fdafbb3cb186341d0386dead0", + "sha3_256_hash_of_public_key": "149e0b6b49fe8adba1217c2c57c83f2b8c5f1d92f319e502b184a65869214f75", + "sha3_256_hash_of_secret_key": "6dfa4d29af6a0e8413d5591339c15d2e2cfac3f502f49acca3efb53b53624666", + "encapsulation_seed": "9ddb3aa9c7905d1a438c93bcf78e3e321813580371ab4e1289e2dbf3701972c2", + "sha3_256_hash_of_ciphertext": "0d379514e14f3cc9d1ce5804db6f58868654a604177058d3f6431ff1f2be431c", + "shared_secret": "d3551ed0fd716e4887c82a6f24c5008ba80a9b5c3fc9e50f188eb224be8102c8" + }, + { + "key_generation_seed": "470b4943f0fe7fd0d8ec5185aba0d1db09d112934e4fb4787e2bbc6b88466e7b8b2809fd40008be70a6b184981101724bc3d5ec5e1956b510b82fd5ad0668a5a", + "sha3_256_hash_of_public_key": "29b1bff7f12eda28dfedfbf0ac16e27008c9fdc62c35e53b28a312bdc91c40bf", + "sha3_256_hash_of_secret_key": "762a61eb847c017ece920f51d5da7a9036ed8b835bfd7793527321ec635e2fd0", + "encapsulation_seed": "26d90b190a6c3d0d9a86cf66005154e7086749e966e7187c249ccb9329fd3b8b", + "sha3_256_hash_of_ciphertext": "a9d77d81f4a1db5985bcd6fde4b68c8f65470f2a48ecf99d6e11b6a31ae8d26d", + "shared_secret": "03139cf9f20fb6bdaa4ee906aeee834815fa924e05ed7e7e3bfb432aad944d6f" + }, + { + "key_generation_seed": "6df4385db978d27b27d2aa5e452e4152b36f097503d9581ac3390105c5727e7dc95fa08ed106ce84660e8a4c90bd2b22634e40769aa0090a101c5dddad45edc5", + "sha3_256_hash_of_public_key": "b990059e901097d00e0ebaf40c5d5dab009c66798489d357e760478ce884cce5", + "sha3_256_hash_of_secret_key": "37a044795bd330e4dc60a6d84bc6e99664d1be418b0239661d2ff16d1501573f", + "encapsulation_seed": "7db6d1a129d6123f1f805b79ad3b413012ea86aed42a05e98e7b1f32f9fbbdec", + "sha3_256_hash_of_ciphertext": "20f09e737440c30b8119448c19c43127a52070265752f2f859f110d136daf470", + "shared_secret": "f87cffe1a96bcded4fe027dc8006065d67d0190b87d805135bdafcb5edb9803c" + }, + { + "key_generation_seed": "dbacba825728444921b227cdba54446b3f6881b47be9cd02832f78b023b1bee0e15274a8e2bc08fe818b117ba28c5dfae74d54fcdf6f20052f79be333edc8dde", + "sha3_256_hash_of_public_key": "175eb63c3144108548720ce7ee0f43a9ff3f52a9924efe9f2f59318bb93c86b5", + "sha3_256_hash_of_secret_key": "1993d7639b79f5e4871a7c58a69fec50f96c1424c2c0ee030ac054ae1b88a56f", + "encapsulation_seed": "1d129b27be7384c359d04311fe5c44917d1fde4bfb57314f483ac617edd5ac49", + "sha3_256_hash_of_ciphertext": "1288de12d00d76095c0072f3f0a0058227e99e9909fba65b58b361f85a76c98a", + "shared_secret": "d2d4a23dec18fd2c413d0c64d58c1d14e19d2a18aef1cb038d14c3c2e79f6a69" + }, + { + "key_generation_seed": "690eb71fd7052b906eaec09937a8ed374e0b02afa27c2f14399932be5839fad281c38c2cb5cfafac81b96a810ab749b61806b6d54c9f8cf4bf1be0192423288f", + "sha3_256_hash_of_public_key": "9bc32a138a2fb5b6072464172abe0fd97e9eabf357c3fa5391d94a415b53abd3", + "sha3_256_hash_of_secret_key": "3db4ab1393cfc8b1c708cf8efdb1c443c975878898b60182c22af66375cba13a", + "encapsulation_seed": "bbc773ebd2df42c36ae05952d6a64c63a5dfb82ceb3ef4f8d4df3a30ec8c0467", + "sha3_256_hash_of_ciphertext": "6f991f90c37724ccf1ea02f0c90b618cd97c1ede4221d4bc369f78d03da4c560", + "shared_secret": "52e36f81dd9a23fb9bb2363c31b715106d38520a31a3304cf754a9432e757224" + }, + { + "key_generation_seed": "32e0ea9089fa928482c0770da545af1bb871a03ce38604138b0d08ea2a10ca2bc06c5bef7b6508409daf847a64c8d30d0974fd3ba7476dc76c46b458a036d884", + "sha3_256_hash_of_public_key": "7ef43a72ef04766f1e899d25c9a005009c788b5faf985123cfb3fb97975de26d", + "sha3_256_hash_of_secret_key": "77431cb18010a604d56fe5a623bed2ffd028a741f176fa09546e9a45a48caa5e", + "encapsulation_seed": "5b17a6adad541efcbf5ae4b0c0452cd2ce32e4f0f8701801c5b63e197c1fcbf4", + "sha3_256_hash_of_ciphertext": "11fd09e815bbe163a61c9d215fc7123799b7e774c8945239cac775057b8606d2", + "shared_secret": "d072cb81aff4aa5712e56f0e9567dd89f2b03488735ba4751a7f0df1c786402a" + }, + { + "key_generation_seed": "6fb2ec719f2a0dea152bf3f64b9d148f8ab8ba88f64e61f5db53e12d59f525574f797c007e4061f95c7d56cfc7ee5c49e849dde3fea8f25e7876df2a18515c34", + "sha3_256_hash_of_public_key": "2c0db43f39b672b2cd912f907cf76a0f6fda925eb2d205546431be0b37b20411", + "sha3_256_hash_of_secret_key": "09844e203f4d8fa30728ab388b9d654847febbf5c9cd939cdc11c9c9be24ce9c", + "encapsulation_seed": "61ab87659525de9656af41246f20e1dbe85c24e335e7ecf9493f46168bc14e94", + "sha3_256_hash_of_ciphertext": "19d527602842910160a13f92dbf9c610a32a5163c3f063271a759487c344cf93", + "shared_secret": "da1085cbc7452cf2ac98ca36631c6ebcfff02e60485f9e807cdb3db77bc92243" + }, + { + "key_generation_seed": "527fb88c8bd9a4d6031dad15e63878abd2b559e7e08d61f69e8e78fca964ee6ae32d432b4f9f751bde0496c580a181ffed762aa35454a02d3f1f47ee0394c89c", + "sha3_256_hash_of_public_key": "aae8e61b905723fa092fb95b839f6de3670c39ce0498c27b87d20c24e7f64e22", + "sha3_256_hash_of_secret_key": "3880f7ca8fc33575a7a6d8bb46fec86a3f12e0068630507ed245d8bc278fbe5d", + "encapsulation_seed": "eca2adc3da1fb15f34033405ec08ef2f46163df4bfcccf8842c600ce0bc2026c", + "sha3_256_hash_of_ciphertext": "9faa095c14ed0b2e38ac99ef1f7c896c8dacb9065dbe677add2960053c1a0421", + "shared_secret": "aca83f1dc628fa87b20133bed4c2eee34b98021f295ab585dfdcefc9e3c032f5" + }, + { + "key_generation_seed": "ac6fcfaeeef795b6ef9e062f02bf42975fa01e7d91ba832f74e05269a72684d05aeda108ea4d6c6bc0fb958286850422bc357ca67b83c986048e0d0087fa11ec", + "sha3_256_hash_of_public_key": "64e085f67e48f00a7a7f82963e8c67176bff839a54fa1008328c0612f98d83d3", + "sha3_256_hash_of_secret_key": "0bfbc25d9df751f4c30907095eb6d9a75ed07fa23218ad0fffc469f0e55553c2", + "encapsulation_seed": "c4f15bec2d7701339d0ade4835193bea3632edcf89e74992620d9eb623a0d0d4", + "sha3_256_hash_of_ciphertext": "bc1227424d0f6e0b6974a798f281b3f2ae089216cacf15a7c87c10aa67040720", + "shared_secret": "3cc0ef85a74184338a10ffbfad5f6d04860d51e7dacf3ee73033b70969785af8" + }, + { + "key_generation_seed": "ba2fb9318d4dbe7488057c33e95e6f054583a2800c41bb83083c330a914a12cfe63f8ffda3565c2424c89b20974b748a65a5aba75133fcb3156dfb6626a83bab", + "sha3_256_hash_of_public_key": "8dab879de09b58d0fc7ade140393ffb5343abbddabdc118fad519b14436a964c", + "sha3_256_hash_of_secret_key": "7c53072fd98ea7bd8c5e873688b1a5650fe7e11c791407ac8c118b7958cf414b", + "encapsulation_seed": "28878249e2ac2b6263422993923a0c8bd05ce56e385ed13c943b03d226856947", + "sha3_256_hash_of_ciphertext": "9013959fd6d233a5baebd70cb33e1eb99ff6b3054af1a7d863dd1203ece5f869", + "shared_secret": "1db6e99f80628e170260354ee6f3854f905d198e9669b4faab478f4b39cc2f0e" + }, + { + "key_generation_seed": "aa6dd1e5799cdf7af9c4fc632b3eb9d51d66e85c8e0a21ec98664fc51ab63c7dfda268813efab5204efa60f78bf81d320d01ac09ac06244f7afbd2d80fd356d9", + "sha3_256_hash_of_public_key": "919a696301240cd6129f66be58e19d99b0d827d9932785cd9ea3d92f7ba54463", + "sha3_256_hash_of_secret_key": "cb1d7301f15951883cc3f287d4dd8fdf5c9b7022f558dff551c2ade5f5065755", + "encapsulation_seed": "17fc65f7fbd7c75ceec421dee84dff5a8cb22764a182db17e0ebe857f54d60eb", + "sha3_256_hash_of_ciphertext": "2a0c4b9f6c8818d628045333456751d87f87821eb4496ad022d23e0d4fa3872c", + "shared_secret": "ef8de288a7ce14ccd5172a4a2f91588559e3780a75b1df329a53b1e400c4c7f5" + }, + { + "key_generation_seed": "195d6c86a3df4c21e3007d7f2768b43c74cb3060e0eca77f0a5d3271542b9a84ae77e0f9f21eabd8c0c6eea7767f4e10fde5c2d79b8400bf96b19014b457ec21", + "sha3_256_hash_of_public_key": "cb6d7232426bdbdfdacd373c9190722e7bf342825f7d829185dcc9120588fc76", + "sha3_256_hash_of_secret_key": "a85e24cc2eafdfe40d82f46471112e1359628b9955f3feae9955b48d563ac952", + "encapsulation_seed": "fa0489f3730100609488e951e6aaa15c0f193bc1dbcfcd013bc418d6c507b176", + "sha3_256_hash_of_ciphertext": "9496733c6b4cfc954325101068c40a02c4e3234cf60f1bad187ac479416f9415", + "shared_secret": "4793f705aed572ace61db13bede3900f2538eaddb904988c1f015bac605a1093" + } +] \ No newline at end of file diff --git a/libcrux-ml-kem/tests/nistkats.rs b/libcrux-ml-kem/tests/nistkats.rs index 1e3a3360..a760b909 100644 --- a/libcrux-ml-kem/tests/nistkats.rs +++ b/libcrux-ml-kem/tests/nistkats.rs @@ -1,4 +1,6 @@ use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768}; +#[cfg(feature = "kyber")] +use libcrux_ml_kem::{kyber1024, kyber512, kyber768}; use serde::Deserialize; use serde_json; use std::{fs::File, io::BufReader, path::Path}; @@ -27,12 +29,12 @@ struct MlKemNISTKAT { } macro_rules! impl_nist_known_answer_tests { - ($name:ident, $parameter_set: literal, $key_gen_derand:expr, $encapsulate_derand:expr, $decapsulate_derand: expr) => { + ($name:ident, $variant:literal, $parameter_set: literal, $key_gen_derand:expr, $encapsulate_derand:expr, $decapsulate_derand: expr) => { #[test] fn $name() { let katfile_path = Path::new("tests") .join("kats") - .join(format!("nistkats_mlkem_{}.json", $parameter_set)); + .join(format!("nistkats_{}_{}.json", $variant, $parameter_set)); let katfile = File::open(katfile_path).expect("Could not open KAT file."); let reader = BufReader::new(katfile); @@ -65,6 +67,7 @@ macro_rules! impl_nist_known_answer_tests { impl_nist_known_answer_tests!( mlkem512_nist_known_answer_tests, + "mlkem", 512, mlkem512::generate_key_pair, mlkem512::encapsulate, @@ -72,6 +75,7 @@ impl_nist_known_answer_tests!( ); impl_nist_known_answer_tests!( mlkem768_nist_known_answer_tests, + "mlkem", 768, mlkem768::generate_key_pair, mlkem768::encapsulate, @@ -79,6 +83,7 @@ impl_nist_known_answer_tests!( ); impl_nist_known_answer_tests!( mlkem1024_nist_known_answer_tests, + "mlkem", 1024, mlkem1024::generate_key_pair, mlkem1024::encapsulate, @@ -87,8 +92,37 @@ impl_nist_known_answer_tests!( impl_nist_known_answer_tests!( mlkem768_nist_kats_portable, + "mlkem", 768, mlkem768::portable::generate_key_pair, mlkem768::portable::encapsulate, mlkem768::portable::decapsulate ); + +#[cfg(feature = "kyber")] +impl_nist_known_answer_tests!( + kyber512_nist_known_answer_tests, + "kyber", + 512, + kyber512::generate_key_pair, + kyber512::encapsulate, + kyber512::decapsulate +); +#[cfg(feature = "kyber")] +impl_nist_known_answer_tests!( + kyber768_nist_known_answer_tests, + "kyber", + 768, + kyber768::generate_key_pair, + kyber768::encapsulate, + kyber768::decapsulate +); +#[cfg(feature = "kyber")] +impl_nist_known_answer_tests!( + kyber1024_nist_known_answer_tests, + "kyber", + 1024, + kyber1024::generate_key_pair, + kyber1024::encapsulate, + kyber1024::decapsulate +); From e5b264cd1c729f5b883139502de0673add345dee Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 11:55:00 +0200 Subject: [PATCH 25/53] Document single Kyber 768 KAT from boringssl --- libcrux-ml-kem/tests/kyber.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libcrux-ml-kem/tests/kyber.rs b/libcrux-ml-kem/tests/kyber.rs index da3c1b09..ca5ec4fa 100644 --- a/libcrux-ml-kem/tests/kyber.rs +++ b/libcrux-ml-kem/tests/kyber.rs @@ -1,6 +1,8 @@ +/// This tests a single one of the Kyber 768 KATs that are also tested in BoringSSL. +/// The values are taken from https://github.com/google/boringssl/blob/master/crypto/kyber/kyber_tests.txt. #[test] #[cfg(feature = "kyber")] -fn kyber768() { +fn kyber768_single_kat() { use libcrux_ml_kem::kyber768; let key_pair = kyber768::generate_key_pair(hex::decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2d8626ed79d451140800e03b59b956f8210e556067407d13dc90fa9e8b872bfb8f").unwrap().try_into().unwrap()); From 608fe19a6f194a6e56a904cd854675dfacfc18d5 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 11:56:49 +0200 Subject: [PATCH 26/53] Format --- libcrux-ml-kem/tests/nistkats.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrux-ml-kem/tests/nistkats.rs b/libcrux-ml-kem/tests/nistkats.rs index a760b909..0c779a3b 100644 --- a/libcrux-ml-kem/tests/nistkats.rs +++ b/libcrux-ml-kem/tests/nistkats.rs @@ -1,6 +1,6 @@ -use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768}; #[cfg(feature = "kyber")] use libcrux_ml_kem::{kyber1024, kyber512, kyber768}; +use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768}; use serde::Deserialize; use serde_json; use std::{fs::File, io::BufReader, path::Path}; From 1233e959acaacb96723e35c6dd410cf99baa74c7 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 13:05:59 +0200 Subject: [PATCH 27/53] Test Kyber on CI --- .github/workflows/mlkem.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/mlkem.yml b/.github/workflows/mlkem.yml index 4f3ed710..1b0c6bd1 100644 --- a/.github/workflows/mlkem.yml +++ b/.github/workflows/mlkem.yml @@ -145,6 +145,12 @@ jobs: cargo clean LIBCRUX_DISABLE_SIMD128=1 LIBCRUX_DISABLE_SIMD256=1 cargo test --verbose --release $RUST_TARGET_FLAG + - name: 🏃🏻‍♀️ Test Kyber + run: | + cargo clean + cargo test --features kyber --verbose $RUST_TARGET_FLAG + + benchmarks: strategy: fail-fast: true From f2f27e53a8e664c119290b822f2401acdba9325d Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 15:07:33 +0200 Subject: [PATCH 28/53] Fix insufficient feature gating --- libcrux-ml-kem/src/lib.rs | 2 +- libcrux-ml-kem/tests/self.rs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 2246137a..cf3bcaf9 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -118,7 +118,6 @@ pub mod mlkem768 { pub use crate::kem::kyber::kyber768::MlKem768PublicKey; } - #[cfg(feature = "pre-verification")] pub mod mlkem1024; #[cfg(not(feature = "pre-verification"))] @@ -159,6 +158,7 @@ pub mod kyber1024 { pub use crate::mlkem1024::validate_public_key; } +#[cfg(feature = "pre-verification")] pub use constants::SHARED_SECRET_SIZE; #[cfg(not(feature = "pre-verification"))] pub const SHARED_SECRET_SIZE: usize = kem::kyber::constants::SHARED_SECRET_SIZE; diff --git a/libcrux-ml-kem/tests/self.rs b/libcrux-ml-kem/tests/self.rs index d25a7e55..14c14ad9 100644 --- a/libcrux-ml-kem/tests/self.rs +++ b/libcrux-ml-kem/tests/self.rs @@ -1,9 +1,6 @@ #[cfg(not(feature = "pre-verification"))] pub mod default { - use libcrux_ml_kem::{ - mlkem1024::{self, MlKem1024Ciphertext}, - mlkem512, mlkem768, MlKemCiphertext, MlKemPrivateKey, - }; + use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768, MlKemCiphertext, MlKemPrivateKey}; use libcrux_sha3::shake256; use rand::{rngs::OsRng, thread_rng, RngCore}; From a9e648973a3938f174e211d59a98794843677826 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 16:46:20 +0200 Subject: [PATCH 29/53] Get rid of various warnings --- libcrux-ml-kem/src/kem.rs | 16 +++---- libcrux-ml-kem/src/kem/kyber.rs | 4 +- .../src/kem/kyber/hash_functions.rs | 2 +- libcrux-ml-kem/src/kem/kyber/kyber1024.rs | 2 +- libcrux-ml-kem/src/kem/kyber/ntt.rs | 2 +- libcrux-ml-kem/src/kem/kyber/serialize.rs | 3 -- libcrux-ml-kem/src/lib.rs | 45 ++++++++++--------- 7 files changed, 37 insertions(+), 37 deletions(-) diff --git a/libcrux-ml-kem/src/kem.rs b/libcrux-ml-kem/src/kem.rs index 247eaed9..5ca3dd67 100644 --- a/libcrux-ml-kem/src/kem.rs +++ b/libcrux-ml-kem/src/kem.rs @@ -20,14 +20,14 @@ pub mod deterministic { pub use super::kyber::kyber768::generate_key_pair as kyber768_generate_keypair_derand; } -use self::kyber::MlKemSharedSecret; -use self::kyber::{kyber1024, kyber512, kyber768}; -pub use kyber::{ - kyber1024::{MlKem1024Ciphertext, MlKem1024PrivateKey, MlKem1024PublicKey}, - kyber512::{MlKem512Ciphertext, MlKem512PrivateKey, MlKem512PublicKey}, - kyber768::{MlKem768Ciphertext, MlKem768PrivateKey, MlKem768PublicKey}, - MlKemCiphertext, MlKemKeyPair, -}; +// use self::kyber::MlKemSharedSecret; +// use self::kyber::{kyber1024, kyber512, kyber768}; +// pub use kyber::{ +// kyber1024::{MlKem1024Ciphertext, MlKem1024PrivateKey, MlKem1024PublicKey}, +// kyber512::{MlKem512Ciphertext, MlKem512PrivateKey, MlKem512PublicKey}, +// kyber768::{MlKem768Ciphertext, MlKem768PrivateKey, MlKem768PublicKey}, +// MlKemCiphertext, MlKemKeyPair, +// }; #[cfg(feature = "tests")] pub use kyber::{ diff --git a/libcrux-ml-kem/src/kem/kyber.rs b/libcrux-ml-kem/src/kem/kyber.rs index 5191be4d..9b6457f2 100644 --- a/libcrux-ml-kem/src/kem/kyber.rs +++ b/libcrux-ml-kem/src/kem/kyber.rs @@ -31,7 +31,7 @@ pub use types::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; // TODO: We should make this an actual type as opposed to alias so we can enforce // some checks at the type level. This is being tracked in: // https://github.com/cryspen/libcrux/issues/123 -pub type MlKemSharedSecret = [u8; constants::SHARED_SECRET_SIZE]; +pub type MlKemSharedSecret = [u8; SHARED_SECRET_SIZE]; use self::{ arithmetic::PolynomialRingElement, @@ -205,7 +205,7 @@ pub(super) fn encapsulate< ETA2_RANDOMNESS_SIZE, >(public_key.as_slice(), randomness, pseudorandomness); - let mut shared_secret_array = [0u8; constants::SHARED_SECRET_SIZE]; + let mut shared_secret_array = [0u8; SHARED_SECRET_SIZE]; shared_secret_array.copy_from_slice(shared_secret); (ciphertext.into(), shared_secret_array) } diff --git a/libcrux-ml-kem/src/kem/kyber/hash_functions.rs b/libcrux-ml-kem/src/kem/kyber/hash_functions.rs index f4b4d78c..309d2364 100644 --- a/libcrux-ml-kem/src/kem/kyber/hash_functions.rs +++ b/libcrux-ml-kem/src/kem/kyber/hash_functions.rs @@ -111,6 +111,6 @@ pub(crate) fn squeeze_block( /// /// **NOTE:** That this needs to be done manually for now. #[inline(always)] -pub(crate) fn free_state(xof_state: [KeccakState1; K]) { +pub(crate) fn free_state(_xof_state: [KeccakState1; K]) { // xof_state.free_memory(); } diff --git a/libcrux-ml-kem/src/kem/kyber/kyber1024.rs b/libcrux-ml-kem/src/kem/kyber/kyber1024.rs index b15c6ec1..f67682fe 100644 --- a/libcrux-ml-kem/src/kem/kyber/kyber1024.rs +++ b/libcrux-ml-kem/src/kem/kyber/kyber1024.rs @@ -58,7 +58,7 @@ pub fn validate_public_key(public_key: MlKem1024PublicKey) -> Option MlKemKeyPair { - super::generate_keypair::< + generate_keypair::< RANK_1024, CPA_PKE_SECRET_KEY_SIZE_1024, SECRET_KEY_SIZE_1024, diff --git a/libcrux-ml-kem/src/kem/kyber/ntt.rs b/libcrux-ml-kem/src/kem/kyber/ntt.rs index 85d819e4..6e933b02 100644 --- a/libcrux-ml-kem/src/kem/kyber/ntt.rs +++ b/libcrux-ml-kem/src/kem/kyber/ntt.rs @@ -5,7 +5,7 @@ use super::{ barrett_reduce, montgomery_multiply_fe_by_fer, montgomery_reduce, FieldElement, FieldElementTimesMontgomeryR, MontgomeryFieldElement, PolynomialRingElement, }, - constants::{COEFFICIENTS_IN_RING_ELEMENT, FIELD_MODULUS}, + constants::COEFFICIENTS_IN_RING_ELEMENT, }; const ZETAS_TIMES_MONTGOMERY_R: [FieldElementTimesMontgomeryR; 128] = [ diff --git a/libcrux-ml-kem/src/kem/kyber/serialize.rs b/libcrux-ml-kem/src/kem/kyber/serialize.rs index c31d893d..2197a860 100644 --- a/libcrux-ml-kem/src/kem/kyber/serialize.rs +++ b/libcrux-ml-kem/src/kem/kyber/serialize.rs @@ -9,9 +9,6 @@ use super::{ use crate::cloop; use crate::hax_utils::hax_debug_assert; -#[cfg(not(hax))] -use super::constants::COEFFICIENTS_IN_RING_ELEMENT; - #[inline(always)] pub(super) fn compress_then_serialize_message( re: PolynomialRingElement, diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 9dba3db9..ac0be298 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -96,39 +96,42 @@ mod kem; pub mod mlkem512; #[cfg(not(feature = "pre-verification"))] pub mod mlkem512 { - pub use crate::kem::kyber::kyber512::decapsulate; - pub use crate::kem::kyber::kyber512::encapsulate; - pub use crate::kem::kyber::kyber512::generate_key_pair; - pub use crate::kem::kyber::kyber512::validate_public_key; - pub use crate::kem::kyber::kyber512::MlKem512Ciphertext; - pub use crate::kem::kyber::kyber512::MlKem512PrivateKey; - pub use crate::kem::kyber::kyber512::MlKem512PublicKey; + pub use crate::kem::kyber::kyber512::*; + // pub use crate::kem::kyber::kyber512::decapsulate; + // pub use crate::kem::kyber::kyber512::encapsulate; + // pub use crate::kem::kyber::kyber512::generate_key_pair; + // pub use crate::kem::kyber::kyber512::validate_public_key; + // pub use crate::kem::kyber::kyber512::MlKem512Ciphertext; + // pub use crate::kem::kyber::kyber512::MlKem512PrivateKey; + // pub use crate::kem::kyber::kyber512::MlKem512PublicKey; } #[cfg(feature = "pre-verification")] pub mod mlkem768; #[cfg(not(feature = "pre-verification"))] pub mod mlkem768 { - pub use crate::kem::kyber::kyber768::decapsulate; - pub use crate::kem::kyber::kyber768::encapsulate; - pub use crate::kem::kyber::kyber768::generate_key_pair; - pub use crate::kem::kyber::kyber768::validate_public_key; - pub use crate::kem::kyber::kyber768::MlKem768Ciphertext; - pub use crate::kem::kyber::kyber768::MlKem768PrivateKey; - pub use crate::kem::kyber::kyber768::MlKem768PublicKey; + pub use crate::kem::kyber::kyber768::*; + // pub use crate::kem::kyber::kyber768::decapsulate; + // pub use crate::kem::kyber::kyber768::encapsulate; + // pub use crate::kem::kyber::kyber768::generate_key_pair; + // pub use crate::kem::kyber::kyber768::validate_public_key; + // pub use crate::kem::kyber::kyber768::MlKem768Ciphertext; + // pub use crate::kem::kyber::kyber768::MlKem768PrivateKey; + // pub use crate::kem::kyber::kyber768::MlKem768PublicKey; } #[cfg(feature = "pre-verification")] pub mod mlkem1024; #[cfg(not(feature = "pre-verification"))] pub mod mlkem1024 { - pub use crate::kem::kyber::kyber1024::decapsulate; - pub use crate::kem::kyber::kyber1024::encapsulate; - pub use crate::kem::kyber::kyber1024::generate_key_pair; - pub use crate::kem::kyber::kyber1024::validate_public_key; - pub use crate::kem::kyber::kyber1024::MlKem1024Ciphertext; - pub use crate::kem::kyber::kyber1024::MlKem1024PrivateKey; - pub use crate::kem::kyber::kyber1024::MlKem1024PublicKey; + pub use crate::kem::kyber::kyber1024::*; + // pub use crate::kem::kyber::kyber1024::decapsulate; + // pub use crate::kem::kyber::kyber1024::encapsulate; + // pub use crate::kem::kyber::kyber1024::generate_key_pair; + // pub use crate::kem::kyber::kyber1024::validate_public_key; + // pub use crate::kem::kyber::kyber1024::MlKem1024Ciphertext; + // pub use crate::kem::kyber::kyber1024::MlKem1024PrivateKey; + // pub use crate::kem::kyber::kyber1024::MlKem1024PublicKey; } #[cfg(all(feature = "kyber", feature = "pre-verification"))] From 956382de52939c387880fea7c592ee00692fc7b2 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 16:46:57 +0200 Subject: [PATCH 30/53] Format --- libcrux-ml-kem/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index ac0be298..13446606 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -96,7 +96,7 @@ mod kem; pub mod mlkem512; #[cfg(not(feature = "pre-verification"))] pub mod mlkem512 { - pub use crate::kem::kyber::kyber512::*; + pub use crate::kem::kyber::kyber512::*; // pub use crate::kem::kyber::kyber512::decapsulate; // pub use crate::kem::kyber::kyber512::encapsulate; // pub use crate::kem::kyber::kyber512::generate_key_pair; @@ -124,7 +124,7 @@ pub mod mlkem768 { pub mod mlkem1024; #[cfg(not(feature = "pre-verification"))] pub mod mlkem1024 { - pub use crate::kem::kyber::kyber1024::*; + pub use crate::kem::kyber::kyber1024::*; // pub use crate::kem::kyber::kyber1024::decapsulate; // pub use crate::kem::kyber::kyber1024::encapsulate; // pub use crate::kem::kyber::kyber1024::generate_key_pair; @@ -143,7 +143,6 @@ pub mod kyber512 { pub use crate::mlkem512::validate_public_key; } - #[cfg(all(feature = "kyber", feature = "pre-verification"))] pub mod kyber768 { //! Kyber 768 (NIST PQC Round 3) From 6d2fda335754e0b23fa7a4e9a525055377fba863 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Wed, 26 Jun 2024 17:00:31 +0200 Subject: [PATCH 31/53] Remove commented `use` declarations --- libcrux-ml-kem/src/lib.rs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 13446606..aadd6c07 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -97,13 +97,6 @@ pub mod mlkem512; #[cfg(not(feature = "pre-verification"))] pub mod mlkem512 { pub use crate::kem::kyber::kyber512::*; - // pub use crate::kem::kyber::kyber512::decapsulate; - // pub use crate::kem::kyber::kyber512::encapsulate; - // pub use crate::kem::kyber::kyber512::generate_key_pair; - // pub use crate::kem::kyber::kyber512::validate_public_key; - // pub use crate::kem::kyber::kyber512::MlKem512Ciphertext; - // pub use crate::kem::kyber::kyber512::MlKem512PrivateKey; - // pub use crate::kem::kyber::kyber512::MlKem512PublicKey; } #[cfg(feature = "pre-verification")] @@ -111,13 +104,6 @@ pub mod mlkem768; #[cfg(not(feature = "pre-verification"))] pub mod mlkem768 { pub use crate::kem::kyber::kyber768::*; - // pub use crate::kem::kyber::kyber768::decapsulate; - // pub use crate::kem::kyber::kyber768::encapsulate; - // pub use crate::kem::kyber::kyber768::generate_key_pair; - // pub use crate::kem::kyber::kyber768::validate_public_key; - // pub use crate::kem::kyber::kyber768::MlKem768Ciphertext; - // pub use crate::kem::kyber::kyber768::MlKem768PrivateKey; - // pub use crate::kem::kyber::kyber768::MlKem768PublicKey; } #[cfg(feature = "pre-verification")] @@ -125,13 +111,6 @@ pub mod mlkem1024; #[cfg(not(feature = "pre-verification"))] pub mod mlkem1024 { pub use crate::kem::kyber::kyber1024::*; - // pub use crate::kem::kyber::kyber1024::decapsulate; - // pub use crate::kem::kyber::kyber1024::encapsulate; - // pub use crate::kem::kyber::kyber1024::generate_key_pair; - // pub use crate::kem::kyber::kyber1024::validate_public_key; - // pub use crate::kem::kyber::kyber1024::MlKem1024Ciphertext; - // pub use crate::kem::kyber::kyber1024::MlKem1024PrivateKey; - // pub use crate::kem::kyber::kyber1024::MlKem1024PublicKey; } #[cfg(all(feature = "kyber", feature = "pre-verification"))] From 906a298960ca9a0597492568c862e9a2edcb1987 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 10:18:20 +0200 Subject: [PATCH 32/53] Fix `unused_mut` warning --- libcrux-ml-kem/src/lib.rs | 2 -- libcrux-ml-kem/tests/self.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 221495a0..0b3e2aa4 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -88,7 +88,6 @@ mod types; #[cfg(feature = "pre-verification")] mod vector; - #[cfg(not(feature = "pre-verification"))] mod kem; // Variants @@ -99,7 +98,6 @@ pub mod mlkem512; #[cfg(all(feature = "mlkem768", feature = "pre-verification"))] pub mod mlkem768; - // Variants #[cfg(all(feature = "mlkem512", not(feature = "pre-verification")))] pub mod mlkem512 { diff --git a/libcrux-ml-kem/tests/self.rs b/libcrux-ml-kem/tests/self.rs index 14c14ad9..1667de5c 100644 --- a/libcrux-ml-kem/tests/self.rs +++ b/libcrux-ml-kem/tests/self.rs @@ -36,7 +36,7 @@ pub mod default { } fn modify_ciphertext( - mut ciphertext: MlKemCiphertext, + ciphertext: MlKemCiphertext, ) -> MlKemCiphertext { let mut raw_ciphertext = [0u8; LEN]; raw_ciphertext.copy_from_slice(ciphertext.as_ref()); From 7f349f114315672933130af302c81f910529cf41 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 10:47:10 +0200 Subject: [PATCH 33/53] Feature gating helper macros --- libcrux-ml-kem/src/cfg.rs | 30 ++++++ libcrux-ml-kem/src/lib.rs | 196 ++++++++++++++++++-------------------- 2 files changed, 123 insertions(+), 103 deletions(-) create mode 100644 libcrux-ml-kem/src/cfg.rs diff --git a/libcrux-ml-kem/src/cfg.rs b/libcrux-ml-kem/src/cfg.rs new file mode 100644 index 00000000..2c8b5367 --- /dev/null +++ b/libcrux-ml-kem/src/cfg.rs @@ -0,0 +1,30 @@ +/// Macro to simplify feature gating of verified code +macro_rules! cfg_verified { + ($($item:item)*) => { + $( + #[cfg(not(feature = "pre-verification"))] + $item + )* + } +} + +/// Macro to simplify `pre-verification` feature gating +macro_rules! cfg_pre_verification { + ($($item:item)*) => { + $( + #[cfg(feature = "pre-verification")] + $item + )* + } +} + +/// Macro to simplify `kyber` feature gating +#[cfg(feature = "pre-verification")] +macro_rules! cfg_kyber { + ($($item:item)*) => { + $( + #[cfg(feature = "kyber")] + $item + )* + } +} diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 0b3e2aa4..66ce6794 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -41,122 +41,112 @@ #![warn(rust_2018_idioms, unused_lifetimes, unused_qualifications)] #![allow(clippy::needless_range_loop)] +/// Feature gating helper macros +#[macro_use] +mod cfg; + #[cfg(feature = "std")] extern crate std; pub(crate) mod hax_utils; -// This module is declared here since otherwise, hax reports the following error: -// -// The THIR body of item -// DefId(0:986 ~ libcrux[92b3]::kem::kyber768::parameters::COEFFICIENTS_IN_RING_ELEMENT) -// was stolen. -// -// This is being tracked in https://github.com/hacspec/hacspec-v2/issues/27 -#[cfg(feature = "pre-verification")] -pub(crate) mod constants; - -/// Helpers for verification and extraction -#[cfg(feature = "pre-verification")] -mod helper; -#[cfg(feature = "pre-verification")] -mod utils; - -#[cfg(feature = "pre-verification")] -mod constant_time_ops; -#[cfg(feature = "pre-verification")] -mod hash_functions; -#[cfg(feature = "pre-verification")] -mod ind_cca; -#[cfg(feature = "pre-verification")] -mod ind_cpa; -#[cfg(feature = "pre-verification")] -mod invert_ntt; - -#[cfg(feature = "pre-verification")] -mod matrix; -#[cfg(feature = "pre-verification")] -mod ntt; -#[cfg(feature = "pre-verification")] -mod polynomial; -#[cfg(feature = "pre-verification")] -mod sampling; -#[cfg(feature = "pre-verification")] -mod serialize; -#[cfg(feature = "pre-verification")] -mod types; -#[cfg(feature = "pre-verification")] -mod vector; +cfg_pre_verification! { + // This module is declared here since otherwise, hax reports the following error: + // + // The THIR body of item + // DefId(0:986 ~ libcrux[92b3]::kem::kyber768::parameters::COEFFICIENTS_IN_RING_ELEMENT) + // was stolen. + // + // This is being tracked in https://github.com/hacspec/hacspec-v2/issues/27 + pub(crate) mod constants; + + /// Helpers for verification and extraction + mod helper; + + mod utils; + mod constant_time_ops; + mod hash_functions; + mod ind_cca; + mod ind_cpa; + mod invert_ntt; + mod matrix; + mod ntt; + mod polynomial; + mod sampling; + mod serialize; + mod types; + mod vector; + + #[cfg(feature = "mlkem1024")] + pub mod mlkem1024; + #[cfg(feature = "mlkem1024")] + pub mod mlkem512; + #[cfg(feature = "mlkem1024")] + pub mod mlkem768; + + pub use constants::SHARED_SECRET_SIZE; + + pub use ind_cca::{MlKemSharedSecret, ENCAPS_SEED_SIZE, KEY_GENERATION_SEED_SIZE}; + + // These types all have type aliases for the different variants. + pub use types::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; + + cfg_kyber! { + pub mod kyber512 { + //! Kyber 512 (NIST PQC Round 3) + pub use crate::mlkem512::generate_key_pair; + pub use crate::mlkem512::kyber::decapsulate; + pub use crate::mlkem512::kyber::encapsulate; + pub use crate::mlkem512::validate_public_key; + } + + pub mod kyber768 { + //! Kyber 768 (NIST PQC Round 3) + pub use crate::mlkem768::generate_key_pair; + pub use crate::mlkem768::kyber::decapsulate; + pub use crate::mlkem768::kyber::encapsulate; + pub use crate::mlkem768::validate_public_key; + } + + pub mod kyber1024 { + //! Kyber 1024 (NIST PQC Round 3) + pub use crate::mlkem1024::generate_key_pair; + pub use crate::mlkem1024::kyber::decapsulate; + pub use crate::mlkem1024::kyber::encapsulate; + pub use crate::mlkem1024::validate_public_key; + } + } +} #[cfg(not(feature = "pre-verification"))] mod kem; -// Variants -#[cfg(all(feature = "mlkem1024", feature = "pre-verification"))] -pub mod mlkem1024; -#[cfg(all(feature = "mlkem512", feature = "pre-verification"))] -pub mod mlkem512; -#[cfg(all(feature = "mlkem768", feature = "pre-verification"))] -pub mod mlkem768; - -// Variants -#[cfg(all(feature = "mlkem512", not(feature = "pre-verification")))] -pub mod mlkem512 { - pub use crate::kem::kyber::kyber512::*; -} -#[cfg(all(feature = "mlkem768", not(feature = "pre-verification")))] -pub mod mlkem768 { - pub use crate::kem::kyber::kyber768::*; -} +cfg_verified! { + // Variants + #[cfg(feature = "mlkem512")] + pub mod mlkem512 { + pub use crate::kem::kyber::kyber512::*; + } -#[cfg(all(feature = "mlkem1024", not(feature = "pre-verification")))] -pub mod mlkem1024 { - pub use crate::kem::kyber::kyber1024::*; -} + #[cfg(feature = "mlkem768")] + pub mod mlkem768 { + pub use crate::kem::kyber::kyber768::*; + } -#[cfg(all(feature = "kyber", feature = "pre-verification"))] -pub mod kyber512 { - //! Kyber 512 (NIST PQC Round 3) - pub use crate::mlkem512::generate_key_pair; - pub use crate::mlkem512::kyber::decapsulate; - pub use crate::mlkem512::kyber::encapsulate; - pub use crate::mlkem512::validate_public_key; -} -#[cfg(all(feature = "kyber", feature = "pre-verification"))] -pub mod kyber768 { - //! Kyber 768 (NIST PQC Round 3) - pub use crate::mlkem768::generate_key_pair; - pub use crate::mlkem768::kyber::decapsulate; - pub use crate::mlkem768::kyber::encapsulate; - pub use crate::mlkem768::validate_public_key; -} + #[cfg(feature = "mlkem1024")] + pub mod mlkem1024 { + pub use crate::kem::kyber::kyber1024::*; + } -#[cfg(all(feature = "kyber", feature = "pre-verification"))] -pub mod kyber1024 { - //! Kyber 1024 (NIST PQC Round 3) - pub use crate::mlkem1024::generate_key_pair; - pub use crate::mlkem1024::kyber::decapsulate; - pub use crate::mlkem1024::kyber::encapsulate; - pub use crate::mlkem1024::validate_public_key; -} + pub const SHARED_SECRET_SIZE: usize = kem::kyber::constants::SHARED_SECRET_SIZE; -#[cfg(feature = "pre-verification")] -pub use constants::SHARED_SECRET_SIZE; -#[cfg(not(feature = "pre-verification"))] -pub const SHARED_SECRET_SIZE: usize = kem::kyber::constants::SHARED_SECRET_SIZE; + pub use kem::kyber::MlKemSharedSecret; -#[cfg(feature = "pre-verification")] -pub use ind_cca::{MlKemSharedSecret, ENCAPS_SEED_SIZE, KEY_GENERATION_SEED_SIZE}; -#[cfg(not(feature = "pre-verification"))] -pub use kem::kyber::MlKemSharedSecret; -#[cfg(not(feature = "pre-verification"))] -pub const ENCAPS_SEED_SIZE: usize = kem::kyber::constants::SHARED_SECRET_SIZE; -#[cfg(not(feature = "pre-verification"))] -pub const KEY_GENERATION_SEED_SIZE: usize = kem::kyber::KEY_GENERATION_SEED_SIZE; + pub const ENCAPS_SEED_SIZE: usize = kem::kyber::constants::SHARED_SECRET_SIZE; -// These types all have type aliases for the different variants. -#[cfg(not(feature = "pre-verification"))] -pub use kem::kyber::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; -#[cfg(feature = "pre-verification")] -pub use types::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; + pub const KEY_GENERATION_SEED_SIZE: usize = kem::kyber::KEY_GENERATION_SEED_SIZE; + // These types all have type aliases for the different variants. + + pub use kem::kyber::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; +} From 19040cda2f92b690c7e9d5c1fcde4e65a8af12ab Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 11:02:58 +0200 Subject: [PATCH 34/53] Fix hax extraction --- Cargo.lock | 1 + libcrux-ml-kem/Cargo.toml | 1 + libcrux-ml-kem/src/kem/kyber/ntt.rs | 2 ++ 3 files changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 87093de8..e7500ff9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1030,6 +1030,7 @@ version = "0.0.2-pre.2" dependencies = [ "criterion", "hax-lib 0.1.0-pre.1 (git+https://github.com/hacspec/hax/)", + "hax-lib-macros 0.1.0-pre.1 (git+https://github.com/hacspec/hax/)", "hex", "libcrux-intrinsics", "libcrux-platform", diff --git a/libcrux-ml-kem/Cargo.toml b/libcrux-ml-kem/Cargo.toml index 2f66da63..c72c48e4 100644 --- a/libcrux-ml-kem/Cargo.toml +++ b/libcrux-ml-kem/Cargo.toml @@ -27,6 +27,7 @@ libcrux-intrinsics = { version = "0.0.2-pre.2", path = "../libcrux-intrinsics" } # The hax config is set by the hax toolchain. [target.'cfg(hax)'.dependencies] hax-lib = { version = "0.1.0-pre.1", git = "https://github.com/hacspec/hax/" } +hax-lib-macros = { version = "0.1.0-pre.1", git = "https://github.com/hacspec/hax/" } [features] default = ["std", "mlkem512", "mlkem768", "mlkem1024"] diff --git a/libcrux-ml-kem/src/kem/kyber/ntt.rs b/libcrux-ml-kem/src/kem/kyber/ntt.rs index 6e933b02..78448ee1 100644 --- a/libcrux-ml-kem/src/kem/kyber/ntt.rs +++ b/libcrux-ml-kem/src/kem/kyber/ntt.rs @@ -7,6 +7,8 @@ use super::{ }, constants::COEFFICIENTS_IN_RING_ELEMENT, }; +#[cfg(hax)] +use crate::kem::kyber::constants::FIELD_MODULUS; const ZETAS_TIMES_MONTGOMERY_R: [FieldElementTimesMontgomeryR; 128] = [ -1044, -758, -359, -1517, 1493, 1422, 287, 202, -171, 622, 1577, 182, 962, -1202, -1474, 1468, From dbde61d12e80808ad2968a38093cc2bbb870bfb2 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 11:23:48 +0200 Subject: [PATCH 35/53] Feature flag documentation --- libcrux-ml-kem/src/lib.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 66ce6794..dc3bc72e 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -1,7 +1,7 @@ //! # ML-KEM //! -//! This crate implements all three ML-KEM variants 512, 768, and 1024. -//! It is formally verified using [hax] and [F*]. +//! This crate implements all three ML-KEM variants 512, 768, and 1024. It is +//! formally verified using [hax](https://cryspen.com/hax) and [F*](https://fstar-lang.org). //! //! ``` //! use rand::{rngs::OsRng, RngCore}; @@ -33,8 +33,19 @@ //! let shared_secret_decapsulated = mlkem768::decapsulate(key_pair.private_key(), &ciphertext); //! ``` //! -//! [hax]: https://cryspen.com/hax -//! [F*]: https://fstar-lang.org +//! ## Features +//! +//! By default, all ML-KEM parameter sets are enabled. If required, they are +//! available individually under feature flags `mlkem512`, `mlkem768`, +//! `mlkem1024`. +//! +//! In addition to the verified implementations of the ML-KEM variants, the +//! feature flag `pre-verification` gives access to, as yet, unverified +//! implementations of ML-KEM that are optimized for SIMD instruction sets. The +//! `pre-verification` flag in combination with the `kyber` flag also gives +//! access to an, as yet, unverified implementation of Kyber as submitted in +//! Round 3 of the NIST PQ competition. +//! #![no_std] #![forbid(unsafe_code)] From 24297ff2d16318e7bb1c40c61d32b8131eacbd4d Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 13:21:40 +0200 Subject: [PATCH 36/53] Fix mistaken feature guards --- libcrux-ml-kem/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index dc3bc72e..57c4cccf 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -90,9 +90,9 @@ cfg_pre_verification! { #[cfg(feature = "mlkem1024")] pub mod mlkem1024; - #[cfg(feature = "mlkem1024")] + #[cfg(feature = "mlkem512")] pub mod mlkem512; - #[cfg(feature = "mlkem1024")] + #[cfg(feature = "mlkem768")] pub mod mlkem768; pub use constants::SHARED_SECRET_SIZE; From 3877346e7c8a0d1ea5c8027ff372f875174cb097 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 13:48:56 +0200 Subject: [PATCH 37/53] Remove commented code --- libcrux-ml-kem/src/kem.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libcrux-ml-kem/src/kem.rs b/libcrux-ml-kem/src/kem.rs index 5ca3dd67..01df82cb 100644 --- a/libcrux-ml-kem/src/kem.rs +++ b/libcrux-ml-kem/src/kem.rs @@ -20,15 +20,6 @@ pub mod deterministic { pub use super::kyber::kyber768::generate_key_pair as kyber768_generate_keypair_derand; } -// use self::kyber::MlKemSharedSecret; -// use self::kyber::{kyber1024, kyber512, kyber768}; -// pub use kyber::{ -// kyber1024::{MlKem1024Ciphertext, MlKem1024PrivateKey, MlKem1024PublicKey}, -// kyber512::{MlKem512Ciphertext, MlKem512PrivateKey, MlKem512PublicKey}, -// kyber768::{MlKem768Ciphertext, MlKem768PrivateKey, MlKem768PublicKey}, -// MlKemCiphertext, MlKemKeyPair, -// }; - #[cfg(feature = "tests")] pub use kyber::{ kyber1024::validate_public_key as ml_kem1024_validate_public_key, From 5271f75980026e0253f4b4a9359692de9bc86a09 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 13:58:00 +0200 Subject: [PATCH 38/53] `size` -> `len` --- libcrux-kem/src/kem.rs | 10 +++++----- libcrux-ml-kem/src/kem/kyber/types.rs | 6 +----- libcrux-ml-kem/src/types.rs | 8 ++------ libcrux-ml-kem/tests/self.rs | 20 ++++++++++---------- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/libcrux-kem/src/kem.rs b/libcrux-kem/src/kem.rs index fdb9e063..51265f62 100644 --- a/libcrux-kem/src/kem.rs +++ b/libcrux-kem/src/kem.rs @@ -484,7 +484,7 @@ impl PrivateKey { .map_err(|_| Error::InvalidPrivateKey) .map(Self::MlKem768), Algorithm::X25519MlKem768Draft00 => { - let key: [u8; MlKem768PrivateKey::size() + 32] = + let key: [u8; MlKem768PrivateKey::len() + 32] = bytes.try_into().map_err(|_| Error::InvalidPrivateKey)?; let (xsk, ksk) = key.split_at(32); Ok(Self::X25519MlKem768Draft00( @@ -790,7 +790,7 @@ impl Ct { .map_err(|_| Error::InvalidCiphertext) .map(Self::MlKem768), Algorithm::X25519MlKem768Draft00 => { - let key: [u8; MlKem768Ciphertext::size() + 32] = + let key: [u8; MlKem768Ciphertext::len() + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; let (xct, kct) = key.split_at(32); Ok(Self::X25519MlKem768Draft00( @@ -799,9 +799,9 @@ impl Ct { )) } Algorithm::XWingKemDraft02 => { - let key: [u8; MlKem768Ciphertext::size() + 32] = + let key: [u8; MlKem768Ciphertext::len() + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; - let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::size()); + let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::len()); Ok(Self::XWingKemDraft02( ct_m.try_into().map_err(|_| Error::InvalidCiphertext)?, ct_x.try_into().map_err(|_| Error::InvalidCiphertext)?, @@ -821,7 +821,7 @@ impl Ct { Algorithm::XWingKyberDraft02 => { let key: [u8; MlKem768Ciphertext::len() + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; - let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::size()); + let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::len()); Ok(Self::XWingKyberDraft02( ct_m.try_into().map_err(|_| Error::InvalidCiphertext)?, ct_x.try_into().map_err(|_| Error::InvalidCiphertext)?, diff --git a/libcrux-ml-kem/src/kem/kyber/types.rs b/libcrux-ml-kem/src/kem/kyber/types.rs index 36ced680..a3856827 100644 --- a/libcrux-ml-kem/src/kem/kyber/types.rs +++ b/libcrux-ml-kem/src/kem/kyber/types.rs @@ -50,11 +50,7 @@ macro_rules! impl_generic_struct { self.value.split_at(mid) } - pub const fn len(&self) -> usize { - SIZE - } - - pub const fn size() -> usize { + pub const fn len() -> usize { SIZE } } diff --git a/libcrux-ml-kem/src/types.rs b/libcrux-ml-kem/src/types.rs index c5ffd59f..b2ab0cc3 100644 --- a/libcrux-ml-kem/src/types.rs +++ b/libcrux-ml-kem/src/types.rs @@ -55,12 +55,8 @@ macro_rules! impl_generic_struct { // self.value.split_at(mid) // } - /// The number of bytes. - pub const fn len(&self) -> usize { - SIZE - } - - pub const fn size() -> usize { + /// The number of bytes + pub const fn len() -> usize { SIZE } } diff --git a/libcrux-ml-kem/tests/self.rs b/libcrux-ml-kem/tests/self.rs index 1667de5c..98a27f44 100644 --- a/libcrux-ml-kem/tests/self.rs +++ b/libcrux-ml-kem/tests/self.rs @@ -48,10 +48,10 @@ pub mod default { } random_u32 >>= 8; - let position = random_u32 % MlKemCiphertext::::size(); + let position = random_u32 % MlKemCiphertext::::len(); raw_ciphertext[position] ^= random_byte; - let ciphertext: [u8; LEN] = raw_ciphertext[0..MlKemCiphertext::::size()] + let ciphertext: [u8; LEN] = raw_ciphertext[0..MlKemCiphertext::::len()] .try_into() .unwrap(); @@ -96,15 +96,15 @@ pub mod default { random_u32 >>= 8; let position = if modify_implicit_rejection_value { - (MlKemPrivateKey::::size() - SHARED_SECRET_SIZE) + (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) } else { - random_u32 % (MlKemPrivateKey::::size() - SHARED_SECRET_SIZE) + random_u32 % (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) }; raw_secret_key[position] ^= random_byte; - let secret_key: [u8; LEN] = raw_secret_key[0..MlKemPrivateKey::::size()] + let secret_key: [u8; LEN] = raw_secret_key[0..MlKemPrivateKey::::len()] .try_into() .unwrap(); @@ -116,7 +116,7 @@ pub mod default { secret_key: MlKemPrivateKey, ) -> [u8; SHARED_SECRET_SIZE] { let mut to_hash = - secret_key[MlKemPrivateKey::::size() - SHARED_SECRET_SIZE..].to_vec(); + secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); to_hash.extend_from_slice(ciphertext.as_ref()); shake256(&to_hash) @@ -302,7 +302,7 @@ pub mod pre_verification { } random_u32 >>= 8; - let position = random_u32 % MlKemCiphertext::::size(); + let position = random_u32 % MlKemCiphertext::::len(); ciphertext[position] ^= random_byte; ciphertext @@ -345,10 +345,10 @@ pub mod pre_verification { random_u32 >>= 8; let position = if modify_implicit_rejection_value { - (MlKemPrivateKey::::size() - SHARED_SECRET_SIZE) + (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) } else { - random_u32 % (MlKemPrivateKey::::size() - SHARED_SECRET_SIZE) + random_u32 % (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) }; raw_secret_key[position] ^= random_byte; @@ -361,7 +361,7 @@ pub mod pre_verification { secret_key: MlKemPrivateKey, ) -> [u8; SHARED_SECRET_SIZE] { let mut to_hash = - secret_key[MlKemPrivateKey::::size() - SHARED_SECRET_SIZE..].to_vec(); + secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); to_hash.extend_from_slice(ciphertext.as_ref()); shake256(&to_hash) From 96ab20d8629dfe933aa66ddbd855bf2da3d4b244 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 13:58:52 +0200 Subject: [PATCH 39/53] Drop explicit dependency on `hax-lib-macros` --- Cargo.lock | 1 - libcrux-ml-kem/Cargo.toml | 1 - libcrux-ml-kem/src/kem/kyber/arithmetic.rs | 20 +++++++++---------- libcrux-ml-kem/src/kem/kyber/compress.rs | 14 ++++++------- .../src/kem/kyber/constant_time_ops.rs | 6 +++--- libcrux-ml-kem/src/kem/kyber/ntt.rs | 12 +++++------ libcrux-ml-kem/src/kem/kyber/sampling.rs | 8 ++++---- src/digest.rs | 2 +- 8 files changed, 31 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7500ff9..87093de8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1030,7 +1030,6 @@ version = "0.0.2-pre.2" dependencies = [ "criterion", "hax-lib 0.1.0-pre.1 (git+https://github.com/hacspec/hax/)", - "hax-lib-macros 0.1.0-pre.1 (git+https://github.com/hacspec/hax/)", "hex", "libcrux-intrinsics", "libcrux-platform", diff --git a/libcrux-ml-kem/Cargo.toml b/libcrux-ml-kem/Cargo.toml index c72c48e4..2f66da63 100644 --- a/libcrux-ml-kem/Cargo.toml +++ b/libcrux-ml-kem/Cargo.toml @@ -27,7 +27,6 @@ libcrux-intrinsics = { version = "0.0.2-pre.2", path = "../libcrux-intrinsics" } # The hax config is set by the hax toolchain. [target.'cfg(hax)'.dependencies] hax-lib = { version = "0.1.0-pre.1", git = "https://github.com/hacspec/hax/" } -hax-lib-macros = { version = "0.1.0-pre.1", git = "https://github.com/hacspec/hax/" } [features] default = ["std", "mlkem512", "mlkem768", "mlkem1024"] diff --git a/libcrux-ml-kem/src/kem/kyber/arithmetic.rs b/libcrux-ml-kem/src/kem/kyber/arithmetic.rs index 4543b6fb..de38ff72 100644 --- a/libcrux-ml-kem/src/kem/kyber/arithmetic.rs +++ b/libcrux-ml-kem/src/kem/kyber/arithmetic.rs @@ -19,8 +19,8 @@ pub(crate) type MontgomeryFieldElement = i32; /// We use 'fer' as a shorthand for this type. pub(crate) type FieldElementTimesMontgomeryR = i32; -#[cfg_attr(hax, hax_lib_macros::requires(n == 4 || n == 5 || n == 10 || n == 11 || n == MONTGOMERY_SHIFT))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| result < 2u32.pow(n.into())))] +#[cfg_attr(hax, hax_lib::requires(n == 4 || n == 5 || n == 10 || n == 11 || n == MONTGOMERY_SHIFT))] +#[cfg_attr(hax, hax_lib::ensures(|result| result < 2u32.pow(n.into())))] #[inline(always)] pub(crate) fn get_n_least_significant_bits(n: u8, value: u32) -> u32 { hax_debug_assert!(n == 4 || n == 5 || n == 10 || n == 11 || n == MONTGOMERY_SHIFT); @@ -46,8 +46,8 @@ const BARRETT_MULTIPLIER: i64 = 20159; /// /// In particular, if `|value| < BARRETT_R`, then `|result| < FIELD_MODULUS`. -#[cfg_attr(hax, hax_lib_macros::requires((i64::from(value) > -BARRETT_R && i64::from(value) < BARRETT_R)))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| result > -FIELD_MODULUS && result < FIELD_MODULUS))] +#[cfg_attr(hax, hax_lib::requires((i64::from(value) > -BARRETT_R && i64::from(value) < BARRETT_R)))] +#[cfg_attr(hax, hax_lib::ensures(|result| result > -FIELD_MODULUS && result < FIELD_MODULUS))] pub(crate) fn barrett_reduce(value: FieldElement) -> FieldElement { hax_debug_assert!( i64::from(value) > -BARRETT_R && i64::from(value) < BARRETT_R, @@ -80,8 +80,8 @@ const INVERSE_OF_MODULUS_MOD_MONTGOMERY_R: u32 = 62209; // FIELD_MODULUS^{-1} mo /// `|result| ≤ (|value| / MONTGOMERY_R) + (FIELD_MODULUS / 2) /// /// In particular, if `|value| ≤ FIELD_MODULUS * MONTGOMERY_R`, then `|o| < (3 · FIELD_MODULUS) / 2`. -#[cfg_attr(hax, hax_lib_macros::requires(value >= -FIELD_MODULUS * MONTGOMERY_R && value <= FIELD_MODULUS * MONTGOMERY_R))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| result >= -(3 * FIELD_MODULUS) / 2 && result <= (3 * FIELD_MODULUS) / 2))] +#[cfg_attr(hax, hax_lib::requires(value >= -FIELD_MODULUS * MONTGOMERY_R && value <= FIELD_MODULUS * MONTGOMERY_R))] +#[cfg_attr(hax, hax_lib::ensures(|result| result >= -(3 * FIELD_MODULUS) / 2 && result <= (3 * FIELD_MODULUS) / 2))] pub(crate) fn montgomery_reduce(value: FieldElement) -> MontgomeryFieldElement { // This forces hax to extract code for MONTGOMERY_R before it extracts code // for this function. The removal of this line is being tracked in: @@ -142,8 +142,8 @@ pub(crate) fn to_standard_domain(mfe: MontgomeryFieldElement) -> FieldElement { /// output `o` such that: /// - `o` is congruent to `fe` /// - 0 ≤ `o` FIELD_MODULUS -#[cfg_attr(hax, hax_lib_macros::requires(fe >= -FIELD_MODULUS && fe < FIELD_MODULUS))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| result >= 0 && result < (FIELD_MODULUS as u16)))] +#[cfg_attr(hax, hax_lib::requires(fe >= -FIELD_MODULUS && fe < FIELD_MODULUS))] +#[cfg_attr(hax, hax_lib::ensures(|result| result >= 0 && result < (FIELD_MODULUS as u16)))] #[inline(always)] pub(crate) fn to_unsigned_representative(fe: FieldElement) -> u16 { hax_debug_assert!(fe >= -FIELD_MODULUS && fe < FIELD_MODULUS); @@ -163,14 +163,14 @@ impl PolynomialRingElement { /// Given two polynomial ring elements `lhs` and `rhs`, compute the pointwise /// sum of their constituent coefficients. -#[cfg_attr(hax, hax_lib_macros::requires( +#[cfg_attr(hax, hax_lib::requires( hax_lib::forall(|i:usize| hax_lib::implies(i < COEFFICIENTS_IN_RING_ELEMENT, || (lhs.coefficients[i].abs() <= ((K as i32) - 1) * FIELD_MODULUS) && (rhs.coefficients[i].abs() <= FIELD_MODULUS) ))))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::forall(|i:usize| hax_lib::implies(i < result.coefficients.len(), || result.coefficients[i].abs() <= (K as i32) * FIELD_MODULUS diff --git a/libcrux-ml-kem/src/kem/kyber/compress.rs b/libcrux-ml-kem/src/kem/kyber/compress.rs index c2ea6f7d..dd1ebd4d 100644 --- a/libcrux-ml-kem/src/kem/kyber/compress.rs +++ b/libcrux-ml-kem/src/kem/kyber/compress.rs @@ -26,8 +26,8 @@ use super::{ /// The NIST FIPS 203 standard can be found at /// . -#[cfg_attr(hax, hax_lib_macros::requires(fe < (FIELD_MODULUS as u16)))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::requires(fe < (FIELD_MODULUS as u16)))] +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::implies(833 <= fe && fe <= 2596, || result == 1) && hax_lib::implies(!(833 <= fe && fe <= 2596), || result == 0) ))] @@ -57,14 +57,14 @@ pub(super) fn compress_message_coefficient(fe: u16) -> u8 { } #[cfg_attr(hax, - hax_lib_macros::requires( + hax_lib::requires( (coefficient_bits == 4 || coefficient_bits == 5 || coefficient_bits == 10 || coefficient_bits == 11) && fe < (FIELD_MODULUS as u16)))] #[cfg_attr(hax, - hax_lib_macros::ensures( + hax_lib::ensures( |result| result >= 0 && result < 2i32.pow(coefficient_bits as u32)))] pub(super) fn compress_ciphertext_coefficient(coefficient_bits: u8, fe: u16) -> FieldElement { hax_debug_assert!( @@ -107,14 +107,14 @@ pub(super) fn compress_ciphertext_coefficient(coefficient_bits: u8, fe: u16) -> /// The NIST FIPS 203 standard can be found at /// . -#[cfg_attr(hax, hax_lib_macros::requires((fe == 0) || (fe == 1)))] +#[cfg_attr(hax, hax_lib::requires((fe == 0) || (fe == 1)))] #[inline(always)] pub(super) fn decompress_message_coefficient(fe: FieldElement) -> FieldElement { -fe & ((FIELD_MODULUS + 1) / 2) } -#[cfg_attr(hax, hax_lib_macros::requires((coefficient_bits == 4 || coefficient_bits == 5 || coefficient_bits == 10 || coefficient_bits == 11) && (fe >= 0) && (fe < 2i32.pow(coefficient_bits as u32))))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| result < FIELD_MODULUS))] +#[cfg_attr(hax, hax_lib::requires((coefficient_bits == 4 || coefficient_bits == 5 || coefficient_bits == 10 || coefficient_bits == 11) && (fe >= 0) && (fe < 2i32.pow(coefficient_bits as u32))))] +#[cfg_attr(hax, hax_lib::ensures(|result| result < FIELD_MODULUS))] pub(super) fn decompress_ciphertext_coefficient( coefficient_bits: u8, fe: FieldElement, diff --git a/libcrux-ml-kem/src/kem/kyber/constant_time_ops.rs b/libcrux-ml-kem/src/kem/kyber/constant_time_ops.rs index 2066a1d7..66b667da 100644 --- a/libcrux-ml-kem/src/kem/kyber/constant_time_ops.rs +++ b/libcrux-ml-kem/src/kem/kyber/constant_time_ops.rs @@ -5,7 +5,7 @@ use crate::hax_utils::hax_debug_assert; // operations are not being optimized away/constant-timedness is not being broken. /// Return 1 if `value` is not zero and 0 otherwise. -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::implies(value == 0, || result == 0) && hax_lib::implies(value != 0, || result == 1) ))] @@ -20,7 +20,7 @@ fn is_non_zero(value: u8) -> u8 { /// Return 1 if the bytes of `lhs` and `rhs` do not exactly /// match and 0 otherwise. -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::implies(lhs == rhs, || result == 0) && hax_lib::implies(lhs != rhs, || result == 1) ))] @@ -41,7 +41,7 @@ pub(crate) fn compare_ciphertexts_in_constant_time /// If `selector` is not zero, return the bytes in `rhs`; return the bytes in /// `lhs` otherwise. -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::implies(selector == 0, || result == lhs) && hax_lib::implies(selector != 0, || result == rhs) ))] diff --git a/libcrux-ml-kem/src/kem/kyber/ntt.rs b/libcrux-ml-kem/src/kem/kyber/ntt.rs index 78448ee1..6d154211 100644 --- a/libcrux-ml-kem/src/kem/kyber/ntt.rs +++ b/libcrux-ml-kem/src/kem/kyber/ntt.rs @@ -82,11 +82,11 @@ fn ntt_at_layer_3328( /// This function operates only on those which were produced by binomial /// sampling, and thus those which have small coefficients. The small /// coefficients let us skip the first round of Montgomery reductions. -#[cfg_attr(hax, hax_lib_macros::requires( +#[cfg_attr(hax, hax_lib::requires( hax_lib::forall(|i:usize| hax_lib::implies(i < re.coefficients.len(), || re.coefficients[i].abs() <= 3 ))))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::forall(|i:usize| hax_lib::implies(i < result.coefficients.len(), || result.coefficients[i].abs() < FIELD_MODULUS @@ -136,11 +136,11 @@ pub(in crate::kem::kyber) fn ntt_binomially_sampled_ring_element( /// /// This function operates on the ring element that partly constitutes /// the ciphertext. -#[cfg_attr(hax, hax_lib_macros::requires( +#[cfg_attr(hax, hax_lib::requires( hax_lib::forall(|i:usize| hax_lib::implies(i < re.coefficients.len(), || re.coefficients[i].abs() <= 3328 ))))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::forall(|i:usize| hax_lib::implies(i < result.coefficients.len(), || result.coefficients[i].abs() < FIELD_MODULUS @@ -295,14 +295,14 @@ fn ntt_multiply_binomials( /// /// The NIST FIPS 203 standard can be found at /// . -#[cfg_attr(hax, hax_lib_macros::requires( +#[cfg_attr(hax, hax_lib::requires( hax_lib::forall(|i:usize| hax_lib::implies(i < COEFFICIENTS_IN_RING_ELEMENT, || (lhs.coefficients[i] >= 0 && lhs.coefficients[i] < 4096) && (rhs.coefficients[i].abs() <= FIELD_MODULUS) ))))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::forall(|i:usize| hax_lib::implies(i < result.coefficients.len(), || result.coefficients[i].abs() <= FIELD_MODULUS diff --git a/libcrux-ml-kem/src/kem/kyber/sampling.rs b/libcrux-ml-kem/src/kem/kyber/sampling.rs index f4d1fbfc..efd975ad 100644 --- a/libcrux-ml-kem/src/kem/kyber/sampling.rs +++ b/libcrux-ml-kem/src/kem/kyber/sampling.rs @@ -149,8 +149,8 @@ pub(super) fn sample_from_xof(seeds: [[u8; 34]; K]) -> [Polynomi /// /// The NIST FIPS 203 standard can be found at /// . -#[cfg_attr(hax, hax_lib_macros::requires(randomness.len() == 2 * 64))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::requires(randomness.len() == 2 * 64))] +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::forall(|i:usize| hax_lib::implies(i < result.coefficients.len(), || result.coefficients[i].abs() <= 2 ))))] @@ -188,8 +188,8 @@ fn sample_from_binomial_distribution_2(randomness: &[u8]) -> PolynomialRingEleme sampled } -#[cfg_attr(hax, hax_lib_macros::requires(randomness.len() == 3 * 64))] -#[cfg_attr(hax, hax_lib_macros::ensures(|result| +#[cfg_attr(hax, hax_lib::requires(randomness.len() == 3 * 64))] +#[cfg_attr(hax, hax_lib::ensures(|result| hax_lib::forall(|i:usize| hax_lib::implies(i < result.coefficients.len(), || result.coefficients[i].abs() <= 3 ))))] diff --git a/src/digest.rs b/src/digest.rs index c7f4ff74..44313868 100644 --- a/src/digest.rs +++ b/src/digest.rs @@ -380,7 +380,7 @@ pub fn shake256(data: &[u8]) -> [u8; LEN] { pub mod incremental_x4 { /// Incremental state - #[cfg_attr(hax, hax_lib_macros::opaque_type)] + #[cfg_attr(hax, hax_lib::opaque_type)] pub struct Shake128StateX4 { state: crate::hacl::sha3::incremental_x4::Shake128StateX4, } From 4b1d95a2b7013bace0b2675a1b7cb981619cbb39 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 14:06:22 +0200 Subject: [PATCH 40/53] Hide helper macro docs --- libcrux-ml-kem/src/kem/kyber/helper.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libcrux-ml-kem/src/kem/kyber/helper.rs b/libcrux-ml-kem/src/kem/kyber/helper.rs index c0bae70f..f46a23ae 100644 --- a/libcrux-ml-kem/src/kem/kyber/helper.rs +++ b/libcrux-ml-kem/src/kem/kyber/helper.rs @@ -2,6 +2,7 @@ /// can go through. #[cfg(not(hax))] +#[doc(hidden)] #[macro_export] macro_rules! cloop { (for ($i:ident, $chunk:ident) in $val:ident.$values:ident.chunks_exact($($chunk_size:expr),*).enumerate() $body:block) => { @@ -37,6 +38,7 @@ macro_rules! cloop { } #[cfg(hax)] +#[doc(hidden)] #[macro_export] macro_rules! cloop { (for ($i:ident, $chunk:ident) in $val:ident.$values:ident.chunks_exact($($chunk_size:expr),*).enumerate() $body:block) => { From bd14f8dbaaaa410644e261a4bb6317edaf90c973 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 14:08:20 +0200 Subject: [PATCH 41/53] Formatting --- libcrux-ml-kem/tests/self.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libcrux-ml-kem/tests/self.rs b/libcrux-ml-kem/tests/self.rs index 98a27f44..4c8b41cd 100644 --- a/libcrux-ml-kem/tests/self.rs +++ b/libcrux-ml-kem/tests/self.rs @@ -96,8 +96,7 @@ pub mod default { random_u32 >>= 8; let position = if modify_implicit_rejection_value { - (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) - + (random_u32 % SHARED_SECRET_SIZE) + (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) } else { random_u32 % (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) }; @@ -115,8 +114,7 @@ pub mod default { ciphertext: MlKemCiphertext, secret_key: MlKemPrivateKey, ) -> [u8; SHARED_SECRET_SIZE] { - let mut to_hash = - secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); + let mut to_hash = secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); to_hash.extend_from_slice(ciphertext.as_ref()); shake256(&to_hash) @@ -345,8 +343,7 @@ pub mod pre_verification { random_u32 >>= 8; let position = if modify_implicit_rejection_value { - (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) - + (random_u32 % SHARED_SECRET_SIZE) + (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) } else { random_u32 % (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) }; @@ -360,8 +357,7 @@ pub mod pre_verification { ciphertext: MlKemCiphertext, secret_key: MlKemPrivateKey, ) -> [u8; SHARED_SECRET_SIZE] { - let mut to_hash = - secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); + let mut to_hash = secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); to_hash.extend_from_slice(ciphertext.as_ref()); shake256(&to_hash) From c7ca638f3137248e5e7233235492c9da6429fa26 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 14:23:02 +0200 Subject: [PATCH 42/53] Call out the `kyber` feature more prominently --- libcrux-ml-kem/src/lib.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 57c4cccf..70821b71 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -1,7 +1,8 @@ //! # ML-KEM //! //! This crate implements all three ML-KEM variants 512, 768, and 1024. It is -//! formally verified using [hax](https://cryspen.com/hax) and [F*](https://fstar-lang.org). +//! formally verified using [hax](https://cryspen.com/hax) and +//! [F*](https://fstar-lang.org). //! //! ``` //! use rand::{rngs::OsRng, RngCore}; @@ -41,10 +42,12 @@ //! //! In addition to the verified implementations of the ML-KEM variants, the //! feature flag `pre-verification` gives access to, as yet, unverified -//! implementations of ML-KEM that are optimized for SIMD instruction sets. The -//! `pre-verification` flag in combination with the `kyber` flag also gives -//! access to an, as yet, unverified implementation of Kyber as submitted in -//! Round 3 of the NIST PQ competition. +//! implementations of ML-KEM that are optimized for SIMD instruction sets. +//! +//! ### Kyber Round 3 +//! The `kyber` flag (in combination with `pre-verification`) also gives access +//! to an, as yet, unverified implementation of Kyber as submitted in Round 3 of +//! the NIST PQ competition. //! #![no_std] From 12d7693557f7533d16dc36532fcddc50411adc48 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Thu, 27 Jun 2024 17:27:15 +0200 Subject: [PATCH 43/53] Feature gate tests etc so `--no-std-features` tests --- libcrux-ml-kem/Cargo.toml | 12 ++++++ libcrux-ml-kem/src/cfg.rs | 2 +- libcrux-ml-kem/src/lib.rs | 66 +++++++++++++++++--------------- libcrux-ml-kem/tests/ml-kem.rs | 13 ++++++- libcrux-ml-kem/tests/nistkats.rs | 14 +++++-- libcrux-ml-kem/tests/self.rs | 34 +++++++++++++--- 6 files changed, 100 insertions(+), 41 deletions(-) diff --git a/libcrux-ml-kem/Cargo.toml b/libcrux-ml-kem/Cargo.toml index 2f66da63..849067a9 100644 --- a/libcrux-ml-kem/Cargo.toml +++ b/libcrux-ml-kem/Cargo.toml @@ -49,3 +49,15 @@ criterion = "0.5" [[bench]] name = "ml-kem" harness = false + +[[example]] +name = "encapsulate" +required-features = ["mlkem768"] + +[[example]] +name = "decapsulate" +required-features = ["mlkem768"] + +[[example]] +name = "keygen" +required-features = ["mlkem768"] diff --git a/libcrux-ml-kem/src/cfg.rs b/libcrux-ml-kem/src/cfg.rs index 2c8b5367..9e7d715a 100644 --- a/libcrux-ml-kem/src/cfg.rs +++ b/libcrux-ml-kem/src/cfg.rs @@ -2,7 +2,7 @@ macro_rules! cfg_verified { ($($item:item)*) => { $( - #[cfg(not(feature = "pre-verification"))] + #[cfg(all(feature = "std", not(feature = "pre-verification")))] $item )* } diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 70821b71..3bfc98ba 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -4,35 +4,40 @@ //! formally verified using [hax](https://cryspen.com/hax) and //! [F*](https://fstar-lang.org). //! -//! ``` -//! use rand::{rngs::OsRng, RngCore}; -//! -//! // Ensure you use good randomness. -//! // It is not recommended to use OsRng directly! -//! // Instead it is highly encouraged to use RNGs like NISTs DRBG to account for -//! // bad system entropy. -//! fn random_array() -> [u8; L] { -//! let mut rng = OsRng; -//! let mut seed = [0; L]; -//! rng.try_fill_bytes(&mut seed).unwrap(); -//! seed -//! } -//! -//! use libcrux_ml_kem::*; -//! -//! // This example use ML-KEM 768. The other variants can be used the same way. -//! -//! // Generate a key pair. -//! let randomness = random_array(); -//! let key_pair = mlkem768::generate_key_pair(randomness); -//! -//! // Encapsulating a shared secret to a public key. -//! let randomness = random_array(); -//! let (ciphertext, shared_secret) = mlkem768::encapsulate(key_pair.public_key(), randomness); -//! -//! // Decapsulating a shared secret with a private key. -//! let shared_secret_decapsulated = mlkem768::decapsulate(key_pair.private_key(), &ciphertext); -//! ``` + +#![cfg_attr( + feature = "mlkem768", + doc = r##" +``` + use rand::{rngs::OsRng, RngCore}; + + // Ensure you use good randomness. + // It is not recommended to use OsRng directly! + // Instead it is highly encouraged to use RNGs like NISTs DRBG to account for + // bad system entropy. + fn random_array() -> [u8; L] { + let mut rng = OsRng; + let mut seed = [0; L]; + rng.try_fill_bytes(&mut seed).unwrap(); + seed + } + + use libcrux_ml_kem::*; + + // This example use ML-KEM 768. The other variants can be used the same way. + + // Generate a key pair. + let randomness = random_array(); + let key_pair = mlkem768::generate_key_pair(randomness); + + // Encapsulating a shared secret to a public key. + let randomness = random_array(); + let (ciphertext, shared_secret) = mlkem768::encapsulate(key_pair.public_key(), randomness); + + // Decapsulating a shared secret with a private key. + let shared_secret_decapsulated = mlkem768::decapsulate(key_pair.private_key(), &ciphertext); +```"## +)] //! //! ## Features //! @@ -49,7 +54,6 @@ //! to an, as yet, unverified implementation of Kyber as submitted in Round 3 of //! the NIST PQ competition. //! - #![no_std] #![forbid(unsafe_code)] #![warn(rust_2018_idioms, unused_lifetimes, unused_qualifications)] @@ -132,7 +136,7 @@ cfg_pre_verification! { } } -#[cfg(not(feature = "pre-verification"))] +#[cfg(all(feature = "std", not(feature = "pre-verification")))] mod kem; cfg_verified! { diff --git a/libcrux-ml-kem/tests/ml-kem.rs b/libcrux-ml-kem/tests/ml-kem.rs index 4e5202ae..785c5f29 100644 --- a/libcrux-ml-kem/tests/ml-kem.rs +++ b/libcrux-ml-kem/tests/ml-kem.rs @@ -6,7 +6,12 @@ use std::{ path::Path, }; -use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768}; +#[cfg(feature = "mlkem1024")] +use libcrux_ml_kem::mlkem1024; +#[cfg(feature = "mlkem512")] +use libcrux_ml_kem::mlkem512; +#[cfg(feature = "mlkem768")] +use libcrux_ml_kem::mlkem768; /// These tests are from https://github.com/C2SP/CCTV/ fn test_invalid_modulus(p: &str) { @@ -18,8 +23,11 @@ fn test_invalid_modulus(p: &str) { let pk = hex::decode(line).unwrap(); let pk = pk.as_slice(); match p { + #[cfg(feature = "mlkem512")] "512" => assert!(mlkem512::validate_public_key(pk.try_into().unwrap()).is_none()), + #[cfg(feature = "mlkem768")] "768" => assert!(mlkem768::validate_public_key(pk.try_into().unwrap()).is_none()), + #[cfg(feature = "mlkem1024")] "1024" => assert!(mlkem1024::validate_public_key(pk.try_into().unwrap()).is_none()), _ => unreachable!(), }; @@ -27,16 +35,19 @@ fn test_invalid_modulus(p: &str) { } #[test] +#[cfg(feature = "mlkem512")] fn invalid_modulus_512() { test_invalid_modulus("512"); } #[test] +#[cfg(feature = "mlkem768")] fn invalid_modulus_768() { test_invalid_modulus("768"); } #[test] +#[cfg(feature = "mlkem1024")] fn invalid_modulus_1024() { test_invalid_modulus("1024"); } diff --git a/libcrux-ml-kem/tests/nistkats.rs b/libcrux-ml-kem/tests/nistkats.rs index ab929738..dae2921a 100644 --- a/libcrux-ml-kem/tests/nistkats.rs +++ b/libcrux-ml-kem/tests/nistkats.rs @@ -1,6 +1,11 @@ +#[cfg(feature = "mlkem1024")] +use libcrux_ml_kem::mlkem1024; +#[cfg(feature = "mlkem512")] +use libcrux_ml_kem::mlkem512; +#[cfg(feature = "mlkem768")] +use libcrux_ml_kem::mlkem768; #[cfg(all(feature = "kyber", feature = "pre-verification"))] use libcrux_ml_kem::{kyber1024, kyber512, kyber768}; -use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768}; use serde::Deserialize; use serde_json; use std::{fs::File, io::BufReader, path::Path}; @@ -64,7 +69,7 @@ macro_rules! impl_nist_known_answer_tests { } }; } - +#[cfg(feature = "mlkem512")] impl_nist_known_answer_tests!( mlkem512_nist_known_answer_tests, "mlkem", @@ -73,6 +78,7 @@ impl_nist_known_answer_tests!( mlkem512::encapsulate, mlkem512::decapsulate ); +#[cfg(feature = "mlkem768")] impl_nist_known_answer_tests!( mlkem768_nist_known_answer_tests, "mlkem", @@ -81,6 +87,8 @@ impl_nist_known_answer_tests!( mlkem768::encapsulate, mlkem768::decapsulate ); + +#[cfg(feature = "mlkem1024")] impl_nist_known_answer_tests!( mlkem1024_nist_known_answer_tests, "mlkem", @@ -90,7 +98,7 @@ impl_nist_known_answer_tests!( mlkem1024::decapsulate ); -#[cfg(feature = "pre-verification")] +#[cfg(all(feature = "mlkem768", feature = "pre-verification"))] impl_nist_known_answer_tests!( mlkem768_nist_kats_portable, "mlkem", diff --git a/libcrux-ml-kem/tests/self.rs b/libcrux-ml-kem/tests/self.rs index 4c8b41cd..d847f465 100644 --- a/libcrux-ml-kem/tests/self.rs +++ b/libcrux-ml-kem/tests/self.rs @@ -1,6 +1,13 @@ -#[cfg(not(feature = "pre-verification"))] +#[cfg(all(feature = "std", not(feature = "pre-verification")))] pub mod default { - use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768, MlKemCiphertext, MlKemPrivateKey}; + #[cfg(feature = "mlkem1024")] + use libcrux_ml_kem::mlkem1024; + #[cfg(feature = "mlkem512")] + use libcrux_ml_kem::mlkem512; + #[cfg(feature = "mlkem768")] + use libcrux_ml_kem::mlkem768; + use libcrux_ml_kem::{MlKemCiphertext, MlKemPrivateKey}; + use libcrux_sha3::shake256; use rand::{rngs::OsRng, thread_rng, RngCore}; @@ -175,56 +182,63 @@ pub mod default { }; } + #[cfg(feature = "mlkem512")] impl_consistency!( consistency_512, mlkem512::generate_key_pair, mlkem512::encapsulate, mlkem512::decapsulate ); + #[cfg(feature = "mlkem768")] impl_consistency!( consistency_768, mlkem768::generate_key_pair, mlkem768::encapsulate, mlkem768::decapsulate ); + #[cfg(feature = "mlkem1024")] impl_consistency!( consistency_1024, mlkem1024::generate_key_pair, mlkem1024::encapsulate, mlkem1024::decapsulate ); - + #[cfg(feature = "mlkem512")] impl_modified_ciphertext!( modified_ciphertext_512, mlkem1024::generate_key_pair, mlkem1024::encapsulate, mlkem1024::decapsulate ); + #[cfg(feature = "mlkem768")] impl_modified_ciphertext!( modified_ciphertext_768, mlkem1024::generate_key_pair, mlkem1024::encapsulate, mlkem1024::decapsulate ); + #[cfg(feature = "mlkem1024")] impl_modified_ciphertext!( modified_ciphertext_1024, mlkem1024::generate_key_pair, mlkem1024::encapsulate, mlkem1024::decapsulate ); - + #[cfg(feature = "mlkem512")] impl_modified_secret_key!( modified_secret_key_512, mlkem1024::generate_key_pair, mlkem1024::encapsulate, mlkem1024::decapsulate ); + #[cfg(feature = "mlkem768")] impl_modified_secret_key!( modified_secret_key_768, mlkem1024::generate_key_pair, mlkem1024::encapsulate, mlkem1024::decapsulate ); + #[cfg(feature = "mlkem1024")] impl_modified_secret_key!( modified_secret_key_1024, mlkem1024::generate_key_pair, @@ -232,18 +246,21 @@ pub mod default { mlkem1024::decapsulate ); + #[cfg(feature = "mlkem512")] impl_modified_ciphertext_and_implicit_rejection_value!( modified_ciphertext_and_implicit_rejection_value_512, mlkem1024::generate_key_pair, mlkem1024::encapsulate, mlkem1024::decapsulate ); + #[cfg(feature = "mlkem768")] impl_modified_ciphertext_and_implicit_rejection_value!( modified_ciphertext_and_implicit_rejection_value_768, mlkem1024::generate_key_pair, mlkem1024::encapsulate, mlkem1024::decapsulate ); + #[cfg(feature = "mlkem1024")] impl_modified_ciphertext_and_implicit_rejection_value!( modified_ciphertext_and_implicit_rejection_value_1024, mlkem1024::generate_key_pair, @@ -254,7 +271,13 @@ pub mod default { #[cfg(feature = "pre-verification")] pub mod pre_verification { - use libcrux_ml_kem::{mlkem1024, mlkem512, mlkem768, MlKemCiphertext, MlKemPrivateKey}; + #[cfg(feature = "mlkem1024")] + use libcrux_ml_kem::mlkem1024; + #[cfg(feature = "mlkem512")] + use libcrux_ml_kem::mlkem512; + #[cfg(feature = "mlkem768")] + use libcrux_ml_kem::mlkem768; + use libcrux_ml_kem::{MlKemCiphertext, MlKemPrivateKey}; use libcrux_sha3::shake256; use rand::{rngs::OsRng, thread_rng, RngCore}; @@ -487,6 +510,7 @@ pub mod pre_verification { mlkem1024::encapsulate, mlkem1024::decapsulate ); + impl_modified_ciphertext_and_implicit_rejection_value!( modified_ciphertext_and_implicit_rejection_value_1024, mlkem1024::generate_key_pair, From c391c741a10b4513e323bdc35c409cee503285d1 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 11:15:57 +0200 Subject: [PATCH 44/53] cleanup; make features work --- libcrux-ml-kem/Cargo.toml | 14 +- libcrux-ml-kem/src/cfg.rs | 5 +- libcrux-ml-kem/src/kem/kyber/helper.rs | 4 +- libcrux-ml-kem/src/kem/kyber/ind_cpa.rs | 4 +- libcrux-ml-kem/src/kem/kyber/matrix.rs | 2 +- libcrux-ml-kem/src/kem/kyber/sampling.rs | 2 +- libcrux-ml-kem/src/kem/kyber/serialize.rs | 2 +- libcrux-ml-kem/src/lib.rs | 28 +- libcrux-ml-kem/tests/self.rs | 711 +++++++--------------- 9 files changed, 264 insertions(+), 508 deletions(-) diff --git a/libcrux-ml-kem/Cargo.toml b/libcrux-ml-kem/Cargo.toml index 849067a9..134a6d97 100644 --- a/libcrux-ml-kem/Cargo.toml +++ b/libcrux-ml-kem/Cargo.toml @@ -29,16 +29,28 @@ libcrux-intrinsics = { version = "0.0.2-pre.2", path = "../libcrux-intrinsics" } hax-lib = { version = "0.1.0-pre.1", git = "https://github.com/hacspec/hax/" } [features] +# By default all variants and std are enabled. default = ["std", "mlkem512", "mlkem768", "mlkem1024"] + +# Hardware features can be force enabled. +# It is not recommended to use these. This crate performs CPU feature detection +# and enables the features when they are available. simd128 = ["libcrux-sha3/simd128"] simd256 = ["libcrux-sha3/simd256"] + +# Features for the different key sizes of ML-KEM mlkem512 = [] mlkem768 = [] mlkem1024 = [] -std = [] + +# Enable Round 3 Kyber in addition to ML-KEM kyber = [] + +# Code that is not yet verified pre-verification = [] +std = [] + [dev-dependencies] rand = { version = "0.8" } serde_json = { version = "1.0" } diff --git a/libcrux-ml-kem/src/cfg.rs b/libcrux-ml-kem/src/cfg.rs index 9e7d715a..4f611d02 100644 --- a/libcrux-ml-kem/src/cfg.rs +++ b/libcrux-ml-kem/src/cfg.rs @@ -1,8 +1,9 @@ -/// Macro to simplify feature gating of verified code +/// Macro to simplify feature gating of verified code that should only be enabled +/// when unverified code is disabled. macro_rules! cfg_verified { ($($item:item)*) => { $( - #[cfg(all(feature = "std", not(feature = "pre-verification")))] + #[cfg(not(feature = "pre-verification"))] $item )* } diff --git a/libcrux-ml-kem/src/kem/kyber/helper.rs b/libcrux-ml-kem/src/kem/kyber/helper.rs index f46a23ae..47fa920a 100644 --- a/libcrux-ml-kem/src/kem/kyber/helper.rs +++ b/libcrux-ml-kem/src/kem/kyber/helper.rs @@ -3,7 +3,6 @@ #[cfg(not(hax))] #[doc(hidden)] -#[macro_export] macro_rules! cloop { (for ($i:ident, $chunk:ident) in $val:ident.$values:ident.chunks_exact($($chunk_size:expr),*).enumerate() $body:block) => { for $i in 0..$val.$values.len() / ($($chunk_size)*) { @@ -39,7 +38,6 @@ macro_rules! cloop { #[cfg(hax)] #[doc(hidden)] -#[macro_export] macro_rules! cloop { (for ($i:ident, $chunk:ident) in $val:ident.$values:ident.chunks_exact($($chunk_size:expr),*).enumerate() $body:block) => { for ($i, $chunk) in $val.$values.chunks_exact($($chunk_size),*).enumerate() $body @@ -57,3 +55,5 @@ macro_rules! cloop { for $i in ($start..$end).step_by($step) $body }; } + +pub(super) use cloop; diff --git a/libcrux-ml-kem/src/kem/kyber/ind_cpa.rs b/libcrux-ml-kem/src/kem/kyber/ind_cpa.rs index 6552e2c0..88605b8b 100644 --- a/libcrux-ml-kem/src/kem/kyber/ind_cpa.rs +++ b/libcrux-ml-kem/src/kem/kyber/ind_cpa.rs @@ -1,9 +1,8 @@ -use std::usize; - use super::{ arithmetic::{to_unsigned_representative, PolynomialRingElement}, constants::{BYTES_PER_RING_ELEMENT, COEFFICIENTS_IN_RING_ELEMENT, SHARED_SECRET_SIZE}, hash_functions::{G, PRF}, + helper::cloop, matrix::*, ntt::*, sampling::sample_from_binomial_distribution, @@ -15,7 +14,6 @@ use super::{ serialize_uncompressed_ring_element, }, }; -use crate::cloop; /// Pad the `slice` with `0`s at the end. #[inline(always)] diff --git a/libcrux-ml-kem/src/kem/kyber/matrix.rs b/libcrux-ml-kem/src/kem/kyber/matrix.rs index a4908eaa..15f624e6 100644 --- a/libcrux-ml-kem/src/kem/kyber/matrix.rs +++ b/libcrux-ml-kem/src/kem/kyber/matrix.rs @@ -4,10 +4,10 @@ use super::{ PolynomialRingElement, }, constants::COEFFICIENTS_IN_RING_ELEMENT, + helper::cloop, ntt::{invert_ntt_montgomery, ntt_multiply}, sampling::sample_from_xof, }; -use crate::cloop; #[inline(always)] #[allow(non_snake_case)] diff --git a/libcrux-ml-kem/src/kem/kyber/sampling.rs b/libcrux-ml-kem/src/kem/kyber/sampling.rs index efd975ad..64e74d51 100644 --- a/libcrux-ml-kem/src/kem/kyber/sampling.rs +++ b/libcrux-ml-kem/src/kem/kyber/sampling.rs @@ -2,8 +2,8 @@ use super::{ arithmetic::{FieldElement, PolynomialRingElement}, constants::{COEFFICIENTS_IN_RING_ELEMENT, FIELD_MODULUS}, hash_functions::*, + helper::cloop, }; -use crate::cloop; use crate::hax_utils::hax_debug_assert; /// If `bytes` contains a set of uniformly random bytes, this function diff --git a/libcrux-ml-kem/src/kem/kyber/serialize.rs b/libcrux-ml-kem/src/kem/kyber/serialize.rs index 2197a860..6943b816 100644 --- a/libcrux-ml-kem/src/kem/kyber/serialize.rs +++ b/libcrux-ml-kem/src/kem/kyber/serialize.rs @@ -5,8 +5,8 @@ use super::{ decompress_ciphertext_coefficient, decompress_message_coefficient, }, constants::{BYTES_PER_RING_ELEMENT, SHARED_SECRET_SIZE}, + helper::cloop, }; -use crate::cloop; use crate::hax_utils::hax_debug_assert; #[inline(always)] diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index 3bfc98ba..c1e69e8b 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -63,11 +63,16 @@ #[macro_use] mod cfg; -#[cfg(feature = "std")] -extern crate std; - pub(crate) mod hax_utils; +// Not-yet verified ML-KEM implementation. +// This implementation has 3 different variant. +// - portable +// - neon +// - avx2 +// +// When #221 is finished, the pre-verification feature will be removed and this +// implementation will be promoted to the default one. cfg_pre_verification! { // This module is declared here since otherwise, hax reports the following error: // @@ -136,10 +141,16 @@ cfg_pre_verification! { } } -#[cfg(all(feature = "std", not(feature = "pre-verification")))] -mod kem; - +// Verified ML-KEM implementation. +// The proofs are in +// - correctness: ../proofs/fstar/extraction-edited +// - secret independence: ../proofs/fstar/extraction-secret-independent +// +// When #221 is completed, this code will be removed and replaced with the, then +// verified, code above. cfg_verified! { + mod kem; + // Variants #[cfg(feature = "mlkem512")] pub mod mlkem512 { @@ -151,20 +162,15 @@ cfg_verified! { pub use crate::kem::kyber::kyber768::*; } - #[cfg(feature = "mlkem1024")] pub mod mlkem1024 { pub use crate::kem::kyber::kyber1024::*; } pub const SHARED_SECRET_SIZE: usize = kem::kyber::constants::SHARED_SECRET_SIZE; - pub use kem::kyber::MlKemSharedSecret; - pub const ENCAPS_SEED_SIZE: usize = kem::kyber::constants::SHARED_SECRET_SIZE; - pub const KEY_GENERATION_SEED_SIZE: usize = kem::kyber::KEY_GENERATION_SEED_SIZE; // These types all have type aliases for the different variants. - pub use kem::kyber::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; } diff --git a/libcrux-ml-kem/tests/self.rs b/libcrux-ml-kem/tests/self.rs index d847f465..052311dc 100644 --- a/libcrux-ml-kem/tests/self.rs +++ b/libcrux-ml-kem/tests/self.rs @@ -1,520 +1,259 @@ -#[cfg(all(feature = "std", not(feature = "pre-verification")))] -pub mod default { - #[cfg(feature = "mlkem1024")] - use libcrux_ml_kem::mlkem1024; - #[cfg(feature = "mlkem512")] - use libcrux_ml_kem::mlkem512; - #[cfg(feature = "mlkem768")] - use libcrux_ml_kem::mlkem768; - use libcrux_ml_kem::{MlKemCiphertext, MlKemPrivateKey}; - - use libcrux_sha3::shake256; - use rand::{rngs::OsRng, thread_rng, RngCore}; - - const SHARED_SECRET_SIZE: usize = 32; - - fn random_array() -> [u8; L] { - let mut rng = OsRng; - let mut seed = [0; L]; - rng.try_fill_bytes(&mut seed).unwrap(); - seed - } +use libcrux_ml_kem::{MlKemCiphertext, MlKemPrivateKey}; - macro_rules! impl_consistency { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); - let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); - assert_eq!( - shared_secret, shared_secret_decapsulated, - "lhs: shared_secret, rhs: shared_secret_decapsulated" - ); - - // If the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. - } - }; - } +use libcrux_sha3::shake256; +use rand::{rngs::OsRng, thread_rng, RngCore}; - fn modify_ciphertext( - ciphertext: MlKemCiphertext, - ) -> MlKemCiphertext { - let mut raw_ciphertext = [0u8; LEN]; - raw_ciphertext.copy_from_slice(ciphertext.as_ref()); - let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); +const SHARED_SECRET_SIZE: usize = 32; - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; - } - random_u32 >>= 8; +fn random_array() -> [u8; L] { + let mut rng = OsRng; + let mut seed = [0; L]; + rng.try_fill_bytes(&mut seed).unwrap(); + seed +} - let position = random_u32 % MlKemCiphertext::::len(); - raw_ciphertext[position] ^= random_byte; +macro_rules! impl_consistency { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); + let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); + assert_eq!( + shared_secret, shared_secret_decapsulated, + "lhs: shared_secret, rhs: shared_secret_decapsulated" + ); + + // If the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; +} - let ciphertext: [u8; LEN] = raw_ciphertext[0..MlKemCiphertext::::len()] - .try_into() - .unwrap(); +fn modify_ciphertext(ciphertext: MlKemCiphertext) -> MlKemCiphertext { + let mut raw_ciphertext = [0u8; LEN]; + raw_ciphertext.copy_from_slice(ciphertext.as_ref()); + let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); - ciphertext.into() + let mut random_byte: u8 = (random_u32 & 0xFF) as u8; + if random_byte == 0 { + random_byte += 1; } + random_u32 >>= 8; - macro_rules! impl_modified_ciphertext { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); - - let ciphertext = modify_ciphertext(ciphertext); - let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); - - assert_ne!(shared_secret, shared_secret_decapsulated); - - // if the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. - } - }; - } + let position = random_u32 % MlKemCiphertext::::len(); + raw_ciphertext[position] ^= random_byte; - fn modify_secret_key( - secret_key: &MlKemPrivateKey, - modify_implicit_rejection_value: bool, - ) -> MlKemPrivateKey { - let mut raw_secret_key = [0u8; LEN]; - raw_secret_key.copy_from_slice(secret_key.as_slice()); + let ciphertext: [u8; LEN] = raw_ciphertext[0..MlKemCiphertext::::len()] + .try_into() + .unwrap(); - let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); + ciphertext.into() +} - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; - } - random_u32 >>= 8; +macro_rules! impl_modified_ciphertext { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); - let position = if modify_implicit_rejection_value { - (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) - } else { - random_u32 % (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) - }; + let ciphertext = modify_ciphertext(ciphertext); + let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); - raw_secret_key[position] ^= random_byte; + assert_ne!(shared_secret, shared_secret_decapsulated); - let secret_key: [u8; LEN] = raw_secret_key[0..MlKemPrivateKey::::len()] - .try_into() - .unwrap(); + // if the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. + } + }; +} - secret_key.into() - } +fn modify_secret_key( + secret_key: &MlKemPrivateKey, + modify_implicit_rejection_value: bool, +) -> MlKemPrivateKey { + let mut raw_secret_key = [0u8; LEN]; + raw_secret_key.copy_from_slice(secret_key.as_slice()); - fn compute_implicit_rejection_shared_secret( - ciphertext: MlKemCiphertext, - secret_key: MlKemPrivateKey, - ) -> [u8; SHARED_SECRET_SIZE] { - let mut to_hash = secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); - to_hash.extend_from_slice(ciphertext.as_ref()); + let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); - shake256(&to_hash) + let mut random_byte: u8 = (random_u32 & 0xFF) as u8; + if random_byte == 0 { + random_byte += 1; } + random_u32 >>= 8; - macro_rules! impl_modified_secret_key { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); - - let secret_key = modify_secret_key(key_pair.private_key(), false); - let shared_secret_decapsulated = $decaps(&secret_key, &ciphertext); - - assert_eq!( - shared_secret_decapsulated, - compute_implicit_rejection_shared_secret(ciphertext, secret_key) - ); - - // if the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. - } - }; - } + let position = if modify_implicit_rejection_value { + (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) + } else { + random_u32 % (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) + }; - macro_rules! impl_modified_ciphertext_and_implicit_rejection_value { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); - - let ciphertext = modify_ciphertext(ciphertext); - let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); - - let secret_key = modify_secret_key(key_pair.private_key(), true); - let shared_secret_decapsulated_ms = $decaps(&secret_key, &ciphertext); - - assert_ne!(shared_secret_decapsulated, shared_secret_decapsulated_ms); - - assert_eq!( - shared_secret_decapsulated_ms, - compute_implicit_rejection_shared_secret(ciphertext, secret_key) - ); - - // if the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. - } - }; - } + raw_secret_key[position] ^= random_byte; - #[cfg(feature = "mlkem512")] - impl_consistency!( - consistency_512, - mlkem512::generate_key_pair, - mlkem512::encapsulate, - mlkem512::decapsulate - ); - #[cfg(feature = "mlkem768")] - impl_consistency!( - consistency_768, - mlkem768::generate_key_pair, - mlkem768::encapsulate, - mlkem768::decapsulate - ); - #[cfg(feature = "mlkem1024")] - impl_consistency!( - consistency_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - #[cfg(feature = "mlkem512")] - impl_modified_ciphertext!( - modified_ciphertext_512, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - #[cfg(feature = "mlkem768")] - impl_modified_ciphertext!( - modified_ciphertext_768, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - #[cfg(feature = "mlkem1024")] - impl_modified_ciphertext!( - modified_ciphertext_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - #[cfg(feature = "mlkem512")] - impl_modified_secret_key!( - modified_secret_key_512, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - #[cfg(feature = "mlkem768")] - impl_modified_secret_key!( - modified_secret_key_768, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - #[cfg(feature = "mlkem1024")] - impl_modified_secret_key!( - modified_secret_key_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - - #[cfg(feature = "mlkem512")] - impl_modified_ciphertext_and_implicit_rejection_value!( - modified_ciphertext_and_implicit_rejection_value_512, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - #[cfg(feature = "mlkem768")] - impl_modified_ciphertext_and_implicit_rejection_value!( - modified_ciphertext_and_implicit_rejection_value_768, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - #[cfg(feature = "mlkem1024")] - impl_modified_ciphertext_and_implicit_rejection_value!( - modified_ciphertext_and_implicit_rejection_value_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); -} + let secret_key: [u8; LEN] = raw_secret_key[0..MlKemPrivateKey::::len()] + .try_into() + .unwrap(); -#[cfg(feature = "pre-verification")] -pub mod pre_verification { - #[cfg(feature = "mlkem1024")] - use libcrux_ml_kem::mlkem1024; - #[cfg(feature = "mlkem512")] - use libcrux_ml_kem::mlkem512; - #[cfg(feature = "mlkem768")] - use libcrux_ml_kem::mlkem768; - use libcrux_ml_kem::{MlKemCiphertext, MlKemPrivateKey}; - use libcrux_sha3::shake256; - use rand::{rngs::OsRng, thread_rng, RngCore}; - - const SHARED_SECRET_SIZE: usize = 32; - - fn random_array() -> [u8; L] { - let mut rng = OsRng; - let mut seed = [0; L]; - rng.try_fill_bytes(&mut seed).unwrap(); - seed - } + secret_key.into() +} - macro_rules! impl_consistency { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); - let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); - assert_eq!( - shared_secret, shared_secret_decapsulated, - "lhs: shared_secret, rhs: shared_secret_decapsulated" - ); - - // If the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. - } - }; - } +fn compute_implicit_rejection_shared_secret( + ciphertext: MlKemCiphertext, + secret_key: MlKemPrivateKey, +) -> [u8; SHARED_SECRET_SIZE] { + let mut to_hash = secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); + to_hash.extend_from_slice(ciphertext.as_ref()); - fn modify_ciphertext( - mut ciphertext: MlKemCiphertext, - ) -> MlKemCiphertext { - let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); + shake256(&to_hash) +} - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; +macro_rules! impl_modified_secret_key { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); + + let secret_key = modify_secret_key(key_pair.private_key(), false); + let shared_secret_decapsulated = $decaps(&secret_key, &ciphertext); + + assert_eq!( + shared_secret_decapsulated, + compute_implicit_rejection_shared_secret(ciphertext, secret_key) + ); + + // if the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. } - random_u32 >>= 8; + }; +} - let position = random_u32 % MlKemCiphertext::::len(); - ciphertext[position] ^= random_byte; +macro_rules! impl_modified_ciphertext_and_implicit_rejection_value { + ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[test] + fn $name() { + let randomness = random_array(); + let key_pair = $key_gen(randomness); + let randomness = random_array(); + let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); - ciphertext - } + let ciphertext = modify_ciphertext(ciphertext); + let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); - macro_rules! impl_modified_ciphertext { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, shared_secret) = $encaps(key_pair.public_key(), randomness); - - let ciphertext = modify_ciphertext(ciphertext); - let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); - - assert_ne!(shared_secret, shared_secret_decapsulated); - - // if the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. - } - }; - } + let secret_key = modify_secret_key(key_pair.private_key(), true); + let shared_secret_decapsulated_ms = $decaps(&secret_key, &ciphertext); - fn modify_secret_key( - secret_key: &MlKemPrivateKey, - modify_implicit_rejection_value: bool, - ) -> MlKemPrivateKey { - let mut raw_secret_key: MlKemPrivateKey = secret_key.as_slice().into(); + assert_ne!(shared_secret_decapsulated, shared_secret_decapsulated_ms); - let mut random_u32: usize = thread_rng().next_u32().try_into().unwrap(); + assert_eq!( + shared_secret_decapsulated_ms, + compute_implicit_rejection_shared_secret(ciphertext, secret_key) + ); - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; + // if the randomness was not enough for the rejection sampling step + // in key-generation and encapsulation, simply return without + // failing. } - random_u32 >>= 8; - - let position = if modify_implicit_rejection_value { - (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) - } else { - random_u32 % (MlKemPrivateKey::::len() - SHARED_SECRET_SIZE) - }; - - raw_secret_key[position] ^= random_byte; - - raw_secret_key - } - - fn compute_implicit_rejection_shared_secret( - ciphertext: MlKemCiphertext, - secret_key: MlKemPrivateKey, - ) -> [u8; SHARED_SECRET_SIZE] { - let mut to_hash = secret_key[MlKemPrivateKey::::len() - SHARED_SECRET_SIZE..].to_vec(); - to_hash.extend_from_slice(ciphertext.as_ref()); - - shake256(&to_hash) - } - - macro_rules! impl_modified_secret_key { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); - - let secret_key = modify_secret_key(key_pair.private_key(), false); - let shared_secret_decapsulated = $decaps(&secret_key, &ciphertext); - - assert_eq!( - shared_secret_decapsulated, - compute_implicit_rejection_shared_secret(ciphertext, secret_key) - ); - - // if the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. - } - }; - } - - macro_rules! impl_modified_ciphertext_and_implicit_rejection_value { - ($name:ident, $key_gen:expr, $encaps:expr, $decaps:expr) => { - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[test] - fn $name() { - let randomness = random_array(); - let key_pair = $key_gen(randomness); - let randomness = random_array(); - let (ciphertext, _) = $encaps(key_pair.public_key(), randomness); - - let ciphertext = modify_ciphertext(ciphertext); - let shared_secret_decapsulated = $decaps(key_pair.private_key(), &ciphertext); - - let secret_key = modify_secret_key(key_pair.private_key(), true); - let shared_secret_decapsulated_ms = $decaps(&secret_key, &ciphertext); - - assert_ne!(shared_secret_decapsulated, shared_secret_decapsulated_ms); - - assert_eq!( - shared_secret_decapsulated_ms, - compute_implicit_rejection_shared_secret(ciphertext, secret_key) - ); - - // if the randomness was not enough for the rejection sampling step - // in key-generation and encapsulation, simply return without - // failing. - } - }; - } - - impl_consistency!( - consistency_512, - mlkem512::generate_key_pair, - mlkem512::encapsulate, - mlkem512::decapsulate - ); - impl_consistency!( - consistency_768, - mlkem768::generate_key_pair, - mlkem768::encapsulate, - mlkem768::decapsulate - ); - impl_consistency!( - consistency_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - - impl_modified_ciphertext!( - modified_ciphertext_512, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - impl_modified_ciphertext!( - modified_ciphertext_768, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - impl_modified_ciphertext!( - modified_ciphertext_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - - impl_modified_secret_key!( - modified_secret_key_512, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - impl_modified_secret_key!( - modified_secret_key_768, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - impl_modified_secret_key!( - modified_secret_key_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - - impl_modified_ciphertext_and_implicit_rejection_value!( - modified_ciphertext_and_implicit_rejection_value_512, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - impl_modified_ciphertext_and_implicit_rejection_value!( - modified_ciphertext_and_implicit_rejection_value_768, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); - - impl_modified_ciphertext_and_implicit_rejection_value!( - modified_ciphertext_and_implicit_rejection_value_1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate - ); + }; } + +#[cfg(feature = "mlkem512")] +impl_consistency!( + consistency_512, + libcrux_ml_kem::mlkem512::generate_key_pair, + libcrux_ml_kem::mlkem512::encapsulate, + libcrux_ml_kem::mlkem512::decapsulate +); +#[cfg(feature = "mlkem768")] +impl_consistency!( + consistency_768, + libcrux_ml_kem::mlkem768::generate_key_pair, + libcrux_ml_kem::mlkem768::encapsulate, + libcrux_ml_kem::mlkem768::decapsulate +); +#[cfg(feature = "mlkem1024")] +impl_consistency!( + consistency_1024, + libcrux_ml_kem::mlkem1024::generate_key_pair, + libcrux_ml_kem::mlkem1024::encapsulate, + libcrux_ml_kem::mlkem1024::decapsulate +); +#[cfg(feature = "mlkem512")] +impl_modified_ciphertext!( + modified_ciphertext_512, + libcrux_ml_kem::mlkem512::generate_key_pair, + libcrux_ml_kem::mlkem512::encapsulate, + libcrux_ml_kem::mlkem512::decapsulate +); +#[cfg(feature = "mlkem768")] +impl_modified_ciphertext!( + modified_ciphertext_768, + libcrux_ml_kem::mlkem768::generate_key_pair, + libcrux_ml_kem::mlkem768::encapsulate, + libcrux_ml_kem::mlkem768::decapsulate +); +#[cfg(feature = "mlkem1024")] +impl_modified_ciphertext!( + modified_ciphertext_1024, + libcrux_ml_kem::mlkem1024::generate_key_pair, + libcrux_ml_kem::mlkem1024::encapsulate, + libcrux_ml_kem::mlkem1024::decapsulate +); +#[cfg(feature = "mlkem512")] +impl_modified_secret_key!( + modified_secret_key_512, + libcrux_ml_kem::mlkem512::generate_key_pair, + libcrux_ml_kem::mlkem512::encapsulate, + libcrux_ml_kem::mlkem512::decapsulate +); +#[cfg(feature = "mlkem768")] +impl_modified_secret_key!( + modified_secret_key_768, + libcrux_ml_kem::mlkem768::generate_key_pair, + libcrux_ml_kem::mlkem768::encapsulate, + libcrux_ml_kem::mlkem768::decapsulate +); +#[cfg(feature = "mlkem1024")] +impl_modified_secret_key!( + modified_secret_key_1024, + libcrux_ml_kem::mlkem1024::generate_key_pair, + libcrux_ml_kem::mlkem1024::encapsulate, + libcrux_ml_kem::mlkem1024::decapsulate +); + +#[cfg(feature = "mlkem512")] +impl_modified_ciphertext_and_implicit_rejection_value!( + modified_ciphertext_and_implicit_rejection_value_512, + libcrux_ml_kem::mlkem512::generate_key_pair, + libcrux_ml_kem::mlkem512::encapsulate, + libcrux_ml_kem::mlkem512::decapsulate +); +#[cfg(feature = "mlkem768")] +impl_modified_ciphertext_and_implicit_rejection_value!( + modified_ciphertext_and_implicit_rejection_value_768, + libcrux_ml_kem::mlkem768::generate_key_pair, + libcrux_ml_kem::mlkem768::encapsulate, + libcrux_ml_kem::mlkem768::decapsulate +); +#[cfg(feature = "mlkem1024")] +impl_modified_ciphertext_and_implicit_rejection_value!( + modified_ciphertext_and_implicit_rejection_value_1024, + libcrux_ml_kem::mlkem1024::generate_key_pair, + libcrux_ml_kem::mlkem1024::encapsulate, + libcrux_ml_kem::mlkem1024::decapsulate +); From fc84415c186516d0231814f2ce8b80a0820c188b Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 13:30:55 +0200 Subject: [PATCH 45/53] more cleanup and docs --- .github/workflows/mlkem.yml | 15 +++ Cargo.toml | 3 +- libcrux-ml-dsa/src/hash_functions.rs | 8 +- libcrux-ml-kem/Cargo.toml | 11 ++ libcrux-ml-kem/src/cfg.rs | 1 + libcrux-ml-kem/src/hash_functions.rs | 12 +-- libcrux-ml-kem/src/kem.rs | 46 ++++---- libcrux-ml-kem/src/kem/kyber.rs | 3 + .../src/kem/kyber/hash_functions.rs | 10 +- libcrux-ml-kem/src/lib.rs | 22 +++- libcrux-ml-kem/src/mlkem1024.rs | 2 +- libcrux-ml-kem/src/mlkem512.rs | 2 +- libcrux-ml-kem/src/mlkem768.rs | 8 +- libcrux-ml-kem/tests/kyber.rs | 2 +- libcrux-ml-kem/tests/ml-kem.rs | 33 +++--- libcrux-ml-kem/tests/nistkats.rs | 82 ++++++++------ libcrux-sha3/Cargo.toml | 3 + libcrux-sha3/src/generic_keccak.rs | 9 +- libcrux-sha3/src/lib.rs | 101 +++++++++++------- sys/platform/Cargo.toml | 3 + sys/platform/src/macos_arm.rs | 2 +- 21 files changed, 237 insertions(+), 141 deletions(-) diff --git a/.github/workflows/mlkem.yml b/.github/workflows/mlkem.yml index 1b0c6bd1..63bb5b04 100644 --- a/.github/workflows/mlkem.yml +++ b/.github/workflows/mlkem.yml @@ -47,6 +47,12 @@ jobs: - run: echo "RUST_TARGET_FLAG=" > $GITHUB_ENV if: ${{ matrix.bits == 64 }} + - run: echo 'EXCLUDE_FEATURES="--exclude-features simd256"' > $GITHUB_ENV + if: ${{ matrix.os == 'macos-latest' }} + + - run: echo 'EXCLUDE_FEATURES="--exclude-features simd128"' > $GITHUB_ENV + if: ${{ matrix.os != 'macos-latest' }} + - name: 🛠️ Setup Rust Nightly run: rustup toolchain install nightly @@ -150,6 +156,15 @@ jobs: cargo clean cargo test --features kyber --verbose $RUST_TARGET_FLAG + - name: 🏃🏻‍♀️ Cargo Check Features + run: | + cargo clean + cargo hack check --feature-powerset $EXCLUDE_FEATURES --verbose --no-dev-deps $RUST_TARGET_FLAG + + - name: 🏃🏻‍♀️ Cargo Test Features + run: | + cargo clean + cargo hack test --each-feature $EXCLUDE_FEATURES --verbose --no-dev-deps $RUST_TARGET_FLAG benchmarks: strategy: diff --git a/Cargo.toml b/Cargo.toml index 5c73a291..01ccd138 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,8 @@ members = [ "libcrux-kem", "libcrux-hmac", "libcrux-hkdf", - "libcrux-ecdh", "libcrux-psq", + "libcrux-ecdh", + "libcrux-psq", ] [workspace.package] diff --git a/libcrux-ml-dsa/src/hash_functions.rs b/libcrux-ml-dsa/src/hash_functions.rs index 33556541..0e9cab46 100644 --- a/libcrux-ml-dsa/src/hash_functions.rs +++ b/libcrux-ml-dsa/src/hash_functions.rs @@ -7,13 +7,13 @@ pub(crate) fn H(input: &[u8]) -> [u8; OUTPUT_LENGTH] } pub(crate) mod H_128 { - use libcrux_sha3::portable::{incremental, KeccakState1}; + use libcrux_sha3::portable::{incremental, KeccakState}; const BLOCK_SIZE: usize = 168; const FIVE_BLOCKS_SIZE: usize = BLOCK_SIZE * 5; #[inline(always)] - pub(crate) fn new(seed: [u8; 34]) -> KeccakState1 { + pub(crate) fn new(seed: [u8; 34]) -> KeccakState { let mut state = incremental::shake128_init(); incremental::shake128_absorb_final(&mut state, &seed); @@ -21,7 +21,7 @@ pub(crate) mod H_128 { } #[inline(always)] - pub(crate) fn squeeze_first_five_blocks(state: &mut KeccakState1) -> [u8; FIVE_BLOCKS_SIZE] { + pub(crate) fn squeeze_first_five_blocks(state: &mut KeccakState) -> [u8; FIVE_BLOCKS_SIZE] { let mut out = [0u8; FIVE_BLOCKS_SIZE]; incremental::shake128_squeeze_first_five_blocks(state, &mut out); @@ -29,7 +29,7 @@ pub(crate) mod H_128 { } #[inline(always)] - pub(crate) fn squeeze_next_block(state: &mut KeccakState1) -> [u8; BLOCK_SIZE] { + pub(crate) fn squeeze_next_block(state: &mut KeccakState) -> [u8; BLOCK_SIZE] { let mut out = [0u8; BLOCK_SIZE]; incremental::shake128_squeeze_next_block(state, &mut out); diff --git a/libcrux-ml-kem/Cargo.toml b/libcrux-ml-kem/Cargo.toml index 134a6d97..972207ef 100644 --- a/libcrux-ml-kem/Cargo.toml +++ b/libcrux-ml-kem/Cargo.toml @@ -73,3 +73,14 @@ required-features = ["mlkem768"] [[example]] name = "keygen" required-features = ["mlkem768"] + +[package.metadata."docs.rs"] +features = ["pre-verification", "kyber"] +rustdoc-args = ["--cfg", "doc_cfg"] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = [ + 'cfg(hax)', + 'cfg(eurydice)', + 'cfg(doc_cfg)', +] } diff --git a/libcrux-ml-kem/src/cfg.rs b/libcrux-ml-kem/src/cfg.rs index 4f611d02..af6c980d 100644 --- a/libcrux-ml-kem/src/cfg.rs +++ b/libcrux-ml-kem/src/cfg.rs @@ -4,6 +4,7 @@ macro_rules! cfg_verified { ($($item:item)*) => { $( #[cfg(not(feature = "pre-verification"))] + #[allow(missing_docs)] $item )* } diff --git a/libcrux-ml-kem/src/hash_functions.rs b/libcrux-ml-kem/src/hash_functions.rs index d2202964..7ab7b6ec 100644 --- a/libcrux-ml-kem/src/hash_functions.rs +++ b/libcrux-ml-kem/src/hash_functions.rs @@ -47,7 +47,7 @@ pub(crate) mod portable { shake128_absorb_final, shake128_init, shake128_squeeze_first_three_blocks, shake128_squeeze_next_block, }, - KeccakState1, + KeccakState, }; /// The state. @@ -55,7 +55,7 @@ pub(crate) mod portable { /// It's only used for SHAKE128. /// All other functions don't actually use any members. pub(crate) struct PortableHash { - shake128_state: [KeccakState1; K], + shake128_state: [KeccakState; K], } impl Hash for PortableHash { @@ -132,7 +132,7 @@ pub(crate) mod portable { pub(crate) mod avx2 { use super::*; use libcrux_sha3::{ - avx2::x4::{self, incremental::KeccakState4}, + avx2::x4::{self, incremental::KeccakState}, portable, }; @@ -141,7 +141,7 @@ pub(crate) mod avx2 { /// It's only used for SHAKE128. /// All other functions don't actually use any members. pub(crate) struct Simd256Hash { - shake128_state: KeccakState4, + shake128_state: KeccakState, } impl Hash for Simd256Hash { @@ -314,14 +314,14 @@ pub(crate) mod avx2 { /// A SIMD128 implementation of [`Hash`] for NEON pub(crate) mod neon { use super::*; - use libcrux_sha3::neon::x2::{self, incremental::KeccakState2}; + use libcrux_sha3::neon::x2::{self, incremental::KeccakState}; /// The state. /// /// It's only used for SHAKE128. /// All other functions don't actually use any members. pub(crate) struct Simd128Hash { - shake128_state: [KeccakState2; 2], + shake128_state: [KeccakState; 2], } impl Hash for Simd128Hash { diff --git a/libcrux-ml-kem/src/kem.rs b/libcrux-ml-kem/src/kem.rs index 01df82cb..e99d4d1e 100644 --- a/libcrux-ml-kem/src/kem.rs +++ b/libcrux-ml-kem/src/kem.rs @@ -2,27 +2,27 @@ #[allow(clippy::all)] pub mod kyber; -// TODO: These functions are currently exposed simply in order to make NIST KAT -// testing possible without an implementation of the NIST AES-CTR DRBG. Remove them -// (and change the visibility of the exported functions to pub(crate)) the -// moment we have an implementation of one. This is tracked by: -// https://github.com/cryspen/libcrux/issues/36 -#[cfg(feature = "tests")] -pub mod deterministic { - pub use super::kyber::kyber1024::decapsulate as kyber1024_decapsulate_derand; - pub use super::kyber::kyber1024::encapsulate as kyber1024_encapsulate_derand; - pub use super::kyber::kyber1024::generate_key_pair as kyber1024_generate_keypair_derand; - pub use super::kyber::kyber512::decapsulate as kyber512_decapsulate_derand; - pub use super::kyber::kyber512::encapsulate as kyber512_encapsulate_derand; - pub use super::kyber::kyber512::generate_key_pair as kyber512_generate_keypair_derand; - pub use super::kyber::kyber768::decapsulate as kyber768_decapsulate_derand; - pub use super::kyber::kyber768::encapsulate as kyber768_encapsulate_derand; - pub use super::kyber::kyber768::generate_key_pair as kyber768_generate_keypair_derand; -} +// // TODO: These functions are currently exposed simply in order to make NIST KAT +// // testing possible without an implementation of the NIST AES-CTR DRBG. Remove them +// // (and change the visibility of the exported functions to pub(crate)) the +// // moment we have an implementation of one. This is tracked by: +// // https://github.com/cryspen/libcrux/issues/36 +// #[cfg(feature = "tests")] +// pub mod deterministic { +// pub use super::kyber::kyber1024::decapsulate as kyber1024_decapsulate_derand; +// pub use super::kyber::kyber1024::encapsulate as kyber1024_encapsulate_derand; +// pub use super::kyber::kyber1024::generate_key_pair as kyber1024_generate_keypair_derand; +// pub use super::kyber::kyber512::decapsulate as kyber512_decapsulate_derand; +// pub use super::kyber::kyber512::encapsulate as kyber512_encapsulate_derand; +// pub use super::kyber::kyber512::generate_key_pair as kyber512_generate_keypair_derand; +// pub use super::kyber::kyber768::decapsulate as kyber768_decapsulate_derand; +// pub use super::kyber::kyber768::encapsulate as kyber768_encapsulate_derand; +// pub use super::kyber::kyber768::generate_key_pair as kyber768_generate_keypair_derand; +// } -#[cfg(feature = "tests")] -pub use kyber::{ - kyber1024::validate_public_key as ml_kem1024_validate_public_key, - kyber512::validate_public_key as ml_kem512_validate_public_key, - kyber768::validate_public_key as ml_kem768_validate_public_key, -}; +// #[cfg(feature = "tests")] +// pub use kyber::{ +// kyber1024::validate_public_key as ml_kem1024_validate_public_key, +// kyber512::validate_public_key as ml_kem512_validate_public_key, +// kyber768::validate_public_key as ml_kem768_validate_public_key, +// }; diff --git a/libcrux-ml-kem/src/kem/kyber.rs b/libcrux-ml-kem/src/kem/kyber.rs index 9b6457f2..e63fb7f9 100644 --- a/libcrux-ml-kem/src/kem/kyber.rs +++ b/libcrux-ml-kem/src/kem/kyber.rs @@ -22,8 +22,11 @@ mod serialize; mod types; // Variants +#[cfg(feature = "mlkem1024")] pub mod kyber1024; +#[cfg(feature = "mlkem512")] pub mod kyber512; +#[cfg(feature = "mlkem768")] pub mod kyber768; pub use types::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; diff --git a/libcrux-ml-kem/src/kem/kyber/hash_functions.rs b/libcrux-ml-kem/src/kem/kyber/hash_functions.rs index 309d2364..57e930c8 100644 --- a/libcrux-ml-kem/src/kem/kyber/hash_functions.rs +++ b/libcrux-ml-kem/src/kem/kyber/hash_functions.rs @@ -9,7 +9,7 @@ use libcrux_sha3::portable::{ shake128_absorb_final, shake128_init, shake128_squeeze_first_three_blocks, shake128_squeeze_next_block, }, - KeccakState1, + KeccakState, }; pub(crate) fn G(input: &[u8]) -> [u8; G_DIGEST_SIZE] { let mut digest = [0u8; G_DIGEST_SIZE]; @@ -44,7 +44,7 @@ pub(crate) fn PRF(input: &[u8]) -> [u8; LEN] { // } #[inline(always)] -pub(crate) fn absorb(input: [[u8; 34]; K]) -> [KeccakState1; K] { +pub(crate) fn absorb(input: [[u8; 34]; K]) -> [KeccakState; K] { debug_assert!(K == 2 || K == 3 || K == 4); let mut state = [shake128_init(); K]; @@ -71,7 +71,7 @@ const THREE_BLOCKS: usize = BLOCK_SIZE * 3; #[inline(always)] pub(crate) fn squeeze_three_blocks( - xof_state: &mut [KeccakState1; K], + xof_state: &mut [KeccakState; K], ) -> [[u8; THREE_BLOCKS]; K] { debug_assert!(K == 2 || K == 3 || K == 4); @@ -96,7 +96,7 @@ pub(crate) fn squeeze_three_blocks( #[inline(always)] pub(crate) fn squeeze_block( - xof_state: &mut [KeccakState1; K], + xof_state: &mut [KeccakState; K], ) -> [[u8; BLOCK_SIZE]; K] { debug_assert!(K == 2 || K == 3 || K == 4); @@ -111,6 +111,6 @@ pub(crate) fn squeeze_block( /// /// **NOTE:** That this needs to be done manually for now. #[inline(always)] -pub(crate) fn free_state(_xof_state: [KeccakState1; K]) { +pub(crate) fn free_state(_xof_state: [KeccakState; K]) { // xof_state.free_memory(); } diff --git a/libcrux-ml-kem/src/lib.rs b/libcrux-ml-kem/src/lib.rs index c1e69e8b..7099d895 100644 --- a/libcrux-ml-kem/src/lib.rs +++ b/libcrux-ml-kem/src/lib.rs @@ -54,10 +54,14 @@ //! to an, as yet, unverified implementation of Kyber as submitted in Round 3 of //! the NIST PQ competition. //! + #![no_std] +#![deny(missing_docs)] #![forbid(unsafe_code)] #![warn(rust_2018_idioms, unused_lifetimes, unused_qualifications)] #![allow(clippy::needless_range_loop)] +// Enable doc cfg feature for doc builds. They use nightly. +#![cfg_attr(doc_cfg, feature(doc_cfg))] /// Feature gating helper macros #[macro_use] @@ -100,13 +104,18 @@ cfg_pre_verification! { mod types; mod vector; - #[cfg(feature = "mlkem1024")] - pub mod mlkem1024; #[cfg(feature = "mlkem512")] + #[cfg_attr(docsrs, doc(cfg(feature = "mlkem512")))] pub mod mlkem512; + #[cfg(feature = "mlkem768")] + #[cfg_attr(docsrs, doc(cfg(feature = "mlkem768")))] pub mod mlkem768; + #[cfg(feature = "mlkem1024")] + #[cfg_attr(docsrs, doc(cfg(feature = "mlkem1024")))] + pub mod mlkem1024; + pub use constants::SHARED_SECRET_SIZE; pub use ind_cca::{MlKemSharedSecret, ENCAPS_SEED_SIZE, KEY_GENERATION_SEED_SIZE}; @@ -115,6 +124,8 @@ cfg_pre_verification! { pub use types::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; cfg_kyber! { + #[cfg(feature = "mlkem512")] + #[cfg_attr(docsrs, doc(cfg(all(feature = "kyber", feature = "mlkem512"))))] pub mod kyber512 { //! Kyber 512 (NIST PQC Round 3) pub use crate::mlkem512::generate_key_pair; @@ -123,6 +134,8 @@ cfg_pre_verification! { pub use crate::mlkem512::validate_public_key; } + #[cfg(feature = "mlkem768")] + #[cfg_attr(docsrs, doc(cfg(all(feature = "kyber", feature = "mlkem768"))))] pub mod kyber768 { //! Kyber 768 (NIST PQC Round 3) pub use crate::mlkem768::generate_key_pair; @@ -131,6 +144,8 @@ cfg_pre_verification! { pub use crate::mlkem768::validate_public_key; } + #[cfg(feature = "mlkem1024")] + #[cfg_attr(docsrs, doc(cfg(all(feature = "kyber", feature = "mlkem1024"))))] pub mod kyber1024 { //! Kyber 1024 (NIST PQC Round 3) pub use crate::mlkem1024::generate_key_pair; @@ -153,16 +168,19 @@ cfg_verified! { // Variants #[cfg(feature = "mlkem512")] + #[cfg_attr(docsrs, doc(cfg(feature = "mlkem512")))] pub mod mlkem512 { pub use crate::kem::kyber::kyber512::*; } #[cfg(feature = "mlkem768")] + #[cfg_attr(docsrs, doc(cfg(feature = "mlkem768")))] pub mod mlkem768 { pub use crate::kem::kyber::kyber768::*; } #[cfg(feature = "mlkem1024")] + #[cfg_attr(docsrs, doc(cfg(feature = "mlkem1024")))] pub mod mlkem1024 { pub use crate::kem::kyber::kyber1024::*; } diff --git a/libcrux-ml-kem/src/mlkem1024.rs b/libcrux-ml-kem/src/mlkem1024.rs index d1107b02..f5be07e8 100644 --- a/libcrux-ml-kem/src/mlkem1024.rs +++ b/libcrux-ml-kem/src/mlkem1024.rs @@ -42,7 +42,7 @@ pub type MlKem1024Ciphertext = MlKemCiphertext; pub type MlKem1024PrivateKey = MlKemPrivateKey; /// An ML-KEM 1024 Public key pub type MlKem1024PublicKey = MlKemPublicKey; -/// Am ML-KEM 1024 Key pair +/// An ML-KEM 1024 Key pair pub type MlKem1024KeyPair = MlKemKeyPair; // Instantiate the different functions. diff --git a/libcrux-ml-kem/src/mlkem512.rs b/libcrux-ml-kem/src/mlkem512.rs index b2c5e057..6e5ba361 100644 --- a/libcrux-ml-kem/src/mlkem512.rs +++ b/libcrux-ml-kem/src/mlkem512.rs @@ -40,7 +40,7 @@ pub type MlKem512Ciphertext = MlKemCiphertext; pub type MlKem512PrivateKey = MlKemPrivateKey; /// An ML-KEM 512 Public key pub type MlKem512PublicKey = MlKemPublicKey; -/// Am ML-KEM 512 Key pair +/// An ML-KEM 512 Key pair pub type MlKem512KeyPair = MlKemKeyPair; // Instantiate the different functions. diff --git a/libcrux-ml-kem/src/mlkem768.rs b/libcrux-ml-kem/src/mlkem768.rs index ae076d38..0b89b78d 100644 --- a/libcrux-ml-kem/src/mlkem768.rs +++ b/libcrux-ml-kem/src/mlkem768.rs @@ -41,7 +41,7 @@ pub type MlKem768Ciphertext = MlKemCiphertext; pub type MlKem768PrivateKey = MlKemPrivateKey; /// An ML-KEM 768 Public key pub type MlKem768PublicKey = MlKemPublicKey; -/// Am ML-KEM 768 Key pair +/// An ML-KEM 768 Key pair pub type MlKem768KeyPair = MlKemKeyPair; // Instantiate the different functions. @@ -227,9 +227,9 @@ pub fn validate_public_key(public_key: MlKem768PublicKey) -> Option assert!(mlkem512::validate_public_key(pk.try_into().unwrap()).is_none()), + "512" => assert!( + libcrux_ml_kem::mlkem512::validate_public_key(pk.try_into().unwrap()).is_none() + ), #[cfg(feature = "mlkem768")] - "768" => assert!(mlkem768::validate_public_key(pk.try_into().unwrap()).is_none()), + "768" => assert!( + libcrux_ml_kem::mlkem768::validate_public_key(pk.try_into().unwrap()).is_none() + ), #[cfg(feature = "mlkem1024")] - "1024" => assert!(mlkem1024::validate_public_key(pk.try_into().unwrap()).is_none()), + "1024" => assert!(libcrux_ml_kem::mlkem1024::validate_public_key( + pk.try_into().unwrap() + ) + .is_none()), _ => unreachable!(), }; } @@ -53,7 +52,7 @@ fn invalid_modulus_1024() { } fn file_name(p: &str) -> std::path::PathBuf { - Path::new("tests") + std::path::Path::new("tests") .join("kats") .join("invalid_modulus") .join(format!("ML-KEM-{}.txt", p)) diff --git a/libcrux-ml-kem/tests/nistkats.rs b/libcrux-ml-kem/tests/nistkats.rs index dae2921a..0089fd7f 100644 --- a/libcrux-ml-kem/tests/nistkats.rs +++ b/libcrux-ml-kem/tests/nistkats.rs @@ -1,11 +1,3 @@ -#[cfg(feature = "mlkem1024")] -use libcrux_ml_kem::mlkem1024; -#[cfg(feature = "mlkem512")] -use libcrux_ml_kem::mlkem512; -#[cfg(feature = "mlkem768")] -use libcrux_ml_kem::mlkem768; -#[cfg(all(feature = "kyber", feature = "pre-verification"))] -use libcrux_ml_kem::{kyber1024, kyber512, kyber768}; use serde::Deserialize; use serde_json; use std::{fs::File, io::BufReader, path::Path}; @@ -74,18 +66,18 @@ impl_nist_known_answer_tests!( mlkem512_nist_known_answer_tests, "mlkem", 512, - mlkem512::generate_key_pair, - mlkem512::encapsulate, - mlkem512::decapsulate + libcrux_ml_kem::mlkem512::generate_key_pair, + libcrux_ml_kem::mlkem512::encapsulate, + libcrux_ml_kem::mlkem512::decapsulate ); #[cfg(feature = "mlkem768")] impl_nist_known_answer_tests!( mlkem768_nist_known_answer_tests, "mlkem", 768, - mlkem768::generate_key_pair, - mlkem768::encapsulate, - mlkem768::decapsulate + libcrux_ml_kem::mlkem768::generate_key_pair, + libcrux_ml_kem::mlkem768::encapsulate, + libcrux_ml_kem::mlkem768::decapsulate ); #[cfg(feature = "mlkem1024")] @@ -93,9 +85,19 @@ impl_nist_known_answer_tests!( mlkem1024_nist_known_answer_tests, "mlkem", 1024, - mlkem1024::generate_key_pair, - mlkem1024::encapsulate, - mlkem1024::decapsulate + libcrux_ml_kem::mlkem1024::generate_key_pair, + libcrux_ml_kem::mlkem1024::encapsulate, + libcrux_ml_kem::mlkem1024::decapsulate +); + +#[cfg(all(feature = "mlkem512", feature = "pre-verification"))] +impl_nist_known_answer_tests!( + mlkem512_nist_kats_portable, + "mlkem", + 512, + libcrux_ml_kem::mlkem512::portable::generate_key_pair, + libcrux_ml_kem::mlkem512::portable::encapsulate, + libcrux_ml_kem::mlkem512::portable::decapsulate ); #[cfg(all(feature = "mlkem768", feature = "pre-verification"))] @@ -103,37 +105,47 @@ impl_nist_known_answer_tests!( mlkem768_nist_kats_portable, "mlkem", 768, - mlkem768::portable::generate_key_pair, - mlkem768::portable::encapsulate, - mlkem768::portable::decapsulate + libcrux_ml_kem::mlkem768::portable::generate_key_pair, + libcrux_ml_kem::mlkem768::portable::encapsulate, + libcrux_ml_kem::mlkem768::portable::decapsulate +); + +#[cfg(all(feature = "mlkem1024", feature = "pre-verification"))] +impl_nist_known_answer_tests!( + mlkem1024_nist_kats_portable, + "mlkem", + 1024, + libcrux_ml_kem::mlkem1024::portable::generate_key_pair, + libcrux_ml_kem::mlkem1024::portable::encapsulate, + libcrux_ml_kem::mlkem1024::portable::decapsulate ); -#[cfg(all(feature = "kyber", feature = "pre-verification"))] +#[cfg(all(feature = "mlkem512", feature = "kyber", feature = "pre-verification"))] impl_nist_known_answer_tests!( - kyber512_nist_known_answer_tests, + kyber512_nist_kats_portable, "kyber", 512, - kyber512::generate_key_pair, - kyber512::encapsulate, - kyber512::decapsulate + libcrux_ml_kem::kyber512::generate_key_pair, + libcrux_ml_kem::kyber512::encapsulate, + libcrux_ml_kem::kyber512::decapsulate ); -#[cfg(all(feature = "kyber", feature = "pre-verification"))] +#[cfg(all(feature = "mlkem768", feature = "kyber", feature = "pre-verification"))] impl_nist_known_answer_tests!( - kyber768_nist_known_answer_tests, + kyber768_nist_kats_portable, "kyber", 768, - kyber768::generate_key_pair, - kyber768::encapsulate, - kyber768::decapsulate + libcrux_ml_kem::kyber768::generate_key_pair, + libcrux_ml_kem::kyber768::encapsulate, + libcrux_ml_kem::kyber768::decapsulate ); -#[cfg(all(feature = "kyber", feature = "pre-verification"))] +#[cfg(all(feature = "mlkem1024", feature = "kyber", feature = "pre-verification"))] impl_nist_known_answer_tests!( - kyber1024_nist_known_answer_tests, + kyber1024_nist_kats_portable, "kyber", 1024, - kyber1024::generate_key_pair, - kyber1024::encapsulate, - kyber1024::decapsulate + libcrux_ml_kem::kyber1024::generate_key_pair, + libcrux_ml_kem::kyber1024::encapsulate, + libcrux_ml_kem::kyber1024::decapsulate ); diff --git a/libcrux-sha3/Cargo.toml b/libcrux-sha3/Cargo.toml index 2fe5dacc..5f13d2d9 100644 --- a/libcrux-sha3/Cargo.toml +++ b/libcrux-sha3/Cargo.toml @@ -30,3 +30,6 @@ harness = false criterion = "0.5.1" hex = "0.4.3" rand = "0.8.5" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(hax)', 'cfg(eurydice)'] } diff --git a/libcrux-sha3/src/generic_keccak.rs b/libcrux-sha3/src/generic_keccak.rs index ef63a654..ad8f52be 100644 --- a/libcrux-sha3/src/generic_keccak.rs +++ b/libcrux-sha3/src/generic_keccak.rs @@ -44,6 +44,7 @@ pub(crate) fn theta_rho>(s: &mut KeccakSta T::xor5(s.st[0][3], s.st[1][3], s.st[2][3], s.st[3][3], s.st[4][3]), T::xor5(s.st[0][4], s.st[1][4], s.st[2][4], s.st[3][4], s.st[4][4]), ]; + #[allow(clippy::identity_op)] let t: [T; 5] = [ T::rotate_left1_and_xor(c[(0 + 4) % 5], c[(0 + 1) % 5]), T::rotate_left1_and_xor(c[(1 + 4) % 5], c[(1 + 1) % 5]), @@ -89,7 +90,7 @@ const _PI: [usize; 24] = [ #[inline(always)] pub(crate) fn pi>(s: &mut KeccakState) { - let old = s.st.clone(); + let old = s.st; s.st[0][1] = old[1][1]; s.st[0][2] = old[2][2]; s.st[0][3] = old[3][3]; @@ -119,6 +120,8 @@ pub(crate) fn pi>(s: &mut KeccakState>(s: &mut KeccakState) { let old = s.st; + + #[allow(clippy::needless_range_loop)] for i in 0..5 { for j in 0..5 { s.st[i][j] = T::and_not_xor(s.st[i][j], old[i][(j + 2) % 5], old[i][(j + 1) % 5]); @@ -191,9 +194,9 @@ pub(crate) fn absorb_final< let last_len = last[0].len(); let mut blocks = [[0u8; 200]; N]; for i in 0..N { - blocks[i][0..last_len].copy_from_slice(&last[i]); + blocks[i][0..last_len].copy_from_slice(last[i]); blocks[i][last_len] = DELIM; - blocks[i][RATE - 1] = blocks[i][RATE - 1] | 128u8; + blocks[i][RATE - 1] |= 0x80; } T::load_block_full::(&mut s.st, blocks); keccakf1600(s) diff --git a/libcrux-sha3/src/lib.rs b/libcrux-sha3/src/lib.rs index ae6d2aa1..fca2dfd8 100644 --- a/libcrux-sha3/src/lib.rs +++ b/libcrux-sha3/src/lib.rs @@ -4,6 +4,8 @@ #![no_std] #![forbid(unsafe_code)] +#![deny(missing_docs)] + pub mod simd; mod generic_keccak; @@ -26,9 +28,16 @@ pub type Sha3_512Digest = [u8; 64]; #[cfg_attr(not(eurydice), derive(Copy, Clone, Debug, PartialEq))] #[repr(u32)] pub enum Algorithm { + /// SHA3 224 Sha224 = 1, + + /// SHA3 256 Sha256 = 2, + + /// SHA3 384 Sha384 = 3, + + /// SHA3 512 Sha512 = 4, } @@ -176,11 +185,12 @@ mod incremental {} /// A portable SHA3 implementations without platform dependent optimisations. pub mod portable { use super::*; - use generic_keccak::{keccak, KeccakState}; + use generic_keccak::{keccak, KeccakState as GenericState}; + /// The Keccak state for the incremental API. #[derive(Clone, Copy)] - pub struct KeccakState1 { - state: KeccakState<1, u64>, + pub struct KeccakState { + state: GenericState<1, u64>, } #[inline(always)] @@ -234,33 +244,33 @@ pub mod portable { /// Initialise the SHAKE state. #[inline(always)] - pub fn shake128_init() -> KeccakState1 { - KeccakState1 { - state: KeccakState::<1, u64>::new(), + pub fn shake128_init() -> KeccakState { + KeccakState { + state: GenericState::<1, u64>::new(), } } /// Absorb #[inline(always)] - pub fn shake128_absorb_final(s: &mut KeccakState1, data0: &[u8]) { + pub fn shake128_absorb_final(s: &mut KeccakState, data0: &[u8]) { absorb_final::<1, u64, 168, 0x1fu8>(&mut s.state, [data0]); } /// Squeeze three blocks #[inline(always)] - pub fn shake128_squeeze_first_three_blocks(s: &mut KeccakState1, out0: &mut [u8]) { + pub fn shake128_squeeze_first_three_blocks(s: &mut KeccakState, out0: &mut [u8]) { squeeze_first_three_blocks::<1, u64, 168>(&mut s.state, [out0]) } /// Squeeze five blocks #[inline(always)] - pub fn shake128_squeeze_first_five_blocks(s: &mut KeccakState1, out0: &mut [u8]) { + pub fn shake128_squeeze_first_five_blocks(s: &mut KeccakState, out0: &mut [u8]) { squeeze_first_five_blocks::<1, u64, 168>(&mut s.state, [out0]) } /// Squeeze another block #[inline(always)] - pub fn shake128_squeeze_next_block(s: &mut KeccakState1, out0: &mut [u8]) { + pub fn shake128_squeeze_next_block(s: &mut KeccakState, out0: &mut [u8]) { squeeze_next_block::<1, u64, 168>(&mut s.state, [out0]) } } @@ -416,24 +426,28 @@ pub mod neon { pub mod incremental { #[cfg(feature = "simd128")] use crate::generic_keccak::{ - absorb_final, squeeze_first_three_blocks, squeeze_next_block, KeccakState, + absorb_final, squeeze_first_three_blocks, squeeze_next_block, + KeccakState as GenericState, }; + /// The Keccak state for the incremental API. #[cfg(feature = "simd128")] - pub struct KeccakState2 { - state: KeccakState<2, crate::simd::arm64::uint64x2_t>, + pub struct KeccakState { + state: GenericState<2, crate::simd::arm64::uint64x2_t>, } + #[cfg(feature = "simd128")] - type KeccakState2Internal = KeccakState<2, crate::simd::arm64::uint64x2_t>; + type KeccakState2Internal = GenericState<2, crate::simd::arm64::uint64x2_t>; + #[allow(dead_code)] #[cfg(not(feature = "simd128"))] pub struct KeccakState2 { - state: [crate::portable::KeccakState1; 2], + state: [crate::portable::KeccakState; 2], } /// Initialise the `KeccakState2`. #[inline(always)] - pub fn shake128_init() -> KeccakState2 { + pub fn shake128_init() -> KeccakState { #[cfg(not(feature = "simd128"))] unimplemented!(); // XXX: These functions could alternatively implement the same with @@ -444,14 +458,15 @@ pub mod neon { // [s0, s1] // } #[cfg(feature = "simd128")] - KeccakState2 { + KeccakState { state: KeccakState2Internal::new(), } } + /// Shake128 absorb `data0` and `data1` in the [`KeccakState`] `s`. #[inline(always)] #[allow(unused_variables)] - pub fn shake128_absorb_final(s: &mut KeccakState2, data0: &[u8], data1: &[u8]) { + pub fn shake128_absorb_final(s: &mut KeccakState, data0: &[u8], data1: &[u8]) { #[cfg(not(feature = "simd128"))] unimplemented!(); // XXX: These functions could alternatively implement the same with @@ -474,7 +489,7 @@ pub mod neon { /// **PANICS** when `N` is not 2, 3, or 4. #[allow(unused_variables, non_snake_case)] #[inline(always)] - fn _shake128_absorb_finalxN(input: [[u8; 34]; N]) -> [KeccakState2; 2] { + fn _shake128_absorb_finalxN(input: [[u8; 34]; N]) -> [KeccakState; 2] { debug_assert!(N == 2 || N == 3 || N == 4); let mut state = [shake128_init(), shake128_init()]; @@ -496,10 +511,12 @@ pub mod neon { state } + /// Squeeze 2 times the first three blocks in parallel in the + /// [`KeccakState`] and return the output in `out0` and `out1`. #[allow(unused_variables)] #[inline(always)] pub fn shake128_squeeze_first_three_blocks( - s: &mut KeccakState2, + s: &mut KeccakState, out0: &mut [u8], out1: &mut [u8], ) { @@ -526,7 +543,7 @@ pub mod neon { #[allow(unused_variables, non_snake_case)] #[inline(always)] fn _shake128_squeeze3xN( - state: &mut [KeccakState2; 2], + state: &mut [KeccakState; 2], ) -> [[u8; LEN]; N] { debug_assert!(N == 2 || N == 3 || N == 4); @@ -575,10 +592,12 @@ pub mod neon { out } + /// Squeeze 2 times the next block in parallel in the + /// [`KeccakState`] and return the output in `out0` and `out1`. #[allow(unused_variables)] #[inline(always)] pub fn shake128_squeeze_next_block( - s: &mut KeccakState2, + s: &mut KeccakState, out0: &mut [u8], out1: &mut [u8], ) { @@ -605,7 +624,7 @@ pub mod neon { #[allow(unused_variables, non_snake_case)] #[inline(always)] fn _shake128_squeezexN( - state: &mut [KeccakState2; 2], + state: &mut [KeccakState; 2], ) -> [[u8; LEN]; N] { debug_assert!(N == 2 || N == 3 || N == 4); @@ -666,7 +685,7 @@ pub mod avx2 { use libcrux_intrinsics::avx2::*; /// Perform 4 SHAKE256 operations in parallel - #[allow(unused_variables)] // TODO: decide if we want to fall back here + #[allow(unused_variables, clippy::too_many_arguments)] // TODO: decide if we want to fall back here #[inline(always)] pub fn shake256( input0: &[u8], @@ -764,7 +783,8 @@ pub mod avx2 { pub mod incremental { #[cfg(feature = "simd256")] use crate::generic_keccak::{ - absorb_final, squeeze_first_three_blocks, squeeze_next_block, KeccakState, + absorb_final, squeeze_first_three_blocks, squeeze_next_block, + KeccakState as GenericState, }; #[cfg(feature = "simd256")] use libcrux_intrinsics::avx2::*; @@ -773,17 +793,21 @@ pub mod avx2 { pub struct KeccakState4 { state: KeccakState<4, Vec256>, } + + /// The Keccak state for the incremental API. #[allow(dead_code)] #[cfg(all(feature = "simd128", not(feature = "simd256")))] - pub struct KeccakState4 { - state: [crate::neon::x2::incremental::KeccakState2; 2], + pub struct KeccakState { + state: [crate::neon::x2::incremental::KeccakState; 2], } + + /// The Keccak state for the incremental API. #[cfg(not(any(feature = "simd256", feature = "simd128")))] - pub type KeccakState4 = [crate::portable::KeccakState1; 4]; + pub type KeccakState4 = [crate::portable::KeccakState; 4]; - /// Initialise the [`KeccakState4`]. + /// Initialise the [`KeccakState`]. #[inline(always)] - pub fn shake128_init() -> KeccakState4 { + pub fn shake128_init() -> KeccakState { #[cfg(not(feature = "simd256"))] unimplemented!(); // XXX: These functions could alternatively implement the same with @@ -803,15 +827,16 @@ pub mod avx2 { // [s0, s1, s2, s3] // } #[cfg(feature = "simd256")] - KeccakState4 { + KeccakState { state: KeccakState::new(), } } + /// Absorb #[inline(always)] #[allow(unused_variables)] // TODO: decide if we want to fall back here pub fn shake128_absorb_final( - s: &mut KeccakState4, + s: &mut KeccakState, data0: &[u8], data1: &[u8], data2: &[u8], @@ -851,7 +876,7 @@ pub mod avx2 { /// **PANICS** when `N` is not 2, 3, or 4. #[inline(always)] #[allow(unused_variables, non_snake_case)] - fn _shake128_absorb_finalxN(input: [[u8; 34]; N]) -> KeccakState4 { + fn _shake128_absorb_finalxN(input: [[u8; 34]; N]) -> KeccakState { debug_assert!(N == 2 || N == 3 || N == 4); let mut state = shake128_init(); @@ -877,10 +902,11 @@ pub mod avx2 { state } + /// Squeeze three blocks #[inline(always)] #[allow(unused_variables)] // TODO: decide if we want to fall back here pub fn shake128_squeeze_first_three_blocks( - s: &mut KeccakState4, + s: &mut KeccakState, out0: &mut [u8], out1: &mut [u8], out2: &mut [u8], @@ -924,7 +950,7 @@ pub mod avx2 { #[inline(always)] #[allow(unused_variables, non_snake_case)] fn _shake128_squeeze3xN( - state: &mut KeccakState4, + state: &mut KeccakState, ) -> [[u8; LEN]; N] { debug_assert!(N == 2 || N == 3 || N == 4); @@ -971,10 +997,11 @@ pub mod avx2 { out } + /// Squeeze another block #[inline(always)] #[allow(unused_variables)] // TODO: decide if we want to fall back here pub fn shake128_squeeze_next_block( - s: &mut KeccakState4, + s: &mut KeccakState, out0: &mut [u8], out1: &mut [u8], out2: &mut [u8], @@ -1015,7 +1042,7 @@ pub mod avx2 { #[allow(unused_variables, non_snake_case)] #[inline(always)] fn _shake128_squeezexN( - state: &mut KeccakState4, + state: &mut KeccakState, ) -> [[u8; LEN]; N] { debug_assert!(N == 2 || N == 3 || N == 4); diff --git a/sys/platform/Cargo.toml b/sys/platform/Cargo.toml index 6766bf9b..76b6405c 100644 --- a/sys/platform/Cargo.toml +++ b/sys/platform/Cargo.toml @@ -11,3 +11,6 @@ description = "Platform detection crate for libcrux." [dependencies] libc = "0.2.153" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(hax)', 'cfg(eurydice)'] } diff --git a/sys/platform/src/macos_arm.rs b/sys/platform/src/macos_arm.rs index 2edafdbd..01ff07be 100644 --- a/sys/platform/src/macos_arm.rs +++ b/sys/platform/src/macos_arm.rs @@ -6,7 +6,7 @@ use libc::{c_char, c_void, sysctlbyname, uname, utsname}; fn cstr(src: &[i8]) -> &str { // default to length if no `0` present let end = src.iter().position(|&c| c == 0).unwrap_or(src.len()); - unsafe { core::str::from_utf8_unchecked(core::mem::transmute(&src[0..end])) } + unsafe { core::str::from_utf8_unchecked(core::mem::transmute::<&[i8], &[u8]>(&src[0..end])) } } /// Check that we're actually on an ARM mac. From 193cc33f8c99e6a9a07b8831b850f0f037e08495 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 13:42:20 +0200 Subject: [PATCH 46/53] update hax extraction --- libcrux-ml-kem/hax.py | 8 ++++- libcrux-ml-kem/src/mlkem1024.rs | 9 ++--- libcrux-ml-kem/src/mlkem512.rs | 9 ++--- libcrux-ml-kem/src/mlkem768.rs | 9 ++--- .../Libcrux_sha3.Avx2.X4.Incremental.fsti | 32 +++++++++-------- .../Libcrux_sha3.Neon.X2.Incremental.fsti | 36 ++++++++++--------- .../Libcrux_sha3.Portable.Incremental.fsti | 18 +++++----- .../extraction/Libcrux_sha3.Portable.fsti | 3 +- .../fstar/extraction/Libcrux_sha3.Traits.fsti | 7 ++-- .../proofs/fstar/extraction/Libcrux_sha3.fsti | 23 +++--------- 10 files changed, 78 insertions(+), 76 deletions(-) diff --git a/libcrux-ml-kem/hax.py b/libcrux-ml-kem/hax.py index 037f0ae4..67c3c26e 100755 --- a/libcrux-ml-kem/hax.py +++ b/libcrux-ml-kem/hax.py @@ -101,11 +101,17 @@ def __call__(self, parser, args, values, option_string=None) -> None: ) # Extract ml-kem - include_str = "+** -libcrux_ml_kem::types::index_impls::**" + include_str = ( + "+** -libcrux_ml_kem::types::index_impls::** -libcrux_ml_kem::kem::**" + ) interface_include = "+**" cargo_hax_into = [ "cargo", "hax", + "-C", + "--features", + "pre-verification", + ";", "into", "-i", include_str, diff --git a/libcrux-ml-kem/src/mlkem1024.rs b/libcrux-ml-kem/src/mlkem1024.rs index f5be07e8..fc94f725 100644 --- a/libcrux-ml-kem/src/mlkem1024.rs +++ b/libcrux-ml-kem/src/mlkem1024.rs @@ -47,7 +47,8 @@ pub type MlKem1024KeyPair = MlKemKeyPair { + ($modp:ident, $p:path, $doc:expr) => { + #[doc = $doc] pub mod $modp { use super::*; use $p as p; @@ -200,11 +201,11 @@ macro_rules! instantiate { // Instantiations -instantiate! {portable, ind_cca::instantiations::portable} +instantiate! {portable, ind_cca::instantiations::portable, "Portable ML-KEM 1024"} #[cfg(feature = "simd256")] -instantiate! {avx2, ind_cca::instantiations::avx2} +instantiate! {avx2, ind_cca::instantiations::avx2, "AVX2 Optimised ML-KEM 1024"} #[cfg(feature = "simd128")] -instantiate! {neon, ind_cca::instantiations::neon} +instantiate! {neon, ind_cca::instantiations::neon, "Neon Optimised ML-KEM 1024"} /// Validate a public key. /// diff --git a/libcrux-ml-kem/src/mlkem512.rs b/libcrux-ml-kem/src/mlkem512.rs index 6e5ba361..9dadfc70 100644 --- a/libcrux-ml-kem/src/mlkem512.rs +++ b/libcrux-ml-kem/src/mlkem512.rs @@ -45,7 +45,8 @@ pub type MlKem512KeyPair = MlKemKeyPair { + ($modp:ident, $p:path, $doc:expr) => { + #[doc = $doc] pub mod $modp { use super::*; use $p as p; @@ -196,11 +197,11 @@ macro_rules! instantiate { // Instantiations -instantiate! {portable, ind_cca::instantiations::portable} +instantiate! {portable, ind_cca::instantiations::portable, "Portable ML-KEM 512"} #[cfg(feature = "simd256")] -instantiate! {avx2, ind_cca::instantiations::avx2} +instantiate! {avx2, ind_cca::instantiations::avx2, "AVX2 Optimised ML-KEM 512"} #[cfg(feature = "simd128")] -instantiate! {neon, ind_cca::instantiations::neon} +instantiate! {neon, ind_cca::instantiations::neon, "Neon Optimised ML-KEM 512"} /// Validate a public key. /// diff --git a/libcrux-ml-kem/src/mlkem768.rs b/libcrux-ml-kem/src/mlkem768.rs index 0b89b78d..7805ad8d 100644 --- a/libcrux-ml-kem/src/mlkem768.rs +++ b/libcrux-ml-kem/src/mlkem768.rs @@ -46,7 +46,8 @@ pub type MlKem768KeyPair = MlKemKeyPair { + ($modp:ident, $p:path, $doc:expr) => { + #[doc = $doc] pub mod $modp { use super::*; use $p as p; @@ -196,11 +197,11 @@ macro_rules! instantiate { // Instantiations -instantiate! {portable, ind_cca::instantiations::portable} +instantiate! {portable, ind_cca::instantiations::portable, "Portable ML-KEM 768"} #[cfg(feature = "simd256")] -instantiate! {avx2, ind_cca::instantiations::avx2} +instantiate! {avx2, ind_cca::instantiations::avx2, "AVX2 Optimised ML-KEM 768"} #[cfg(feature = "simd128")] -instantiate! {neon, ind_cca::instantiations::neon} +instantiate! {neon, ind_cca::instantiations::neon, "Neon Optimised ML-KEM 768"} /// Validate a public key. /// diff --git a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Avx2.X4.Incremental.fsti b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Avx2.X4.Incremental.fsti index 9fdd87ec..4fbf9ca9 100644 --- a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Avx2.X4.Incremental.fsti +++ b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Avx2.X4.Incremental.fsti @@ -3,42 +3,46 @@ module Libcrux_sha3.Avx2.X4.Incremental open Core open FStar.Mul -type t_KeccakState4 = { f_state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 (sz 2) } +/// The Keccak state for the incremental API. +type t_KeccakState = { f_state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) } /// Initialise the state and perform up to 4 absorbs at the same time, /// using two [`KeccakState4`]. /// **PANICS** when `N` is not 2, 3, or 4. val v__shake128_absorb_finalxN (v_N: usize) (input: t_Array (t_Array u8 (sz 34)) v_N) - : Prims.Pure t_KeccakState4 Prims.l_True (fun _ -> Prims.l_True) + : Prims.Pure t_KeccakState Prims.l_True (fun _ -> Prims.l_True) /// Squeeze up to 3 x 4 (N) blocks in parallel, using two [`KeccakState4`]. /// Each block is of size `LEN`. /// **PANICS** when `N` is not 2, 3, or 4. -val v__shake128_squeeze3xN (v_LEN v_N: usize) (state: t_KeccakState4) - : Prims.Pure (t_KeccakState4 & t_Array (t_Array u8 v_LEN) v_N) +val v__shake128_squeeze3xN (v_LEN v_N: usize) (state: t_KeccakState) + : Prims.Pure (t_KeccakState & t_Array (t_Array u8 v_LEN) v_N) Prims.l_True (fun _ -> Prims.l_True) /// Squeeze up to 4 (N) blocks in parallel, using two [`KeccakState4`]. /// Each block is of size `LEN`. /// **PANICS** when `N` is not 2, 3, or 4. -val v__shake128_squeezexN (v_LEN v_N: usize) (state: t_KeccakState4) - : Prims.Pure (t_KeccakState4 & t_Array (t_Array u8 v_LEN) v_N) +val v__shake128_squeezexN (v_LEN v_N: usize) (state: t_KeccakState) + : Prims.Pure (t_KeccakState & t_Array (t_Array u8 v_LEN) v_N) Prims.l_True (fun _ -> Prims.l_True) -val shake128_absorb_final (s: t_KeccakState4) (data0 data1 data2 data3: t_Slice u8) - : Prims.Pure t_KeccakState4 Prims.l_True (fun _ -> Prims.l_True) +/// Absorb +val shake128_absorb_final (s: t_KeccakState) (data0 data1 data2 data3: t_Slice u8) + : Prims.Pure t_KeccakState Prims.l_True (fun _ -> Prims.l_True) -/// Initialise the [`KeccakState4`]. -val shake128_init: Prims.unit -> Prims.Pure t_KeccakState4 Prims.l_True (fun _ -> Prims.l_True) +/// Initialise the [`KeccakState`]. +val shake128_init: Prims.unit -> Prims.Pure t_KeccakState Prims.l_True (fun _ -> Prims.l_True) -val shake128_squeeze_first_three_blocks (s: t_KeccakState4) (out0 out1 out2 out3: t_Slice u8) - : Prims.Pure (t_KeccakState4 & t_Slice u8 & t_Slice u8 & t_Slice u8 & t_Slice u8) +/// Squeeze three blocks +val shake128_squeeze_first_three_blocks (s: t_KeccakState) (out0 out1 out2 out3: t_Slice u8) + : Prims.Pure (t_KeccakState & t_Slice u8 & t_Slice u8 & t_Slice u8 & t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) -val shake128_squeeze_next_block (s: t_KeccakState4) (out0 out1 out2 out3: t_Slice u8) - : Prims.Pure (t_KeccakState4 & t_Slice u8 & t_Slice u8 & t_Slice u8 & t_Slice u8) +/// Squeeze another block +val shake128_squeeze_next_block (s: t_KeccakState) (out0 out1 out2 out3: t_Slice u8) + : Prims.Pure (t_KeccakState & t_Slice u8 & t_Slice u8 & t_Slice u8 & t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Neon.X2.Incremental.fsti b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Neon.X2.Incremental.fsti index c9ca03f5..064580f4 100644 --- a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Neon.X2.Incremental.fsti +++ b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Neon.X2.Incremental.fsti @@ -3,11 +3,8 @@ module Libcrux_sha3.Neon.X2.Incremental open Core open FStar.Mul -unfold -let t_KeccakState2Internal = - Libcrux_sha3.Generic_keccak.t_KeccakState (sz 2) Core.Core_arch.Arm_shared.Neon.t_uint64x2_t - -type t_KeccakState2 = { +/// The Keccak state for the incremental API. +type t_KeccakState = { f_state:Libcrux_sha3.Generic_keccak.t_KeccakState (sz 2) Core.Core_arch.Arm_shared.Neon.t_uint64x2_t } @@ -16,32 +13,37 @@ type t_KeccakState2 = { /// using two [`KeccakState2`]. /// **PANICS** when `N` is not 2, 3, or 4. val v__shake128_absorb_finalxN (v_N: usize) (input: t_Array (t_Array u8 (sz 34)) v_N) - : Prims.Pure (t_Array t_KeccakState2 (sz 2)) Prims.l_True (fun _ -> Prims.l_True) + : Prims.Pure (t_Array t_KeccakState (sz 2)) Prims.l_True (fun _ -> Prims.l_True) /// Squeeze up to 3 x 4 (N) blocks in parallel, using two [`KeccakState2`]. /// Each block is of size `LEN`. /// **PANICS** when `N` is not 2, 3, or 4. -val v__shake128_squeeze3xN (v_LEN v_N: usize) (state: t_Array t_KeccakState2 (sz 2)) - : Prims.Pure (t_Array t_KeccakState2 (sz 2) & t_Array (t_Array u8 v_LEN) v_N) +val v__shake128_squeeze3xN (v_LEN v_N: usize) (state: t_Array t_KeccakState (sz 2)) + : Prims.Pure (t_Array t_KeccakState (sz 2) & t_Array (t_Array u8 v_LEN) v_N) Prims.l_True (fun _ -> Prims.l_True) /// Squeeze up to 4 (N) blocks in parallel, using two [`KeccakState2`]. /// Each block is of size `LEN`. /// **PANICS** when `N` is not 2, 3, or 4. -val v__shake128_squeezexN (v_LEN v_N: usize) (state: t_Array t_KeccakState2 (sz 2)) - : Prims.Pure (t_Array t_KeccakState2 (sz 2) & t_Array (t_Array u8 v_LEN) v_N) +val v__shake128_squeezexN (v_LEN v_N: usize) (state: t_Array t_KeccakState (sz 2)) + : Prims.Pure (t_Array t_KeccakState (sz 2) & t_Array (t_Array u8 v_LEN) v_N) Prims.l_True (fun _ -> Prims.l_True) -val shake128_absorb_final (s: t_KeccakState2) (data0 data1: t_Slice u8) - : Prims.Pure t_KeccakState2 Prims.l_True (fun _ -> Prims.l_True) +/// Shake128 absorb `data0` and `data1` in the [`KeccakState`] `s`. +val shake128_absorb_final (s: t_KeccakState) (data0 data1: t_Slice u8) + : Prims.Pure t_KeccakState Prims.l_True (fun _ -> Prims.l_True) /// Initialise the `KeccakState2`. -val shake128_init: Prims.unit -> Prims.Pure t_KeccakState2 Prims.l_True (fun _ -> Prims.l_True) +val shake128_init: Prims.unit -> Prims.Pure t_KeccakState Prims.l_True (fun _ -> Prims.l_True) -val shake128_squeeze_first_three_blocks (s: t_KeccakState2) (out0 out1: t_Slice u8) - : Prims.Pure (t_KeccakState2 & t_Slice u8 & t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) +/// Squeeze 2 times the first three blocks in parallel in the +/// [`KeccakState`] and return the output in `out0` and `out1`. +val shake128_squeeze_first_three_blocks (s: t_KeccakState) (out0 out1: t_Slice u8) + : Prims.Pure (t_KeccakState & t_Slice u8 & t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) -val shake128_squeeze_next_block (s: t_KeccakState2) (out0 out1: t_Slice u8) - : Prims.Pure (t_KeccakState2 & t_Slice u8 & t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) +/// Squeeze 2 times the next block in parallel in the +/// [`KeccakState`] and return the output in `out0` and `out1`. +val shake128_squeeze_next_block (s: t_KeccakState) (out0 out1: t_Slice u8) + : Prims.Pure (t_KeccakState & t_Slice u8 & t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Portable.Incremental.fsti b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Portable.Incremental.fsti index 1bf58e63..9235132e 100644 --- a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Portable.Incremental.fsti +++ b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Portable.Incremental.fsti @@ -4,27 +4,27 @@ open Core open FStar.Mul /// Absorb -val shake128_absorb_final (s: Libcrux_sha3.Portable.t_KeccakState1) (data0: t_Slice u8) - : Prims.Pure Libcrux_sha3.Portable.t_KeccakState1 Prims.l_True (fun _ -> Prims.l_True) +val shake128_absorb_final (s: Libcrux_sha3.Portable.t_KeccakState) (data0: t_Slice u8) + : Prims.Pure Libcrux_sha3.Portable.t_KeccakState Prims.l_True (fun _ -> Prims.l_True) /// Initialise the SHAKE state. val shake128_init: Prims.unit - -> Prims.Pure Libcrux_sha3.Portable.t_KeccakState1 Prims.l_True (fun _ -> Prims.l_True) + -> Prims.Pure Libcrux_sha3.Portable.t_KeccakState Prims.l_True (fun _ -> Prims.l_True) /// Squeeze five blocks -val shake128_squeeze_first_five_blocks (s: Libcrux_sha3.Portable.t_KeccakState1) (out0: t_Slice u8) - : Prims.Pure (Libcrux_sha3.Portable.t_KeccakState1 & t_Slice u8) +val shake128_squeeze_first_five_blocks (s: Libcrux_sha3.Portable.t_KeccakState) (out0: t_Slice u8) + : Prims.Pure (Libcrux_sha3.Portable.t_KeccakState & t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) /// Squeeze three blocks -val shake128_squeeze_first_three_blocks (s: Libcrux_sha3.Portable.t_KeccakState1) (out0: t_Slice u8) - : Prims.Pure (Libcrux_sha3.Portable.t_KeccakState1 & t_Slice u8) +val shake128_squeeze_first_three_blocks (s: Libcrux_sha3.Portable.t_KeccakState) (out0: t_Slice u8) + : Prims.Pure (Libcrux_sha3.Portable.t_KeccakState & t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) /// Squeeze another block -val shake128_squeeze_next_block (s: Libcrux_sha3.Portable.t_KeccakState1) (out0: t_Slice u8) - : Prims.Pure (Libcrux_sha3.Portable.t_KeccakState1 & t_Slice u8) +val shake128_squeeze_next_block (s: Libcrux_sha3.Portable.t_KeccakState) (out0: t_Slice u8) + : Prims.Pure (Libcrux_sha3.Portable.t_KeccakState & t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Portable.fsti b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Portable.fsti index 4e914abb..06ea8588 100644 --- a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Portable.fsti +++ b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Portable.fsti @@ -23,4 +23,5 @@ val shake128 (digest data: t_Slice u8) val shake256 (digest data: t_Slice u8) : Prims.Pure (t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) -type t_KeccakState1 = { f_state:Libcrux_sha3.Generic_keccak.t_KeccakState (sz 1) u64 } +/// The Keccak state for the incremental API. +type t_KeccakState = { f_state:Libcrux_sha3.Generic_keccak.t_KeccakState (sz 1) u64 } diff --git a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Traits.fsti b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Traits.fsti index 60af4096..5ca1bdfc 100644 --- a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Traits.fsti +++ b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Traits.fsti @@ -11,8 +11,8 @@ let _ = /// A Keccak Item /// This holds the internal state and depends on the architecture. -class t_KeccakStateItem (v_Self: Type0) (v_N: usize) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_7919791445461910775:Libcrux_sha3.Traits.Internal.t_KeccakItem +class t_KeccakStateItem (#v_Self: Type0) (v_N: usize) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_1179490486619621168:Libcrux_sha3.Traits.Internal.t_KeccakItem v_Self v_N } @@ -23,5 +23,4 @@ let impl (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: Libcrux_sha3.Traits.Internal.t_KeccakItem v_T v_N) - : t_KeccakStateItem v_T v_N = - { _super_7919791445461910775 = FStar.Tactics.Typeclasses.solve; __marker_trait = () } + : t_KeccakStateItem #v_T v_N = { _super_1179490486619621168 = FStar.Tactics.Typeclasses.solve } diff --git a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.fsti b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.fsti index 9f4daa21..4ed67223 100644 --- a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.fsti +++ b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.fsti @@ -17,7 +17,7 @@ type t_Algorithm = | Algorithm_Sha512 : t_Algorithm [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_1: Core.Convert.t_From u32 t_Algorithm = +let impl_1: Core.Convert.t_From #u32 #t_Algorithm = { f_from_pre = (fun (v: t_Algorithm) -> true); f_from_post = (fun (v: t_Algorithm) (out: u32) -> true); @@ -35,21 +35,8 @@ let discriminant_Algorithm_Sha512: u32 = 4ul val t_Algorithm_cast_to_repr (x: t_Algorithm) : Prims.Pure u32 Prims.l_True (fun _ -> Prims.l_True) -/// A SHA3 224 Digest -unfold -let t_Sha3_224Digest = t_Array u8 (sz 28) - -/// A SHA3 256 Digest -unfold -let t_Sha3_256Digest = t_Array u8 (sz 32) - -/// A SHA3 384 Digest -unfold -let t_Sha3_384Digest = t_Array u8 (sz 48) - -/// A SHA3 512 Digest -unfold -let t_Sha3_512Digest = t_Array u8 (sz 64) +val from__panic_cold_explicit: Prims.unit + -> Prims.Pure Rust_primitives.Hax.t_Never Prims.l_True (fun _ -> Prims.l_True) /// Returns the output size of a digest. val digest_size (mode: t_Algorithm) : Prims.Pure usize Prims.l_True (fun _ -> Prims.l_True) @@ -99,7 +86,7 @@ val shake256 (v_BYTES: usize) (data: t_Slice u8) : Prims.Pure (t_Array u8 v_BYTES) Prims.l_True (fun _ -> Prims.l_True) [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl: Core.Convert.t_From t_Algorithm u32 = +let impl: Core.Convert.t_From #t_Algorithm #u32 = { f_from_pre = (fun (v: u32) -> true); f_from_post = (fun (v: u32) (out: t_Algorithm) -> true); @@ -112,7 +99,7 @@ let impl: Core.Convert.t_From t_Algorithm u32 = | 3ul -> Algorithm_Sha384 <: t_Algorithm | 4ul -> Algorithm_Sha512 <: t_Algorithm | _ -> - Rust_primitives.Hax.never_to_any (Core.Panicking.panic "explicit panic" + Rust_primitives.Hax.never_to_any (from__panic_cold_explicit () <: Rust_primitives.Hax.t_Never) } From d19b8975e7c927b177d6195ea24b4928403a6bde Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 14:09:57 +0200 Subject: [PATCH 47/53] fixup x64 and hax extract --- .../extraction/Libcrux_intrinsics.Avx2.fsti | 6 - libcrux-kem/Cargo.toml | 5 +- .../Libcrux_ml_kem.Constant_time_ops.fsti | 18 +- .../extraction/Libcrux_ml_kem.Constants.fsti | 20 +- .../Libcrux_ml_kem.Hash_functions.Avx2.fsti | 18 +- .../Libcrux_ml_kem.Hash_functions.Neon.fsti | 83 +- ...ibcrux_ml_kem.Hash_functions.Portable.fsti | 26 +- .../Libcrux_ml_kem.Hash_functions.fsti | 6 +- ...rux_ml_kem.Ind_cca.Instantiations.Avx2.fst | 5 +- ...ux_ml_kem.Ind_cca.Instantiations.Avx2.fsti | 19 +- ...ml_kem.Ind_cca.Instantiations.Portable.fst | 7 +- ...l_kem.Ind_cca.Instantiations.Portable.fsti | 19 +- .../Libcrux_ml_kem.Ind_cca.Multiplexing.fsti | 10 +- .../extraction/Libcrux_ml_kem.Ind_cca.fst | 46 +- .../extraction/Libcrux_ml_kem.Ind_cca.fsti | 175 +- .../extraction/Libcrux_ml_kem.Ind_cpa.fsti | 190 +- .../extraction/Libcrux_ml_kem.Matrix.fsti | 30 +- .../extraction/Libcrux_ml_kem.Mlkem1024.fsti | 75 +- .../extraction/Libcrux_ml_kem.Mlkem512.fsti | 75 +- .../extraction/Libcrux_ml_kem.Mlkem768.fsti | 81 +- .../extraction/Libcrux_ml_kem.Polynomial.fsti | 23 +- .../extraction/Libcrux_ml_kem.Sampling.fsti | 18 +- .../extraction/Libcrux_ml_kem.Serialize.fsti | 24 +- .../fstar/extraction/Libcrux_ml_kem.Types.fst | 14 + .../extraction/Libcrux_ml_kem.Types.fsti | 50 +- ...Libcrux_ml_kem.Vector.Avx2.Arithmetic.fsti | 26 +- .../Libcrux_ml_kem.Vector.Avx2.Compress.fsti | 6 +- .../Libcrux_ml_kem.Vector.Avx2.Ntt.fsti | 4 +- .../Libcrux_ml_kem.Vector.Avx2.Portable.fsti | 9 +- .../Libcrux_ml_kem.Vector.Avx2.Serialize.fsti | 16 +- .../Libcrux_ml_kem.Vector.Avx2.fsti | 2 +- ...ibcrux_ml_kem.Vector.Rej_sample_table.fsti | 2019 ++++++++++++++++- .../Libcrux_ml_kem.Vector.Traits.fsti | 10 +- .../extraction/Libcrux_ml_kem.Vector.fst | 23 +- .../extraction/Libcrux_ml_kem.Vector.fsti | 143 +- .../Libcrux_sha3.Avx2.X4.Incremental.fsti | 10 +- .../Libcrux_sha3.Neon.X2.Incremental.fsti | 5 +- libcrux-sha3/src/lib.rs | 18 +- 38 files changed, 2795 insertions(+), 539 deletions(-) diff --git a/libcrux-intrinsics/proofs/fstar/extraction/Libcrux_intrinsics.Avx2.fsti b/libcrux-intrinsics/proofs/fstar/extraction/Libcrux_intrinsics.Avx2.fsti index 2a049de1..166c93c2 100644 --- a/libcrux-intrinsics/proofs/fstar/extraction/Libcrux_intrinsics.Avx2.fsti +++ b/libcrux-intrinsics/proofs/fstar/extraction/Libcrux_intrinsics.Avx2.fsti @@ -3,12 +3,6 @@ module Libcrux_intrinsics.Avx2 open Core open FStar.Mul -unfold -let t_Vec128 = Core.Core_arch.X86.t____m128i - -unfold -let t_Vec256 = Core.Core_arch.X86.t____m256i - val mm256_add_epi16 (lhs rhs: Core.Core_arch.X86.t____m256i) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-kem/Cargo.toml b/libcrux-kem/Cargo.toml index a08600a6..b0497922 100644 --- a/libcrux-kem/Cargo.toml +++ b/libcrux-kem/Cargo.toml @@ -17,14 +17,11 @@ libcrux-sha3 = { version = "0.0.2-pre.2", path = "../libcrux-sha3" } libcrux-ecdh = { version = "0.0.2-pre.2", path = "../libcrux-ecdh" } rand = { version = "0.8" } - [features] -tests = [] # Expose functions for testing. +tests = [] # Expose functions for testing. kyber = ["libcrux-ml-kem/kyber"] pre-verification = ["libcrux-ml-kem/pre-verification"] - - [dev-dependencies] libcrux-kem = { version = "0.0.2-pre.2", path = "./", features = ["tests"] } libcrux = { version = "0.0.2-pre.2", path = "../", features = ["rand"] } diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Constant_time_ops.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Constant_time_ops.fsti index 560d2964..fa256358 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Constant_time_ops.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Constant_time_ops.fsti @@ -3,35 +3,35 @@ module Libcrux_ml_kem.Constant_time_ops open Core open FStar.Mul -/// Return 1 if the bytes of `lhs` and `rhs` do not exactly -/// match and 0 otherwise. -val compare_ciphertexts_in_constant_time (v_CIPHERTEXT_SIZE: usize) (lhs rhs: t_Slice u8) +/// Return 1 if `value` is not zero and 0 otherwise. +val is_non_zero (value: u8) : Prims.Pure u8 Prims.l_True (ensures fun result -> let result:u8 = result in - Hax_lib.implies (lhs =. rhs <: bool) + Hax_lib.implies (value =. 0uy <: bool) (fun temp_0_ -> let _:Prims.unit = temp_0_ in result =. 0uy <: bool) && - Hax_lib.implies (lhs <>. rhs <: bool) + Hax_lib.implies (value <>. 0uy <: bool) (fun temp_0_ -> let _:Prims.unit = temp_0_ in result =. 1uy <: bool)) -/// Return 1 if `value` is not zero and 0 otherwise. -val is_non_zero (value: u8) +/// Return 1 if the bytes of `lhs` and `rhs` do not exactly +/// match and 0 otherwise. +val compare_ciphertexts_in_constant_time (v_CIPHERTEXT_SIZE: usize) (lhs rhs: t_Slice u8) : Prims.Pure u8 Prims.l_True (ensures fun result -> let result:u8 = result in - Hax_lib.implies (value =. 0uy <: bool) + Hax_lib.implies (lhs =. rhs <: bool) (fun temp_0_ -> let _:Prims.unit = temp_0_ in result =. 0uy <: bool) && - Hax_lib.implies (value <>. 0uy <: bool) + Hax_lib.implies (lhs <>. rhs <: bool) (fun temp_0_ -> let _:Prims.unit = temp_0_ in result =. 1uy <: bool)) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Constants.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Constants.fsti index 210ffc32..76d143aa 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Constants.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Constants.fsti @@ -4,24 +4,24 @@ open Core open FStar.Mul /// Each field element needs floor(log_2(FIELD_MODULUS)) + 1 = 12 bits to represent -let v_BITS_PER_COEFFICIENT: usize = Rust_primitives.Hax.dropped_body +let v_BITS_PER_COEFFICIENT: usize = sz 12 + +/// Coefficients per ring element +let v_COEFFICIENTS_IN_RING_ELEMENT: usize = sz 256 /// Bits required per (uncompressed) ring element -let v_BITS_PER_RING_ELEMENT: usize = Rust_primitives.Hax.dropped_body +let v_BITS_PER_RING_ELEMENT: usize = v_COEFFICIENTS_IN_RING_ELEMENT *! sz 12 /// Bytes required per (uncompressed) ring element -let v_BYTES_PER_RING_ELEMENT: usize = Rust_primitives.Hax.dropped_body - -/// Coefficients per ring element -let v_COEFFICIENTS_IN_RING_ELEMENT: usize = Rust_primitives.Hax.dropped_body +let v_BYTES_PER_RING_ELEMENT: usize = v_BITS_PER_RING_ELEMENT /! sz 8 -let v_CPA_PKE_KEY_GENERATION_SEED_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_KEY_GENERATION_SEED_SIZE: usize = sz 32 /// SHA3 512 digest size -let v_G_DIGEST_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_G_DIGEST_SIZE: usize = sz 64 /// SHA3 256 digest size -let v_H_DIGEST_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_H_DIGEST_SIZE: usize = sz 32 /// The size of an ML-KEM shared secret. -let v_SHARED_SECRET_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_SHARED_SECRET_SIZE: usize = sz 32 diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Avx2.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Avx2.fsti index 2a80b014..d0edb5a6 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Avx2.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Avx2.fsti @@ -6,10 +6,10 @@ open FStar.Mul /// The state. /// It's only used for SHAKE128. /// All other functions don't actually use any members. -type t_Simd256Hash = { f_shake128_state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState4 } +type t_Simd256Hash = { f_shake128_state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd256Hash v_K = +let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash #t_Simd256Hash v_K = { f_G_pre = (fun (input: t_Slice u8) -> true); f_G_post = (fun (input: t_Slice u8) (out: t_Array u8 (sz 64)) -> true); @@ -201,13 +201,13 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd256Hash v_K = in () in - let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState4 = + let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState = Libcrux_sha3.Avx2.X4.Incremental.shake128_init () in - let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState4 = + let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState = match cast (v_K <: usize) <: u8 with | 2uy -> - let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState4 = + let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState = Libcrux_sha3.Avx2.X4.Incremental.shake128_absorb_final state (Rust_primitives.unsize (input.[ sz 0 ] <: t_Array u8 (sz 34)) <: t_Slice u8) (Rust_primitives.unsize (input.[ sz 1 ] <: t_Array u8 (sz 34)) <: t_Slice u8) @@ -216,7 +216,7 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd256Hash v_K = in state | 3uy -> - let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState4 = + let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState = Libcrux_sha3.Avx2.X4.Incremental.shake128_absorb_final state (Rust_primitives.unsize (input.[ sz 0 ] <: t_Array u8 (sz 34)) <: t_Slice u8) (Rust_primitives.unsize (input.[ sz 1 ] <: t_Array u8 (sz 34)) <: t_Slice u8) @@ -225,7 +225,7 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd256Hash v_K = in state | 4uy -> - let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState4 = + let state:Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState = Libcrux_sha3.Avx2.X4.Incremental.shake128_absorb_final state (Rust_primitives.unsize (input.[ sz 0 ] <: t_Array u8 (sz 34)) <: t_Slice u8) (Rust_primitives.unsize (input.[ sz 1 ] <: t_Array u8 (sz 34)) <: t_Slice u8) @@ -265,7 +265,7 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd256Hash v_K = let out1:t_Array u8 (sz 504) = Rust_primitives.Hax.repeat 0uy (sz 504) in let out2:t_Array u8 (sz 504) = Rust_primitives.Hax.repeat 0uy (sz 504) in let out3:t_Array u8 (sz 504) = Rust_primitives.Hax.repeat 0uy (sz 504) in - let tmp0, tmp1, tmp2, tmp3, tmp4:(Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState4 & + let tmp0, tmp1, tmp2, tmp3, tmp4:(Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState & t_Array u8 (sz 504) & t_Array u8 (sz 504) & t_Array u8 (sz 504) & @@ -349,7 +349,7 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd256Hash v_K = let out1:t_Array u8 (sz 168) = Rust_primitives.Hax.repeat 0uy (sz 168) in let out2:t_Array u8 (sz 168) = Rust_primitives.Hax.repeat 0uy (sz 168) in let out3:t_Array u8 (sz 168) = Rust_primitives.Hax.repeat 0uy (sz 168) in - let tmp0, tmp1, tmp2, tmp3, tmp4:(Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState4 & + let tmp0, tmp1, tmp2, tmp3, tmp4:(Libcrux_sha3.Avx2.X4.Incremental.t_KeccakState & t_Array u8 (sz 168) & t_Array u8 (sz 168) & t_Array u8 (sz 168) & diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Neon.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Neon.fsti index 6fda7a42..45f0d592 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Neon.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Neon.fsti @@ -7,11 +7,11 @@ open FStar.Mul /// It's only used for SHAKE128. /// All other functions don't actually use any members. type t_Simd128Hash = { - f_shake128_state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 (sz 2) + f_shake128_state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = +let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash #t_Simd128Hash v_K = { f_G_pre = (fun (input: t_Slice u8) -> true); f_G_post = (fun (input: t_Slice u8) (out: t_Array u8 (sz 64)) -> true); @@ -214,7 +214,7 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = in () in - let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 (sz 2) = + let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) = let list = [ Libcrux_sha3.Neon.X2.Incremental.shake128_init (); @@ -224,67 +224,67 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 2); Rust_primitives.Hax.array_of_list 2 list in - let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 (sz 2) = + let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) = match cast (v_K <: usize) <: u8 with | 2uy -> - let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 (sz 2) = + let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) = Rust_primitives.Hax.Monomorphized_update_at.update_at_usize state (sz 0) (Libcrux_sha3.Neon.X2.Incremental.shake128_absorb_final (state.[ sz 0 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) (Rust_primitives.unsize (input.[ sz 0 ] <: t_Array u8 (sz 34)) <: t_Slice u8) (Rust_primitives.unsize (input.[ sz 1 ] <: t_Array u8 (sz 34)) <: t_Slice u8) <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) in state | 3uy -> - let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 (sz 2) = + let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) = Rust_primitives.Hax.Monomorphized_update_at.update_at_usize state (sz 0) (Libcrux_sha3.Neon.X2.Incremental.shake128_absorb_final (state.[ sz 0 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) (Rust_primitives.unsize (input.[ sz 0 ] <: t_Array u8 (sz 34)) <: t_Slice u8) (Rust_primitives.unsize (input.[ sz 1 ] <: t_Array u8 (sz 34)) <: t_Slice u8) <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) in - let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 (sz 2) = + let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) = Rust_primitives.Hax.Monomorphized_update_at.update_at_usize state (sz 1) (Libcrux_sha3.Neon.X2.Incremental.shake128_absorb_final (state.[ sz 1 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) (Rust_primitives.unsize (input.[ sz 2 ] <: t_Array u8 (sz 34)) <: t_Slice u8) (Rust_primitives.unsize (input.[ sz 2 ] <: t_Array u8 (sz 34)) <: t_Slice u8) <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) in state | 4uy -> - let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 (sz 2) = + let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) = Rust_primitives.Hax.Monomorphized_update_at.update_at_usize state (sz 0) (Libcrux_sha3.Neon.X2.Incremental.shake128_absorb_final (state.[ sz 0 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) (Rust_primitives.unsize (input.[ sz 0 ] <: t_Array u8 (sz 34)) <: t_Slice u8) (Rust_primitives.unsize (input.[ sz 1 ] <: t_Array u8 (sz 34)) <: t_Slice u8) <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) in - let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 (sz 2) = + let state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) = Rust_primitives.Hax.Monomorphized_update_at.update_at_usize state (sz 1) (Libcrux_sha3.Neon.X2.Incremental.shake128_absorb_final (state.[ sz 1 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) (Rust_primitives.unsize (input.[ sz 2 ] <: t_Array u8 (sz 34)) <: t_Slice u8) (Rust_primitives.unsize (input.[ sz 3 ] <: t_Array u8 (sz 34)) <: t_Slice u8) <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) in state | _ -> state @@ -327,13 +327,13 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = t_Simd128Hash) = match cast (v_K <: usize) <: u8 with | 2uy -> - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 504) & t_Array u8 (sz 504)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_first_three_blocks (self .f_shake128_state.[ sz 0 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out0 out1 in @@ -365,13 +365,13 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = t_Array u8 (sz 504) & t_Simd128Hash) | 3uy -> - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 504) & t_Array u8 (sz 504)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_first_three_blocks (self .f_shake128_state.[ sz 0 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out0 out1 in @@ -390,13 +390,13 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = let out0:t_Array u8 (sz 504) = tmp1 in let out1:t_Array u8 (sz 504) = tmp2 in let _:Prims.unit = () in - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 504) & t_Array u8 (sz 504)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_first_three_blocks (self .f_shake128_state.[ sz 1 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out2 out3 in @@ -431,13 +431,13 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = t_Array u8 (sz 504) & t_Simd128Hash) | 4uy -> - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 504) & t_Array u8 (sz 504)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_first_three_blocks (self .f_shake128_state.[ sz 0 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out0 out1 in @@ -456,13 +456,13 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = let out0:t_Array u8 (sz 504) = tmp1 in let out1:t_Array u8 (sz 504) = tmp2 in let _:Prims.unit = () in - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 504) & t_Array u8 (sz 504)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_first_three_blocks (self .f_shake128_state.[ sz 1 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out2 out3 in @@ -544,13 +544,12 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = t_Simd128Hash) = match cast (v_K <: usize) <: u8 with | 2uy -> - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & - t_Array u8 (sz 168) & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 168) & t_Array u8 (sz 168)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_next_block (self.f_shake128_state.[ sz 0 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out0 out1 in @@ -582,13 +581,12 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = t_Array u8 (sz 168) & t_Simd128Hash) | 3uy -> - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & - t_Array u8 (sz 168) & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 168) & t_Array u8 (sz 168)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_next_block (self.f_shake128_state.[ sz 0 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out0 out1 in @@ -607,13 +605,12 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = let out0:t_Array u8 (sz 168) = tmp1 in let out1:t_Array u8 (sz 168) = tmp2 in let _:Prims.unit = () in - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & - t_Array u8 (sz 168) & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 168) & t_Array u8 (sz 168)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_next_block (self.f_shake128_state.[ sz 1 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out2 out3 in @@ -648,13 +645,12 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = t_Array u8 (sz 168) & t_Simd128Hash) | 4uy -> - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & - t_Array u8 (sz 168) & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 168) & t_Array u8 (sz 168)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_next_block (self.f_shake128_state.[ sz 0 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out0 out1 in @@ -673,13 +669,12 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash t_Simd128Hash v_K = let out0:t_Array u8 (sz 168) = tmp1 in let out1:t_Array u8 (sz 168) = tmp2 in let _:Prims.unit = () in - let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2 & - t_Array u8 (sz 168) & + let tmp0, tmp1, tmp2:(Libcrux_sha3.Neon.X2.Incremental.t_KeccakState & t_Array u8 (sz 168) & t_Array u8 (sz 168)) = Libcrux_sha3.Neon.X2.Incremental.shake128_squeeze_next_block (self.f_shake128_state.[ sz 1 ] <: - Libcrux_sha3.Neon.X2.Incremental.t_KeccakState2) + Libcrux_sha3.Neon.X2.Incremental.t_KeccakState) out2 out3 in diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Portable.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Portable.fsti index d76d909e..3ea14e98 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Portable.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.Portable.fsti @@ -7,11 +7,11 @@ open FStar.Mul /// It's only used for SHAKE128. /// All other functions don't actually use any members. type t_PortableHash (v_K: usize) = { - f_shake128_state:t_Array Libcrux_sha3.Portable.t_KeccakState1 v_K + f_shake128_state:t_Array Libcrux_sha3.Portable.t_KeccakState v_K } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash (t_PortableHash v_K) v_K = +let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash #(t_PortableHash v_K) v_K = { f_G_pre = (fun (input: t_Slice u8) -> true); f_G_post = (fun (input: t_Slice u8) (out: t_Array u8 (sz 64)) -> true); @@ -107,13 +107,13 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash (t_PortableHash v_K in () in - let state:t_Array Libcrux_sha3.Portable.t_KeccakState1 v_K = + let state:t_Array Libcrux_sha3.Portable.t_KeccakState v_K = Rust_primitives.Hax.repeat (Libcrux_sha3.Portable.Incremental.shake128_init () <: - Libcrux_sha3.Portable.t_KeccakState1) + Libcrux_sha3.Portable.t_KeccakState) v_K in - let state:t_Array Libcrux_sha3.Portable.t_KeccakState1 v_K = + let state:t_Array Libcrux_sha3.Portable.t_KeccakState v_K = Core.Iter.Traits.Iterator.f_fold (Core.Iter.Traits.Collect.f_into_iter #(Core.Ops.Range.t_Range usize) ({ Core.Ops.Range.f_start = sz 0; Core.Ops.Range.f_end = v_K } @@ -123,18 +123,18 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash (t_PortableHash v_K Core.Ops.Range.t_Range usize) state (fun state i -> - let state:t_Array Libcrux_sha3.Portable.t_KeccakState1 v_K = state in + let state:t_Array Libcrux_sha3.Portable.t_KeccakState v_K = state in let i:usize = i in Rust_primitives.Hax.Monomorphized_update_at.update_at_usize state i (Libcrux_sha3.Portable.Incremental.shake128_absorb_final (state.[ i ] <: - Libcrux_sha3.Portable.t_KeccakState1) + Libcrux_sha3.Portable.t_KeccakState) (Rust_primitives.unsize (input.[ i ] <: t_Array u8 (sz 34)) <: t_Slice u8) <: - Libcrux_sha3.Portable.t_KeccakState1) + Libcrux_sha3.Portable.t_KeccakState) <: - t_Array Libcrux_sha3.Portable.t_KeccakState1 v_K) + t_Array Libcrux_sha3.Portable.t_KeccakState v_K) in { f_shake128_state = state } <: t_PortableHash v_K); f_shake128_squeeze_three_blocks_pre = (fun (self: t_PortableHash v_K) -> true); @@ -178,11 +178,11 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash (t_PortableHash v_K (fun temp_0_ i -> let out, self:(t_Array (t_Array u8 (sz 504)) v_K & t_PortableHash v_K) = temp_0_ in let i:usize = i in - let tmp0, tmp1:(Libcrux_sha3.Portable.t_KeccakState1 & t_Array u8 (sz 504)) = + let tmp0, tmp1:(Libcrux_sha3.Portable.t_KeccakState & t_Array u8 (sz 504)) = Libcrux_sha3.Portable.Incremental.shake128_squeeze_first_three_blocks (self .f_shake128_state.[ i ] <: - Libcrux_sha3.Portable.t_KeccakState1) + Libcrux_sha3.Portable.t_KeccakState) (out.[ i ] <: t_Array u8 (sz 504)) in let self:t_PortableHash v_K = @@ -245,11 +245,11 @@ let impl (v_K: usize) : Libcrux_ml_kem.Hash_functions.t_Hash (t_PortableHash v_K (fun temp_0_ i -> let out, self:(t_Array (t_Array u8 (sz 168)) v_K & t_PortableHash v_K) = temp_0_ in let i:usize = i in - let tmp0, tmp1:(Libcrux_sha3.Portable.t_KeccakState1 & t_Array u8 (sz 168)) = + let tmp0, tmp1:(Libcrux_sha3.Portable.t_KeccakState & t_Array u8 (sz 168)) = Libcrux_sha3.Portable.Incremental.shake128_squeeze_next_block (self.f_shake128_state.[ i ] <: - Libcrux_sha3.Portable.t_KeccakState1) + Libcrux_sha3.Portable.t_KeccakState) (out.[ i ] <: t_Array u8 (sz 168)) in let self:t_PortableHash v_K = diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.fsti index 9c5c2c46..f4fd2612 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Hash_functions.fsti @@ -9,7 +9,7 @@ open FStar.Mul /// - AVX2 /// - NEON /// - Portable -class t_Hash (v_Self: Type0) (v_K: usize) = { +class t_Hash (#v_Self: Type0) (v_K: usize) = { f_G_pre:t_Slice u8 -> bool; f_G_post:t_Slice u8 -> t_Array u8 (sz 64) -> bool; f_G:x0: t_Slice u8 @@ -51,7 +51,7 @@ class t_Hash (v_Self: Type0) (v_K: usize) = { } /// The SHA3 block size. -let v_BLOCK_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_BLOCK_SIZE: usize = sz 168 /// The size of 3 SHA3 blocks. -let v_THREE_BLOCKS: usize = Rust_primitives.Hax.dropped_body +let v_THREE_BLOCKS: usize = v_BLOCK_SIZE *! sz 3 diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Avx2.fst b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Avx2.fst index 1b7adcd0..f82013fb 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Avx2.fst +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Avx2.fst @@ -7,6 +7,7 @@ let _ = (* This module has implicit dependencies, here we make them explicit. *) (* The implicit dependencies arise from typeclasses instances. *) let open Libcrux_ml_kem.Hash_functions.Avx2 in + let open Libcrux_ml_kem.Ind_cca in let open Libcrux_ml_kem.Vector.Avx2 in () @@ -21,7 +22,7 @@ let decapsulate v_VECTOR_V_COMPRESSION_FACTOR v_C1_BLOCK_SIZE v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE v_IMPLICIT_REJECTION_HASH_INPUT_SIZE #Libcrux_ml_kem.Vector.Avx2.t_SIMD256Vector #Libcrux_ml_kem.Hash_functions.Avx2.t_Simd256Hash - private_key ciphertext + #Libcrux_ml_kem.Ind_cca.t_MlKem private_key ciphertext let encapsulate (v_K v_CIPHERTEXT_SIZE v_PUBLIC_KEY_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE: @@ -33,7 +34,7 @@ let encapsulate v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE #Libcrux_ml_kem.Vector.Avx2.t_SIMD256Vector #Libcrux_ml_kem.Hash_functions.Avx2.t_Simd256Hash - public_key randomness + #Libcrux_ml_kem.Ind_cca.t_MlKem public_key randomness let validate_public_key (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Avx2.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Avx2.fsti index 5c35e737..50e6fd92 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Avx2.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Avx2.fsti @@ -3,11 +3,13 @@ module Libcrux_ml_kem.Ind_cca.Instantiations.Avx2 open Core open FStar.Mul -/// Portable public key validation -val validate_public_key - (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) - (public_key: t_Array u8 v_PUBLIC_KEY_SIZE) - : Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) +let _ = + (* This module has implicit dependencies, here we make them explicit. *) + (* The implicit dependencies arise from typeclasses instances. *) + let open Libcrux_ml_kem.Hash_functions.Avx2 in + let open Libcrux_ml_kem.Ind_cca in + let open Libcrux_ml_kem.Vector.Avx2 in + () /// Portable decapsulate val decapsulate @@ -17,7 +19,6 @@ val decapsulate (ciphertext: Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -/// Portable encapsualte val encapsulate (v_K v_CIPHERTEXT_SIZE v_PUBLIC_KEY_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE: usize) @@ -27,6 +28,12 @@ val encapsulate Prims.l_True (fun _ -> Prims.l_True) +/// Portable public key validation +val validate_public_key + (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) + (public_key: t_Array u8 v_PUBLIC_KEY_SIZE) + : Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + /// Portable generate key pair. val generate_keypair (v_K v_CPA_PRIVATE_KEY_SIZE v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE v_BYTES_PER_RING_ELEMENT v_ETA1 v_ETA1_RANDOMNESS_SIZE: diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Portable.fst b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Portable.fst index e94abdbc..1179aa8f 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Portable.fst +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Portable.fst @@ -7,6 +7,7 @@ let _ = (* This module has implicit dependencies, here we make them explicit. *) (* The implicit dependencies arise from typeclasses instances. *) let open Libcrux_ml_kem.Hash_functions.Portable in + let open Libcrux_ml_kem.Ind_cca in let open Libcrux_ml_kem.Vector in () @@ -21,7 +22,8 @@ let decapsulate v_VECTOR_V_COMPRESSION_FACTOR v_C1_BLOCK_SIZE v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE v_IMPLICIT_REJECTION_HASH_INPUT_SIZE #Libcrux_ml_kem.Vector.Portable.t_PortableVector - #(Libcrux_ml_kem.Hash_functions.Portable.t_PortableHash v_K) private_key ciphertext + #(Libcrux_ml_kem.Hash_functions.Portable.t_PortableHash v_K) #Libcrux_ml_kem.Ind_cca.t_MlKem + private_key ciphertext let encapsulate (v_K v_CIPHERTEXT_SIZE v_PUBLIC_KEY_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE: @@ -33,7 +35,8 @@ let encapsulate v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE #Libcrux_ml_kem.Vector.Portable.t_PortableVector - #(Libcrux_ml_kem.Hash_functions.Portable.t_PortableHash v_K) public_key randomness + #(Libcrux_ml_kem.Hash_functions.Portable.t_PortableHash v_K) #Libcrux_ml_kem.Ind_cca.t_MlKem + public_key randomness let validate_public_key (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Portable.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Portable.fsti index 417351f4..999e59e0 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Portable.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Instantiations.Portable.fsti @@ -3,11 +3,13 @@ module Libcrux_ml_kem.Ind_cca.Instantiations.Portable open Core open FStar.Mul -/// Portable public key validation -val validate_public_key - (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) - (public_key: t_Array u8 v_PUBLIC_KEY_SIZE) - : Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) +let _ = + (* This module has implicit dependencies, here we make them explicit. *) + (* The implicit dependencies arise from typeclasses instances. *) + let open Libcrux_ml_kem.Hash_functions.Portable in + let open Libcrux_ml_kem.Ind_cca in + let open Libcrux_ml_kem.Vector in + () /// Portable decapsulate val decapsulate @@ -17,7 +19,6 @@ val decapsulate (ciphertext: Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -/// Portable encapsualte val encapsulate (v_K v_CIPHERTEXT_SIZE v_PUBLIC_KEY_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE: usize) @@ -27,6 +28,12 @@ val encapsulate Prims.l_True (fun _ -> Prims.l_True) +/// Portable public key validation +val validate_public_key + (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) + (public_key: t_Array u8 v_PUBLIC_KEY_SIZE) + : Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + /// Portable generate key pair. val generate_keypair (v_K v_CPA_PRIVATE_KEY_SIZE v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE v_BYTES_PER_RING_ELEMENT v_ETA1 v_ETA1_RANDOMNESS_SIZE: diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Multiplexing.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Multiplexing.fsti index f94109b2..15f4b79b 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Multiplexing.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.Multiplexing.fsti @@ -3,11 +3,6 @@ module Libcrux_ml_kem.Ind_cca.Multiplexing open Core open FStar.Mul -val validate_public_key - (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) - (public_key: t_Array u8 v_PUBLIC_KEY_SIZE) - : Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) - val decapsulate (v_K v_SECRET_KEY_SIZE v_CPA_SECRET_KEY_SIZE v_PUBLIC_KEY_SIZE v_CIPHERTEXT_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_C1_BLOCK_SIZE v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize) @@ -24,6 +19,11 @@ val encapsulate Prims.l_True (fun _ -> Prims.l_True) +val validate_public_key + (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) + (public_key: t_Array u8 v_PUBLIC_KEY_SIZE) + : Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + val generate_keypair (v_K v_CPA_PRIVATE_KEY_SIZE v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE v_BYTES_PER_RING_ELEMENT v_ETA1 v_ETA1_RANDOMNESS_SIZE: usize) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.fst b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.fst index 0b2ab931..375453be 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.fst +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.fst @@ -157,13 +157,14 @@ let validate_public_key let decapsulate (v_K v_SECRET_KEY_SIZE v_CPA_SECRET_KEY_SIZE v_PUBLIC_KEY_SIZE v_CIPHERTEXT_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_C1_BLOCK_SIZE v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize) - (#v_Vector #v_Hasher: Type0) + (#v_Vector #v_Hasher #v_Scheme: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] - i2: + i3: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector) (#[FStar.Tactics.Typeclasses.tcresolve ()] - i3: + i4: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K) + (#[FStar.Tactics.Typeclasses.tcresolve ()] i5: t_Variant v_Scheme) (private_key: Libcrux_ml_kem.Types.t_MlKemPrivateKey v_SECRET_KEY_SIZE) (ciphertext: Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) = @@ -259,23 +260,41 @@ let decapsulate t_Slice u8) (Rust_primitives.unsize expected_ciphertext <: t_Slice u8) in - Libcrux_ml_kem.Constant_time_ops.select_shared_secret_in_constant_time shared_secret + let implicit_rejection_shared_secret:t_Array u8 (sz 32) = + f_kdf #v_Scheme + v_K + v_CIPHERTEXT_SIZE + #v_Hasher + (Rust_primitives.unsize implicit_rejection_shared_secret <: t_Slice u8) + ciphertext + in + let shared_secret:t_Array u8 (sz 32) = + f_kdf #v_Scheme v_K v_CIPHERTEXT_SIZE #v_Hasher shared_secret ciphertext + in + Libcrux_ml_kem.Constant_time_ops.select_shared_secret_in_constant_time (Rust_primitives.unsize shared_secret + + <: + t_Slice u8) (Rust_primitives.unsize implicit_rejection_shared_secret <: t_Slice u8) selector let encapsulate (v_K v_CIPHERTEXT_SIZE v_PUBLIC_KEY_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE: usize) - (#v_Vector #v_Hasher: Type0) + (#v_Vector #v_Hasher #v_Scheme: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] - i2: + i3: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector) (#[FStar.Tactics.Typeclasses.tcresolve ()] - i3: + i4: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K) + (#[FStar.Tactics.Typeclasses.tcresolve ()] i5: t_Variant v_Scheme) (public_key: Libcrux_ml_kem.Types.t_MlKemPublicKey v_PUBLIC_KEY_SIZE) (randomness: t_Array u8 (sz 32)) = + let randomness:t_Array u8 (sz 32) = + f_entropy_preprocess #v_Scheme v_K #v_Hasher (Rust_primitives.unsize randomness <: t_Slice u8) + in let (to_hash: t_Array u8 (sz 64)):t_Array u8 (sz 64) = Libcrux_ml_kem.Utils.into_padded_array (sz 64) (Rust_primitives.unsize randomness <: t_Slice u8) in @@ -323,14 +342,15 @@ let encapsulate <: t_Slice u8) randomness pseudorandomness in - let shared_secret_array:t_Array u8 (sz 32) = Rust_primitives.Hax.repeat 0uy (sz 32) in + let ciphertext:Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE = + Core.Convert.f_from #(Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) + #(t_Array u8 v_CIPHERTEXT_SIZE) + ciphertext + in let shared_secret_array:t_Array u8 (sz 32) = - Core.Slice.impl__copy_from_slice #u8 shared_secret_array shared_secret + f_kdf #v_Scheme v_K v_CIPHERTEXT_SIZE #v_Hasher shared_secret ciphertext in - Core.Convert.f_from #(Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) - #(t_Array u8 v_CIPHERTEXT_SIZE) - ciphertext, - shared_secret_array + ciphertext, shared_secret_array <: (Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE & t_Array u8 (sz 32)) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.fsti index 2731071c..5842b292 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cca.fsti @@ -7,19 +7,17 @@ let _ = (* This module has implicit dependencies, here we make them explicit. *) (* The implicit dependencies arise from typeclasses instances. *) let open Libcrux_ml_kem.Hash_functions in + let open Libcrux_ml_kem.Types in let open Libcrux_ml_kem.Vector.Traits in () -/// An ML-KEM shared secret. -/// A byte array of size [`SHARED_SECRET_SIZE`]. -unfold -let t_MlKemSharedSecret = t_Array u8 (sz 32) - /// Seed size for encapsulation -let v_ENCAPS_SEED_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_ENCAPS_SEED_SIZE: usize = Libcrux_ml_kem.Constants.v_SHARED_SECRET_SIZE /// Seed size for key generation -let v_KEY_GENERATION_SEED_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_KEY_GENERATION_SEED_SIZE: usize = + Libcrux_ml_kem.Constants.v_CPA_PKE_KEY_GENERATION_SEED_SIZE +! + Libcrux_ml_kem.Constants.v_SHARED_SECRET_SIZE /// Serialize the secret key. val serialize_kem_secret_key @@ -29,6 +27,13 @@ val serialize_kem_secret_key (private_key public_key implicit_rejection_value: t_Slice u8) : Prims.Pure (t_Array u8 v_SERIALIZED_KEY_LEN) Prims.l_True (fun _ -> Prims.l_True) +/// Implements [`Variant`], to perform the ML-KEM-specific actions +/// during encapsulation and decapsulation. +/// Specifically, +/// * during encapsulation, the initial randomness is used without prior hashing, +/// * the derivation of the shared secret does not include a hash of the ML-KEM ciphertext. +type t_MlKem = | MlKem : t_MlKem + val validate_public_key (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) (#v_Vector: Type0) @@ -36,12 +41,155 @@ val validate_public_key (public_key: t_Array u8 v_PUBLIC_KEY_SIZE) : Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) +/// This trait collects differences in specification between ML-KEM +/// (Draft FIPS 203) and the Round 3 CRYSTALS-Kyber submission in the +/// NIST PQ competition. +/// cf. FIPS 203 (Draft), section 1.3 +class t_Variant (#v_Self: Type0) = { + f_kdf_pre: + v_K: usize -> + v_CIPHERTEXT_SIZE: usize -> + #v_Hasher: Type0 -> + {| i1: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} -> + t_Slice u8 -> + Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE + -> bool; + f_kdf_post: + v_K: usize -> + v_CIPHERTEXT_SIZE: usize -> + #v_Hasher: Type0 -> + {| i1: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} -> + t_Slice u8 -> + Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE -> + t_Array u8 (sz 32) + -> bool; + f_kdf: + v_K: usize -> + v_CIPHERTEXT_SIZE: usize -> + #v_Hasher: Type0 -> + {| i1: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} -> + x0: t_Slice u8 -> + x1: Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE + -> Prims.Pure (t_Array u8 (sz 32)) + (f_kdf_pre v_K v_CIPHERTEXT_SIZE v_Hasher i1 x0 x1) + (fun result -> f_kdf_post v_K v_CIPHERTEXT_SIZE v_Hasher i1 x0 x1 result); + f_entropy_preprocess_pre: + v_K: usize -> + #v_Hasher: Type0 -> + {| i3: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} -> + t_Slice u8 + -> bool; + f_entropy_preprocess_post: + v_K: usize -> + #v_Hasher: Type0 -> + {| i3: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} -> + t_Slice u8 -> + t_Array u8 (sz 32) + -> bool; + f_entropy_preprocess: + v_K: usize -> + #v_Hasher: Type0 -> + {| i3: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} -> + x0: t_Slice u8 + -> Prims.Pure (t_Array u8 (sz 32)) + (f_entropy_preprocess_pre v_K v_Hasher i3 x0) + (fun result -> f_entropy_preprocess_post v_K v_Hasher i3 x0 result) +} + +[@@ FStar.Tactics.Typeclasses.tcinstance] +let impl: t_Variant #t_MlKem = + { + f_kdf_pre + = + (fun + (v_K: usize) + (v_CIPHERTEXT_SIZE: usize) + (#v_Hasher: Type0) + (#[FStar.Tactics.Typeclasses.tcresolve ()] + i1: + Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K) + (shared_secret: t_Slice u8) + (_: Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) + -> + true); + f_kdf_post + = + (fun + (v_K: usize) + (v_CIPHERTEXT_SIZE: usize) + (#v_Hasher: Type0) + (#[FStar.Tactics.Typeclasses.tcresolve ()] + i1: + Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K) + (shared_secret: t_Slice u8) + (_: Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) + (out: t_Array u8 (sz 32)) + -> + true); + f_kdf + = + (fun + (v_K: usize) + (v_CIPHERTEXT_SIZE: usize) + (#v_Hasher: Type0) + (#[FStar.Tactics.Typeclasses.tcresolve ()] + i1: + Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K) + (shared_secret: t_Slice u8) + (_: Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) + -> + Core.Result.impl__unwrap #(t_Array u8 (sz 32)) + #Core.Array.t_TryFromSliceError + (Core.Convert.f_try_into #(t_Slice u8) #(t_Array u8 (sz 32)) shared_secret + <: + Core.Result.t_Result (t_Array u8 (sz 32)) Core.Array.t_TryFromSliceError)); + f_entropy_preprocess_pre + = + (fun + (v_K: usize) + (#v_Hasher: Type0) + (#[FStar.Tactics.Typeclasses.tcresolve ()] + i3: + Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K) + (randomness: t_Slice u8) + -> + true); + f_entropy_preprocess_post + = + (fun + (v_K: usize) + (#v_Hasher: Type0) + (#[FStar.Tactics.Typeclasses.tcresolve ()] + i3: + Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K) + (randomness: t_Slice u8) + (out: t_Array u8 (sz 32)) + -> + true); + f_entropy_preprocess + = + fun + (v_K: usize) + (#v_Hasher: Type0) + (#[FStar.Tactics.Typeclasses.tcresolve ()] + i3: + Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K) + (randomness: t_Slice u8) + -> + Core.Result.impl__unwrap #(t_Array u8 (sz 32)) + #Core.Array.t_TryFromSliceError + (Core.Convert.f_try_into #(t_Slice u8) #(t_Array u8 (sz 32)) randomness + <: + Core.Result.t_Result (t_Array u8 (sz 32)) Core.Array.t_TryFromSliceError) + } + val decapsulate (v_K v_SECRET_KEY_SIZE v_CPA_SECRET_KEY_SIZE v_PUBLIC_KEY_SIZE v_CIPHERTEXT_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_C1_BLOCK_SIZE v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize) - (#v_Vector #v_Hasher: Type0) - {| i2: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - {| i3: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} + (#v_Vector #v_Hasher #v_Scheme: Type0) + {| i3: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + {| i4: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} + {| i5: t_Variant v_Scheme |} (private_key: Libcrux_ml_kem.Types.t_MlKemPrivateKey v_SECRET_KEY_SIZE) (ciphertext: Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) @@ -49,9 +197,10 @@ val decapsulate val encapsulate (v_K v_CIPHERTEXT_SIZE v_PUBLIC_KEY_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE: usize) - (#v_Vector #v_Hasher: Type0) - {| i2: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - {| i3: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} + (#v_Vector #v_Hasher #v_Scheme: Type0) + {| i3: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + {| i4: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} + {| i5: t_Variant v_Scheme |} (public_key: Libcrux_ml_kem.Types.t_MlKemPublicKey v_PUBLIC_KEY_SIZE) (randomness: t_Array u8 (sz 32)) : Prims.Pure (Libcrux_ml_kem.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE & t_Array u8 (sz 32)) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cpa.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cpa.fsti index 7b73f006..9a3df274 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cpa.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Ind_cpa.fsti @@ -10,32 +10,50 @@ let _ = let open Libcrux_ml_kem.Vector.Traits in () -/// This function implements Algorithm 14 of the -/// NIST FIPS 203 specification; this is the Kyber CPA-PKE decryption algorithm. -/// Algorithm 14 is reproduced below: -/// ```plaintext -/// Input: decryption key dkₚₖₑ ∈ 𝔹^{384k}. -/// Input: ciphertext c ∈ 𝔹^{32(dᵤk + dᵥ)}. -/// Output: message m ∈ 𝔹^{32}. -/// c₁ ← c[0 : 32dᵤk] -/// c₂ ← c[32dᵤk : 32(dᵤk + dᵥ)] -/// u ← Decompress_{dᵤ}(ByteDecode_{dᵤ}(c₁)) -/// v ← Decompress_{dᵥ}(ByteDecode_{dᵥ}(c₂)) -/// ŝ ← ByteDecode₁₂(dkₚₖₑ) -/// w ← v - NTT-¹(ŝᵀ ◦ NTT(u)) -/// m ← ByteEncode₁(Compress₁(w)) -/// return m -/// ``` -/// The NIST FIPS 203 standard can be found at -/// . -val decrypt - (v_K v_CIPHERTEXT_SIZE v_VECTOR_U_ENCODED_SIZE v_U_COMPRESSION_FACTOR v_V_COMPRESSION_FACTOR: - usize) +/// Sample a vector of ring elements from a centered binomial distribution. +val sample_ring_element_cbd + (v_K v_ETA2_RANDOMNESS_SIZE v_ETA2: usize) + (#v_Vector #v_Hasher: Type0) + {| i2: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + {| i3: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} + (prf_input: t_Array u8 (sz 33)) + (domain_separator: u8) + : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K & u8) + Prims.l_True + (fun _ -> Prims.l_True) + +/// Sample a vector of ring elements from a centered binomial distribution and +/// convert them into their NTT representations. +val sample_vector_cbd_then_ntt + (v_K v_ETA v_ETA_RANDOMNESS_SIZE: usize) + (#v_Vector #v_Hasher: Type0) + {| i2: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + {| i3: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} + (prf_input: t_Array u8 (sz 33)) + (domain_separator: u8) + : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K & u8) + Prims.l_True + (fun _ -> Prims.l_True) + +/// Call [`compress_then_serialize_ring_element_u`] on each ring element. +val compress_then_serialize_u + (v_K v_OUT_LEN v_COMPRESSION_FACTOR v_BLOCK_LEN: usize) + (#v_Vector: Type0) + {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + (input: t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) + (out: t_Slice u8) + : Prims.Pure (t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) + +/// Call [`deserialize_then_decompress_ring_element_u`] on each ring element +/// in the `ciphertext`. +val deserialize_then_decompress_u + (v_K v_CIPHERTEXT_SIZE v_U_COMPRESSION_FACTOR: usize) (#v_Vector: Type0) {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - (secret_key: t_Slice u8) (ciphertext: t_Array u8 v_CIPHERTEXT_SIZE) - : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) + : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) + Prims.l_True + (fun _ -> Prims.l_True) /// This function implements Algorithm 13 of the /// NIST FIPS 203 specification; this is the Kyber CPA-PKE encryption algorithm. @@ -83,6 +101,60 @@ val encrypt (randomness: t_Slice u8) : Prims.Pure (t_Array u8 v_CIPHERTEXT_SIZE) Prims.l_True (fun _ -> Prims.l_True) +/// Call [`deserialize_to_uncompressed_ring_element`] for each ring element. +val deserialize_secret_key + (v_K: usize) + (#v_Vector: Type0) + {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + (secret_key: t_Slice u8) + : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) + Prims.l_True + (fun _ -> Prims.l_True) + +/// This function implements Algorithm 14 of the +/// NIST FIPS 203 specification; this is the Kyber CPA-PKE decryption algorithm. +/// Algorithm 14 is reproduced below: +/// ```plaintext +/// Input: decryption key dkₚₖₑ ∈ 𝔹^{384k}. +/// Input: ciphertext c ∈ 𝔹^{32(dᵤk + dᵥ)}. +/// Output: message m ∈ 𝔹^{32}. +/// c₁ ← c[0 : 32dᵤk] +/// c₂ ← c[32dᵤk : 32(dᵤk + dᵥ)] +/// u ← Decompress_{dᵤ}(ByteDecode_{dᵤ}(c₁)) +/// v ← Decompress_{dᵥ}(ByteDecode_{dᵥ}(c₂)) +/// ŝ ← ByteDecode₁₂(dkₚₖₑ) +/// w ← v - NTT-¹(ŝᵀ ◦ NTT(u)) +/// m ← ByteEncode₁(Compress₁(w)) +/// return m +/// ``` +/// The NIST FIPS 203 standard can be found at +/// . +val decrypt + (v_K v_CIPHERTEXT_SIZE v_VECTOR_U_ENCODED_SIZE v_U_COMPRESSION_FACTOR v_V_COMPRESSION_FACTOR: + usize) + (#v_Vector: Type0) + {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + (secret_key: t_Slice u8) + (ciphertext: t_Array u8 v_CIPHERTEXT_SIZE) + : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) + +/// Call [`serialize_uncompressed_ring_element`] for each ring element. +val serialize_secret_key + (v_K v_OUT_LEN: usize) + (#v_Vector: Type0) + {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + (key: t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) + : Prims.Pure (t_Array u8 v_OUT_LEN) Prims.l_True (fun _ -> Prims.l_True) + +/// Concatenate `t` and `ρ` into the public key. +val serialize_public_key + (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) + (#v_Vector: Type0) + {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + (tt_as_ntt: t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) + (seed_for_a: t_Slice u8) + : Prims.Pure (t_Array u8 v_PUBLIC_KEY_SIZE) Prims.l_True (fun _ -> Prims.l_True) + /// This function implements most of Algorithm 12 of the /// NIST FIPS 203 specification; this is the Kyber CPA-PKE key generation algorithm. /// We say "most of" since Algorithm 12 samples the required randomness within @@ -126,75 +198,3 @@ val generate_keypair : Prims.Pure (t_Array u8 v_PRIVATE_KEY_SIZE & t_Array u8 v_PUBLIC_KEY_SIZE) Prims.l_True (fun _ -> Prims.l_True) - -/// Call [`compress_then_serialize_ring_element_u`] on each ring element. -val compress_then_serialize_u - (v_K v_OUT_LEN v_COMPRESSION_FACTOR v_BLOCK_LEN: usize) - (#v_Vector: Type0) - {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - (input: t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) - (out: t_Slice u8) - : Prims.Pure (t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) - -/// Call [`deserialize_to_uncompressed_ring_element`] for each ring element. -val deserialize_secret_key - (v_K: usize) - (#v_Vector: Type0) - {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - (secret_key: t_Slice u8) - : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) - Prims.l_True - (fun _ -> Prims.l_True) - -/// Call [`deserialize_then_decompress_ring_element_u`] on each ring element -/// in the `ciphertext`. -val deserialize_then_decompress_u - (v_K v_CIPHERTEXT_SIZE v_U_COMPRESSION_FACTOR: usize) - (#v_Vector: Type0) - {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - (ciphertext: t_Array u8 v_CIPHERTEXT_SIZE) - : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) - Prims.l_True - (fun _ -> Prims.l_True) - -/// Sample a vector of ring elements from a centered binomial distribution. -val sample_ring_element_cbd - (v_K v_ETA2_RANDOMNESS_SIZE v_ETA2: usize) - (#v_Vector #v_Hasher: Type0) - {| i2: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - {| i3: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} - (prf_input: t_Array u8 (sz 33)) - (domain_separator: u8) - : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K & u8) - Prims.l_True - (fun _ -> Prims.l_True) - -/// Sample a vector of ring elements from a centered binomial distribution and -/// convert them into their NTT representations. -val sample_vector_cbd_then_ntt - (v_K v_ETA v_ETA_RANDOMNESS_SIZE: usize) - (#v_Vector #v_Hasher: Type0) - {| i2: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - {| i3: Libcrux_ml_kem.Hash_functions.t_Hash v_Hasher v_K |} - (prf_input: t_Array u8 (sz 33)) - (domain_separator: u8) - : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K & u8) - Prims.l_True - (fun _ -> Prims.l_True) - -/// Concatenate `t` and `ρ` into the public key. -val serialize_public_key - (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) - (#v_Vector: Type0) - {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - (tt_as_ntt: t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) - (seed_for_a: t_Slice u8) - : Prims.Pure (t_Array u8 v_PUBLIC_KEY_SIZE) Prims.l_True (fun _ -> Prims.l_True) - -/// Call [`serialize_uncompressed_ring_element`] for each ring element. -val serialize_secret_key - (v_K v_OUT_LEN: usize) - (#v_Vector: Type0) - {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - (key: t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) - : Prims.Pure (t_Array u8 v_OUT_LEN) Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Matrix.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Matrix.fsti index 9b53942d..dce9ae91 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Matrix.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Matrix.fsti @@ -23,21 +23,6 @@ val compute_As_plus_e Prims.l_True (fun _ -> Prims.l_True) -/// The following functions compute various expressions involving -/// vectors and matrices. The computation of these expressions has been -/// abstracted away into these functions in order to save on loop iterations. -/// Compute v − InverseNTT(sᵀ ◦ NTT(u)) -val compute_message - (v_K: usize) - (#v_Vector: Type0) - {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - (v: Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) - (secret_as_ntt u_as_ntt: - t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) - : Prims.Pure (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) - Prims.l_True - (fun _ -> Prims.l_True) - /// Compute InverseNTT(tᵀ ◦ r̂) + e₂ + message val compute_ring_element_v (v_K: usize) @@ -61,6 +46,21 @@ val compute_vector_u Prims.l_True (fun _ -> Prims.l_True) +/// The following functions compute various expressions involving +/// vectors and matrices. The computation of these expressions has been +/// abstracted away into these functions in order to save on loop iterations. +/// Compute v − InverseNTT(sᵀ ◦ NTT(u)) +val compute_message + (v_K: usize) + (#v_Vector: Type0) + {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + (v: Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) + (secret_as_ntt u_as_ntt: + t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) + : Prims.Pure (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) + Prims.l_True + (fun _ -> Prims.l_True) + val sample_matrix_A (v_K: usize) (#v_Vector #v_Hasher: Type0) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem1024.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem1024.fsti index f8c25b6f..cbeae42d 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem1024.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem1024.fsti @@ -3,47 +3,64 @@ module Libcrux_ml_kem.Mlkem1024 open Core open FStar.Mul -let v_C1_BLOCK_SIZE_1024_: usize = Rust_primitives.Hax.dropped_body +let v_ETA1: usize = sz 2 -let v_C1_SIZE_1024_: usize = Rust_primitives.Hax.dropped_body +let v_ETA1_RANDOMNESS_SIZE: usize = v_ETA1 *! sz 64 -let v_C2_SIZE_1024_: usize = Rust_primitives.Hax.dropped_body +let v_ETA2: usize = sz 2 -let v_CPA_PKE_CIPHERTEXT_SIZE_1024_: usize = Rust_primitives.Hax.dropped_body +let v_ETA2_RANDOMNESS_SIZE: usize = v_ETA2 *! sz 64 -let v_CPA_PKE_PUBLIC_KEY_SIZE_1024_: usize = Rust_primitives.Hax.dropped_body +let v_RANK_1024_: usize = sz 4 -let v_CPA_PKE_SECRET_KEY_SIZE_1024_: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_SECRET_KEY_SIZE_1024_: usize = + ((v_RANK_1024_ *! Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT <: usize) *! + Libcrux_ml_kem.Constants.v_BITS_PER_COEFFICIENT + <: + usize) /! + sz 8 -let v_ETA1: usize = Rust_primitives.Hax.dropped_body +let v_RANKED_BYTES_PER_RING_ELEMENT_1024_: usize = + (v_RANK_1024_ *! Libcrux_ml_kem.Constants.v_BITS_PER_RING_ELEMENT <: usize) /! sz 8 -let v_ETA1_RANDOMNESS_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_T_AS_NTT_ENCODED_SIZE_1024_: usize = + ((v_RANK_1024_ *! Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT <: usize) *! + Libcrux_ml_kem.Constants.v_BITS_PER_COEFFICIENT + <: + usize) /! + sz 8 -let v_ETA2: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_PUBLIC_KEY_SIZE_1024_: usize = v_T_AS_NTT_ENCODED_SIZE_1024_ +! sz 32 -let v_ETA2_RANDOMNESS_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_SECRET_KEY_SIZE_1024_: usize = + ((v_CPA_PKE_SECRET_KEY_SIZE_1024_ +! v_CPA_PKE_PUBLIC_KEY_SIZE_1024_ <: usize) +! + Libcrux_ml_kem.Constants.v_H_DIGEST_SIZE + <: + usize) +! + Libcrux_ml_kem.Constants.v_SHARED_SECRET_SIZE -let v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_VECTOR_U_COMPRESSION_FACTOR_1024_: usize = sz 11 -let v_RANKED_BYTES_PER_RING_ELEMENT_1024_: usize = Rust_primitives.Hax.dropped_body +let v_C1_BLOCK_SIZE_1024_: usize = + (Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT *! v_VECTOR_U_COMPRESSION_FACTOR_1024_ + <: + usize) /! + sz 8 -let v_RANK_1024_: usize = Rust_primitives.Hax.dropped_body +let v_C1_SIZE_1024_: usize = v_C1_BLOCK_SIZE_1024_ *! v_RANK_1024_ -let v_SECRET_KEY_SIZE_1024_: usize = Rust_primitives.Hax.dropped_body +let v_VECTOR_V_COMPRESSION_FACTOR_1024_: usize = sz 5 -let v_T_AS_NTT_ENCODED_SIZE_1024_: usize = Rust_primitives.Hax.dropped_body +let v_C2_SIZE_1024_: usize = + (Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT *! v_VECTOR_V_COMPRESSION_FACTOR_1024_ + <: + usize) /! + sz 8 -let v_VECTOR_U_COMPRESSION_FACTOR_1024_: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_CIPHERTEXT_SIZE_1024_: usize = v_C1_SIZE_1024_ +! v_C2_SIZE_1024_ -let v_VECTOR_V_COMPRESSION_FACTOR_1024_: usize = Rust_primitives.Hax.dropped_body - -/// An ML-KEM 1024 Ciphertext -unfold -let t_MlKem1024Ciphertext = Libcrux_ml_kem.Types.t_MlKemCiphertext (sz 1568) - -/// An ML-KEM 1024 Private key -unfold -let t_MlKem1024PrivateKey = Libcrux_ml_kem.Types.t_MlKemPrivateKey (sz 3168) +let v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = + Libcrux_ml_kem.Constants.v_SHARED_SECRET_SIZE +! v_CPA_PKE_CIPHERTEXT_SIZE_1024_ /// Decapsulate ML-KEM 1024 /// Generates an [`MlKemSharedSecret`]. @@ -53,10 +70,6 @@ val decapsulate (ciphertext: Libcrux_ml_kem.Types.t_MlKemCiphertext (sz 1568)) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -/// An ML-KEM 1024 Public key -unfold -let t_MlKem1024PublicKey = Libcrux_ml_kem.Types.t_MlKemPublicKey (sz 1568) - /// Encapsulate ML-KEM 1024 /// Generates an ([`MlKem1024Ciphertext`], [`MlKemSharedSecret`]) tuple. /// The input is a reference to an [`MlKem1024PublicKey`] and [`SHARED_SECRET_SIZE`] @@ -75,10 +88,6 @@ val validate_public_key (public_key: Libcrux_ml_kem.Types.t_MlKemPublicKey (sz 1 Prims.l_True (fun _ -> Prims.l_True) -/// Am ML-KEM 1024 Key pair -unfold -let t_MlKem1024KeyPair = Libcrux_ml_kem.Types.t_MlKemKeyPair (sz 3168) (sz 1568) - /// Generate ML-KEM 1024 Key Pair /// Generate an ML-KEM key pair. The input is a byte array of size /// [`KEY_GENERATION_SEED_SIZE`]. diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem512.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem512.fsti index 155d70c2..eda388fe 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem512.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem512.fsti @@ -3,47 +3,64 @@ module Libcrux_ml_kem.Mlkem512 open Core open FStar.Mul -let v_C1_BLOCK_SIZE_512_: usize = Rust_primitives.Hax.dropped_body +let v_ETA1: usize = sz 3 -let v_C1_SIZE_512_: usize = Rust_primitives.Hax.dropped_body +let v_ETA1_RANDOMNESS_SIZE: usize = v_ETA1 *! sz 64 -let v_C2_SIZE_512_: usize = Rust_primitives.Hax.dropped_body +let v_ETA2: usize = sz 2 -let v_CPA_PKE_CIPHERTEXT_SIZE_512_: usize = Rust_primitives.Hax.dropped_body +let v_ETA2_RANDOMNESS_SIZE: usize = v_ETA2 *! sz 64 -let v_CPA_PKE_PUBLIC_KEY_SIZE_512_: usize = Rust_primitives.Hax.dropped_body +let v_RANK_512_: usize = sz 2 -let v_CPA_PKE_SECRET_KEY_SIZE_512_: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_SECRET_KEY_SIZE_512_: usize = + ((v_RANK_512_ *! Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT <: usize) *! + Libcrux_ml_kem.Constants.v_BITS_PER_COEFFICIENT + <: + usize) /! + sz 8 -let v_ETA1: usize = Rust_primitives.Hax.dropped_body +let v_RANKED_BYTES_PER_RING_ELEMENT_512_: usize = + (v_RANK_512_ *! Libcrux_ml_kem.Constants.v_BITS_PER_RING_ELEMENT <: usize) /! sz 8 -let v_ETA1_RANDOMNESS_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_T_AS_NTT_ENCODED_SIZE_512_: usize = + ((v_RANK_512_ *! Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT <: usize) *! + Libcrux_ml_kem.Constants.v_BITS_PER_COEFFICIENT + <: + usize) /! + sz 8 -let v_ETA2: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_PUBLIC_KEY_SIZE_512_: usize = v_T_AS_NTT_ENCODED_SIZE_512_ +! sz 32 -let v_ETA2_RANDOMNESS_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_SECRET_KEY_SIZE_512_: usize = + ((v_CPA_PKE_SECRET_KEY_SIZE_512_ +! v_CPA_PKE_PUBLIC_KEY_SIZE_512_ <: usize) +! + Libcrux_ml_kem.Constants.v_H_DIGEST_SIZE + <: + usize) +! + Libcrux_ml_kem.Constants.v_SHARED_SECRET_SIZE -let v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_VECTOR_U_COMPRESSION_FACTOR_512_: usize = sz 10 -let v_RANKED_BYTES_PER_RING_ELEMENT_512_: usize = Rust_primitives.Hax.dropped_body +let v_C1_BLOCK_SIZE_512_: usize = + (Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT *! v_VECTOR_U_COMPRESSION_FACTOR_512_ + <: + usize) /! + sz 8 -let v_RANK_512_: usize = Rust_primitives.Hax.dropped_body +let v_C1_SIZE_512_: usize = v_C1_BLOCK_SIZE_512_ *! v_RANK_512_ -let v_SECRET_KEY_SIZE_512_: usize = Rust_primitives.Hax.dropped_body +let v_VECTOR_V_COMPRESSION_FACTOR_512_: usize = sz 4 -let v_T_AS_NTT_ENCODED_SIZE_512_: usize = Rust_primitives.Hax.dropped_body +let v_C2_SIZE_512_: usize = + (Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT *! v_VECTOR_V_COMPRESSION_FACTOR_512_ + <: + usize) /! + sz 8 -let v_VECTOR_U_COMPRESSION_FACTOR_512_: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_CIPHERTEXT_SIZE_512_: usize = v_C1_SIZE_512_ +! v_C2_SIZE_512_ -let v_VECTOR_V_COMPRESSION_FACTOR_512_: usize = Rust_primitives.Hax.dropped_body - -/// An ML-KEM 512 Ciphertext -unfold -let t_MlKem512Ciphertext = Libcrux_ml_kem.Types.t_MlKemCiphertext (sz 768) - -/// An ML-KEM 512 Private key -unfold -let t_MlKem512PrivateKey = Libcrux_ml_kem.Types.t_MlKemPrivateKey (sz 1632) +let v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = + Libcrux_ml_kem.Constants.v_SHARED_SECRET_SIZE +! v_CPA_PKE_CIPHERTEXT_SIZE_512_ /// Decapsulate ML-KEM 512 /// Generates an [`MlKemSharedSecret`]. @@ -53,10 +70,6 @@ val decapsulate (ciphertext: Libcrux_ml_kem.Types.t_MlKemCiphertext (sz 768)) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -/// An ML-KEM 512 Public key -unfold -let t_MlKem512PublicKey = Libcrux_ml_kem.Types.t_MlKemPublicKey (sz 800) - /// Encapsulate ML-KEM 512 /// Generates an ([`MlKem512Ciphertext`], [`MlKemSharedSecret`]) tuple. /// The input is a reference to an [`MlKem512PublicKey`] and [`SHARED_SECRET_SIZE`] @@ -75,10 +88,6 @@ val validate_public_key (public_key: Libcrux_ml_kem.Types.t_MlKemPublicKey (sz 8 Prims.l_True (fun _ -> Prims.l_True) -/// Am ML-KEM 512 Key pair -unfold -let t_MlKem512KeyPair = Libcrux_ml_kem.Types.t_MlKemKeyPair (sz 1632) (sz 800) - /// Generate ML-KEM 512 Key Pair /// Generate an ML-KEM key pair. The input is a byte array of size /// [`KEY_GENERATION_SEED_SIZE`]. diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem768.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem768.fsti index 6260bb2f..733e4752 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem768.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Mlkem768.fsti @@ -3,47 +3,64 @@ module Libcrux_ml_kem.Mlkem768 open Core open FStar.Mul -let v_C1_BLOCK_SIZE_768_: usize = Rust_primitives.Hax.dropped_body +let v_ETA1: usize = sz 2 -let v_C1_SIZE_768_: usize = Rust_primitives.Hax.dropped_body +let v_ETA1_RANDOMNESS_SIZE: usize = v_ETA1 *! sz 64 -let v_C2_SIZE_768_: usize = Rust_primitives.Hax.dropped_body +let v_ETA2: usize = sz 2 -let v_CPA_PKE_CIPHERTEXT_SIZE_768_: usize = Rust_primitives.Hax.dropped_body +let v_ETA2_RANDOMNESS_SIZE: usize = v_ETA2 *! sz 64 -let v_CPA_PKE_PUBLIC_KEY_SIZE_768_: usize = Rust_primitives.Hax.dropped_body +let v_RANK_768_: usize = sz 3 -let v_CPA_PKE_SECRET_KEY_SIZE_768_: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_SECRET_KEY_SIZE_768_: usize = + ((v_RANK_768_ *! Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT <: usize) *! + Libcrux_ml_kem.Constants.v_BITS_PER_COEFFICIENT + <: + usize) /! + sz 8 -let v_ETA1: usize = Rust_primitives.Hax.dropped_body +let v_RANKED_BYTES_PER_RING_ELEMENT_768_: usize = + (v_RANK_768_ *! Libcrux_ml_kem.Constants.v_BITS_PER_RING_ELEMENT <: usize) /! sz 8 -let v_ETA1_RANDOMNESS_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_T_AS_NTT_ENCODED_SIZE_768_: usize = + ((v_RANK_768_ *! Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT <: usize) *! + Libcrux_ml_kem.Constants.v_BITS_PER_COEFFICIENT + <: + usize) /! + sz 8 -let v_ETA2: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_PUBLIC_KEY_SIZE_768_: usize = v_T_AS_NTT_ENCODED_SIZE_768_ +! sz 32 -let v_ETA2_RANDOMNESS_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_SECRET_KEY_SIZE_768_: usize = + ((v_CPA_PKE_SECRET_KEY_SIZE_768_ +! v_CPA_PKE_PUBLIC_KEY_SIZE_768_ <: usize) +! + Libcrux_ml_kem.Constants.v_H_DIGEST_SIZE + <: + usize) +! + Libcrux_ml_kem.Constants.v_SHARED_SECRET_SIZE -let v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = Rust_primitives.Hax.dropped_body +let v_VECTOR_U_COMPRESSION_FACTOR_768_: usize = sz 10 -let v_RANKED_BYTES_PER_RING_ELEMENT_768_: usize = Rust_primitives.Hax.dropped_body +let v_C1_BLOCK_SIZE_768_: usize = + (Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT *! v_VECTOR_U_COMPRESSION_FACTOR_768_ + <: + usize) /! + sz 8 -let v_RANK_768_: usize = Rust_primitives.Hax.dropped_body +let v_C1_SIZE_768_: usize = v_C1_BLOCK_SIZE_768_ *! v_RANK_768_ -let v_SECRET_KEY_SIZE_768_: usize = Rust_primitives.Hax.dropped_body +let v_VECTOR_V_COMPRESSION_FACTOR_768_: usize = sz 4 -let v_T_AS_NTT_ENCODED_SIZE_768_: usize = Rust_primitives.Hax.dropped_body +let v_C2_SIZE_768_: usize = + (Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT *! v_VECTOR_V_COMPRESSION_FACTOR_768_ + <: + usize) /! + sz 8 -let v_VECTOR_U_COMPRESSION_FACTOR_768_: usize = Rust_primitives.Hax.dropped_body +let v_CPA_PKE_CIPHERTEXT_SIZE_768_: usize = v_C1_SIZE_768_ +! v_C2_SIZE_768_ -let v_VECTOR_V_COMPRESSION_FACTOR_768_: usize = Rust_primitives.Hax.dropped_body - -/// An ML-KEM 768 Ciphertext -unfold -let t_MlKem768Ciphertext = Libcrux_ml_kem.Types.t_MlKemCiphertext (sz 1088) - -/// An ML-KEM 768 Private key -unfold -let t_MlKem768PrivateKey = Libcrux_ml_kem.Types.t_MlKemPrivateKey (sz 2400) +let v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = + Libcrux_ml_kem.Constants.v_SHARED_SECRET_SIZE +! v_CPA_PKE_CIPHERTEXT_SIZE_768_ /// Decapsulate ML-KEM 768 /// Generates an [`MlKemSharedSecret`]. @@ -53,10 +70,6 @@ val decapsulate (ciphertext: Libcrux_ml_kem.Types.t_MlKemCiphertext (sz 1088)) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -/// An ML-KEM 768 Public key -unfold -let t_MlKem768PublicKey = Libcrux_ml_kem.Types.t_MlKemPublicKey (sz 1184) - /// Encapsulate ML-KEM 768 /// Generates an ([`MlKem768Ciphertext`], [`MlKemSharedSecret`]) tuple. /// The input is a reference to an [`MlKem768PublicKey`] and [`SHARED_SECRET_SIZE`] @@ -75,19 +88,15 @@ val validate_public_key (public_key: Libcrux_ml_kem.Types.t_MlKemPublicKey (sz 1 Prims.l_True (fun _ -> Prims.l_True) -/// Am ML-KEM 768 Key pair -unfold -let t_MlKem768KeyPair = Libcrux_ml_kem.Types.t_MlKemKeyPair (sz 2400) (sz 1184) - /// Generate ML-KEM 768 Key Pair /// Generate an ML-KEM key pair. The input is a byte array of size /// [`KEY_GENERATION_SEED_SIZE`]. /// This function uses CPU feature detection to pick the most efficient version /// on each platform. To use a specific version with your own feature detection /// use one of the following -/// - [`generate_key_pair_avx2`] -/// - [`generate_key_pair_neon`] -/// - [`generate_key_pair_portable`] +/// - `generate_key_pair_avx2` +/// - `generate_key_pair_neon` +/// - `generate_key_pair_portable` /// This function returns an [`MlKem768KeyPair`]. val generate_key_pair (randomness: t_Array u8 (sz 64)) : Prims.Pure (Libcrux_ml_kem.Types.t_MlKemKeyPair (sz 2400) (sz 1184)) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Polynomial.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Polynomial.fsti index 80bc1336..51dae0e1 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Polynomial.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Polynomial.fsti @@ -9,9 +9,28 @@ let _ = let open Libcrux_ml_kem.Vector.Traits in () -let v_VECTORS_IN_RING_ELEMENT: usize = Rust_primitives.Hax.dropped_body +let v_ZETAS_TIMES_MONTGOMERY_R: t_Array i16 (sz 128) = + let list = + [ + (-1044s); (-758s); (-359s); (-1517s); 1493s; 1422s; 287s; 202s; (-171s); 622s; 1577s; 182s; + 962s; (-1202s); (-1474s); 1468s; 573s; (-1325s); 264s; 383s; (-829s); 1458s; (-1602s); (-130s); + (-681s); 1017s; 732s; 608s; (-1542s); 411s; (-205s); (-1571s); 1223s; 652s; (-552s); 1015s; + (-1293s); 1491s; (-282s); (-1544s); 516s; (-8s); (-320s); (-666s); (-1618s); (-1162s); 126s; + 1469s; (-853s); (-90s); (-271s); 830s; 107s; (-1421s); (-247s); (-951s); (-398s); 961s; + (-1508s); (-725s); 448s; (-1065s); 677s; (-1275s); (-1103s); 430s; 555s; 843s; (-1251s); 871s; + 1550s; 105s; 422s; 587s; 177s; (-235s); (-291s); (-460s); 1574s; 1653s; (-246s); 778s; 1159s; + (-147s); (-777s); 1483s; (-602s); 1119s; (-1590s); 644s; (-872s); 349s; 418s; 329s; (-156s); + (-75s); 817s; 1097s; 603s; 610s; 1322s; (-1285s); (-1465s); 384s; (-1215s); (-136s); 1218s; + (-1335s); (-874s); 220s; (-1187s); (-1659s); (-1185s); (-1530s); (-1278s); 794s; (-1510s); + (-854s); (-870s); 478s; (-108s); (-308s); 996s; 991s; 958s; (-1460s); 1522s; 1628s + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 128); + Rust_primitives.Hax.array_of_list 128 list -let v_ZETAS_TIMES_MONTGOMERY_R: t_Array i16 (sz 128) = Rust_primitives.Hax.dropped_body +let v_VECTORS_IN_RING_ELEMENT: usize = + Libcrux_ml_kem.Constants.v_COEFFICIENTS_IN_RING_ELEMENT /! + Libcrux_ml_kem.Vector.Traits.v_FIELD_ELEMENTS_IN_VECTOR type t_PolynomialRingElement (v_Vector: Type0) {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Sampling.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Sampling.fsti index 2f9d5a51..5f5ac19d 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Sampling.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Sampling.fsti @@ -54,15 +54,6 @@ val sample_from_uniform_distribution_next Prims.l_True (fun _ -> Prims.l_True) -val sample_from_binomial_distribution - (v_ETA: usize) - (#v_Vector: Type0) - {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - (randomness: t_Slice u8) - : Prims.Pure (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) - Prims.l_True - (fun _ -> Prims.l_True) - /// Given a series of uniformly random bytes in `randomness`, for some number `eta`, /// the `sample_from_binomial_distribution_{eta}` functions sample /// a ring element from a binomial distribution centered at 0 that uses two sets @@ -117,6 +108,15 @@ val sample_from_binomial_distribution_3_ (requires (Core.Slice.impl__len #u8 randomness <: usize) =. (sz 3 *! sz 64 <: usize)) (fun _ -> Prims.l_True) +val sample_from_binomial_distribution + (v_ETA: usize) + (#v_Vector: Type0) + {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + (randomness: t_Slice u8) + : Prims.Pure (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) + Prims.l_True + (fun _ -> Prims.l_True) + val sample_from_xof (v_K: usize) (#v_Vector #v_Hasher: Type0) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Serialize.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Serialize.fsti index b7aa994d..f4e2ef81 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Serialize.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Serialize.fsti @@ -58,18 +58,6 @@ val compress_then_serialize_ring_element_v (out: t_Slice u8) : Prims.Pure (t_Slice u8) Prims.l_True (fun _ -> Prims.l_True) -/// This function deserializes ring elements and reduces the result by the field -/// modulus. -/// This function MUST NOT be used on secret inputs. -val deserialize_ring_elements_reduced - (v_PUBLIC_KEY_SIZE v_K: usize) - (#v_Vector: Type0) - {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} - (public_key: t_Slice u8) - : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) - Prims.l_True - (fun _ -> Prims.l_True) - val deserialize_then_decompress_10_ (#v_Vector: Type0) {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} @@ -138,6 +126,18 @@ val deserialize_to_reduced_ring_element Prims.l_True (fun _ -> Prims.l_True) +/// This function deserializes ring elements and reduces the result by the field +/// modulus. +/// This function MUST NOT be used on secret inputs. +val deserialize_ring_elements_reduced + (v_PUBLIC_KEY_SIZE v_K: usize) + (#v_Vector: Type0) + {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} + (public_key: t_Slice u8) + : Prims.Pure (t_Array (Libcrux_ml_kem.Polynomial.t_PolynomialRingElement v_Vector) v_K) + Prims.l_True + (fun _ -> Prims.l_True) + val deserialize_to_uncompressed_ring_element (#v_Vector: Type0) {| i1: Libcrux_ml_kem.Vector.Traits.t_Operations v_Vector |} diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Types.fst b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Types.fst index 8ef0918f..b329bf40 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Types.fst +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Types.fst @@ -3,6 +3,12 @@ module Libcrux_ml_kem.Types open Core open FStar.Mul +let impl_6__len (v_SIZE: usize) (_: Prims.unit) = v_SIZE + +let impl_12__len (v_SIZE: usize) (_: Prims.unit) = v_SIZE + +let impl_18__len (v_SIZE: usize) (_: Prims.unit) = v_SIZE + let impl_6__as_slice (v_SIZE: usize) (self: t_MlKemCiphertext v_SIZE) = self.f_value let impl_12__as_slice (v_SIZE: usize) (self: t_MlKemPrivateKey v_SIZE) = self.f_value @@ -15,6 +21,14 @@ let impl__from (pk: t_MlKemPublicKey v_PUBLIC_KEY_SIZE) = { f_sk = sk; f_pk = pk } <: t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE +let impl__into_parts + (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) + (self: t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) + = + self.f_sk, self.f_pk + <: + (t_MlKemPrivateKey v_PRIVATE_KEY_SIZE & t_MlKemPublicKey v_PUBLIC_KEY_SIZE) + let impl__new (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) (sk: t_Array u8 v_PRIVATE_KEY_SIZE) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Types.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Types.fsti index 9cdbe743..dc15da28 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Types.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Types.fsti @@ -3,11 +3,23 @@ module Libcrux_ml_kem.Types open Core open FStar.Mul +/// The number of bytes +val impl_6__len: v_SIZE: usize -> Prims.unit + -> Prims.Pure usize Prims.l_True (fun _ -> Prims.l_True) + +/// The number of bytes +val impl_12__len: v_SIZE: usize -> Prims.unit + -> Prims.Pure usize Prims.l_True (fun _ -> Prims.l_True) + +/// The number of bytes +val impl_18__len: v_SIZE: usize -> Prims.unit + -> Prims.Pure usize Prims.l_True (fun _ -> Prims.l_True) + ///An ML-KEM Ciphertext type t_MlKemCiphertext (v_SIZE: usize) = { f_value:t_Array u8 v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_1 (v_SIZE: usize) : Core.Convert.t_AsRef (t_MlKemCiphertext v_SIZE) (t_Slice u8) = +let impl_1 (v_SIZE: usize) : Core.Convert.t_AsRef #(t_MlKemCiphertext v_SIZE) #(t_Slice u8) = { f_as_ref_pre = (fun (self: t_MlKemCiphertext v_SIZE) -> true); f_as_ref_post = (fun (self: t_MlKemCiphertext v_SIZE) (out: t_Slice u8) -> true); @@ -15,7 +27,7 @@ let impl_1 (v_SIZE: usize) : Core.Convert.t_AsRef (t_MlKemCiphertext v_SIZE) (t_ } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_2 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemCiphertext v_SIZE) (t_Array u8 v_SIZE) = +let impl_2 (v_SIZE: usize) : Core.Convert.t_From #(t_MlKemCiphertext v_SIZE) #(t_Array u8 v_SIZE) = { f_from_pre = (fun (value: t_Array u8 v_SIZE) -> true); f_from_post = (fun (value: t_Array u8 v_SIZE) (out: t_MlKemCiphertext v_SIZE) -> true); @@ -23,7 +35,7 @@ let impl_2 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemCiphertext v_SIZE) (t_A } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_3 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemCiphertext v_SIZE) (t_Array u8 v_SIZE) = +let impl_3 (v_SIZE: usize) : Core.Convert.t_From #(t_MlKemCiphertext v_SIZE) #(t_Array u8 v_SIZE) = { f_from_pre = (fun (value: t_Array u8 v_SIZE) -> true); f_from_post = (fun (value: t_Array u8 v_SIZE) (out: t_MlKemCiphertext v_SIZE) -> true); @@ -34,7 +46,7 @@ let impl_3 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemCiphertext v_SIZE) (t_A } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_4 (v_SIZE: usize) : Core.Convert.t_From (t_Array u8 v_SIZE) (t_MlKemCiphertext v_SIZE) = +let impl_4 (v_SIZE: usize) : Core.Convert.t_From #(t_Array u8 v_SIZE) #(t_MlKemCiphertext v_SIZE) = { f_from_pre = (fun (value: t_MlKemCiphertext v_SIZE) -> true); f_from_post = (fun (value: t_MlKemCiphertext v_SIZE) (out: t_Array u8 v_SIZE) -> true); @@ -49,7 +61,7 @@ val impl_6__as_slice (v_SIZE: usize) (self: t_MlKemCiphertext v_SIZE) type t_MlKemPrivateKey (v_SIZE: usize) = { f_value:t_Array u8 v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_7 (v_SIZE: usize) : Core.Convert.t_AsRef (t_MlKemPrivateKey v_SIZE) (t_Slice u8) = +let impl_7 (v_SIZE: usize) : Core.Convert.t_AsRef #(t_MlKemPrivateKey v_SIZE) #(t_Slice u8) = { f_as_ref_pre = (fun (self: t_MlKemPrivateKey v_SIZE) -> true); f_as_ref_post = (fun (self: t_MlKemPrivateKey v_SIZE) (out: t_Slice u8) -> true); @@ -57,7 +69,7 @@ let impl_7 (v_SIZE: usize) : Core.Convert.t_AsRef (t_MlKemPrivateKey v_SIZE) (t_ } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_8 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPrivateKey v_SIZE) (t_Array u8 v_SIZE) = +let impl_8 (v_SIZE: usize) : Core.Convert.t_From #(t_MlKemPrivateKey v_SIZE) #(t_Array u8 v_SIZE) = { f_from_pre = (fun (value: t_Array u8 v_SIZE) -> true); f_from_post = (fun (value: t_Array u8 v_SIZE) (out: t_MlKemPrivateKey v_SIZE) -> true); @@ -65,7 +77,7 @@ let impl_8 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPrivateKey v_SIZE) (t_A } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_9 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPrivateKey v_SIZE) (t_Array u8 v_SIZE) = +let impl_9 (v_SIZE: usize) : Core.Convert.t_From #(t_MlKemPrivateKey v_SIZE) #(t_Array u8 v_SIZE) = { f_from_pre = (fun (value: t_Array u8 v_SIZE) -> true); f_from_post = (fun (value: t_Array u8 v_SIZE) (out: t_MlKemPrivateKey v_SIZE) -> true); @@ -76,7 +88,7 @@ let impl_9 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPrivateKey v_SIZE) (t_A } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_10 (v_SIZE: usize) : Core.Convert.t_From (t_Array u8 v_SIZE) (t_MlKemPrivateKey v_SIZE) = +let impl_10 (v_SIZE: usize) : Core.Convert.t_From #(t_Array u8 v_SIZE) #(t_MlKemPrivateKey v_SIZE) = { f_from_pre = (fun (value: t_MlKemPrivateKey v_SIZE) -> true); f_from_post = (fun (value: t_MlKemPrivateKey v_SIZE) (out: t_Array u8 v_SIZE) -> true); @@ -91,7 +103,7 @@ val impl_12__as_slice (v_SIZE: usize) (self: t_MlKemPrivateKey v_SIZE) type t_MlKemPublicKey (v_SIZE: usize) = { f_value:t_Array u8 v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_13 (v_SIZE: usize) : Core.Convert.t_AsRef (t_MlKemPublicKey v_SIZE) (t_Slice u8) = +let impl_13 (v_SIZE: usize) : Core.Convert.t_AsRef #(t_MlKemPublicKey v_SIZE) #(t_Slice u8) = { f_as_ref_pre = (fun (self: t_MlKemPublicKey v_SIZE) -> true); f_as_ref_post = (fun (self: t_MlKemPublicKey v_SIZE) (out: t_Slice u8) -> true); @@ -99,7 +111,7 @@ let impl_13 (v_SIZE: usize) : Core.Convert.t_AsRef (t_MlKemPublicKey v_SIZE) (t_ } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_14 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPublicKey v_SIZE) (t_Array u8 v_SIZE) = +let impl_14 (v_SIZE: usize) : Core.Convert.t_From #(t_MlKemPublicKey v_SIZE) #(t_Array u8 v_SIZE) = { f_from_pre = (fun (value: t_Array u8 v_SIZE) -> true); f_from_post = (fun (value: t_Array u8 v_SIZE) (out: t_MlKemPublicKey v_SIZE) -> true); @@ -107,7 +119,7 @@ let impl_14 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPublicKey v_SIZE) (t_A } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_15 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPublicKey v_SIZE) (t_Array u8 v_SIZE) = +let impl_15 (v_SIZE: usize) : Core.Convert.t_From #(t_MlKemPublicKey v_SIZE) #(t_Array u8 v_SIZE) = { f_from_pre = (fun (value: t_Array u8 v_SIZE) -> true); f_from_post = (fun (value: t_Array u8 v_SIZE) (out: t_MlKemPublicKey v_SIZE) -> true); @@ -118,7 +130,7 @@ let impl_15 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPublicKey v_SIZE) (t_A } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_16 (v_SIZE: usize) : Core.Convert.t_From (t_Array u8 v_SIZE) (t_MlKemPublicKey v_SIZE) = +let impl_16 (v_SIZE: usize) : Core.Convert.t_From #(t_Array u8 v_SIZE) #(t_MlKemPublicKey v_SIZE) = { f_from_pre = (fun (value: t_MlKemPublicKey v_SIZE) -> true); f_from_post = (fun (value: t_MlKemPublicKey v_SIZE) (out: t_Array u8 v_SIZE) -> true); @@ -130,7 +142,7 @@ val impl_18__as_slice (v_SIZE: usize) (self: t_MlKemPublicKey v_SIZE) : Prims.Pure (t_Array u8 v_SIZE) Prims.l_True (fun _ -> Prims.l_True) [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_5 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_MlKemCiphertext v_SIZE) (t_Slice u8) = +let impl_5 (v_SIZE: usize) : Core.Convert.t_TryFrom #(t_MlKemCiphertext v_SIZE) #(t_Slice u8) = { f_Error = Core.Array.t_TryFromSliceError; f_try_from_pre = (fun (value: t_Slice u8) -> true); @@ -156,7 +168,7 @@ let impl_5 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_MlKemCiphertext v_SIZE) ( } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_11 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_MlKemPrivateKey v_SIZE) (t_Slice u8) = +let impl_11 (v_SIZE: usize) : Core.Convert.t_TryFrom #(t_MlKemPrivateKey v_SIZE) #(t_Slice u8) = { f_Error = Core.Array.t_TryFromSliceError; f_try_from_pre = (fun (value: t_Slice u8) -> true); @@ -182,7 +194,7 @@ let impl_11 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_MlKemPrivateKey v_SIZE) } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_17 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_MlKemPublicKey v_SIZE) (t_Slice u8) = +let impl_17 (v_SIZE: usize) : Core.Convert.t_TryFrom #(t_MlKemPublicKey v_SIZE) #(t_Slice u8) = { f_Error = Core.Array.t_TryFromSliceError; f_try_from_pre = (fun (value: t_Slice u8) -> true); @@ -222,6 +234,14 @@ val impl__from Prims.l_True (fun _ -> Prims.l_True) +/// Separate this key into the public and private key. +val impl__into_parts + (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) + (self: t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) + : Prims.Pure (t_MlKemPrivateKey v_PRIVATE_KEY_SIZE & t_MlKemPublicKey v_PUBLIC_KEY_SIZE) + Prims.l_True + (fun _ -> Prims.l_True) + /// Creates a new [`MlKemKeyPair`]. val impl__new (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Arithmetic.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Arithmetic.fsti index b808a037..d7e59b4b 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Arithmetic.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Arithmetic.fsti @@ -3,19 +3,28 @@ module Libcrux_ml_kem.Vector.Avx2.Arithmetic open Core open FStar.Mul -let v_BARRETT_MULTIPLIER: i16 = Rust_primitives.Hax.dropped_body +let v_BARRETT_MULTIPLIER: i16 = 20159s val add (lhs rhs: Core.Core_arch.X86.t____m256i) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) +val bitwise_and_with_constant (vector: Core.Core_arch.X86.t____m256i) (constant: i16) + : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) + +val multiply_by_constant (vector: Core.Core_arch.X86.t____m256i) (constant: i16) + : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) + +val shift_right (v_SHIFT_BY: i32) (vector: Core.Core_arch.X86.t____m256i) + : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) + +val sub (lhs rhs: Core.Core_arch.X86.t____m256i) + : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) + /// See Section 3.2 of the implementation notes document for an explanation /// of this code. val barrett_reduce (vector: Core.Core_arch.X86.t____m256i) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) -val bitwise_and_with_constant (vector: Core.Core_arch.X86.t____m256i) (constant: i16) - : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) - val cond_subtract_3329_ (vector: Core.Core_arch.X86.t____m256i) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) @@ -30,12 +39,3 @@ val montgomery_multiply_m128i_by_constants (v c: Core.Core_arch.X86.t____m128i) val montgomery_reduce_i32s (v: Core.Core_arch.X86.t____m256i) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) - -val multiply_by_constant (vector: Core.Core_arch.X86.t____m256i) (constant: i16) - : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) - -val shift_right (v_SHIFT_BY: i32) (vector: Core.Core_arch.X86.t____m256i) - : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) - -val sub (lhs rhs: Core.Core_arch.X86.t____m256i) - : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Compress.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Compress.fsti index efc3482e..cf82ca72 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Compress.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Compress.fsti @@ -3,6 +3,9 @@ module Libcrux_ml_kem.Vector.Avx2.Compress open Core open FStar.Mul +val mulhi_mm256_epi32 (lhs rhs: Core.Core_arch.X86.t____m256i) + : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) + val compress_ciphertext_coefficient (v_COEFFICIENT_BITS: i32) (vector: Core.Core_arch.X86.t____m256i) @@ -15,6 +18,3 @@ val decompress_ciphertext_coefficient (v_COEFFICIENT_BITS: i32) (vector: Core.Core_arch.X86.t____m256i) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) - -val mulhi_mm256_epi32 (lhs rhs: Core.Core_arch.X86.t____m256i) - : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Ntt.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Ntt.fsti index 75b8e11b..5b5d55f7 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Ntt.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Ntt.fsti @@ -3,6 +3,8 @@ module Libcrux_ml_kem.Vector.Avx2.Ntt open Core open FStar.Mul +let ntt_multiply__PERMUTE_WITH: i32 = 216l + val inv_ntt_layer_1_step (vector: Core.Core_arch.X86.t____m256i) (zeta0 zeta1 zeta2 zeta3: i16) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) @@ -23,5 +25,3 @@ val ntt_layer_3_step (vector: Core.Core_arch.X86.t____m256i) (zeta: i16) val ntt_multiply (lhs rhs: Core.Core_arch.X86.t____m256i) (zeta0 zeta1 zeta2 zeta3: i16) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) - -let ntt_multiply__PERMUTE_WITH: i32 = Rust_primitives.Hax.dropped_body diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Portable.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Portable.fsti index ec0c9817..2304c3b2 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Portable.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Portable.fsti @@ -3,14 +3,8 @@ module Libcrux_ml_kem.Vector.Avx2.Portable open Core open FStar.Mul -unfold -let t_FieldElement = i16 - type t_PortableVector = { f_elements:t_Array i16 (sz 16) } -val deserialize_11_ (bytes: t_Slice u8) - : Prims.Pure t_PortableVector Prims.l_True (fun _ -> Prims.l_True) - val from_i16_array (array: t_Array i16 (sz 16)) : Prims.Pure t_PortableVector Prims.l_True (fun _ -> Prims.l_True) @@ -21,3 +15,6 @@ val to_i16_array (v: t_PortableVector) : Prims.Pure (t_Array i16 (sz 16)) Prims.l_True (fun _ -> Prims.l_True) val zero: Prims.unit -> Prims.Pure t_PortableVector Prims.l_True (fun _ -> Prims.l_True) + +val deserialize_11_ (bytes: t_Slice u8) + : Prims.Pure t_PortableVector Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Serialize.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Serialize.fsti index 2d6f3898..40b7a961 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Serialize.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.Serialize.fsti @@ -9,9 +9,6 @@ val deserialize_1_ (bytes: t_Slice u8) val deserialize_10_ (bytes: t_Slice u8) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) -val deserialize_11_ (bytes: t_Slice u8) - : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) - val deserialize_12_ (bytes: t_Slice u8) : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) @@ -27,14 +24,17 @@ val serialize_1_ (vector: Core.Core_arch.X86.t____m256i) val serialize_10_ (vector: Core.Core_arch.X86.t____m256i) : Prims.Pure (t_Array u8 (sz 20)) Prims.l_True (fun _ -> Prims.l_True) -val serialize_11_ (vector: Core.Core_arch.X86.t____m256i) - : Prims.Pure (t_Array u8 (sz 22)) Prims.l_True (fun _ -> Prims.l_True) - val serialize_12_ (vector: Core.Core_arch.X86.t____m256i) : Prims.Pure (t_Array u8 (sz 24)) Prims.l_True (fun _ -> Prims.l_True) +val serialize_5_ (vector: Core.Core_arch.X86.t____m256i) + : Prims.Pure (t_Array u8 (sz 10)) Prims.l_True (fun _ -> Prims.l_True) + val serialize_4_ (vector: Core.Core_arch.X86.t____m256i) : Prims.Pure (t_Array u8 (sz 8)) Prims.l_True (fun _ -> Prims.l_True) -val serialize_5_ (vector: Core.Core_arch.X86.t____m256i) - : Prims.Pure (t_Array u8 (sz 10)) Prims.l_True (fun _ -> Prims.l_True) +val deserialize_11_ (bytes: t_Slice u8) + : Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True) + +val serialize_11_ (vector: Core.Core_arch.X86.t____m256i) + : Prims.Pure (t_Array u8 (sz 22)) Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.fsti index 7d65a411..cc388fd6 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Avx2.fsti @@ -14,7 +14,7 @@ val to_i16_array (v: t_SIMD256Vector) val zero: Prims.unit -> Prims.Pure t_SIMD256Vector Prims.l_True (fun _ -> Prims.l_True) [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl: Libcrux_ml_kem.Vector.Traits.t_Operations t_SIMD256Vector = +let impl: Libcrux_ml_kem.Vector.Traits.t_Operations #t_SIMD256Vector = { _super_11581440318597584651 = FStar.Tactics.Typeclasses.solve; _super_9442900250278684536 = FStar.Tactics.Typeclasses.solve; diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Rej_sample_table.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Rej_sample_table.fsti index fbf536a4..ce3906fe 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Rej_sample_table.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Rej_sample_table.fsti @@ -4,4 +4,2021 @@ open Core open FStar.Mul let v_REJECTION_SAMPLE_SHUFFLE_TABLE: t_Array (t_Array u8 (sz 16)) (sz 256) = - Rust_primitives.Hax.dropped_body + let list = + [ + (let list = + [ + 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 255uy; 255uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 14uy; 15uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 2uy; 3uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; 255uy; + 255uy; 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 0uy; 1uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 2uy; 3uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [ + 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy; 255uy; + 255uy + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [0uy; 1uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + (let list = + [2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy; 255uy; 255uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list); + let list = + [0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy; 8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 16); + Rust_primitives.Hax.array_of_list 16 list + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 256); + Rust_primitives.Hax.array_of_list 256 list diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Traits.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Traits.fsti index 5c09d720..679937d5 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Traits.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.Traits.fsti @@ -3,7 +3,7 @@ module Libcrux_ml_kem.Vector.Traits open Core open FStar.Mul -class t_Operations (v_Self: Type0) = { +class t_Operations (#v_Self: Type0) = { [@@@ FStar.Tactics.Typeclasses.no_method]_super_11581440318597584651:Core.Marker.t_Copy v_Self; [@@@ FStar.Tactics.Typeclasses.no_method]_super_9442900250278684536:Core.Clone.t_Clone v_Self; f_ZERO_pre:Prims.unit -> bool; @@ -181,13 +181,13 @@ class t_Operations (v_Self: Type0) = { (fun result -> f_rej_sample_post x0 x1 result) } -let v_FIELD_ELEMENTS_IN_VECTOR: usize = Rust_primitives.Hax.dropped_body +let v_FIELD_ELEMENTS_IN_VECTOR: usize = sz 16 -let v_FIELD_MODULUS: i16 = Rust_primitives.Hax.dropped_body +let v_FIELD_MODULUS: i16 = 3329s -let v_INVERSE_OF_MODULUS_MOD_MONTGOMERY_R: u32 = Rust_primitives.Hax.dropped_body +let v_INVERSE_OF_MODULUS_MOD_MONTGOMERY_R: u32 = 62209ul -let v_MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS: i16 = Rust_primitives.Hax.dropped_body +let v_MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS: i16 = 1353s val decompress_1_ (#v_T: Type0) {| i1: t_Operations v_T |} (v: v_T) : Prims.Pure v_T Prims.l_True (fun _ -> Prims.l_True) diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.fst b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.fst index c80c01c5..aa287104 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.fst +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.fst @@ -76,18 +76,23 @@ let ntt_multiply_binomials (a0, a1: (i16 & i16)) (b0, b1: (i16 & i16)) (zeta: i1 let rej_sample (a: t_Slice u8) (result: t_Slice i16) = let sampled:usize = sz 0 in let result, sampled:(t_Slice i16 & usize) = - Core.Iter.Traits.Iterator.f_fold (Core.Iter.Traits.Collect.f_into_iter #(Core.Slice.Iter.t_Chunks - u8) - (Core.Slice.impl__chunks #u8 a (sz 3) <: Core.Slice.Iter.t_Chunks u8) + Core.Iter.Traits.Iterator.f_fold (Core.Iter.Traits.Collect.f_into_iter #(Core.Ops.Range.t_Range + usize) + ({ + Core.Ops.Range.f_start = sz 0; + Core.Ops.Range.f_end = (Core.Slice.impl__len #u8 a <: usize) /! sz 3 <: usize + } + <: + Core.Ops.Range.t_Range usize) <: - Core.Slice.Iter.t_Chunks u8) + Core.Ops.Range.t_Range usize) (result, sampled <: (t_Slice i16 & usize)) - (fun temp_0_ bytes -> + (fun temp_0_ i -> let result, sampled:(t_Slice i16 & usize) = temp_0_ in - let bytes:t_Slice u8 = bytes in - let b1:i16 = cast (bytes.[ sz 0 ] <: u8) <: i16 in - let b2:i16 = cast (bytes.[ sz 1 ] <: u8) <: i16 in - let b3:i16 = cast (bytes.[ sz 2 ] <: u8) <: i16 in + let i:usize = i in + let b1:i16 = cast (a.[ (i *! sz 3 <: usize) +! sz 0 <: usize ] <: u8) <: i16 in + let b2:i16 = cast (a.[ (i *! sz 3 <: usize) +! sz 1 <: usize ] <: u8) <: i16 in + let b3:i16 = cast (a.[ (i *! sz 3 <: usize) +! sz 2 <: usize ] <: u8) <: i16 in let d1:i16 = ((b2 &. 15s <: i16) <>! 4l <: i16) in let result, sampled:(t_Slice i16 & usize) = diff --git a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.fsti b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.fsti index 39f14280..df37aa96 100644 --- a/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.fsti +++ b/libcrux-ml-kem/proofs/fstar/extraction/Libcrux_ml_kem.Vector.fsti @@ -9,33 +9,16 @@ let _ = let open Libcrux_ml_kem.Vector.Portable in () -/// Values having this type hold a representative 'x' of the Kyber field. -/// We use 'fe' as a shorthand for this type. -unfold -let t_FieldElement = i16 - -/// If 'x' denotes a value of type `fe`, values having this type hold a -/// representative y ≡ x·MONTGOMERY_R (mod FIELD_MODULUS). -/// We use 'fer' as a shorthand for this type. -unfold -let t_FieldElementTimesMontgomeryR = i16 - -/// If 'x' denotes a value of type `fe`, values having this type hold a -/// representative y ≡ x·MONTGOMERY_R^(-1) (mod FIELD_MODULUS). -/// We use 'mfe' as a shorthand for this type -unfold -let t_MontgomeryFieldElement = i16 - /// This is calculated as ⌊(BARRETT_R / FIELD_MODULUS) + 1/2⌋ -let v_BARRETT_MULTIPLIER: i32 = Rust_primitives.Hax.dropped_body +let v_BARRETT_MULTIPLIER: i32 = 20159l -let v_BARRETT_R: i32 = Rust_primitives.Hax.dropped_body +let v_BARRETT_SHIFT: i32 = 26l -let v_BARRETT_SHIFT: i32 = Rust_primitives.Hax.dropped_body +let v_BARRETT_R: i32 = 1l <. (Core.Ops.Arith.Neg.neg Libcrux_ml_kem.Vector.Traits.v_FIELD_MODULUS <: i16) && result <. Libcrux_ml_kem.Vector.Traits.v_FIELD_MODULUS) -val compress_ciphertext_coefficient (coefficient_bits: u8) (fe: u16) - : Prims.Pure i16 - (requires - (coefficient_bits =. 4uy || coefficient_bits =. 5uy || coefficient_bits =. 10uy || - coefficient_bits =. 11uy) && - fe <. (cast (Libcrux_ml_kem.Vector.Traits.v_FIELD_MODULUS <: i16) <: u16)) - (ensures - fun result -> - let result:i16 = result in - result >=. 0s && - result <. (Core.Num.impl__i16__pow 2s (cast (coefficient_bits <: u8) <: u32) <: i16)) - /// The `compress_*` functions implement the `Compress` function specified in the NIST FIPS /// 203 standard (Page 18, Expression 4.5), which is defined as: /// ```plaintext @@ -105,14 +76,17 @@ val get_n_least_significant_bits (n: u8) (value: u32) let result:u32 = result in result <. (Core.Num.impl__u32__pow 2ul (Core.Convert.f_into #u8 #u32 n <: u32) <: u32)) -/// If `fe` is some field element 'x' of the Kyber field and `fer` is congruent to -/// `y · MONTGOMERY_R`, this procedure outputs a value that is congruent to -/// `x · y`, as follows: -/// `fe · fer ≡ x · y · MONTGOMERY_R (mod FIELD_MODULUS)` -/// `montgomery_reduce` takes the value `x · y · MONTGOMERY_R` and outputs a representative -/// `x · y · MONTGOMERY_R * MONTGOMERY_R^{-1} ≡ x · y (mod FIELD_MODULUS)`. -val montgomery_multiply_fe_by_fer (fe fer: i16) - : Prims.Pure i16 Prims.l_True (fun _ -> Prims.l_True) +val compress_ciphertext_coefficient (coefficient_bits: u8) (fe: u16) + : Prims.Pure i16 + (requires + (coefficient_bits =. 4uy || coefficient_bits =. 5uy || coefficient_bits =. 10uy || + coefficient_bits =. 11uy) && + fe <. (cast (Libcrux_ml_kem.Vector.Traits.v_FIELD_MODULUS <: i16) <: u16)) + (ensures + fun result -> + let result:i16 = result in + result >=. 0s && + result <. (Core.Num.impl__i16__pow 2s (cast (coefficient_bits <: u8) <: u32) <: i16)) /// Signed Montgomery Reduction /// Given an input `value`, `montgomery_reduce` outputs a representative `o` @@ -147,6 +121,15 @@ val montgomery_reduce_element (value: i32) i16) && result <=. ((3s *! Libcrux_ml_kem.Vector.Traits.v_FIELD_MODULUS <: i16) /! 2s <: i16)) +/// If `fe` is some field element 'x' of the Kyber field and `fer` is congruent to +/// `y · MONTGOMERY_R`, this procedure outputs a value that is congruent to +/// `x · y`, as follows: +/// `fe · fer ≡ x · y · MONTGOMERY_R (mod FIELD_MODULUS)` +/// `montgomery_reduce` takes the value `x · y · MONTGOMERY_R` and outputs a representative +/// `x · y · MONTGOMERY_R * MONTGOMERY_R^{-1} ≡ x · y (mod FIELD_MODULUS)`. +val montgomery_multiply_fe_by_fer (fe fer: i16) + : Prims.Pure i16 Prims.l_True (fun _ -> Prims.l_True) + /// Compute the product of two Kyber binomials with respect to the /// modulus `X² - zeta`. /// This function almost implements Algorithm 11 of the @@ -206,36 +189,6 @@ val decompress_ciphertext_coefficient Prims.l_True (fun _ -> Prims.l_True) -val deserialize_1_ (v: t_Slice u8) - : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector - Prims.l_True - (fun _ -> Prims.l_True) - -val deserialize_10_ (bytes: t_Slice u8) - : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector - Prims.l_True - (fun _ -> Prims.l_True) - -val deserialize_11_ (bytes: t_Slice u8) - : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector - Prims.l_True - (fun _ -> Prims.l_True) - -val deserialize_12_ (bytes: t_Slice u8) - : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector - Prims.l_True - (fun _ -> Prims.l_True) - -val deserialize_4_ (bytes: t_Slice u8) - : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector - Prims.l_True - (fun _ -> Prims.l_True) - -val deserialize_5_ (bytes: t_Slice u8) - : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector - Prims.l_True - (fun _ -> Prims.l_True) - val from_i16_array (array: t_Slice i16) : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector Prims.l_True @@ -285,13 +238,6 @@ val ntt_layer_3_step (v: Libcrux_ml_kem.Vector.Portable.t_PortableVector) (zeta: Prims.l_True (fun _ -> Prims.l_True) -val ntt_multiply - (lhs rhs: Libcrux_ml_kem.Vector.Portable.t_PortableVector) - (zeta0 zeta1 zeta2 zeta3: i16) - : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector - Prims.l_True - (fun _ -> Prims.l_True) - val serialize_1_ (v: Libcrux_ml_kem.Vector.Portable.t_PortableVector) : Prims.Pure (t_Array u8 (sz 2)) Prims.l_True (fun _ -> Prims.l_True) @@ -323,8 +269,45 @@ val sub (lhs rhs: Libcrux_ml_kem.Vector.Portable.t_PortableVector) val zero: Prims.unit -> Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector Prims.l_True (fun _ -> Prims.l_True) +val deserialize_1_ (v: t_Slice u8) + : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector + Prims.l_True + (fun _ -> Prims.l_True) + +val deserialize_10_ (bytes: t_Slice u8) + : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector + Prims.l_True + (fun _ -> Prims.l_True) + +val deserialize_11_ (bytes: t_Slice u8) + : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector + Prims.l_True + (fun _ -> Prims.l_True) + +val deserialize_12_ (bytes: t_Slice u8) + : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector + Prims.l_True + (fun _ -> Prims.l_True) + +val deserialize_4_ (bytes: t_Slice u8) + : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector + Prims.l_True + (fun _ -> Prims.l_True) + +val deserialize_5_ (bytes: t_Slice u8) + : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector + Prims.l_True + (fun _ -> Prims.l_True) + +val ntt_multiply + (lhs rhs: Libcrux_ml_kem.Vector.Portable.t_PortableVector) + (zeta0 zeta1 zeta2 zeta3: i16) + : Prims.Pure Libcrux_ml_kem.Vector.Portable.t_PortableVector + Prims.l_True + (fun _ -> Prims.l_True) + [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl: Libcrux_ml_kem.Vector.Traits.t_Operations Libcrux_ml_kem.Vector.Portable.t_PortableVector = +let impl: Libcrux_ml_kem.Vector.Traits.t_Operations #Libcrux_ml_kem.Vector.Portable.t_PortableVector = { _super_11581440318597584651 = FStar.Tactics.Typeclasses.solve; _super_9442900250278684536 = FStar.Tactics.Typeclasses.solve; diff --git a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Avx2.X4.Incremental.fsti b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Avx2.X4.Incremental.fsti index 4fbf9ca9..0fb291cc 100644 --- a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Avx2.X4.Incremental.fsti +++ b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Avx2.X4.Incremental.fsti @@ -4,15 +4,17 @@ open Core open FStar.Mul /// The Keccak state for the incremental API. -type t_KeccakState = { f_state:t_Array Libcrux_sha3.Neon.X2.Incremental.t_KeccakState (sz 2) } +type t_KeccakState = { + f_state:Libcrux_sha3.Generic_keccak.t_KeccakState (sz 4) Core.Core_arch.X86.t____m256i +} /// Initialise the state and perform up to 4 absorbs at the same time, -/// using two [`KeccakState4`]. +/// using two [`KeccakState`]. /// **PANICS** when `N` is not 2, 3, or 4. val v__shake128_absorb_finalxN (v_N: usize) (input: t_Array (t_Array u8 (sz 34)) v_N) : Prims.Pure t_KeccakState Prims.l_True (fun _ -> Prims.l_True) -/// Squeeze up to 3 x 4 (N) blocks in parallel, using two [`KeccakState4`]. +/// Squeeze up to 3 x 4 (N) blocks in parallel, using two [`KeccakState`]. /// Each block is of size `LEN`. /// **PANICS** when `N` is not 2, 3, or 4. val v__shake128_squeeze3xN (v_LEN v_N: usize) (state: t_KeccakState) @@ -20,7 +22,7 @@ val v__shake128_squeeze3xN (v_LEN v_N: usize) (state: t_KeccakState) Prims.l_True (fun _ -> Prims.l_True) -/// Squeeze up to 4 (N) blocks in parallel, using two [`KeccakState4`]. +/// Squeeze up to 4 (N) blocks in parallel, using two [`KeccakState`]. /// Each block is of size `LEN`. /// **PANICS** when `N` is not 2, 3, or 4. val v__shake128_squeezexN (v_LEN v_N: usize) (state: t_KeccakState) diff --git a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Neon.X2.Incremental.fsti b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Neon.X2.Incremental.fsti index 064580f4..7305a3b1 100644 --- a/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Neon.X2.Incremental.fsti +++ b/libcrux-sha3/proofs/fstar/extraction/Libcrux_sha3.Neon.X2.Incremental.fsti @@ -4,10 +4,7 @@ open Core open FStar.Mul /// The Keccak state for the incremental API. -type t_KeccakState = { - f_state:Libcrux_sha3.Generic_keccak.t_KeccakState (sz 2) - Core.Core_arch.Arm_shared.Neon.t_uint64x2_t -} +type t_KeccakState = { f_state:t_Array Libcrux_sha3.Portable.t_KeccakState (sz 2) } /// Initialise the state and perform up to 4 absorbs at the same time, /// using two [`KeccakState2`]. diff --git a/libcrux-sha3/src/lib.rs b/libcrux-sha3/src/lib.rs index fca2dfd8..dcc01ba5 100644 --- a/libcrux-sha3/src/lib.rs +++ b/libcrux-sha3/src/lib.rs @@ -439,9 +439,10 @@ pub mod neon { #[cfg(feature = "simd128")] type KeccakState2Internal = GenericState<2, crate::simd::arm64::uint64x2_t>; + /// The Keccak state for the incremental API. #[allow(dead_code)] #[cfg(not(feature = "simd128"))] - pub struct KeccakState2 { + pub struct KeccakState { state: [crate::portable::KeccakState; 2], } @@ -789,9 +790,10 @@ pub mod avx2 { #[cfg(feature = "simd256")] use libcrux_intrinsics::avx2::*; + /// The Keccak state for the incremental API. #[cfg(feature = "simd256")] - pub struct KeccakState4 { - state: KeccakState<4, Vec256>, + pub struct KeccakState { + state: GenericState<4, Vec256>, } /// The Keccak state for the incremental API. @@ -803,7 +805,7 @@ pub mod avx2 { /// The Keccak state for the incremental API. #[cfg(not(any(feature = "simd256", feature = "simd128")))] - pub type KeccakState4 = [crate::portable::KeccakState; 4]; + pub type KeccakState = [crate::portable::KeccakState; 4]; /// Initialise the [`KeccakState`]. #[inline(always)] @@ -828,7 +830,7 @@ pub mod avx2 { // } #[cfg(feature = "simd256")] KeccakState { - state: KeccakState::new(), + state: GenericState::new(), } } @@ -871,7 +873,7 @@ pub mod avx2 { } /// Initialise the state and perform up to 4 absorbs at the same time, - /// using two [`KeccakState4`]. + /// using two [`KeccakState`]. /// /// **PANICS** when `N` is not 2, 3, or 4. #[inline(always)] @@ -943,7 +945,7 @@ pub mod avx2 { ); } - /// Squeeze up to 3 x 4 (N) blocks in parallel, using two [`KeccakState4`]. + /// Squeeze up to 3 x 4 (N) blocks in parallel, using two [`KeccakState`]. /// Each block is of size `LEN`. /// /// **PANICS** when `N` is not 2, 3, or 4. @@ -1035,7 +1037,7 @@ pub mod avx2 { squeeze_next_block::<4, Vec256, 168>(&mut s.state, [out0, out1, out2, out3]); } - /// Squeeze up to 4 (N) blocks in parallel, using two [`KeccakState4`]. + /// Squeeze up to 4 (N) blocks in parallel, using two [`KeccakState`]. /// Each block is of size `LEN`. /// /// **PANICS** when `N` is not 2, 3, or 4. From a3ce34330b21041e1d493dac8292bc805ccaf516 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 14:36:46 +0200 Subject: [PATCH 48/53] update C extraction --- libcrux-ml-kem/c.sh | 10 +- libcrux-ml-kem/c/benches/sha3.cc | 4 +- libcrux-ml-kem/c/code_gen.txt | 8 +- libcrux-ml-kem/c/eurydice_glue.h | 41 +- libcrux-ml-kem/c/internal/libcrux_core.h | 13 +- .../c/internal/libcrux_mlkem_avx2.h | 2 +- .../c/internal/libcrux_mlkem_portable.h | 2 +- libcrux-ml-kem/c/internal/libcrux_sha3_avx2.h | 4 +- .../c/internal/libcrux_sha3_internal.h | 6 +- libcrux-ml-kem/c/libcrux_core.c | 2 +- libcrux-ml-kem/c/libcrux_core.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem1024.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem1024_avx2.c | 2 +- libcrux-ml-kem/c/libcrux_mlkem1024_avx2.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem1024_portable.c | 2 +- libcrux-ml-kem/c/libcrux_mlkem1024_portable.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem512.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem512_avx2.c | 2 +- libcrux-ml-kem/c/libcrux_mlkem512_avx2.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem512_portable.c | 2 +- libcrux-ml-kem/c/libcrux_mlkem512_portable.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem768.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem768_avx2.c | 2 +- libcrux-ml-kem/c/libcrux_mlkem768_avx2.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem768_portable.c | 2 +- libcrux-ml-kem/c/libcrux_mlkem768_portable.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem_avx2.c | 500 ++++++++---------- libcrux-ml-kem/c/libcrux_mlkem_avx2.h | 2 +- libcrux-ml-kem/c/libcrux_mlkem_portable.c | 353 ++++++------- libcrux-ml-kem/c/libcrux_mlkem_portable.h | 2 +- libcrux-ml-kem/c/libcrux_sha3.h | 2 +- libcrux-ml-kem/c/libcrux_sha3_avx2.c | 226 ++++---- libcrux-ml-kem/c/libcrux_sha3_avx2.h | 2 +- libcrux-ml-kem/c/libcrux_sha3_internal.h | 155 +++--- libcrux-ml-kem/c/libcrux_sha3_neon.c | 120 +---- libcrux-ml-kem/c/libcrux_sha3_neon.h | 15 +- 36 files changed, 637 insertions(+), 864 deletions(-) diff --git a/libcrux-ml-kem/c.sh b/libcrux-ml-kem/c.sh index 73e296a4..ba15a2ab 100755 --- a/libcrux-ml-kem/c.sh +++ b/libcrux-ml-kem/c.sh @@ -19,7 +19,7 @@ clean=0 config=c.yaml out=c glue=$EURYDICE_HOME/include/eurydice_glue.h -features= +features="--cargo-arg=--features=pre-verification" # Parse command line arguments. all_args=("$@") @@ -32,7 +32,7 @@ while [ $# -gt 0 ]; do --config) config="$2"; shift ;; --out) out="$2"; shift ;; --glue) glue="$2"; shift ;; - --mlkem768) features="--cargo-arg=--no-default-features --cargo-arg=--features=mlkem768" ;; + --mlkem768) features="${features} --cargo-arg=--no-default-features --cargo-arg=--features=mlkem768" ;; esac shift done @@ -81,7 +81,11 @@ clang-format --style=Google -i intrinsics/*.h [[ -z "$CHARON_REV" && -d $CHARON_HOME/.git ]] && export CHARON_REV=$(git -C $CHARON_HOME rev-parse HEAD) [[ -z "$EURYDICE_REV" && -d $EURYDICE_HOME/.git ]] && export EURYDICE_REV=$(git -C $EURYDICE_HOME rev-parse HEAD) [[ -z "$KRML_REV" && -d $KRML_HOME/.git ]] && export KRML_REV=$(git -C $KRML_HOME rev-parse HEAD) -[[ -z "$FSTAR_REV" && -d $FSTAR_HOME/.git ]] && export FSTAR_REV=$(git -C $FSTAR_HOME rev-parse HEAD) +if [[ -z "$FSTAR_REV" && -d $FSTAR_HOME/.git ]]; then + export FSTAR_REV=$(git -C $FSTAR_HOME rev-parse HEAD) +else + export FSTAR_REV=$(fstar.exe --version | grep commit | sed 's/commit=\(.*\)/\1/') +fi rm -f code_gen.txt echo "This code was generated with the following tools:" >> code_gen.txt echo -n "Charon: " >> code_gen.txt diff --git a/libcrux-ml-kem/c/benches/sha3.cc b/libcrux-ml-kem/c/benches/sha3.cc index b2712fea..dc6a5d9e 100644 --- a/libcrux-ml-kem/c/benches/sha3.cc +++ b/libcrux-ml-kem/c/benches/sha3.cc @@ -71,13 +71,13 @@ shake128_34_504(benchmark::State &state) Eurydice_slice last[4] = {EURYDICE_SLICE(input, 0, 34), EURYDICE_SLICE(input, 0, 34), EURYDICE_SLICE(input, 0, 34), EURYDICE_SLICE(input, 0, 34)}; Eurydice_slice out[4] = {EURYDICE_SLICE(digest0, 0, 504), EURYDICE_SLICE(digest1, 0, 504), EURYDICE_SLICE(digest2, 0, 504), EURYDICE_SLICE(digest3, 0, 504)}; - libcrux_sha3_avx2_x4_incremental_KeccakState4 st = libcrux_sha3_avx2_x4_incremental_shake128_init(); + libcrux_sha3_avx2_x4_incremental_KeccakState st = libcrux_sha3_avx2_x4_incremental_shake128_init(); libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168size_t_31uint8_t(&st, last); libcrux_sha3_generic_keccak_squeeze_first_three_blocks__core_core_arch_x86___m256i_4size_t_168size_t(&st, out); for (auto _ : state) { - libcrux_sha3_avx2_x4_incremental_KeccakState4 st = libcrux_sha3_avx2_x4_incremental_shake128_init(); + libcrux_sha3_avx2_x4_incremental_KeccakState st = libcrux_sha3_avx2_x4_incremental_shake128_init(); libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168size_t_31uint8_t(&st, last); libcrux_sha3_generic_keccak_squeeze_first_three_blocks__core_core_arch_x86___m256i_4size_t_168size_t(&st, out); } diff --git a/libcrux-ml-kem/c/code_gen.txt b/libcrux-ml-kem/c/code_gen.txt index aa3d27d4..6d88a77b 100644 --- a/libcrux-ml-kem/c/code_gen.txt +++ b/libcrux-ml-kem/c/code_gen.txt @@ -1,5 +1,5 @@ This code was generated with the following tools: -Charon: ae55966c01a1a4b185a1a34da7861ba5db74c8ad -Eurydice: bbfd102bbfbc3e4c362953f093dbfd65e2fbc10c -Karamel: 409fe4552f8f46351241cba1decfaa4d9fa6ffea -F*: +Charon: 23f20c184e51015582b7918ea4f1eb063b28daba +Eurydice: 30fdb50add4dabaee90051878c166bac8c5ac26a +Karamel: 42a431696cd32d41155d7e484720eb71fd5dc7b1 +F*: a32b316e521fa4f239b610ec8f1d15e78d62cbe8-dirty diff --git a/libcrux-ml-kem/c/eurydice_glue.h b/libcrux-ml-kem/c/eurydice_glue.h index 0e51e219..ed8c1f0f 100644 --- a/libcrux-ml-kem/c/eurydice_glue.h +++ b/libcrux-ml-kem/c/eurydice_glue.h @@ -85,7 +85,7 @@ typedef struct { #define Eurydice_array_eq(sz, a1, a2, t, _, _ret_t) \ (memcmp(a1, a2, sz * sizeof(t)) == 0) -#define core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq \ +#define core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq \ Eurydice_array_eq #define core_slice___Slice_T___split_at(slice, mid, element_type, ret_t) \ @@ -135,6 +135,21 @@ core_convert_num___core__convert__From_i32__for_i64__59__from(int32_t x) { return x; } +static inline uint64_t +core_convert_num___core__convert__From_u8__for_u64__66__from(uint8_t x) { + return x; +} + +static inline uint64_t +core_convert_num___core__convert__From_u16__for_u64__70__from(uint16_t x) { + return x; +} + +static inline size_t +core_convert_num___core__convert__From_u16__for_usize__96__from(uint16_t x) { + return x; +} + static inline uint32_t core_num__u8_6__count_ones(uint8_t x0) { #ifdef _MSC_VER return __popcnt(x0); @@ -163,9 +178,14 @@ static inline uint8_t Eurydice_shr_pv_u8(uint8_t *p, int32_t v) { return (*p) >> v; } -// ITERATORS +#define core_num_nonzero_private_NonZeroUsizeInner size_t +static inline core_num_nonzero_private_NonZeroUsizeInner +core_num_nonzero_private___core__clone__Clone_for_core__num__nonzero__private__NonZeroUsizeInner__26__clone( + core_num_nonzero_private_NonZeroUsizeInner *x0) { + return *x0; +} -#define core_num_nonzero_NonZeroUsize size_t +// ITERATORS #define Eurydice_range_iter_next(iter_ptr, t, ret_t) \ (((iter_ptr)->start == (iter_ptr)->end) \ ? (CLITERAL(ret_t){.tag = core_option_None}) \ @@ -183,6 +203,9 @@ static inline uint8_t Eurydice_shr_pv_u8(uint8_t *p, int32_t v) { #define Eurydice_into_iter(x, t, _ret_t) (x) #define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter \ Eurydice_into_iter +// This name changed on 20240627 +#define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter \ + Eurydice_into_iter typedef struct { Eurydice_slice slice; @@ -214,11 +237,15 @@ static inline Eurydice_slice chunk_next(Eurydice_chunks *chunks, .chunk_size = sz_}) #define core_slice_iter_Chunks Eurydice_chunks #define core_slice_iter_ChunksExact Eurydice_chunks -#define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___70__next( \ - iter, t, ret_t) \ - (((iter)->slice.len == 0) ? ((ret_t){.tag = core_option_None}) \ - : ((ret_t){.tag = core_option_Some, \ +#define Eurydice_chunks_next(iter, t, ret_t) \ + (((iter)->slice.len == 0) ? ((ret_t){.tag = core_option_None}) \ + : ((ret_t){.tag = core_option_Some, \ .f0 = chunk_next(iter, sizeof(t))})) +#define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___70__next \ + Eurydice_chunks_next +// This name changed on 20240627 +#define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___71__next \ + Eurydice_chunks_next #define core_slice_iter__core__slice__iter__ChunksExact__a__T__89__next( \ iter, t, _ret_t) \ core_slice_iter__core__slice__iter__Chunks__a__T__70__next(iter, t) diff --git a/libcrux-ml-kem/c/internal/libcrux_core.h b/libcrux-ml-kem/c/internal/libcrux_core.h index 0fb3b23d..e6ac1986 100644 --- a/libcrux-ml-kem/c/internal/libcrux_core.h +++ b/libcrux-ml-kem/c/internal/libcrux_core.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __internal_libcrux_core_H @@ -15,12 +15,6 @@ extern "C" { #include "../libcrux_core.h" #include "eurydice_glue.h" -extern void core_fmt_rt__core__fmt__rt__Argument__a__1__none( - core_fmt_rt_Argument *x0); - -extern core_fmt_Arguments core_fmt__core__fmt__Arguments__a__2__new_v1( - Eurydice_slice x0, Eurydice_slice x1); - #define CORE_NUM__U32_8__BITS (32U) static inline uint32_t core_num__u8_6__count_ones(uint8_t x0); @@ -216,11 +210,6 @@ void core_result__core__result__Result_T__E___unwrap__uint8_t_10size_t__core_arr core_result_Result__uint8_t_10size_t__core_array_TryFromSliceError self, uint8_t ret[10U]); -typedef struct core_option_Option__Eurydice_slice_uint8_t_s { - core_option_Option__size_t_tags tag; - Eurydice_slice f0; -} core_option_Option__Eurydice_slice_uint8_t; - typedef struct core_result_Result__int16_t_16size_t__core_array_TryFromSliceError_s { core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError_tags tag; diff --git a/libcrux-ml-kem/c/internal/libcrux_mlkem_avx2.h b/libcrux-ml-kem/c/internal/libcrux_mlkem_avx2.h index 8b193ff9..ac8d14aa 100644 --- a/libcrux-ml-kem/c/internal/libcrux_mlkem_avx2.h +++ b/libcrux-ml-kem/c/internal/libcrux_mlkem_avx2.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __internal_libcrux_mlkem_avx2_H diff --git a/libcrux-ml-kem/c/internal/libcrux_mlkem_portable.h b/libcrux-ml-kem/c/internal/libcrux_mlkem_portable.h index 5e2ab8b9..9905d0fc 100644 --- a/libcrux-ml-kem/c/internal/libcrux_mlkem_portable.h +++ b/libcrux-ml-kem/c/internal/libcrux_mlkem_portable.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __internal_libcrux_mlkem_portable_H diff --git a/libcrux-ml-kem/c/internal/libcrux_sha3_avx2.h b/libcrux-ml-kem/c/internal/libcrux_sha3_avx2.h index ca52d786..29a37289 100644 --- a/libcrux-ml-kem/c/internal/libcrux_sha3_avx2.h +++ b/libcrux-ml-kem/c/internal/libcrux_sha3_avx2.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __internal_libcrux_sha3_avx2_H @@ -18,7 +18,7 @@ extern "C" { #include "intrinsics/libcrux_intrinsics_avx2.h" typedef libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - libcrux_sha3_avx2_x4_incremental_KeccakState4; + libcrux_sha3_avx2_x4_incremental_KeccakState; void libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168size_t_31uint8_t( libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t diff --git a/libcrux-ml-kem/c/internal/libcrux_sha3_internal.h b/libcrux-ml-kem/c/internal/libcrux_sha3_internal.h index 9bc61dff..9a5805f0 100644 --- a/libcrux-ml-kem/c/internal/libcrux_sha3_internal.h +++ b/libcrux-ml-kem/c/internal/libcrux_sha3_internal.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __internal_libcrux_sha3_internal_H @@ -16,7 +16,7 @@ extern "C" { #include "eurydice_glue.h" typedef libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t - libcrux_sha3_portable_KeccakState1; + libcrux_sha3_portable_KeccakState; static inline libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t libcrux_sha3_portable_incremental_shake128_init(void) { @@ -178,7 +178,7 @@ libcrux_sha3_portable_incremental_shake128_squeeze_first_five_blocks( } static inline libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t -libcrux_sha3_portable___core__clone__Clone_for_libcrux_sha3__portable__KeccakState1___clone( +libcrux_sha3_portable___core__clone__Clone_for_libcrux_sha3__portable__KeccakState___clone( libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *self) { return self[0U]; } diff --git a/libcrux-ml-kem/c/libcrux_core.c b/libcrux-ml-kem/c/libcrux_core.c index fcd3a82b..7113bd76 100644 --- a/libcrux-ml-kem/c/libcrux_core.c +++ b/libcrux-ml-kem/c/libcrux_core.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "internal/libcrux_core.h" diff --git a/libcrux-ml-kem/c/libcrux_core.h b/libcrux-ml-kem/c/libcrux_core.h index ec93700b..d6566c1d 100644 --- a/libcrux-ml-kem/c/libcrux_core.h +++ b/libcrux-ml-kem/c/libcrux_core.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_core_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem1024.h b/libcrux-ml-kem/c/libcrux_mlkem1024.h index e11fc760..92202737 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem1024.h +++ b/libcrux-ml-kem/c/libcrux_mlkem1024.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem1024_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem1024_avx2.c b/libcrux-ml-kem/c/libcrux_mlkem1024_avx2.c index 7c0b024d..ac85f251 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem1024_avx2.c +++ b/libcrux-ml-kem/c/libcrux_mlkem1024_avx2.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "libcrux_mlkem1024_avx2.h" diff --git a/libcrux-ml-kem/c/libcrux_mlkem1024_avx2.h b/libcrux-ml-kem/c/libcrux_mlkem1024_avx2.h index 4e5ffff3..3452114a 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem1024_avx2.h +++ b/libcrux-ml-kem/c/libcrux_mlkem1024_avx2.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem1024_avx2_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem1024_portable.c b/libcrux-ml-kem/c/libcrux_mlkem1024_portable.c index b8bcb998..67151773 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem1024_portable.c +++ b/libcrux-ml-kem/c/libcrux_mlkem1024_portable.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "libcrux_mlkem1024_portable.h" diff --git a/libcrux-ml-kem/c/libcrux_mlkem1024_portable.h b/libcrux-ml-kem/c/libcrux_mlkem1024_portable.h index 86d28619..6e842d3f 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem1024_portable.h +++ b/libcrux-ml-kem/c/libcrux_mlkem1024_portable.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem1024_portable_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem512.h b/libcrux-ml-kem/c/libcrux_mlkem512.h index 438b35f4..f15e2be1 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem512.h +++ b/libcrux-ml-kem/c/libcrux_mlkem512.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem512_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem512_avx2.c b/libcrux-ml-kem/c/libcrux_mlkem512_avx2.c index f3462da0..25e97440 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem512_avx2.c +++ b/libcrux-ml-kem/c/libcrux_mlkem512_avx2.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "libcrux_mlkem512_avx2.h" diff --git a/libcrux-ml-kem/c/libcrux_mlkem512_avx2.h b/libcrux-ml-kem/c/libcrux_mlkem512_avx2.h index 929a9bad..6ff1c669 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem512_avx2.h +++ b/libcrux-ml-kem/c/libcrux_mlkem512_avx2.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem512_avx2_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem512_portable.c b/libcrux-ml-kem/c/libcrux_mlkem512_portable.c index d69cddf1..6a7cdbce 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem512_portable.c +++ b/libcrux-ml-kem/c/libcrux_mlkem512_portable.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "libcrux_mlkem512_portable.h" diff --git a/libcrux-ml-kem/c/libcrux_mlkem512_portable.h b/libcrux-ml-kem/c/libcrux_mlkem512_portable.h index 269a4ac2..1349dbf9 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem512_portable.h +++ b/libcrux-ml-kem/c/libcrux_mlkem512_portable.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem512_portable_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem768.h b/libcrux-ml-kem/c/libcrux_mlkem768.h index e2ef0eeb..e65cbce2 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem768.h +++ b/libcrux-ml-kem/c/libcrux_mlkem768.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem768_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem768_avx2.c b/libcrux-ml-kem/c/libcrux_mlkem768_avx2.c index 7e65fa6c..45e781db 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem768_avx2.c +++ b/libcrux-ml-kem/c/libcrux_mlkem768_avx2.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "libcrux_mlkem768_avx2.h" diff --git a/libcrux-ml-kem/c/libcrux_mlkem768_avx2.h b/libcrux-ml-kem/c/libcrux_mlkem768_avx2.h index 79eb5fc8..a0f3922e 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem768_avx2.h +++ b/libcrux-ml-kem/c/libcrux_mlkem768_avx2.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem768_avx2_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem768_portable.c b/libcrux-ml-kem/c/libcrux_mlkem768_portable.c index 58dd5ea2..e30258c8 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem768_portable.c +++ b/libcrux-ml-kem/c/libcrux_mlkem768_portable.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "libcrux_mlkem768_portable.h" diff --git a/libcrux-ml-kem/c/libcrux_mlkem768_portable.h b/libcrux-ml-kem/c/libcrux_mlkem768_portable.h index 2cd183b3..4b45aaf5 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem768_portable.h +++ b/libcrux-ml-kem/c/libcrux_mlkem768_portable.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem768_portable_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem_avx2.c b/libcrux-ml-kem/c/libcrux_mlkem_avx2.c index c767b1b1..46112ceb 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem_avx2.c +++ b/libcrux-ml-kem/c/libcrux_mlkem_avx2.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "internal/libcrux_mlkem_avx2.h" @@ -1761,7 +1761,7 @@ bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_avx2_SIMD Eurydice_array_to_subslice_from((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), public_key_serialized); - return core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq( + return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( (size_t)1184U, public_key, public_key_serialized, uint8_t, uint8_t, bool); } @@ -1788,52 +1788,41 @@ closure__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_ libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector)); } -static inline libcrux_sha3_avx2_x4_incremental_KeccakState4 +static inline libcrux_sha3_avx2_x4_incremental_KeccakState shake128_init_absorb___3size_t(uint8_t input[3U][34U]) { libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t state = libcrux_sha3_avx2_x4_incremental_shake128_init(); - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = &state; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)34U, input[1U], uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)34U, input[2U], uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_absorb_final( - uu____0, uu____1, uu____2, uu____3, + &state, + Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)34U, input[1U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)34U, input[2U], uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice)); return state; } static inline void shake128_squeeze_three_blocks___3size_t( - libcrux_sha3_avx2_x4_incremental_KeccakState4 *self, - uint8_t ret[3U][504U]) { + libcrux_sha3_avx2_x4_incremental_KeccakState *self, uint8_t ret[3U][504U]) { uint8_t out[3U][504U] = {{0U}}; uint8_t out0[504U] = {0U}; uint8_t out1[504U] = {0U}; uint8_t out2[504U] = {0U}; uint8_t out3[504U] = {0U}; - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = self; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)504U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)504U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)504U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_squeeze_first_three_blocks( - uu____0, uu____1, uu____2, uu____3, + self, + Eurydice_array_to_slice((size_t)504U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)504U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)504U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)504U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____4[504U]; - memcpy(uu____4, out0, (size_t)504U * sizeof(uint8_t)); - memcpy(out[0U], uu____4, (size_t)504U * sizeof(uint8_t)); - uint8_t uu____5[504U]; - memcpy(uu____5, out1, (size_t)504U * sizeof(uint8_t)); - memcpy(out[1U], uu____5, (size_t)504U * sizeof(uint8_t)); - uint8_t uu____6[504U]; - memcpy(uu____6, out2, (size_t)504U * sizeof(uint8_t)); - memcpy(out[2U], uu____6, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____0[504U]; + memcpy(uu____0, out0, (size_t)504U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____1[504U]; + memcpy(uu____1, out1, (size_t)504U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____2[504U]; + memcpy(uu____2, out2, (size_t)504U * sizeof(uint8_t)); + memcpy(out[2U], uu____2, (size_t)504U * sizeof(uint8_t)); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[504U])); } @@ -1879,33 +1868,27 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_avx2_SIMD256Vector_ } static inline void shake128_squeeze_block___3size_t( - libcrux_sha3_avx2_x4_incremental_KeccakState4 *self, - uint8_t ret[3U][168U]) { + libcrux_sha3_avx2_x4_incremental_KeccakState *self, uint8_t ret[3U][168U]) { uint8_t out[3U][168U] = {{0U}}; uint8_t out0[168U] = {0U}; uint8_t out1[168U] = {0U}; uint8_t out2[168U] = {0U}; uint8_t out3[168U] = {0U}; - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = self; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)168U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)168U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)168U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_squeeze_next_block( - uu____0, uu____1, uu____2, uu____3, + self, + Eurydice_array_to_slice((size_t)168U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)168U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)168U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)168U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____4[168U]; - memcpy(uu____4, out0, (size_t)168U * sizeof(uint8_t)); - memcpy(out[0U], uu____4, (size_t)168U * sizeof(uint8_t)); - uint8_t uu____5[168U]; - memcpy(uu____5, out1, (size_t)168U * sizeof(uint8_t)); - memcpy(out[1U], uu____5, (size_t)168U * sizeof(uint8_t)); - uint8_t uu____6[168U]; - memcpy(uu____6, out2, (size_t)168U * sizeof(uint8_t)); - memcpy(out[2U], uu____6, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____0[168U]; + memcpy(uu____0, out0, (size_t)168U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____1[168U]; + memcpy(uu____1, out1, (size_t)168U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____2[168U]; + memcpy(uu____2, out2, (size_t)168U * sizeof(uint8_t)); + memcpy(out[2U], uu____2, (size_t)168U * sizeof(uint8_t)); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[168U])); } @@ -1990,7 +1973,7 @@ sample_from_xof__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_fu int16_t out[3U][272U] = {{0U}}; uint8_t uu____0[3U][34U]; memcpy(uu____0, seeds, (size_t)3U * sizeof(uint8_t[34U])); - libcrux_sha3_avx2_x4_incremental_KeccakState4 xof_state = + libcrux_sha3_avx2_x4_incremental_KeccakState xof_state = shake128_init_absorb___3size_t(uu____0); uint8_t randomness0[3U][504U]; shake128_squeeze_three_blocks___3size_t(&xof_state, randomness0); @@ -2096,32 +2079,24 @@ static inline void PRFxN___3size_t_128size_t(uint8_t (*input)[33U], uint8_t out1[128U] = {0U}; uint8_t out2[128U] = {0U}; uint8_t out3[128U] = {0U}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)33U, input[2U], uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____4 = - Eurydice_array_to_slice((size_t)128U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____5 = - Eurydice_array_to_slice((size_t)128U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____6 = - Eurydice_array_to_slice((size_t)128U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_shake256( - uu____0, uu____1, uu____2, uu____3, uu____4, uu____5, uu____6, + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[2U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)128U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____7[128U]; - memcpy(uu____7, out0, (size_t)128U * sizeof(uint8_t)); - memcpy(out[0U], uu____7, (size_t)128U * sizeof(uint8_t)); - uint8_t uu____8[128U]; - memcpy(uu____8, out1, (size_t)128U * sizeof(uint8_t)); - memcpy(out[1U], uu____8, (size_t)128U * sizeof(uint8_t)); - uint8_t uu____9[128U]; - memcpy(uu____9, out2, (size_t)128U * sizeof(uint8_t)); - memcpy(out[2U], uu____9, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____0[128U]; + memcpy(uu____0, out0, (size_t)128U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____1[128U]; + memcpy(uu____1, out1, (size_t)128U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____2[128U]; + memcpy(uu____2, out2, (size_t)128U * sizeof(uint8_t)); + memcpy(out[2U], uu____2, (size_t)128U * sizeof(uint8_t)); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[128U])); } @@ -2745,26 +2720,25 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_avx2_SIMD256Vecto memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1152U * sizeof(uint8_t)); uint8_t public_key[1184U]; memcpy(public_key, uu____0.snd, (size_t)1184U * sizeof(uint8_t)); - Eurydice_slice uu____1 = Eurydice_array_to_slice( - (size_t)1152U, ind_cpa_private_key, uint8_t, Eurydice_slice); uint8_t secret_key_serialized[2400U]; serialize_kem_secret_key__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_2400size_t( - uu____1, + Eurydice_array_to_slice((size_t)1152U, ind_cpa_private_key, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)1184U, public_key, uint8_t, Eurydice_slice), implicit_rejection_value, secret_key_serialized); - uint8_t uu____2[2400U]; - memcpy(uu____2, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); + uint8_t uu____1[2400U]; + memcpy(uu____1, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey____2400size_t private_key = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPrivateKey_SIZE___8__from___2400size_t( - uu____2); - libcrux_ml_kem_types_MlKemPrivateKey____2400size_t uu____3 = private_key; - uint8_t uu____4[1184U]; - memcpy(uu____4, public_key, (size_t)1184U * sizeof(uint8_t)); + uu____1); + libcrux_ml_kem_types_MlKemPrivateKey____2400size_t uu____2 = private_key; + uint8_t uu____3[1184U]; + memcpy(uu____3, public_key, (size_t)1184U * sizeof(uint8_t)); return libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemKeyPair_PRIVATE_KEY_SIZE__PUBLIC_KEY_SIZE___from___2400size_t_1184size_t( - uu____3, + uu____2, libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPublicKey_SIZE___14__from___1184size_t( - uu____4)); + uu____3)); } static inline void @@ -3074,10 +3048,11 @@ compute_vector_u__libcrux_ml_kem_vector_avx2_SIMD256Vector_3size_t( static core_core_arch_x86___m256i decompress_1__libcrux_ml_kem_vector_avx2_SIMD256Vector( core_core_arch_x86___m256i v) { + core_core_arch_x86___m256i uu____0 = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ZERO(); return libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___bitwise_and_with_constant( libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___sub( - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ZERO(), - &v), + uu____0, &v), (int16_t)1665); } @@ -4387,11 +4362,10 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vecto uint8_t shared_secret[32U]; kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_1088size_t( shared_secret0, shared_secret); - Eurydice_slice uu____9 = Eurydice_array_to_slice((size_t)32U, shared_secret, - uint8_t, Eurydice_slice); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( - uu____9, + Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t, Eurydice_slice), selector, ret0); @@ -4525,7 +4499,7 @@ bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_avx2_SIMD Eurydice_array_to_subslice_from((size_t)1568U, public_key, (size_t)1536U, uint8_t, size_t, Eurydice_slice), public_key_serialized); - return core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq( + return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( (size_t)1568U, public_key, public_key_serialized, uint8_t, uint8_t, bool); } @@ -4552,55 +4526,44 @@ closure__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_ libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector)); } -static inline libcrux_sha3_avx2_x4_incremental_KeccakState4 +static inline libcrux_sha3_avx2_x4_incremental_KeccakState shake128_init_absorb___4size_t(uint8_t input[4U][34U]) { libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t state = libcrux_sha3_avx2_x4_incremental_shake128_init(); - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = &state; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)34U, input[1U], uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)34U, input[2U], uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_absorb_final( - uu____0, uu____1, uu____2, uu____3, + &state, + Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)34U, input[1U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)34U, input[2U], uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)34U, input[3U], uint8_t, Eurydice_slice)); return state; } static inline void shake128_squeeze_three_blocks___4size_t( - libcrux_sha3_avx2_x4_incremental_KeccakState4 *self, - uint8_t ret[4U][504U]) { + libcrux_sha3_avx2_x4_incremental_KeccakState *self, uint8_t ret[4U][504U]) { uint8_t out[4U][504U] = {{0U}}; uint8_t out0[504U] = {0U}; uint8_t out1[504U] = {0U}; uint8_t out2[504U] = {0U}; uint8_t out3[504U] = {0U}; - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = self; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)504U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)504U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)504U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_squeeze_first_three_blocks( - uu____0, uu____1, uu____2, uu____3, + self, + Eurydice_array_to_slice((size_t)504U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)504U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)504U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)504U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____4[504U]; - memcpy(uu____4, out0, (size_t)504U * sizeof(uint8_t)); - memcpy(out[0U], uu____4, (size_t)504U * sizeof(uint8_t)); - uint8_t uu____5[504U]; - memcpy(uu____5, out1, (size_t)504U * sizeof(uint8_t)); - memcpy(out[1U], uu____5, (size_t)504U * sizeof(uint8_t)); - uint8_t uu____6[504U]; - memcpy(uu____6, out2, (size_t)504U * sizeof(uint8_t)); - memcpy(out[2U], uu____6, (size_t)504U * sizeof(uint8_t)); - uint8_t uu____7[504U]; - memcpy(uu____7, out3, (size_t)504U * sizeof(uint8_t)); - memcpy(out[3U], uu____7, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____0[504U]; + memcpy(uu____0, out0, (size_t)504U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____1[504U]; + memcpy(uu____1, out1, (size_t)504U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____2[504U]; + memcpy(uu____2, out2, (size_t)504U * sizeof(uint8_t)); + memcpy(out[2U], uu____2, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____3[504U]; + memcpy(uu____3, out3, (size_t)504U * sizeof(uint8_t)); + memcpy(out[3U], uu____3, (size_t)504U * sizeof(uint8_t)); memcpy(ret, out, (size_t)4U * sizeof(uint8_t[504U])); } @@ -4646,36 +4609,30 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_avx2_SIMD256Vector_ } static inline void shake128_squeeze_block___4size_t( - libcrux_sha3_avx2_x4_incremental_KeccakState4 *self, - uint8_t ret[4U][168U]) { + libcrux_sha3_avx2_x4_incremental_KeccakState *self, uint8_t ret[4U][168U]) { uint8_t out[4U][168U] = {{0U}}; uint8_t out0[168U] = {0U}; uint8_t out1[168U] = {0U}; uint8_t out2[168U] = {0U}; uint8_t out3[168U] = {0U}; - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = self; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)168U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)168U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)168U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_squeeze_next_block( - uu____0, uu____1, uu____2, uu____3, + self, + Eurydice_array_to_slice((size_t)168U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)168U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)168U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)168U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____4[168U]; - memcpy(uu____4, out0, (size_t)168U * sizeof(uint8_t)); - memcpy(out[0U], uu____4, (size_t)168U * sizeof(uint8_t)); - uint8_t uu____5[168U]; - memcpy(uu____5, out1, (size_t)168U * sizeof(uint8_t)); - memcpy(out[1U], uu____5, (size_t)168U * sizeof(uint8_t)); - uint8_t uu____6[168U]; - memcpy(uu____6, out2, (size_t)168U * sizeof(uint8_t)); - memcpy(out[2U], uu____6, (size_t)168U * sizeof(uint8_t)); - uint8_t uu____7[168U]; - memcpy(uu____7, out3, (size_t)168U * sizeof(uint8_t)); - memcpy(out[3U], uu____7, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____0[168U]; + memcpy(uu____0, out0, (size_t)168U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____1[168U]; + memcpy(uu____1, out1, (size_t)168U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____2[168U]; + memcpy(uu____2, out2, (size_t)168U * sizeof(uint8_t)); + memcpy(out[2U], uu____2, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____3[168U]; + memcpy(uu____3, out3, (size_t)168U * sizeof(uint8_t)); + memcpy(out[3U], uu____3, (size_t)168U * sizeof(uint8_t)); memcpy(ret, out, (size_t)4U * sizeof(uint8_t[168U])); } @@ -4740,7 +4697,7 @@ sample_from_xof__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_fu int16_t out[4U][272U] = {{0U}}; uint8_t uu____0[4U][34U]; memcpy(uu____0, seeds, (size_t)4U * sizeof(uint8_t[34U])); - libcrux_sha3_avx2_x4_incremental_KeccakState4 xof_state = + libcrux_sha3_avx2_x4_incremental_KeccakState xof_state = shake128_init_absorb___4size_t(uu____0); uint8_t randomness0[4U][504U]; shake128_squeeze_three_blocks___4size_t(&xof_state, randomness0); @@ -4846,35 +4803,27 @@ static inline void PRFxN___4size_t_128size_t(uint8_t (*input)[33U], uint8_t out1[128U] = {0U}; uint8_t out2[128U] = {0U}; uint8_t out3[128U] = {0U}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)33U, input[2U], uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)33U, input[3U], uint8_t, Eurydice_slice); - Eurydice_slice uu____4 = - Eurydice_array_to_slice((size_t)128U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____5 = - Eurydice_array_to_slice((size_t)128U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____6 = - Eurydice_array_to_slice((size_t)128U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_shake256( - uu____0, uu____1, uu____2, uu____3, uu____4, uu____5, uu____6, + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[2U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[3U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)128U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____7[128U]; - memcpy(uu____7, out0, (size_t)128U * sizeof(uint8_t)); - memcpy(out[0U], uu____7, (size_t)128U * sizeof(uint8_t)); - uint8_t uu____8[128U]; - memcpy(uu____8, out1, (size_t)128U * sizeof(uint8_t)); - memcpy(out[1U], uu____8, (size_t)128U * sizeof(uint8_t)); - uint8_t uu____9[128U]; - memcpy(uu____9, out2, (size_t)128U * sizeof(uint8_t)); - memcpy(out[2U], uu____9, (size_t)128U * sizeof(uint8_t)); - uint8_t uu____10[128U]; - memcpy(uu____10, out3, (size_t)128U * sizeof(uint8_t)); - memcpy(out[3U], uu____10, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____0[128U]; + memcpy(uu____0, out0, (size_t)128U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____1[128U]; + memcpy(uu____1, out1, (size_t)128U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____2[128U]; + memcpy(uu____2, out2, (size_t)128U * sizeof(uint8_t)); + memcpy(out[2U], uu____2, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____3[128U]; + memcpy(uu____3, out3, (size_t)128U * sizeof(uint8_t)); + memcpy(out[3U], uu____3, (size_t)128U * sizeof(uint8_t)); memcpy(ret, out, (size_t)4U * sizeof(uint8_t[128U])); } @@ -5176,26 +5125,25 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_avx2_SIMD256Vecto memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1536U * sizeof(uint8_t)); uint8_t public_key[1568U]; memcpy(public_key, uu____0.snd, (size_t)1568U * sizeof(uint8_t)); - Eurydice_slice uu____1 = Eurydice_array_to_slice( - (size_t)1536U, ind_cpa_private_key, uint8_t, Eurydice_slice); uint8_t secret_key_serialized[3168U]; serialize_kem_secret_key__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_4size_t_3168size_t( - uu____1, + Eurydice_array_to_slice((size_t)1536U, ind_cpa_private_key, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)1568U, public_key, uint8_t, Eurydice_slice), implicit_rejection_value, secret_key_serialized); - uint8_t uu____2[3168U]; - memcpy(uu____2, secret_key_serialized, (size_t)3168U * sizeof(uint8_t)); + uint8_t uu____1[3168U]; + memcpy(uu____1, secret_key_serialized, (size_t)3168U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey____3168size_t private_key = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPrivateKey_SIZE___8__from___3168size_t( - uu____2); - libcrux_ml_kem_types_MlKemPrivateKey____3168size_t uu____3 = private_key; - uint8_t uu____4[1568U]; - memcpy(uu____4, public_key, (size_t)1568U * sizeof(uint8_t)); + uu____1); + libcrux_ml_kem_types_MlKemPrivateKey____3168size_t uu____2 = private_key; + uint8_t uu____3[1568U]; + memcpy(uu____3, public_key, (size_t)1568U * sizeof(uint8_t)); return libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemKeyPair_PRIVATE_KEY_SIZE__PUBLIC_KEY_SIZE___from___3168size_t_1568size_t( - uu____3, + uu____2, libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPublicKey_SIZE___14__from___1568size_t( - uu____4)); + uu____3)); } static inline void @@ -5924,11 +5872,10 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vecto uint8_t shared_secret[32U]; kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_4size_t_1568size_t( shared_secret0, shared_secret); - Eurydice_slice uu____9 = Eurydice_array_to_slice((size_t)32U, shared_secret, - uint8_t, Eurydice_slice); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( - uu____9, + Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t, Eurydice_slice), selector, ret0); @@ -6062,7 +6009,7 @@ bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_avx2_SIMD Eurydice_array_to_subslice_from((size_t)800U, public_key, (size_t)768U, uint8_t, size_t, Eurydice_slice), public_key_serialized); - return core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq( + return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( (size_t)800U, public_key, public_key_serialized, uint8_t, uint8_t, bool); } @@ -6089,49 +6036,38 @@ closure__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_ libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector)); } -static inline libcrux_sha3_avx2_x4_incremental_KeccakState4 +static inline libcrux_sha3_avx2_x4_incremental_KeccakState shake128_init_absorb___2size_t(uint8_t input[2U][34U]) { libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t state = libcrux_sha3_avx2_x4_incremental_shake128_init(); - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = &state; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)34U, input[1U], uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_absorb_final( - uu____0, uu____1, uu____2, uu____3, + &state, + Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)34U, input[1U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice)); return state; } static inline void shake128_squeeze_three_blocks___2size_t( - libcrux_sha3_avx2_x4_incremental_KeccakState4 *self, - uint8_t ret[2U][504U]) { + libcrux_sha3_avx2_x4_incremental_KeccakState *self, uint8_t ret[2U][504U]) { uint8_t out[2U][504U] = {{0U}}; uint8_t out0[504U] = {0U}; uint8_t out1[504U] = {0U}; uint8_t out2[504U] = {0U}; uint8_t out3[504U] = {0U}; - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = self; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)504U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)504U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)504U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_squeeze_first_three_blocks( - uu____0, uu____1, uu____2, uu____3, + self, + Eurydice_array_to_slice((size_t)504U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)504U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)504U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)504U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____4[504U]; - memcpy(uu____4, out0, (size_t)504U * sizeof(uint8_t)); - memcpy(out[0U], uu____4, (size_t)504U * sizeof(uint8_t)); - uint8_t uu____5[504U]; - memcpy(uu____5, out1, (size_t)504U * sizeof(uint8_t)); - memcpy(out[1U], uu____5, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____0[504U]; + memcpy(uu____0, out0, (size_t)504U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____1[504U]; + memcpy(uu____1, out1, (size_t)504U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)504U * sizeof(uint8_t)); memcpy(ret, out, (size_t)2U * sizeof(uint8_t[504U])); } @@ -6177,30 +6113,24 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_avx2_SIMD256Vector_ } static inline void shake128_squeeze_block___2size_t( - libcrux_sha3_avx2_x4_incremental_KeccakState4 *self, - uint8_t ret[2U][168U]) { + libcrux_sha3_avx2_x4_incremental_KeccakState *self, uint8_t ret[2U][168U]) { uint8_t out[2U][168U] = {{0U}}; uint8_t out0[168U] = {0U}; uint8_t out1[168U] = {0U}; uint8_t out2[168U] = {0U}; uint8_t out3[168U] = {0U}; - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = self; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)168U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)168U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)168U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_squeeze_next_block( - uu____0, uu____1, uu____2, uu____3, + self, + Eurydice_array_to_slice((size_t)168U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)168U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)168U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)168U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____4[168U]; - memcpy(uu____4, out0, (size_t)168U * sizeof(uint8_t)); - memcpy(out[0U], uu____4, (size_t)168U * sizeof(uint8_t)); - uint8_t uu____5[168U]; - memcpy(uu____5, out1, (size_t)168U * sizeof(uint8_t)); - memcpy(out[1U], uu____5, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____0[168U]; + memcpy(uu____0, out0, (size_t)168U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____1[168U]; + memcpy(uu____1, out1, (size_t)168U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)168U * sizeof(uint8_t)); memcpy(ret, out, (size_t)2U * sizeof(uint8_t[168U])); } @@ -6265,7 +6195,7 @@ sample_from_xof__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_fu int16_t out[2U][272U] = {{0U}}; uint8_t uu____0[2U][34U]; memcpy(uu____0, seeds, (size_t)2U * sizeof(uint8_t[34U])); - libcrux_sha3_avx2_x4_incremental_KeccakState4 xof_state = + libcrux_sha3_avx2_x4_incremental_KeccakState xof_state = shake128_init_absorb___2size_t(uu____0); uint8_t randomness0[2U][504U]; shake128_squeeze_three_blocks___2size_t(&xof_state, randomness0); @@ -6371,29 +6301,21 @@ static inline void PRFxN___2size_t_192size_t(uint8_t (*input)[33U], uint8_t out1[192U] = {0U}; uint8_t out2[192U] = {0U}; uint8_t out3[192U] = {0U}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____4 = - Eurydice_array_to_slice((size_t)192U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____5 = - Eurydice_array_to_slice((size_t)192U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____6 = - Eurydice_array_to_slice((size_t)192U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_shake256( - uu____0, uu____1, uu____2, uu____3, uu____4, uu____5, uu____6, + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)192U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)192U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)192U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)192U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____7[192U]; - memcpy(uu____7, out0, (size_t)192U * sizeof(uint8_t)); - memcpy(out[0U], uu____7, (size_t)192U * sizeof(uint8_t)); - uint8_t uu____8[192U]; - memcpy(uu____8, out1, (size_t)192U * sizeof(uint8_t)); - memcpy(out[1U], uu____8, (size_t)192U * sizeof(uint8_t)); + uint8_t uu____0[192U]; + memcpy(uu____0, out0, (size_t)192U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)192U * sizeof(uint8_t)); + uint8_t uu____1[192U]; + memcpy(uu____1, out1, (size_t)192U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)192U * sizeof(uint8_t)); memcpy(ret, out, (size_t)2U * sizeof(uint8_t[192U])); } @@ -6706,26 +6628,25 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_avx2_SIMD256Vecto memcpy(ind_cpa_private_key, uu____0.fst, (size_t)768U * sizeof(uint8_t)); uint8_t public_key[800U]; memcpy(public_key, uu____0.snd, (size_t)800U * sizeof(uint8_t)); - Eurydice_slice uu____1 = Eurydice_array_to_slice( - (size_t)768U, ind_cpa_private_key, uint8_t, Eurydice_slice); uint8_t secret_key_serialized[1632U]; serialize_kem_secret_key__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_2size_t_1632size_t( - uu____1, + Eurydice_array_to_slice((size_t)768U, ind_cpa_private_key, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)800U, public_key, uint8_t, Eurydice_slice), implicit_rejection_value, secret_key_serialized); - uint8_t uu____2[1632U]; - memcpy(uu____2, secret_key_serialized, (size_t)1632U * sizeof(uint8_t)); + uint8_t uu____1[1632U]; + memcpy(uu____1, secret_key_serialized, (size_t)1632U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey____1632size_t private_key = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPrivateKey_SIZE___8__from___1632size_t( - uu____2); - libcrux_ml_kem_types_MlKemPrivateKey____1632size_t uu____3 = private_key; - uint8_t uu____4[800U]; - memcpy(uu____4, public_key, (size_t)800U * sizeof(uint8_t)); + uu____1); + libcrux_ml_kem_types_MlKemPrivateKey____1632size_t uu____2 = private_key; + uint8_t uu____3[800U]; + memcpy(uu____3, public_key, (size_t)800U * sizeof(uint8_t)); return libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemKeyPair_PRIVATE_KEY_SIZE__PUBLIC_KEY_SIZE___from___1632size_t_800size_t( - uu____3, + uu____2, libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPublicKey_SIZE___14__from___800size_t( - uu____4)); + uu____3)); } static inline void @@ -6782,29 +6703,21 @@ static inline void PRFxN___2size_t_128size_t(uint8_t (*input)[33U], uint8_t out1[128U] = {0U}; uint8_t out2[128U] = {0U}; uint8_t out3[128U] = {0U}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____4 = - Eurydice_array_to_slice((size_t)128U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____5 = - Eurydice_array_to_slice((size_t)128U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____6 = - Eurydice_array_to_slice((size_t)128U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_shake256( - uu____0, uu____1, uu____2, uu____3, uu____4, uu____5, uu____6, + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)128U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____7[128U]; - memcpy(uu____7, out0, (size_t)128U * sizeof(uint8_t)); - memcpy(out[0U], uu____7, (size_t)128U * sizeof(uint8_t)); - uint8_t uu____8[128U]; - memcpy(uu____8, out1, (size_t)128U * sizeof(uint8_t)); - memcpy(out[1U], uu____8, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____0[128U]; + memcpy(uu____0, out0, (size_t)128U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____1[128U]; + memcpy(uu____1, out1, (size_t)128U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)128U * sizeof(uint8_t)); memcpy(ret, out, (size_t)2U * sizeof(uint8_t[128U])); } @@ -7399,11 +7312,10 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vecto uint8_t shared_secret[32U]; kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_2size_t_768size_t( shared_secret0, shared_secret); - Eurydice_slice uu____9 = Eurydice_array_to_slice((size_t)32U, shared_secret, - uint8_t, Eurydice_slice); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( - uu____9, + Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t, Eurydice_slice), selector, ret0); diff --git a/libcrux-ml-kem/c/libcrux_mlkem_avx2.h b/libcrux-ml-kem/c/libcrux_mlkem_avx2.h index 024a0801..653e4cb9 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem_avx2.h +++ b/libcrux-ml-kem/c/libcrux_mlkem_avx2.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem_avx2_H diff --git a/libcrux-ml-kem/c/libcrux_mlkem_portable.c b/libcrux-ml-kem/c/libcrux_mlkem_portable.c index 4e0f1677..015b1272 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem_portable.c +++ b/libcrux-ml-kem/c/libcrux_mlkem_portable.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "internal/libcrux_mlkem_portable.h" @@ -690,7 +690,7 @@ inline libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_cond_subtract_3329( libcrux_ml_kem_vector_portable_PortableVector v) { core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR}), @@ -2102,72 +2102,61 @@ libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_m inline size_t libcrux_ml_kem_vector_rej_sample(Eurydice_slice a, Eurydice_slice result) { size_t sampled = (size_t)0U; - core_slice_iter_Chunks iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( - core_slice___Slice_T___chunks(a, (size_t)3U, uint8_t, - core_slice_iter_Chunks), - core_slice_iter_Chunks, core_slice_iter_Chunks); - while (true) { - core_option_Option__Eurydice_slice_uint8_t uu____0 = - core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___70__next( - &iter, uint8_t, core_option_Option__Eurydice_slice_uint8_t); - if (uu____0.tag == core_option_None) { - break; - } else { - Eurydice_slice bytes = uu____0.f0; - int16_t b1 = (int16_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, - uint8_t *, uint8_t); - int16_t b2 = (int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, - uint8_t *, uint8_t); - int16_t b3 = (int16_t)Eurydice_slice_index(bytes, (size_t)2U, uint8_t, - uint8_t *, uint8_t); - int16_t d1 = (b2 & (int16_t)15) << 8U | b1; - int16_t d2 = b3 << 4U | b2 >> 4U; - bool uu____1; - int16_t uu____2; - bool uu____3; - size_t uu____4; - int16_t uu____5; - size_t uu____6; - int16_t uu____7; - if (d1 < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS) { - if (sampled < (size_t)16U) { - int16_t uu____8 = d1; - Eurydice_slice_index(result, sampled, int16_t, int16_t *, int16_t) = - uu____8; - sampled++; - uu____2 = d2; - uu____7 = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; - uu____1 = uu____2 < uu____7; - if (uu____1) { - uu____4 = sampled; - uu____3 = uu____4 < (size_t)16U; - if (uu____3) { - uu____5 = d2; - uu____6 = sampled; - Eurydice_slice_index(result, uu____6, int16_t, int16_t *, - int16_t) = uu____5; - sampled++; - continue; - } + for (size_t i = (size_t)0U; + i < core_slice___Slice_T___len(a, uint8_t, size_t) / (size_t)3U; i++) { + size_t i0 = i; + int16_t b1 = (int16_t)Eurydice_slice_index(a, i0 * (size_t)3U + (size_t)0U, + uint8_t, uint8_t *, uint8_t); + int16_t b2 = (int16_t)Eurydice_slice_index(a, i0 * (size_t)3U + (size_t)1U, + uint8_t, uint8_t *, uint8_t); + int16_t b3 = (int16_t)Eurydice_slice_index(a, i0 * (size_t)3U + (size_t)2U, + uint8_t, uint8_t *, uint8_t); + int16_t d1 = (b2 & (int16_t)15) << 8U | b1; + int16_t d2 = b3 << 4U | b2 >> 4U; + bool uu____0; + int16_t uu____1; + bool uu____2; + size_t uu____3; + int16_t uu____4; + size_t uu____5; + int16_t uu____6; + if (d1 < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS) { + if (sampled < (size_t)16U) { + int16_t uu____7 = d1; + Eurydice_slice_index(result, sampled, int16_t, int16_t *, int16_t) = + uu____7; + sampled++; + uu____1 = d2; + uu____6 = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; + uu____0 = uu____1 < uu____6; + if (uu____0) { + uu____3 = sampled; + uu____2 = uu____3 < (size_t)16U; + if (uu____2) { + uu____4 = d2; + uu____5 = sampled; + Eurydice_slice_index(result, uu____5, int16_t, int16_t *, int16_t) = + uu____4; + sampled++; + continue; } - continue; } + continue; } - uu____2 = d2; - uu____7 = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; - uu____1 = uu____2 < uu____7; - if (uu____1) { - uu____4 = sampled; - uu____3 = uu____4 < (size_t)16U; - if (uu____3) { - uu____5 = d2; - uu____6 = sampled; - Eurydice_slice_index(result, uu____6, int16_t, int16_t *, int16_t) = - uu____5; - sampled++; - continue; - } + } + uu____1 = d2; + uu____6 = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; + uu____0 = uu____1 < uu____6; + if (uu____0) { + uu____3 = sampled; + uu____2 = uu____3 < (size_t)16U; + if (uu____2) { + uu____4 = d2; + uu____5 = sampled; + Eurydice_slice_index(result, uu____5, int16_t, int16_t *, int16_t) = + uu____4; + sampled++; + continue; } } } @@ -2432,7 +2421,7 @@ bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_ Eurydice_array_to_subslice_from((size_t)1568U, public_key, (size_t)1536U, uint8_t, size_t, Eurydice_slice), public_key_serialized); - return core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq( + return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( (size_t)1568U, public_key, public_key_serialized, uint8_t, uint8_t, bool); } @@ -2472,19 +2461,17 @@ static inline PortableHash____4size_t shake128_init_absorb___4size_t( state[i] = libcrux_sha3_portable_incremental_shake128_init();); KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &state[i0]; libcrux_sha3_portable_incremental_shake128_absorb_final( - uu____0, Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, - Eurydice_slice));); - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t uu____1[4U]; + &state[i0], Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, + Eurydice_slice));); + libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t uu____0[4U]; memcpy( - uu____1, state, + uu____0, state, (size_t)4U * sizeof(libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t)); PortableHash____4size_t lit; memcpy( - lit.shake128_state, uu____1, + lit.shake128_state, uu____0, (size_t)4U * sizeof(libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t)); return lit; @@ -2495,11 +2482,10 @@ static inline void shake128_squeeze_three_blocks___4size_t( uint8_t out[4U][504U] = {{0U}}; KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &self->shake128_state[i0]; libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( - uu____0, Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, - Eurydice_slice));); + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)4U * sizeof(uint8_t[504U])); } @@ -2547,13 +2533,11 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe static inline void shake128_squeeze_block___4size_t( PortableHash____4size_t *self, uint8_t ret[4U][168U]) { uint8_t out[4U][168U] = {{0U}}; - KRML_MAYBE_FOR4( - i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &self->shake128_state[i0]; - libcrux_sha3_portable_incremental_shake128_squeeze_next_block( - uu____0, Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, - Eurydice_slice));); + KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; + libcrux_sha3_portable_incremental_shake128_squeeze_next_block( + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)4U * sizeof(uint8_t[168U])); } @@ -2740,13 +2724,12 @@ typedef struct static inline void PRFxN___4size_t_128size_t(uint8_t (*input)[33U], uint8_t ret[4U][128U]) { uint8_t out[4U][128U] = {{0U}}; - KRML_MAYBE_FOR4( - i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_slice((size_t)128U, out[i0], - uint8_t, Eurydice_slice); - libcrux_sha3_portable_shake256( - uu____0, Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, - Eurydice_slice));); + KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; + libcrux_sha3_portable_shake256( + Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t, + Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)4U * sizeof(uint8_t[128U])); } @@ -3375,26 +3358,25 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1536U * sizeof(uint8_t)); uint8_t public_key[1568U]; memcpy(public_key, uu____0.snd, (size_t)1568U * sizeof(uint8_t)); - Eurydice_slice uu____1 = Eurydice_array_to_slice( - (size_t)1536U, ind_cpa_private_key, uint8_t, Eurydice_slice); uint8_t secret_key_serialized[3168U]; serialize_kem_secret_key__libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_3168size_t( - uu____1, + Eurydice_array_to_slice((size_t)1536U, ind_cpa_private_key, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)1568U, public_key, uint8_t, Eurydice_slice), implicit_rejection_value, secret_key_serialized); - uint8_t uu____2[3168U]; - memcpy(uu____2, secret_key_serialized, (size_t)3168U * sizeof(uint8_t)); + uint8_t uu____1[3168U]; + memcpy(uu____1, secret_key_serialized, (size_t)3168U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey____3168size_t private_key = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPrivateKey_SIZE___8__from___3168size_t( - uu____2); - libcrux_ml_kem_types_MlKemPrivateKey____3168size_t uu____3 = private_key; - uint8_t uu____4[1568U]; - memcpy(uu____4, public_key, (size_t)1568U * sizeof(uint8_t)); + uu____1); + libcrux_ml_kem_types_MlKemPrivateKey____3168size_t uu____2 = private_key; + uint8_t uu____3[1568U]; + memcpy(uu____3, public_key, (size_t)1568U * sizeof(uint8_t)); return libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemKeyPair_PRIVATE_KEY_SIZE__PUBLIC_KEY_SIZE___from___3168size_t_1568size_t( - uu____3, + uu____2, libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPublicKey_SIZE___14__from___1568size_t( - uu____4)); + uu____3)); } static inline void @@ -3708,10 +3690,11 @@ compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t( static libcrux_ml_kem_vector_portable_PortableVector decompress_1__libcrux_ml_kem_vector_portable_PortableVector( libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_PortableVector uu____0 = + libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___bitwise_and_with_constant( libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(), - &v), + uu____0, &v), (int16_t)1665); } @@ -4690,11 +4673,10 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable uint8_t shared_secret[32U]; kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1568size_t( shared_secret0, shared_secret); - Eurydice_slice uu____9 = Eurydice_array_to_slice((size_t)32U, shared_secret, - uint8_t, Eurydice_slice); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( - uu____9, + Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t, Eurydice_slice), selector, ret0); @@ -4828,7 +4810,7 @@ bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_ Eurydice_array_to_subslice_from((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), public_key_serialized); - return core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq( + return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( (size_t)1184U, public_key, public_key_serialized, uint8_t, uint8_t, bool); } @@ -4868,19 +4850,17 @@ static inline PortableHash____3size_t shake128_init_absorb___3size_t( state[i] = libcrux_sha3_portable_incremental_shake128_init();); KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &state[i0]; libcrux_sha3_portable_incremental_shake128_absorb_final( - uu____0, Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, - Eurydice_slice));); - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t uu____1[3U]; + &state[i0], Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, + Eurydice_slice));); + libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t uu____0[3U]; memcpy( - uu____1, state, + uu____0, state, (size_t)3U * sizeof(libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t)); PortableHash____3size_t lit; memcpy( - lit.shake128_state, uu____1, + lit.shake128_state, uu____0, (size_t)3U * sizeof(libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t)); return lit; @@ -4891,11 +4871,10 @@ static inline void shake128_squeeze_three_blocks___3size_t( uint8_t out[3U][504U] = {{0U}}; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &self->shake128_state[i0]; libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( - uu____0, Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, - Eurydice_slice));); + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[504U])); } @@ -4943,13 +4922,11 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe static inline void shake128_squeeze_block___3size_t( PortableHash____3size_t *self, uint8_t ret[3U][168U]) { uint8_t out[3U][168U] = {{0U}}; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &self->shake128_state[i0]; - libcrux_sha3_portable_incremental_shake128_squeeze_next_block( - uu____0, Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, - Eurydice_slice));); + KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; + libcrux_sha3_portable_incremental_shake128_squeeze_next_block( + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[168U])); } @@ -5115,13 +5092,12 @@ typedef struct static inline void PRFxN___3size_t_128size_t(uint8_t (*input)[33U], uint8_t ret[3U][128U]) { uint8_t out[3U][128U] = {{0U}}; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_slice((size_t)128U, out[i0], - uint8_t, Eurydice_slice); - libcrux_sha3_portable_shake256( - uu____0, Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, - Eurydice_slice));); + KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; + libcrux_sha3_portable_shake256( + Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t, + Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[128U])); } @@ -5424,26 +5400,25 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1152U * sizeof(uint8_t)); uint8_t public_key[1184U]; memcpy(public_key, uu____0.snd, (size_t)1184U * sizeof(uint8_t)); - Eurydice_slice uu____1 = Eurydice_array_to_slice( - (size_t)1152U, ind_cpa_private_key, uint8_t, Eurydice_slice); uint8_t secret_key_serialized[2400U]; serialize_kem_secret_key__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2400size_t( - uu____1, + Eurydice_array_to_slice((size_t)1152U, ind_cpa_private_key, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)1184U, public_key, uint8_t, Eurydice_slice), implicit_rejection_value, secret_key_serialized); - uint8_t uu____2[2400U]; - memcpy(uu____2, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); + uint8_t uu____1[2400U]; + memcpy(uu____1, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey____2400size_t private_key = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPrivateKey_SIZE___8__from___2400size_t( - uu____2); - libcrux_ml_kem_types_MlKemPrivateKey____2400size_t uu____3 = private_key; - uint8_t uu____4[1184U]; - memcpy(uu____4, public_key, (size_t)1184U * sizeof(uint8_t)); + uu____1); + libcrux_ml_kem_types_MlKemPrivateKey____2400size_t uu____2 = private_key; + uint8_t uu____3[1184U]; + memcpy(uu____3, public_key, (size_t)1184U * sizeof(uint8_t)); return libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemKeyPair_PRIVATE_KEY_SIZE__PUBLIC_KEY_SIZE___from___2400size_t_1184size_t( - uu____3, + uu____2, libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPublicKey_SIZE___14__from___1184size_t( - uu____4)); + uu____3)); } static inline void @@ -6178,11 +6153,10 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable uint8_t shared_secret[32U]; kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t( shared_secret0, shared_secret); - Eurydice_slice uu____9 = Eurydice_array_to_slice((size_t)32U, shared_secret, - uint8_t, Eurydice_slice); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( - uu____9, + Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t, Eurydice_slice), selector, ret0); @@ -6316,7 +6290,7 @@ bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_ Eurydice_array_to_subslice_from((size_t)800U, public_key, (size_t)768U, uint8_t, size_t, Eurydice_slice), public_key_serialized); - return core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq( + return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( (size_t)800U, public_key, public_key_serialized, uint8_t, uint8_t, bool); } @@ -6356,19 +6330,17 @@ static inline PortableHash____2size_t shake128_init_absorb___2size_t( state[i] = libcrux_sha3_portable_incremental_shake128_init();); KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &state[i0]; libcrux_sha3_portable_incremental_shake128_absorb_final( - uu____0, Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, - Eurydice_slice));); - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t uu____1[2U]; + &state[i0], Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, + Eurydice_slice));); + libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t uu____0[2U]; memcpy( - uu____1, state, + uu____0, state, (size_t)2U * sizeof(libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t)); PortableHash____2size_t lit; memcpy( - lit.shake128_state, uu____1, + lit.shake128_state, uu____0, (size_t)2U * sizeof(libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t)); return lit; @@ -6379,11 +6351,10 @@ static inline void shake128_squeeze_three_blocks___2size_t( uint8_t out[2U][504U] = {{0U}}; KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &self->shake128_state[i0]; libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( - uu____0, Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, - Eurydice_slice));); + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)2U * sizeof(uint8_t[504U])); } @@ -6431,13 +6402,11 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe static inline void shake128_squeeze_block___2size_t( PortableHash____2size_t *self, uint8_t ret[2U][168U]) { uint8_t out[2U][168U] = {{0U}}; - KRML_MAYBE_FOR2( - i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &self->shake128_state[i0]; - libcrux_sha3_portable_incremental_shake128_squeeze_next_block( - uu____0, Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, - Eurydice_slice));); + KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; + libcrux_sha3_portable_incremental_shake128_squeeze_next_block( + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)2U * sizeof(uint8_t[168U])); } @@ -6603,13 +6572,12 @@ typedef struct static inline void PRFxN___2size_t_192size_t(uint8_t (*input)[33U], uint8_t ret[2U][192U]) { uint8_t out[2U][192U] = {{0U}}; - KRML_MAYBE_FOR2( - i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_slice((size_t)192U, out[i0], - uint8_t, Eurydice_slice); - libcrux_sha3_portable_shake256( - uu____0, Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, - Eurydice_slice));); + KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; + libcrux_sha3_portable_shake256( + Eurydice_array_to_slice((size_t)192U, out[i0], uint8_t, + Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)2U * sizeof(uint8_t[192U])); } @@ -6923,26 +6891,25 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable memcpy(ind_cpa_private_key, uu____0.fst, (size_t)768U * sizeof(uint8_t)); uint8_t public_key[800U]; memcpy(public_key, uu____0.snd, (size_t)800U * sizeof(uint8_t)); - Eurydice_slice uu____1 = Eurydice_array_to_slice( - (size_t)768U, ind_cpa_private_key, uint8_t, Eurydice_slice); uint8_t secret_key_serialized[1632U]; serialize_kem_secret_key__libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_1632size_t( - uu____1, + Eurydice_array_to_slice((size_t)768U, ind_cpa_private_key, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)800U, public_key, uint8_t, Eurydice_slice), implicit_rejection_value, secret_key_serialized); - uint8_t uu____2[1632U]; - memcpy(uu____2, secret_key_serialized, (size_t)1632U * sizeof(uint8_t)); + uint8_t uu____1[1632U]; + memcpy(uu____1, secret_key_serialized, (size_t)1632U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey____1632size_t private_key = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPrivateKey_SIZE___8__from___1632size_t( - uu____2); - libcrux_ml_kem_types_MlKemPrivateKey____1632size_t uu____3 = private_key; - uint8_t uu____4[800U]; - memcpy(uu____4, public_key, (size_t)800U * sizeof(uint8_t)); + uu____1); + libcrux_ml_kem_types_MlKemPrivateKey____1632size_t uu____2 = private_key; + uint8_t uu____3[800U]; + memcpy(uu____3, public_key, (size_t)800U * sizeof(uint8_t)); return libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemKeyPair_PRIVATE_KEY_SIZE__PUBLIC_KEY_SIZE___from___1632size_t_800size_t( - uu____3, + uu____2, libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPublicKey_SIZE___14__from___800size_t( - uu____4)); + uu____3)); } static inline void @@ -6995,13 +6962,12 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector static inline void PRFxN___2size_t_128size_t(uint8_t (*input)[33U], uint8_t ret[2U][128U]) { uint8_t out[2U][128U] = {{0U}}; - KRML_MAYBE_FOR2( - i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_slice((size_t)128U, out[i0], - uint8_t, Eurydice_slice); - libcrux_sha3_portable_shake256( - uu____0, Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, - Eurydice_slice));); + KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; + libcrux_sha3_portable_shake256( + Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t, + Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)2U * sizeof(uint8_t[128U])); } @@ -7601,11 +7567,10 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable uint8_t shared_secret[32U]; kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t( shared_secret0, shared_secret); - Eurydice_slice uu____9 = Eurydice_array_to_slice((size_t)32U, shared_secret, - uint8_t, Eurydice_slice); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( - uu____9, + Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t, Eurydice_slice), selector, ret0); diff --git a/libcrux-ml-kem/c/libcrux_mlkem_portable.h b/libcrux-ml-kem/c/libcrux_mlkem_portable.h index 7d4843f6..a7e7cef8 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem_portable.h +++ b/libcrux-ml-kem/c/libcrux_mlkem_portable.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem_portable_H diff --git a/libcrux-ml-kem/c/libcrux_sha3.h b/libcrux-ml-kem/c/libcrux_sha3.h index 21f3d570..7559883e 100644 --- a/libcrux-ml-kem/c/libcrux_sha3.h +++ b/libcrux-ml-kem/c/libcrux_sha3.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_sha3_H diff --git a/libcrux-ml-kem/c/libcrux_sha3_avx2.c b/libcrux-ml-kem/c/libcrux_sha3_avx2.c index 9f8d2d17..bcbd6859 100644 --- a/libcrux-ml-kem/c/libcrux_sha3_avx2.c +++ b/libcrux-ml-kem/c/libcrux_sha3_avx2.c @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "internal/libcrux_sha3_avx2.h" @@ -1002,8 +1002,7 @@ static inline void pi__core_core_arch_x86___m256i_4size_t( libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t *s) { core_core_arch_x86___m256i old[5U][5U]; - core_array___core__clone__Clone_for__Array_T__N___20__clone( - (size_t)5U, s->st, old, core_core_arch_x86___m256i[5U], void *); + memcpy(old, s->st, (size_t)5U * sizeof(core_core_arch_x86___m256i[5U])); s->st[0U][1U] = old[1U][1U]; s->st[0U][2U] = old[2U][2U]; s->st[0U][3U] = old[3U][3U]; @@ -1078,17 +1077,15 @@ static inline void absorb_block__core_core_arch_x86___m256i_4size_t_136size_t( static inline void load_block_full___136size_t( core_core_arch_x86___m256i (*s)[5U], uint8_t blocks[4U][200U]) { - core_core_arch_x86___m256i(*uu____0)[5U] = s; - Eurydice_slice uu____1 = Eurydice_array_to_slice((size_t)200U, blocks[0U], - uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = Eurydice_array_to_slice((size_t)200U, blocks[1U], - uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = Eurydice_array_to_slice((size_t)200U, blocks[2U], - uint8_t, Eurydice_slice); - Eurydice_slice buf[4U] = {uu____1, uu____2, uu____3, + Eurydice_slice buf[4U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], + uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, blocks[1U], + uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, blocks[2U], + uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)200U, blocks[3U], uint8_t, Eurydice_slice)}; - load_block___136size_t(uu____0, buf); + load_block___136size_t(s, buf); } static inline void load_block_full___136size_t0( @@ -1106,21 +1103,22 @@ absorb_final__core_core_arch_x86___m256i_4size_t_136size_t_31uint8_t( Eurydice_slice last[4U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[4U][200U] = {{0U}}; - KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i0], - (CLITERAL(core_ops_range_Range__size_t){ - .start = (size_t)0U, .end = last_len}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i0], - uint8_t, void *); - blocks[i0][last_len] = 31U; - blocks[i0][(size_t)136U - (size_t)1U] = - (uint32_t)blocks[i0][(size_t)136U - (size_t)1U] | 128U;); - core_core_arch_x86___m256i(*uu____1)[5U] = s->st; - uint8_t uu____2[4U][200U]; - memcpy(uu____2, blocks, (size_t)4U * sizeof(uint8_t[200U])); - load_block_full___136size_t0(uu____1, uu____2); + KRML_MAYBE_FOR4( + i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)200U, blocks[i0], + (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, + .end = last_len}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, + void *); + blocks[i0][last_len] = 31U; size_t uu____1 = i0; + size_t uu____2 = (size_t)136U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U;); + core_core_arch_x86___m256i(*uu____3)[5U] = s->st; + uint8_t uu____4[4U][200U]; + memcpy(uu____4, blocks, (size_t)4U * sizeof(uint8_t[200U])); + load_block_full___136size_t0(uu____3, uu____4); keccakf1600__core_core_arch_x86___m256i_4size_t(s); } @@ -1204,55 +1202,55 @@ static inline void store_block___136size_t(core_core_arch_x86___m256i (*s)[5U], uint8_t u8s[32U] = {0U}; size_t i0 = (size_t)4U * ((size_t)136U / (size_t)32U) / (size_t)5U; size_t j0 = (size_t)4U * ((size_t)136U / (size_t)32U) % (size_t)5U; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)32U, u8s, uint8_t, Eurydice_slice); - libcrux_intrinsics_avx2_mm256_storeu_si256_u8(uu____0, s[i0][j0]); - Eurydice_slice uu____1 = Eurydice_slice_subslice( + libcrux_intrinsics_avx2_mm256_storeu_si256_u8( + Eurydice_array_to_slice((size_t)32U, u8s, uint8_t, Eurydice_slice), + s[i0][j0]); + Eurydice_slice uu____0 = Eurydice_slice_subslice( out[0U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____1, + uu____0, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____2 = Eurydice_slice_subslice( + Eurydice_slice uu____1 = Eurydice_slice_subslice( out[1U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____2, + uu____1, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)8U, .end = (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____3 = Eurydice_slice_subslice( + Eurydice_slice uu____2 = Eurydice_slice_subslice( out[2U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____3, + uu____2, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)16U, .end = (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____4 = Eurydice_slice_subslice( + Eurydice_slice uu____3 = Eurydice_slice_subslice( out[3U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____4, + uu____3, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)24U, .end = (size_t)32U}), @@ -1265,55 +1263,55 @@ static inline void store_block___136size_t(core_core_arch_x86___m256i (*s)[5U], ((size_t)4U * ((size_t)136U / (size_t)32U) + (size_t)1U) / (size_t)5U; size_t j = ((size_t)4U * ((size_t)136U / (size_t)32U) + (size_t)1U) % (size_t)5U; - Eurydice_slice uu____5 = - Eurydice_array_to_slice((size_t)32U, u8s0, uint8_t, Eurydice_slice); - libcrux_intrinsics_avx2_mm256_storeu_si256_u8(uu____5, s[i][j]); - Eurydice_slice uu____6 = Eurydice_slice_subslice( + libcrux_intrinsics_avx2_mm256_storeu_si256_u8( + Eurydice_array_to_slice((size_t)32U, u8s0, uint8_t, Eurydice_slice), + s[i][j]); + Eurydice_slice uu____4 = Eurydice_slice_subslice( out[0U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____6, + uu____4, Eurydice_array_to_subslice((size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____7 = Eurydice_slice_subslice( + Eurydice_slice uu____5 = Eurydice_slice_subslice( out[1U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____7, + uu____5, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)8U, .end = (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____8 = Eurydice_slice_subslice( + Eurydice_slice uu____6 = Eurydice_slice_subslice( out[2U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____8, + uu____6, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)16U, .end = (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____9 = Eurydice_slice_subslice( + Eurydice_slice uu____7 = Eurydice_slice_subslice( out[3U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____9, + uu____7, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)24U, @@ -1329,29 +1327,24 @@ static inline void store_block_full___136size_t( uint8_t out1[200U] = {0U}; uint8_t out2[200U] = {0U}; uint8_t out3[200U] = {0U}; - core_core_arch_x86___m256i(*uu____0)[5U] = s; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)200U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)200U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)200U, out2, uint8_t, Eurydice_slice); Eurydice_slice buf[4U] = { - uu____1, uu____2, uu____3, + Eurydice_array_to_slice((size_t)200U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)200U, out3, uint8_t, Eurydice_slice)}; - store_block___136size_t(uu____0, buf); - uint8_t uu____4[200U]; - memcpy(uu____4, out0, (size_t)200U * sizeof(uint8_t)); - uint8_t uu____5[200U]; - memcpy(uu____5, out1, (size_t)200U * sizeof(uint8_t)); - uint8_t uu____6[200U]; - memcpy(uu____6, out2, (size_t)200U * sizeof(uint8_t)); - uint8_t uu____7[200U]; - memcpy(uu____7, out3, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____4, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[1U], uu____5, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[2U], uu____6, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[3U], uu____7, (size_t)200U * sizeof(uint8_t)); + store_block___136size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out0, (size_t)200U * sizeof(uint8_t)); + uint8_t uu____1[200U]; + memcpy(uu____1, out1, (size_t)200U * sizeof(uint8_t)); + uint8_t uu____2[200U]; + memcpy(uu____2, out2, (size_t)200U * sizeof(uint8_t)); + uint8_t uu____3[200U]; + memcpy(uu____3, out3, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[1U], uu____1, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[2U], uu____2, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[3U], uu____3, (size_t)200U * sizeof(uint8_t)); } static inline void store_block_full___136size_t0( @@ -1466,7 +1459,7 @@ keccak__core_core_arch_x86___m256i_4size_t_136size_t_31uint8_t( memcpy(o1, uu____4.snd, (size_t)4U * sizeof(Eurydice_slice)); squeeze_first_block__core_core_arch_x86___m256i_4size_t_136size_t(&s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -1717,17 +1710,15 @@ static inline void load_block___168size_t(core_core_arch_x86___m256i (*s)[5U], static inline void load_block_full___168size_t( core_core_arch_x86___m256i (*s)[5U], uint8_t blocks[4U][200U]) { - core_core_arch_x86___m256i(*uu____0)[5U] = s; - Eurydice_slice uu____1 = Eurydice_array_to_slice((size_t)200U, blocks[0U], - uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = Eurydice_array_to_slice((size_t)200U, blocks[1U], - uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = Eurydice_array_to_slice((size_t)200U, blocks[2U], - uint8_t, Eurydice_slice); - Eurydice_slice buf[4U] = {uu____1, uu____2, uu____3, + Eurydice_slice buf[4U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], + uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, blocks[1U], + uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, blocks[2U], + uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)200U, blocks[3U], uint8_t, Eurydice_slice)}; - load_block___168size_t(uu____0, buf); + load_block___168size_t(s, buf); } static inline void load_block_full___168size_t0( @@ -1745,21 +1736,22 @@ libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168 Eurydice_slice last[4U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[4U][200U] = {{0U}}; - KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i0], - (CLITERAL(core_ops_range_Range__size_t){ - .start = (size_t)0U, .end = last_len}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i0], - uint8_t, void *); - blocks[i0][last_len] = 31U; - blocks[i0][(size_t)168U - (size_t)1U] = - (uint32_t)blocks[i0][(size_t)168U - (size_t)1U] | 128U;); - core_core_arch_x86___m256i(*uu____1)[5U] = s->st; - uint8_t uu____2[4U][200U]; - memcpy(uu____2, blocks, (size_t)4U * sizeof(uint8_t[200U])); - load_block_full___168size_t0(uu____1, uu____2); + KRML_MAYBE_FOR4( + i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)200U, blocks[i0], + (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, + .end = last_len}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, + void *); + blocks[i0][last_len] = 31U; size_t uu____1 = i0; + size_t uu____2 = (size_t)168U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U;); + core_core_arch_x86___m256i(*uu____3)[5U] = s->st; + uint8_t uu____4[4U][200U]; + memcpy(uu____4, blocks, (size_t)4U * sizeof(uint8_t[200U])); + load_block_full___168size_t0(uu____3, uu____4); keccakf1600__core_core_arch_x86___m256i_4size_t(s); } @@ -1853,55 +1845,55 @@ static inline void store_block___168size_t(core_core_arch_x86___m256i (*s)[5U], uint8_t u8s[32U] = {0U}; size_t i0 = (size_t)4U * ((size_t)168U / (size_t)32U) / (size_t)5U; size_t j0 = (size_t)4U * ((size_t)168U / (size_t)32U) % (size_t)5U; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)32U, u8s, uint8_t, Eurydice_slice); - libcrux_intrinsics_avx2_mm256_storeu_si256_u8(uu____0, s[i0][j0]); - Eurydice_slice uu____1 = Eurydice_slice_subslice( + libcrux_intrinsics_avx2_mm256_storeu_si256_u8( + Eurydice_array_to_slice((size_t)32U, u8s, uint8_t, Eurydice_slice), + s[i0][j0]); + Eurydice_slice uu____0 = Eurydice_slice_subslice( out[0U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____1, + uu____0, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____2 = Eurydice_slice_subslice( + Eurydice_slice uu____1 = Eurydice_slice_subslice( out[1U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____2, + uu____1, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)8U, .end = (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____3 = Eurydice_slice_subslice( + Eurydice_slice uu____2 = Eurydice_slice_subslice( out[2U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____3, + uu____2, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)16U, .end = (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____4 = Eurydice_slice_subslice( + Eurydice_slice uu____3 = Eurydice_slice_subslice( out[3U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____4, + uu____3, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)24U, .end = (size_t)32U}), @@ -1914,55 +1906,55 @@ static inline void store_block___168size_t(core_core_arch_x86___m256i (*s)[5U], ((size_t)4U * ((size_t)168U / (size_t)32U) + (size_t)1U) / (size_t)5U; size_t j = ((size_t)4U * ((size_t)168U / (size_t)32U) + (size_t)1U) % (size_t)5U; - Eurydice_slice uu____5 = - Eurydice_array_to_slice((size_t)32U, u8s0, uint8_t, Eurydice_slice); - libcrux_intrinsics_avx2_mm256_storeu_si256_u8(uu____5, s[i][j]); - Eurydice_slice uu____6 = Eurydice_slice_subslice( + libcrux_intrinsics_avx2_mm256_storeu_si256_u8( + Eurydice_array_to_slice((size_t)32U, u8s0, uint8_t, Eurydice_slice), + s[i][j]); + Eurydice_slice uu____4 = Eurydice_slice_subslice( out[0U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____6, + uu____4, Eurydice_array_to_subslice((size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____7 = Eurydice_slice_subslice( + Eurydice_slice uu____5 = Eurydice_slice_subslice( out[1U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____7, + uu____5, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)8U, .end = (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____8 = Eurydice_slice_subslice( + Eurydice_slice uu____6 = Eurydice_slice_subslice( out[2U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____8, + uu____6, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)16U, .end = (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____9 = Eurydice_slice_subslice( + Eurydice_slice uu____7 = Eurydice_slice_subslice( out[3U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____9, + uu____7, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)24U, diff --git a/libcrux-ml-kem/c/libcrux_sha3_avx2.h b/libcrux-ml-kem/c/libcrux_sha3_avx2.h index 3f123391..0280b176 100644 --- a/libcrux-ml-kem/c/libcrux_sha3_avx2.h +++ b/libcrux-ml-kem/c/libcrux_sha3_avx2.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_sha3_avx2_H diff --git a/libcrux-ml-kem/c/libcrux_sha3_internal.h b/libcrux-ml-kem/c/libcrux_sha3_internal.h index 8c78b421..0a2911da 100644 --- a/libcrux-ml-kem/c/libcrux_sha3_internal.h +++ b/libcrux-ml-kem/c/libcrux_sha3_internal.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_sha3_internal_H @@ -234,10 +234,9 @@ static inline void libcrux_sha3_portable_keccak_load_block___168size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___168size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___168size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___168size_t(s, buf); } static inline void @@ -825,8 +824,7 @@ static inline void libcrux_sha3_generic_keccak_theta_rho__uint64_t_1size_t( static inline void libcrux_sha3_generic_keccak_pi__uint64_t_1size_t( libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *s) { uint64_t old[5U][5U]; - core_array___core__clone__Clone_for__Array_T__N___20__clone( - (size_t)5U, s->st, old, uint64_t[5U], void *); + memcpy(old, s->st, (size_t)5U * sizeof(uint64_t[5U])); s->st[0U][1U] = old[1U][1U]; s->st[0U][2U] = old[2U][2U]; s->st[0U][3U] = old[3U][3U]; @@ -901,14 +899,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_168size_t_31uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 31U; - blocks[i][(size_t)168U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)168U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)168U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___168size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -977,13 +976,12 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_168size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___168size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___168size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___168size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -1087,7 +1085,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_168size_t_31uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_168size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -1170,10 +1168,9 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_104size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___104size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___104size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___104size_t(s, buf); } static inline void @@ -1200,14 +1197,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_104size_t_6uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 6U; - blocks[i][(size_t)104U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)104U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)104U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___104size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -1232,13 +1230,12 @@ static inline void libcrux_sha3_portable_keccak_store_block___104size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___104size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___104size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___104size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -1365,7 +1362,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_104size_t_6uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_104size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -1448,10 +1445,9 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_144size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___144size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___144size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___144size_t(s, buf); } static inline void @@ -1478,14 +1474,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_144size_t_6uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 6U; - blocks[i][(size_t)144U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)144U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)144U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___144size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -1510,13 +1507,12 @@ static inline void libcrux_sha3_portable_keccak_store_block___144size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___144size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___144size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___144size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -1643,7 +1639,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_144size_t_6uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_144size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -1726,10 +1722,9 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_136size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___136size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___136size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___136size_t(s, buf); } static inline void @@ -1756,14 +1751,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_136size_t_31uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 31U; - blocks[i][(size_t)136U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)136U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)136U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___136size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -1788,13 +1784,12 @@ static inline void libcrux_sha3_portable_keccak_store_block___136size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___136size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___136size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___136size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -1921,7 +1916,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_136size_t_31uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_136size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -1973,14 +1968,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_136size_t_6uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 6U; - blocks[i][(size_t)136U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)136U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)136U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___136size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -2030,7 +2026,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_136size_t_6uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_136size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -2113,10 +2109,9 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_72size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___72size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___72size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___72size_t(s, buf); } static inline void @@ -2143,14 +2138,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_72size_t_6uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 6U; - blocks[i][(size_t)72U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)72U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)72U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___72size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -2175,13 +2171,12 @@ static inline void libcrux_sha3_portable_keccak_store_block___72size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___72size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___72size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___72size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -2308,7 +2303,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_72size_t_6uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_72size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); diff --git a/libcrux-ml-kem/c/libcrux_sha3_neon.c b/libcrux-ml-kem/c/libcrux_sha3_neon.c index d2967a19..2fbb8591 100644 --- a/libcrux-ml-kem/c/libcrux_sha3_neon.c +++ b/libcrux-ml-kem/c/libcrux_sha3_neon.c @@ -2,27 +2,13 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #include "libcrux_sha3_neon.h" -#include "internal/libcrux_core.h" - inline void libcrux_sha3_neon_sha512(Eurydice_slice digest, Eurydice_slice data) { - Prims_string buf[1U] = { - "not implemented: The target architecture does not support neon " - "instructions."}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)1U, buf, Prims_string, Eurydice_slice); - core_fmt_rt_Argument ret[0U]; - core_fmt_rt__core__fmt__rt__Argument__a__1__none(ret); - LowStar_Ignore_ignore( - core_fmt__core__fmt__Arguments__a__2__new_v1( - uu____0, Eurydice_array_to_slice( - (size_t)0U, ret, core_fmt_rt_Argument, Eurydice_slice)), - core_fmt_Arguments, void *); KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); @@ -30,18 +16,6 @@ inline void libcrux_sha3_neon_sha512(Eurydice_slice digest, inline void libcrux_sha3_neon_sha256(Eurydice_slice digest, Eurydice_slice data) { - Prims_string buf[1U] = { - "not implemented: The target architecture does not support neon " - "instructions."}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)1U, buf, Prims_string, Eurydice_slice); - core_fmt_rt_Argument ret[0U]; - core_fmt_rt__core__fmt__rt__Argument__a__1__none(ret); - LowStar_Ignore_ignore( - core_fmt__core__fmt__Arguments__a__2__new_v1( - uu____0, Eurydice_array_to_slice( - (size_t)0U, ret, core_fmt_rt_Argument, Eurydice_slice)), - core_fmt_Arguments, void *); KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); @@ -51,77 +25,29 @@ inline void libcrux_sha3_neon_x2_shake256(Eurydice_slice input0, Eurydice_slice input1, Eurydice_slice out0, Eurydice_slice out1) { - Prims_string buf[1U] = { - "not implemented: The target architecture does not support neon " - "instructions."}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)1U, buf, Prims_string, Eurydice_slice); - core_fmt_rt_Argument ret[0U]; - core_fmt_rt__core__fmt__rt__Argument__a__1__none(ret); - LowStar_Ignore_ignore( - core_fmt__core__fmt__Arguments__a__2__new_v1( - uu____0, Eurydice_array_to_slice( - (size_t)0U, ret, core_fmt_rt_Argument, Eurydice_slice)), - core_fmt_Arguments, void *); KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } -inline libcrux_sha3_neon_x2_incremental_KeccakState2 +inline libcrux_sha3_neon_x2_incremental_KeccakState libcrux_sha3_neon_x2_incremental_shake128_init(void) { - Prims_string buf[1U] = { - "not implemented: The target architecture does not support neon " - "instructions."}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)1U, buf, Prims_string, Eurydice_slice); - core_fmt_rt_Argument ret[0U]; - core_fmt_rt__core__fmt__rt__Argument__a__1__none(ret); - LowStar_Ignore_ignore( - core_fmt__core__fmt__Arguments__a__2__new_v1( - uu____0, Eurydice_array_to_slice( - (size_t)0U, ret, core_fmt_rt_Argument, Eurydice_slice)), - core_fmt_Arguments, void *); KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } inline void libcrux_sha3_neon_x2_incremental_shake128_absorb_final( - libcrux_sha3_neon_x2_incremental_KeccakState2 *s, Eurydice_slice data0, + libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice data0, Eurydice_slice data1) { - Prims_string buf[1U] = { - "not implemented: The target architecture does not support neon " - "instructions."}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)1U, buf, Prims_string, Eurydice_slice); - core_fmt_rt_Argument ret[0U]; - core_fmt_rt__core__fmt__rt__Argument__a__1__none(ret); - LowStar_Ignore_ignore( - core_fmt__core__fmt__Arguments__a__2__new_v1( - uu____0, Eurydice_array_to_slice( - (size_t)0U, ret, core_fmt_rt_Argument, Eurydice_slice)), - core_fmt_Arguments, void *); KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); } inline void libcrux_sha3_neon_x2_incremental_shake128_squeeze_next_block( - libcrux_sha3_neon_x2_incremental_KeccakState2 *s, Eurydice_slice out0, + libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice out0, Eurydice_slice out1) { - Prims_string buf[1U] = { - "not implemented: The target architecture does not support neon " - "instructions."}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)1U, buf, Prims_string, Eurydice_slice); - core_fmt_rt_Argument ret[0U]; - core_fmt_rt__core__fmt__rt__Argument__a__1__none(ret); - LowStar_Ignore_ignore( - core_fmt__core__fmt__Arguments__a__2__new_v1( - uu____0, Eurydice_array_to_slice( - (size_t)0U, ret, core_fmt_rt_Argument, Eurydice_slice)), - core_fmt_Arguments, void *); KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); @@ -129,20 +55,8 @@ inline void libcrux_sha3_neon_x2_incremental_shake128_squeeze_next_block( inline void libcrux_sha3_neon_x2_incremental_shake128_squeeze_first_three_blocks( - libcrux_sha3_neon_x2_incremental_KeccakState2 *s, Eurydice_slice out0, + libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice out0, Eurydice_slice out1) { - Prims_string buf[1U] = { - "not implemented: The target architecture does not support neon " - "instructions."}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)1U, buf, Prims_string, Eurydice_slice); - core_fmt_rt_Argument ret[0U]; - core_fmt_rt__core__fmt__rt__Argument__a__1__none(ret); - LowStar_Ignore_ignore( - core_fmt__core__fmt__Arguments__a__2__new_v1( - uu____0, Eurydice_array_to_slice( - (size_t)0U, ret, core_fmt_rt_Argument, Eurydice_slice)), - core_fmt_Arguments, void *); KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); @@ -150,18 +64,6 @@ libcrux_sha3_neon_x2_incremental_shake128_squeeze_first_three_blocks( inline void libcrux_sha3_neon_sha224(Eurydice_slice digest, Eurydice_slice data) { - Prims_string buf[1U] = { - "not implemented: The target architecture does not support neon " - "instructions."}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)1U, buf, Prims_string, Eurydice_slice); - core_fmt_rt_Argument ret[0U]; - core_fmt_rt__core__fmt__rt__Argument__a__1__none(ret); - LowStar_Ignore_ignore( - core_fmt__core__fmt__Arguments__a__2__new_v1( - uu____0, Eurydice_array_to_slice( - (size_t)0U, ret, core_fmt_rt_Argument, Eurydice_slice)), - core_fmt_Arguments, void *); KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); @@ -169,18 +71,6 @@ inline void libcrux_sha3_neon_sha224(Eurydice_slice digest, inline void libcrux_sha3_neon_sha384(Eurydice_slice digest, Eurydice_slice data) { - Prims_string buf[1U] = { - "not implemented: The target architecture does not support neon " - "instructions."}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)1U, buf, Prims_string, Eurydice_slice); - core_fmt_rt_Argument ret[0U]; - core_fmt_rt__core__fmt__rt__Argument__a__1__none(ret); - LowStar_Ignore_ignore( - core_fmt__core__fmt__Arguments__a__2__new_v1( - uu____0, Eurydice_array_to_slice( - (size_t)0U, ret, core_fmt_rt_Argument, Eurydice_slice)), - core_fmt_Arguments, void *); KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); KRML_HOST_EXIT(255U); diff --git a/libcrux-ml-kem/c/libcrux_sha3_neon.h b/libcrux-ml-kem/c/libcrux_sha3_neon.h index 0450e690..9a803b37 100644 --- a/libcrux-ml-kem/c/libcrux_sha3_neon.h +++ b/libcrux-ml-kem/c/libcrux_sha3_neon.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_sha3_neon_H @@ -14,7 +14,6 @@ extern "C" { #include "eurydice_glue.h" #include "intrinsics/libcrux_intrinsics_arm64.h" -#include "libcrux_core.h" #include "libcrux_sha3_internal.h" void libcrux_sha3_neon_sha512(Eurydice_slice digest, Eurydice_slice data); @@ -24,23 +23,23 @@ void libcrux_sha3_neon_sha256(Eurydice_slice digest, Eurydice_slice data); void libcrux_sha3_neon_x2_shake256(Eurydice_slice input0, Eurydice_slice input1, Eurydice_slice out0, Eurydice_slice out1); -typedef struct libcrux_sha3_neon_x2_incremental_KeccakState2_s { +typedef struct libcrux_sha3_neon_x2_incremental_KeccakState_s { libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t state[2U]; -} libcrux_sha3_neon_x2_incremental_KeccakState2; +} libcrux_sha3_neon_x2_incremental_KeccakState; -libcrux_sha3_neon_x2_incremental_KeccakState2 +libcrux_sha3_neon_x2_incremental_KeccakState libcrux_sha3_neon_x2_incremental_shake128_init(void); void libcrux_sha3_neon_x2_incremental_shake128_absorb_final( - libcrux_sha3_neon_x2_incremental_KeccakState2 *s, Eurydice_slice data0, + libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice data0, Eurydice_slice data1); void libcrux_sha3_neon_x2_incremental_shake128_squeeze_next_block( - libcrux_sha3_neon_x2_incremental_KeccakState2 *s, Eurydice_slice out0, + libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice out0, Eurydice_slice out1); void libcrux_sha3_neon_x2_incremental_shake128_squeeze_first_three_blocks( - libcrux_sha3_neon_x2_incremental_KeccakState2 *s, Eurydice_slice out0, + libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice out0, Eurydice_slice out1); void libcrux_sha3_neon_sha224(Eurydice_slice digest, Eurydice_slice data); From a576e70332f5f279be7ba98711538c7a34a4ad20 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 15:20:32 +0200 Subject: [PATCH 49/53] update header only C code --- libcrux-ml-kem/c.sh | 6 +- libcrux-ml-kem/cg/README.md | 6 +- libcrux-ml-kem/cg/benches/sha3.cc | 4 +- libcrux-ml-kem/cg/eurydice_glue.h | 12 +- .../cg/karamel/lowstar_endianness.h | 231 ------------------ libcrux-ml-kem/cg/karamel/target.h | 175 +------------ libcrux-ml-kem/cg/libcrux_core.h | 2 +- libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h | 226 +++++++++-------- libcrux-ml-kem/cg/libcrux_mlkem768_portable.h | 145 ++++++----- libcrux-ml-kem/cg/libcrux_sha3_avx2.h | 228 +++++++++-------- libcrux-ml-kem/cg/libcrux_sha3_portable.h | 171 +++++++------ libcrux-ml-kem/src/ind_cca.rs | 8 +- 12 files changed, 423 insertions(+), 791 deletions(-) delete mode 100644 libcrux-ml-kem/cg/karamel/lowstar_endianness.h diff --git a/libcrux-ml-kem/c.sh b/libcrux-ml-kem/c.sh index ba15a2ab..ffed1c80 100755 --- a/libcrux-ml-kem/c.sh +++ b/libcrux-ml-kem/c.sh @@ -20,6 +20,7 @@ config=c.yaml out=c glue=$EURYDICE_HOME/include/eurydice_glue.h features="--cargo-arg=--features=pre-verification" +eurydice_glue=1 # Parse command line arguments. all_args=("$@") @@ -33,6 +34,7 @@ while [ $# -gt 0 ]; do --out) out="$2"; shift ;; --glue) glue="$2"; shift ;; --mlkem768) features="${features} --cargo-arg=--no-default-features --cargo-arg=--features=mlkem768" ;; + --no-glue) eurydice_glue=0 ;; esac shift done @@ -71,7 +73,9 @@ fi echo "Running eurydice ..." $EURYDICE_HOME/eurydice --config ../$config ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc -cp $EURYDICE_HOME/include/eurydice_glue.h . +if [[ "$eurydice_glue" = 1 ]]; then + cp $EURYDICE_HOME/include/eurydice_glue.h . +fi clang-format --style=Google -i *.c *.h clang-format --style=Google -i internal/*.h diff --git a/libcrux-ml-kem/cg/README.md b/libcrux-ml-kem/cg/README.md index 3e2297c0..f5a975b9 100644 --- a/libcrux-ml-kem/cg/README.md +++ b/libcrux-ml-kem/cg/README.md @@ -5,11 +5,15 @@ This folder contains the extracted ML-KEM C code. ## Generating C code The C code is generated from Rust using [Charon], [Eurydice] and [Karamel]. -The [c.sh](../c.sh) bash script drives the extraction, using the [c.yaml](../c.yaml) +The [c.sh](../c.sh) bash script drives the extraction, using the [cg.yaml](../cg.yaml) configuration file. While running the commands separately is possible, it is not recommended because the script sets all necessary configuration flags. +```bash +./c.sh --config cg.yaml --out cg --mlkem768 --no-glue +``` + ## Build Make sure to use `CC=clang CXX=clang++` when benchmarking on Linux to get full performance. diff --git a/libcrux-ml-kem/cg/benches/sha3.cc b/libcrux-ml-kem/cg/benches/sha3.cc index b7c9d777..734b245c 100644 --- a/libcrux-ml-kem/cg/benches/sha3.cc +++ b/libcrux-ml-kem/cg/benches/sha3.cc @@ -68,13 +68,13 @@ shake128_34_504(benchmark::State &state) Eurydice_slice last[4] = {EURYDICE_SLICE(input, 0, 34), EURYDICE_SLICE(input, 0, 34), EURYDICE_SLICE(input, 0, 34), EURYDICE_SLICE(input, 0, 34)}; Eurydice_slice out[4] = {EURYDICE_SLICE(digest0, 0, 504), EURYDICE_SLICE(digest1, 0, 504), EURYDICE_SLICE(digest2, 0, 504), EURYDICE_SLICE(digest3, 0, 504)}; - libcrux_sha3_avx2_x4_incremental_KeccakState4 st = libcrux_sha3_avx2_x4_incremental_shake128_init(); + libcrux_sha3_avx2_x4_incremental_KeccakState st = libcrux_sha3_avx2_x4_incremental_shake128_init(); libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168size_t_31uint8_t(&st, last); libcrux_sha3_generic_keccak_squeeze_first_three_blocks__core_core_arch_x86___m256i_4size_t_168size_t(&st, out); for (auto _ : state) { - libcrux_sha3_avx2_x4_incremental_KeccakState4 st = libcrux_sha3_avx2_x4_incremental_shake128_init(); + libcrux_sha3_avx2_x4_incremental_KeccakState st = libcrux_sha3_avx2_x4_incremental_shake128_init(); libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168size_t_31uint8_t(&st, last); libcrux_sha3_generic_keccak_squeeze_first_three_blocks__core_core_arch_x86___m256i_4size_t_168size_t(&st, out); } diff --git a/libcrux-ml-kem/cg/eurydice_glue.h b/libcrux-ml-kem/cg/eurydice_glue.h index bad6ff16..9f42825d 100644 --- a/libcrux-ml-kem/cg/eurydice_glue.h +++ b/libcrux-ml-kem/cg/eurydice_glue.h @@ -10,7 +10,6 @@ extern "C" { #include #include -#include "karamel/lowstar_endianness.h" #include "karamel/target.h" // SLICES, ARRAYS, ETC. @@ -77,7 +76,7 @@ typedef struct { #define Eurydice_array_eq(sz, a1, a2, t, _, _ret_t) \ (memcmp(a1, a2, sz * sizeof(t)) == 0) -#define core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq \ +#define core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq \ Eurydice_array_eq #define core_slice___Slice_T___split_at(slice, mid, element_type, ret_t) \ @@ -106,10 +105,12 @@ static inline void Eurydice_slice_to_array3(uint8_t *dst_tag, char *dst_ok, // CORE STUFF (conversions, endianness, ...) static inline void core_num__u64_9__to_le_bytes(uint64_t v, uint8_t buf[8]) { - store64_le(buf, v); + memcpy(buf, &v, sizeof(v)); } static inline uint64_t core_num__u64_9__from_le_bytes(uint8_t buf[8]) { - return load64_le(buf); + uint64_t v; + memcpy(&v, buf, sizeof(v)); + return v; } static inline uint32_t core_num__u8_6__count_ones(uint8_t x0) { @@ -128,7 +129,6 @@ static inline uint8_t core_num__u8_6__wrapping_sub(uint8_t x, uint8_t y) { return x - y; } - // static inline uint8_t Eurydice_bitand_pv_u8(uint8_t *p, uint8_t v) { // return (*p) & v; // } @@ -149,7 +149,7 @@ static inline uint8_t core_num__u8_6__wrapping_sub(uint8_t x, uint8_t y) { // See note in karamel/lib/Inlining.ml if you change this #define Eurydice_into_iter(x, t, _ret_t) (x) -#define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter \ +#define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter \ Eurydice_into_iter #if defined(__cplusplus) diff --git a/libcrux-ml-kem/cg/karamel/lowstar_endianness.h b/libcrux-ml-kem/cg/karamel/lowstar_endianness.h deleted file mode 100644 index 1aa2ccd6..00000000 --- a/libcrux-ml-kem/cg/karamel/lowstar_endianness.h +++ /dev/null @@ -1,231 +0,0 @@ -/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. - Licensed under the Apache 2.0 License. */ - -#ifndef __LOWSTAR_ENDIANNESS_H -#define __LOWSTAR_ENDIANNESS_H - -#include -#include - -/******************************************************************************/ -/* Implementing C.fst (part 2: endian-ness macros) */ -/******************************************************************************/ - -/* ... for Linux */ -#if defined(__linux__) || defined(__CYGWIN__) || defined (__USE_SYSTEM_ENDIAN_H__) || defined(__GLIBC__) -# include - -/* ... for OSX */ -#elif defined(__APPLE__) -# include -# define htole64(x) OSSwapHostToLittleInt64(x) -# define le64toh(x) OSSwapLittleToHostInt64(x) -# define htobe64(x) OSSwapHostToBigInt64(x) -# define be64toh(x) OSSwapBigToHostInt64(x) - -# define htole16(x) OSSwapHostToLittleInt16(x) -# define le16toh(x) OSSwapLittleToHostInt16(x) -# define htobe16(x) OSSwapHostToBigInt16(x) -# define be16toh(x) OSSwapBigToHostInt16(x) - -# define htole32(x) OSSwapHostToLittleInt32(x) -# define le32toh(x) OSSwapLittleToHostInt32(x) -# define htobe32(x) OSSwapHostToBigInt32(x) -# define be32toh(x) OSSwapBigToHostInt32(x) - -/* ... for Solaris */ -#elif defined(__sun__) -# include -# define htole64(x) LE_64(x) -# define le64toh(x) LE_64(x) -# define htobe64(x) BE_64(x) -# define be64toh(x) BE_64(x) - -# define htole16(x) LE_16(x) -# define le16toh(x) LE_16(x) -# define htobe16(x) BE_16(x) -# define be16toh(x) BE_16(x) - -# define htole32(x) LE_32(x) -# define le32toh(x) LE_32(x) -# define htobe32(x) BE_32(x) -# define be32toh(x) BE_32(x) - -/* ... for the BSDs */ -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -# include -#elif defined(__OpenBSD__) -# include - -/* ... for Windows (MSVC)... not targeting XBOX 360! */ -#elif defined(_MSC_VER) - -# include -# define htobe16(x) _byteswap_ushort(x) -# define htole16(x) (x) -# define be16toh(x) _byteswap_ushort(x) -# define le16toh(x) (x) - -# define htobe32(x) _byteswap_ulong(x) -# define htole32(x) (x) -# define be32toh(x) _byteswap_ulong(x) -# define le32toh(x) (x) - -# define htobe64(x) _byteswap_uint64(x) -# define htole64(x) (x) -# define be64toh(x) _byteswap_uint64(x) -# define le64toh(x) (x) - -/* ... for Windows (GCC-like, e.g. mingw or clang) */ -#elif (defined(_WIN32) || defined(_WIN64) || defined(__EMSCRIPTEN__)) && \ - (defined(__GNUC__) || defined(__clang__)) - -# define htobe16(x) __builtin_bswap16(x) -# define htole16(x) (x) -# define be16toh(x) __builtin_bswap16(x) -# define le16toh(x) (x) - -# define htobe32(x) __builtin_bswap32(x) -# define htole32(x) (x) -# define be32toh(x) __builtin_bswap32(x) -# define le32toh(x) (x) - -# define htobe64(x) __builtin_bswap64(x) -# define htole64(x) (x) -# define be64toh(x) __builtin_bswap64(x) -# define le64toh(x) (x) - -/* ... generic big-endian fallback code */ -/* ... AIX doesn't have __BYTE_ORDER__ (with XLC compiler) & is always big-endian */ -#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || defined(_AIX) - -/* byte swapping code inspired by: - * https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h - * */ - -# define htobe32(x) (x) -# define be32toh(x) (x) -# define htole32(x) \ - (__extension__({ \ - uint32_t _temp = (x); \ - ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \ - ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \ - })) -# define le32toh(x) (htole32((x))) - -# define htobe64(x) (x) -# define be64toh(x) (x) -# define htole64(x) \ - (__extension__({ \ - uint64_t __temp = (x); \ - uint32_t __low = htobe32((uint32_t)__temp); \ - uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \ - (((uint64_t)__low) << 32) | __high; \ - })) -# define le64toh(x) (htole64((x))) - -/* ... generic little-endian fallback code */ -#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - -# define htole32(x) (x) -# define le32toh(x) (x) -# define htobe32(x) \ - (__extension__({ \ - uint32_t _temp = (x); \ - ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \ - ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \ - })) -# define be32toh(x) (htobe32((x))) - -# define htole64(x) (x) -# define le64toh(x) (x) -# define htobe64(x) \ - (__extension__({ \ - uint64_t __temp = (x); \ - uint32_t __low = htobe32((uint32_t)__temp); \ - uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \ - (((uint64_t)__low) << 32) | __high; \ - })) -# define be64toh(x) (htobe64((x))) - -/* ... couldn't determine endian-ness of the target platform */ -#else -# error "Please define __BYTE_ORDER__!" - -#endif /* defined(__linux__) || ... */ - -/* Loads and stores. These avoid undefined behavior due to unaligned memory - * accesses, via memcpy. */ - -inline static uint16_t load16(uint8_t *b) { - uint16_t x; - memcpy(&x, b, 2); - return x; -} - -inline static uint32_t load32(uint8_t *b) { - uint32_t x; - memcpy(&x, b, 4); - return x; -} - -inline static uint64_t load64(uint8_t *b) { - uint64_t x; - memcpy(&x, b, 8); - return x; -} - -inline static void store16(uint8_t *b, uint16_t i) { - memcpy(b, &i, 2); -} - -inline static void store32(uint8_t *b, uint32_t i) { - memcpy(b, &i, 4); -} - -inline static void store64(uint8_t *b, uint64_t i) { - memcpy(b, &i, 8); -} - -/* Legacy accessors so that this header can serve as an implementation of - * C.Endianness */ -#define load16_le(b) (le16toh(load16(b))) -#define store16_le(b, i) (store16(b, htole16(i))) -#define load16_be(b) (be16toh(load16(b))) -#define store16_be(b, i) (store16(b, htobe16(i))) - -#define load32_le(b) (le32toh(load32(b))) -#define store32_le(b, i) (store32(b, htole32(i))) -#define load32_be(b) (be32toh(load32(b))) -#define store32_be(b, i) (store32(b, htobe32(i))) - -#define load64_le(b) (le64toh(load64(b))) -#define store64_le(b, i) (store64(b, htole64(i))) -#define load64_be(b) (be64toh(load64(b))) -#define store64_be(b, i) (store64(b, htobe64(i))) - -/* Co-existence of LowStar.Endianness and FStar.Endianness generates name - * conflicts, because of course both insist on having no prefixes. Until a - * prefix is added, or until we truly retire FStar.Endianness, solve this issue - * in an elegant way. */ -#define load16_le0 load16_le -#define store16_le0 store16_le -#define load16_be0 load16_be -#define store16_be0 store16_be - -#define load32_le0 load32_le -#define store32_le0 store32_le -#define load32_be0 load32_be -#define store32_be0 store32_be - -#define load64_le0 load64_le -#define store64_le0 store64_le -#define load64_be0 load64_be -#define store64_be0 store64_be - -#define load128_le0 load128_le -#define store128_le0 store128_le -#define load128_be0 load128_be -#define store128_be0 store128_be - -#endif diff --git a/libcrux-ml-kem/cg/karamel/target.h b/libcrux-ml-kem/cg/karamel/target.h index d5331476..65a62197 100644 --- a/libcrux-ml-kem/cg/karamel/target.h +++ b/libcrux-ml-kem/cg/karamel/target.h @@ -4,25 +4,6 @@ #ifndef __KRML_TARGET_H #define __KRML_TARGET_H -#include -#include -#include -#include -#include -#include -#include - -/* Since KaRaMeL emits the inline keyword unconditionally, we follow the - * guidelines at https://gcc.gnu.org/onlinedocs/gcc/Inline.html and make this - * __inline__ to ensure the code compiles with -std=c90 and earlier. */ -#ifdef __GNUC__ -# define inline __inline__ -#endif - -/******************************************************************************/ -/* Macros that KaRaMeL will generate. */ -/******************************************************************************/ - /* For "bare" targets that do not have a C stdlib, the user might want to use * [-add-early-include '"mydefinitions.h"'] and override these. */ #ifndef KRML_HOST_PRINTF @@ -42,160 +23,6 @@ # define KRML_HOST_EXIT exit #endif -#ifndef KRML_HOST_MALLOC -# define KRML_HOST_MALLOC malloc -#endif - -#ifndef KRML_HOST_CALLOC -# define KRML_HOST_CALLOC calloc -#endif - -#ifndef KRML_HOST_FREE -# define KRML_HOST_FREE free -#endif - -#ifndef KRML_HOST_IGNORE -# define KRML_HOST_IGNORE(x) (void)(x) -#endif - -#ifndef KRML_MAYBE_UNUSED_VAR -# define KRML_MAYBE_UNUSED_VAR(x) KRML_HOST_IGNORE(x) -#endif - -#ifndef KRML_MAYBE_UNUSED -# if defined(__GNUC__) -# define KRML_MAYBE_UNUSED __attribute__((unused)) -# else -# define KRML_MAYBE_UNUSED -# endif -#endif - -#ifndef KRML_NOINLINE -# if defined(_MSC_VER) -# define KRML_NOINLINE __declspec(noinline) -# elif defined (__GNUC__) -# define KRML_NOINLINE __attribute__((noinline,unused)) -# else -# define KRML_NOINLINE -# warning "The KRML_NOINLINE macro is not defined for this toolchain!" -# warning "The compiler may defeat side-channel resistance with optimizations." -# warning "Please locate target.h and try to fill it out with a suitable definition for this compiler." -# endif -#endif - -#ifndef KRML_PRE_ALIGN -# ifdef _MSC_VER -# define KRML_PRE_ALIGN(X) __declspec(align(X)) -# else -# define KRML_PRE_ALIGN(X) -# endif -#endif - -#ifndef KRML_POST_ALIGN -# ifdef _MSC_VER -# define KRML_POST_ALIGN(X) -# else -# define KRML_POST_ALIGN(X) __attribute__((aligned(X))) -# endif -#endif - -/* MinGW-W64 does not support C11 aligned_alloc, but it supports - * MSVC's _aligned_malloc. - */ -#ifndef KRML_ALIGNED_MALLOC -# ifdef __MINGW32__ -# include <_mingw.h> -# endif -# if ( \ - defined(_MSC_VER) || \ - (defined(__MINGW32__) && defined(__MINGW64_VERSION_MAJOR))) -# define KRML_ALIGNED_MALLOC(X, Y) _aligned_malloc(Y, X) -# else -# define KRML_ALIGNED_MALLOC(X, Y) aligned_alloc(X, Y) -# endif -#endif - -/* Since aligned allocations with MinGW-W64 are done with - * _aligned_malloc (see above), such pointers must be freed with - * _aligned_free. - */ -#ifndef KRML_ALIGNED_FREE -# ifdef __MINGW32__ -# include <_mingw.h> -# endif -# if ( \ - defined(_MSC_VER) || \ - (defined(__MINGW32__) && defined(__MINGW64_VERSION_MAJOR))) -# define KRML_ALIGNED_FREE(X) _aligned_free(X) -# else -# define KRML_ALIGNED_FREE(X) free(X) -# endif -#endif - -#ifndef KRML_HOST_TIME - -# include - -/* Prims_nat not yet in scope */ -inline static int32_t krml_time(void) { - return (int32_t)time(NULL); -} - -# define KRML_HOST_TIME krml_time -#endif - -/* In statement position, exiting is easy. */ -#define KRML_EXIT \ - do { \ - KRML_HOST_PRINTF("Unimplemented function at %s:%d\n", __FILE__, __LINE__); \ - KRML_HOST_EXIT(254); \ - } while (0) - -/* In expression position, use the comma-operator and a malloc to return an - * expression of the right size. KaRaMeL passes t as the parameter to the macro. - */ -#define KRML_EABORT(t, msg) \ - (KRML_HOST_PRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, msg), \ - KRML_HOST_EXIT(255), *((t *)KRML_HOST_MALLOC(sizeof(t)))) - -/* In FStar.Buffer.fst, the size of arrays is uint32_t, but it's a number of - * *elements*. Do an ugly, run-time check (some of which KaRaMeL can eliminate). - */ -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4)) -# define _KRML_CHECK_SIZE_PRAGMA \ - _Pragma("GCC diagnostic ignored \"-Wtype-limits\"") -#else -# define _KRML_CHECK_SIZE_PRAGMA -#endif - -#define KRML_CHECK_SIZE(size_elt, sz) \ - do { \ - _KRML_CHECK_SIZE_PRAGMA \ - if (((size_t)(sz)) > ((size_t)(SIZE_MAX / (size_elt)))) { \ - KRML_HOST_PRINTF( \ - "Maximum allocatable size exceeded, aborting before overflow at " \ - "%s:%d\n", \ - __FILE__, __LINE__); \ - KRML_HOST_EXIT(253); \ - } \ - } while (0) - -#if defined(_MSC_VER) && _MSC_VER < 1900 -# define KRML_HOST_SNPRINTF(buf, sz, fmt, arg) \ - _snprintf_s(buf, sz, _TRUNCATE, fmt, arg) -#else -# define KRML_HOST_SNPRINTF(buf, sz, fmt, arg) snprintf(buf, sz, fmt, arg) -#endif - -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4)) -# define KRML_DEPRECATED(x) __attribute__((deprecated(x))) -#elif defined(__GNUC__) -/* deprecated attribute is not defined in GCC < 4.5. */ -# define KRML_DEPRECATED(x) -#elif defined(_MSC_VER) -# define KRML_DEPRECATED(x) __declspec(deprecated(x)) -#endif - /* Macros for prettier unrolling of loops */ #define KRML_LOOP1(i, n, x) { \ x \ @@ -277,7 +104,7 @@ inline static int32_t krml_time(void) { } while (0) #ifndef KRML_UNROLL_MAX -# define KRML_UNROLL_MAX 16 +# define KRML_UNROLL_MAX 0 #endif /* 1 is the number of loop iterations, i.e. (n - z)/k as evaluated by krml */ diff --git a/libcrux-ml-kem/cg/libcrux_core.h b/libcrux-ml-kem/cg/libcrux_core.h index 3722fd4b..4c13971d 100644 --- a/libcrux-ml-kem/cg/libcrux_core.h +++ b/libcrux-ml-kem/cg/libcrux_core.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_core_H diff --git a/libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h b/libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h index e65c8602..26c3be60 100644 --- a/libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h +++ b/libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem768_avx2_H @@ -2767,25 +2767,20 @@ libcrux_ml_kem_matrix_sample_matrix_A_closure__libcrux_ml_kem_vector_avx2_SIMD25 libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector)); } -typedef libcrux_sha3_avx2_x4_incremental_KeccakState4 +typedef libcrux_sha3_avx2_x4_incremental_KeccakState libcrux_ml_kem_hash_functions_avx2_Simd256Hash; __attribute__((target("avx2"))) -static inline libcrux_sha3_avx2_x4_incremental_KeccakState4 +static inline libcrux_sha3_avx2_x4_incremental_KeccakState libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__avx2__Simd256Hash___shake128_init_absorb___3size_t( uint8_t input[3U][34U]) { libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t state = libcrux_sha3_avx2_x4_incremental_shake128_init(); - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = &state; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)34U, input[1U], uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)34U, input[2U], uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_absorb_final( - uu____0, uu____1, uu____2, uu____3, + &state, + Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)34U, input[1U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)34U, input[2U], uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)34U, input[0U], uint8_t, Eurydice_slice)); return state; } @@ -2793,33 +2788,27 @@ libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for __attribute__((target("avx2"))) static inline void libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__avx2__Simd256Hash___shake128_squeeze_three_blocks___3size_t( - libcrux_sha3_avx2_x4_incremental_KeccakState4 *self, - uint8_t ret[3U][504U]) { + libcrux_sha3_avx2_x4_incremental_KeccakState *self, uint8_t ret[3U][504U]) { uint8_t out[3U][504U] = {{0U}}; uint8_t out0[504U] = {0U}; uint8_t out1[504U] = {0U}; uint8_t out2[504U] = {0U}; uint8_t out3[504U] = {0U}; - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = self; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)504U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)504U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)504U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_squeeze_first_three_blocks( - uu____0, uu____1, uu____2, uu____3, + self, + Eurydice_array_to_slice((size_t)504U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)504U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)504U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)504U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____4[504U]; - memcpy(uu____4, out0, (size_t)504U * sizeof(uint8_t)); - memcpy(out[0U], uu____4, (size_t)504U * sizeof(uint8_t)); - uint8_t uu____5[504U]; - memcpy(uu____5, out1, (size_t)504U * sizeof(uint8_t)); - memcpy(out[1U], uu____5, (size_t)504U * sizeof(uint8_t)); - uint8_t uu____6[504U]; - memcpy(uu____6, out2, (size_t)504U * sizeof(uint8_t)); - memcpy(out[2U], uu____6, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____0[504U]; + memcpy(uu____0, out0, (size_t)504U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____1[504U]; + memcpy(uu____1, out1, (size_t)504U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)504U * sizeof(uint8_t)); + uint8_t uu____2[504U]; + memcpy(uu____2, out2, (size_t)504U * sizeof(uint8_t)); + memcpy(out[2U], uu____2, (size_t)504U * sizeof(uint8_t)); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[504U])); } @@ -2868,33 +2857,27 @@ libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_ve __attribute__((target("avx2"))) static inline void libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__avx2__Simd256Hash___shake128_squeeze_block___3size_t( - libcrux_sha3_avx2_x4_incremental_KeccakState4 *self, - uint8_t ret[3U][168U]) { + libcrux_sha3_avx2_x4_incremental_KeccakState *self, uint8_t ret[3U][168U]) { uint8_t out[3U][168U] = {{0U}}; uint8_t out0[168U] = {0U}; uint8_t out1[168U] = {0U}; uint8_t out2[168U] = {0U}; uint8_t out3[168U] = {0U}; - libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - *uu____0 = self; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)168U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)168U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)168U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_incremental_shake128_squeeze_next_block( - uu____0, uu____1, uu____2, uu____3, + self, + Eurydice_array_to_slice((size_t)168U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)168U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)168U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)168U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____4[168U]; - memcpy(uu____4, out0, (size_t)168U * sizeof(uint8_t)); - memcpy(out[0U], uu____4, (size_t)168U * sizeof(uint8_t)); - uint8_t uu____5[168U]; - memcpy(uu____5, out1, (size_t)168U * sizeof(uint8_t)); - memcpy(out[1U], uu____5, (size_t)168U * sizeof(uint8_t)); - uint8_t uu____6[168U]; - memcpy(uu____6, out2, (size_t)168U * sizeof(uint8_t)); - memcpy(out[2U], uu____6, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____0[168U]; + memcpy(uu____0, out0, (size_t)168U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____1[168U]; + memcpy(uu____1, out1, (size_t)168U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)168U * sizeof(uint8_t)); + uint8_t uu____2[168U]; + memcpy(uu____2, out2, (size_t)168U * sizeof(uint8_t)); + memcpy(out[2U], uu____2, (size_t)168U * sizeof(uint8_t)); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[168U])); } @@ -2985,7 +2968,7 @@ libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_avx2_SIMD256Vecto int16_t out[3U][272U] = {{0U}}; uint8_t uu____0[3U][34U]; memcpy(uu____0, seeds, (size_t)3U * sizeof(uint8_t[34U])); - libcrux_sha3_avx2_x4_incremental_KeccakState4 xof_state = + libcrux_sha3_avx2_x4_incremental_KeccakState xof_state = libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__avx2__Simd256Hash___shake128_init_absorb___3size_t( uu____0); uint8_t randomness0[3U][504U]; @@ -3104,32 +3087,24 @@ libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for uint8_t out1[128U] = {0U}; uint8_t out2[128U] = {0U}; uint8_t out3[128U] = {0U}; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)33U, input[2U], uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice); - Eurydice_slice uu____4 = - Eurydice_array_to_slice((size_t)128U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____5 = - Eurydice_array_to_slice((size_t)128U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____6 = - Eurydice_array_to_slice((size_t)128U, out2, uint8_t, Eurydice_slice); libcrux_sha3_avx2_x4_shake256( - uu____0, uu____1, uu____2, uu____3, uu____4, uu____5, uu____6, + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[1U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[2U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[0U], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)128U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)128U, out3, uint8_t, Eurydice_slice)); - uint8_t uu____7[128U]; - memcpy(uu____7, out0, (size_t)128U * sizeof(uint8_t)); - memcpy(out[0U], uu____7, (size_t)128U * sizeof(uint8_t)); - uint8_t uu____8[128U]; - memcpy(uu____8, out1, (size_t)128U * sizeof(uint8_t)); - memcpy(out[1U], uu____8, (size_t)128U * sizeof(uint8_t)); - uint8_t uu____9[128U]; - memcpy(uu____9, out2, (size_t)128U * sizeof(uint8_t)); - memcpy(out[2U], uu____9, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____0[128U]; + memcpy(uu____0, out0, (size_t)128U * sizeof(uint8_t)); + memcpy(out[0U], uu____0, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____1[128U]; + memcpy(uu____1, out1, (size_t)128U * sizeof(uint8_t)); + memcpy(out[1U], uu____1, (size_t)128U * sizeof(uint8_t)); + uint8_t uu____2[128U]; + memcpy(uu____2, out2, (size_t)128U * sizeof(uint8_t)); + memcpy(out[2U], uu____2, (size_t)128U * sizeof(uint8_t)); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[128U])); } @@ -3501,10 +3476,11 @@ __attribute__((target("avx2"))) static inline core_core_arch_x86___m256i libcrux_ml_kem_vector_traits_decompress_1__libcrux_ml_kem_vector_avx2_SIMD256Vector( core_core_arch_x86___m256i v) { + core_core_arch_x86___m256i uu____0 = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ZERO(); return libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___bitwise_and_with_constant( libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___sub( - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ZERO(), - &v), + uu____0, &v), (int16_t)1665); } @@ -4130,7 +4106,19 @@ libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux __attribute__((target("avx2"))) static inline void -libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( +libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_1088size_t( + Eurydice_slice shared_secret, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *_, + uint8_t ret[32U]) { + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + shared_secret, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); +} + +__attribute__((target("avx2"))) +static inline void +libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( libcrux_ml_kem_types_MlKemPrivateKey____2400size_t *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t uu____0 = @@ -4174,7 +4162,7 @@ libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_lib Eurydice_array_to_slice((size_t)64U, hashed, uint8_t, Eurydice_slice), LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t); - Eurydice_slice shared_secret = uu____3.fst; + Eurydice_slice shared_secret0 = uu____3.fst; Eurydice_slice pseudorandomness = uu____3.snd; uint8_t to_hash[1120U]; libcrux_ml_kem_utils_into_padded_array___1120size_t(implicit_rejection_value, @@ -4187,10 +4175,10 @@ libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_lib libcrux_ml_kem_types___core__convert__AsRef__Slice_u8___for_libcrux_ml_kem__types__MlKemCiphertext_SIZE___1__as_ref___1088size_t( ciphertext), uint8_t, void *); - uint8_t implicit_rejection_shared_secret[32U]; + uint8_t implicit_rejection_shared_secret0[32U]; libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__avx2__Simd256Hash___PRF___3size_t_32size_t( Eurydice_array_to_slice((size_t)1120U, to_hash, uint8_t, Eurydice_slice), - implicit_rejection_shared_secret); + implicit_rejection_shared_secret0); Eurydice_slice uu____5 = ind_cpa_public_key; uint8_t uu____6[32U]; memcpy(uu____6, decrypted, (size_t)32U * sizeof(uint8_t)); @@ -4204,10 +4192,18 @@ libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_lib libcrux_ml_kem_constant_time_ops_compare_ciphertexts_in_constant_time___1088size_t( uu____7, Eurydice_array_to_slice((size_t)1088U, expected_ciphertext, uint8_t, Eurydice_slice)); - Eurydice_slice uu____8 = shared_secret; + uint8_t implicit_rejection_shared_secret[32U]; + libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_1088size_t( + Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret0, + uint8_t, Eurydice_slice), + ciphertext, implicit_rejection_shared_secret); + uint8_t shared_secret[32U]; + libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_1088size_t( + shared_secret0, ciphertext, shared_secret); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( - uu____8, + Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t, Eurydice_slice), selector, ret0); @@ -4220,7 +4216,7 @@ libcrux_ml_kem_ind_cca_instantiations_avx2_decapsulate___3size_t_2400size_t_1152 libcrux_ml_kem_types_MlKemPrivateKey____2400size_t *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { uint8_t ret0[32U]; - libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( + libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( private_key, ciphertext, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } @@ -4235,6 +4231,17 @@ static inline void libcrux_ml_kem_mlkem768_avx2_decapsulate( memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } +__attribute__((target("avx2"))) +static inline void +libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___entropy_preprocess__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t( + Eurydice_slice randomness, uint8_t ret[32U]) { + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + randomness, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); +} + __attribute__((target("avx2"))) static inline void libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__avx2__Simd256Hash___H___3size_t( @@ -4248,12 +4255,17 @@ libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for __attribute__((target("avx2"))) static inline K___libcrux_ml_kem_types_MlKemCiphertext___1088size_t___uint8_t_32size_t_ -libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( libcrux_ml_kem_types_MlKemPublicKey____1184size_t *public_key, uint8_t randomness[32U]) { + uint8_t randomness0[32U]; + libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___entropy_preprocess__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t( + Eurydice_array_to_slice((size_t)32U, randomness, uint8_t, Eurydice_slice), + randomness0); uint8_t to_hash[64U]; libcrux_ml_kem_utils_into_padded_array___64size_t( - Eurydice_array_to_slice((size_t)32U, randomness, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)32U, randomness0, uint8_t, + Eurydice_slice), to_hash); Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( (size_t)64U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, @@ -4287,20 +4299,19 @@ libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_lib public_key), uint8_t, Eurydice_slice); uint8_t uu____3[32U]; - memcpy(uu____3, randomness, (size_t)32U * sizeof(uint8_t)); + memcpy(uu____3, randomness0, (size_t)32U * sizeof(uint8_t)); uint8_t ciphertext[1088U]; libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____2, uu____3, pseudorandomness, ciphertext); - uint8_t shared_secret_array[32U] = {0U}; - core_slice___Slice_T___copy_from_slice( - Eurydice_array_to_slice((size_t)32U, shared_secret_array, uint8_t, - Eurydice_slice), - shared_secret, uint8_t, void *); uint8_t uu____4[1088U]; memcpy(uu____4, ciphertext, (size_t)1088U * sizeof(uint8_t)); - libcrux_ml_kem_mlkem768_MlKem768Ciphertext uu____5 = + libcrux_ml_kem_mlkem768_MlKem768Ciphertext ciphertext0 = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemCiphertext_SIZE___2__from___1088size_t( uu____4); + uint8_t shared_secret_array[32U]; + libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_1088size_t( + shared_secret, &ciphertext0, shared_secret_array); + libcrux_ml_kem_mlkem768_MlKem768Ciphertext uu____5 = ciphertext0; uint8_t uu____6[32U]; memcpy(uu____6, shared_secret_array, (size_t)32U * sizeof(uint8_t)); K___libcrux_ml_kem_types_MlKemCiphertext___1088size_t___uint8_t_32size_t_ lit; @@ -4317,7 +4328,7 @@ libcrux_ml_kem_ind_cca_instantiations_avx2_encapsulate___3size_t_1088size_t_1184 libcrux_ml_kem_types_MlKemPublicKey____1184size_t *uu____0 = public_key; uint8_t uu____1[32U]; memcpy(uu____1, randomness, (size_t)32U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( + return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____0, uu____1); } @@ -4701,26 +4712,25 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_avx2_SIMD256Vecto memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1152U * sizeof(uint8_t)); uint8_t public_key[1184U]; memcpy(public_key, uu____0.snd, (size_t)1184U * sizeof(uint8_t)); - Eurydice_slice uu____1 = Eurydice_array_to_slice( - (size_t)1152U, ind_cpa_private_key, uint8_t, Eurydice_slice); uint8_t secret_key_serialized[2400U]; libcrux_ml_kem_ind_cca_serialize_kem_secret_key__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_2400size_t( - uu____1, + Eurydice_array_to_slice((size_t)1152U, ind_cpa_private_key, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)1184U, public_key, uint8_t, Eurydice_slice), implicit_rejection_value, secret_key_serialized); - uint8_t uu____2[2400U]; - memcpy(uu____2, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); + uint8_t uu____1[2400U]; + memcpy(uu____1, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey____2400size_t private_key = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPrivateKey_SIZE___8__from___2400size_t( - uu____2); - libcrux_ml_kem_types_MlKemPrivateKey____2400size_t uu____3 = private_key; - uint8_t uu____4[1184U]; - memcpy(uu____4, public_key, (size_t)1184U * sizeof(uint8_t)); + uu____1); + libcrux_ml_kem_types_MlKemPrivateKey____2400size_t uu____2 = private_key; + uint8_t uu____3[1184U]; + memcpy(uu____3, public_key, (size_t)1184U * sizeof(uint8_t)); return libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemKeyPair_PRIVATE_KEY_SIZE__PUBLIC_KEY_SIZE___from___2400size_t_1184size_t( - uu____3, + uu____2, libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPublicKey_SIZE___14__from___1184size_t( - uu____4)); + uu____3)); } __attribute__((target("avx2"))) @@ -4809,7 +4819,7 @@ libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_avx2_SIMD256Ve Eurydice_array_to_subslice_from((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), public_key_serialized); - return core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq( + return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( (size_t)1184U, public_key, public_key_serialized, uint8_t, uint8_t, bool); } diff --git a/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h b/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h index ba79f177..9ed3e89a 100644 --- a/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h +++ b/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem768_portable_H @@ -22,7 +22,7 @@ extern "C" { (LIBCRUX_ML_KEM_HASH_FUNCTIONS_BLOCK_SIZE * (size_t)3U) typedef struct libcrux_ml_kem_hash_functions_neon_Simd128Hash_s { - libcrux_sha3_neon_x2_incremental_KeccakState2 shake128_state[2U]; + libcrux_sha3_neon_x2_incremental_KeccakState shake128_state[2U]; } libcrux_ml_kem_hash_functions_neon_Simd128Hash; #define LIBCRUX_ML_KEM_IND_CCA_ENCAPS_SEED_SIZE \ @@ -732,7 +732,7 @@ static inline libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_cond_subtract_3329( libcrux_ml_kem_vector_portable_PortableVector v) { core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR}), @@ -3269,19 +3269,17 @@ libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K_ state[i] = libcrux_sha3_portable_incremental_shake128_init();); KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &state[i0]; libcrux_sha3_portable_incremental_shake128_absorb_final( - uu____0, Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, - Eurydice_slice));); - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t uu____1[3U]; + &state[i0], Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, + Eurydice_slice));); + libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t uu____0[3U]; memcpy( - uu____1, state, + uu____0, state, (size_t)3U * sizeof(libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t)); libcrux_ml_kem_hash_functions_portable_PortableHash____3size_t lit; memcpy( - lit.shake128_state, uu____1, + lit.shake128_state, uu____0, (size_t)3U * sizeof(libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t)); return lit; @@ -3294,11 +3292,10 @@ libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K_ uint8_t out[3U][504U] = {{0U}}; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &self->shake128_state[i0]; libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( - uu____0, Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, - Eurydice_slice));); + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[504U])); } @@ -3348,13 +3345,11 @@ libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K_ libcrux_ml_kem_hash_functions_portable_PortableHash____3size_t *self, uint8_t ret[3U][168U]) { uint8_t out[3U][168U] = {{0U}}; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *uu____0 = - &self->shake128_state[i0]; - libcrux_sha3_portable_incremental_shake128_squeeze_next_block( - uu____0, Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, - Eurydice_slice));); + KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; + libcrux_sha3_portable_incremental_shake128_squeeze_next_block( + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[168U])); } @@ -3553,13 +3548,12 @@ static inline void libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__portable__PortableHash_K____PRFxN___3size_t_128size_t( uint8_t (*input)[33U], uint8_t ret[3U][128U]) { uint8_t out[3U][128U] = {{0U}}; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_slice((size_t)128U, out[i0], - uint8_t, Eurydice_slice); - libcrux_sha3_portable_shake256( - uu____0, Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, - Eurydice_slice));); + KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; + libcrux_sha3_portable_shake256( + Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t, + Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, + Eurydice_slice));); memcpy(ret, out, (size_t)3U * sizeof(uint8_t[128U])); } @@ -3918,10 +3912,11 @@ libcrux_ml_kem_matrix_compute_vector_u__libcrux_ml_kem_vector_portable_PortableV static inline libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_traits_decompress_1__libcrux_ml_kem_vector_portable_PortableVector( libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_PortableVector uu____0 = + libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___bitwise_and_with_constant( libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(), - &v), + uu____0, &v), (int16_t)1665); } @@ -4343,7 +4338,18 @@ libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_portable_PortableVector_li } static inline void -libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( +libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t( + Eurydice_slice shared_secret, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *_, + uint8_t ret[32U]) { + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + shared_secret, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); +} + +static inline void +libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( libcrux_ml_kem_types_MlKemPrivateKey____2400size_t *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t uu____0 = @@ -4387,7 +4393,7 @@ libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVecto Eurydice_array_to_slice((size_t)64U, hashed, uint8_t, Eurydice_slice), LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE, uint8_t, K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t); - Eurydice_slice shared_secret = uu____3.fst; + Eurydice_slice shared_secret0 = uu____3.fst; Eurydice_slice pseudorandomness = uu____3.snd; uint8_t to_hash[1120U]; libcrux_ml_kem_utils_into_padded_array___1120size_t(implicit_rejection_value, @@ -4400,10 +4406,10 @@ libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVecto libcrux_ml_kem_types___core__convert__AsRef__Slice_u8___for_libcrux_ml_kem__types__MlKemCiphertext_SIZE___1__as_ref___1088size_t( ciphertext), uint8_t, void *); - uint8_t implicit_rejection_shared_secret[32U]; + uint8_t implicit_rejection_shared_secret0[32U]; libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__portable__PortableHash_K____PRF___3size_t_32size_t( Eurydice_array_to_slice((size_t)1120U, to_hash, uint8_t, Eurydice_slice), - implicit_rejection_shared_secret); + implicit_rejection_shared_secret0); Eurydice_slice uu____5 = ind_cpa_public_key; uint8_t uu____6[32U]; memcpy(uu____6, decrypted, (size_t)32U * sizeof(uint8_t)); @@ -4417,10 +4423,18 @@ libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVecto libcrux_ml_kem_constant_time_ops_compare_ciphertexts_in_constant_time___1088size_t( uu____7, Eurydice_array_to_slice((size_t)1088U, expected_ciphertext, uint8_t, Eurydice_slice)); - Eurydice_slice uu____8 = shared_secret; + uint8_t implicit_rejection_shared_secret[32U]; + libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t( + Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret0, + uint8_t, Eurydice_slice), + ciphertext, implicit_rejection_shared_secret); + uint8_t shared_secret[32U]; + libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t( + shared_secret0, ciphertext, shared_secret); uint8_t ret0[32U]; libcrux_ml_kem_constant_time_ops_select_shared_secret_in_constant_time( - uu____8, + Eurydice_array_to_slice((size_t)32U, shared_secret, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)32U, implicit_rejection_shared_secret, uint8_t, Eurydice_slice), selector, ret0); @@ -4432,7 +4446,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_decapsulate___3size_t_2400size_t_ libcrux_ml_kem_types_MlKemPrivateKey____2400size_t *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { uint8_t ret0[32U]; - libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( + libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( private_key, ciphertext, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } @@ -4446,6 +4460,16 @@ static inline void libcrux_ml_kem_mlkem768_portable_decapsulate( memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } +static inline void +libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___entropy_preprocess__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + Eurydice_slice randomness, uint8_t ret[32U]) { + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + randomness, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); +} + static inline void libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__portable__PortableHash_K____H___3size_t( Eurydice_slice input, uint8_t ret[32U]) { @@ -4457,12 +4481,17 @@ libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K_ } static inline K___libcrux_ml_kem_types_MlKemCiphertext___1088size_t___uint8_t_32size_t_ -libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( libcrux_ml_kem_types_MlKemPublicKey____1184size_t *public_key, uint8_t randomness[32U]) { + uint8_t randomness0[32U]; + libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___entropy_preprocess__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + Eurydice_array_to_slice((size_t)32U, randomness, uint8_t, Eurydice_slice), + randomness0); uint8_t to_hash[64U]; libcrux_ml_kem_utils_into_padded_array___64size_t( - Eurydice_array_to_slice((size_t)32U, randomness, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)32U, randomness0, uint8_t, + Eurydice_slice), to_hash); Eurydice_slice uu____0 = Eurydice_array_to_subslice_from( (size_t)64U, to_hash, LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE, uint8_t, @@ -4496,20 +4525,19 @@ libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVecto public_key), uint8_t, Eurydice_slice); uint8_t uu____3[32U]; - memcpy(uu____3, randomness, (size_t)32U * sizeof(uint8_t)); + memcpy(uu____3, randomness0, (size_t)32U * sizeof(uint8_t)); uint8_t ciphertext[1088U]; libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____2, uu____3, pseudorandomness, ciphertext); - uint8_t shared_secret_array[32U] = {0U}; - core_slice___Slice_T___copy_from_slice( - Eurydice_array_to_slice((size_t)32U, shared_secret_array, uint8_t, - Eurydice_slice), - shared_secret, uint8_t, void *); uint8_t uu____4[1088U]; memcpy(uu____4, ciphertext, (size_t)1088U * sizeof(uint8_t)); - libcrux_ml_kem_mlkem768_MlKem768Ciphertext uu____5 = + libcrux_ml_kem_mlkem768_MlKem768Ciphertext ciphertext0 = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemCiphertext_SIZE___2__from___1088size_t( uu____4); + uint8_t shared_secret_array[32U]; + libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__ind_cca__MlKem___kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t( + shared_secret, &ciphertext0, shared_secret_array); + libcrux_ml_kem_mlkem768_MlKem768Ciphertext uu____5 = ciphertext0; uint8_t uu____6[32U]; memcpy(uu____6, shared_secret_array, (size_t)32U * sizeof(uint8_t)); K___libcrux_ml_kem_types_MlKemCiphertext___1088size_t___uint8_t_32size_t_ lit; @@ -4525,7 +4553,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_encapsulate___3size_t_1088size_t_ libcrux_ml_kem_types_MlKemPublicKey____1184size_t *uu____0 = public_key; uint8_t uu____1[32U]; memcpy(uu____1, randomness, (size_t)32U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( + return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____0, uu____1); } @@ -4898,26 +4926,25 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1152U * sizeof(uint8_t)); uint8_t public_key[1184U]; memcpy(public_key, uu____0.snd, (size_t)1184U * sizeof(uint8_t)); - Eurydice_slice uu____1 = Eurydice_array_to_slice( - (size_t)1152U, ind_cpa_private_key, uint8_t, Eurydice_slice); uint8_t secret_key_serialized[2400U]; libcrux_ml_kem_ind_cca_serialize_kem_secret_key__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2400size_t( - uu____1, + Eurydice_array_to_slice((size_t)1152U, ind_cpa_private_key, uint8_t, + Eurydice_slice), Eurydice_array_to_slice((size_t)1184U, public_key, uint8_t, Eurydice_slice), implicit_rejection_value, secret_key_serialized); - uint8_t uu____2[2400U]; - memcpy(uu____2, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); + uint8_t uu____1[2400U]; + memcpy(uu____1, secret_key_serialized, (size_t)2400U * sizeof(uint8_t)); libcrux_ml_kem_types_MlKemPrivateKey____2400size_t private_key = libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPrivateKey_SIZE___8__from___2400size_t( - uu____2); - libcrux_ml_kem_types_MlKemPrivateKey____2400size_t uu____3 = private_key; - uint8_t uu____4[1184U]; - memcpy(uu____4, public_key, (size_t)1184U * sizeof(uint8_t)); + uu____1); + libcrux_ml_kem_types_MlKemPrivateKey____2400size_t uu____2 = private_key; + uint8_t uu____3[1184U]; + memcpy(uu____3, public_key, (size_t)1184U * sizeof(uint8_t)); return libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemKeyPair_PRIVATE_KEY_SIZE__PUBLIC_KEY_SIZE___from___2400size_t_1184size_t( - uu____3, + uu____2, libcrux_ml_kem_types___core__convert__From__Array_u8__SIZE___for_libcrux_ml_kem__types__MlKemPublicKey_SIZE___14__from___1184size_t( - uu____4)); + uu____3)); } static inline libcrux_ml_kem_mlkem768_MlKem768KeyPair @@ -5001,7 +5028,7 @@ libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_Porta Eurydice_array_to_subslice_from((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), public_key_serialized); - return core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq( + return core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( (size_t)1184U, public_key, public_key_serialized, uint8_t, uint8_t, bool); } diff --git a/libcrux-ml-kem/cg/libcrux_sha3_avx2.h b/libcrux-ml-kem/cg/libcrux_sha3_avx2.h index 51717b01..2bc4d84e 100644 --- a/libcrux-ml-kem/cg/libcrux_sha3_avx2.h +++ b/libcrux-ml-kem/cg/libcrux_sha3_avx2.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_sha3_avx2_H @@ -1252,8 +1252,7 @@ libcrux_sha3_generic_keccak_pi__core_core_arch_x86___m256i_4size_t( libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t *s) { core_core_arch_x86___m256i old[5U][5U]; - core_array___core__clone__Clone_for__Array_T__N___20__clone( - (size_t)5U, s->st, old, core_core_arch_x86___m256i[5U], void *); + memcpy(old, s->st, (size_t)5U * sizeof(core_core_arch_x86___m256i[5U])); s->st[0U][1U] = old[1U][1U]; s->st[0U][2U] = old[2U][2U]; s->st[0U][3U] = old[3U][3U]; @@ -1342,17 +1341,15 @@ libcrux_sha3_generic_keccak_absorb_block__core_core_arch_x86___m256i_4size_t_136 __attribute__((target("avx2"))) static inline void libcrux_sha3_simd_avx2_load_block_full___136size_t( core_core_arch_x86___m256i (*s)[5U], uint8_t blocks[4U][200U]) { - core_core_arch_x86___m256i(*uu____0)[5U] = s; - Eurydice_slice uu____1 = Eurydice_array_to_slice((size_t)200U, blocks[0U], - uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = Eurydice_array_to_slice((size_t)200U, blocks[1U], - uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = Eurydice_array_to_slice((size_t)200U, blocks[2U], - uint8_t, Eurydice_slice); - Eurydice_slice buf[4U] = {uu____1, uu____2, uu____3, + Eurydice_slice buf[4U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], + uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, blocks[1U], + uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, blocks[2U], + uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)200U, blocks[3U], uint8_t, Eurydice_slice)}; - libcrux_sha3_simd_avx2_load_block___136size_t(uu____0, buf); + libcrux_sha3_simd_avx2_load_block___136size_t(s, buf); } __attribute__((target("avx2"))) @@ -1373,22 +1370,23 @@ libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_136 Eurydice_slice last[4U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[4U][200U] = {{0U}}; - KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i0], - (CLITERAL(core_ops_range_Range__size_t){ - .start = (size_t)0U, .end = last_len}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i0], - uint8_t, void *); - blocks[i0][last_len] = 31U; - blocks[i0][(size_t)136U - (size_t)1U] = - (uint32_t)blocks[i0][(size_t)136U - (size_t)1U] | 128U;); - core_core_arch_x86___m256i(*uu____1)[5U] = s->st; - uint8_t uu____2[4U][200U]; - memcpy(uu____2, blocks, (size_t)4U * sizeof(uint8_t[200U])); + KRML_MAYBE_FOR4( + i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)200U, blocks[i0], + (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, + .end = last_len}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, + void *); + blocks[i0][last_len] = 31U; size_t uu____1 = i0; + size_t uu____2 = (size_t)136U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U;); + core_core_arch_x86___m256i(*uu____3)[5U] = s->st; + uint8_t uu____4[4U][200U]; + memcpy(uu____4, blocks, (size_t)4U * sizeof(uint8_t[200U])); libcrux_sha3_simd_avx2___libcrux_sha3__traits__internal__KeccakItem_4__usize__for_core__core_arch__x86____m256i___load_block_full___136size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__core_core_arch_x86___m256i_4size_t( s); } @@ -1474,55 +1472,55 @@ static inline void libcrux_sha3_simd_avx2_store_block___136size_t( uint8_t u8s[32U] = {0U}; size_t i0 = (size_t)4U * ((size_t)136U / (size_t)32U) / (size_t)5U; size_t j0 = (size_t)4U * ((size_t)136U / (size_t)32U) % (size_t)5U; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)32U, u8s, uint8_t, Eurydice_slice); - libcrux_intrinsics_avx2_mm256_storeu_si256_u8(uu____0, s[i0][j0]); - Eurydice_slice uu____1 = Eurydice_slice_subslice( + libcrux_intrinsics_avx2_mm256_storeu_si256_u8( + Eurydice_array_to_slice((size_t)32U, u8s, uint8_t, Eurydice_slice), + s[i0][j0]); + Eurydice_slice uu____0 = Eurydice_slice_subslice( out[0U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____1, + uu____0, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____2 = Eurydice_slice_subslice( + Eurydice_slice uu____1 = Eurydice_slice_subslice( out[1U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____2, + uu____1, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)8U, .end = (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____3 = Eurydice_slice_subslice( + Eurydice_slice uu____2 = Eurydice_slice_subslice( out[2U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____3, + uu____2, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)16U, .end = (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____4 = Eurydice_slice_subslice( + Eurydice_slice uu____3 = Eurydice_slice_subslice( out[3U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____4, + uu____3, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)24U, .end = (size_t)32U}), @@ -1535,55 +1533,55 @@ static inline void libcrux_sha3_simd_avx2_store_block___136size_t( ((size_t)4U * ((size_t)136U / (size_t)32U) + (size_t)1U) / (size_t)5U; size_t j = ((size_t)4U * ((size_t)136U / (size_t)32U) + (size_t)1U) % (size_t)5U; - Eurydice_slice uu____5 = - Eurydice_array_to_slice((size_t)32U, u8s0, uint8_t, Eurydice_slice); - libcrux_intrinsics_avx2_mm256_storeu_si256_u8(uu____5, s[i][j]); - Eurydice_slice uu____6 = Eurydice_slice_subslice( + libcrux_intrinsics_avx2_mm256_storeu_si256_u8( + Eurydice_array_to_slice((size_t)32U, u8s0, uint8_t, Eurydice_slice), + s[i][j]); + Eurydice_slice uu____4 = Eurydice_slice_subslice( out[0U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____6, + uu____4, Eurydice_array_to_subslice((size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____7 = Eurydice_slice_subslice( + Eurydice_slice uu____5 = Eurydice_slice_subslice( out[1U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____7, + uu____5, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)8U, .end = (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____8 = Eurydice_slice_subslice( + Eurydice_slice uu____6 = Eurydice_slice_subslice( out[2U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____8, + uu____6, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)16U, .end = (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____9 = Eurydice_slice_subslice( + Eurydice_slice uu____7 = Eurydice_slice_subslice( out[3U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____9, + uu____7, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)24U, @@ -1600,29 +1598,24 @@ static inline void libcrux_sha3_simd_avx2_store_block_full___136size_t( uint8_t out1[200U] = {0U}; uint8_t out2[200U] = {0U}; uint8_t out3[200U] = {0U}; - core_core_arch_x86___m256i(*uu____0)[5U] = s; - Eurydice_slice uu____1 = - Eurydice_array_to_slice((size_t)200U, out0, uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = - Eurydice_array_to_slice((size_t)200U, out1, uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = - Eurydice_array_to_slice((size_t)200U, out2, uint8_t, Eurydice_slice); Eurydice_slice buf[4U] = { - uu____1, uu____2, uu____3, + Eurydice_array_to_slice((size_t)200U, out0, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, out1, uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, out2, uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)200U, out3, uint8_t, Eurydice_slice)}; - libcrux_sha3_simd_avx2_store_block___136size_t(uu____0, buf); - uint8_t uu____4[200U]; - memcpy(uu____4, out0, (size_t)200U * sizeof(uint8_t)); - uint8_t uu____5[200U]; - memcpy(uu____5, out1, (size_t)200U * sizeof(uint8_t)); - uint8_t uu____6[200U]; - memcpy(uu____6, out2, (size_t)200U * sizeof(uint8_t)); - uint8_t uu____7[200U]; - memcpy(uu____7, out3, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____4, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[1U], uu____5, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[2U], uu____6, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[3U], uu____7, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_simd_avx2_store_block___136size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out0, (size_t)200U * sizeof(uint8_t)); + uint8_t uu____1[200U]; + memcpy(uu____1, out1, (size_t)200U * sizeof(uint8_t)); + uint8_t uu____2[200U]; + memcpy(uu____2, out2, (size_t)200U * sizeof(uint8_t)); + uint8_t uu____3[200U]; + memcpy(uu____3, out3, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[1U], uu____1, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[2U], uu____2, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[3U], uu____3, (size_t)200U * sizeof(uint8_t)); } __attribute__((target("avx2"))) @@ -1758,7 +1751,7 @@ libcrux_sha3_generic_keccak_keccak__core_core_arch_x86___m256i_4size_t_136size_t libcrux_sha3_generic_keccak_squeeze_first_block__core_core_arch_x86___m256i_4size_t_136size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -1799,7 +1792,7 @@ static inline void libcrux_sha3_avx2_x4_shake256( } typedef libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t - libcrux_sha3_avx2_x4_incremental_KeccakState4; + libcrux_sha3_avx2_x4_incremental_KeccakState; __attribute__((target("avx2"))) static inline libcrux_sha3_generic_keccak_KeccakState__core_core_arch_x86___m256i__4size_t @@ -2020,17 +2013,15 @@ static inline void libcrux_sha3_simd_avx2_load_block___168size_t( __attribute__((target("avx2"))) static inline void libcrux_sha3_simd_avx2_load_block_full___168size_t( core_core_arch_x86___m256i (*s)[5U], uint8_t blocks[4U][200U]) { - core_core_arch_x86___m256i(*uu____0)[5U] = s; - Eurydice_slice uu____1 = Eurydice_array_to_slice((size_t)200U, blocks[0U], - uint8_t, Eurydice_slice); - Eurydice_slice uu____2 = Eurydice_array_to_slice((size_t)200U, blocks[1U], - uint8_t, Eurydice_slice); - Eurydice_slice uu____3 = Eurydice_array_to_slice((size_t)200U, blocks[2U], - uint8_t, Eurydice_slice); - Eurydice_slice buf[4U] = {uu____1, uu____2, uu____3, + Eurydice_slice buf[4U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], + uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, blocks[1U], + uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)200U, blocks[2U], + uint8_t, Eurydice_slice), Eurydice_array_to_slice((size_t)200U, blocks[3U], uint8_t, Eurydice_slice)}; - libcrux_sha3_simd_avx2_load_block___168size_t(uu____0, buf); + libcrux_sha3_simd_avx2_load_block___168size_t(s, buf); } __attribute__((target("avx2"))) @@ -2051,22 +2042,23 @@ libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168 Eurydice_slice last[4U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[4U][200U] = {{0U}}; - KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i0], - (CLITERAL(core_ops_range_Range__size_t){ - .start = (size_t)0U, .end = last_len}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i0], - uint8_t, void *); - blocks[i0][last_len] = 31U; - blocks[i0][(size_t)168U - (size_t)1U] = - (uint32_t)blocks[i0][(size_t)168U - (size_t)1U] | 128U;); - core_core_arch_x86___m256i(*uu____1)[5U] = s->st; - uint8_t uu____2[4U][200U]; - memcpy(uu____2, blocks, (size_t)4U * sizeof(uint8_t[200U])); + KRML_MAYBE_FOR4( + i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)200U, blocks[i0], + (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, + .end = last_len}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, + void *); + blocks[i0][last_len] = 31U; size_t uu____1 = i0; + size_t uu____2 = (size_t)168U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U;); + core_core_arch_x86___m256i(*uu____3)[5U] = s->st; + uint8_t uu____4[4U][200U]; + memcpy(uu____4, blocks, (size_t)4U * sizeof(uint8_t[200U])); libcrux_sha3_simd_avx2___libcrux_sha3__traits__internal__KeccakItem_4__usize__for_core__core_arch__x86____m256i___load_block_full___168size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__core_core_arch_x86___m256i_4size_t( s); } @@ -2163,55 +2155,55 @@ static inline void libcrux_sha3_simd_avx2_store_block___168size_t( uint8_t u8s[32U] = {0U}; size_t i0 = (size_t)4U * ((size_t)168U / (size_t)32U) / (size_t)5U; size_t j0 = (size_t)4U * ((size_t)168U / (size_t)32U) % (size_t)5U; - Eurydice_slice uu____0 = - Eurydice_array_to_slice((size_t)32U, u8s, uint8_t, Eurydice_slice); - libcrux_intrinsics_avx2_mm256_storeu_si256_u8(uu____0, s[i0][j0]); - Eurydice_slice uu____1 = Eurydice_slice_subslice( + libcrux_intrinsics_avx2_mm256_storeu_si256_u8( + Eurydice_array_to_slice((size_t)32U, u8s, uint8_t, Eurydice_slice), + s[i0][j0]); + Eurydice_slice uu____0 = Eurydice_slice_subslice( out[0U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____1, + uu____0, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____2 = Eurydice_slice_subslice( + Eurydice_slice uu____1 = Eurydice_slice_subslice( out[1U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____2, + uu____1, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)8U, .end = (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____3 = Eurydice_slice_subslice( + Eurydice_slice uu____2 = Eurydice_slice_subslice( out[2U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____3, + uu____2, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)16U, .end = (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____4 = Eurydice_slice_subslice( + Eurydice_slice uu____3 = Eurydice_slice_subslice( out[3U], (CLITERAL(core_ops_range_Range__size_t){.start = start, .end = start + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____4, + uu____3, Eurydice_array_to_subslice((size_t)32U, u8s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)24U, .end = (size_t)32U}), @@ -2224,55 +2216,55 @@ static inline void libcrux_sha3_simd_avx2_store_block___168size_t( ((size_t)4U * ((size_t)168U / (size_t)32U) + (size_t)1U) / (size_t)5U; size_t j = ((size_t)4U * ((size_t)168U / (size_t)32U) + (size_t)1U) % (size_t)5U; - Eurydice_slice uu____5 = - Eurydice_array_to_slice((size_t)32U, u8s0, uint8_t, Eurydice_slice); - libcrux_intrinsics_avx2_mm256_storeu_si256_u8(uu____5, s[i][j]); - Eurydice_slice uu____6 = Eurydice_slice_subslice( + libcrux_intrinsics_avx2_mm256_storeu_si256_u8( + Eurydice_array_to_slice((size_t)32U, u8s0, uint8_t, Eurydice_slice), + s[i][j]); + Eurydice_slice uu____4 = Eurydice_slice_subslice( out[0U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____6, + uu____4, Eurydice_array_to_subslice((size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____7 = Eurydice_slice_subslice( + Eurydice_slice uu____5 = Eurydice_slice_subslice( out[1U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____7, + uu____5, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)8U, .end = (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____8 = Eurydice_slice_subslice( + Eurydice_slice uu____6 = Eurydice_slice_subslice( out[2U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____8, + uu____6, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)16U, .end = (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice), uint8_t, void *); - Eurydice_slice uu____9 = Eurydice_slice_subslice( + Eurydice_slice uu____7 = Eurydice_slice_subslice( out[3U], (CLITERAL(core_ops_range_Range__size_t){.start = start + (size_t)8U, .end = start + (size_t)16U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice( - uu____9, + uu____7, Eurydice_array_to_subslice( (size_t)32U, u8s0, (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)24U, diff --git a/libcrux-ml-kem/cg/libcrux_sha3_portable.h b/libcrux-ml-kem/cg/libcrux_sha3_portable.h index dc6234dd..431ba627 100644 --- a/libcrux-ml-kem/cg/libcrux_sha3_portable.h +++ b/libcrux-ml-kem/cg/libcrux_sha3_portable.h @@ -2,7 +2,7 @@ This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL version: 42a43169 */ #ifndef __libcrux_sha3_portable_H @@ -817,8 +817,7 @@ static inline void libcrux_sha3_generic_keccak_theta_rho__uint64_t_1size_t( static inline void libcrux_sha3_generic_keccak_pi__uint64_t_1size_t( libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *s) { uint64_t old[5U][5U]; - core_array___core__clone__Clone_for__Array_T__N___20__clone( - (size_t)5U, s->st, old, uint64_t[5U], void *); + memcpy(old, s->st, (size_t)5U * sizeof(uint64_t[5U])); s->st[0U][1U] = old[1U][1U]; s->st[0U][2U] = old[2U][2U]; s->st[0U][3U] = old[3U][3U]; @@ -892,10 +891,9 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_72size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___72size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___72size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___72size_t(s, buf); } static inline void @@ -922,14 +920,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_72size_t_6uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 6U; - blocks[i][(size_t)72U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)72U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)72U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___72size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -954,13 +953,12 @@ static inline void libcrux_sha3_portable_keccak_store_block___72size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___72size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___72size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___72size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -1087,7 +1085,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_72size_t_6uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_72size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -1177,10 +1175,9 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_136size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___136size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___136size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___136size_t(s, buf); } static inline void @@ -1207,14 +1204,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_136size_t_6uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 6U; - blocks[i][(size_t)136U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)136U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)136U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___136size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -1239,13 +1237,12 @@ static inline void libcrux_sha3_portable_keccak_store_block___136size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___136size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___136size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___136size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -1372,7 +1369,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_136size_t_6uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_136size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -1431,14 +1428,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_136size_t_31uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 31U; - blocks[i][(size_t)136U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)136U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)136U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___136size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -1488,7 +1486,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_136size_t_31uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_136size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -1556,13 +1554,13 @@ static inline void libcrux_sha3_neon_x2_shake256(Eurydice_slice input0, } typedef libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t - libcrux_sha3_portable_KeccakState1; + libcrux_sha3_portable_KeccakState; -typedef struct libcrux_sha3_neon_x2_incremental_KeccakState2_s { +typedef struct libcrux_sha3_neon_x2_incremental_KeccakState_s { libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t state[2U]; -} libcrux_sha3_neon_x2_incremental_KeccakState2; +} libcrux_sha3_neon_x2_incremental_KeccakState; -static inline libcrux_sha3_neon_x2_incremental_KeccakState2 +static inline libcrux_sha3_neon_x2_incremental_KeccakState libcrux_sha3_neon_x2_incremental_shake128_init(void) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); @@ -1570,7 +1568,7 @@ libcrux_sha3_neon_x2_incremental_shake128_init(void) { } static inline void libcrux_sha3_neon_x2_incremental_shake128_absorb_final( - libcrux_sha3_neon_x2_incremental_KeccakState2 *s, Eurydice_slice data0, + libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice data0, Eurydice_slice data1) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); @@ -1578,7 +1576,7 @@ static inline void libcrux_sha3_neon_x2_incremental_shake128_absorb_final( } static inline void libcrux_sha3_neon_x2_incremental_shake128_squeeze_next_block( - libcrux_sha3_neon_x2_incremental_KeccakState2 *s, Eurydice_slice out0, + libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice out0, Eurydice_slice out1) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); @@ -1587,7 +1585,7 @@ static inline void libcrux_sha3_neon_x2_incremental_shake128_squeeze_next_block( static inline void libcrux_sha3_neon_x2_incremental_shake128_squeeze_first_three_blocks( - libcrux_sha3_neon_x2_incremental_KeccakState2 *s, Eurydice_slice out0, + libcrux_sha3_neon_x2_incremental_KeccakState *s, Eurydice_slice out0, Eurydice_slice out1) { KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, "panic!"); @@ -1624,10 +1622,9 @@ static inline void libcrux_sha3_portable_keccak_load_block___168size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___168size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___168size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___168size_t(s, buf); } static inline void @@ -1654,14 +1651,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_168size_t_31uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 31U; - blocks[i][(size_t)168U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)168U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)168U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___168size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -1839,10 +1837,9 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_144size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___144size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___144size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___144size_t(s, buf); } static inline void @@ -1869,14 +1866,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_144size_t_6uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 6U; - blocks[i][(size_t)144U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)144U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)144U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___144size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -1901,13 +1899,12 @@ static inline void libcrux_sha3_portable_keccak_store_block___144size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___144size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___144size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___144size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -2034,7 +2031,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_144size_t_6uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_144size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -2124,10 +2121,9 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_104size_t( static inline void libcrux_sha3_portable_keccak_load_block_full___104size_t( uint64_t (*s)[5U], uint8_t blocks[1U][200U]) { - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = {Eurydice_array_to_slice((size_t)200U, blocks[0U], uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_load_block___104size_t(uu____0, buf); + libcrux_sha3_portable_keccak_load_block___104size_t(s, buf); } static inline void @@ -2154,14 +2150,15 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_104size_t_6uint8_t( uint8_t, core_ops_range_Range__size_t, Eurydice_slice); core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); blocks[i][last_len] = 6U; - blocks[i][(size_t)104U - (size_t)1U] = - (uint32_t)blocks[i][(size_t)104U - (size_t)1U] | 128U; + size_t uu____1 = i; + size_t uu____2 = (size_t)104U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } - uint64_t(*uu____1)[5U] = s->st; - uint8_t uu____2[1U][200U]; - memcpy(uu____2, blocks, (size_t)1U * sizeof(uint8_t[200U])); + uint64_t(*uu____3)[5U] = s->st; + uint8_t uu____4[1U][200U]; + memcpy(uu____4, blocks, (size_t)1U * sizeof(uint8_t[200U])); libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___load_block_full___104size_t( - uu____1, uu____2); + uu____3, uu____4); libcrux_sha3_generic_keccak_keccakf1600__uint64_t_1size_t(s); } @@ -2186,13 +2183,12 @@ static inline void libcrux_sha3_portable_keccak_store_block___104size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___104size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___104size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___104size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -2319,7 +2315,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_104size_t_6uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_104size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -2435,13 +2431,12 @@ libcrux_sha3_generic_keccak_absorb_block__uint64_t_1size_t_168size_t( static inline void libcrux_sha3_portable_keccak_store_block_full___168size_t( uint64_t (*s)[5U], uint8_t ret[1U][200U]) { uint8_t out[200U] = {0U}; - uint64_t(*uu____0)[5U] = s; Eurydice_slice buf[1U] = { Eurydice_array_to_slice((size_t)200U, out, uint8_t, Eurydice_slice)}; - libcrux_sha3_portable_keccak_store_block___168size_t(uu____0, buf); - uint8_t uu____1[200U]; - memcpy(uu____1, out, (size_t)200U * sizeof(uint8_t)); - memcpy(ret[0U], uu____1, (size_t)200U * sizeof(uint8_t)); + libcrux_sha3_portable_keccak_store_block___168size_t(s, buf); + uint8_t uu____0[200U]; + memcpy(uu____0, out, (size_t)200U * sizeof(uint8_t)); + memcpy(ret[0U], uu____0, (size_t)200U * sizeof(uint8_t)); } static inline void @@ -2545,7 +2540,7 @@ libcrux_sha3_generic_keccak_keccak__uint64_t_1size_t_168size_t_31uint8_t( libcrux_sha3_generic_keccak_squeeze_first_block__uint64_t_1size_t_168size_t( &s, o0); core_ops_range_Range__size_t iter = - core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter( + core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)1U, .end = blocks}), core_ops_range_Range__size_t, core_ops_range_Range__size_t); @@ -2671,7 +2666,7 @@ libcrux_sha3_portable_incremental_shake128_squeeze_first_five_blocks( } static inline libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t -libcrux_sha3_portable___core__clone__Clone_for_libcrux_sha3__portable__KeccakState1___clone( +libcrux_sha3_portable___core__clone__Clone_for_libcrux_sha3__portable__KeccakState___clone( libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *self) { return self[0U]; } diff --git a/libcrux-ml-kem/src/ind_cca.rs b/libcrux-ml-kem/src/ind_cca.rs index 34fcd5bc..f5d5883d 100644 --- a/libcrux-ml-kem/src/ind_cca.rs +++ b/libcrux-ml-kem/src/ind_cca.rs @@ -301,11 +301,15 @@ impl Variant for MlKem { shared_secret: &[u8], _: &MlKemCiphertext, ) -> [u8; 32] { - shared_secret.try_into().unwrap() + let mut out = [0u8; 32]; + out.copy_from_slice(shared_secret); + out } #[inline(always)] fn entropy_preprocess>(randomness: &[u8]) -> [u8; 32] { - randomness.try_into().unwrap() + let mut out = [0u8; 32]; + out.copy_from_slice(randomness); + out } } From 65fd9fd307bf3a7998f52049b8d0f089b24ee6fe Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 15:26:41 +0200 Subject: [PATCH 50/53] update C code --- libcrux-ml-kem/c/internal/libcrux_core.h | 21 +- .../c/internal/libcrux_mlkem_portable.h | 24 +- libcrux-ml-kem/c/libcrux_core.c | 14 - libcrux-ml-kem/c/libcrux_core.h | 4 +- libcrux-ml-kem/c/libcrux_mlkem512_portable.c | 24 +- libcrux-ml-kem/c/libcrux_mlkem_avx2.c | 76 +- libcrux-ml-kem/c/libcrux_mlkem_portable.c | 3260 +++++++++-------- libcrux-ml-kem/c/libcrux_mlkem_portable.h | 376 +- .../c/libcrux_sha3_libcrux_ml_kem.h | 6 +- 9 files changed, 1985 insertions(+), 1820 deletions(-) diff --git a/libcrux-ml-kem/c/internal/libcrux_core.h b/libcrux-ml-kem/c/internal/libcrux_core.h index e6ac1986..8ac7a4eb 100644 --- a/libcrux-ml-kem/c/internal/libcrux_core.h +++ b/libcrux-ml-kem/c/internal/libcrux_core.h @@ -138,19 +138,6 @@ uint8_t * libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemPublicKey_SIZE__18__as_slice___800size_t( libcrux_ml_kem_types_MlKemPublicKey____800size_t *self); -typedef struct - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError_s { - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError_tags tag; - union { - uint8_t case_Ok[32U]; - core_array_TryFromSliceError case_Err; - } val; -} core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError; - -void core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError self, - uint8_t ret[32U]); - uint8_t libcrux_ml_kem_constant_time_ops_compare_ciphertexts_in_constant_time___768size_t( Eurydice_slice lhs, Eurydice_slice rhs); @@ -173,7 +160,7 @@ void libcrux_ml_kem_utils_into_padded_array___64size_t(Eurydice_slice slice, typedef struct core_result_Result__uint8_t_24size_t__core_array_TryFromSliceError_s { - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError_tags tag; + core_result_Result__uint8_t_24size_t__core_array_TryFromSliceError_tags tag; union { uint8_t case_Ok[24U]; core_array_TryFromSliceError case_Err; @@ -186,7 +173,7 @@ void core_result__core__result__Result_T__E___unwrap__uint8_t_24size_t__core_arr typedef struct core_result_Result__uint8_t_20size_t__core_array_TryFromSliceError_s { - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError_tags tag; + core_result_Result__uint8_t_24size_t__core_array_TryFromSliceError_tags tag; union { uint8_t case_Ok[20U]; core_array_TryFromSliceError case_Err; @@ -199,7 +186,7 @@ void core_result__core__result__Result_T__E___unwrap__uint8_t_20size_t__core_arr typedef struct core_result_Result__uint8_t_10size_t__core_array_TryFromSliceError_s { - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError_tags tag; + core_result_Result__uint8_t_24size_t__core_array_TryFromSliceError_tags tag; union { uint8_t case_Ok[10U]; core_array_TryFromSliceError case_Err; @@ -212,7 +199,7 @@ void core_result__core__result__Result_T__E___unwrap__uint8_t_10size_t__core_arr typedef struct core_result_Result__int16_t_16size_t__core_array_TryFromSliceError_s { - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError_tags tag; + core_result_Result__uint8_t_24size_t__core_array_TryFromSliceError_tags tag; union { int16_t case_Ok[16U]; core_array_TryFromSliceError case_Err; diff --git a/libcrux-ml-kem/c/internal/libcrux_mlkem_portable.h b/libcrux-ml-kem/c/internal/libcrux_mlkem_portable.h index 9905d0fc..18964fd5 100644 --- a/libcrux-ml-kem/c/internal/libcrux_mlkem_portable.h +++ b/libcrux-ml-kem/c/internal/libcrux_mlkem_portable.h @@ -23,51 +23,51 @@ extern const int16_t libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[128U]; (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / \ LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR) -bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536size_t_1568size_t( +bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1536size_t_1568size_t( uint8_t *public_key); libcrux_ml_kem_mlkem1024_MlKem1024KeyPair -libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_3168size_t_1568size_t_1536size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_3168size_t_1568size_t_1536size_t_2size_t_128size_t( uint8_t randomness[64U]); K___libcrux_ml_kem_types_MlKemCiphertext___1568size_t___uint8_t_32size_t_ -libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( libcrux_ml_kem_types_MlKemPublicKey____1568size_t *public_key, uint8_t randomness[32U]); -void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_3168size_t_1536size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t_1600size_t( +void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_3168size_t_1536size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t_1600size_t( libcrux_ml_kem_types_MlKemPrivateKey____3168size_t *private_key, libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext, uint8_t ret[32U]); -bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( +bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( uint8_t *public_key); libcrux_ml_kem_mlkem768_MlKem768KeyPair -libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( uint8_t randomness[64U]); K___libcrux_ml_kem_types_MlKemCiphertext___1088size_t___uint8_t_32size_t_ -libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( libcrux_ml_kem_types_MlKemPublicKey____1184size_t *public_key, uint8_t randomness[32U]); -void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( +void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( libcrux_ml_kem_types_MlKemPrivateKey____2400size_t *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]); -bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_800size_t( +bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_800size_t( uint8_t *public_key); libcrux_ml_kem_types_MlKemKeyPair____1632size_t__800size_t -libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_1632size_t_800size_t_768size_t_3size_t_192size_t( +libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_1632size_t_800size_t_768size_t_3size_t_192size_t( uint8_t randomness[64U]); K___libcrux_ml_kem_types_MlKemCiphertext___768size_t___uint8_t_32size_t_ -libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_768size_t_800size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_768size_t_800size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( libcrux_ml_kem_types_MlKemPublicKey____800size_t *public_key, uint8_t randomness[32U]); -void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_1632size_t_768size_t_800size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t_800size_t( +void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_1632size_t_768size_t_800size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t_800size_t( libcrux_ml_kem_types_MlKemPrivateKey____1632size_t *private_key, libcrux_ml_kem_types_MlKemCiphertext____768size_t *ciphertext, uint8_t ret[32U]); diff --git a/libcrux-ml-kem/c/libcrux_core.c b/libcrux-ml-kem/c/libcrux_core.c index 7113bd76..23efe21c 100644 --- a/libcrux-ml-kem/c/libcrux_core.c +++ b/libcrux-ml-kem/c/libcrux_core.c @@ -242,20 +242,6 @@ libcrux_ml_kem_types__libcrux_ml_kem__types__MlKemPublicKey_SIZE__18__as_slice__ return self->value; } -void core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError self, - uint8_t ret[32U]) { - if (self.tag == core_result_Ok) { - uint8_t f0[32U]; - memcpy(f0, self.val.case_Ok, (size_t)32U * sizeof(uint8_t)); - memcpy(ret, f0, (size_t)32U * sizeof(uint8_t)); - } else { - KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n", __FILE__, __LINE__, - "unwrap not Ok"); - KRML_HOST_EXIT(255U); - } -} - uint8_t libcrux_ml_kem_constant_time_ops_compare_ciphertexts_in_constant_time___768size_t( Eurydice_slice lhs, Eurydice_slice rhs) { diff --git a/libcrux-ml-kem/c/libcrux_core.h b/libcrux-ml-kem/c/libcrux_core.h index d6566c1d..f4c2f05d 100644 --- a/libcrux-ml-kem/c/libcrux_core.h +++ b/libcrux-ml-kem/c/libcrux_core.h @@ -128,11 +128,11 @@ typedef struct #define core_result_Err 1 typedef uint8_t - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError_tags; + core_result_Result__uint8_t_24size_t__core_array_TryFromSliceError_tags; typedef struct core_result_Result__uint8_t_8size_t__core_array_TryFromSliceError_s { - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError_tags tag; + core_result_Result__uint8_t_24size_t__core_array_TryFromSliceError_tags tag; union { uint8_t case_Ok[8U]; core_array_TryFromSliceError case_Err; diff --git a/libcrux-ml-kem/c/libcrux_mlkem512_portable.c b/libcrux-ml-kem/c/libcrux_mlkem512_portable.c index 6a7cdbce..90a3fa4e 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem512_portable.c +++ b/libcrux-ml-kem/c/libcrux_mlkem512_portable.c @@ -14,7 +14,7 @@ void libcrux_ml_kem_ind_cca_instantiations_portable_decapsulate___2size_t_1632si libcrux_ml_kem_types_MlKemCiphertext____768size_t *ciphertext, uint8_t ret[32U]) { uint8_t ret0[32U]; - libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_1632size_t_768size_t_800size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t_800size_t( + libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_1632size_t_768size_t_800size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t_800size_t( private_key, ciphertext, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } @@ -36,7 +36,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_encapsulate___2size_t_768size_t_8 libcrux_ml_kem_types_MlKemPublicKey____800size_t *uu____0 = public_key; uint8_t uu____1[32U]; memcpy(uu____1, randomness, (size_t)32U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_768size_t_800size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( + return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_768size_t_800size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( uu____0, uu____1); } @@ -56,7 +56,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_generate_keypair___2size_t_768siz uint8_t randomness[64U]) { uint8_t uu____0[64U]; memcpy(uu____0, randomness, (size_t)64U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_1632size_t_800size_t_768size_t_3size_t_192size_t( + return libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_1632size_t_800size_t_768size_t_3size_t_192size_t( uu____0); } @@ -70,7 +70,7 @@ libcrux_ml_kem_mlkem512_portable_generate_key_pair(uint8_t randomness[64U]) { bool libcrux_ml_kem_ind_cca_instantiations_portable_validate_public_key___2size_t_768size_t_800size_t( uint8_t *public_key) { - return libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_800size_t( + return libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_800size_t( public_key); } @@ -93,7 +93,7 @@ libcrux_ml_kem_mlkem512_portable_validate_public_key( bool libcrux_ml_kem_ind_cca_instantiations_portable_validate_public_key___4size_t_1536size_t_1568size_t( uint8_t *public_key) { - return libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536size_t_1568size_t( + return libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1536size_t_1568size_t( public_key); } @@ -102,7 +102,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_generate_keypair___4size_t_1536si uint8_t randomness[64U]) { uint8_t uu____0[64U]; memcpy(uu____0, randomness, (size_t)64U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_3168size_t_1568size_t_1536size_t_2size_t_128size_t( + return libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_3168size_t_1568size_t_1536size_t_2size_t_128size_t( uu____0); } @@ -113,7 +113,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_encapsulate___4size_t_1568size_t_ libcrux_ml_kem_types_MlKemPublicKey____1568size_t *uu____0 = public_key; uint8_t uu____1[32U]; memcpy(uu____1, randomness, (size_t)32U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( + return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( uu____0, uu____1); } @@ -122,14 +122,14 @@ void libcrux_ml_kem_ind_cca_instantiations_portable_decapsulate___4size_t_3168si libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext, uint8_t ret[32U]) { uint8_t ret0[32U]; - libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_3168size_t_1536size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t_1600size_t( + libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_3168size_t_1536size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t_1600size_t( private_key, ciphertext, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } bool libcrux_ml_kem_ind_cca_instantiations_portable_validate_public_key___3size_t_1152size_t_1184size_t( uint8_t *public_key) { - return libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( + return libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( public_key); } @@ -138,7 +138,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_generate_keypair___3size_t_1152si uint8_t randomness[64U]) { uint8_t uu____0[64U]; memcpy(uu____0, randomness, (size_t)64U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( + return libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( uu____0); } @@ -149,7 +149,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_encapsulate___3size_t_1088size_t_ libcrux_ml_kem_types_MlKemPublicKey____1184size_t *uu____0 = public_key; uint8_t uu____1[32U]; memcpy(uu____1, randomness, (size_t)32U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( + return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____0, uu____1); } @@ -157,7 +157,7 @@ void libcrux_ml_kem_ind_cca_instantiations_portable_decapsulate___3size_t_2400si libcrux_ml_kem_types_MlKemPrivateKey____2400size_t *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { uint8_t ret0[32U]; - libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( + libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( private_key, ciphertext, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } diff --git a/libcrux-ml-kem/c/libcrux_mlkem_avx2.c b/libcrux-ml-kem/c/libcrux_mlkem_avx2.c index 46112ceb..e9536025 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem_avx2.c +++ b/libcrux-ml-kem/c/libcrux_mlkem_avx2.c @@ -618,10 +618,10 @@ libcrux_ml_kem_vector_avx2_serialize_deserialize_1(Eurydice_slice bytes) { libcrux_intrinsics_avx2_mm256_set_epi16( (int16_t)1 << 8U, (int16_t)1 << 9U, (int16_t)1 << 10U, (int16_t)1 << 11U, (int16_t)1 << 12U, (int16_t)1 << 13U, - (int16_t)1 << 14U, (int16_t)1 << 15U, (int16_t)1 << 8U, + (int16_t)1 << 14U, (int16_t)-32768, (int16_t)1 << 8U, (int16_t)1 << 9U, (int16_t)1 << 10U, (int16_t)1 << 11U, (int16_t)1 << 12U, (int16_t)1 << 13U, (int16_t)1 << 14U, - (int16_t)1 << 15U); + (int16_t)-32768); core_core_arch_x86___m256i coefficients_in_msb = libcrux_intrinsics_avx2_mm256_mullo_epi16(coefficients, shift_lsb_to_msb); return libcrux_intrinsics_avx2_mm256_srli_epi16( @@ -2744,13 +2744,11 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_avx2_SIMD256Vecto static inline void entropy_preprocess__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t( Eurydice_slice randomness, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, randomness, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + randomness, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } static inline void @@ -3611,13 +3609,11 @@ encrypt__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_ static inline void kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t_1088size_t( Eurydice_slice shared_secret, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, shared_secret, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + shared_secret, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } K___libcrux_ml_kem_types_MlKemCiphertext___1088size_t___uint8_t_32size_t_ @@ -5149,13 +5145,11 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_avx2_SIMD256Vecto static inline void entropy_preprocess__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_4size_t( Eurydice_slice randomness, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, randomness, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + randomness, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } static inline void @@ -5535,13 +5529,11 @@ encrypt__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_ static inline void kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_4size_t_1568size_t( Eurydice_slice shared_secret, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, shared_secret, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + shared_secret, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } K___libcrux_ml_kem_types_MlKemCiphertext___1568size_t___uint8_t_32size_t_ @@ -6652,13 +6644,11 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_avx2_SIMD256Vecto static inline void entropy_preprocess__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_2size_t( Eurydice_slice randomness, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, randomness, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + randomness, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } static inline void @@ -7016,13 +7006,11 @@ encrypt__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_ static inline void kdf__libcrux_ml_kem_hash_functions_avx2_Simd256Hash_2size_t_768size_t( Eurydice_slice shared_secret, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, shared_secret, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + shared_secret, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } K___libcrux_ml_kem_types_MlKemCiphertext___768size_t___uint8_t_32size_t_ diff --git a/libcrux-ml-kem/c/libcrux_mlkem_portable.c b/libcrux-ml-kem/c/libcrux_mlkem_portable.c index 015b1272..0b24895b 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem_portable.c +++ b/libcrux-ml-kem/c/libcrux_mlkem_portable.c @@ -559,9 +559,9 @@ const uint8_t {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U}}; -inline libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_zero( - void) { - libcrux_ml_kem_vector_portable_PortableVector lit; +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_vector_type_zero(void) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; lit.elements[0U] = (int16_t)0; lit.elements[1U] = (int16_t)0; lit.elements[2U] = (int16_t)0; @@ -581,15 +581,16 @@ inline libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_zero( return lit; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO( void) { - return libcrux_ml_kem_vector_zero(); + return libcrux_ml_kem_vector_portable_vector_type_zero(); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_from_i16_array(Eurydice_slice array) { - libcrux_ml_kem_vector_portable_PortableVector lit; +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_vector_type_from_i16_array( + Eurydice_slice array) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; int16_t ret[16U]; core_result_Result__int16_t_16size_t__core_array_TryFromSliceError dst; Eurydice_slice_to_array2( @@ -606,15 +607,16 @@ libcrux_ml_kem_vector_from_i16_array(Eurydice_slice array) { return lit; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___from_i16_array( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___from_i16_array( Eurydice_slice array) { - return libcrux_ml_kem_vector_from_i16_array(array); + return libcrux_ml_kem_vector_portable_vector_type_from_i16_array(array); } -inline libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_add( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -624,16 +626,17 @@ inline libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_add( return lhs; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs) { - return libcrux_ml_kem_vector_add(lhs, rhs); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { + return libcrux_ml_kem_vector_portable_arithmetic_add(lhs, rhs); } -inline libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_sub( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -643,16 +646,16 @@ inline libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_sub( return lhs; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs) { - return libcrux_ml_kem_vector_sub(lhs, rhs); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { + return libcrux_ml_kem_vector_portable_arithmetic_sub(lhs, rhs); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -662,15 +665,15 @@ libcrux_ml_kem_vector_multiply_by_constant( return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { - return libcrux_ml_kem_vector_multiply_by_constant(v, c); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { + return libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant(v, c); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_bitwise_and_with_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -680,15 +683,16 @@ libcrux_ml_kem_vector_bitwise_and_with_constant( return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___bitwise_and_with_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { - return libcrux_ml_kem_vector_bitwise_and_with_constant(v, c); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___bitwise_and_with_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { + return libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant(v, + c); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_cond_subtract_3329( - libcrux_ml_kem_vector_portable_PortableVector v) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { core_ops_range_Range__size_t iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){ @@ -711,78 +715,92 @@ libcrux_ml_kem_vector_cond_subtract_3329( } } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___cond_subtract_3329( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_cond_subtract_3329(v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___cond_subtract_3329( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329(v); } -int16_t libcrux_ml_kem_vector_barrett_reduce_element(int16_t value) { - int32_t t = (int32_t)value * LIBCRUX_ML_KEM_VECTOR_BARRETT_MULTIPLIER + - (LIBCRUX_ML_KEM_VECTOR_BARRETT_R >> 1U); +int16_t libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + int16_t value) { + int32_t t = (int32_t)value * + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_MULTIPLIER + + (LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_R >> 1U); int16_t quotient = - (int16_t)(t >> (uint32_t)LIBCRUX_ML_KEM_VECTOR_BARRETT_SHIFT); + (int16_t)(t >> + (uint32_t) + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT); return value - quotient * LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_barrett_reduce( - libcrux_ml_kem_vector_portable_PortableVector v) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int16_t uu____0 = - libcrux_ml_kem_vector_barrett_reduce_element(v.elements[i0]); + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[i0]); v.elements[i0] = uu____0; } return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_barrett_reduce(v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce(v); } -int16_t libcrux_ml_kem_vector_montgomery_reduce_element(int32_t value) { +int16_t libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + int32_t value) { int32_t k = (int32_t)(int16_t)value * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_INVERSE_OF_MODULUS_MOD_MONTGOMERY_R; int32_t k_times_modulus = (int32_t)(int16_t)k * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; - int16_t c = (int16_t)(k_times_modulus >> - (uint32_t)LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_SHIFT); + int16_t c = + (int16_t)(k_times_modulus >> + (uint32_t) + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT); int16_t value_high = - (int16_t)(value >> (uint32_t)LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_SHIFT); + (int16_t)(value >> + (uint32_t) + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT); return value_high - c; } -inline int16_t libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( +inline int16_t +libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( int16_t fe, int16_t fer) { - return libcrux_ml_kem_vector_montgomery_reduce_element((int32_t)fe * - (int32_t)fer); + return libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + (int32_t)fe * (int32_t)fer); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_montgomery_multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int16_t uu____0 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(v.elements[i0], c); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[i0], c); v.elements[i0] = uu____0; } return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t r) { - return libcrux_ml_kem_vector_montgomery_multiply_by_constant(v, r); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t r) { + return libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( + v, r); } -uint8_t libcrux_ml_kem_vector_compress_message_coefficient(uint16_t fe) { +uint8_t libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( + uint16_t fe) { int16_t shifted = (int16_t)1664 - (int16_t)fe; int16_t mask = shifted >> 15U; int16_t shifted_to_positive = mask ^ shifted; @@ -790,80 +808,91 @@ uint8_t libcrux_ml_kem_vector_compress_message_coefficient(uint16_t fe) { return (uint8_t)(shifted_positive_in_range >> 15U & (int16_t)1); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_compress_1( - libcrux_ml_kem_vector_portable_PortableVector v) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_compress_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - uint8_t uu____0 = libcrux_ml_kem_vector_compress_message_coefficient( - (uint16_t)v.elements[i0]); + uint8_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( + (uint16_t)v.elements[i0]); v.elements[i0] = (int16_t)uu____0; } return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress_1( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_compress_1(v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_compress_1(v); } -inline uint32_t libcrux_ml_kem_vector_get_n_least_significant_bits( +inline uint32_t +libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( uint8_t n, uint32_t value) { return value & ((1U << (uint32_t)n) - 1U); } -int16_t libcrux_ml_kem_vector_compress_ciphertext_coefficient( +int16_t libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( uint8_t coefficient_bits, uint16_t fe) { uint64_t compressed = (uint64_t)fe << (uint32_t)coefficient_bits; compressed = compressed + 1664ULL; compressed = compressed * 10321340ULL; compressed = compressed >> 35U; - return (int16_t)libcrux_ml_kem_vector_get_n_least_significant_bits( - coefficient_bits, (uint32_t)compressed); + return (int16_t) + libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( + coefficient_bits, (uint32_t)compressed); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { - int16_t t = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[2U], zeta0); + int16_t t = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[2U], zeta0); v.elements[2U] = v.elements[0U] - t; v.elements[0U] = v.elements[0U] + t; - int16_t t0 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[3U], zeta0); + int16_t t0 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[3U], zeta0); v.elements[3U] = v.elements[1U] - t0; v.elements[1U] = v.elements[1U] + t0; - int16_t t1 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[6U], zeta1); + int16_t t1 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[6U], zeta1); v.elements[6U] = v.elements[4U] - t1; v.elements[4U] = v.elements[4U] + t1; - int16_t t2 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[7U], zeta1); + int16_t t2 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[7U], zeta1); v.elements[7U] = v.elements[5U] - t2; v.elements[5U] = v.elements[5U] + t2; - int16_t t3 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)2U], zeta2); + int16_t t3 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)2U], zeta2); v.elements[(size_t)8U + (size_t)2U] = v.elements[(size_t)8U + (size_t)0U] - t3; v.elements[(size_t)8U + (size_t)0U] = v.elements[(size_t)8U + (size_t)0U] + t3; - int16_t t4 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)3U], zeta2); + int16_t t4 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)3U], zeta2); v.elements[(size_t)8U + (size_t)3U] = v.elements[(size_t)8U + (size_t)1U] - t4; v.elements[(size_t)8U + (size_t)1U] = v.elements[(size_t)8U + (size_t)1U] + t4; - int16_t t5 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)6U], zeta3); + int16_t t5 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)6U], zeta3); v.elements[(size_t)8U + (size_t)6U] = v.elements[(size_t)8U + (size_t)4U] - t5; v.elements[(size_t)8U + (size_t)4U] = v.elements[(size_t)8U + (size_t)4U] + t5; - int16_t t6 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)7U], zeta3); + int16_t t6 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)7U], zeta3); v.elements[(size_t)8U + (size_t)7U] = v.elements[(size_t)8U + (size_t)5U] - t6; v.elements[(size_t)8U + (size_t)5U] = @@ -871,53 +900,62 @@ libcrux_ml_kem_vector_ntt_layer_1_step( return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { - return libcrux_ml_kem_vector_ntt_layer_1_step(a, zeta0, zeta1, zeta2, zeta3); + return libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step(a, zeta0, zeta1, + zeta2, zeta3); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1) { - int16_t t = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[4U], zeta0); + int16_t t = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[4U], zeta0); v.elements[4U] = v.elements[0U] - t; v.elements[0U] = v.elements[0U] + t; - int16_t t0 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[5U], zeta0); + int16_t t0 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[5U], zeta0); v.elements[5U] = v.elements[1U] - t0; v.elements[1U] = v.elements[1U] + t0; - int16_t t1 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[6U], zeta0); + int16_t t1 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[6U], zeta0); v.elements[6U] = v.elements[2U] - t1; v.elements[2U] = v.elements[2U] + t1; - int16_t t2 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[7U], zeta0); + int16_t t2 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[7U], zeta0); v.elements[7U] = v.elements[3U] - t2; v.elements[3U] = v.elements[3U] + t2; - int16_t t3 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)4U], zeta1); + int16_t t3 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)4U], zeta1); v.elements[(size_t)8U + (size_t)4U] = v.elements[(size_t)8U + (size_t)0U] - t3; v.elements[(size_t)8U + (size_t)0U] = v.elements[(size_t)8U + (size_t)0U] + t3; - int16_t t4 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)5U], zeta1); + int16_t t4 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)5U], zeta1); v.elements[(size_t)8U + (size_t)5U] = v.elements[(size_t)8U + (size_t)1U] - t4; v.elements[(size_t)8U + (size_t)1U] = v.elements[(size_t)8U + (size_t)1U] + t4; - int16_t t5 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)6U], zeta1); + int16_t t5 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)6U], zeta1); v.elements[(size_t)8U + (size_t)6U] = v.elements[(size_t)8U + (size_t)2U] - t5; v.elements[(size_t)8U + (size_t)2U] = v.elements[(size_t)8U + (size_t)2U] + t5; - int16_t t6 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)7U], zeta1); + int16_t t6 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)7U], zeta1); v.elements[(size_t)8U + (size_t)7U] = v.elements[(size_t)8U + (size_t)3U] - t6; v.elements[(size_t)8U + (size_t)3U] = @@ -925,274 +963,320 @@ libcrux_ml_kem_vector_ntt_layer_2_step( return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1) { - return libcrux_ml_kem_vector_ntt_layer_2_step(a, zeta0, zeta1); + return libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step(a, zeta0, zeta1); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta) { int16_t t = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(v.elements[8U], zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[8U], zeta); v.elements[8U] = v.elements[0U] - t; v.elements[0U] = v.elements[0U] + t; int16_t t0 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(v.elements[9U], zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[9U], zeta); v.elements[9U] = v.elements[1U] - t0; v.elements[1U] = v.elements[1U] + t0; - int16_t t1 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[10U], zeta); + int16_t t1 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[10U], zeta); v.elements[10U] = v.elements[2U] - t1; v.elements[2U] = v.elements[2U] + t1; - int16_t t2 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[11U], zeta); + int16_t t2 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[11U], zeta); v.elements[11U] = v.elements[3U] - t2; v.elements[3U] = v.elements[3U] + t2; - int16_t t3 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[12U], zeta); + int16_t t3 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[12U], zeta); v.elements[12U] = v.elements[4U] - t3; v.elements[4U] = v.elements[4U] + t3; - int16_t t4 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[13U], zeta); + int16_t t4 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[13U], zeta); v.elements[13U] = v.elements[5U] - t4; v.elements[5U] = v.elements[5U] + t4; - int16_t t5 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[14U], zeta); + int16_t t5 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[14U], zeta); v.elements[14U] = v.elements[6U] - t5; v.elements[6U] = v.elements[6U] + t5; - int16_t t6 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[15U], zeta); + int16_t t6 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[15U], zeta); v.elements[15U] = v.elements[7U] - t6; v.elements[7U] = v.elements[7U] + t6; return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta) { - return libcrux_ml_kem_vector_ntt_layer_3_step(a, zeta); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta) { + return libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step(a, zeta); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_inv_ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { int16_t a_minus_b = v.elements[2U] - v.elements[0U]; - int16_t uu____0 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[0U] + v.elements[2U]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[0U] + v.elements[2U]); v.elements[0U] = uu____0; int16_t uu____1 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b, zeta0); v.elements[2U] = uu____1; int16_t a_minus_b0 = v.elements[3U] - v.elements[1U]; - int16_t uu____2 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[1U] + v.elements[3U]); + int16_t uu____2 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[1U] + v.elements[3U]); v.elements[1U] = uu____2; int16_t uu____3 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b0, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b0, zeta0); v.elements[3U] = uu____3; int16_t a_minus_b1 = v.elements[6U] - v.elements[4U]; - int16_t uu____4 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[4U] + v.elements[6U]); + int16_t uu____4 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[4U] + v.elements[6U]); v.elements[4U] = uu____4; int16_t uu____5 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b1, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b1, zeta1); v.elements[6U] = uu____5; int16_t a_minus_b2 = v.elements[7U] - v.elements[5U]; - int16_t uu____6 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[5U] + v.elements[7U]); + int16_t uu____6 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[5U] + v.elements[7U]); v.elements[5U] = uu____6; int16_t uu____7 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b2, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b2, zeta1); v.elements[7U] = uu____7; int16_t a_minus_b3 = v.elements[(size_t)8U + (size_t)2U] - v.elements[(size_t)8U + (size_t)0U]; - int16_t uu____8 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[(size_t)8U + (size_t)0U] + - v.elements[(size_t)8U + (size_t)2U]); + int16_t uu____8 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[(size_t)8U + (size_t)0U] + + v.elements[(size_t)8U + (size_t)2U]); v.elements[(size_t)8U + (size_t)0U] = uu____8; int16_t uu____9 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b3, zeta2); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b3, zeta2); v.elements[(size_t)8U + (size_t)2U] = uu____9; int16_t a_minus_b4 = v.elements[(size_t)8U + (size_t)3U] - v.elements[(size_t)8U + (size_t)1U]; - int16_t uu____10 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[(size_t)8U + (size_t)1U] + - v.elements[(size_t)8U + (size_t)3U]); + int16_t uu____10 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[(size_t)8U + (size_t)1U] + + v.elements[(size_t)8U + (size_t)3U]); v.elements[(size_t)8U + (size_t)1U] = uu____10; int16_t uu____11 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b4, zeta2); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b4, zeta2); v.elements[(size_t)8U + (size_t)3U] = uu____11; int16_t a_minus_b5 = v.elements[(size_t)8U + (size_t)6U] - v.elements[(size_t)8U + (size_t)4U]; - int16_t uu____12 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[(size_t)8U + (size_t)4U] + - v.elements[(size_t)8U + (size_t)6U]); + int16_t uu____12 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[(size_t)8U + (size_t)4U] + + v.elements[(size_t)8U + (size_t)6U]); v.elements[(size_t)8U + (size_t)4U] = uu____12; int16_t uu____13 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b5, zeta3); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b5, zeta3); v.elements[(size_t)8U + (size_t)6U] = uu____13; int16_t a_minus_b6 = v.elements[(size_t)8U + (size_t)7U] - v.elements[(size_t)8U + (size_t)5U]; - int16_t uu____14 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[(size_t)8U + (size_t)5U] + - v.elements[(size_t)8U + (size_t)7U]); + int16_t uu____14 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[(size_t)8U + (size_t)5U] + + v.elements[(size_t)8U + (size_t)7U]); v.elements[(size_t)8U + (size_t)5U] = uu____14; int16_t uu____15 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b6, zeta3); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b6, zeta3); v.elements[(size_t)8U + (size_t)7U] = uu____15; return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { - return libcrux_ml_kem_vector_inv_ntt_layer_1_step(a, zeta0, zeta1, zeta2, - zeta3); + return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( + a, zeta0, zeta1, zeta2, zeta3); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_inv_ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1) { int16_t a_minus_b = v.elements[4U] - v.elements[0U]; v.elements[0U] = v.elements[0U] + v.elements[4U]; int16_t uu____0 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b, zeta0); v.elements[4U] = uu____0; int16_t a_minus_b0 = v.elements[5U] - v.elements[1U]; v.elements[1U] = v.elements[1U] + v.elements[5U]; int16_t uu____1 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b0, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b0, zeta0); v.elements[5U] = uu____1; int16_t a_minus_b1 = v.elements[6U] - v.elements[2U]; v.elements[2U] = v.elements[2U] + v.elements[6U]; int16_t uu____2 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b1, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b1, zeta0); v.elements[6U] = uu____2; int16_t a_minus_b2 = v.elements[7U] - v.elements[3U]; v.elements[3U] = v.elements[3U] + v.elements[7U]; int16_t uu____3 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b2, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b2, zeta0); v.elements[7U] = uu____3; int16_t a_minus_b3 = v.elements[(size_t)8U + (size_t)4U] - v.elements[(size_t)8U + (size_t)0U]; v.elements[(size_t)8U + (size_t)0U] = v.elements[(size_t)8U + (size_t)0U] + v.elements[(size_t)8U + (size_t)4U]; int16_t uu____4 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b3, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b3, zeta1); v.elements[(size_t)8U + (size_t)4U] = uu____4; int16_t a_minus_b4 = v.elements[(size_t)8U + (size_t)5U] - v.elements[(size_t)8U + (size_t)1U]; v.elements[(size_t)8U + (size_t)1U] = v.elements[(size_t)8U + (size_t)1U] + v.elements[(size_t)8U + (size_t)5U]; int16_t uu____5 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b4, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b4, zeta1); v.elements[(size_t)8U + (size_t)5U] = uu____5; int16_t a_minus_b5 = v.elements[(size_t)8U + (size_t)6U] - v.elements[(size_t)8U + (size_t)2U]; v.elements[(size_t)8U + (size_t)2U] = v.elements[(size_t)8U + (size_t)2U] + v.elements[(size_t)8U + (size_t)6U]; int16_t uu____6 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b5, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b5, zeta1); v.elements[(size_t)8U + (size_t)6U] = uu____6; int16_t a_minus_b6 = v.elements[(size_t)8U + (size_t)7U] - v.elements[(size_t)8U + (size_t)3U]; v.elements[(size_t)8U + (size_t)3U] = v.elements[(size_t)8U + (size_t)3U] + v.elements[(size_t)8U + (size_t)7U]; int16_t uu____7 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b6, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b6, zeta1); v.elements[(size_t)8U + (size_t)7U] = uu____7; return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1) { - return libcrux_ml_kem_vector_inv_ntt_layer_2_step(a, zeta0, zeta1); + return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step(a, zeta0, + zeta1); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_inv_ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta) { int16_t a_minus_b = v.elements[8U] - v.elements[0U]; v.elements[0U] = v.elements[0U] + v.elements[8U]; int16_t uu____0 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b, zeta); v.elements[8U] = uu____0; int16_t a_minus_b0 = v.elements[9U] - v.elements[1U]; v.elements[1U] = v.elements[1U] + v.elements[9U]; int16_t uu____1 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b0, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b0, zeta); v.elements[9U] = uu____1; int16_t a_minus_b1 = v.elements[10U] - v.elements[2U]; v.elements[2U] = v.elements[2U] + v.elements[10U]; int16_t uu____2 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b1, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b1, zeta); v.elements[10U] = uu____2; int16_t a_minus_b2 = v.elements[11U] - v.elements[3U]; v.elements[3U] = v.elements[3U] + v.elements[11U]; int16_t uu____3 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b2, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b2, zeta); v.elements[11U] = uu____3; int16_t a_minus_b3 = v.elements[12U] - v.elements[4U]; v.elements[4U] = v.elements[4U] + v.elements[12U]; int16_t uu____4 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b3, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b3, zeta); v.elements[12U] = uu____4; int16_t a_minus_b4 = v.elements[13U] - v.elements[5U]; v.elements[5U] = v.elements[5U] + v.elements[13U]; int16_t uu____5 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b4, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b4, zeta); v.elements[13U] = uu____5; int16_t a_minus_b5 = v.elements[14U] - v.elements[6U]; v.elements[6U] = v.elements[6U] + v.elements[14U]; int16_t uu____6 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b5, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b5, zeta); v.elements[14U] = uu____6; int16_t a_minus_b6 = v.elements[15U] - v.elements[7U]; v.elements[7U] = v.elements[7U] + v.elements[15U]; int16_t uu____7 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b6, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b6, zeta); v.elements[15U] = uu____7; return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta) { - return libcrux_ml_kem_vector_inv_ntt_layer_3_step(a, zeta); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta) { + return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step(a, zeta); } -inline K___int16_t_int16_t libcrux_ml_kem_vector_ntt_multiply_binomials( +inline K___int16_t_int16_t +libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( K___int16_t_int16_t _, K___int16_t_int16_t _0, int16_t zeta) { int16_t a0 = _.fst; int16_t a1 = _.snd; int16_t b0 = _0.fst; int16_t b1 = _0.snd; int32_t uu____0 = (int32_t)a0 * (int32_t)b0; - int16_t uu____1 = libcrux_ml_kem_vector_montgomery_reduce_element( - uu____0 + (int32_t)libcrux_ml_kem_vector_montgomery_reduce_element( - (int32_t)a1 * (int32_t)b1) * - (int32_t)zeta); + int16_t uu____1 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + uu____0 + + (int32_t) + libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + (int32_t)a1 * (int32_t)b1) * + (int32_t)zeta); return (CLITERAL(K___int16_t_int16_t){ .fst = uu____1, - .snd = libcrux_ml_kem_vector_montgomery_reduce_element( - (int32_t)a0 * (int32_t)b1 + (int32_t)a1 * (int32_t)b0)}); -} - -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_multiply( - libcrux_ml_kem_vector_portable_PortableVector *lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs, int16_t zeta0, - int16_t zeta1, int16_t zeta2, int16_t zeta3) { - libcrux_ml_kem_vector_portable_PortableVector out = - libcrux_ml_kem_vector_zero(); + .snd = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + (int32_t)a0 * (int32_t)b1 + (int32_t)a1 * (int32_t)b0)}); +} + +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_multiply( + libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, + int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector out = + libcrux_ml_kem_vector_portable_vector_type_zero(); K___int16_t_int16_t lit0; lit0.fst = lhs->elements[0U]; lit0.snd = lhs->elements[1U]; @@ -1200,7 +1284,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit1.fst = rhs->elements[0U]; lit1.snd = rhs->elements[1U]; K___int16_t_int16_t product = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit0, lit1, zeta0); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit0, lit1, + zeta0); out.elements[0U] = product.fst; out.elements[1U] = product.snd; K___int16_t_int16_t lit2; @@ -1210,7 +1295,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit3.fst = rhs->elements[2U]; lit3.snd = rhs->elements[3U]; K___int16_t_int16_t product0 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit2, lit3, -zeta0); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit2, lit3, + -zeta0); out.elements[2U] = product0.fst; out.elements[3U] = product0.snd; K___int16_t_int16_t lit4; @@ -1220,7 +1306,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit5.fst = rhs->elements[4U]; lit5.snd = rhs->elements[5U]; K___int16_t_int16_t product1 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit4, lit5, zeta1); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit4, lit5, + zeta1); out.elements[4U] = product1.fst; out.elements[5U] = product1.snd; K___int16_t_int16_t lit6; @@ -1230,7 +1317,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit7.fst = rhs->elements[6U]; lit7.snd = rhs->elements[7U]; K___int16_t_int16_t product2 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit6, lit7, -zeta1); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit6, lit7, + -zeta1); out.elements[6U] = product2.fst; out.elements[7U] = product2.snd; K___int16_t_int16_t lit8; @@ -1240,7 +1328,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit9.fst = rhs->elements[(size_t)8U + (size_t)0U]; lit9.snd = rhs->elements[(size_t)8U + (size_t)1U]; K___int16_t_int16_t product3 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit8, lit9, zeta2); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit8, lit9, + zeta2); out.elements[(size_t)8U + (size_t)0U] = product3.fst; out.elements[(size_t)8U + (size_t)1U] = product3.snd; K___int16_t_int16_t lit10; @@ -1250,7 +1339,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit11.fst = rhs->elements[(size_t)8U + (size_t)2U]; lit11.snd = rhs->elements[(size_t)8U + (size_t)3U]; K___int16_t_int16_t product4 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit10, lit11, -zeta2); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit10, lit11, + -zeta2); out.elements[(size_t)8U + (size_t)2U] = product4.fst; out.elements[(size_t)8U + (size_t)3U] = product4.snd; K___int16_t_int16_t lit12; @@ -1260,7 +1350,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit13.fst = rhs->elements[(size_t)8U + (size_t)4U]; lit13.snd = rhs->elements[(size_t)8U + (size_t)5U]; K___int16_t_int16_t product5 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit12, lit13, zeta3); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit12, lit13, + zeta3); out.elements[(size_t)8U + (size_t)4U] = product5.fst; out.elements[(size_t)8U + (size_t)5U] = product5.snd; K___int16_t_int16_t lit14; @@ -1270,23 +1361,25 @@ libcrux_ml_kem_vector_ntt_multiply( lit.fst = rhs->elements[(size_t)8U + (size_t)6U]; lit.snd = rhs->elements[(size_t)8U + (size_t)7U]; K___int16_t_int16_t product6 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit14, lit, -zeta3); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit14, lit, + -zeta3); out.elements[(size_t)8U + (size_t)6U] = product6.fst; out.elements[(size_t)8U + (size_t)7U] = product6.snd; return out; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_multiply( - libcrux_ml_kem_vector_portable_PortableVector *lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs, int16_t zeta0, - int16_t zeta1, int16_t zeta2, int16_t zeta3) { - return libcrux_ml_kem_vector_ntt_multiply(lhs, rhs, zeta0, zeta1, zeta2, - zeta3); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_multiply( + libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, + int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { + return libcrux_ml_kem_vector_portable_ntt_ntt_multiply(lhs, rhs, zeta0, zeta1, + zeta2, zeta3); } -inline void libcrux_ml_kem_vector_serialize_1( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[2U]) { +inline void libcrux_ml_kem_vector_portable_serialize_serialize_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[2U]) { uint8_t result[2U] = {0U}; KRML_MAYBE_FOR8( i, (size_t)0U, (size_t)8U, (size_t)1U, size_t i0 = i; @@ -1301,17 +1394,18 @@ inline void libcrux_ml_kem_vector_serialize_1( memcpy(ret, result, (size_t)2U * sizeof(uint8_t)); } -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_1( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[2U]) { +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[2U]) { uint8_t ret0[2U]; - libcrux_ml_kem_vector_serialize_1(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_1(a, ret0); memcpy(ret, ret0, (size_t)2U * sizeof(uint8_t)); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_1(Eurydice_slice v) { - libcrux_ml_kem_vector_portable_PortableVector result = - libcrux_ml_kem_vector_zero(); +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_1(Eurydice_slice v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector result = + libcrux_ml_kem_vector_portable_vector_type_zero(); KRML_MAYBE_FOR8(i, (size_t)0U, (size_t)8U, (size_t)1U, size_t i0 = i; uint8_t *uu____0 = &Eurydice_slice_index( v, (size_t)0U, uint8_t, uint8_t *, uint8_t); @@ -1328,14 +1422,15 @@ libcrux_ml_kem_vector_deserialize_1(Eurydice_slice v) { return result; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_1( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_1( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_1(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_1(a); } -inline void libcrux_ml_kem_vector_serialize_4( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[8U]) { +inline void libcrux_ml_kem_vector_portable_serialize_serialize_4( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[8U]) { uint8_t result[8U] = {0U}; result[0U] = (uint32_t)(uint8_t)v.elements[1U] << 4U | (uint32_t)(uint8_t)v.elements[0U]; @@ -1356,17 +1451,18 @@ inline void libcrux_ml_kem_vector_serialize_4( memcpy(ret, result, (size_t)8U * sizeof(uint8_t)); } -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_4( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[8U]) { +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_4( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[8U]) { uint8_t ret0[8U]; - libcrux_ml_kem_vector_serialize_4(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_4(a, ret0); memcpy(ret, ret0, (size_t)8U * sizeof(uint8_t)); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_4(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector v = - libcrux_ml_kem_vector_zero(); +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_4(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v = + libcrux_ml_kem_vector_portable_vector_type_zero(); uint8_t *uu____0 = &Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *, uint8_t); v.elements[0U] = (int16_t)((uint32_t)uu____0[0U] & 15U); @@ -1418,14 +1514,15 @@ libcrux_ml_kem_vector_deserialize_4(Eurydice_slice bytes) { return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_4( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_4( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_4(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_4(a); } -inline void libcrux_ml_kem_vector_serialize_5( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[10U]) { +inline void libcrux_ml_kem_vector_portable_serialize_serialize_5( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[10U]) { uint8_t result[10U] = {0U}; result[0U] = (uint8_t)((v.elements[1U] & (int16_t)7) << 5U | v.elements[0U]); result[1U] = @@ -1456,17 +1553,18 @@ inline void libcrux_ml_kem_vector_serialize_5( memcpy(ret, result, (size_t)10U * sizeof(uint8_t)); } -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_5( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[10U]) { +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_5( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[10U]) { uint8_t ret0[10U]; - libcrux_ml_kem_vector_serialize_5(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_5(a, ret0); memcpy(ret, ret0, (size_t)10U * sizeof(uint8_t)); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_5(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector v = - libcrux_ml_kem_vector_zero(); +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_5(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v = + libcrux_ml_kem_vector_portable_vector_type_zero(); uint8_t *uu____0 = &Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *, uint8_t); v.elements[0U] = (int16_t)((uint32_t)uu____0[0U] & 31U); @@ -1557,14 +1655,15 @@ libcrux_ml_kem_vector_deserialize_5(Eurydice_slice bytes) { return v; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_5( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_5( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_5(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_5(a); } -inline void libcrux_ml_kem_vector_serialize_10( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[20U]) { +inline void libcrux_ml_kem_vector_portable_serialize_serialize_10( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[20U]) { uint8_t result[20U] = {0U}; result[0U] = (uint8_t)(v.elements[0U] & (int16_t)255); result[1U] = (uint32_t)(uint8_t)(v.elements[1U] & (int16_t)63) << 2U | @@ -1621,17 +1720,18 @@ inline void libcrux_ml_kem_vector_serialize_10( memcpy(ret, result, (size_t)20U * sizeof(uint8_t)); } -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_10( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[20U]) { +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_10( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[20U]) { uint8_t ret0[20U]; - libcrux_ml_kem_vector_serialize_10(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_10(a, ret0); memcpy(ret, ret0, (size_t)20U * sizeof(uint8_t)); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_10(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector result = - libcrux_ml_kem_vector_zero(); +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_10(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector result = + libcrux_ml_kem_vector_portable_vector_type_zero(); int16_t uu____0 = ((int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *, uint8_t) & (int16_t)3) @@ -1751,14 +1851,15 @@ libcrux_ml_kem_vector_deserialize_10(Eurydice_slice bytes) { return result; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_10( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_10( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_10(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_10(a); } -inline void libcrux_ml_kem_vector_serialize_11( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[22U]) { +inline void libcrux_ml_kem_vector_portable_serialize_serialize_11( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[22U]) { uint8_t result[22U] = {0U}; result[0U] = (uint8_t)v.elements[0U]; result[1U] = (uint32_t)(uint8_t)(v.elements[1U] & (int16_t)31) << 3U | @@ -1815,17 +1916,18 @@ inline void libcrux_ml_kem_vector_serialize_11( memcpy(ret, result, (size_t)22U * sizeof(uint8_t)); } -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_11( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[22U]) { +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_11( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[22U]) { uint8_t ret0[22U]; - libcrux_ml_kem_vector_serialize_11(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_11(a, ret0); memcpy(ret, ret0, (size_t)22U * sizeof(uint8_t)); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_11(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector result = - libcrux_ml_kem_vector_zero(); +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_11(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector result = + libcrux_ml_kem_vector_portable_vector_type_zero(); int16_t uu____0 = ((int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *, uint8_t) & (int16_t)7) @@ -1963,14 +2065,15 @@ libcrux_ml_kem_vector_deserialize_11(Eurydice_slice bytes) { return result; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_11( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_11( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_11(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_11(a); } -inline void libcrux_ml_kem_vector_serialize_12( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[24U]) { +inline void libcrux_ml_kem_vector_portable_serialize_serialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[24U]) { uint8_t result[24U] = {0U}; result[0U] = (uint8_t)(v.elements[0U] & (int16_t)255); result[1U] = @@ -2015,17 +2118,18 @@ inline void libcrux_ml_kem_vector_serialize_12( memcpy(ret, result, (size_t)24U * sizeof(uint8_t)); } -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_12( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[24U]) { +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[24U]) { uint8_t ret0[24U]; - libcrux_ml_kem_vector_serialize_12(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_12(a, ret0); memcpy(ret, ret0, (size_t)24U * sizeof(uint8_t)); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_12(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector re = - libcrux_ml_kem_vector_zero(); +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_12(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector re = + libcrux_ml_kem_vector_portable_vector_type_zero(); int16_t byte0 = (int16_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *, uint8_t); int16_t byte1 = (int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, @@ -2093,14 +2197,14 @@ libcrux_ml_kem_vector_deserialize_12(Eurydice_slice bytes) { return re; } -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_12( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_12( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_12(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_12(a); } -inline size_t libcrux_ml_kem_vector_rej_sample(Eurydice_slice a, - Eurydice_slice result) { +inline size_t libcrux_ml_kem_vector_portable_sampling_rej_sample( + Eurydice_slice a, Eurydice_slice result) { size_t sampled = (size_t)0U; for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(a, uint8_t, size_t) / (size_t)3U; i++) { @@ -2164,61 +2268,61 @@ inline size_t libcrux_ml_kem_vector_rej_sample(Eurydice_slice a, } size_t -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( Eurydice_slice a, Eurydice_slice out) { - return libcrux_ml_kem_vector_rej_sample(a, out); + return libcrux_ml_kem_vector_portable_sampling_rej_sample(a, out); } -inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_portable___core__clone__Clone_for_libcrux_ml_kem__vector__portable__PortableVector___clone( - libcrux_ml_kem_vector_portable_PortableVector *self) { +inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_vector_type___core__clone__Clone_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___clone( + libcrux_ml_kem_vector_portable_vector_type_PortableVector *self) { return self[0U]; } -static libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -ZERO__libcrux_ml_kem_vector_portable_PortableVector(void) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(void) { + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; lit.coefficients[0U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[1U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[2U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[3U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[4U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[5U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[6U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[7U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[8U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[9U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[10U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[11U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[12U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[13U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[14U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[15U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); return lit; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - re = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + re = ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)24U; @@ -2229,11 +2333,11 @@ deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVect (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)24U, .end = i0 * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_12( bytes); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___cond_subtract_3329( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___cond_subtract_3329( coefficient); re.coefficients[i0] = uu____0; } @@ -2241,15 +2345,16 @@ deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVect } static inline void -deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1568size_t_4size_t( +deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1568size_t_4size_t( Eurydice_slice public_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[4U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[4U]; - KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, - deserialized_pk[i] = - ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + KRML_MAYBE_FOR4( + i, (size_t)0U, (size_t)4U, (size_t)1U, + deserialized_pk[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -2262,9 +2367,9 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( ring_element); deserialized_pk[i0] = uu____0; } @@ -2272,11 +2377,12 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector ret, deserialized_pk, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -shift_right___15int32_t(libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +shift_right___15int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -2285,36 +2391,38 @@ shift_right___15int32_t(libcrux_ml_kem_vector_portable_PortableVector v) { return v; } -static libcrux_ml_kem_vector_portable_PortableVector shift_right___15int32_t0( - libcrux_ml_kem_vector_portable_PortableVector v) { +static libcrux_ml_kem_vector_portable_vector_type_PortableVector +shift_right___15int32_t0( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return shift_right___15int32_t(v); } -static libcrux_ml_kem_vector_portable_PortableVector -to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector a) { - libcrux_ml_kem_vector_portable_PortableVector t = shift_right___15int32_t0(a); - libcrux_ml_kem_vector_portable_PortableVector fm = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___bitwise_and_with_constant( +static libcrux_ml_kem_vector_portable_vector_type_PortableVector +to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector t = + shift_right___15int32_t0(a); + libcrux_ml_kem_vector_portable_vector_type_PortableVector fm = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___bitwise_and_with_constant( t, LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS); - return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + return libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( a, &fm); } static inline void -serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, uint8_t ret[384U]) { uint8_t serialized[384U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = - to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[i0]); uint8_t bytes[24U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_12( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_12( coefficient, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)384U, serialized, @@ -2330,8 +2438,8 @@ serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVect } static inline void -serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1536size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector key[4U], uint8_t ret[1536U]) { uint8_t out[1536U] = {0U}; @@ -2341,13 +2449,13 @@ serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536 core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)4U, key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = key[i0]; Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)1536U, out, @@ -2357,7 +2465,7 @@ serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536 LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); uint8_t ret0[384U]; - serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &re, ret0); core_slice___Slice_T___copy_from_slice( uu____0, @@ -2368,8 +2476,8 @@ serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536 } static inline void -serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536size_t_1568size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1536size_t_1568size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[4U], Eurydice_slice seed_for_a, uint8_t ret[1568U]) { uint8_t public_key_serialized[1568U] = {0U}; @@ -2378,15 +2486,15 @@ serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536 (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = (size_t)1536U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1[4U]; memcpy( uu____1, t_as_ntt, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t ret0[1536U]; - serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536size_t( + serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1536size_t( uu____1, ret0); core_slice___Slice_T___copy_from_slice( uu____0, @@ -2400,23 +2508,23 @@ serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536 memcpy(ret, public_key_serialized, (size_t)1568U * sizeof(uint8_t)); } -bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536size_t_1568size_t( +bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1536size_t_1568size_t( uint8_t *public_key) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[4U]; - deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1568size_t_4size_t( + deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1568size_t_4size_t( Eurydice_array_to_subslice_to((size_t)1568U, public_key, (size_t)1536U, uint8_t, size_t, Eurydice_slice), deserialized_pk); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0[4U]; memcpy( uu____0, deserialized_pk, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t public_key_serialized[1568U]; - serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536size_t_1568size_t( + serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1536size_t_1568size_t( uu____0, Eurydice_array_to_subslice_from((size_t)1568U, public_key, (size_t)1536U, uint8_t, size_t, Eurydice_slice), @@ -2434,19 +2542,20 @@ static inline void G___4size_t(Eurydice_slice input, uint8_t ret[64U]) { } static void -closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[4U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret0[4U]; KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, - ret0[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + ret0[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); memcpy( ret, ret0, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } typedef struct PortableHash____4size_t_s { @@ -2490,7 +2599,7 @@ static inline void shake128_squeeze_three_blocks___4size_t( } static inline bool -sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_4size_t_504size_t( +sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_504size_t( uint8_t randomness[4U][504U], size_t *sampled_coefficients, int16_t (*out)[272U]) { KRML_MAYBE_FOR4( @@ -2506,7 +2615,7 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe .end = r * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); size_t sampled = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( uu____0, Eurydice_array_to_subslice( (size_t)272U, out[i1], @@ -2542,7 +2651,7 @@ static inline void shake128_squeeze_block___4size_t( } static inline bool -sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_4size_t_168size_t( +sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_168size_t( uint8_t randomness[4U][168U], size_t *sampled_coefficients, int16_t (*out)[272U]) { KRML_MAYBE_FOR4( @@ -2558,7 +2667,7 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe .end = r * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); size_t sampled = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( uu____0, Eurydice_array_to_subslice( (size_t)272U, out[i1], @@ -2582,16 +2691,17 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe return done; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice a) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - result = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + result = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___from_i16_array( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___from_i16_array( Eurydice_slice_subslice( a, (CLITERAL(core_ops_range_Range__size_t){ @@ -2603,10 +2713,10 @@ from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( return result; } -static libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t0( +static libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t0( int16_t s[272U]) { - return from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( + return from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_array_to_subslice((size_t)272U, s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)256U}), @@ -2615,9 +2725,9 @@ closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_funct } static inline void -sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( +sample_from_xof__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( uint8_t seeds[4U][34U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[4U]) { size_t sampled_coefficients[4U] = {0U}; int16_t out[4U][272U] = {{0U}}; @@ -2629,7 +2739,7 @@ sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha uint8_t uu____1[4U][504U]; memcpy(uu____1, randomness0, (size_t)4U * sizeof(uint8_t[504U])); bool done = - sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_4size_t_504size_t( + sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_504size_t( uu____1, sampled_coefficients, out); while (true) { if (done) { @@ -2640,36 +2750,36 @@ sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha uint8_t uu____2[4U][168U]; memcpy(uu____2, randomness, (size_t)4U * sizeof(uint8_t[168U])); done = - sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_4size_t_168size_t( + sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_168size_t( uu____2, sampled_coefficients, out); } } int16_t uu____3[4U][272U]; memcpy(uu____3, out, (size_t)4U * sizeof(int16_t[272U])); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret0[4U]; KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, ret0[i] = - closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t0( + closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t0( uu____3[i]);); memcpy( ret, ret0, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline void -sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( +sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( uint8_t seed[34U], bool transpose, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[4U][4U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[4U][4U]; KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, - closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( + closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( A_transpose[i]);); KRML_MAYBE_FOR4( i0, (size_t)0U, (size_t)4U, (size_t)1U, size_t i1 = i0; @@ -2682,9 +2792,9 @@ sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha seeds[j][32U] = (uint8_t)i1; seeds[j][33U] = (uint8_t)j;); uint8_t uu____1[4U][34U]; memcpy(uu____1, seeds, (size_t)4U * sizeof(uint8_t[34U])); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector sampled[4U]; - sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( + sample_from_xof__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( uu____1, sampled); for ( size_t i = (size_t)0U; @@ -2692,13 +2802,13 @@ sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)4U, sampled, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector sample = sampled[j]; if (transpose) { A_transpose[j][i1] = sample; @@ -2710,16 +2820,16 @@ sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha ret, A_transpose, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [4U])); } typedef struct - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_4size_t__uint8_t_s { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t__uint8_t_s { + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector fst[4U]; uint8_t snd; -} __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_4size_t__uint8_t; +} __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t__uint8_t; static inline void PRFxN___4size_t_128size_t(uint8_t (*input)[33U], uint8_t ret[4U][128U]) { @@ -2733,8 +2843,8 @@ static inline void PRFxN___4size_t_128size_t(uint8_t (*input)[33U], memcpy(ret, out, (size_t)4U * sizeof(uint8_t[128U])); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -sample_from_binomial_distribution_2__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +sample_from_binomial_distribution_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice randomness) { int16_t sampled_i16s[256U] = {0U}; for (size_t i0 = (size_t)0U; @@ -2776,13 +2886,13 @@ sample_from_binomial_distribution_2__libcrux_ml_kem_vector_portable_PortableVect sampled_i16s[(size_t)8U * chunk_number + offset] = outcome_1 - outcome_2; } } - return from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( + return from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_array_to_slice((size_t)256U, sampled_i16s, int16_t, Eurydice_slice)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -sample_from_binomial_distribution_3__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +sample_from_binomial_distribution_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice randomness) { int16_t sampled_i16s[256U] = {0U}; for (size_t i0 = (size_t)0U; @@ -2822,76 +2932,77 @@ sample_from_binomial_distribution_3__libcrux_ml_kem_vector_portable_PortableVect sampled_i16s[(size_t)4U * chunk_number + offset] = outcome_1 - outcome_2; } } - return from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( + return from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_array_to_slice((size_t)256U, sampled_i16s, int16_t, Eurydice_slice)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_slice randomness) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0; uu____0 = - sample_from_binomial_distribution_2__libcrux_ml_kem_vector_portable_PortableVector( + sample_from_binomial_distribution_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( randomness); return uu____0; } static inline void -ntt_at_layer_7__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +ntt_at_layer_7__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { size_t step = LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT / (size_t)2U; for (size_t i = (size_t)0U; i < step; i++) { size_t j = i; - libcrux_ml_kem_vector_portable_PortableVector t = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector t = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___multiply_by_constant( re->coefficients[j + step], (int16_t)-1600); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( re->coefficients[j], &t); re->coefficients[j + step] = uu____0; - libcrux_ml_kem_vector_portable_PortableVector uu____1 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( re->coefficients[j], &t); re->coefficients[j] = uu____1; } } typedef struct - __libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector_s { - libcrux_ml_kem_vector_portable_PortableVector fst; - libcrux_ml_kem_vector_portable_PortableVector snd; -} __libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector; - -static libcrux_ml_kem_vector_portable_PortableVector -montgomery_multiply_fe__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t fer) { - return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( + __libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector_s { + libcrux_ml_kem_vector_portable_vector_type_PortableVector fst; + libcrux_ml_kem_vector_portable_vector_type_PortableVector snd; +} __libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector; + +static libcrux_ml_kem_vector_portable_vector_type_PortableVector +montgomery_multiply_fe__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t fer) { + return libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( v, fer); } -static inline __libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector -ntt_layer_int_vec_step__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector a, - libcrux_ml_kem_vector_portable_PortableVector b, int16_t zeta_r) { - libcrux_ml_kem_vector_portable_PortableVector t = - montgomery_multiply_fe__libcrux_ml_kem_vector_portable_PortableVector( +static inline __libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector +ntt_layer_int_vec_step__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + libcrux_ml_kem_vector_portable_vector_type_PortableVector b, + int16_t zeta_r) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector t = + montgomery_multiply_fe__libcrux_ml_kem_vector_portable_vector_type_PortableVector( b, zeta_r); - b = libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( + b = libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( a, &t); - a = libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + a = libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( a, &t); return (CLITERAL( - __libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector){ + __libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector){ .fst = a, .snd = b}); } static inline void -ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( +ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t layer) { size_t step = (size_t)1U << (uint32_t)layer; @@ -2903,14 +3014,14 @@ ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( size_t step_vec = step / (size_t)16U; for (size_t i = offset_vec; i < offset_vec + step_vec; i++) { size_t j = i; - __libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector + __libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - ntt_layer_int_vec_step__libcrux_ml_kem_vector_portable_PortableVector( + ntt_layer_int_vec_step__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[j], re->coefficients[j + step_vec], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R [zeta_i[0U]]); - libcrux_ml_kem_vector_portable_PortableVector x = uu____0.fst; - libcrux_ml_kem_vector_portable_PortableVector y = uu____0.snd; + libcrux_ml_kem_vector_portable_vector_type_PortableVector x = uu____0.fst; + libcrux_ml_kem_vector_portable_vector_type_PortableVector y = uu____0.snd; re->coefficients[j] = x; re->coefficients[j + step_vec] = y; } @@ -2918,30 +3029,30 @@ ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( } static inline void -ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector( +ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { KRML_MAYBE_FOR16( i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; zeta_i[0U] = zeta_i[0U] + (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_3_step( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); re->coefficients[round] = uu____0;); } static inline void -ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector( +ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { KRML_MAYBE_FOR16( i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; zeta_i[0U] = zeta_i[0U] + (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_2_step( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + @@ -2950,15 +3061,15 @@ ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector( } static inline void -ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector( +ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { KRML_MAYBE_FOR16( i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; zeta_i[0U] = zeta_i[0U] + (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_1_step( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + @@ -2971,45 +3082,50 @@ ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector( } static inline void -poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( self->coefficients[i0]); self->coefficients[i0] = uu____0; } } static inline void -ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { - ntt_at_layer_7__libcrux_ml_kem_vector_portable_PortableVector(re); + ntt_at_layer_7__libcrux_ml_kem_vector_portable_vector_type_PortableVector(re); size_t zeta_i = (size_t)1U; - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)6U); - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)5U); - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)4U); - ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, re); - ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, re); - ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, re); - poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector(re); -} - -static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_4size_t__uint8_t -sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_2size_t_128size_t( + ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + re); +} + +static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t__uint8_t +sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_2size_t_128size_t( uint8_t prf_input[33U], uint8_t domain_separator) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re_as_ntt[4U]; KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, - re_as_ntt[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + re_as_ntt[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[4U][33U]; @@ -3023,45 +3139,45 @@ sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcru PRFxN___4size_t_128size_t(prf_inputs, prf_outputs); KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = - sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t, Eurydice_slice)); re_as_ntt[i0] = uu____1; - ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &re_as_ntt[i0]);); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____2[4U]; memcpy( uu____2, re_as_ntt, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_4size_t__uint8_t + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t__uint8_t lit; memcpy( lit.fst, uu____2, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); lit.snd = domain_separator; return lit; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - out = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + out = ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_multiply( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_multiply( &self->coefficients[i0], &rhs->coefficients[i0], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + (size_t)4U * i0], @@ -3080,84 +3196,87 @@ ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( } static inline void -add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_4size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; - i < - core_slice___Slice_T___len( - Eurydice_array_to_slice( - (size_t)16U, self->coefficients, - libcrux_ml_kem_vector_portable_PortableVector, Eurydice_slice), - libcrux_ml_kem_vector_portable_PortableVector, size_t); + i < core_slice___Slice_T___len( + Eurydice_array_to_slice( + (size_t)16U, self->coefficients, + libcrux_ml_kem_vector_portable_vector_type_PortableVector, + Eurydice_slice), + libcrux_ml_kem_vector_portable_vector_type_PortableVector, + size_t); i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( self->coefficients[i0], &rhs->coefficients[i0]); self->coefficients[i0] = uu____0; } } -static libcrux_ml_kem_vector_portable_PortableVector -to_standard_domain__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( +static libcrux_ml_kem_vector_portable_vector_type_PortableVector +to_standard_domain__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( v, LIBCRUX_ML_KEM_VECTOR_TRAITS_MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS); } static inline void -add_standard_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +add_standard_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t j = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_normal_form = - to_standard_domain__libcrux_ml_kem_vector_portable_PortableVector( - self->coefficients[j]); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_normal_form = + to_standard_domain__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + self->coefficients[j]); + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( coefficient_normal_form, &error->coefficients[j])); self->coefficients[j] = uu____0; } } static inline void -compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_4size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector ( +compute_As_plus_e__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ( *matrix_A)[4U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *s_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[4U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result[4U]; KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, - result[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + result[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for ( size_t i0 = (size_t)0U; i0 < core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)4U, matrix_A, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [4U], Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [4U], size_t); i0++) { size_t i1 = i0; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *row = matrix_A[i1]; for ( size_t i = (size_t)0U; @@ -3165,32 +3284,33 @@ compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_4size_t( core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)4U, row, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *matrix_element = &row[j]; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - matrix_element, &s_as_ntt[j]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + matrix_element, &s_as_ntt[j]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( &result[i1], &product); } - add_standard_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + add_standard_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &result[i1], &error_as_ntt[i1]); } memcpy( ret, result, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static libcrux_ml_kem_utils_extraction_helper_Keypair1024 -generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_1568size_t_1536size_t_2size_t_128size_t( +generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_1568size_t_1536size_t_2size_t_128size_t( Eurydice_slice key_generation_seed) { uint8_t hashed[64U]; G___4size_t(key_generation_seed, hashed); @@ -3201,64 +3321,64 @@ generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_h K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t); Eurydice_slice seed_for_A = uu____0.fst; Eurydice_slice seed_for_secret_and_error = uu____0.snd; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[4U][4U]; uint8_t ret[34U]; libcrux_ml_kem_utils_into_padded_array___34size_t(seed_for_A, ret); - sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( + sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( ret, true, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array___33size_t(seed_for_secret_and_error, prf_input); uint8_t uu____1[33U]; memcpy(uu____1, prf_input, (size_t)33U * sizeof(uint8_t)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_4size_t__uint8_t + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t__uint8_t uu____2 = - sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_2size_t_128size_t( + sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_2size_t_128size_t( uu____1, 0U); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[4U]; memcpy( secret_as_ntt, uu____2.fst, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator = uu____2.snd; uint8_t uu____3[33U]; memcpy(uu____3, prf_input, (size_t)33U * sizeof(uint8_t)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_as_ntt[4U]; memcpy( error_as_ntt, - sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_2size_t_128size_t( + sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_2size_t_128size_t( uu____3, domain_separator) .fst, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[4U]; - compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + compute_As_plus_e__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( A_transpose, secret_as_ntt, error_as_ntt, t_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____4[4U]; memcpy( uu____4, t_as_ntt, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t public_key_serialized[1568U]; - serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536size_t_1568size_t( + serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1536size_t_1568size_t( uu____4, seed_for_A, public_key_serialized); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____5[4U]; memcpy( uu____5, secret_as_ntt, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t secret_key_serialized[1536U]; - serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1536size_t( + serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1536size_t( uu____5, secret_key_serialized); uint8_t uu____6[1536U]; memcpy(uu____6, secret_key_serialized, (size_t)1536U * sizeof(uint8_t)); @@ -3339,7 +3459,7 @@ serialize_kem_secret_key__libcrux_ml_kem_hash_functions_portable_PortableHash___ } libcrux_ml_kem_mlkem1024_MlKem1024KeyPair -libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_3168size_t_1568size_t_1536size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_3168size_t_1568size_t_1536size_t_2size_t_128size_t( uint8_t randomness[64U]) { Eurydice_slice ind_cpa_keypair_randomness = Eurydice_array_to_subslice( (size_t)64U, randomness, @@ -3352,7 +3472,7 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t, size_t, Eurydice_slice); libcrux_ml_kem_utils_extraction_helper_Keypair1024 uu____0 = - generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_1568size_t_1536size_t_2size_t_128size_t( + generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1536size_t_1568size_t_1536size_t_2size_t_128size_t( ind_cpa_keypair_randomness); uint8_t ind_cpa_private_key[1536U]; memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1536U * sizeof(uint8_t)); @@ -3382,25 +3502,24 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable static inline void entropy_preprocess__libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( Eurydice_slice randomness, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, randomness, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + randomness, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } static inline void -deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1536size_t_4size_t( +deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1536size_t_4size_t( Eurydice_slice public_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[4U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[4U]; - KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, - deserialized_pk[i] = - ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + KRML_MAYBE_FOR4( + i, (size_t)0U, (size_t)4U, (size_t)1U, + deserialized_pk[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -3413,9 +3532,9 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( ring_element); deserialized_pk[i0] = uu____0; } @@ -3423,17 +3542,18 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector ret, deserialized_pk, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_4size_t__uint8_t -sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_128size_t_2size_t( +static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t__uint8_t +sample_ring_element_cbd__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_128size_t_2size_t( uint8_t prf_input[33U], uint8_t domain_separator) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_1[4U]; KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, - error_1[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + error_1[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[4U][33U]; @@ -3447,26 +3567,26 @@ sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_m PRFxN___4size_t_128size_t(prf_inputs, prf_outputs); KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = - sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t, Eurydice_slice)); error_1[i0] = uu____1;); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____2[4U]; memcpy( uu____2, error_1, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_4size_t__uint8_t + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t__uint8_t lit; memcpy( lit.fst, uu____2, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); lit.snd = domain_separator; return lit; } @@ -3481,15 +3601,15 @@ static inline void PRF___4size_t_128size_t(Eurydice_slice input, } static inline void -invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector( +invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { KRML_MAYBE_FOR16( i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; zeta_i[0U] = zeta_i[0U] - (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_1_step( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - @@ -3502,15 +3622,15 @@ invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector( } static inline void -invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector( +invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { KRML_MAYBE_FOR16( i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; zeta_i[0U] = zeta_i[0U] - (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_2_step( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - @@ -3519,41 +3639,42 @@ invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector( } static inline void -invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector( +invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { KRML_MAYBE_FOR16( i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; zeta_i[0U] = zeta_i[0U] - (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_3_step( re->coefficients[round], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); re->coefficients[round] = uu____0;); } -static inline __libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector -inv_ntt_layer_int_vec_step_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector a, - libcrux_ml_kem_vector_portable_PortableVector b, int16_t zeta_r) { - libcrux_ml_kem_vector_portable_PortableVector a_minus_b = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( +static inline __libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector +inv_ntt_layer_int_vec_step_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + libcrux_ml_kem_vector_portable_vector_type_PortableVector b, + int16_t zeta_r) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector a_minus_b = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( b, &a); - a = libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + a = libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( a, &b)); - b = montgomery_multiply_fe__libcrux_ml_kem_vector_portable_PortableVector( + b = montgomery_multiply_fe__libcrux_ml_kem_vector_portable_vector_type_PortableVector( a_minus_b, zeta_r); return (CLITERAL( - __libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector){ + __libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector){ .fst = a, .snd = b}); } static inline void -invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( +invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t layer) { size_t step = (size_t)1U << (uint32_t)layer; @@ -3567,14 +3688,14 @@ invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( step / LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; for (size_t i = offset_vec; i < offset_vec + step_vec; i++) { size_t j = i; - __libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector + __libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - inv_ntt_layer_int_vec_step_reduce__libcrux_ml_kem_vector_portable_PortableVector( + inv_ntt_layer_int_vec_step_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[j], re->coefficients[j + step_vec], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R [zeta_i[0U]]); - libcrux_ml_kem_vector_portable_PortableVector x = uu____0.fst; - libcrux_ml_kem_vector_portable_PortableVector y = uu____0.snd; + libcrux_ml_kem_vector_portable_vector_type_PortableVector x = uu____0.fst; + libcrux_ml_kem_vector_portable_vector_type_PortableVector y = uu____0.snd; re->coefficients[j] = x; re->coefficients[j + step_vec] = y; } @@ -3582,78 +3703,81 @@ invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( } static inline void -invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_4size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { size_t zeta_i = LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / (size_t)2U; - invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, - re); - invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, - re); - invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, - re); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)4U); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)5U); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)6U); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)7U); - poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector(re); + poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + re); } static inline void -add_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +add_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t j = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_normal_form = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( - self->coefficients[j], (int16_t)1441); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_normal_form = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( + self->coefficients[j], (int16_t)1441); + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( coefficient_normal_form, &error->coefficients[j])); self->coefficients[j] = uu____0; } } static inline void -compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector ( +compute_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ( *a_as_ntt)[4U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *r_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_1, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[4U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result[4U]; KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, - result[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + result[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for ( size_t i0 = (size_t)0U; i0 < core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)4U, a_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [4U], Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [4U], size_t); i0++) { size_t i1 = i0; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *row = a_as_ntt[i1]; for ( size_t i = (size_t)0U; @@ -3661,169 +3785,180 @@ compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t( core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)4U, row, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *a_element = &row[j]; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - a_element, &r_as_ntt[j]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + a_element, &r_as_ntt[j]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( &result[i1], &product); } - invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( &result[i1]); - add_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + add_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &result[i1], &error_1[i1]); } memcpy( ret, result, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static libcrux_ml_kem_vector_portable_PortableVector -decompress_1__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector v) { - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); - return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___bitwise_and_with_constant( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( +static libcrux_ml_kem_vector_portable_vector_type_PortableVector +decompress_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); + return libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___bitwise_and_with_constant( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( uu____0, &v), (int16_t)1665); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( uint8_t serialized[32U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - re = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + re = ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); KRML_MAYBE_FOR16( i, (size_t)0U, (size_t)16U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_compressed = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_1( - Eurydice_array_to_subslice( - (size_t)32U, serialized, - (CLITERAL(core_ops_range_Range__size_t){ - .start = (size_t)2U * i0, - .end = (size_t)2U * i0 + (size_t)2U}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - decompress_1__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_compressed = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_1( + Eurydice_array_to_subslice( + (size_t)32U, serialized, + (CLITERAL(core_ops_range_Range__size_t){ + .start = (size_t)2U * i0, + .end = (size_t)2U * i0 + (size_t)2U}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + decompress_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( coefficient_compressed); re.coefficients[i0] = uu____0;); return re; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -add_message_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +add_message_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *message, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_normal_form = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( - result.coefficients[i0], (int16_t)1441); - libcrux_ml_kem_vector_portable_PortableVector tmp = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_normal_form = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( + result.coefficients[i0], (int16_t)1441); + libcrux_ml_kem_vector_portable_vector_type_PortableVector tmp = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( self->coefficients[i0], &message->coefficients[i0]); - libcrux_ml_kem_vector_portable_PortableVector tmp0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector tmp0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( coefficient_normal_form, &tmp); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( tmp0); result.coefficients[i0] = uu____0; } return result; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -compute_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +compute_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *t_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *r_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_2, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *message) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - result = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + result = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - &t_as_ntt[i0], &r_as_ntt[i0]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &t_as_ntt[i0], &r_as_ntt[i0]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( &result, &product);); - invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( &result); result = - add_message_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + add_message_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( error_2, message, result); return result; } -static inline libcrux_ml_kem_vector_portable_PortableVector -compress___10int32_t(libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +compress___10int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - int16_t uu____0 = libcrux_ml_kem_vector_compress_ciphertext_coefficient( - (uint8_t)(int32_t)10, (uint16_t)v.elements[i0]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( + (uint8_t)(int32_t)10, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } -static libcrux_ml_kem_vector_portable_PortableVector compress___10int32_t0( - libcrux_ml_kem_vector_portable_PortableVector v) { +static libcrux_ml_kem_vector_portable_vector_type_PortableVector +compress___10int32_t0( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return compress___10int32_t(v); } -static inline libcrux_ml_kem_vector_portable_PortableVector -compress___11int32_t(libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +compress___11int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - int16_t uu____0 = libcrux_ml_kem_vector_compress_ciphertext_coefficient( - (uint8_t)(int32_t)11, (uint16_t)v.elements[i0]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( + (uint8_t)(int32_t)11, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } -static libcrux_ml_kem_vector_portable_PortableVector compress___11int32_t0( - libcrux_ml_kem_vector_portable_PortableVector v) { +static libcrux_ml_kem_vector_portable_vector_type_PortableVector +compress___11int32_t0( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return compress___11int32_t(v); } static inline void -compress_then_serialize_11__libcrux_ml_kem_vector_portable_PortableVector_352size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_11__libcrux_ml_kem_vector_portable_vector_type_PortableVector_352size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, uint8_t ret[352U]) { uint8_t serialized[352U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = compress___11int32_t0( - to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[i0])); uint8_t bytes[22U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_11( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_11( coefficient, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)352U, serialized, @@ -3839,19 +3974,19 @@ compress_then_serialize_11__libcrux_ml_kem_vector_portable_PortableVector_352siz } static inline void -compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_11size_t_352size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_11size_t_352size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, uint8_t ret[352U]) { uint8_t uu____0[352U]; - compress_then_serialize_11__libcrux_ml_kem_vector_portable_PortableVector_352size_t( + compress_then_serialize_11__libcrux_ml_kem_vector_portable_vector_type_PortableVector_352size_t( re, uu____0); memcpy(ret, uu____0, (size_t)352U * sizeof(uint8_t)); } static void -compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1408size_t_11size_t_352size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1408size_t_11size_t_352size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector input[4U], Eurydice_slice out) { for ( @@ -3860,13 +3995,13 @@ compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)4U, input, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = input[i0]; Eurydice_slice uu____0 = Eurydice_slice_subslice( out, @@ -3875,7 +4010,7 @@ compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t .end = (i0 + (size_t)1U) * ((size_t)1408U / (size_t)4U)}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); uint8_t ret[352U]; - compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_11size_t_352size_t( + compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_11size_t_352size_t( &re, ret); core_slice___Slice_T___copy_from_slice( uu____0, @@ -3884,37 +4019,40 @@ compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t } } -static inline libcrux_ml_kem_vector_portable_PortableVector compress___4int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +compress___4int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - int16_t uu____0 = libcrux_ml_kem_vector_compress_ciphertext_coefficient( - (uint8_t)(int32_t)4, (uint16_t)v.elements[i0]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( + (uint8_t)(int32_t)4, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } -static libcrux_ml_kem_vector_portable_PortableVector compress___4int32_t0( - libcrux_ml_kem_vector_portable_PortableVector v) { +static libcrux_ml_kem_vector_portable_vector_type_PortableVector +compress___4int32_t0( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return compress___4int32_t(v); } static inline void -compress_then_serialize_4__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_4__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re, Eurydice_slice serialized) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = compress___4int32_t0( - to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re.coefficients[i0])); uint8_t bytes[8U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_4( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_4( coefficient, bytes); Eurydice_slice uu____0 = Eurydice_slice_subslice( serialized, @@ -3928,37 +4066,40 @@ compress_then_serialize_4__libcrux_ml_kem_vector_portable_PortableVector( } } -static inline libcrux_ml_kem_vector_portable_PortableVector compress___5int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +compress___5int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - int16_t uu____0 = libcrux_ml_kem_vector_compress_ciphertext_coefficient( - (uint8_t)(int32_t)5, (uint16_t)v.elements[i0]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( + (uint8_t)(int32_t)5, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } -static libcrux_ml_kem_vector_portable_PortableVector compress___5int32_t0( - libcrux_ml_kem_vector_portable_PortableVector v) { +static libcrux_ml_kem_vector_portable_vector_type_PortableVector +compress___5int32_t0( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return compress___5int32_t(v); } static inline void -compress_then_serialize_5__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_5__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re, Eurydice_slice serialized) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficients = + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficients = compress___5int32_t0( - to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re.coefficients[i0])); uint8_t bytes[10U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_5( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_5( coefficients, bytes); Eurydice_slice uu____0 = Eurydice_slice_subslice( serialized, @@ -3973,102 +4114,102 @@ compress_then_serialize_5__libcrux_ml_kem_vector_portable_PortableVector( } static inline void -compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_5size_t_160size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_5size_t_160size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re, Eurydice_slice out) { - compress_then_serialize_5__libcrux_ml_kem_vector_portable_PortableVector(re, - out); + compress_then_serialize_5__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + re, out); } static void -encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( +encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( Eurydice_slice public_key, uint8_t message[32U], Eurydice_slice randomness, uint8_t ret[1568U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[4U]; - deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1536size_t_4size_t( + deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1536size_t_4size_t( Eurydice_slice_subslice_to(public_key, (size_t)1536U, uint8_t, size_t, Eurydice_slice), t_as_ntt); Eurydice_slice seed = Eurydice_slice_subslice_from( public_key, (size_t)1536U, uint8_t, size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[4U][4U]; uint8_t ret0[34U]; libcrux_ml_kem_utils_into_padded_array___34size_t(seed, ret0); - sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( + sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t( ret0, false, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array___33size_t(randomness, prf_input); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_4size_t__uint8_t + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t__uint8_t uu____1 = - sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_2size_t_128size_t( + sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_2size_t_128size_t( uu____0, 0U); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector r_as_ntt[4U]; memcpy( r_as_ntt, uu____1.fst, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator0 = uu____1.snd; uint8_t uu____2[33U]; memcpy(uu____2, prf_input, (size_t)33U * sizeof(uint8_t)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_4size_t__uint8_t + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t__uint8_t uu____3 = - sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_128size_t_2size_t( + sample_ring_element_cbd__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_128size_t_2size_t( uu____2, domain_separator0); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_1[4U]; memcpy( error_1, uu____3.fst, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator = uu____3.snd; prf_input[32U] = domain_separator; uint8_t prf_output[128U]; PRF___4size_t_128size_t( Eurydice_array_to_slice((size_t)33U, prf_input, uint8_t, Eurydice_slice), prf_output); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_2 = - sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_array_to_slice((size_t)128U, prf_output, uint8_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u[4U]; - compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + compute_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( A_transpose, r_as_ntt, error_1, u); uint8_t uu____4[32U]; memcpy(uu____4, message, (size_t)32U * sizeof(uint8_t)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector message_as_ring_element = - deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( uu____4); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - v = compute_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + v = compute_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( t_as_ntt, r_as_ntt, &error_2, &message_as_ring_element); uint8_t ciphertext[1568U] = {0U}; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____5[4U]; memcpy( uu____5, u, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1408size_t_11size_t_352size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + compress_then_serialize_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1408size_t_11size_t_352size_t( uu____5, Eurydice_array_to_subslice( (size_t)1568U, ciphertext, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)1408U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____6 = v; - compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_5size_t_160size_t( + compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_5size_t_160size_t( uu____6, Eurydice_array_to_subslice_from((size_t)1568U, ciphertext, (size_t)1408U, uint8_t, size_t, Eurydice_slice)); @@ -4078,17 +4219,15 @@ encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_funct static inline void kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1568size_t( Eurydice_slice shared_secret, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, shared_secret, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + shared_secret, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } K___libcrux_ml_kem_types_MlKemCiphertext___1568size_t___uint8_t_32size_t_ -libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( libcrux_ml_kem_types_MlKemPublicKey____1568size_t *public_key, uint8_t randomness[32U]) { uint8_t randomness0[32U]; @@ -4134,7 +4273,7 @@ libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVecto uint8_t uu____3[32U]; memcpy(uu____3, randomness0, (size_t)32U * sizeof(uint8_t)); uint8_t ciphertext[1568U]; - encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( + encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( uu____2, uu____3, pseudorandomness, ciphertext); uint8_t uu____4[1568U]; memcpy(uu____4, ciphertext, (size_t)1568U * sizeof(uint8_t)); @@ -4153,9 +4292,9 @@ libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVecto return lit; } -static inline libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector decompress_ciphertext_coefficient___10int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -4168,17 +4307,17 @@ decompress_ciphertext_coefficient___10int32_t( return v; } -static libcrux_ml_kem_vector_portable_PortableVector +static libcrux_ml_kem_vector_portable_vector_type_PortableVector decompress_ciphertext_coefficient___10int32_t0( - libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return decompress_ciphertext_coefficient___10int32_t(v); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_then_decompress_10__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_then_decompress_10__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - re = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + re = ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)20U; @@ -4189,19 +4328,19 @@ deserialize_then_decompress_10__libcrux_ml_kem_vector_portable_PortableVector( (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)20U, .end = i0 * (size_t)20U + (size_t)20U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_10( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_10( bytes); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = decompress_ciphertext_coefficient___10int32_t0(coefficient); re.coefficients[i0] = uu____0; } return re; } -static inline libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector decompress_ciphertext_coefficient___11int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -4214,17 +4353,17 @@ decompress_ciphertext_coefficient___11int32_t( return v; } -static libcrux_ml_kem_vector_portable_PortableVector +static libcrux_ml_kem_vector_portable_vector_type_PortableVector decompress_ciphertext_coefficient___11int32_t0( - libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return decompress_ciphertext_coefficient___11int32_t(v); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_then_decompress_11__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_then_decompress_11__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - re = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + re = ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)22U; @@ -4235,56 +4374,61 @@ deserialize_then_decompress_11__libcrux_ml_kem_vector_portable_PortableVector( (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)22U, .end = i0 * (size_t)22U + (size_t)22U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_11( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_11( bytes); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = decompress_ciphertext_coefficient___11int32_t0(coefficient); re.coefficients[i0] = uu____0; } return re; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_11size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_11size_t( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0; uu____0 = - deserialize_then_decompress_11__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_then_decompress_11__libcrux_ml_kem_vector_portable_vector_type_PortableVector( serialized); return uu____0; } static inline void -ntt_vector_u__libcrux_ml_kem_vector_portable_PortableVector_11size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +ntt_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_11size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { size_t zeta_i = (size_t)0U; - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)7U); - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)6U); - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)5U); - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)4U); - ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, re); - ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, re); - ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, re); - poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector(re); + ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + re); } static inline void -deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1568size_t_11size_t( +deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1568size_t_11size_t( uint8_t *ciphertext, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[4U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u_as_ntt[4U]; KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, - u_as_ntt[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + u_as_ntt[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len( Eurydice_array_to_slice((size_t)1568U, ciphertext, uint8_t, @@ -4305,24 +4449,24 @@ deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_4si LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)11U / (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_11size_t( + deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_11size_t( u_bytes); u_as_ntt[i0] = uu____0; - ntt_vector_u__libcrux_ml_kem_vector_portable_PortableVector_11size_t( + ntt_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_11size_t( &u_as_ntt[i0]); } memcpy( ret, u_as_ntt, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector decompress_ciphertext_coefficient___4int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -4335,17 +4479,17 @@ decompress_ciphertext_coefficient___4int32_t( return v; } -static libcrux_ml_kem_vector_portable_PortableVector +static libcrux_ml_kem_vector_portable_vector_type_PortableVector decompress_ciphertext_coefficient___4int32_t0( - libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return decompress_ciphertext_coefficient___4int32_t(v); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_then_decompress_4__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_then_decompress_4__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - re = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + re = ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)8U; i++) { @@ -4355,19 +4499,19 @@ deserialize_then_decompress_4__libcrux_ml_kem_vector_portable_PortableVector( (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)8U, .end = i0 * (size_t)8U + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_4( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_4( bytes); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = decompress_ciphertext_coefficient___4int32_t0(coefficient); re.coefficients[i0] = uu____0; } return re; } -static inline libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector decompress_ciphertext_coefficient___5int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -4380,17 +4524,17 @@ decompress_ciphertext_coefficient___5int32_t( return v; } -static libcrux_ml_kem_vector_portable_PortableVector +static libcrux_ml_kem_vector_portable_vector_type_PortableVector decompress_ciphertext_coefficient___5int32_t0( - libcrux_ml_kem_vector_portable_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { return decompress_ciphertext_coefficient___5int32_t(v); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_then_decompress_5__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_then_decompress_5__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - re = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + re = ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)10U; @@ -4401,33 +4545,33 @@ deserialize_then_decompress_5__libcrux_ml_kem_vector_portable_PortableVector( (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)10U, .end = i0 * (size_t)10U + (size_t)10U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_5( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_5( bytes); re.coefficients[i0] = uu____0; - libcrux_ml_kem_vector_portable_PortableVector uu____1 = + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = decompress_ciphertext_coefficient___5int32_t0(re.coefficients[i0]); re.coefficients[i0] = uu____1; } return re; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_5size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_5size_t( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0; uu____0 = - deserialize_then_decompress_5__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_then_decompress_5__libcrux_ml_kem_vector_portable_vector_type_PortableVector( serialized); return uu____0; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - re = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + re = ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)24U; @@ -4438,8 +4582,8 @@ deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_Portabl (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)24U, .end = i0 * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_12( bytes); re.coefficients[i0] = uu____0; } @@ -4447,15 +4591,16 @@ deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_Portabl } static inline void -deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t( +deserialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( Eurydice_slice secret_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[4U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[4U]; - KRML_MAYBE_FOR4(i, (size_t)0U, (size_t)4U, (size_t)1U, - secret_as_ntt[i] = - ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + KRML_MAYBE_FOR4( + i, (size_t)0U, (size_t)4U, (size_t)1U, + secret_as_ntt[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(secret_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -4468,9 +4613,9 @@ deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t( .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( secret_bytes); secret_as_ntt[i0] = uu____0; } @@ -4478,70 +4623,75 @@ deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t( ret, secret_as_ntt, (size_t)4U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -subtract_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +subtract_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector b) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_normal_form = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( - b.coefficients[i0], (int16_t)1441); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_normal_form = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( + b.coefficients[i0], (int16_t)1441); + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( self->coefficients[i0], &coefficient_normal_form)); b.coefficients[i0] = uu____0; } return b; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -compute_message__libcrux_ml_kem_vector_portable_PortableVector_4size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +compute_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *secret_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *u_as_ntt) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - result = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + result = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); KRML_MAYBE_FOR4( i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - &secret_as_ntt[i0], &u_as_ntt[i0]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &secret_as_ntt[i0], &u_as_ntt[i0]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( &result, &product);); - invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( &result); result = - subtract_reduce__libcrux_ml_kem_vector_portable_PortableVector(v, result); + subtract_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + v, result); return result; } static inline void -compress_then_serialize_message__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re, uint8_t ret[32U]) { uint8_t serialized[32U] = {0U}; KRML_MAYBE_FOR16( i, (size_t)0U, (size_t)16U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = - to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re.coefficients[i0]); - libcrux_ml_kem_vector_portable_PortableVector coefficient_compressed = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress_1( - coefficient); + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_compressed = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress_1( + coefficient); uint8_t bytes[2U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_1( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_1( coefficient_compressed, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)32U, serialized, @@ -4556,27 +4706,27 @@ compress_then_serialize_message__libcrux_ml_kem_vector_portable_PortableVector( } static void -decrypt__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1568size_t_1408size_t_11size_t_5size_t( +decrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1568size_t_1408size_t_11size_t_5size_t( Eurydice_slice secret_key, uint8_t *ciphertext, uint8_t ret[32U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u_as_ntt[4U]; - deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1568size_t_11size_t( + deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1568size_t_11size_t( ciphertext, u_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - v = deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_5size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + v = deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_5size_t( Eurydice_array_to_subslice_from((size_t)1568U, ciphertext, (size_t)1408U, uint8_t, size_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[4U]; - deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + deserialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( secret_key, secret_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector message = - compute_message__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + compute_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( &v, secret_as_ntt, u_as_ntt); uint8_t ret0[32U]; - compress_then_serialize_message__libcrux_ml_kem_vector_portable_PortableVector( + compress_then_serialize_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( message, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } @@ -4590,7 +4740,7 @@ static inline void PRF___4size_t_32size_t(Eurydice_slice input, memcpy(ret, digest, (size_t)32U * sizeof(uint8_t)); } -void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_3168size_t_1536size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t_1600size_t( +void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___libcrux_ml_kem_ind_cca_MlKem_4size_t_3168size_t_1536size_t_1568size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t_1600size_t( libcrux_ml_kem_types_MlKemPrivateKey____3168size_t *private_key, libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext, uint8_t ret[32U]) { @@ -4615,7 +4765,7 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable Eurydice_slice ind_cpa_public_key_hash = uu____2.fst; Eurydice_slice implicit_rejection_value = uu____2.snd; uint8_t decrypted[32U]; - decrypt__libcrux_ml_kem_vector_portable_PortableVector_4size_t_1568size_t_1408size_t_11size_t_5size_t( + decrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_1568size_t_1408size_t_11size_t_5size_t( ind_cpa_secret_key, ciphertext->value, decrypted); uint8_t to_hash0[64U]; libcrux_ml_kem_utils_into_padded_array___64size_t( @@ -4656,7 +4806,7 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable uint8_t uu____6[32U]; memcpy(uu____6, decrypted, (size_t)32U * sizeof(uint8_t)); uint8_t expected_ciphertext[1568U]; - encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( + encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___4size_t___4size_t_1568size_t_1536size_t_1408size_t_160size_t_11size_t_5size_t_352size_t_2size_t_128size_t_2size_t_128size_t( uu____5, uu____6, pseudorandomness, expected_ciphertext); Eurydice_slice uu____7 = libcrux_ml_kem_types___core__convert__AsRef__Slice_u8___for_libcrux_ml_kem__types__MlKemCiphertext_SIZE___1__as_ref___1568size_t( @@ -4684,15 +4834,16 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable } static inline void -deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1184size_t_3size_t( +deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1184size_t_3size_t( Eurydice_slice public_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[3U]; - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, - deserialized_pk[i] = - ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + KRML_MAYBE_FOR3( + i, (size_t)0U, (size_t)3U, (size_t)1U, + deserialized_pk[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -4705,9 +4856,9 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( ring_element); deserialized_pk[i0] = uu____0; } @@ -4715,12 +4866,12 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector ret, deserialized_pk, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline void -serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector key[3U], uint8_t ret[1152U]) { uint8_t out[1152U] = {0U}; @@ -4730,13 +4881,13 @@ serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152 core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = key[i0]; Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)1152U, out, @@ -4746,7 +4897,7 @@ serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152 LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); uint8_t ret0[384U]; - serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &re, ret0); core_slice___Slice_T___copy_from_slice( uu____0, @@ -4757,8 +4908,8 @@ serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152 } static inline void -serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[3U], Eurydice_slice seed_for_a, uint8_t ret[1184U]) { uint8_t public_key_serialized[1184U] = {0U}; @@ -4767,15 +4918,15 @@ serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152 (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = (size_t)1152U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1[3U]; memcpy( uu____1, t_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t ret0[1152U]; - serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t( + serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t( uu____1, ret0); core_slice___Slice_T___copy_from_slice( uu____0, @@ -4789,23 +4940,23 @@ serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152 memcpy(ret, public_key_serialized, (size_t)1184U * sizeof(uint8_t)); } -bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( +bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( uint8_t *public_key) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[3U]; - deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1184size_t_3size_t( + deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1184size_t_3size_t( Eurydice_array_to_subslice_to((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), deserialized_pk); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0[3U]; memcpy( uu____0, deserialized_pk, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t public_key_serialized[1184U]; - serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( + serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( uu____0, Eurydice_array_to_subslice_from((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), @@ -4823,19 +4974,20 @@ static inline void G___3size_t(Eurydice_slice input, uint8_t ret[64U]) { } static void -closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret0[3U]; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, - ret0[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + ret0[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); memcpy( ret, ret0, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } typedef struct PortableHash____3size_t_s { @@ -4879,7 +5031,7 @@ static inline void shake128_squeeze_three_blocks___3size_t( } static inline bool -sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_3size_t_504size_t( +sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_504size_t( uint8_t randomness[3U][504U], size_t *sampled_coefficients, int16_t (*out)[272U]) { KRML_MAYBE_FOR3( @@ -4895,7 +5047,7 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe .end = r * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); size_t sampled = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( uu____0, Eurydice_array_to_subslice( (size_t)272U, out[i1], @@ -4931,7 +5083,7 @@ static inline void shake128_squeeze_block___3size_t( } static inline bool -sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_3size_t_168size_t( +sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_168size_t( uint8_t randomness[3U][168U], size_t *sampled_coefficients, int16_t (*out)[272U]) { KRML_MAYBE_FOR3( @@ -4947,7 +5099,7 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe .end = r * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); size_t sampled = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( uu____0, Eurydice_array_to_subslice( (size_t)272U, out[i1], @@ -4971,10 +5123,10 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe return done; } -static libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t0( +static libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t0( int16_t s[272U]) { - return from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( + return from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_array_to_subslice((size_t)272U, s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)256U}), @@ -4983,9 +5135,9 @@ closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_funct } static inline void -sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( +sample_from_xof__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( uint8_t seeds[3U][34U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { size_t sampled_coefficients[3U] = {0U}; int16_t out[3U][272U] = {{0U}}; @@ -4997,7 +5149,7 @@ sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha uint8_t uu____1[3U][504U]; memcpy(uu____1, randomness0, (size_t)3U * sizeof(uint8_t[504U])); bool done = - sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_3size_t_504size_t( + sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_504size_t( uu____1, sampled_coefficients, out); while (true) { if (done) { @@ -5008,36 +5160,36 @@ sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha uint8_t uu____2[3U][168U]; memcpy(uu____2, randomness, (size_t)3U * sizeof(uint8_t[168U])); done = - sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_3size_t_168size_t( + sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_168size_t( uu____2, sampled_coefficients, out); } } int16_t uu____3[3U][272U]; memcpy(uu____3, out, (size_t)3U * sizeof(int16_t[272U])); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret0[3U]; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, ret0[i] = - closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t0( + closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t0( uu____3[i]);); memcpy( ret, ret0, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline void -sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( +sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( uint8_t seed[34U], bool transpose, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U][3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[3U][3U]; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, - closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( A_transpose[i]);); KRML_MAYBE_FOR3( i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; @@ -5050,9 +5202,9 @@ sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha seeds[j][32U] = (uint8_t)i1; seeds[j][33U] = (uint8_t)j;); uint8_t uu____1[3U][34U]; memcpy(uu____1, seeds, (size_t)3U * sizeof(uint8_t[34U])); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector sampled[3U]; - sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + sample_from_xof__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( uu____1, sampled); for ( size_t i = (size_t)0U; @@ -5060,13 +5212,13 @@ sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, sampled, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector sample = sampled[j]; if (transpose) { A_transpose[j][i1] = sample; @@ -5078,16 +5230,16 @@ sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha ret, A_transpose, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U])); } typedef struct - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t_s { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t_s { + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector fst[3U]; uint8_t snd; -} __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t; +} __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t; static inline void PRFxN___3size_t_128size_t(uint8_t (*input)[33U], uint8_t ret[3U][128U]) { @@ -5101,14 +5253,15 @@ static inline void PRFxN___3size_t_128size_t(uint8_t (*input)[33U], memcpy(ret, out, (size_t)3U * sizeof(uint8_t[128U])); } -static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t -sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( +static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t +sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( uint8_t prf_input[33U], uint8_t domain_separator) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re_as_ntt[3U]; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, - re_as_ntt[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + re_as_ntt[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[3U][33U]; @@ -5122,84 +5275,86 @@ sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcru PRFxN___3size_t_128size_t(prf_inputs, prf_outputs); KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = - sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t, Eurydice_slice)); re_as_ntt[i0] = uu____1; - ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &re_as_ntt[i0]);); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____2[3U]; memcpy( uu____2, re_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t lit; memcpy( lit.fst, uu____2, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); lit.snd = domain_separator; return lit; } static inline void -add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; - i < - core_slice___Slice_T___len( - Eurydice_array_to_slice( - (size_t)16U, self->coefficients, - libcrux_ml_kem_vector_portable_PortableVector, Eurydice_slice), - libcrux_ml_kem_vector_portable_PortableVector, size_t); + i < core_slice___Slice_T___len( + Eurydice_array_to_slice( + (size_t)16U, self->coefficients, + libcrux_ml_kem_vector_portable_vector_type_PortableVector, + Eurydice_slice), + libcrux_ml_kem_vector_portable_vector_type_PortableVector, + size_t); i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( self->coefficients[i0], &rhs->coefficients[i0]); self->coefficients[i0] = uu____0; } } static inline void -compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector ( +compute_As_plus_e__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ( *matrix_A)[3U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *s_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result[3U]; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, - result[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + result[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for ( size_t i0 = (size_t)0U; i0 < core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, matrix_A, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U], Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U], size_t); i0++) { size_t i1 = i0; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *row = matrix_A[i1]; for ( size_t i = (size_t)0U; @@ -5207,32 +5362,33 @@ compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_3size_t( core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, row, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *matrix_element = &row[j]; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - matrix_element, &s_as_ntt[j]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + matrix_element, &s_as_ntt[j]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result[i1], &product); } - add_standard_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + add_standard_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &result[i1], &error_as_ntt[i1]); } memcpy( ret, result, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static libcrux_ml_kem_utils_extraction_helper_Keypair768 -generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_1184size_t_1152size_t_2size_t_128size_t( +generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_1184size_t_1152size_t_2size_t_128size_t( Eurydice_slice key_generation_seed) { uint8_t hashed[64U]; G___3size_t(key_generation_seed, hashed); @@ -5243,64 +5399,64 @@ generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_h K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t); Eurydice_slice seed_for_A = uu____0.fst; Eurydice_slice seed_for_secret_and_error = uu____0.snd; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[3U][3U]; uint8_t ret[34U]; libcrux_ml_kem_utils_into_padded_array___34size_t(seed_for_A, ret); - sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( ret, true, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array___33size_t(seed_for_secret_and_error, prf_input); uint8_t uu____1[33U]; memcpy(uu____1, prf_input, (size_t)33U * sizeof(uint8_t)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t uu____2 = - sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( + sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( uu____1, 0U); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[3U]; memcpy( secret_as_ntt, uu____2.fst, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator = uu____2.snd; uint8_t uu____3[33U]; memcpy(uu____3, prf_input, (size_t)33U * sizeof(uint8_t)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_as_ntt[3U]; memcpy( error_as_ntt, - sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( + sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( uu____3, domain_separator) .fst, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[3U]; - compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + compute_As_plus_e__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( A_transpose, secret_as_ntt, error_as_ntt, t_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____4[3U]; memcpy( uu____4, t_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t public_key_serialized[1184U]; - serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( + serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( uu____4, seed_for_A, public_key_serialized); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____5[3U]; memcpy( uu____5, secret_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t secret_key_serialized[1152U]; - serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t( + serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t( uu____5, secret_key_serialized); uint8_t uu____6[1152U]; memcpy(uu____6, secret_key_serialized, (size_t)1152U * sizeof(uint8_t)); @@ -5381,7 +5537,7 @@ serialize_kem_secret_key__libcrux_ml_kem_hash_functions_portable_PortableHash___ } libcrux_ml_kem_mlkem768_MlKem768KeyPair -libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( uint8_t randomness[64U]) { Eurydice_slice ind_cpa_keypair_randomness = Eurydice_array_to_subslice( (size_t)64U, randomness, @@ -5394,7 +5550,7 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t, size_t, Eurydice_slice); libcrux_ml_kem_utils_extraction_helper_Keypair768 uu____0 = - generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_1184size_t_1152size_t_2size_t_128size_t( + generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_1184size_t_1152size_t_2size_t_128size_t( ind_cpa_keypair_randomness); uint8_t ind_cpa_private_key[1152U]; memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1152U * sizeof(uint8_t)); @@ -5424,25 +5580,24 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable static inline void entropy_preprocess__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( Eurydice_slice randomness, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, randomness, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + randomness, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } static inline void -deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1152size_t_3size_t( +deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1152size_t_3size_t( Eurydice_slice public_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[3U]; - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, - deserialized_pk[i] = - ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + KRML_MAYBE_FOR3( + i, (size_t)0U, (size_t)3U, (size_t)1U, + deserialized_pk[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -5455,9 +5610,9 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( ring_element); deserialized_pk[i0] = uu____0; } @@ -5465,17 +5620,18 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector ret, deserialized_pk, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t -sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( +static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t +sample_ring_element_cbd__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( uint8_t prf_input[33U], uint8_t domain_separator) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_1[3U]; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, - error_1[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + error_1[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[3U][33U]; @@ -5489,26 +5645,26 @@ sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_m PRFxN___3size_t_128size_t(prf_inputs, prf_outputs); KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = - sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t, Eurydice_slice)); error_1[i0] = uu____1;); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____2[3U]; memcpy( uu____2, error_1, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t lit; memcpy( lit.fst, uu____2, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); lit.snd = domain_separator; return lit; } @@ -5523,58 +5679,60 @@ static inline void PRF___3size_t_128size_t(Eurydice_slice input, } static inline void -invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { size_t zeta_i = LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / (size_t)2U; - invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, - re); - invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, - re); - invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, - re); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)4U); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)5U); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)6U); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)7U); - poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector(re); + poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + re); } static inline void -compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector ( +compute_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ( *a_as_ntt)[3U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *r_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_1, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result[3U]; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, - result[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + result[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for ( size_t i0 = (size_t)0U; i0 < core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, a_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U], Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U], size_t); i0++) { size_t i1 = i0; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *row = a_as_ntt[i1]; for ( size_t i = (size_t)0U; @@ -5582,74 +5740,77 @@ compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t( core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, row, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *a_element = &row[j]; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - a_element, &r_as_ntt[j]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + a_element, &r_as_ntt[j]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result[i1], &product); } - invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result[i1]); - add_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + add_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &result[i1], &error_1[i1]); } memcpy( ret, result, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -compute_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +compute_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *t_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *r_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_2, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *message) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - result = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + result = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - &t_as_ntt[i0], &r_as_ntt[i0]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &t_as_ntt[i0], &r_as_ntt[i0]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result, &product);); - invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result); result = - add_message_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + add_message_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( error_2, message, result); return result; } static inline void -compress_then_serialize_10__libcrux_ml_kem_vector_portable_PortableVector_320size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_10__libcrux_ml_kem_vector_portable_vector_type_PortableVector_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, uint8_t ret[320U]) { uint8_t serialized[320U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = compress___10int32_t0( - to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[i0])); uint8_t bytes[20U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_10( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_10( coefficient, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)320U, serialized, @@ -5665,19 +5826,19 @@ compress_then_serialize_10__libcrux_ml_kem_vector_portable_PortableVector_320siz } static inline void -compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t_320size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, uint8_t ret[320U]) { uint8_t uu____0[320U]; - compress_then_serialize_10__libcrux_ml_kem_vector_portable_PortableVector_320size_t( + compress_then_serialize_10__libcrux_ml_kem_vector_portable_vector_type_PortableVector_320size_t( re, uu____0); memcpy(ret, uu____0, (size_t)320U * sizeof(uint8_t)); } static void -compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t_960size_t_10size_t_320size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_960size_t_10size_t_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector input[3U], Eurydice_slice out) { for ( @@ -5686,13 +5847,13 @@ compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, input, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = input[i0]; Eurydice_slice uu____0 = Eurydice_slice_subslice( out, @@ -5701,7 +5862,7 @@ compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t .end = (i0 + (size_t)1U) * ((size_t)960U / (size_t)3U)}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); uint8_t ret[320U]; - compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t_320size_t( + compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t_320size_t( &re, ret); core_slice___Slice_T___copy_from_slice( uu____0, @@ -5711,102 +5872,102 @@ compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t } static inline void -compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t_128size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_128size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re, Eurydice_slice out) { - compress_then_serialize_4__libcrux_ml_kem_vector_portable_PortableVector(re, - out); + compress_then_serialize_4__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + re, out); } static void -encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( +encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( Eurydice_slice public_key, uint8_t message[32U], Eurydice_slice randomness, uint8_t ret[1088U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[3U]; - deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1152size_t_3size_t( + deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1152size_t_3size_t( Eurydice_slice_subslice_to(public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), t_as_ntt); Eurydice_slice seed = Eurydice_slice_subslice_from( public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[3U][3U]; uint8_t ret0[34U]; libcrux_ml_kem_utils_into_padded_array___34size_t(seed, ret0); - sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( ret0, false, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array___33size_t(randomness, prf_input); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t uu____1 = - sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( + sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( uu____0, 0U); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector r_as_ntt[3U]; memcpy( r_as_ntt, uu____1.fst, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator0 = uu____1.snd; uint8_t uu____2[33U]; memcpy(uu____2, prf_input, (size_t)33U * sizeof(uint8_t)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t uu____3 = - sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( + sample_ring_element_cbd__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( uu____2, domain_separator0); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_1[3U]; memcpy( error_1, uu____3.fst, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator = uu____3.snd; prf_input[32U] = domain_separator; uint8_t prf_output[128U]; PRF___3size_t_128size_t( Eurydice_array_to_slice((size_t)33U, prf_input, uint8_t, Eurydice_slice), prf_output); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_2 = - sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_array_to_slice((size_t)128U, prf_output, uint8_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u[3U]; - compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + compute_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( A_transpose, r_as_ntt, error_1, u); uint8_t uu____4[32U]; memcpy(uu____4, message, (size_t)32U * sizeof(uint8_t)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector message_as_ring_element = - deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( uu____4); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - v = compute_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + v = compute_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( t_as_ntt, r_as_ntt, &error_2, &message_as_ring_element); uint8_t ciphertext[1088U] = {0U}; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____5[3U]; memcpy( uu____5, u, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t_960size_t_10size_t_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + compress_then_serialize_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_960size_t_10size_t_320size_t( uu____5, Eurydice_array_to_subslice( (size_t)1088U, ciphertext, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)960U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____6 = v; - compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t_128size_t( + compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_128size_t( uu____6, Eurydice_array_to_subslice_from((size_t)1088U, ciphertext, (size_t)960U, uint8_t, size_t, Eurydice_slice)); @@ -5816,17 +5977,15 @@ encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_funct static inline void kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t( Eurydice_slice shared_secret, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, shared_secret, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + shared_secret, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } K___libcrux_ml_kem_types_MlKemCiphertext___1088size_t___uint8_t_32size_t_ -libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( libcrux_ml_kem_types_MlKemPublicKey____1184size_t *public_key, uint8_t randomness[32U]) { uint8_t randomness0[32U]; @@ -5872,7 +6031,7 @@ libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVecto uint8_t uu____3[32U]; memcpy(uu____3, randomness0, (size_t)32U * sizeof(uint8_t)); uint8_t ciphertext[1088U]; - encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( + encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____2, uu____3, pseudorandomness, ciphertext); uint8_t uu____4[1088U]; memcpy(uu____4, ciphertext, (size_t)1088U * sizeof(uint8_t)); @@ -5891,46 +6050,51 @@ libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVecto return lit; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0; uu____0 = - deserialize_then_decompress_10__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_then_decompress_10__libcrux_ml_kem_vector_portable_vector_type_PortableVector( serialized); return uu____0; } static inline void -ntt_vector_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +ntt_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { size_t zeta_i = (size_t)0U; - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)7U); - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)6U); - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)5U); - ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)4U); - ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, re); - ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, re); - ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, re); - poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector(re); + ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + re); } static inline void -deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1088size_t_10size_t( +deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1088size_t_10size_t( uint8_t *ciphertext, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u_as_ntt[3U]; KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, - u_as_ntt[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + u_as_ntt[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len( Eurydice_array_to_slice((size_t)1088U, ciphertext, uint8_t, @@ -5951,42 +6115,43 @@ deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_3si LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)10U / (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( + deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( u_bytes); u_as_ntt[i0] = uu____0; - ntt_vector_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( + ntt_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( &u_as_ntt[i0]); } memcpy( ret, u_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0; uu____0 = - deserialize_then_decompress_4__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_then_decompress_4__libcrux_ml_kem_vector_portable_vector_type_PortableVector( serialized); return uu____0; } static inline void -deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t( +deserialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( Eurydice_slice secret_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[3U]; - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, - secret_as_ntt[i] = - ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + KRML_MAYBE_FOR3( + i, (size_t)0U, (size_t)3U, (size_t)1U, + secret_as_ntt[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(secret_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -5999,9 +6164,9 @@ deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t( .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( secret_bytes); secret_as_ntt[i0] = uu____0; } @@ -6009,55 +6174,58 @@ deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t( ret, secret_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -compute_message__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +compute_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *secret_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *u_as_ntt) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - result = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + result = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); KRML_MAYBE_FOR3( i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - &secret_as_ntt[i0], &u_as_ntt[i0]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &secret_as_ntt[i0], &u_as_ntt[i0]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result, &product);); - invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result); result = - subtract_reduce__libcrux_ml_kem_vector_portable_PortableVector(v, result); + subtract_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + v, result); return result; } static void -decrypt__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1088size_t_960size_t_10size_t_4size_t( +decrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1088size_t_960size_t_10size_t_4size_t( Eurydice_slice secret_key, uint8_t *ciphertext, uint8_t ret[32U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u_as_ntt[3U]; - deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1088size_t_10size_t( + deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1088size_t_10size_t( ciphertext, u_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - v = deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + v = deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( Eurydice_array_to_subslice_from((size_t)1088U, ciphertext, (size_t)960U, uint8_t, size_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[3U]; - deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + deserialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( secret_key, secret_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector message = - compute_message__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + compute_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &v, secret_as_ntt, u_as_ntt); uint8_t ret0[32U]; - compress_then_serialize_message__libcrux_ml_kem_vector_portable_PortableVector( + compress_then_serialize_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( message, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } @@ -6071,7 +6239,7 @@ static inline void PRF___3size_t_32size_t(Eurydice_slice input, memcpy(ret, digest, (size_t)32U * sizeof(uint8_t)); } -void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( +void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( libcrux_ml_kem_types_MlKemPrivateKey____2400size_t *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t uu____0 = @@ -6095,7 +6263,7 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable Eurydice_slice ind_cpa_public_key_hash = uu____2.fst; Eurydice_slice implicit_rejection_value = uu____2.snd; uint8_t decrypted[32U]; - decrypt__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1088size_t_960size_t_10size_t_4size_t( + decrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1088size_t_960size_t_10size_t_4size_t( ind_cpa_secret_key, ciphertext->value, decrypted); uint8_t to_hash0[64U]; libcrux_ml_kem_utils_into_padded_array___64size_t( @@ -6136,7 +6304,7 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable uint8_t uu____6[32U]; memcpy(uu____6, decrypted, (size_t)32U * sizeof(uint8_t)); uint8_t expected_ciphertext[1088U]; - encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( + encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____5, uu____6, pseudorandomness, expected_ciphertext); Eurydice_slice uu____7 = libcrux_ml_kem_types___core__convert__AsRef__Slice_u8___for_libcrux_ml_kem__types__MlKemCiphertext_SIZE___1__as_ref___1088size_t( @@ -6164,15 +6332,16 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable } static inline void -deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_800size_t_2size_t( +deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_800size_t_2size_t( Eurydice_slice public_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[2U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[2U]; - KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, - deserialized_pk[i] = - ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + KRML_MAYBE_FOR2( + i, (size_t)0U, (size_t)2U, (size_t)1U, + deserialized_pk[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -6185,9 +6354,9 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( ring_element); deserialized_pk[i0] = uu____0; } @@ -6195,12 +6364,12 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector ret, deserialized_pk, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline void -serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector key[2U], uint8_t ret[768U]) { uint8_t out[768U] = {0U}; @@ -6210,13 +6379,13 @@ serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768s core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)2U, key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = key[i0]; Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)768U, out, @@ -6226,7 +6395,7 @@ serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768s LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); uint8_t ret0[384U]; - serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &re, ret0); core_slice___Slice_T___copy_from_slice( uu____0, @@ -6237,8 +6406,8 @@ serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768s } static inline void -serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_800size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_800size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[2U], Eurydice_slice seed_for_a, uint8_t ret[800U]) { uint8_t public_key_serialized[800U] = {0U}; @@ -6247,15 +6416,15 @@ serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768s (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = (size_t)768U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1[2U]; memcpy( uu____1, t_as_ntt, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t ret0[768U]; - serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t( + serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t( uu____1, ret0); core_slice___Slice_T___copy_from_slice( uu____0, @@ -6269,23 +6438,23 @@ serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768s memcpy(ret, public_key_serialized, (size_t)800U * sizeof(uint8_t)); } -bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_800size_t( +bool libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_800size_t( uint8_t *public_key) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[2U]; - deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_800size_t_2size_t( + deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_800size_t_2size_t( Eurydice_array_to_subslice_to((size_t)800U, public_key, (size_t)768U, uint8_t, size_t, Eurydice_slice), deserialized_pk); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0[2U]; memcpy( uu____0, deserialized_pk, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t public_key_serialized[800U]; - serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_800size_t( + serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_800size_t( uu____0, Eurydice_array_to_subslice_from((size_t)800U, public_key, (size_t)768U, uint8_t, size_t, Eurydice_slice), @@ -6303,19 +6472,20 @@ static inline void G___2size_t(Eurydice_slice input, uint8_t ret[64U]) { } static void -closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[2U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret0[2U]; KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, - ret0[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + ret0[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); memcpy( ret, ret0, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } typedef struct PortableHash____2size_t_s { @@ -6359,7 +6529,7 @@ static inline void shake128_squeeze_three_blocks___2size_t( } static inline bool -sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_2size_t_504size_t( +sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_504size_t( uint8_t randomness[2U][504U], size_t *sampled_coefficients, int16_t (*out)[272U]) { KRML_MAYBE_FOR2( @@ -6375,7 +6545,7 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe .end = r * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); size_t sampled = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( uu____0, Eurydice_array_to_subslice( (size_t)272U, out[i1], @@ -6411,7 +6581,7 @@ static inline void shake128_squeeze_block___2size_t( } static inline bool -sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_2size_t_168size_t( +sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_168size_t( uint8_t randomness[2U][168U], size_t *sampled_coefficients, int16_t (*out)[272U]) { KRML_MAYBE_FOR2( @@ -6427,7 +6597,7 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe .end = r * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); size_t sampled = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( uu____0, Eurydice_array_to_subslice( (size_t)272U, out[i1], @@ -6451,10 +6621,10 @@ sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVe return done; } -static libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t0( +static libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t0( int16_t s[272U]) { - return from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( + return from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_array_to_subslice((size_t)272U, s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)256U}), @@ -6463,9 +6633,9 @@ closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_funct } static inline void -sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( +sample_from_xof__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( uint8_t seeds[2U][34U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[2U]) { size_t sampled_coefficients[2U] = {0U}; int16_t out[2U][272U] = {{0U}}; @@ -6477,7 +6647,7 @@ sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha uint8_t uu____1[2U][504U]; memcpy(uu____1, randomness0, (size_t)2U * sizeof(uint8_t[504U])); bool done = - sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_2size_t_504size_t( + sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_504size_t( uu____1, sampled_coefficients, out); while (true) { if (done) { @@ -6488,36 +6658,36 @@ sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha uint8_t uu____2[2U][168U]; memcpy(uu____2, randomness, (size_t)2U * sizeof(uint8_t[168U])); done = - sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_2size_t_168size_t( + sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_168size_t( uu____2, sampled_coefficients, out); } } int16_t uu____3[2U][272U]; memcpy(uu____3, out, (size_t)2U * sizeof(int16_t[272U])); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret0[2U]; KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, ret0[i] = - closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t0( + closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t0( uu____3[i]);); memcpy( ret, ret0, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline void -sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( +sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( uint8_t seed[34U], bool transpose, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[2U][2U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[2U][2U]; KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, - closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( + closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( A_transpose[i]);); KRML_MAYBE_FOR2( i0, (size_t)0U, (size_t)2U, (size_t)1U, size_t i1 = i0; @@ -6530,9 +6700,9 @@ sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha seeds[j][32U] = (uint8_t)i1; seeds[j][33U] = (uint8_t)j;); uint8_t uu____1[2U][34U]; memcpy(uu____1, seeds, (size_t)2U * sizeof(uint8_t[34U])); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector sampled[2U]; - sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( + sample_from_xof__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( uu____1, sampled); for ( size_t i = (size_t)0U; @@ -6540,13 +6710,13 @@ sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)2U, sampled, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector sample = sampled[j]; if (transpose) { A_transpose[j][i1] = sample; @@ -6558,16 +6728,16 @@ sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_ha ret, A_transpose, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [2U])); } typedef struct - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_2size_t__uint8_t_s { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t__uint8_t_s { + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector fst[2U]; uint8_t snd; -} __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_2size_t__uint8_t; +} __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t__uint8_t; static inline void PRFxN___2size_t_192size_t(uint8_t (*input)[33U], uint8_t ret[2U][192U]) { @@ -6581,25 +6751,26 @@ static inline void PRFxN___2size_t_192size_t(uint8_t (*input)[33U], memcpy(ret, out, (size_t)2U * sizeof(uint8_t[192U])); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_3size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( Eurydice_slice randomness) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0; uu____0 = - sample_from_binomial_distribution_3__libcrux_ml_kem_vector_portable_PortableVector( + sample_from_binomial_distribution_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( randomness); return uu____0; } -static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_2size_t__uint8_t -sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_3size_t_192size_t( +static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t__uint8_t +sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_3size_t_192size_t( uint8_t prf_input[33U], uint8_t domain_separator) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re_as_ntt[2U]; KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, - re_as_ntt[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + re_as_ntt[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[2U][33U]; @@ -6613,84 +6784,86 @@ sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcru PRFxN___2size_t_192size_t(prf_inputs, prf_outputs); KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = - sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( Eurydice_array_to_slice((size_t)192U, prf_outputs[i0], uint8_t, Eurydice_slice)); re_as_ntt[i0] = uu____1; - ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &re_as_ntt[i0]);); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____2[2U]; memcpy( uu____2, re_as_ntt, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_2size_t__uint8_t + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t__uint8_t lit; memcpy( lit.fst, uu____2, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); lit.snd = domain_separator; return lit; } static inline void -add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_2size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; - i < - core_slice___Slice_T___len( - Eurydice_array_to_slice( - (size_t)16U, self->coefficients, - libcrux_ml_kem_vector_portable_PortableVector, Eurydice_slice), - libcrux_ml_kem_vector_portable_PortableVector, size_t); + i < core_slice___Slice_T___len( + Eurydice_array_to_slice( + (size_t)16U, self->coefficients, + libcrux_ml_kem_vector_portable_vector_type_PortableVector, + Eurydice_slice), + libcrux_ml_kem_vector_portable_vector_type_PortableVector, + size_t); i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( self->coefficients[i0], &rhs->coefficients[i0]); self->coefficients[i0] = uu____0; } } static inline void -compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_2size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector ( +compute_As_plus_e__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ( *matrix_A)[2U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *s_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[2U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result[2U]; KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, - result[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + result[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for ( size_t i0 = (size_t)0U; i0 < core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)2U, matrix_A, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [2U], Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [2U], size_t); i0++) { size_t i1 = i0; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *row = matrix_A[i1]; for ( size_t i = (size_t)0U; @@ -6698,32 +6871,33 @@ compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_2size_t( core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)2U, row, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *matrix_element = &row[j]; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - matrix_element, &s_as_ntt[j]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + matrix_element, &s_as_ntt[j]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( &result[i1], &product); } - add_standard_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + add_standard_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &result[i1], &error_as_ntt[i1]); } memcpy( ret, result, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static libcrux_ml_kem_utils_extraction_helper_Keypair512 -generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_800size_t_768size_t_3size_t_192size_t( +generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_800size_t_768size_t_3size_t_192size_t( Eurydice_slice key_generation_seed) { uint8_t hashed[64U]; G___2size_t(key_generation_seed, hashed); @@ -6734,64 +6908,64 @@ generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_h K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t); Eurydice_slice seed_for_A = uu____0.fst; Eurydice_slice seed_for_secret_and_error = uu____0.snd; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[2U][2U]; uint8_t ret[34U]; libcrux_ml_kem_utils_into_padded_array___34size_t(seed_for_A, ret); - sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( + sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( ret, true, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array___33size_t(seed_for_secret_and_error, prf_input); uint8_t uu____1[33U]; memcpy(uu____1, prf_input, (size_t)33U * sizeof(uint8_t)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_2size_t__uint8_t + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t__uint8_t uu____2 = - sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_3size_t_192size_t( + sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_3size_t_192size_t( uu____1, 0U); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[2U]; memcpy( secret_as_ntt, uu____2.fst, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator = uu____2.snd; uint8_t uu____3[33U]; memcpy(uu____3, prf_input, (size_t)33U * sizeof(uint8_t)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_as_ntt[2U]; memcpy( error_as_ntt, - sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_3size_t_192size_t( + sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_3size_t_192size_t( uu____3, domain_separator) .fst, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[2U]; - compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + compute_As_plus_e__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( A_transpose, secret_as_ntt, error_as_ntt, t_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____4[2U]; memcpy( uu____4, t_as_ntt, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t public_key_serialized[800U]; - serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_800size_t( + serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_800size_t( uu____4, seed_for_A, public_key_serialized); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____5[2U]; memcpy( uu____5, secret_as_ntt, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t secret_key_serialized[768U]; - serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t( + serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t( uu____5, secret_key_serialized); uint8_t uu____6[768U]; memcpy(uu____6, secret_key_serialized, (size_t)768U * sizeof(uint8_t)); @@ -6872,7 +7046,7 @@ serialize_kem_secret_key__libcrux_ml_kem_hash_functions_portable_PortableHash___ } libcrux_ml_kem_types_MlKemKeyPair____1632size_t__800size_t -libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_1632size_t_800size_t_768size_t_3size_t_192size_t( +libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_1632size_t_800size_t_768size_t_3size_t_192size_t( uint8_t randomness[64U]) { Eurydice_slice ind_cpa_keypair_randomness = Eurydice_array_to_subslice( (size_t)64U, randomness, @@ -6885,7 +7059,7 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t, size_t, Eurydice_slice); libcrux_ml_kem_utils_extraction_helper_Keypair512 uu____0 = - generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_800size_t_768size_t_3size_t_192size_t( + generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_800size_t_768size_t_3size_t_192size_t( ind_cpa_keypair_randomness); uint8_t ind_cpa_private_key[768U]; memcpy(ind_cpa_private_key, uu____0.fst, (size_t)768U * sizeof(uint8_t)); @@ -6915,25 +7089,24 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable static inline void entropy_preprocess__libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( Eurydice_slice randomness, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, randomness, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + randomness, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } static inline void -deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_768size_t_2size_t( +deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_768size_t_2size_t( Eurydice_slice public_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[2U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[2U]; - KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, - deserialized_pk[i] = - ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + KRML_MAYBE_FOR2( + i, (size_t)0U, (size_t)2U, (size_t)1U, + deserialized_pk[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -6946,9 +7119,9 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( ring_element); deserialized_pk[i0] = uu____0; } @@ -6956,7 +7129,7 @@ deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector ret, deserialized_pk, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline void PRFxN___2size_t_128size_t(uint8_t (*input)[33U], @@ -6971,14 +7144,15 @@ static inline void PRFxN___2size_t_128size_t(uint8_t (*input)[33U], memcpy(ret, out, (size_t)2U * sizeof(uint8_t[128U])); } -static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_2size_t__uint8_t -sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_128size_t_2size_t( +static inline __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t__uint8_t +sample_ring_element_cbd__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_128size_t_2size_t( uint8_t prf_input[33U], uint8_t domain_separator) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_1[2U]; KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, - error_1[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + error_1[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[2U][33U]; @@ -6992,26 +7166,26 @@ sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_m PRFxN___2size_t_128size_t(prf_inputs, prf_outputs); KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = - sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t, Eurydice_slice)); error_1[i0] = uu____1;); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____2[2U]; memcpy( uu____2, error_1, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_2size_t__uint8_t + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t__uint8_t lit; memcpy( lit.fst, uu____2, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); lit.snd = domain_separator; return lit; } @@ -7026,58 +7200,60 @@ static inline void PRF___2size_t_128size_t(Eurydice_slice input, } static inline void -invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_2size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { size_t zeta_i = LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / (size_t)2U; - invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, - re); - invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, - re); - invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector(&zeta_i, - re); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &zeta_i, re); + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)4U); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)5U); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)6U); - invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)7U); - poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector(re); + poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + re); } static inline void -compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector ( +compute_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ( *a_as_ntt)[2U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *r_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_1, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[2U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result[2U]; KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, - result[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + result[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for ( size_t i0 = (size_t)0U; i0 < core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)2U, a_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [2U], Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [2U], size_t); i0++) { size_t i1 = i0; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *row = a_as_ntt[i1]; for ( size_t i = (size_t)0U; @@ -7085,62 +7261,65 @@ compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t( core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)2U, row, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *a_element = &row[j]; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - a_element, &r_as_ntt[j]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + a_element, &r_as_ntt[j]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( &result[i1], &product); } - invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( &result[i1]); - add_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + add_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &result[i1], &error_1[i1]); } memcpy( ret, result, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -compute_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_2size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +compute_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *t_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *r_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_2, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *message) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - result = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + result = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - &t_as_ntt[i0], &r_as_ntt[i0]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &t_as_ntt[i0], &r_as_ntt[i0]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( &result, &product);); - invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( &result); result = - add_message_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + add_message_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( error_2, message, result); return result; } static void -compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t_640size_t_10size_t_320size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +compress_then_serialize_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_640size_t_10size_t_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector input[2U], Eurydice_slice out) { for ( @@ -7149,13 +7328,13 @@ compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)2U, input, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = input[i0]; Eurydice_slice uu____0 = Eurydice_slice_subslice( out, @@ -7164,7 +7343,7 @@ compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t .end = (i0 + (size_t)1U) * ((size_t)640U / (size_t)2U)}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); uint8_t ret[320U]; - compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t_320size_t( + compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t_320size_t( &re, ret); core_slice___Slice_T___copy_from_slice( uu____0, @@ -7174,93 +7353,93 @@ compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t } static void -encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( +encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( Eurydice_slice public_key, uint8_t message[32U], Eurydice_slice randomness, uint8_t ret[768U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[2U]; - deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_768size_t_2size_t( + deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_768size_t_2size_t( Eurydice_slice_subslice_to(public_key, (size_t)768U, uint8_t, size_t, Eurydice_slice), t_as_ntt); Eurydice_slice seed = Eurydice_slice_subslice_from( public_key, (size_t)768U, uint8_t, size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[2U][2U]; uint8_t ret0[34U]; libcrux_ml_kem_utils_into_padded_array___34size_t(seed, ret0); - sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( + sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t( ret0, false, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array___33size_t(randomness, prf_input); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_2size_t__uint8_t + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t__uint8_t uu____1 = - sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_3size_t_192size_t( + sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_3size_t_192size_t( uu____0, 0U); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector r_as_ntt[2U]; memcpy( r_as_ntt, uu____1.fst, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator0 = uu____1.snd; uint8_t uu____2[33U]; memcpy(uu____2, prf_input, (size_t)33U * sizeof(uint8_t)); - __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_2size_t__uint8_t + __libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t__uint8_t uu____3 = - sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_128size_t_2size_t( + sample_ring_element_cbd__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_128size_t_2size_t( uu____2, domain_separator0); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_1[2U]; memcpy( error_1, uu____3.fst, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator = uu____3.snd; prf_input[32U] = domain_separator; uint8_t prf_output[128U]; PRF___2size_t_128size_t( Eurydice_array_to_slice((size_t)33U, prf_input, uint8_t, Eurydice_slice), prf_output); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_2 = - sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_array_to_slice((size_t)128U, prf_output, uint8_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u[2U]; - compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + compute_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( A_transpose, r_as_ntt, error_1, u); uint8_t uu____4[32U]; memcpy(uu____4, message, (size_t)32U * sizeof(uint8_t)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector message_as_ring_element = - deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( uu____4); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - v = compute_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + v = compute_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( t_as_ntt, r_as_ntt, &error_2, &message_as_ring_element); uint8_t ciphertext[768U] = {0U}; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____5[2U]; memcpy( uu____5, u, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t_640size_t_10size_t_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + compress_then_serialize_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_640size_t_10size_t_320size_t( uu____5, Eurydice_array_to_subslice( (size_t)768U, ciphertext, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)640U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____6 = v; - compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t_128size_t( + compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_128size_t( uu____6, Eurydice_array_to_subslice_from((size_t)768U, ciphertext, (size_t)640U, uint8_t, size_t, Eurydice_slice)); @@ -7270,17 +7449,15 @@ encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_funct static inline void kdf__libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t( Eurydice_slice shared_secret, uint8_t ret[32U]) { - uint8_t ret0[32U]; - core_result_Result__uint8_t_32size_t__core_array_TryFromSliceError dst; - Eurydice_slice_to_array2(&dst, shared_secret, Eurydice_slice, uint8_t[32U], - void *); - core_result__core__result__Result_T__E___unwrap__uint8_t_32size_t__core_array_TryFromSliceError( - dst, ret0); - memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); + uint8_t out[32U] = {0U}; + core_slice___Slice_T___copy_from_slice( + Eurydice_array_to_slice((size_t)32U, out, uint8_t, Eurydice_slice), + shared_secret, uint8_t, void *); + memcpy(ret, out, (size_t)32U * sizeof(uint8_t)); } K___libcrux_ml_kem_types_MlKemCiphertext___768size_t___uint8_t_32size_t_ -libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_768size_t_800size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_768size_t_800size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( libcrux_ml_kem_types_MlKemPublicKey____800size_t *public_key, uint8_t randomness[32U]) { uint8_t randomness0[32U]; @@ -7326,7 +7503,7 @@ libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVecto uint8_t uu____3[32U]; memcpy(uu____3, randomness0, (size_t)32U * sizeof(uint8_t)); uint8_t ciphertext[768U]; - encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( + encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( uu____2, uu____3, pseudorandomness, ciphertext); uint8_t uu____4[768U]; memcpy(uu____4, ciphertext, (size_t)768U * sizeof(uint8_t)); @@ -7346,15 +7523,16 @@ libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVecto } static inline void -deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_10size_t( +deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_10size_t( uint8_t *ciphertext, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[2U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u_as_ntt[2U]; KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, - u_as_ntt[i] = ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + u_as_ntt[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len( Eurydice_array_to_slice((size_t)768U, ciphertext, uint8_t, @@ -7375,31 +7553,32 @@ deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_2si LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)10U / (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( + deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( u_bytes); u_as_ntt[i0] = uu____0; - ntt_vector_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( + ntt_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( &u_as_ntt[i0]); } memcpy( ret, u_as_ntt, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline void -deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t( +deserialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_slice secret_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[2U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[2U]; - KRML_MAYBE_FOR2(i, (size_t)0U, (size_t)2U, (size_t)1U, - secret_as_ntt[i] = - ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + KRML_MAYBE_FOR2( + i, (size_t)0U, (size_t)2U, (size_t)1U, + secret_as_ntt[i] = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector();); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(secret_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -7412,9 +7591,9 @@ deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t( .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( secret_bytes); secret_as_ntt[i0] = uu____0; } @@ -7422,55 +7601,58 @@ deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t( ret, secret_as_ntt, (size_t)2U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -compute_message__libcrux_ml_kem_vector_portable_PortableVector_2size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +compute_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *secret_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *u_as_ntt) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - result = ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + result = + ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); KRML_MAYBE_FOR2( i, (size_t)0U, (size_t)2U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - &secret_as_ntt[i0], &u_as_ntt[i0]); - add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &secret_as_ntt[i0], &u_as_ntt[i0]); + add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( &result, &product);); - invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( &result); result = - subtract_reduce__libcrux_ml_kem_vector_portable_PortableVector(v, result); + subtract_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + v, result); return result; } static void -decrypt__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_640size_t_10size_t_4size_t( +decrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_640size_t_10size_t_4size_t( Eurydice_slice secret_key, uint8_t *ciphertext, uint8_t ret[32U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u_as_ntt[2U]; - deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_10size_t( + deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_10size_t( ciphertext, u_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - v = deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + v = deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( Eurydice_array_to_subslice_from((size_t)768U, ciphertext, (size_t)640U, uint8_t, size_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[2U]; - deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + deserialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( secret_key, secret_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector message = - compute_message__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + compute_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( &v, secret_as_ntt, u_as_ntt); uint8_t ret0[32U]; - compress_then_serialize_message__libcrux_ml_kem_vector_portable_PortableVector( + compress_then_serialize_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( message, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } @@ -7484,7 +7666,7 @@ static inline void PRF___2size_t_32size_t(Eurydice_slice input, memcpy(ret, digest, (size_t)32U * sizeof(uint8_t)); } -void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_1632size_t_768size_t_800size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t_800size_t( +void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___libcrux_ml_kem_ind_cca_MlKem_2size_t_1632size_t_768size_t_800size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t_800size_t( libcrux_ml_kem_types_MlKemPrivateKey____1632size_t *private_key, libcrux_ml_kem_types_MlKemCiphertext____768size_t *ciphertext, uint8_t ret[32U]) { @@ -7509,7 +7691,7 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable Eurydice_slice ind_cpa_public_key_hash = uu____2.fst; Eurydice_slice implicit_rejection_value = uu____2.snd; uint8_t decrypted[32U]; - decrypt__libcrux_ml_kem_vector_portable_PortableVector_2size_t_768size_t_640size_t_10size_t_4size_t( + decrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t_768size_t_640size_t_10size_t_4size_t( ind_cpa_secret_key, ciphertext->value, decrypted); uint8_t to_hash0[64U]; libcrux_ml_kem_utils_into_padded_array___64size_t( @@ -7550,7 +7732,7 @@ void libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_Portable uint8_t uu____6[32U]; memcpy(uu____6, decrypted, (size_t)32U * sizeof(uint8_t)); uint8_t expected_ciphertext[768U]; - encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( + encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___2size_t___2size_t_768size_t_768size_t_640size_t_128size_t_10size_t_4size_t_320size_t_3size_t_192size_t_2size_t_128size_t( uu____5, uu____6, pseudorandomness, expected_ciphertext); Eurydice_slice uu____7 = libcrux_ml_kem_types___core__convert__AsRef__Slice_u8___for_libcrux_ml_kem__types__MlKemCiphertext_SIZE___1__as_ref___768size_t( diff --git a/libcrux-ml-kem/c/libcrux_mlkem_portable.h b/libcrux-ml-kem/c/libcrux_mlkem_portable.h index a7e7cef8..68b2d4d5 100644 --- a/libcrux-ml-kem/c/libcrux_mlkem_portable.h +++ b/libcrux-ml-kem/c/libcrux_mlkem_portable.h @@ -31,284 +31,306 @@ extern const uint8_t libcrux_ml_kem_vector_rej_sample_table_REJECTION_SAMPLE_SHUFFLE_TABLE[256U] [16U]; -typedef struct libcrux_ml_kem_vector_portable_PortableVector_s { +typedef struct libcrux_ml_kem_vector_portable_vector_type_PortableVector_s { int16_t elements[16U]; -} libcrux_ml_kem_vector_portable_PortableVector; +} libcrux_ml_kem_vector_portable_vector_type_PortableVector; -libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_zero(void); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_vector_type_zero(void); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO( void); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_from_i16_array(Eurydice_slice array); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_vector_type_from_i16_array(Eurydice_slice array); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___from_i16_array( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___from_i16_array( Eurydice_slice array); -libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_add( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs); -libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_sub( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_bitwise_and_with_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___bitwise_and_with_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___bitwise_and_with_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_cond_subtract_3329( - libcrux_ml_kem_vector_portable_PortableVector v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___cond_subtract_3329( - libcrux_ml_kem_vector_portable_PortableVector v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___cond_subtract_3329( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v); -#define LIBCRUX_ML_KEM_VECTOR_BARRETT_MULTIPLIER ((int32_t)20159) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_MULTIPLIER \ + ((int32_t)20159) -#define LIBCRUX_ML_KEM_VECTOR_BARRETT_SHIFT ((int32_t)26) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT ((int32_t)26) -#define LIBCRUX_ML_KEM_VECTOR_BARRETT_R \ - ((int32_t)1 << (uint32_t)LIBCRUX_ML_KEM_VECTOR_BARRETT_SHIFT) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_R \ + ((int32_t)1 << (uint32_t) \ + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT) -int16_t libcrux_ml_kem_vector_barrett_reduce_element(int16_t value); +int16_t libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + int16_t value); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_barrett_reduce( - libcrux_ml_kem_vector_portable_PortableVector v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector_portable_PortableVector v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v); -#define LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_SHIFT (16U) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT (16U) -#define LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_R \ - ((int32_t)1 << (uint32_t)LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_SHIFT) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_R \ + ((int32_t)1 << (uint32_t) \ + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT) -int16_t libcrux_ml_kem_vector_montgomery_reduce_element(int32_t value); +int16_t libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + int32_t value); -int16_t libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(int16_t fe, - int16_t fer); +int16_t libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + int16_t fe, int16_t fer); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_montgomery_multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t r); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t r); -uint8_t libcrux_ml_kem_vector_compress_message_coefficient(uint16_t fe); +uint8_t libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( + uint16_t fe); -libcrux_ml_kem_vector_portable_PortableVector libcrux_ml_kem_vector_compress_1( - libcrux_ml_kem_vector_portable_PortableVector v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_compress_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress_1( - libcrux_ml_kem_vector_portable_PortableVector v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v); -uint32_t libcrux_ml_kem_vector_get_n_least_significant_bits(uint8_t n, - uint32_t value); +uint32_t libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( + uint8_t n, uint32_t value); -int16_t libcrux_ml_kem_vector_compress_ciphertext_coefficient( +int16_t libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( uint8_t coefficient_bits, uint16_t fe); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_inv_ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_inv_ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_inv_ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta); typedef struct K___int16_t_int16_t_s { int16_t fst; int16_t snd; } K___int16_t_int16_t; -K___int16_t_int16_t libcrux_ml_kem_vector_ntt_multiply_binomials( +K___int16_t_int16_t libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( K___int16_t_int16_t _, K___int16_t_int16_t _0, int16_t zeta); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_multiply( - libcrux_ml_kem_vector_portable_PortableVector *lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs, int16_t zeta0, - int16_t zeta1, int16_t zeta2, int16_t zeta3); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_multiply( + libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, + int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_multiply( - libcrux_ml_kem_vector_portable_PortableVector *lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs, int16_t zeta0, - int16_t zeta1, int16_t zeta2, int16_t zeta3); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_multiply( + libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, + int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3); -void libcrux_ml_kem_vector_serialize_1( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[2U]); +void libcrux_ml_kem_vector_portable_serialize_serialize_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[2U]); -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_1( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[2U]); +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[2U]); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_1(Eurydice_slice v); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_1(Eurydice_slice v); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_1( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_1( Eurydice_slice a); -void libcrux_ml_kem_vector_serialize_4( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[8U]); +void libcrux_ml_kem_vector_portable_serialize_serialize_4( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[8U]); -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_4( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[8U]); +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_4( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[8U]); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_4(Eurydice_slice bytes); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_4(Eurydice_slice bytes); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_4( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_4( Eurydice_slice a); -void libcrux_ml_kem_vector_serialize_5( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[10U]); +void libcrux_ml_kem_vector_portable_serialize_serialize_5( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[10U]); -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_5( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[10U]); +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_5( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[10U]); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_5(Eurydice_slice bytes); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_5(Eurydice_slice bytes); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_5( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_5( Eurydice_slice a); -void libcrux_ml_kem_vector_serialize_10( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[20U]); +void libcrux_ml_kem_vector_portable_serialize_serialize_10( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[20U]); -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_10( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[20U]); +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_10( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[20U]); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_10(Eurydice_slice bytes); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_10(Eurydice_slice bytes); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_10( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_10( Eurydice_slice a); -void libcrux_ml_kem_vector_serialize_11( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[22U]); +void libcrux_ml_kem_vector_portable_serialize_serialize_11( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[22U]); -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_11( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[22U]); +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_11( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[22U]); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_11(Eurydice_slice bytes); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_11(Eurydice_slice bytes); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_11( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_11( Eurydice_slice a); -void libcrux_ml_kem_vector_serialize_12( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[24U]); +void libcrux_ml_kem_vector_portable_serialize_serialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[24U]); -void libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_12( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[24U]); +void libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[24U]); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_12(Eurydice_slice bytes); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_12(Eurydice_slice bytes); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_12( +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_12( Eurydice_slice a); -size_t libcrux_ml_kem_vector_rej_sample(Eurydice_slice a, - Eurydice_slice result); +size_t libcrux_ml_kem_vector_portable_sampling_rej_sample( + Eurydice_slice a, Eurydice_slice result); size_t -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( Eurydice_slice a, Eurydice_slice out); -libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_portable___core__clone__Clone_for_libcrux_ml_kem__vector__portable__PortableVector___clone( - libcrux_ml_kem_vector_portable_PortableVector *self); +libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_vector_type___core__clone__Clone_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___clone( + libcrux_ml_kem_vector_portable_vector_type_PortableVector *self); typedef struct - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_s { - libcrux_ml_kem_vector_portable_PortableVector coefficients[16U]; -} libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_s { + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficients[16U]; +} libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector; #if defined(__cplusplus) } diff --git a/libcrux-ml-kem/c/libcrux_sha3_libcrux_ml_kem.h b/libcrux-ml-kem/c/libcrux_sha3_libcrux_ml_kem.h index 4627e4a1..99955263 100644 --- a/libcrux-ml-kem/c/libcrux_sha3_libcrux_ml_kem.h +++ b/libcrux-ml-kem/c/libcrux_sha3_libcrux_ml_kem.h @@ -1,8 +1,8 @@ /* This file was generated by KaRaMeL - KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../c.yaml - ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 409fe455 + KaRaMeL invocation: /home/karthik/eurydice/eurydice --config ../c.yaml + ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: f09228ef KaRaMeL + version: 42a43169 */ #ifndef __libcrux_sha3_libcrux_ml_kem_H From 9c15edaadf32ebd3c58a0d4a66a7143feccdb026 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 15:39:23 +0200 Subject: [PATCH 51/53] install cargo hack on ci --- .github/workflows/mlkem.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/mlkem.yml b/.github/workflows/mlkem.yml index 63bb5b04..8f7bc084 100644 --- a/.github/workflows/mlkem.yml +++ b/.github/workflows/mlkem.yml @@ -40,6 +40,7 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: taiki-e/install-action@cargo-hack - name: Update dependencies run: cargo update From 58c79cd4014a6fce4d8c2d4c7414bdc26ae39042 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 15:48:06 +0200 Subject: [PATCH 52/53] ci --- .github/workflows/mlkem.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mlkem.yml b/.github/workflows/mlkem.yml index 8f7bc084..741c2230 100644 --- a/.github/workflows/mlkem.yml +++ b/.github/workflows/mlkem.yml @@ -48,10 +48,10 @@ jobs: - run: echo "RUST_TARGET_FLAG=" > $GITHUB_ENV if: ${{ matrix.bits == 64 }} - - run: echo 'EXCLUDE_FEATURES="--exclude-features simd256"' > $GITHUB_ENV + - run: echo 'EXCLUDE_FEATURES=--exclude-features simd256' > $GITHUB_ENV if: ${{ matrix.os == 'macos-latest' }} - - run: echo 'EXCLUDE_FEATURES="--exclude-features simd128"' > $GITHUB_ENV + - run: echo 'EXCLUDE_FEATURES=--exclude-features simd128' > $GITHUB_ENV if: ${{ matrix.os != 'macos-latest' }} - name: 🛠️ Setup Rust Nightly From 43cab0a26ca72505eb9bb370b7a0f606731a7960 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 28 Jun 2024 16:21:48 +0200 Subject: [PATCH 53/53] more updates --- .github/workflows/mlkem.yml | 4 +- libcrux-ml-kem/c.sh | 4 +- libcrux-ml-kem/cg.yaml | 45 - libcrux-ml-kem/cg/README.md | 2 +- libcrux-ml-kem/cg/eurydice_glue.h | 7 - libcrux-ml-kem/cg/karamel/target.h | 188 -- libcrux-ml-kem/cg/libcrux_core.h | 4 +- libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h | 617 ++-- libcrux-ml-kem/cg/libcrux_mlkem768_portable.h | 2741 +++++++++-------- libcrux-ml-kem/cg/libcrux_sha3_avx2.h | 123 +- libcrux-ml-kem/cg/libcrux_sha3_portable.h | 195 +- 11 files changed, 1953 insertions(+), 1977 deletions(-) diff --git a/.github/workflows/mlkem.yml b/.github/workflows/mlkem.yml index 741c2230..ca57fcc6 100644 --- a/.github/workflows/mlkem.yml +++ b/.github/workflows/mlkem.yml @@ -158,14 +158,16 @@ jobs: cargo test --features kyber --verbose $RUST_TARGET_FLAG - name: 🏃🏻‍♀️ Cargo Check Features + if: ${{ matrix.bits == 64 }} run: | cargo clean cargo hack check --feature-powerset $EXCLUDE_FEATURES --verbose --no-dev-deps $RUST_TARGET_FLAG - name: 🏃🏻‍♀️ Cargo Test Features + if: ${{ matrix.bits == 64 }} run: | cargo clean - cargo hack test --each-feature $EXCLUDE_FEATURES --verbose --no-dev-deps $RUST_TARGET_FLAG + cargo hack test --each-feature $EXCLUDE_FEATURES --verbose $RUST_TARGET_FLAG benchmarks: strategy: diff --git a/libcrux-ml-kem/c.sh b/libcrux-ml-kem/c.sh index ffed1c80..1299cf49 100755 --- a/libcrux-ml-kem/c.sh +++ b/libcrux-ml-kem/c.sh @@ -21,6 +21,7 @@ out=c glue=$EURYDICE_HOME/include/eurydice_glue.h features="--cargo-arg=--features=pre-verification" eurydice_glue=1 +unrolling=16 # Parse command line arguments. all_args=("$@") @@ -35,6 +36,7 @@ while [ $# -gt 0 ]; do --glue) glue="$2"; shift ;; --mlkem768) features="${features} --cargo-arg=--no-default-features --cargo-arg=--features=mlkem768" ;; --no-glue) eurydice_glue=0 ;; + --no-unrolling) unrolling=0 ;; esac shift done @@ -72,7 +74,7 @@ if [[ "$clean" = 1 ]]; then fi echo "Running eurydice ..." -$EURYDICE_HOME/eurydice --config ../$config ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc +$EURYDICE_HOME/eurydice --config ../$config -funroll-loops $unrolling ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc if [[ "$eurydice_glue" = 1 ]]; then cp $EURYDICE_HOME/include/eurydice_glue.h . fi diff --git a/libcrux-ml-kem/cg.yaml b/libcrux-ml-kem/cg.yaml index d4b5be5a..f7833c76 100644 --- a/libcrux-ml-kem/cg.yaml +++ b/libcrux-ml-kem/cg.yaml @@ -48,50 +48,6 @@ files: monomorphizations_using: - [libcrux_sha3, "*"] - # Common parts of SHA3 (this catches stuff that hasn't matched above). Must - # # come after the (more precise) patterns above concerning platform-specific hash_functions - # - name: libcrux_sha3_internal - # api: - # patterns: - # - [libcrux_sha3, "*"] - # monomorphizations_of: - # - [libcrux_sha3, "*"] - # monomorphizations_using: - # - [libcrux_sha3, "*"] - # inline_static: true - - # MLKEM: HASH FUNCTIONS (as used by mlkem) - - # - name: libcrux_mlkem_avx2 - # api: - # - [libcrux_ml_kem, vector, avx2, "*"] - # - [libcrux_ml_kem, hash_functions, avx2, "*"] - # private: - # monomorphizations_using: - # - [libcrux_ml_kem, vector, avx2, "*"] - # - [libcrux_ml_kem, hash_functions, avx2, "*"] - # monomorphizations_of: - # - [libcrux_ml_kem, vector, avx2, "*"] - # - [libcrux_ml_kem, hash_functions, avx2, "*"] - - # # This covers slightly more than the two bundles above, but this greatly - # # simplifies our lives. - # - name: libcrux_mlkem_portable - # inline_static: true - # api: - # patterns: - # - [libcrux_ml_kem, vector, "*"] - # - [libcrux_ml_kem, hash_functions, portable, "*"] - # - [ libcrux_ml_kem, polynomial, "*" ] - # monomorphizations_using: - # - [ libcrux_ml_kem, polynomial, "*" ] - # - [libcrux_ml_kem, vector, "*"] - # - [libcrux_ml_kem, hash_functions, portable, "*"] - # monomorphizations_of: - # - [ libcrux_ml_kem, polynomial, "*" ] - # - [libcrux_ml_kem, vector, "*"] - # - [libcrux_ml_kem, hash_functions, portable, "*"] - # MLKEM: MISC NON-ARCHITECTURE SPECIFIC HEADERS - name: libcrux_core inline_static: true @@ -139,7 +95,6 @@ files: - [libcrux_ml_kem, "*"] - [libcrux_ml_kem, vector, "*"] - [libcrux_ml_kem, hash_functions, portable, "*"] - # - [libcrux_ml_kem, polynomial, "*" ] - [libcrux_ml_kem, mlkem768, portable, "*"] - [libcrux_ml_kem, ind_cca, instantiations, portable, "*"] monomorphizations_of: diff --git a/libcrux-ml-kem/cg/README.md b/libcrux-ml-kem/cg/README.md index f5a975b9..b18d4228 100644 --- a/libcrux-ml-kem/cg/README.md +++ b/libcrux-ml-kem/cg/README.md @@ -11,7 +11,7 @@ While running the commands separately is possible, it is not recommended because the script sets all necessary configuration flags. ```bash -./c.sh --config cg.yaml --out cg --mlkem768 --no-glue +./c.sh --config cg.yaml --out cg --mlkem768 --no-glue --no-unrolling ``` ## Build diff --git a/libcrux-ml-kem/cg/eurydice_glue.h b/libcrux-ml-kem/cg/eurydice_glue.h index 9f42825d..ec6d47b7 100644 --- a/libcrux-ml-kem/cg/eurydice_glue.h +++ b/libcrux-ml-kem/cg/eurydice_glue.h @@ -129,13 +129,6 @@ static inline uint8_t core_num__u8_6__wrapping_sub(uint8_t x, uint8_t y) { return x - y; } -// static inline uint8_t Eurydice_bitand_pv_u8(uint8_t *p, uint8_t v) { -// return (*p) & v; -// } -// static inline uint8_t Eurydice_shr_pv_u8(uint8_t *p, int32_t v) { -// return (*p) >> v; -// } - // ITERATORS #define Eurydice_range_iter_next(iter_ptr, t, ret_t) \ diff --git a/libcrux-ml-kem/cg/karamel/target.h b/libcrux-ml-kem/cg/karamel/target.h index 65a62197..804507b8 100644 --- a/libcrux-ml-kem/cg/karamel/target.h +++ b/libcrux-ml-kem/cg/karamel/target.h @@ -4,8 +4,6 @@ #ifndef __KRML_TARGET_H #define __KRML_TARGET_H -/* For "bare" targets that do not have a C stdlib, the user might want to use - * [-add-early-include '"mydefinitions.h"'] and override these. */ #ifndef KRML_HOST_PRINTF # define KRML_HOST_PRINTF printf #endif @@ -23,190 +21,4 @@ # define KRML_HOST_EXIT exit #endif -/* Macros for prettier unrolling of loops */ -#define KRML_LOOP1(i, n, x) { \ - x \ - i += n; \ - (void) i; \ -} - -#define KRML_LOOP2(i, n, x) \ - KRML_LOOP1(i, n, x) \ - KRML_LOOP1(i, n, x) - -#define KRML_LOOP3(i, n, x) \ - KRML_LOOP2(i, n, x) \ - KRML_LOOP1(i, n, x) - -#define KRML_LOOP4(i, n, x) \ - KRML_LOOP2(i, n, x) \ - KRML_LOOP2(i, n, x) - -#define KRML_LOOP5(i, n, x) \ - KRML_LOOP4(i, n, x) \ - KRML_LOOP1(i, n, x) - -#define KRML_LOOP6(i, n, x) \ - KRML_LOOP4(i, n, x) \ - KRML_LOOP2(i, n, x) - -#define KRML_LOOP7(i, n, x) \ - KRML_LOOP4(i, n, x) \ - KRML_LOOP3(i, n, x) - -#define KRML_LOOP8(i, n, x) \ - KRML_LOOP4(i, n, x) \ - KRML_LOOP4(i, n, x) - -#define KRML_LOOP9(i, n, x) \ - KRML_LOOP8(i, n, x) \ - KRML_LOOP1(i, n, x) - -#define KRML_LOOP10(i, n, x) \ - KRML_LOOP8(i, n, x) \ - KRML_LOOP2(i, n, x) - -#define KRML_LOOP11(i, n, x) \ - KRML_LOOP8(i, n, x) \ - KRML_LOOP3(i, n, x) - -#define KRML_LOOP12(i, n, x) \ - KRML_LOOP8(i, n, x) \ - KRML_LOOP4(i, n, x) - -#define KRML_LOOP13(i, n, x) \ - KRML_LOOP8(i, n, x) \ - KRML_LOOP5(i, n, x) - -#define KRML_LOOP14(i, n, x) \ - KRML_LOOP8(i, n, x) \ - KRML_LOOP6(i, n, x) - -#define KRML_LOOP15(i, n, x) \ - KRML_LOOP8(i, n, x) \ - KRML_LOOP7(i, n, x) - -#define KRML_LOOP16(i, n, x) \ - KRML_LOOP8(i, n, x) \ - KRML_LOOP8(i, n, x) - -#define KRML_UNROLL_FOR(i, z, n, k, x) \ - do { \ - uint32_t i = z; \ - KRML_LOOP##n(i, k, x) \ - } while (0) - -#define KRML_ACTUAL_FOR(i, z, n, k, x) \ - do { \ - for (uint32_t i = z; i < n; i += k) { \ - x \ - } \ - } while (0) - -#ifndef KRML_UNROLL_MAX -# define KRML_UNROLL_MAX 0 -#endif - -/* 1 is the number of loop iterations, i.e. (n - z)/k as evaluated by krml */ -#if 0 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR0(i, z, n, k, x) -#else -# define KRML_MAYBE_FOR0(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 1 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR1(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 1, k, x) -#else -# define KRML_MAYBE_FOR1(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 2 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR2(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 2, k, x) -#else -# define KRML_MAYBE_FOR2(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 3 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR3(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 3, k, x) -#else -# define KRML_MAYBE_FOR3(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 4 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR4(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 4, k, x) -#else -# define KRML_MAYBE_FOR4(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 5 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR5(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 5, k, x) -#else -# define KRML_MAYBE_FOR5(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 6 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR6(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 6, k, x) -#else -# define KRML_MAYBE_FOR6(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 7 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR7(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 7, k, x) -#else -# define KRML_MAYBE_FOR7(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 8 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR8(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 8, k, x) -#else -# define KRML_MAYBE_FOR8(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 9 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR9(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 9, k, x) -#else -# define KRML_MAYBE_FOR9(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 10 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR10(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 10, k, x) -#else -# define KRML_MAYBE_FOR10(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 11 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR11(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 11, k, x) -#else -# define KRML_MAYBE_FOR11(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 12 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR12(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 12, k, x) -#else -# define KRML_MAYBE_FOR12(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 13 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR13(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 13, k, x) -#else -# define KRML_MAYBE_FOR13(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 14 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR14(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 14, k, x) -#else -# define KRML_MAYBE_FOR14(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 15 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR15(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 15, k, x) -#else -# define KRML_MAYBE_FOR15(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif - -#if 16 <= KRML_UNROLL_MAX -# define KRML_MAYBE_FOR16(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 16, k, x) -#else -# define KRML_MAYBE_FOR16(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) -#endif #endif diff --git a/libcrux-ml-kem/cg/libcrux_core.h b/libcrux-ml-kem/cg/libcrux_core.h index 4c13971d..d822e564 100644 --- a/libcrux-ml-kem/cg/libcrux_core.h +++ b/libcrux-ml-kem/cg/libcrux_core.h @@ -1,8 +1,8 @@ /* This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml - ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 42a43169 + -funroll-loops 0 ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: + KaRaMeL version: 42a43169 */ #ifndef __libcrux_core_H diff --git a/libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h b/libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h index 26c3be60..26dd84ea 100644 --- a/libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h +++ b/libcrux-ml-kem/cg/libcrux_mlkem768_avx2.h @@ -1,8 +1,8 @@ /* This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml - ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 42a43169 + -funroll-loops 0 ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem768_avx2_H @@ -676,10 +676,10 @@ libcrux_ml_kem_vector_avx2_serialize_deserialize_1(Eurydice_slice bytes) { libcrux_intrinsics_avx2_mm256_set_epi16( (int16_t)1 << 8U, (int16_t)1 << 9U, (int16_t)1 << 10U, (int16_t)1 << 11U, (int16_t)1 << 12U, (int16_t)1 << 13U, - (int16_t)1 << 14U, (int16_t)1 << 15U, (int16_t)1 << 8U, + (int16_t)1 << 14U, (int16_t)-32768, (int16_t)1 << 8U, (int16_t)1 << 9U, (int16_t)1 << 10U, (int16_t)1 << 11U, (int16_t)1 << 12U, (int16_t)1 << 13U, (int16_t)1 << 14U, - (int16_t)1 << 15U); + (int16_t)-32768); core_core_arch_x86___m256i coefficients_in_msb = libcrux_intrinsics_avx2_mm256_mullo_epi16(coefficients, shift_lsb_to_msb); return libcrux_intrinsics_avx2_mm256_srli_epi16( @@ -1920,14 +1920,15 @@ libcrux_ml_kem_ntt_ntt_at_layer_3__libcrux_ml_kem_vector_avx2_SIMD256Vector( libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector *re, size_t _layer, size_t _initial_coefficient_bound) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] + (size_t)1U; - core_core_arch_x86___m256i uu____0 = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ntt_layer_3_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); - re->coefficients[round] = uu____0;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] + (size_t)1U; + core_core_arch_x86___m256i uu____0 = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ntt_layer_3_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); + re->coefficients[round] = uu____0; + } } __attribute__((target("avx2"))) @@ -1937,16 +1938,18 @@ libcrux_ml_kem_ntt_ntt_at_layer_2__libcrux_ml_kem_vector_avx2_SIMD256Vector( libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector *re, size_t _layer, size_t _initial_coefficient_bound) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] + (size_t)1U; - core_core_arch_x86___m256i uu____0 = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ntt_layer_2_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + - (size_t)1U]); - re->coefficients[round] = uu____0; zeta_i[0U] = zeta_i[0U] + (size_t)1U;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] + (size_t)1U; + core_core_arch_x86___m256i uu____0 = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ntt_layer_2_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + + (size_t)1U]); + re->coefficients[round] = uu____0; + zeta_i[0U] = zeta_i[0U] + (size_t)1U; + } } __attribute__((target("avx2"))) @@ -1956,20 +1959,22 @@ libcrux_ml_kem_ntt_ntt_at_layer_1__libcrux_ml_kem_vector_avx2_SIMD256Vector( libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector *re, size_t _layer, size_t _initial_coefficient_bound) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] + (size_t)1U; - core_core_arch_x86___m256i uu____0 = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ntt_layer_1_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + - (size_t)1U], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + - (size_t)2U], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + - (size_t)3U]); - re->coefficients[round] = uu____0; zeta_i[0U] = zeta_i[0U] + (size_t)3U;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] + (size_t)1U; + core_core_arch_x86___m256i uu____0 = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___ntt_layer_1_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + + (size_t)1U], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + + (size_t)2U], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + + (size_t)3U]); + re->coefficients[round] = uu____0; + zeta_i[0U] = zeta_i[0U] + (size_t)3U; + } } __attribute__((target("avx2"))) @@ -2019,10 +2024,10 @@ libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u__libcrux_ml_kem_vector_avx2 ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector u_as_ntt[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - u_as_ntt[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + u_as_ntt[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); + } for (size_t i = (size_t)0U; i < core_slice___Slice_T___len( Eurydice_array_to_slice((size_t)1088U, ciphertext, uint8_t, @@ -2294,10 +2299,10 @@ libcrux_ml_kem_ind_cpa_deserialize_secret_key__libcrux_ml_kem_vector_avx2_SIMD25 ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector secret_as_ntt[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - secret_as_ntt[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + secret_as_ntt[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); + } for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(secret_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -2384,20 +2389,22 @@ libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_1__libcrux_ml_kem_vector_avx2_SIMD libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector *re, size_t _layer) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] - (size_t)1U; - core_core_arch_x86___m256i uu____0 = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___inv_ntt_layer_1_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - - (size_t)1U], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - - (size_t)2U], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - - (size_t)3U]); - re->coefficients[round] = uu____0; zeta_i[0U] = zeta_i[0U] - (size_t)3U;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] - (size_t)1U; + core_core_arch_x86___m256i uu____0 = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___inv_ntt_layer_1_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - + (size_t)1U], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - + (size_t)2U], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - + (size_t)3U]); + re->coefficients[round] = uu____0; + zeta_i[0U] = zeta_i[0U] - (size_t)3U; + } } __attribute__((target("avx2"))) @@ -2407,16 +2414,18 @@ libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_2__libcrux_ml_kem_vector_avx2_SIMD libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector *re, size_t _layer) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] - (size_t)1U; - core_core_arch_x86___m256i uu____0 = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___inv_ntt_layer_2_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - - (size_t)1U]); - re->coefficients[round] = uu____0; zeta_i[0U] = zeta_i[0U] - (size_t)1U;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] - (size_t)1U; + core_core_arch_x86___m256i uu____0 = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___inv_ntt_layer_2_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - + (size_t)1U]); + re->coefficients[round] = uu____0; + zeta_i[0U] = zeta_i[0U] - (size_t)1U; + } } __attribute__((target("avx2"))) @@ -2426,14 +2435,15 @@ libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_3__libcrux_ml_kem_vector_avx2_SIMD libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector *re, size_t _layer) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] - (size_t)1U; - core_core_arch_x86___m256i uu____0 = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___inv_ntt_layer_3_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); - re->coefficients[round] = uu____0;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] - (size_t)1U; + core_core_arch_x86___m256i uu____0 = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___inv_ntt_layer_3_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); + re->coefficients[round] = uu____0; + } } __attribute__((target("avx2"))) @@ -2545,14 +2555,15 @@ libcrux_ml_kem_matrix_compute_message__libcrux_ml_kem_vector_avx2_SIMD256Vector_ libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector result = libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector - product = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_avx2_SIMD256Vector( - &secret_as_ntt[i0], &u_as_ntt[i0]); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_avx2_SIMD256Vector_3size_t( - &result, &product);); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector + product = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_avx2_SIMD256Vector( + &secret_as_ntt[i0], &u_as_ntt[i0]); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_avx2_SIMD256Vector_3size_t( + &result, &product); + } libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_avx2_SIMD256Vector_3size_t( &result); result = @@ -2597,26 +2608,27 @@ libcrux_ml_kem_serialize_compress_then_serialize_message__libcrux_ml_kem_vector_ re, uint8_t ret[32U]) { uint8_t serialized[32U] = {0U}; - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t i0 = i; - core_core_arch_x86___m256i coefficient = - libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_avx2_SIMD256Vector( - re.coefficients[i0]); - core_core_arch_x86___m256i coefficient_compressed = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___compress_1( - coefficient); - uint8_t bytes[2U]; - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___serialize_1( - coefficient_compressed, bytes); - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)32U, serialized, - (CLITERAL(core_ops_range_Range__size_t){ - .start = (size_t)2U * i0, .end = (size_t)2U * i0 + (size_t)2U}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice( - uu____0, - Eurydice_array_to_slice((size_t)2U, bytes, uint8_t, Eurydice_slice), - uint8_t, void *);); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t i0 = i; + core_core_arch_x86___m256i coefficient = + libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_avx2_SIMD256Vector( + re.coefficients[i0]); + core_core_arch_x86___m256i coefficient_compressed = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___compress_1( + coefficient); + uint8_t bytes[2U]; + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___serialize_1( + coefficient_compressed, bytes); + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)32U, serialized, + (CLITERAL(core_ops_range_Range__size_t){ + .start = (size_t)2U * i0, .end = (size_t)2U * i0 + (size_t)2U}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + core_slice___Slice_T___copy_from_slice( + uu____0, + Eurydice_array_to_slice((size_t)2U, bytes, uint8_t, Eurydice_slice), + uint8_t, void *); + } memcpy(ret, serialized, (size_t)32U * sizeof(uint8_t)); } @@ -2712,10 +2724,10 @@ libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vecto ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector deserialized_pk[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - deserialized_pk[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + deserialized_pk[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); + } for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -2756,10 +2768,10 @@ libcrux_ml_kem_matrix_sample_matrix_A_closure__libcrux_ml_kem_vector_avx2_SIMD25 ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector ret0[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - ret0[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + ret0[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); + } memcpy( ret, ret0, (size_t)3U * @@ -2817,40 +2829,43 @@ static inline bool libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_avx2_SIMD256Vector_3size_t_504size_t( uint8_t randomness[3U][504U], size_t *sampled_coefficients, int16_t (*out)[272U]) { - KRML_MAYBE_FOR3( - i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; - for (size_t i = (size_t)0U; i < (size_t)504U / (size_t)24U; i++) { - size_t r = i; - if (sampled_coefficients[i1] < - LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)504U, randomness[i1], - (CLITERAL(core_ops_range_Range__size_t){ - .start = r * (size_t)24U, - .end = r * (size_t)24U + (size_t)24U}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - size_t sampled = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___rej_sample( - uu____0, - Eurydice_array_to_subslice( - (size_t)272U, out[i1], - (CLITERAL(core_ops_range_Range__size_t){ - .start = sampled_coefficients[i1], - .end = sampled_coefficients[i1] + (size_t)16U}), - int16_t, core_ops_range_Range__size_t, Eurydice_slice)); - size_t uu____1 = i1; - sampled_coefficients[uu____1] = - sampled_coefficients[uu____1] + sampled; - } - }); - bool done = true; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - if (sampled_coefficients[i0] >= + for (size_t i0 = (size_t)0U; i0 < (size_t)3U; i0++) { + size_t i1 = i0; + for (size_t i = (size_t)0U; i < (size_t)504U / (size_t)24U; i++) { + size_t r = i; + if (sampled_coefficients[i1] < LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { - sampled_coefficients[i0] = - LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; - } else { done = false; }); + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)504U, randomness[i1], + (CLITERAL(core_ops_range_Range__size_t){ + .start = r * (size_t)24U, + .end = r * (size_t)24U + (size_t)24U}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + size_t sampled = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___rej_sample( + uu____0, + Eurydice_array_to_subslice( + (size_t)272U, out[i1], + (CLITERAL(core_ops_range_Range__size_t){ + .start = sampled_coefficients[i1], + .end = sampled_coefficients[i1] + (size_t)16U}), + int16_t, core_ops_range_Range__size_t, Eurydice_slice)); + size_t uu____1 = i1; + sampled_coefficients[uu____1] = sampled_coefficients[uu____1] + sampled; + } + } + } + bool done = true; + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + if (sampled_coefficients[i0] >= + LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { + sampled_coefficients[i0] = + LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; + } else { + done = false; + } + } return done; } @@ -2886,40 +2901,43 @@ static inline bool libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_avx2_SIMD256Vector_3size_t_168size_t( uint8_t randomness[3U][168U], size_t *sampled_coefficients, int16_t (*out)[272U]) { - KRML_MAYBE_FOR3( - i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; - for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)24U; i++) { - size_t r = i; - if (sampled_coefficients[i1] < - LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)168U, randomness[i1], - (CLITERAL(core_ops_range_Range__size_t){ - .start = r * (size_t)24U, - .end = r * (size_t)24U + (size_t)24U}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - size_t sampled = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___rej_sample( - uu____0, - Eurydice_array_to_subslice( - (size_t)272U, out[i1], - (CLITERAL(core_ops_range_Range__size_t){ - .start = sampled_coefficients[i1], - .end = sampled_coefficients[i1] + (size_t)16U}), - int16_t, core_ops_range_Range__size_t, Eurydice_slice)); - size_t uu____1 = i1; - sampled_coefficients[uu____1] = - sampled_coefficients[uu____1] + sampled; - } - }); - bool done = true; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - if (sampled_coefficients[i0] >= + for (size_t i0 = (size_t)0U; i0 < (size_t)3U; i0++) { + size_t i1 = i0; + for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)24U; i++) { + size_t r = i; + if (sampled_coefficients[i1] < LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { - sampled_coefficients[i0] = - LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; - } else { done = false; }); + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)168U, randomness[i1], + (CLITERAL(core_ops_range_Range__size_t){ + .start = r * (size_t)24U, + .end = r * (size_t)24U + (size_t)24U}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + size_t sampled = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___rej_sample( + uu____0, + Eurydice_array_to_subslice( + (size_t)272U, out[i1], + (CLITERAL(core_ops_range_Range__size_t){ + .start = sampled_coefficients[i1], + .end = sampled_coefficients[i1] + (size_t)16U}), + int16_t, core_ops_range_Range__size_t, Eurydice_slice)); + size_t uu____1 = i1; + sampled_coefficients[uu____1] = sampled_coefficients[uu____1] + sampled; + } + } + } + bool done = true; + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + if (sampled_coefficients[i0] >= + LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { + sampled_coefficients[i0] = + LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; + } else { + done = false; + } + } return done; } @@ -2997,11 +3015,11 @@ libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_avx2_SIMD256Vecto memcpy(uu____3, out, (size_t)3U * sizeof(int16_t[272U])); libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector ret0[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - ret0[i] = - libcrux_ml_kem_sampling_sample_from_xof_closure__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t( - uu____3[i]);); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + ret0[i] = + libcrux_ml_kem_sampling_sample_from_xof_closure__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t( + uu____3[i]); + } memcpy( ret, ret0, (size_t)3U * @@ -3017,45 +3035,50 @@ libcrux_ml_kem_matrix_sample_matrix_A__libcrux_ml_kem_vector_avx2_SIMD256Vector_ ret[3U][3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector A_transpose[3U][3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - libcrux_ml_kem_matrix_sample_matrix_A_closure__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t( - i, A_transpose[i]);); - KRML_MAYBE_FOR3( - i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; - uint8_t uu____0[34U]; - memcpy(uu____0, seed, (size_t)34U * sizeof(uint8_t)); - uint8_t seeds[3U][34U]; KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - memcpy(seeds[i], uu____0, (size_t)34U * sizeof(uint8_t));); - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t j = i; - seeds[j][32U] = (uint8_t)i1; seeds[j][33U] = (uint8_t)j;); - uint8_t uu____1[3U][34U]; - memcpy(uu____1, seeds, (size_t)3U * sizeof(uint8_t[34U])); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + libcrux_ml_kem_matrix_sample_matrix_A_closure__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t( + i, A_transpose[i]); + } + for (size_t i0 = (size_t)0U; i0 < (size_t)3U; i0++) { + size_t i1 = i0; + uint8_t uu____0[34U]; + memcpy(uu____0, seed, (size_t)34U * sizeof(uint8_t)); + uint8_t seeds[3U][34U]; + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + memcpy(seeds[i], uu____0, (size_t)34U * sizeof(uint8_t)); + } + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t j = i; + seeds[j][32U] = (uint8_t)i1; + seeds[j][33U] = (uint8_t)j; + } + uint8_t uu____1[3U][34U]; + memcpy(uu____1, seeds, (size_t)3U * sizeof(uint8_t[34U])); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector + sampled[3U]; + libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t( + uu____1, sampled); + for ( + size_t i = (size_t)0U; + i < + core_slice___Slice_T___len( + Eurydice_array_to_slice( + (size_t)3U, sampled, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector, + Eurydice_slice), + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector, + size_t); + i++) { + size_t j = i; libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector - sampled[3U]; - libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_avx2_SIMD256Vector_libcrux_ml_kem_hash_functions_avx2_Simd256Hash_3size_t( - uu____1, sampled); - for ( - size_t i = (size_t)0U; - i < - core_slice___Slice_T___len( - Eurydice_array_to_slice( - (size_t)3U, sampled, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector, - Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector, - size_t); - i++) { - size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector - sample = sampled[j]; - if (transpose) { - A_transpose[j][i1] = sample; - } else { - A_transpose[i1][j] = sample; - } - }); + sample = sampled[j]; + if (transpose) { + A_transpose[j][i1] = sample; + } else { + A_transpose[i1][j] = sample; + } + } + } memcpy( ret, A_transpose, (size_t)3U * @@ -3268,32 +3291,35 @@ libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_avx2_SI uint8_t prf_input[33U], uint8_t domain_separator) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector re_as_ntt[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - re_as_ntt[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + re_as_ntt[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); + } uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[3U][33U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - memcpy(prf_inputs[i], uu____0, (size_t)33U * sizeof(uint8_t));); - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - prf_inputs[i0][32U] = domain_separator; - domain_separator = (uint32_t)domain_separator + 1U;); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + memcpy(prf_inputs[i], uu____0, (size_t)33U * sizeof(uint8_t)); + } + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + prf_inputs[i0][32U] = domain_separator; + domain_separator = (uint32_t)domain_separator + 1U; + } uint8_t prf_outputs[3U][128U]; libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__avx2__Simd256Hash___PRFxN___3size_t_128size_t( prf_inputs, prf_outputs); - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector - uu____1 = - libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_avx2_SIMD256Vector_2size_t( - Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], - uint8_t, Eurydice_slice)); - re_as_ntt[i0] = uu____1; - libcrux_ml_kem_ntt_ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_avx2_SIMD256Vector( - &re_as_ntt[i0]);); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector + uu____1 = + libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_avx2_SIMD256Vector_2size_t( + Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t, + Eurydice_slice)); + re_as_ntt[i0] = uu____1; + libcrux_ml_kem_ntt_ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_avx2_SIMD256Vector( + &re_as_ntt[i0]); + } libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector uu____2[3U]; memcpy( @@ -3325,30 +3351,33 @@ libcrux_ml_kem_ind_cpa_sample_ring_element_cbd__libcrux_ml_kem_vector_avx2_SIMD2 uint8_t prf_input[33U], uint8_t domain_separator) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector error_1[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - error_1[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + error_1[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); + } uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[3U][33U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - memcpy(prf_inputs[i], uu____0, (size_t)33U * sizeof(uint8_t));); - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - prf_inputs[i0][32U] = domain_separator; - domain_separator = (uint32_t)domain_separator + 1U;); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + memcpy(prf_inputs[i], uu____0, (size_t)33U * sizeof(uint8_t)); + } + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + prf_inputs[i0][32U] = domain_separator; + domain_separator = (uint32_t)domain_separator + 1U; + } uint8_t prf_outputs[3U][128U]; libcrux_ml_kem_hash_functions_avx2___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__avx2__Simd256Hash___PRFxN___3size_t_128size_t( prf_inputs, prf_outputs); - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector - uu____1 = - libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_avx2_SIMD256Vector_2size_t( - Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], - uint8_t, Eurydice_slice)); - error_1[i0] = uu____1;); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector + uu____1 = + libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_avx2_SIMD256Vector_2size_t( + Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t, + Eurydice_slice)); + error_1[i0] = uu____1; + } libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector uu____2[3U]; memcpy( @@ -3419,10 +3448,10 @@ libcrux_ml_kem_matrix_compute_vector_u__libcrux_ml_kem_vector_avx2_SIMD256Vector ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector result[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - result[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + result[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); + } for ( size_t i0 = (size_t)0U; i0 < @@ -3491,20 +3520,21 @@ libcrux_ml_kem_serialize_deserialize_then_decompress_message__libcrux_ml_kem_vec libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector re = libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t i0 = i; - core_core_arch_x86___m256i coefficient_compressed = - libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___deserialize_1( - Eurydice_array_to_subslice( - (size_t)32U, serialized, - (CLITERAL(core_ops_range_Range__size_t){ - .start = (size_t)2U * i0, - .end = (size_t)2U * i0 + (size_t)2U}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); - core_core_arch_x86___m256i uu____0 = - libcrux_ml_kem_vector_traits_decompress_1__libcrux_ml_kem_vector_avx2_SIMD256Vector( - coefficient_compressed); - re.coefficients[i0] = uu____0;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t i0 = i; + core_core_arch_x86___m256i coefficient_compressed = + libcrux_ml_kem_vector_avx2___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__avx2__SIMD256Vector___deserialize_1( + Eurydice_array_to_subslice( + (size_t)32U, serialized, + (CLITERAL(core_ops_range_Range__size_t){ + .start = (size_t)2U * i0, + .end = (size_t)2U * i0 + (size_t)2U}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); + core_core_arch_x86___m256i uu____0 = + libcrux_ml_kem_vector_traits_decompress_1__libcrux_ml_kem_vector_avx2_SIMD256Vector( + coefficient_compressed); + re.coefficients[i0] = uu____0; + } return re; } @@ -3551,14 +3581,15 @@ libcrux_ml_kem_matrix_compute_ring_element_v__libcrux_ml_kem_vector_avx2_SIMD256 libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector result = libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector - product = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_avx2_SIMD256Vector( - &t_as_ntt[i0], &r_as_ntt[i0]); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_avx2_SIMD256Vector_3size_t( - &result, &product);); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector + product = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_avx2_SIMD256Vector( + &t_as_ntt[i0], &r_as_ntt[i0]); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_avx2_SIMD256Vector_3size_t( + &result, &product); + } libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_avx2_SIMD256Vector_3size_t( &result); result = @@ -4393,10 +4424,10 @@ libcrux_ml_kem_matrix_compute_As_plus_e__libcrux_ml_kem_vector_avx2_SIMD256Vecto ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector result[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - result[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + result[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); + } for ( size_t i0 = (size_t)0U; i0 < @@ -4767,10 +4798,10 @@ libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vecto ret[3U]) { libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_avx2_SIMD256Vector deserialized_pk[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - deserialized_pk[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + deserialized_pk[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_avx2_SIMD256Vector(); + } for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; diff --git a/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h b/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h index 9ed3e89a..f8ee1b1c 100644 --- a/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h +++ b/libcrux-ml-kem/cg/libcrux_mlkem768_portable.h @@ -1,8 +1,8 @@ /* This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml - ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 42a43169 + -funroll-loops 0 ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: + KaRaMeL version: 42a43169 */ #ifndef __libcrux_mlkem768_portable_H @@ -597,13 +597,13 @@ static const uint8_t {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U}}; -typedef struct libcrux_ml_kem_vector_portable_PortableVector_s { +typedef struct libcrux_ml_kem_vector_portable_vector_type_PortableVector_s { int16_t elements[16U]; -} libcrux_ml_kem_vector_portable_PortableVector; +} libcrux_ml_kem_vector_portable_vector_type_PortableVector; -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_zero(void) { - libcrux_ml_kem_vector_portable_PortableVector lit; +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_vector_type_zero(void) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; lit.elements[0U] = (int16_t)0; lit.elements[1U] = (int16_t)0; lit.elements[2U] = (int16_t)0; @@ -623,15 +623,16 @@ libcrux_ml_kem_vector_zero(void) { return lit; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO( void) { - return libcrux_ml_kem_vector_zero(); + return libcrux_ml_kem_vector_portable_vector_type_zero(); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_from_i16_array(Eurydice_slice array) { - libcrux_ml_kem_vector_portable_PortableVector lit; +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_vector_type_from_i16_array( + Eurydice_slice array) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; int16_t ret[16U]; core_result_Result__int16_t_16size_t__core_array_TryFromSliceError dst; Eurydice_slice_to_array2( @@ -648,15 +649,16 @@ libcrux_ml_kem_vector_from_i16_array(Eurydice_slice array) { return lit; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___from_i16_array( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___from_i16_array( Eurydice_slice array) { - return libcrux_ml_kem_vector_from_i16_array(array); + return libcrux_ml_kem_vector_portable_vector_type_from_i16_array(array); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_add(libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -666,16 +668,17 @@ libcrux_ml_kem_vector_add(libcrux_ml_kem_vector_portable_PortableVector lhs, return lhs; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs) { - return libcrux_ml_kem_vector_add(lhs, rhs); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { + return libcrux_ml_kem_vector_portable_arithmetic_add(lhs, rhs); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_sub(libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -685,16 +688,16 @@ libcrux_ml_kem_vector_sub(libcrux_ml_kem_vector_portable_PortableVector lhs, return lhs; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( - libcrux_ml_kem_vector_portable_PortableVector lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs) { - return libcrux_ml_kem_vector_sub(lhs, rhs); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { + return libcrux_ml_kem_vector_portable_arithmetic_sub(lhs, rhs); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -704,15 +707,15 @@ libcrux_ml_kem_vector_multiply_by_constant( return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { - return libcrux_ml_kem_vector_multiply_by_constant(v, c); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { + return libcrux_ml_kem_vector_portable_arithmetic_multiply_by_constant(v, c); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_bitwise_and_with_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -722,15 +725,16 @@ libcrux_ml_kem_vector_bitwise_and_with_constant( return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___bitwise_and_with_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { - return libcrux_ml_kem_vector_bitwise_and_with_constant(v, c); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___bitwise_and_with_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { + return libcrux_ml_kem_vector_portable_arithmetic_bitwise_and_with_constant(v, + c); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_cond_subtract_3329( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { core_ops_range_Range__size_t iter = core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter( (CLITERAL(core_ops_range_Range__size_t){ @@ -753,92 +757,109 @@ libcrux_ml_kem_vector_cond_subtract_3329( } } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___cond_subtract_3329( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_cond_subtract_3329(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___cond_subtract_3329( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_arithmetic_cond_subtract_3329(v); } -#define LIBCRUX_ML_KEM_VECTOR_BARRETT_MULTIPLIER ((int32_t)20159) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_MULTIPLIER \ + ((int32_t)20159) -#define LIBCRUX_ML_KEM_VECTOR_BARRETT_SHIFT ((int32_t)26) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT ((int32_t)26) -#define LIBCRUX_ML_KEM_VECTOR_BARRETT_R \ - ((int32_t)1 << (uint32_t)LIBCRUX_ML_KEM_VECTOR_BARRETT_SHIFT) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_R \ + ((int32_t)1 << (uint32_t) \ + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT) -static inline int16_t libcrux_ml_kem_vector_barrett_reduce_element( +static inline int16_t +libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( int16_t value) { - int32_t t = (int32_t)value * LIBCRUX_ML_KEM_VECTOR_BARRETT_MULTIPLIER + - (LIBCRUX_ML_KEM_VECTOR_BARRETT_R >> 1U); + int32_t t = (int32_t)value * + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_MULTIPLIER + + (LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_R >> 1U); int16_t quotient = - (int16_t)(t >> (uint32_t)LIBCRUX_ML_KEM_VECTOR_BARRETT_SHIFT); + (int16_t)(t >> + (uint32_t) + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_BARRETT_SHIFT); return value - quotient * LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_barrett_reduce( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int16_t uu____0 = - libcrux_ml_kem_vector_barrett_reduce_element(v.elements[i0]); + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[i0]); v.elements[i0] = uu____0; } return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_barrett_reduce(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce(v); } -#define LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_SHIFT (16U) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT (16U) -#define LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_R \ - ((int32_t)1 << (uint32_t)LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_SHIFT) +#define LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_R \ + ((int32_t)1 << (uint32_t) \ + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT) -static inline int16_t libcrux_ml_kem_vector_montgomery_reduce_element( +static inline int16_t +libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( int32_t value) { int32_t k = (int32_t)(int16_t)value * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_INVERSE_OF_MODULUS_MOD_MONTGOMERY_R; int32_t k_times_modulus = (int32_t)(int16_t)k * (int32_t)LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS; - int16_t c = (int16_t)(k_times_modulus >> - (uint32_t)LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_SHIFT); + int16_t c = + (int16_t)(k_times_modulus >> + (uint32_t) + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT); int16_t value_high = - (int16_t)(value >> (uint32_t)LIBCRUX_ML_KEM_VECTOR_MONTGOMERY_SHIFT); + (int16_t)(value >> + (uint32_t) + LIBCRUX_ML_KEM_VECTOR_PORTABLE_ARITHMETIC_MONTGOMERY_SHIFT); return value_high - c; } -static inline int16_t libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( +static inline int16_t +libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( int16_t fe, int16_t fer) { - return libcrux_ml_kem_vector_montgomery_reduce_element((int32_t)fe * - (int32_t)fer); + return libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + (int32_t)fe * (int32_t)fer); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_montgomery_multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t c) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t c) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; int16_t uu____0 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(v.elements[i0], c); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[i0], c); v.elements[i0] = uu____0; } return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t r) { - return libcrux_ml_kem_vector_montgomery_multiply_by_constant(v, r); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t r) { + return libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_by_constant( + v, r); } -static inline uint8_t libcrux_ml_kem_vector_compress_message_coefficient( +static inline uint8_t +libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( uint16_t fe) { int16_t shifted = (int16_t)1664 - (int16_t)fe; int16_t mask = shifted >> 15U; @@ -847,80 +868,92 @@ static inline uint8_t libcrux_ml_kem_vector_compress_message_coefficient( return (uint8_t)(shifted_positive_in_range >> 15U & (int16_t)1); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_compress_1( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_compress_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - uint8_t uu____0 = libcrux_ml_kem_vector_compress_message_coefficient( - (uint16_t)v.elements[i0]); + uint8_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_message_coefficient( + (uint16_t)v.elements[i0]); v.elements[i0] = (int16_t)uu____0; } return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress_1( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_compress_1(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_compress_1(v); } -static inline uint32_t libcrux_ml_kem_vector_get_n_least_significant_bits( +static inline uint32_t +libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( uint8_t n, uint32_t value) { return value & ((1U << (uint32_t)n) - 1U); } -static inline int16_t libcrux_ml_kem_vector_compress_ciphertext_coefficient( +static inline int16_t +libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( uint8_t coefficient_bits, uint16_t fe) { uint64_t compressed = (uint64_t)fe << (uint32_t)coefficient_bits; compressed = compressed + 1664ULL; compressed = compressed * 10321340ULL; compressed = compressed >> 35U; - return (int16_t)libcrux_ml_kem_vector_get_n_least_significant_bits( - coefficient_bits, (uint32_t)compressed); + return (int16_t) + libcrux_ml_kem_vector_portable_arithmetic_get_n_least_significant_bits( + coefficient_bits, (uint32_t)compressed); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { - int16_t t = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[2U], zeta0); + int16_t t = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[2U], zeta0); v.elements[2U] = v.elements[0U] - t; v.elements[0U] = v.elements[0U] + t; - int16_t t0 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[3U], zeta0); + int16_t t0 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[3U], zeta0); v.elements[3U] = v.elements[1U] - t0; v.elements[1U] = v.elements[1U] + t0; - int16_t t1 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[6U], zeta1); + int16_t t1 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[6U], zeta1); v.elements[6U] = v.elements[4U] - t1; v.elements[4U] = v.elements[4U] + t1; - int16_t t2 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[7U], zeta1); + int16_t t2 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[7U], zeta1); v.elements[7U] = v.elements[5U] - t2; v.elements[5U] = v.elements[5U] + t2; - int16_t t3 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)2U], zeta2); + int16_t t3 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)2U], zeta2); v.elements[(size_t)8U + (size_t)2U] = v.elements[(size_t)8U + (size_t)0U] - t3; v.elements[(size_t)8U + (size_t)0U] = v.elements[(size_t)8U + (size_t)0U] + t3; - int16_t t4 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)3U], zeta2); + int16_t t4 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)3U], zeta2); v.elements[(size_t)8U + (size_t)3U] = v.elements[(size_t)8U + (size_t)1U] - t4; v.elements[(size_t)8U + (size_t)1U] = v.elements[(size_t)8U + (size_t)1U] + t4; - int16_t t5 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)6U], zeta3); + int16_t t5 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)6U], zeta3); v.elements[(size_t)8U + (size_t)6U] = v.elements[(size_t)8U + (size_t)4U] - t5; v.elements[(size_t)8U + (size_t)4U] = v.elements[(size_t)8U + (size_t)4U] + t5; - int16_t t6 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)7U], zeta3); + int16_t t6 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)7U], zeta3); v.elements[(size_t)8U + (size_t)7U] = v.elements[(size_t)8U + (size_t)5U] - t6; v.elements[(size_t)8U + (size_t)5U] = @@ -928,53 +961,62 @@ libcrux_ml_kem_vector_ntt_layer_1_step( return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { - return libcrux_ml_kem_vector_ntt_layer_1_step(a, zeta0, zeta1, zeta2, zeta3); + return libcrux_ml_kem_vector_portable_ntt_ntt_layer_1_step(a, zeta0, zeta1, + zeta2, zeta3); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1) { - int16_t t = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[4U], zeta0); + int16_t t = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[4U], zeta0); v.elements[4U] = v.elements[0U] - t; v.elements[0U] = v.elements[0U] + t; - int16_t t0 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[5U], zeta0); + int16_t t0 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[5U], zeta0); v.elements[5U] = v.elements[1U] - t0; v.elements[1U] = v.elements[1U] + t0; - int16_t t1 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[6U], zeta0); + int16_t t1 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[6U], zeta0); v.elements[6U] = v.elements[2U] - t1; v.elements[2U] = v.elements[2U] + t1; - int16_t t2 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[7U], zeta0); + int16_t t2 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[7U], zeta0); v.elements[7U] = v.elements[3U] - t2; v.elements[3U] = v.elements[3U] + t2; - int16_t t3 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)4U], zeta1); + int16_t t3 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)4U], zeta1); v.elements[(size_t)8U + (size_t)4U] = v.elements[(size_t)8U + (size_t)0U] - t3; v.elements[(size_t)8U + (size_t)0U] = v.elements[(size_t)8U + (size_t)0U] + t3; - int16_t t4 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)5U], zeta1); + int16_t t4 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)5U], zeta1); v.elements[(size_t)8U + (size_t)5U] = v.elements[(size_t)8U + (size_t)1U] - t4; v.elements[(size_t)8U + (size_t)1U] = v.elements[(size_t)8U + (size_t)1U] + t4; - int16_t t5 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)6U], zeta1); + int16_t t5 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)6U], zeta1); v.elements[(size_t)8U + (size_t)6U] = v.elements[(size_t)8U + (size_t)2U] - t5; v.elements[(size_t)8U + (size_t)2U] = v.elements[(size_t)8U + (size_t)2U] + t5; - int16_t t6 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[(size_t)8U + (size_t)7U], zeta1); + int16_t t6 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[(size_t)8U + (size_t)7U], zeta1); v.elements[(size_t)8U + (size_t)7U] = v.elements[(size_t)8U + (size_t)3U] - t6; v.elements[(size_t)8U + (size_t)3U] = @@ -982,248 +1024,289 @@ libcrux_ml_kem_vector_ntt_layer_2_step( return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1) { - return libcrux_ml_kem_vector_ntt_layer_2_step(a, zeta0, zeta1); + return libcrux_ml_kem_vector_portable_ntt_ntt_layer_2_step(a, zeta0, zeta1); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta) { int16_t t = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(v.elements[8U], zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[8U], zeta); v.elements[8U] = v.elements[0U] - t; v.elements[0U] = v.elements[0U] + t; int16_t t0 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(v.elements[9U], zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[9U], zeta); v.elements[9U] = v.elements[1U] - t0; v.elements[1U] = v.elements[1U] + t0; - int16_t t1 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[10U], zeta); + int16_t t1 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[10U], zeta); v.elements[10U] = v.elements[2U] - t1; v.elements[2U] = v.elements[2U] + t1; - int16_t t2 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[11U], zeta); + int16_t t2 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[11U], zeta); v.elements[11U] = v.elements[3U] - t2; v.elements[3U] = v.elements[3U] + t2; - int16_t t3 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[12U], zeta); + int16_t t3 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[12U], zeta); v.elements[12U] = v.elements[4U] - t3; v.elements[4U] = v.elements[4U] + t3; - int16_t t4 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[13U], zeta); + int16_t t4 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[13U], zeta); v.elements[13U] = v.elements[5U] - t4; v.elements[5U] = v.elements[5U] + t4; - int16_t t5 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[14U], zeta); + int16_t t5 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[14U], zeta); v.elements[14U] = v.elements[6U] - t5; v.elements[6U] = v.elements[6U] + t5; - int16_t t6 = libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer( - v.elements[15U], zeta); + int16_t t6 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + v.elements[15U], zeta); v.elements[15U] = v.elements[7U] - t6; v.elements[7U] = v.elements[7U] + t6; return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta) { - return libcrux_ml_kem_vector_ntt_layer_3_step(a, zeta); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta) { + return libcrux_ml_kem_vector_portable_ntt_ntt_layer_3_step(a, zeta); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_inv_ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { int16_t a_minus_b = v.elements[2U] - v.elements[0U]; - int16_t uu____0 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[0U] + v.elements[2U]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[0U] + v.elements[2U]); v.elements[0U] = uu____0; int16_t uu____1 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b, zeta0); v.elements[2U] = uu____1; int16_t a_minus_b0 = v.elements[3U] - v.elements[1U]; - int16_t uu____2 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[1U] + v.elements[3U]); + int16_t uu____2 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[1U] + v.elements[3U]); v.elements[1U] = uu____2; int16_t uu____3 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b0, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b0, zeta0); v.elements[3U] = uu____3; int16_t a_minus_b1 = v.elements[6U] - v.elements[4U]; - int16_t uu____4 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[4U] + v.elements[6U]); + int16_t uu____4 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[4U] + v.elements[6U]); v.elements[4U] = uu____4; int16_t uu____5 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b1, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b1, zeta1); v.elements[6U] = uu____5; int16_t a_minus_b2 = v.elements[7U] - v.elements[5U]; - int16_t uu____6 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[5U] + v.elements[7U]); + int16_t uu____6 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[5U] + v.elements[7U]); v.elements[5U] = uu____6; int16_t uu____7 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b2, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b2, zeta1); v.elements[7U] = uu____7; int16_t a_minus_b3 = v.elements[(size_t)8U + (size_t)2U] - v.elements[(size_t)8U + (size_t)0U]; - int16_t uu____8 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[(size_t)8U + (size_t)0U] + - v.elements[(size_t)8U + (size_t)2U]); + int16_t uu____8 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[(size_t)8U + (size_t)0U] + + v.elements[(size_t)8U + (size_t)2U]); v.elements[(size_t)8U + (size_t)0U] = uu____8; int16_t uu____9 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b3, zeta2); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b3, zeta2); v.elements[(size_t)8U + (size_t)2U] = uu____9; int16_t a_minus_b4 = v.elements[(size_t)8U + (size_t)3U] - v.elements[(size_t)8U + (size_t)1U]; - int16_t uu____10 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[(size_t)8U + (size_t)1U] + - v.elements[(size_t)8U + (size_t)3U]); + int16_t uu____10 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[(size_t)8U + (size_t)1U] + + v.elements[(size_t)8U + (size_t)3U]); v.elements[(size_t)8U + (size_t)1U] = uu____10; int16_t uu____11 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b4, zeta2); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b4, zeta2); v.elements[(size_t)8U + (size_t)3U] = uu____11; int16_t a_minus_b5 = v.elements[(size_t)8U + (size_t)6U] - v.elements[(size_t)8U + (size_t)4U]; - int16_t uu____12 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[(size_t)8U + (size_t)4U] + - v.elements[(size_t)8U + (size_t)6U]); + int16_t uu____12 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[(size_t)8U + (size_t)4U] + + v.elements[(size_t)8U + (size_t)6U]); v.elements[(size_t)8U + (size_t)4U] = uu____12; int16_t uu____13 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b5, zeta3); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b5, zeta3); v.elements[(size_t)8U + (size_t)6U] = uu____13; int16_t a_minus_b6 = v.elements[(size_t)8U + (size_t)7U] - v.elements[(size_t)8U + (size_t)5U]; - int16_t uu____14 = libcrux_ml_kem_vector_barrett_reduce_element( - v.elements[(size_t)8U + (size_t)5U] + - v.elements[(size_t)8U + (size_t)7U]); + int16_t uu____14 = + libcrux_ml_kem_vector_portable_arithmetic_barrett_reduce_element( + v.elements[(size_t)8U + (size_t)5U] + + v.elements[(size_t)8U + (size_t)7U]); v.elements[(size_t)8U + (size_t)5U] = uu____14; int16_t uu____15 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b6, zeta3); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b6, zeta3); v.elements[(size_t)8U + (size_t)7U] = uu____15; return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_1_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_1_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { - return libcrux_ml_kem_vector_inv_ntt_layer_1_step(a, zeta0, zeta1, zeta2, - zeta3); + return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_1_step( + a, zeta0, zeta1, zeta2, zeta3); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_inv_ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta0, +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta0, int16_t zeta1) { int16_t a_minus_b = v.elements[4U] - v.elements[0U]; v.elements[0U] = v.elements[0U] + v.elements[4U]; int16_t uu____0 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b, zeta0); v.elements[4U] = uu____0; int16_t a_minus_b0 = v.elements[5U] - v.elements[1U]; v.elements[1U] = v.elements[1U] + v.elements[5U]; int16_t uu____1 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b0, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b0, zeta0); v.elements[5U] = uu____1; int16_t a_minus_b1 = v.elements[6U] - v.elements[2U]; v.elements[2U] = v.elements[2U] + v.elements[6U]; int16_t uu____2 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b1, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b1, zeta0); v.elements[6U] = uu____2; int16_t a_minus_b2 = v.elements[7U] - v.elements[3U]; v.elements[3U] = v.elements[3U] + v.elements[7U]; int16_t uu____3 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b2, zeta0); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b2, zeta0); v.elements[7U] = uu____3; int16_t a_minus_b3 = v.elements[(size_t)8U + (size_t)4U] - v.elements[(size_t)8U + (size_t)0U]; v.elements[(size_t)8U + (size_t)0U] = v.elements[(size_t)8U + (size_t)0U] + v.elements[(size_t)8U + (size_t)4U]; int16_t uu____4 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b3, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b3, zeta1); v.elements[(size_t)8U + (size_t)4U] = uu____4; int16_t a_minus_b4 = v.elements[(size_t)8U + (size_t)5U] - v.elements[(size_t)8U + (size_t)1U]; v.elements[(size_t)8U + (size_t)1U] = v.elements[(size_t)8U + (size_t)1U] + v.elements[(size_t)8U + (size_t)5U]; int16_t uu____5 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b4, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b4, zeta1); v.elements[(size_t)8U + (size_t)5U] = uu____5; int16_t a_minus_b5 = v.elements[(size_t)8U + (size_t)6U] - v.elements[(size_t)8U + (size_t)2U]; v.elements[(size_t)8U + (size_t)2U] = v.elements[(size_t)8U + (size_t)2U] + v.elements[(size_t)8U + (size_t)6U]; int16_t uu____6 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b5, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b5, zeta1); v.elements[(size_t)8U + (size_t)6U] = uu____6; int16_t a_minus_b6 = v.elements[(size_t)8U + (size_t)7U] - v.elements[(size_t)8U + (size_t)3U]; v.elements[(size_t)8U + (size_t)3U] = v.elements[(size_t)8U + (size_t)3U] + v.elements[(size_t)8U + (size_t)7U]; int16_t uu____7 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b6, zeta1); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b6, zeta1); v.elements[(size_t)8U + (size_t)7U] = uu____7; return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_2_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta0, +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_2_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta0, int16_t zeta1) { - return libcrux_ml_kem_vector_inv_ntt_layer_2_step(a, zeta0, zeta1); + return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_2_step(a, zeta0, + zeta1); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_inv_ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t zeta) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t zeta) { int16_t a_minus_b = v.elements[8U] - v.elements[0U]; v.elements[0U] = v.elements[0U] + v.elements[8U]; int16_t uu____0 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b, zeta); v.elements[8U] = uu____0; int16_t a_minus_b0 = v.elements[9U] - v.elements[1U]; v.elements[1U] = v.elements[1U] + v.elements[9U]; int16_t uu____1 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b0, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b0, zeta); v.elements[9U] = uu____1; int16_t a_minus_b1 = v.elements[10U] - v.elements[2U]; v.elements[2U] = v.elements[2U] + v.elements[10U]; int16_t uu____2 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b1, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b1, zeta); v.elements[10U] = uu____2; int16_t a_minus_b2 = v.elements[11U] - v.elements[3U]; v.elements[3U] = v.elements[3U] + v.elements[11U]; int16_t uu____3 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b2, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b2, zeta); v.elements[11U] = uu____3; int16_t a_minus_b3 = v.elements[12U] - v.elements[4U]; v.elements[4U] = v.elements[4U] + v.elements[12U]; int16_t uu____4 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b3, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b3, zeta); v.elements[12U] = uu____4; int16_t a_minus_b4 = v.elements[13U] - v.elements[5U]; v.elements[5U] = v.elements[5U] + v.elements[13U]; int16_t uu____5 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b4, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b4, zeta); v.elements[13U] = uu____5; int16_t a_minus_b5 = v.elements[14U] - v.elements[6U]; v.elements[6U] = v.elements[6U] + v.elements[14U]; int16_t uu____6 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b5, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b5, zeta); v.elements[14U] = uu____6; int16_t a_minus_b6 = v.elements[15U] - v.elements[7U]; v.elements[7U] = v.elements[7U] + v.elements[15U]; int16_t uu____7 = - libcrux_ml_kem_vector_montgomery_multiply_fe_by_fer(a_minus_b6, zeta); + libcrux_ml_kem_vector_portable_arithmetic_montgomery_multiply_fe_by_fer( + a_minus_b6, zeta); v.elements[15U] = uu____7; return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_3_step( - libcrux_ml_kem_vector_portable_PortableVector a, int16_t zeta) { - return libcrux_ml_kem_vector_inv_ntt_layer_3_step(a, zeta); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_3_step( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, int16_t zeta) { + return libcrux_ml_kem_vector_portable_ntt_inv_ntt_layer_3_step(a, zeta); } typedef struct K___int16_t_int16_t_s { @@ -1231,30 +1314,35 @@ typedef struct K___int16_t_int16_t_s { int16_t snd; } K___int16_t_int16_t; -static inline K___int16_t_int16_t libcrux_ml_kem_vector_ntt_multiply_binomials( +static inline K___int16_t_int16_t +libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials( K___int16_t_int16_t _, K___int16_t_int16_t _0, int16_t zeta) { int16_t a0 = _.fst; int16_t a1 = _.snd; int16_t b0 = _0.fst; int16_t b1 = _0.snd; int32_t uu____0 = (int32_t)a0 * (int32_t)b0; - int16_t uu____1 = libcrux_ml_kem_vector_montgomery_reduce_element( - uu____0 + (int32_t)libcrux_ml_kem_vector_montgomery_reduce_element( - (int32_t)a1 * (int32_t)b1) * - (int32_t)zeta); + int16_t uu____1 = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + uu____0 + + (int32_t) + libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + (int32_t)a1 * (int32_t)b1) * + (int32_t)zeta); return (CLITERAL(K___int16_t_int16_t){ .fst = uu____1, - .snd = libcrux_ml_kem_vector_montgomery_reduce_element( - (int32_t)a0 * (int32_t)b1 + (int32_t)a1 * (int32_t)b0)}); -} - -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_ntt_multiply( - libcrux_ml_kem_vector_portable_PortableVector *lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs, int16_t zeta0, - int16_t zeta1, int16_t zeta2, int16_t zeta3) { - libcrux_ml_kem_vector_portable_PortableVector out = - libcrux_ml_kem_vector_zero(); + .snd = + libcrux_ml_kem_vector_portable_arithmetic_montgomery_reduce_element( + (int32_t)a0 * (int32_t)b1 + (int32_t)a1 * (int32_t)b0)}); +} + +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_ntt_ntt_multiply( + libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, + int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector out = + libcrux_ml_kem_vector_portable_vector_type_zero(); K___int16_t_int16_t lit0; lit0.fst = lhs->elements[0U]; lit0.snd = lhs->elements[1U]; @@ -1262,7 +1350,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit1.fst = rhs->elements[0U]; lit1.snd = rhs->elements[1U]; K___int16_t_int16_t product = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit0, lit1, zeta0); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit0, lit1, + zeta0); out.elements[0U] = product.fst; out.elements[1U] = product.snd; K___int16_t_int16_t lit2; @@ -1272,7 +1361,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit3.fst = rhs->elements[2U]; lit3.snd = rhs->elements[3U]; K___int16_t_int16_t product0 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit2, lit3, -zeta0); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit2, lit3, + -zeta0); out.elements[2U] = product0.fst; out.elements[3U] = product0.snd; K___int16_t_int16_t lit4; @@ -1282,7 +1372,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit5.fst = rhs->elements[4U]; lit5.snd = rhs->elements[5U]; K___int16_t_int16_t product1 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit4, lit5, zeta1); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit4, lit5, + zeta1); out.elements[4U] = product1.fst; out.elements[5U] = product1.snd; K___int16_t_int16_t lit6; @@ -1292,7 +1383,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit7.fst = rhs->elements[6U]; lit7.snd = rhs->elements[7U]; K___int16_t_int16_t product2 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit6, lit7, -zeta1); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit6, lit7, + -zeta1); out.elements[6U] = product2.fst; out.elements[7U] = product2.snd; K___int16_t_int16_t lit8; @@ -1302,7 +1394,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit9.fst = rhs->elements[(size_t)8U + (size_t)0U]; lit9.snd = rhs->elements[(size_t)8U + (size_t)1U]; K___int16_t_int16_t product3 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit8, lit9, zeta2); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit8, lit9, + zeta2); out.elements[(size_t)8U + (size_t)0U] = product3.fst; out.elements[(size_t)8U + (size_t)1U] = product3.snd; K___int16_t_int16_t lit10; @@ -1312,7 +1405,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit11.fst = rhs->elements[(size_t)8U + (size_t)2U]; lit11.snd = rhs->elements[(size_t)8U + (size_t)3U]; K___int16_t_int16_t product4 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit10, lit11, -zeta2); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit10, lit11, + -zeta2); out.elements[(size_t)8U + (size_t)2U] = product4.fst; out.elements[(size_t)8U + (size_t)3U] = product4.snd; K___int16_t_int16_t lit12; @@ -1322,7 +1416,8 @@ libcrux_ml_kem_vector_ntt_multiply( lit13.fst = rhs->elements[(size_t)8U + (size_t)4U]; lit13.snd = rhs->elements[(size_t)8U + (size_t)5U]; K___int16_t_int16_t product5 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit12, lit13, zeta3); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit12, lit13, + zeta3); out.elements[(size_t)8U + (size_t)4U] = product5.fst; out.elements[(size_t)8U + (size_t)5U] = product5.snd; K___int16_t_int16_t lit14; @@ -1332,54 +1427,61 @@ libcrux_ml_kem_vector_ntt_multiply( lit.fst = rhs->elements[(size_t)8U + (size_t)6U]; lit.snd = rhs->elements[(size_t)8U + (size_t)7U]; K___int16_t_int16_t product6 = - libcrux_ml_kem_vector_ntt_multiply_binomials(lit14, lit, -zeta3); + libcrux_ml_kem_vector_portable_ntt_ntt_multiply_binomials(lit14, lit, + -zeta3); out.elements[(size_t)8U + (size_t)6U] = product6.fst; out.elements[(size_t)8U + (size_t)7U] = product6.snd; return out; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_multiply( - libcrux_ml_kem_vector_portable_PortableVector *lhs, - libcrux_ml_kem_vector_portable_PortableVector *rhs, int16_t zeta0, - int16_t zeta1, int16_t zeta2, int16_t zeta3) { - return libcrux_ml_kem_vector_ntt_multiply(lhs, rhs, zeta0, zeta1, zeta2, - zeta3); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_multiply( + libcrux_ml_kem_vector_portable_vector_type_PortableVector *lhs, + libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs, + int16_t zeta0, int16_t zeta1, int16_t zeta2, int16_t zeta3) { + return libcrux_ml_kem_vector_portable_ntt_ntt_multiply(lhs, rhs, zeta0, zeta1, + zeta2, zeta3); } -static inline void libcrux_ml_kem_vector_serialize_1( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[2U]) { +static inline void libcrux_ml_kem_vector_portable_serialize_serialize_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[2U]) { uint8_t result[2U] = {0U}; - KRML_MAYBE_FOR8( - i, (size_t)0U, (size_t)8U, (size_t)1U, size_t i0 = i; - size_t uu____0 = (size_t)0U; - result[uu____0] = (uint32_t)result[uu____0] | - (uint32_t)(uint8_t)v.elements[i0] << (uint32_t)i0;); - KRML_MAYBE_FOR8(i, (size_t)8U, (size_t)16U, (size_t)1U, size_t i0 = i; - size_t uu____1 = (size_t)1U; - result[uu____1] = (uint32_t)result[uu____1] | - (uint32_t)(uint8_t)v.elements[i0] - << (uint32_t)(i0 - (size_t)8U);); + for (size_t i = (size_t)0U; i < (size_t)8U; i++) { + size_t i0 = i; + size_t uu____0 = (size_t)0U; + result[uu____0] = (uint32_t)result[uu____0] | + (uint32_t)(uint8_t)v.elements[i0] << (uint32_t)i0; + } + for (size_t i = (size_t)8U; i < (size_t)16U; i++) { + size_t i0 = i; + size_t uu____1 = (size_t)1U; + result[uu____1] = + (uint32_t)result[uu____1] | (uint32_t)(uint8_t)v.elements[i0] + << (uint32_t)(i0 - (size_t)8U); + } memcpy(ret, result, (size_t)2U * sizeof(uint8_t)); } static inline void -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_1( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[2U]) { +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_1( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[2U]) { uint8_t ret0[2U]; - libcrux_ml_kem_vector_serialize_1(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_1(a, ret0); memcpy(ret, ret0, (size_t)2U * sizeof(uint8_t)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_1(Eurydice_slice v) { - libcrux_ml_kem_vector_portable_PortableVector result = - libcrux_ml_kem_vector_zero(); - KRML_MAYBE_FOR8(i, (size_t)0U, (size_t)8U, (size_t)1U, size_t i0 = i; - uint8_t *uu____0 = &Eurydice_slice_index( - v, (size_t)0U, uint8_t, uint8_t *, uint8_t); - result.elements[i0] = - (int16_t)((uint32_t)uu____0[0U] >> (uint32_t)i0 & 1U);); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_1(Eurydice_slice v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector result = + libcrux_ml_kem_vector_portable_vector_type_zero(); + for (size_t i = (size_t)0U; i < (size_t)8U; i++) { + size_t i0 = i; + uint8_t *uu____0 = + &Eurydice_slice_index(v, (size_t)0U, uint8_t, uint8_t *, uint8_t); + result.elements[i0] = (int16_t)((uint32_t)uu____0[0U] >> (uint32_t)i0 & 1U); + } for (size_t i = (size_t)8U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -1391,14 +1493,15 @@ libcrux_ml_kem_vector_deserialize_1(Eurydice_slice v) { return result; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_1( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_1( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_1(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_1(a); } -static inline void libcrux_ml_kem_vector_serialize_4( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[8U]) { +static inline void libcrux_ml_kem_vector_portable_serialize_serialize_4( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[8U]) { uint8_t result[8U] = {0U}; result[0U] = (uint32_t)(uint8_t)v.elements[1U] << 4U | (uint32_t)(uint8_t)v.elements[0U]; @@ -1420,17 +1523,18 @@ static inline void libcrux_ml_kem_vector_serialize_4( } static inline void -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_4( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[8U]) { +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_4( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[8U]) { uint8_t ret0[8U]; - libcrux_ml_kem_vector_serialize_4(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_4(a, ret0); memcpy(ret, ret0, (size_t)8U * sizeof(uint8_t)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_4(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector v = - libcrux_ml_kem_vector_zero(); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_4(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v = + libcrux_ml_kem_vector_portable_vector_type_zero(); uint8_t *uu____0 = &Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *, uint8_t); v.elements[0U] = (int16_t)((uint32_t)uu____0[0U] & 15U); @@ -1482,14 +1586,15 @@ libcrux_ml_kem_vector_deserialize_4(Eurydice_slice bytes) { return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_4( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_4( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_4(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_4(a); } -static inline void libcrux_ml_kem_vector_serialize_5( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[10U]) { +static inline void libcrux_ml_kem_vector_portable_serialize_serialize_5( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[10U]) { uint8_t result[10U] = {0U}; result[0U] = (uint8_t)((v.elements[1U] & (int16_t)7) << 5U | v.elements[0U]); result[1U] = @@ -1521,17 +1626,18 @@ static inline void libcrux_ml_kem_vector_serialize_5( } static inline void -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_5( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[10U]) { +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_5( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[10U]) { uint8_t ret0[10U]; - libcrux_ml_kem_vector_serialize_5(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_5(a, ret0); memcpy(ret, ret0, (size_t)10U * sizeof(uint8_t)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_5(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector v = - libcrux_ml_kem_vector_zero(); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_5(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector v = + libcrux_ml_kem_vector_portable_vector_type_zero(); uint8_t *uu____0 = &Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *, uint8_t); v.elements[0U] = (int16_t)((uint32_t)uu____0[0U] & 31U); @@ -1622,14 +1728,15 @@ libcrux_ml_kem_vector_deserialize_5(Eurydice_slice bytes) { return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_5( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_5( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_5(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_5(a); } -static inline void libcrux_ml_kem_vector_serialize_10( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[20U]) { +static inline void libcrux_ml_kem_vector_portable_serialize_serialize_10( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[20U]) { uint8_t result[20U] = {0U}; result[0U] = (uint8_t)(v.elements[0U] & (int16_t)255); result[1U] = (uint32_t)(uint8_t)(v.elements[1U] & (int16_t)63) << 2U | @@ -1687,17 +1794,18 @@ static inline void libcrux_ml_kem_vector_serialize_10( } static inline void -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_10( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[20U]) { +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_10( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[20U]) { uint8_t ret0[20U]; - libcrux_ml_kem_vector_serialize_10(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_10(a, ret0); memcpy(ret, ret0, (size_t)20U * sizeof(uint8_t)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_10(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector result = - libcrux_ml_kem_vector_zero(); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_10(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector result = + libcrux_ml_kem_vector_portable_vector_type_zero(); int16_t uu____0 = ((int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *, uint8_t) & (int16_t)3) @@ -1817,14 +1925,15 @@ libcrux_ml_kem_vector_deserialize_10(Eurydice_slice bytes) { return result; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_10( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_10( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_10(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_10(a); } -static inline void libcrux_ml_kem_vector_serialize_11( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[22U]) { +static inline void libcrux_ml_kem_vector_portable_serialize_serialize_11( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[22U]) { uint8_t result[22U] = {0U}; result[0U] = (uint8_t)v.elements[0U]; result[1U] = (uint32_t)(uint8_t)(v.elements[1U] & (int16_t)31) << 3U | @@ -1882,17 +1991,18 @@ static inline void libcrux_ml_kem_vector_serialize_11( } static inline void -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_11( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[22U]) { +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_11( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[22U]) { uint8_t ret0[22U]; - libcrux_ml_kem_vector_serialize_11(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_11(a, ret0); memcpy(ret, ret0, (size_t)22U * sizeof(uint8_t)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_11(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector result = - libcrux_ml_kem_vector_zero(); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_11(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector result = + libcrux_ml_kem_vector_portable_vector_type_zero(); int16_t uu____0 = ((int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, uint8_t *, uint8_t) & (int16_t)7) @@ -2030,14 +2140,15 @@ libcrux_ml_kem_vector_deserialize_11(Eurydice_slice bytes) { return result; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_11( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_11( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_11(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_11(a); } -static inline void libcrux_ml_kem_vector_serialize_12( - libcrux_ml_kem_vector_portable_PortableVector v, uint8_t ret[24U]) { +static inline void libcrux_ml_kem_vector_portable_serialize_serialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, + uint8_t ret[24U]) { uint8_t result[24U] = {0U}; result[0U] = (uint8_t)(v.elements[0U] & (int16_t)255); result[1U] = @@ -2083,17 +2194,18 @@ static inline void libcrux_ml_kem_vector_serialize_12( } static inline void -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_12( - libcrux_ml_kem_vector_portable_PortableVector a, uint8_t ret[24U]) { +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + uint8_t ret[24U]) { uint8_t ret0[24U]; - libcrux_ml_kem_vector_serialize_12(a, ret0); + libcrux_ml_kem_vector_portable_serialize_serialize_12(a, ret0); memcpy(ret, ret0, (size_t)24U * sizeof(uint8_t)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_deserialize_12(Eurydice_slice bytes) { - libcrux_ml_kem_vector_portable_PortableVector re = - libcrux_ml_kem_vector_zero(); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_serialize_deserialize_12(Eurydice_slice bytes) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector re = + libcrux_ml_kem_vector_portable_vector_type_zero(); int16_t byte0 = (int16_t)Eurydice_slice_index(bytes, (size_t)0U, uint8_t, uint8_t *, uint8_t); int16_t byte1 = (int16_t)Eurydice_slice_index(bytes, (size_t)1U, uint8_t, @@ -2161,14 +2273,14 @@ libcrux_ml_kem_vector_deserialize_12(Eurydice_slice bytes) { return re; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_12( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_12( Eurydice_slice a) { - return libcrux_ml_kem_vector_deserialize_12(a); + return libcrux_ml_kem_vector_portable_serialize_deserialize_12(a); } -static inline size_t libcrux_ml_kem_vector_rej_sample(Eurydice_slice a, - Eurydice_slice result) { +static inline size_t libcrux_ml_kem_vector_portable_sampling_rej_sample( + Eurydice_slice a, Eurydice_slice result) { size_t sampled = (size_t)0U; for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(a, uint8_t, size_t) / (size_t)3U; i++) { @@ -2232,9 +2344,9 @@ static inline size_t libcrux_ml_kem_vector_rej_sample(Eurydice_slice a, } static inline size_t -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( Eurydice_slice a, Eurydice_slice out) { - return libcrux_ml_kem_vector_rej_sample(a, out); + return libcrux_ml_kem_vector_portable_sampling_rej_sample(a, out); } #define LIBCRUX_ML_KEM_MLKEM768_VECTOR_U_COMPRESSION_FACTOR_768 ((size_t)10U) @@ -2301,59 +2413,59 @@ typedef libcrux_ml_kem_types_MlKemPublicKey____1184size_t LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE) typedef struct - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_s { - libcrux_ml_kem_vector_portable_PortableVector coefficients[16U]; -} libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_s { + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficients[16U]; +} libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector; -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector( void) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector lit; lit.coefficients[0U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[1U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[2U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[3U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[4U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[5U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[6U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[7U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[8U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[9U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[10U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[11U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[12U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[13U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[14U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); lit.coefficients[15U] = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); return lit; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u_closure__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1088size_t_10size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1088size_t_10size_t( size_t _) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_decompress_ciphertext_coefficient___10int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient___10int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -2366,18 +2478,19 @@ libcrux_ml_kem_vector_decompress_ciphertext_coefficient___10int32_t( return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___decompress_ciphertext_coefficient___10int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_decompress_ciphertext_coefficient___10int32_t(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___decompress_ciphertext_coefficient___10int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient___10int32_t( + v); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_then_decompress_10__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_then_decompress_10__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)20U; @@ -2388,20 +2501,20 @@ libcrux_ml_kem_serialize_deserialize_then_decompress_10__libcrux_ml_kem_vector_p (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)20U, .end = i0 * (size_t)20U + (size_t)20U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_10( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_10( bytes); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___decompress_ciphertext_coefficient___10int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___decompress_ciphertext_coefficient___10int32_t( coefficient); re.coefficients[i0] = uu____0; } return re; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_decompress_ciphertext_coefficient___11int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient___11int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -2414,18 +2527,19 @@ libcrux_ml_kem_vector_decompress_ciphertext_coefficient___11int32_t( return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___decompress_ciphertext_coefficient___11int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_decompress_ciphertext_coefficient___11int32_t(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___decompress_ciphertext_coefficient___11int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient___11int32_t( + v); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_then_decompress_11__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_then_decompress_11__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)22U; @@ -2436,61 +2550,62 @@ libcrux_ml_kem_serialize_deserialize_then_decompress_11__libcrux_ml_kem_vector_p (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)22U, .end = i0 * (size_t)22U + (size_t)22U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_11( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_11( bytes); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___decompress_ciphertext_coefficient___11int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___decompress_ciphertext_coefficient___11int32_t( coefficient); re.coefficients[i0] = uu____0; } return re; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0; uu____0 = - libcrux_ml_kem_serialize_deserialize_then_decompress_10__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_serialize_deserialize_then_decompress_10__libcrux_ml_kem_vector_portable_vector_type_PortableVector( serialized); return uu____0; } typedef struct - K___libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector_s { - libcrux_ml_kem_vector_portable_PortableVector fst; - libcrux_ml_kem_vector_portable_PortableVector snd; -} K___libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector; - -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_traits_montgomery_multiply_fe__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector v, int16_t fer) { - return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( + K___libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector_s { + libcrux_ml_kem_vector_portable_vector_type_PortableVector fst; + libcrux_ml_kem_vector_portable_vector_type_PortableVector snd; +} K___libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector; + +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_traits_montgomery_multiply_fe__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v, int16_t fer) { + return libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( v, fer); } -static inline K___libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_ntt_ntt_layer_int_vec_step__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector a, - libcrux_ml_kem_vector_portable_PortableVector b, int16_t zeta_r) { - libcrux_ml_kem_vector_portable_PortableVector t = - libcrux_ml_kem_vector_traits_montgomery_multiply_fe__libcrux_ml_kem_vector_portable_PortableVector( +static inline K___libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_ntt_ntt_layer_int_vec_step__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + libcrux_ml_kem_vector_portable_vector_type_PortableVector b, + int16_t zeta_r) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector t = + libcrux_ml_kem_vector_traits_montgomery_multiply_fe__libcrux_ml_kem_vector_portable_vector_type_PortableVector( b, zeta_r); - b = libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( + b = libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( a, &t); - a = libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + a = libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( a, &t); return (CLITERAL( - K___libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector){ + K___libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector){ .fst = a, .snd = b}); } static inline void -libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( +libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t layer, size_t _initial_coefficient_bound) { size_t step = (size_t)1U << (uint32_t)layer; @@ -2502,14 +2617,14 @@ libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableV size_t step_vec = step / (size_t)16U; for (size_t i = offset_vec; i < offset_vec + step_vec; i++) { size_t j = i; - K___libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector + K___libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - libcrux_ml_kem_ntt_ntt_layer_int_vec_step__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_layer_int_vec_step__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[j], re->coefficients[j + step_vec], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R [zeta_i[0U]]); - libcrux_ml_kem_vector_portable_PortableVector x = uu____0.fst; - libcrux_ml_kem_vector_portable_PortableVector y = uu____0.snd; + libcrux_ml_kem_vector_portable_vector_type_PortableVector x = uu____0.fst; + libcrux_ml_kem_vector_portable_vector_type_PortableVector y = uu____0.snd; re->coefficients[j] = x; re->coefficients[j + step_vec] = y; } @@ -2517,109 +2632,114 @@ libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableV } static inline void -libcrux_ml_kem_ntt_ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector( +libcrux_ml_kem_ntt_ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t _layer, size_t _initial_coefficient_bound) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] + (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_3_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); - re->coefficients[round] = uu____0;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] + (size_t)1U; + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_3_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); + re->coefficients[round] = uu____0; + } } static inline void -libcrux_ml_kem_ntt_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector( +libcrux_ml_kem_ntt_ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t _layer, size_t _initial_coefficient_bound) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] + (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_2_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + - (size_t)1U]); - re->coefficients[round] = uu____0; zeta_i[0U] = zeta_i[0U] + (size_t)1U;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] + (size_t)1U; + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_2_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + + (size_t)1U]); + re->coefficients[round] = uu____0; + zeta_i[0U] = zeta_i[0U] + (size_t)1U; + } } static inline void -libcrux_ml_kem_ntt_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector( +libcrux_ml_kem_ntt_ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t _layer, size_t _initial_coefficient_bound) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] + (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_layer_1_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + - (size_t)1U], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + - (size_t)2U], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + - (size_t)3U]); - re->coefficients[round] = uu____0; zeta_i[0U] = zeta_i[0U] + (size_t)3U;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] + (size_t)1U; + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_layer_1_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + + (size_t)1U], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + + (size_t)2U], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] + + (size_t)3U]); + re->coefficients[round] = uu____0; + zeta_i[0U] = zeta_i[0U] + (size_t)3U; + } } static inline void -libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( self->coefficients[i0]); self->coefficients[i0] = uu____0; } } static inline void -libcrux_ml_kem_ntt_ntt_vector_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_ntt_ntt_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { size_t zeta_i = (size_t)0U; - libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)7U, (size_t)3328U); - libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)6U, (size_t)3328U); - libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)5U, (size_t)3328U); - libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)4U, (size_t)3328U); - libcrux_ml_kem_ntt_ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)3U, (size_t)3328U); - libcrux_ml_kem_ntt_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)2U, (size_t)3328U); - libcrux_ml_kem_ntt_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)1U, (size_t)3328U); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re); } static inline void -libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1088size_t_10size_t( +libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1088size_t_10size_t( uint8_t *ciphertext, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u_as_ntt[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - u_as_ntt[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + u_as_ntt[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + } for (size_t i = (size_t)0U; i < core_slice___Slice_T___len( Eurydice_array_to_slice((size_t)1088U, ciphertext, uint8_t, @@ -2640,24 +2760,24 @@ libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u__libcrux_ml_kem_vector_port LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * (size_t)10U / (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( + libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( u_bytes); u_as_ntt[i0] = uu____0; - libcrux_ml_kem_ntt_ntt_vector_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t( + libcrux_ml_kem_ntt_ntt_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t( &u_as_ntt[i0]); } memcpy( ret, u_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_decompress_ciphertext_coefficient___4int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient___4int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -2670,18 +2790,19 @@ libcrux_ml_kem_vector_decompress_ciphertext_coefficient___4int32_t( return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___decompress_ciphertext_coefficient___4int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_decompress_ciphertext_coefficient___4int32_t(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___decompress_ciphertext_coefficient___4int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient___4int32_t( + v); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_then_decompress_4__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_then_decompress_4__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)8U; i++) { @@ -2691,20 +2812,20 @@ libcrux_ml_kem_serialize_deserialize_then_decompress_4__libcrux_ml_kem_vector_po (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)8U, .end = i0 * (size_t)8U + (size_t)8U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_4( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_4( bytes); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___decompress_ciphertext_coefficient___4int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___decompress_ciphertext_coefficient___4int32_t( coefficient); re.coefficients[i0] = uu____0; } return re; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_decompress_ciphertext_coefficient___5int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient___5int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -2717,18 +2838,19 @@ libcrux_ml_kem_vector_decompress_ciphertext_coefficient___5int32_t( return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___decompress_ciphertext_coefficient___5int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_decompress_ciphertext_coefficient___5int32_t(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___decompress_ciphertext_coefficient___5int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_decompress_ciphertext_coefficient___5int32_t( + v); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_then_decompress_5__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_then_decompress_5__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)10U; @@ -2739,41 +2861,41 @@ libcrux_ml_kem_serialize_deserialize_then_decompress_5__libcrux_ml_kem_vector_po (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)10U, .end = i0 * (size_t)10U + (size_t)10U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_5( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_5( bytes); re.coefficients[i0] = uu____0; - libcrux_ml_kem_vector_portable_PortableVector uu____1 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___decompress_ciphertext_coefficient___5int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___decompress_ciphertext_coefficient___5int32_t( re.coefficients[i0]); re.coefficients[i0] = uu____1; } return re; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0; uu____0 = - libcrux_ml_kem_serialize_deserialize_then_decompress_4__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_serialize_deserialize_then_decompress_4__libcrux_ml_kem_vector_portable_vector_type_PortableVector( serialized); return uu____0; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_ind_cpa_deserialize_secret_key_closure__libcrux_ml_kem_vector_portable_PortableVector_3size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_ind_cpa_deserialize_secret_key_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( size_t _) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)24U; @@ -2784,8 +2906,8 @@ libcrux_ml_kem_serialize_deserialize_to_uncompressed_ring_element__libcrux_ml_ke (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)24U, .end = i0 * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_12( bytes); re.coefficients[i0] = uu____0; } @@ -2793,16 +2915,16 @@ libcrux_ml_kem_serialize_deserialize_to_uncompressed_ring_element__libcrux_ml_ke } static inline void -libcrux_ml_kem_ind_cpa_deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t( +libcrux_ml_kem_ind_cpa_deserialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( Eurydice_slice secret_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - secret_as_ntt[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + secret_as_ntt[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + } for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(secret_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -2815,9 +2937,9 @@ libcrux_ml_kem_ind_cpa_deserialize_secret_key__libcrux_ml_kem_vector_portable_Po .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - libcrux_ml_kem_serialize_deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_serialize_deserialize_to_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( secret_bytes); secret_as_ntt[i0] = uu____0; } @@ -2825,23 +2947,23 @@ libcrux_ml_kem_ind_cpa_deserialize_secret_key__libcrux_ml_kem_vector_portable_Po ret, secret_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector out = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ntt_multiply( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ntt_multiply( &self->coefficients[i0], &rhs->coefficients[i0], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[(size_t)64U + (size_t)4U * i0], @@ -2860,104 +2982,111 @@ libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vec } static inline void -libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *rhs) { for (size_t i = (size_t)0U; - i < - core_slice___Slice_T___len( - Eurydice_array_to_slice( - (size_t)16U, self->coefficients, - libcrux_ml_kem_vector_portable_PortableVector, Eurydice_slice), - libcrux_ml_kem_vector_portable_PortableVector, size_t); + i < core_slice___Slice_T___len( + Eurydice_array_to_slice( + (size_t)16U, self->coefficients, + libcrux_ml_kem_vector_portable_vector_type_PortableVector, + Eurydice_slice), + libcrux_ml_kem_vector_portable_vector_type_PortableVector, + size_t); i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( self->coefficients[i0], &rhs->coefficients[i0]); self->coefficients[i0] = uu____0; } } static inline void -libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector( +libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t _layer) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] - (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_1_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - - (size_t)1U], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - - (size_t)2U], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - - (size_t)3U]); - re->coefficients[round] = uu____0; zeta_i[0U] = zeta_i[0U] - (size_t)3U;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] - (size_t)1U; + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_1_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - + (size_t)1U], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - + (size_t)2U], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - + (size_t)3U]); + re->coefficients[round] = uu____0; + zeta_i[0U] = zeta_i[0U] - (size_t)3U; + } } static inline void -libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector( +libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t _layer) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] - (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_2_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - - (size_t)1U]); - re->coefficients[round] = uu____0; zeta_i[0U] = zeta_i[0U] - (size_t)1U;); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] - (size_t)1U; + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_2_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U] - + (size_t)1U]); + re->coefficients[round] = uu____0; + zeta_i[0U] = zeta_i[0U] - (size_t)1U; + } } static inline void -libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector( +libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t _layer) { - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t round = i; - zeta_i[0U] = zeta_i[0U] - (size_t)1U; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___inv_ntt_layer_3_step( - re->coefficients[round], - libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); - re->coefficients[round] = uu____0;); -} - -static inline K___libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_invert_ntt_inv_ntt_layer_int_vec_step_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector a, - libcrux_ml_kem_vector_portable_PortableVector b, int16_t zeta_r) { - libcrux_ml_kem_vector_portable_PortableVector a_minus_b = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t round = i; + zeta_i[0U] = zeta_i[0U] - (size_t)1U; + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___inv_ntt_layer_3_step( + re->coefficients[round], + libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R[zeta_i[0U]]); + re->coefficients[round] = uu____0; + } +} + +static inline K___libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_invert_ntt_inv_ntt_layer_int_vec_step_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a, + libcrux_ml_kem_vector_portable_vector_type_PortableVector b, + int16_t zeta_r) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector a_minus_b = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( b, &a); - a = libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + a = libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( a, &b)); - b = libcrux_ml_kem_vector_traits_montgomery_multiply_fe__libcrux_ml_kem_vector_portable_PortableVector( + b = libcrux_ml_kem_vector_traits_montgomery_multiply_fe__libcrux_ml_kem_vector_portable_vector_type_PortableVector( a_minus_b, zeta_r); return (CLITERAL( - K___libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector){ + K___libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector){ .fst = a, .snd = b}); } static inline void -libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( +libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( size_t *zeta_i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, size_t layer) { size_t step = (size_t)1U << (uint32_t)layer; @@ -2971,14 +3100,14 @@ libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_port step / LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; for (size_t i = offset_vec; i < offset_vec + step_vec; i++) { size_t j = i; - K___libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_vector_portable_PortableVector + K___libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - libcrux_ml_kem_invert_ntt_inv_ntt_layer_int_vec_step_reduce__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_invert_ntt_inv_ntt_layer_int_vec_step_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[j], re->coefficients[j + step_vec], libcrux_ml_kem_polynomial_ZETAS_TIMES_MONTGOMERY_R [zeta_i[0U]]); - libcrux_ml_kem_vector_portable_PortableVector x = uu____0.fst; - libcrux_ml_kem_vector_portable_PortableVector y = uu____0.snd; + libcrux_ml_kem_vector_portable_vector_type_PortableVector x = uu____0.fst; + libcrux_ml_kem_vector_portable_vector_type_PortableVector y = uu____0.snd; re->coefficients[j] = x; re->coefficients[j + step_vec] = y; } @@ -2986,80 +3115,82 @@ libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_port } static inline void -libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { size_t zeta_i = LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT / (size_t)2U; - libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)1U); - libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)2U); - libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)3U); - libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)4U); - libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)5U); - libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)6U); - libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_invert_ntt_invert_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)7U); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___subtract_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___subtract_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector b) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_normal_form = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( - b.coefficients[i0], (int16_t)1441); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_normal_form = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( + b.coefficients[i0], (int16_t)1441); + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( self->coefficients[i0], &coefficient_normal_form)); b.coefficients[i0] = uu____0; } return b; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_matrix_compute_message__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_matrix_compute_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *v, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *secret_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *u_as_ntt) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - &secret_as_ntt[i0], &u_as_ntt[i0]); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - &result, &product);); - libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &secret_as_ntt[i0], &u_as_ntt[i0]); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + &result, &product); + } + libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result); result = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___subtract_reduce__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___subtract_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( v, result); return result; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_shift_right___15int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_arithmetic_shift_right___15int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; @@ -3068,76 +3199,78 @@ libcrux_ml_kem_vector_shift_right___15int32_t( return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___shift_right___15int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_shift_right___15int32_t(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___shift_right___15int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_arithmetic_shift_right___15int32_t(v); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector a) { - libcrux_ml_kem_vector_portable_PortableVector t = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___shift_right___15int32_t( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector a) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector t = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___shift_right___15int32_t( a); - libcrux_ml_kem_vector_portable_PortableVector fm = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___bitwise_and_with_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector fm = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___bitwise_and_with_constant( t, LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_MODULUS); - return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + return libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( a, &fm); } static inline void -libcrux_ml_kem_serialize_compress_then_serialize_message__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_serialize_compress_then_serialize_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re, uint8_t ret[32U]) { uint8_t serialized[32U] = {0U}; - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( - re.coefficients[i0]); - libcrux_ml_kem_vector_portable_PortableVector coefficient_compressed = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress_1( - coefficient); - uint8_t bytes[2U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_1( - coefficient_compressed, bytes); - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)32U, serialized, - (CLITERAL(core_ops_range_Range__size_t){ - .start = (size_t)2U * i0, .end = (size_t)2U * i0 + (size_t)2U}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice( - uu____0, - Eurydice_array_to_slice((size_t)2U, bytes, uint8_t, Eurydice_slice), - uint8_t, void *);); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t i0 = i; + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + re.coefficients[i0]); + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_compressed = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress_1( + coefficient); + uint8_t bytes[2U]; + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_1( + coefficient_compressed, bytes); + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)32U, serialized, + (CLITERAL(core_ops_range_Range__size_t){ + .start = (size_t)2U * i0, .end = (size_t)2U * i0 + (size_t)2U}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + core_slice___Slice_T___copy_from_slice( + uu____0, + Eurydice_array_to_slice((size_t)2U, bytes, uint8_t, Eurydice_slice), + uint8_t, void *); + } memcpy(ret, serialized, (size_t)32U * sizeof(uint8_t)); } static inline void -libcrux_ml_kem_ind_cpa_decrypt__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1088size_t_960size_t_10size_t_4size_t( +libcrux_ml_kem_ind_cpa_decrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1088size_t_960size_t_10size_t_4size_t( Eurydice_slice secret_key, uint8_t *ciphertext, uint8_t ret[32U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u_as_ntt[3U]; - libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1088size_t_10size_t( + libcrux_ml_kem_ind_cpa_deserialize_then_decompress_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1088size_t_10size_t( ciphertext, u_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - v = libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + v = libcrux_ml_kem_serialize_deserialize_then_decompress_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t( Eurydice_array_to_subslice_from((size_t)1088U, ciphertext, (size_t)960U, uint8_t, size_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[3U]; - libcrux_ml_kem_ind_cpa_deserialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_ind_cpa_deserialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( secret_key, secret_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector message = - libcrux_ml_kem_matrix_compute_message__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_matrix_compute_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &v, secret_as_ntt, u_as_ntt); uint8_t ret0[32U]; - libcrux_ml_kem_serialize_compress_then_serialize_message__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_serialize_compress_then_serialize_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( message, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } @@ -3162,18 +3295,18 @@ libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K_ memcpy(ret, digest, (size_t)32U * sizeof(uint8_t)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_closure__libcrux_ml_kem_vector_portable_PortableVector_1152size_t_3size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1152size_t_3size_t( size_t _i) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice serialized) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(serialized, uint8_t, size_t) / (size_t)24U; @@ -3184,11 +3317,11 @@ libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element__libcrux_ml_kem_vec (CLITERAL(core_ops_range_Range__size_t){ .start = i0 * (size_t)24U, .end = i0 * (size_t)24U + (size_t)24U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_12( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_12( bytes); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___cond_subtract_3329( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___cond_subtract_3329( coefficient); re.coefficients[i0] = uu____0; } @@ -3196,16 +3329,16 @@ libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element__libcrux_ml_kem_vec } static inline void -libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1152size_t_3size_t( +libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1152size_t_3size_t( Eurydice_slice public_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - deserialized_pk[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + deserialized_pk[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + } for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -3218,9 +3351,9 @@ libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vecto .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( ring_element); deserialized_pk[i0] = uu____0; } @@ -3228,31 +3361,31 @@ libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vecto ret, deserialized_pk, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_matrix_sample_matrix_A_closure_closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_matrix_sample_matrix_A_closure_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( size_t _j) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); } static inline void -libcrux_ml_kem_matrix_sample_matrix_A_closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( +libcrux_ml_kem_matrix_sample_matrix_A_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( size_t _i, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret0[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - ret0[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + ret0[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + } memcpy( ret, ret0, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } typedef struct @@ -3264,14 +3397,15 @@ static inline libcrux_ml_kem_hash_functions_portable_PortableHash____3size_t libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__portable__PortableHash_K____shake128_init_absorb___3size_t( uint8_t input[3U][34U]) { libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t state[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - state[i] = libcrux_sha3_portable_incremental_shake128_init();); - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_portable_incremental_shake128_absorb_final( - &state[i0], Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, - Eurydice_slice));); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + state[i] = libcrux_sha3_portable_incremental_shake128_init(); + } + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_sha3_portable_incremental_shake128_absorb_final( + &state[i0], Eurydice_array_to_slice((size_t)34U, input[i0], uint8_t, + Eurydice_slice)); + } libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t uu____0[3U]; memcpy( uu____0, state, @@ -3290,53 +3424,57 @@ libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K_ libcrux_ml_kem_hash_functions_portable_PortableHash____3size_t *self, uint8_t ret[3U][504U]) { uint8_t out[3U][504U] = {{0U}}; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( - &self->shake128_state[i0], - Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, - Eurydice_slice));); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_sha3_portable_incremental_shake128_squeeze_first_three_blocks( + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)504U, out[i0], uint8_t, + Eurydice_slice)); + } memcpy(ret, out, (size_t)3U * sizeof(uint8_t[504U])); } static inline bool -libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_3size_t_504size_t( +libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_504size_t( uint8_t randomness[3U][504U], size_t *sampled_coefficients, int16_t (*out)[272U]) { - KRML_MAYBE_FOR3( - i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; - for (size_t i = (size_t)0U; i < (size_t)504U / (size_t)24U; i++) { - size_t r = i; - if (sampled_coefficients[i1] < - LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)504U, randomness[i1], - (CLITERAL(core_ops_range_Range__size_t){ - .start = r * (size_t)24U, - .end = r * (size_t)24U + (size_t)24U}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - size_t sampled = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( - uu____0, - Eurydice_array_to_subslice( - (size_t)272U, out[i1], - (CLITERAL(core_ops_range_Range__size_t){ - .start = sampled_coefficients[i1], - .end = sampled_coefficients[i1] + (size_t)16U}), - int16_t, core_ops_range_Range__size_t, Eurydice_slice)); - size_t uu____1 = i1; - sampled_coefficients[uu____1] = - sampled_coefficients[uu____1] + sampled; - } - }); - bool done = true; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - if (sampled_coefficients[i0] >= + for (size_t i0 = (size_t)0U; i0 < (size_t)3U; i0++) { + size_t i1 = i0; + for (size_t i = (size_t)0U; i < (size_t)504U / (size_t)24U; i++) { + size_t r = i; + if (sampled_coefficients[i1] < LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { - sampled_coefficients[i0] = - LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; - } else { done = false; }); + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)504U, randomness[i1], + (CLITERAL(core_ops_range_Range__size_t){ + .start = r * (size_t)24U, + .end = r * (size_t)24U + (size_t)24U}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + size_t sampled = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( + uu____0, + Eurydice_array_to_subslice( + (size_t)272U, out[i1], + (CLITERAL(core_ops_range_Range__size_t){ + .start = sampled_coefficients[i1], + .end = sampled_coefficients[i1] + (size_t)16U}), + int16_t, core_ops_range_Range__size_t, Eurydice_slice)); + size_t uu____1 = i1; + sampled_coefficients[uu____1] = sampled_coefficients[uu____1] + sampled; + } + } + } + bool done = true; + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + if (sampled_coefficients[i0] >= + LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { + sampled_coefficients[i0] = + LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; + } else { + done = false; + } + } return done; } @@ -3345,66 +3483,71 @@ libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K_ libcrux_ml_kem_hash_functions_portable_PortableHash____3size_t *self, uint8_t ret[3U][168U]) { uint8_t out[3U][168U] = {{0U}}; - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_portable_incremental_shake128_squeeze_next_block( - &self->shake128_state[i0], - Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, - Eurydice_slice));); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_sha3_portable_incremental_shake128_squeeze_next_block( + &self->shake128_state[i0], + Eurydice_array_to_slice((size_t)168U, out[i0], uint8_t, + Eurydice_slice)); + } memcpy(ret, out, (size_t)3U * sizeof(uint8_t[168U])); } static inline bool -libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_3size_t_168size_t( +libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_168size_t( uint8_t randomness[3U][168U], size_t *sampled_coefficients, int16_t (*out)[272U]) { - KRML_MAYBE_FOR3( - i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; - for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)24U; i++) { - size_t r = i; - if (sampled_coefficients[i1] < - LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)168U, randomness[i1], - (CLITERAL(core_ops_range_Range__size_t){ - .start = r * (size_t)24U, - .end = r * (size_t)24U + (size_t)24U}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - size_t sampled = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___rej_sample( - uu____0, - Eurydice_array_to_subslice( - (size_t)272U, out[i1], - (CLITERAL(core_ops_range_Range__size_t){ - .start = sampled_coefficients[i1], - .end = sampled_coefficients[i1] + (size_t)16U}), - int16_t, core_ops_range_Range__size_t, Eurydice_slice)); - size_t uu____1 = i1; - sampled_coefficients[uu____1] = - sampled_coefficients[uu____1] + sampled; - } - }); - bool done = true; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - if (sampled_coefficients[i0] >= + for (size_t i0 = (size_t)0U; i0 < (size_t)3U; i0++) { + size_t i1 = i0; + for (size_t i = (size_t)0U; i < (size_t)168U / (size_t)24U; i++) { + size_t r = i; + if (sampled_coefficients[i1] < LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { - sampled_coefficients[i0] = - LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; - } else { done = false; }); + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)168U, randomness[i1], + (CLITERAL(core_ops_range_Range__size_t){ + .start = r * (size_t)24U, + .end = r * (size_t)24U + (size_t)24U}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + size_t sampled = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___rej_sample( + uu____0, + Eurydice_array_to_subslice( + (size_t)272U, out[i1], + (CLITERAL(core_ops_range_Range__size_t){ + .start = sampled_coefficients[i1], + .end = sampled_coefficients[i1] + (size_t)16U}), + int16_t, core_ops_range_Range__size_t, Eurydice_slice)); + size_t uu____1 = i1; + sampled_coefficients[uu____1] = sampled_coefficients[uu____1] + sampled; + } + } + } + bool done = true; + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + if (sampled_coefficients[i0] >= + LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT) { + sampled_coefficients[i0] = + LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT; + } else { + done = false; + } + } return done; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice a) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___from_i16_array( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___from_i16_array( Eurydice_slice_subslice( a, (CLITERAL(core_ops_range_Range__size_t){ @@ -3416,10 +3559,10 @@ libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vec return result; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_sampling_sample_from_xof_closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_sampling_sample_from_xof_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( int16_t s[272U]) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_array_to_subslice((size_t)272U, s, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)256U}), @@ -3428,9 +3571,9 @@ libcrux_ml_kem_sampling_sample_from_xof_closure__libcrux_ml_kem_vector_portable_ } static inline void -libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( +libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( uint8_t seeds[3U][34U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { size_t sampled_coefficients[3U] = {0U}; int16_t out[3U][272U] = {{0U}}; @@ -3445,7 +3588,7 @@ libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_portable_Portable uint8_t uu____1[3U][504U]; memcpy(uu____1, randomness0, (size_t)3U * sizeof(uint8_t[504U])); bool done = - libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_3size_t_504size_t( + libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_504size_t( uu____1, sampled_coefficients, out); while (true) { if (done) { @@ -3457,108 +3600,114 @@ libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_portable_Portable uint8_t uu____2[3U][168U]; memcpy(uu____2, randomness, (size_t)3U * sizeof(uint8_t[168U])); done = - libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_PortableVector_3size_t_168size_t( + libcrux_ml_kem_sampling_sample_from_uniform_distribution_next__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_168size_t( uu____2, sampled_coefficients, out); } } int16_t uu____3[3U][272U]; memcpy(uu____3, out, (size_t)3U * sizeof(int16_t[272U])); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret0[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - ret0[i] = - libcrux_ml_kem_sampling_sample_from_xof_closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( - uu____3[i]);); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + ret0[i] = + libcrux_ml_kem_sampling_sample_from_xof_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + uu____3[i]); + } memcpy( ret, ret0, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline void -libcrux_ml_kem_matrix_sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( +libcrux_ml_kem_matrix_sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( uint8_t seed[34U], bool transpose, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U][3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[3U][3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - libcrux_ml_kem_matrix_sample_matrix_A_closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( - i, A_transpose[i]);); - KRML_MAYBE_FOR3( - i0, (size_t)0U, (size_t)3U, (size_t)1U, size_t i1 = i0; - uint8_t uu____0[34U]; - memcpy(uu____0, seed, (size_t)34U * sizeof(uint8_t)); - uint8_t seeds[3U][34U]; KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - memcpy(seeds[i], uu____0, (size_t)34U * sizeof(uint8_t));); - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t j = i; - seeds[j][32U] = (uint8_t)i1; seeds[j][33U] = (uint8_t)j;); - uint8_t uu____1[3U][34U]; - memcpy(uu____1, seeds, (size_t)3U * sizeof(uint8_t[34U])); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - sampled[3U]; - libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( - uu____1, sampled); - for ( - size_t i = (size_t)0U; - i < - core_slice___Slice_T___len( - Eurydice_array_to_slice( - (size_t)3U, sampled, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, - Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, - size_t); - i++) { - size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - sample = sampled[j]; - if (transpose) { - A_transpose[j][i1] = sample; - } else { - A_transpose[i1][j] = sample; - } - }); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + libcrux_ml_kem_matrix_sample_matrix_A_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + i, A_transpose[i]); + } + for (size_t i0 = (size_t)0U; i0 < (size_t)3U; i0++) { + size_t i1 = i0; + uint8_t uu____0[34U]; + memcpy(uu____0, seed, (size_t)34U * sizeof(uint8_t)); + uint8_t seeds[3U][34U]; + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + memcpy(seeds[i], uu____0, (size_t)34U * sizeof(uint8_t)); + } + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t j = i; + seeds[j][32U] = (uint8_t)i1; + seeds[j][33U] = (uint8_t)j; + } + uint8_t uu____1[3U][34U]; + memcpy(uu____1, seeds, (size_t)3U * sizeof(uint8_t[34U])); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + sampled[3U]; + libcrux_ml_kem_sampling_sample_from_xof__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + uu____1, sampled); + for ( + size_t i = (size_t)0U; + i < + core_slice___Slice_T___len( + Eurydice_array_to_slice( + (size_t)3U, sampled, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, + Eurydice_slice), + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, + size_t); + i++) { + size_t j = i; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + sample = sampled[j]; + if (transpose) { + A_transpose[j][i1] = sample; + } else { + A_transpose[i1][j] = sample; + } + } + } memcpy( ret, A_transpose, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U])); } typedef struct - K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t_s { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t_s { + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector fst[3U]; uint8_t snd; -} K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t; +} K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t; -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt_closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( size_t _i) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); } static inline void libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__portable__PortableHash_K____PRFxN___3size_t_128size_t( uint8_t (*input)[33U], uint8_t ret[3U][128U]) { uint8_t out[3U][128U] = {{0U}}; - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_sha3_portable_shake256( - Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t, - Eurydice_slice), - Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, - Eurydice_slice));); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_sha3_portable_shake256( + Eurydice_array_to_slice((size_t)128U, out[i0], uint8_t, Eurydice_slice), + Eurydice_array_to_slice((size_t)33U, input[i0], uint8_t, + Eurydice_slice)); + } memcpy(ret, out, (size_t)3U * sizeof(uint8_t[128U])); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_sampling_sample_from_binomial_distribution_2__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_sampling_sample_from_binomial_distribution_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice randomness) { int16_t sampled_i16s[256U] = {0U}; for (size_t i0 = (size_t)0U; @@ -3600,13 +3749,13 @@ libcrux_ml_kem_sampling_sample_from_binomial_distribution_2__libcrux_ml_kem_vect sampled_i16s[(size_t)8U * chunk_number + offset] = outcome_1 - outcome_2; } } - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_array_to_slice((size_t)256U, sampled_i16s, int16_t, Eurydice_slice)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_sampling_sample_from_binomial_distribution_3__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_sampling_sample_from_binomial_distribution_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_slice randomness) { int16_t sampled_i16s[256U] = {0U}; for (size_t i0 = (size_t)0U; @@ -3646,164 +3795,170 @@ libcrux_ml_kem_sampling_sample_from_binomial_distribution_3__libcrux_ml_kem_vect sampled_i16s[(size_t)4U * chunk_number + offset] = outcome_1 - outcome_2; } } - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___from_i16_array__libcrux_ml_kem_vector_portable_PortableVector( + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___from_i16_array__libcrux_ml_kem_vector_portable_vector_type_PortableVector( Eurydice_array_to_slice((size_t)256U, sampled_i16s, int16_t, Eurydice_slice)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_slice randomness) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0; uu____0 = - libcrux_ml_kem_sampling_sample_from_binomial_distribution_2__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_sampling_sample_from_binomial_distribution_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( randomness); return uu____0; } static inline void -libcrux_ml_kem_ntt_ntt_at_layer_7__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_ntt_ntt_at_layer_7__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { size_t step = LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT / (size_t)2U; for (size_t i = (size_t)0U; i < step; i++) { size_t j = i; - libcrux_ml_kem_vector_portable_PortableVector t = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___multiply_by_constant( + libcrux_ml_kem_vector_portable_vector_type_PortableVector t = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___multiply_by_constant( re->coefficients[j + step], (int16_t)-1600); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( re->coefficients[j], &t); re->coefficients[j + step] = uu____0; - libcrux_ml_kem_vector_portable_PortableVector uu____1 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( re->coefficients[j], &t); re->coefficients[j] = uu____1; } } static inline void -libcrux_ml_kem_ntt_ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_ntt_ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re) { - libcrux_ml_kem_ntt_ntt_at_layer_7__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_7__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re); size_t zeta_i = (size_t)1U; - libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)6U, (size_t)3U); - libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)5U, (size_t)3U); - libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_4_plus__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)4U, (size_t)3U); - libcrux_ml_kem_ntt_ntt_at_layer_3__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_3__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)3U, (size_t)3U); - libcrux_ml_kem_ntt_ntt_at_layer_2__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_2__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)2U, (size_t)3U); - libcrux_ml_kem_ntt_ntt_at_layer_1__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_ntt_ntt_at_layer_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &zeta_i, re, (size_t)1U, (size_t)3U); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___poly_barrett_reduce__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___poly_barrett_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re); } -static inline K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t -libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( +static inline K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t +libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( uint8_t prf_input[33U], uint8_t domain_separator) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re_as_ntt[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - re_as_ntt[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + re_as_ntt[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + } uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[3U][33U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - memcpy(prf_inputs[i], uu____0, (size_t)33U * sizeof(uint8_t));); - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - prf_inputs[i0][32U] = domain_separator; - domain_separator = (uint32_t)domain_separator + 1U;); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + memcpy(prf_inputs[i], uu____0, (size_t)33U * sizeof(uint8_t)); + } + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + prf_inputs[i0][32U] = domain_separator; + domain_separator = (uint32_t)domain_separator + 1U; + } uint8_t prf_outputs[3U][128U]; libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__portable__PortableHash_K____PRFxN___3size_t_128size_t( prf_inputs, prf_outputs); - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - uu____1 = - libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( - Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], - uint8_t, Eurydice_slice)); - re_as_ntt[i0] = uu____1; - libcrux_ml_kem_ntt_ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_PortableVector( - &re_as_ntt[i0]);); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + uu____1 = + libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( + Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t, + Eurydice_slice)); + re_as_ntt[i0] = uu____1; + libcrux_ml_kem_ntt_ntt_binomially_sampled_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &re_as_ntt[i0]); + } + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____2[3U]; memcpy( uu____2, re_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t lit; memcpy( lit.fst, uu____2, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); lit.snd = domain_separator; return lit; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_ind_cpa_sample_ring_element_cbd_closure__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_ind_cpa_sample_ring_element_cbd_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( size_t _i) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); } -static inline K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t -libcrux_ml_kem_ind_cpa_sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( +static inline K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t +libcrux_ml_kem_ind_cpa_sample_ring_element_cbd__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( uint8_t prf_input[33U], uint8_t domain_separator) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_1[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - error_1[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + error_1[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + } uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); uint8_t prf_inputs[3U][33U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - memcpy(prf_inputs[i], uu____0, (size_t)33U * sizeof(uint8_t));); - KRML_MAYBE_FOR3(i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - prf_inputs[i0][32U] = domain_separator; - domain_separator = (uint32_t)domain_separator + 1U;); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + memcpy(prf_inputs[i], uu____0, (size_t)33U * sizeof(uint8_t)); + } + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + prf_inputs[i0][32U] = domain_separator; + domain_separator = (uint32_t)domain_separator + 1U; + } uint8_t prf_outputs[3U][128U]; libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__portable__PortableHash_K____PRFxN___3size_t_128size_t( prf_inputs, prf_outputs); - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - uu____1 = - libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( - Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], - uint8_t, Eurydice_slice)); - error_1[i0] = uu____1;); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + uu____1 = + libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( + Eurydice_array_to_slice((size_t)128U, prf_outputs[i0], uint8_t, + Eurydice_slice)); + error_1[i0] = uu____1; + } + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____2[3U]; memcpy( uu____2, error_1, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t lit; memcpy( lit.fst, uu____2, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); lit.snd = domain_separator; return lit; } @@ -3818,63 +3973,64 @@ libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K_ memcpy(ret, digest, (size_t)128U * sizeof(uint8_t)); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_matrix_compute_vector_u_closure__libcrux_ml_kem_vector_portable_PortableVector_3size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_matrix_compute_vector_u_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( size_t _i) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); } static inline void -libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t j = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_normal_form = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( - self->coefficients[j], (int16_t)1441); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_normal_form = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( + self->coefficients[j], (int16_t)1441); + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( coefficient_normal_form, &error->coefficients[j])); self->coefficients[j] = uu____0; } } static inline void -libcrux_ml_kem_matrix_compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector ( +libcrux_ml_kem_matrix_compute_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ( *a_as_ntt)[3U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *r_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_1, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - result[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + result[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + } for ( size_t i0 = (size_t)0U; i0 < core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, a_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U], Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U], size_t); i0++) { size_t i1 = i0; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *row = a_as_ntt[i1]; for ( size_t i = (size_t)0U; @@ -3882,158 +4038,163 @@ libcrux_ml_kem_matrix_compute_vector_u__libcrux_ml_kem_vector_portable_PortableV core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, row, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *a_element = &row[j]; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector product = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( a_element, &r_as_ntt[j]); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result[i1], &product); } - libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result[i1]); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &result[i1], &error_1[i1]); } memcpy( ret, result, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_traits_decompress_1__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector v) { - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___ZERO(); - return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___bitwise_and_with_constant( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___sub( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_traits_decompress_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___ZERO(); + return libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___bitwise_and_with_constant( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___sub( uu____0, &v), (int16_t)1665); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_PortableVector( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( uint8_t serialized[32U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); - KRML_MAYBE_FOR16( - i, (size_t)0U, (size_t)16U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_compressed = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___deserialize_1( - Eurydice_array_to_subslice( - (size_t)32U, serialized, - (CLITERAL(core_ops_range_Range__size_t){ - .start = (size_t)2U * i0, - .end = (size_t)2U * i0 + (size_t)2U}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector_traits_decompress_1__libcrux_ml_kem_vector_portable_PortableVector( - coefficient_compressed); - re.coefficients[i0] = uu____0;); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + for (size_t i = (size_t)0U; i < (size_t)16U; i++) { + size_t i0 = i; + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_compressed = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___deserialize_1( + Eurydice_array_to_subslice( + (size_t)32U, serialized, + (CLITERAL(core_ops_range_Range__size_t){ + .start = (size_t)2U * i0, + .end = (size_t)2U * i0 + (size_t)2U}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_traits_decompress_1__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + coefficient_compressed); + re.coefficients[i0] = uu____0; + } return re; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_message_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_message_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *message, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_normal_form = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( - result.coefficients[i0], (int16_t)1441); - libcrux_ml_kem_vector_portable_PortableVector tmp = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_normal_form = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( + result.coefficients[i0], (int16_t)1441); + libcrux_ml_kem_vector_portable_vector_type_PortableVector tmp = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( self->coefficients[i0], &message->coefficients[i0]); - libcrux_ml_kem_vector_portable_PortableVector tmp0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector tmp0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( coefficient_normal_form, &tmp); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( tmp0); result.coefficients[i0] = uu____0; } return result; } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_matrix_compute_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_matrix_compute_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *t_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *r_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_2, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *message) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - product = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( - &t_as_ntt[i0], &r_as_ntt[i0]); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - &result, &product);); - libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + size_t i0 = i; + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + product = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + &t_as_ntt[i0], &r_as_ntt[i0]); + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + &result, &product); + } + libcrux_ml_kem_invert_ntt_invert_ntt_montgomery__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result); result = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_message_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_message_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( error_2, message, result); return result; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_compress___10int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_compress___10int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - int16_t uu____0 = libcrux_ml_kem_vector_compress_ciphertext_coefficient( - (uint8_t)(int32_t)10, (uint16_t)v.elements[i0]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( + (uint8_t)(int32_t)10, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress___10int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_compress___10int32_t(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress___10int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_compress___10int32_t(v); } static inline void -libcrux_ml_kem_serialize_compress_then_serialize_10__libcrux_ml_kem_vector_portable_PortableVector_320size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_serialize_compress_then_serialize_10__libcrux_ml_kem_vector_portable_vector_type_PortableVector_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, uint8_t ret[320U]) { uint8_t serialized[320U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress___10int32_t( - libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress___10int32_t( + libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[i0])); uint8_t bytes[20U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_10( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_10( coefficient, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)320U, serialized, @@ -4048,40 +4209,41 @@ libcrux_ml_kem_serialize_compress_then_serialize_10__libcrux_ml_kem_vector_porta memcpy(ret, serialized, (size_t)320U * sizeof(uint8_t)); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_compress___11int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_compress___11int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - int16_t uu____0 = libcrux_ml_kem_vector_compress_ciphertext_coefficient( - (uint8_t)(int32_t)11, (uint16_t)v.elements[i0]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( + (uint8_t)(int32_t)11, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress___11int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_compress___11int32_t(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress___11int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_compress___11int32_t(v); } static inline void -libcrux_ml_kem_serialize_compress_then_serialize_11__libcrux_ml_kem_vector_portable_PortableVector_320size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_serialize_compress_then_serialize_11__libcrux_ml_kem_vector_portable_vector_type_PortableVector_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, uint8_t ret[320U]) { uint8_t serialized[320U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress___11int32_t( - libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress___11int32_t( + libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[i0])); uint8_t bytes[22U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_11( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_11( coefficient, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)320U, serialized, @@ -4097,19 +4259,19 @@ libcrux_ml_kem_serialize_compress_then_serialize_11__libcrux_ml_kem_vector_porta } static inline void -libcrux_ml_kem_serialize_compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t_320size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_serialize_compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, uint8_t ret[320U]) { uint8_t uu____0[320U]; - libcrux_ml_kem_serialize_compress_then_serialize_10__libcrux_ml_kem_vector_portable_PortableVector_320size_t( + libcrux_ml_kem_serialize_compress_then_serialize_10__libcrux_ml_kem_vector_portable_vector_type_PortableVector_320size_t( re, uu____0); memcpy(ret, uu____0, (size_t)320U * sizeof(uint8_t)); } static inline void -libcrux_ml_kem_ind_cpa_compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t_960size_t_10size_t_320size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_ind_cpa_compress_then_serialize_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_960size_t_10size_t_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector input[3U], Eurydice_slice out) { for ( @@ -4118,13 +4280,13 @@ libcrux_ml_kem_ind_cpa_compress_then_serialize_u__libcrux_ml_kem_vector_portable core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, input, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = input[i0]; Eurydice_slice uu____0 = Eurydice_slice_subslice( out, @@ -4133,7 +4295,7 @@ libcrux_ml_kem_ind_cpa_compress_then_serialize_u__libcrux_ml_kem_vector_portable .end = (i0 + (size_t)1U) * ((size_t)960U / (size_t)3U)}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); uint8_t ret[320U]; - libcrux_ml_kem_serialize_compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_PortableVector_10size_t_320size_t( + libcrux_ml_kem_serialize_compress_then_serialize_ring_element_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_10size_t_320size_t( &re, ret); core_slice___Slice_T___copy_from_slice( uu____0, @@ -4142,39 +4304,40 @@ libcrux_ml_kem_ind_cpa_compress_then_serialize_u__libcrux_ml_kem_vector_portable } } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_compress___4int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_compress___4int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - int16_t uu____0 = libcrux_ml_kem_vector_compress_ciphertext_coefficient( - (uint8_t)(int32_t)4, (uint16_t)v.elements[i0]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( + (uint8_t)(int32_t)4, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress___4int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_compress___4int32_t(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress___4int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_compress___4int32_t(v); } static inline void -libcrux_ml_kem_serialize_compress_then_serialize_4__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_serialize_compress_then_serialize_4__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re, Eurydice_slice serialized) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress___4int32_t( - libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress___4int32_t( + libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re.coefficients[i0])); uint8_t bytes[8U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_4( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_4( coefficient, bytes); Eurydice_slice uu____0 = Eurydice_slice_subslice( serialized, @@ -4188,39 +4351,40 @@ libcrux_ml_kem_serialize_compress_then_serialize_4__libcrux_ml_kem_vector_portab } } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_compress___5int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_compress_compress___5int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_VECTOR_TRAITS_FIELD_ELEMENTS_IN_VECTOR; i++) { size_t i0 = i; - int16_t uu____0 = libcrux_ml_kem_vector_compress_ciphertext_coefficient( - (uint8_t)(int32_t)5, (uint16_t)v.elements[i0]); + int16_t uu____0 = + libcrux_ml_kem_vector_portable_compress_compress_ciphertext_coefficient( + (uint8_t)(int32_t)5, (uint16_t)v.elements[i0]); v.elements[i0] = uu____0; } return v; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress___5int32_t( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector_compress___5int32_t(v); +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress___5int32_t( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable_compress_compress___5int32_t(v); } static inline void -libcrux_ml_kem_serialize_compress_then_serialize_5__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_serialize_compress_then_serialize_5__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re, Eurydice_slice serialized) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficients = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___compress___5int32_t( - libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficients = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___compress___5int32_t( + libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re.coefficients[i0])); uint8_t bytes[10U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_5( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_5( coefficients, bytes); Eurydice_slice uu____0 = Eurydice_slice_subslice( serialized, @@ -4235,102 +4399,102 @@ libcrux_ml_kem_serialize_compress_then_serialize_5__libcrux_ml_kem_vector_portab } static inline void -libcrux_ml_kem_serialize_compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t_128size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_serialize_compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_128size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re, Eurydice_slice out) { - libcrux_ml_kem_serialize_compress_then_serialize_4__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_serialize_compress_then_serialize_4__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re, out); } static inline void -libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( Eurydice_slice public_key, uint8_t message[32U], Eurydice_slice randomness, uint8_t ret[1088U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[3U]; - libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1152size_t_3size_t( + libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1152size_t_3size_t( Eurydice_slice_subslice_to(public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), t_as_ntt); Eurydice_slice seed = Eurydice_slice_subslice_from( public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[3U][3U]; uint8_t ret0[34U]; libcrux_ml_kem_utils_into_padded_array___34size_t(seed, ret0); - libcrux_ml_kem_matrix_sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + libcrux_ml_kem_matrix_sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( ret0, false, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array___33size_t(randomness, prf_input); uint8_t uu____0[33U]; memcpy(uu____0, prf_input, (size_t)33U * sizeof(uint8_t)); - K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t uu____1 = - libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( + libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( uu____0, 0U); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector r_as_ntt[3U]; memcpy( r_as_ntt, uu____1.fst, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator0 = uu____1.snd; uint8_t uu____2[33U]; memcpy(uu____2, prf_input, (size_t)33U * sizeof(uint8_t)); - K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t uu____3 = - libcrux_ml_kem_ind_cpa_sample_ring_element_cbd__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( + libcrux_ml_kem_ind_cpa_sample_ring_element_cbd__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_128size_t_2size_t( uu____2, domain_separator0); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_1[3U]; memcpy( error_1, uu____3.fst, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator = uu____3.snd; prf_input[32U] = domain_separator; uint8_t prf_output[128U]; libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__portable__PortableHash_K____PRF___3size_t_128size_t( Eurydice_array_to_slice((size_t)33U, prf_input, uint8_t, Eurydice_slice), prf_output); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_2 = - libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_PortableVector_2size_t( + libcrux_ml_kem_sampling_sample_from_binomial_distribution__libcrux_ml_kem_vector_portable_vector_type_PortableVector_2size_t( Eurydice_array_to_slice((size_t)128U, prf_output, uint8_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector u[3U]; - libcrux_ml_kem_matrix_compute_vector_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_matrix_compute_vector_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( A_transpose, r_as_ntt, error_1, u); uint8_t uu____4[32U]; memcpy(uu____4, message, (size_t)32U * sizeof(uint8_t)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector message_as_ring_element = - libcrux_ml_kem_serialize_deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_serialize_deserialize_then_decompress_message__libcrux_ml_kem_vector_portable_vector_type_PortableVector( uu____4); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector - v = libcrux_ml_kem_matrix_compute_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector + v = libcrux_ml_kem_matrix_compute_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( t_as_ntt, r_as_ntt, &error_2, &message_as_ring_element); uint8_t ciphertext[1088U] = {0U}; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____5[3U]; memcpy( uu____5, u, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - libcrux_ml_kem_ind_cpa_compress_then_serialize_u__libcrux_ml_kem_vector_portable_PortableVector_3size_t_960size_t_10size_t_320size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + libcrux_ml_kem_ind_cpa_compress_then_serialize_u__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_960size_t_10size_t_320size_t( uu____5, Eurydice_array_to_subslice( (size_t)1088U, ciphertext, (CLITERAL(core_ops_range_Range__size_t){ .start = (size_t)0U, .end = (size_t)960U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____6 = v; - libcrux_ml_kem_serialize_compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_PortableVector_4size_t_128size_t( + libcrux_ml_kem_serialize_compress_then_serialize_ring_element_v__libcrux_ml_kem_vector_portable_vector_type_PortableVector_4size_t_128size_t( uu____6, Eurydice_array_to_subslice_from((size_t)1088U, ciphertext, (size_t)960U, uint8_t, size_t, Eurydice_slice)); @@ -4349,7 +4513,7 @@ libcrux_ml_kem_ind_cca___libcrux_ml_kem__ind_cca__Variant_for_libcrux_ml_kem__in } static inline void -libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( +libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( libcrux_ml_kem_types_MlKemPrivateKey____2400size_t *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t uu____0 = @@ -4373,7 +4537,7 @@ libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVecto Eurydice_slice ind_cpa_public_key_hash = uu____2.fst; Eurydice_slice implicit_rejection_value = uu____2.snd; uint8_t decrypted[32U]; - libcrux_ml_kem_ind_cpa_decrypt__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1088size_t_960size_t_10size_t_4size_t( + libcrux_ml_kem_ind_cpa_decrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1088size_t_960size_t_10size_t_4size_t( ind_cpa_secret_key, ciphertext->value, decrypted); uint8_t to_hash0[64U]; libcrux_ml_kem_utils_into_padded_array___64size_t( @@ -4414,7 +4578,7 @@ libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVecto uint8_t uu____6[32U]; memcpy(uu____6, decrypted, (size_t)32U * sizeof(uint8_t)); uint8_t expected_ciphertext[1088U]; - libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( + libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____5, uu____6, pseudorandomness, expected_ciphertext); Eurydice_slice uu____7 = libcrux_ml_kem_types___core__convert__AsRef__Slice_u8___for_libcrux_ml_kem__types__MlKemCiphertext_SIZE___1__as_ref___1088size_t( @@ -4446,7 +4610,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_decapsulate___3size_t_2400size_t_ libcrux_ml_kem_types_MlKemPrivateKey____2400size_t *private_key, libcrux_ml_kem_mlkem768_MlKem768Ciphertext *ciphertext, uint8_t ret[32U]) { uint8_t ret0[32U]; - libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( + libcrux_ml_kem_ind_cca_decapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_2400size_t_1152size_t_1184size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t_1120size_t( private_key, ciphertext, ret0); memcpy(ret, ret0, (size_t)32U * sizeof(uint8_t)); } @@ -4481,7 +4645,7 @@ libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K_ } static inline K___libcrux_ml_kem_types_MlKemCiphertext___1088size_t___uint8_t_32size_t_ -libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( libcrux_ml_kem_types_MlKemPublicKey____1184size_t *public_key, uint8_t randomness[32U]) { uint8_t randomness0[32U]; @@ -4527,7 +4691,7 @@ libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVecto uint8_t uu____3[32U]; memcpy(uu____3, randomness0, (size_t)32U * sizeof(uint8_t)); uint8_t ciphertext[1088U]; - libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( + libcrux_ml_kem_ind_cpa_encrypt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1088size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____2, uu____3, pseudorandomness, ciphertext); uint8_t uu____4[1088U]; memcpy(uu____4, ciphertext, (size_t)1088U * sizeof(uint8_t)); @@ -4553,7 +4717,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_encapsulate___3size_t_1088size_t_ libcrux_ml_kem_types_MlKemPublicKey____1184size_t *uu____0 = public_key; uint8_t uu____1[32U]; memcpy(uu____1, randomness, (size_t)32U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( + return libcrux_ml_kem_ind_cca_encapsulate__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___libcrux_ml_kem_ind_cca_MlKem_3size_t_1088size_t_1184size_t_1152size_t_960size_t_128size_t_10size_t_4size_t_320size_t_2size_t_128size_t_2size_t_128size_t( uu____0, uu____1); } @@ -4568,70 +4732,71 @@ libcrux_ml_kem_mlkem768_portable_encapsulate( uu____0, uu____1); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_matrix_compute_As_plus_e_closure__libcrux_ml_kem_vector_portable_PortableVector_3size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_matrix_compute_As_plus_e_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( size_t _i) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_traits_to_standard_domain__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_vector_portable_PortableVector v) { - return libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___montgomery_multiply_by_constant( +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_traits_to_standard_domain__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector v) { + return libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___montgomery_multiply_by_constant( v, LIBCRUX_ML_KEM_VECTOR_TRAITS_MONTGOMERY_R_SQUARED_MOD_FIELD_MODULUS); } static inline void -libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_standard_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_standard_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *self, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error) { for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t j = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient_normal_form = - libcrux_ml_kem_vector_traits_to_standard_domain__libcrux_ml_kem_vector_portable_PortableVector( - self->coefficients[j]); - libcrux_ml_kem_vector_portable_PortableVector uu____0 = - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___barrett_reduce( - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___add( + libcrux_ml_kem_vector_portable_vector_type_PortableVector + coefficient_normal_form = + libcrux_ml_kem_vector_traits_to_standard_domain__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + self->coefficients[j]); + libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___barrett_reduce( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___add( coefficient_normal_form, &error->coefficients[j])); self->coefficients[j] = uu____0; } } static inline void -libcrux_ml_kem_matrix_compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_3size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector ( +libcrux_ml_kem_matrix_compute_As_plus_e__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ( *matrix_A)[3U], - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *s_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *error_as_ntt, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector result[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - result[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + result[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + } for ( size_t i0 = (size_t)0U; i0 < core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, matrix_A, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U], Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector [3U], size_t); i0++) { size_t i1 = i0; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *row = matrix_A[i1]; for ( size_t i = (size_t)0U; @@ -4639,45 +4804,45 @@ libcrux_ml_kem_matrix_compute_As_plus_e__libcrux_ml_kem_vector_portable_Portable core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, row, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t j = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *matrix_element = &row[j]; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector product = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ntt_multiply__libcrux_ml_kem_vector_portable_vector_type_PortableVector( matrix_element, &s_as_ntt[j]); - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_to_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( &result[i1], &product); } - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_standard_error_reduce__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___add_standard_error_reduce__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &result[i1], &error_as_ntt[i1]); } memcpy( ret, result, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline void -libcrux_ml_kem_serialize_serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_serialize_serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector *re, uint8_t ret[384U]) { uint8_t serialized[384U] = {0U}; for (size_t i = (size_t)0U; i < LIBCRUX_ML_KEM_POLYNOMIAL_VECTORS_IN_RING_ELEMENT; i++) { size_t i0 = i; - libcrux_ml_kem_vector_portable_PortableVector coefficient = - libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_vector_portable_vector_type_PortableVector coefficient = + libcrux_ml_kem_vector_traits_to_unsigned_representative__libcrux_ml_kem_vector_portable_vector_type_PortableVector( re->coefficients[i0]); uint8_t bytes[24U]; - libcrux_ml_kem_vector___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__PortableVector___serialize_12( + libcrux_ml_kem_vector_portable___libcrux_ml_kem__vector__traits__Operations_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___serialize_12( coefficient, bytes); Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)384U, serialized, @@ -4693,8 +4858,8 @@ libcrux_ml_kem_serialize_serialize_uncompressed_ring_element__libcrux_ml_kem_vec } static inline void -libcrux_ml_kem_ind_cpa_serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_ind_cpa_serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector key[3U], uint8_t ret[1152U]) { uint8_t out[1152U] = {0U}; @@ -4704,13 +4869,13 @@ libcrux_ml_kem_ind_cpa_serialize_secret_key__libcrux_ml_kem_vector_portable_Port core_slice___Slice_T___len( Eurydice_array_to_slice( (size_t)3U, key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, Eurydice_slice), - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector, + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector, size_t); i++) { size_t i0 = i; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector re = key[i0]; Eurydice_slice uu____0 = Eurydice_array_to_subslice( (size_t)1152U, out, @@ -4720,7 +4885,7 @@ libcrux_ml_kem_ind_cpa_serialize_secret_key__libcrux_ml_kem_vector_portable_Port LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); uint8_t ret0[384U]; - libcrux_ml_kem_serialize_serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_serialize_serialize_uncompressed_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( &re, ret0); core_slice___Slice_T___copy_from_slice( uu____0, @@ -4731,8 +4896,8 @@ libcrux_ml_kem_ind_cpa_serialize_secret_key__libcrux_ml_kem_vector_portable_Port } static inline void -libcrux_ml_kem_ind_cpa_serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector +libcrux_ml_kem_ind_cpa_serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[3U], Eurydice_slice seed_for_a, uint8_t ret[1184U]) { uint8_t public_key_serialized[1184U] = {0U}; @@ -4741,15 +4906,15 @@ libcrux_ml_kem_ind_cpa_serialize_public_key__libcrux_ml_kem_vector_portable_Port (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = (size_t)1152U}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____1[3U]; memcpy( uu____1, t_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t ret0[1152U]; - libcrux_ml_kem_ind_cpa_serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t( + libcrux_ml_kem_ind_cpa_serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t( uu____1, ret0); core_slice___Slice_T___copy_from_slice( uu____0, @@ -4764,7 +4929,7 @@ libcrux_ml_kem_ind_cpa_serialize_public_key__libcrux_ml_kem_vector_portable_Port } static inline libcrux_ml_kem_utils_extraction_helper_Keypair768 -libcrux_ml_kem_ind_cpa_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_1184size_t_1152size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cpa_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_1184size_t_1152size_t_2size_t_128size_t( Eurydice_slice key_generation_seed) { uint8_t hashed[64U]; libcrux_ml_kem_hash_functions_portable___libcrux_ml_kem__hash_functions__Hash_K__for_libcrux_ml_kem__hash_functions__portable__PortableHash_K____G___3size_t( @@ -4776,64 +4941,64 @@ libcrux_ml_kem_ind_cpa_generate_keypair__libcrux_ml_kem_vector_portable_Portable K___Eurydice_slice_uint8_t_Eurydice_slice_uint8_t); Eurydice_slice seed_for_A = uu____0.fst; Eurydice_slice seed_for_secret_and_error = uu____0.snd; - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector A_transpose[3U][3U]; uint8_t ret[34U]; libcrux_ml_kem_utils_into_padded_array___34size_t(seed_for_A, ret); - libcrux_ml_kem_matrix_sample_matrix_A__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( + libcrux_ml_kem_matrix_sample_matrix_A__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t( ret, true, A_transpose); uint8_t prf_input[33U]; libcrux_ml_kem_utils_into_padded_array___33size_t(seed_for_secret_and_error, prf_input); uint8_t uu____1[33U]; memcpy(uu____1, prf_input, (size_t)33U * sizeof(uint8_t)); - K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector_3size_t__uint8_t + K___libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t__uint8_t uu____2 = - libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( + libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( uu____1, 0U); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector secret_as_ntt[3U]; memcpy( secret_as_ntt, uu____2.fst, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t domain_separator = uu____2.snd; uint8_t uu____3[33U]; memcpy(uu____3, prf_input, (size_t)33U * sizeof(uint8_t)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector error_as_ntt[3U]; memcpy( error_as_ntt, - libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( + libcrux_ml_kem_ind_cpa_sample_vector_cbd_then_ntt__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_2size_t_128size_t( uu____3, domain_separator) .fst, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector t_as_ntt[3U]; - libcrux_ml_kem_matrix_compute_As_plus_e__libcrux_ml_kem_vector_portable_PortableVector_3size_t( + libcrux_ml_kem_matrix_compute_As_plus_e__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t( A_transpose, secret_as_ntt, error_as_ntt, t_as_ntt); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____4[3U]; memcpy( uu____4, t_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t public_key_serialized[1184U]; - libcrux_ml_kem_ind_cpa_serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( + libcrux_ml_kem_ind_cpa_serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( uu____4, seed_for_A, public_key_serialized); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____5[3U]; memcpy( uu____5, secret_as_ntt, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t secret_key_serialized[1152U]; - libcrux_ml_kem_ind_cpa_serialize_secret_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t( + libcrux_ml_kem_ind_cpa_serialize_secret_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t( uu____5, secret_key_serialized); uint8_t uu____6[1152U]; memcpy(uu____6, secret_key_serialized, (size_t)1152U * sizeof(uint8_t)); @@ -4907,7 +5072,7 @@ libcrux_ml_kem_ind_cca_serialize_kem_secret_key__libcrux_ml_kem_hash_functions_p } static inline libcrux_ml_kem_mlkem768_MlKem768KeyPair -libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( +libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( uint8_t randomness[64U]) { Eurydice_slice ind_cpa_keypair_randomness = Eurydice_array_to_subslice( (size_t)64U, randomness, @@ -4920,7 +5085,7 @@ libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_Portable LIBCRUX_ML_KEM_CONSTANTS_CPA_PKE_KEY_GENERATION_SEED_SIZE, uint8_t, size_t, Eurydice_slice); libcrux_ml_kem_utils_extraction_helper_Keypair768 uu____0 = - libcrux_ml_kem_ind_cpa_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_1184size_t_1152size_t_2size_t_128size_t( + libcrux_ml_kem_ind_cpa_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_1184size_t_1152size_t_2size_t_128size_t( ind_cpa_keypair_randomness); uint8_t ind_cpa_private_key[1152U]; memcpy(ind_cpa_private_key, uu____0.fst, (size_t)1152U * sizeof(uint8_t)); @@ -4952,7 +5117,7 @@ libcrux_ml_kem_ind_cca_instantiations_portable_generate_keypair___3size_t_1152si uint8_t randomness[64U]) { uint8_t uu____0[64U]; memcpy(uu____0, randomness, (size_t)64U * sizeof(uint8_t)); - return libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( + return libcrux_ml_kem_ind_cca_generate_keypair__libcrux_ml_kem_vector_portable_vector_type_PortableVector_libcrux_ml_kem_hash_functions_portable_PortableHash___3size_t___3size_t_1152size_t_2400size_t_1184size_t_1152size_t_2size_t_128size_t( uu____0); } @@ -4964,23 +5129,23 @@ libcrux_ml_kem_mlkem768_portable_generate_key_pair(uint8_t randomness[64U]) { uu____0); } -static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_closure__libcrux_ml_kem_vector_portable_PortableVector_1184size_t_3size_t( +static inline libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_serialize_deserialize_ring_elements_reduced_closure__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1184size_t_3size_t( size_t _i) { - return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector(); + return libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); } static inline void -libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1184size_t_3size_t( +libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1184size_t_3size_t( Eurydice_slice public_key, - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector ret[3U]) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[3U]; - KRML_MAYBE_FOR3( - i, (size_t)0U, (size_t)3U, (size_t)1U, - deserialized_pk[i] = - libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_PortableVector();); + for (size_t i = (size_t)0U; i < (size_t)3U; i++) { + deserialized_pk[i] = + libcrux_ml_kem_polynomial__libcrux_ml_kem__polynomial__PolynomialRingElement_Vector__TraitClause_0___ZERO__libcrux_ml_kem_vector_portable_vector_type_PortableVector(); + } for (size_t i = (size_t)0U; i < core_slice___Slice_T___len(public_key, uint8_t, size_t) / LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT; @@ -4993,9 +5158,9 @@ libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vecto .end = i0 * LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT + LIBCRUX_ML_KEM_CONSTANTS_BYTES_PER_RING_ELEMENT}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0 = - libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_PortableVector( + libcrux_ml_kem_serialize_deserialize_to_reduced_ring_element__libcrux_ml_kem_vector_portable_vector_type_PortableVector( ring_element); deserialized_pk[i0] = uu____0; } @@ -5003,27 +5168,27 @@ libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vecto ret, deserialized_pk, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); } static inline bool -libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( +libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( uint8_t *public_key) { - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector deserialized_pk[3U]; - libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_PortableVector_1184size_t_3size_t( + libcrux_ml_kem_serialize_deserialize_ring_elements_reduced__libcrux_ml_kem_vector_portable_vector_type_PortableVector_1184size_t_3size_t( Eurydice_array_to_subslice_to((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), deserialized_pk); - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector uu____0[3U]; memcpy( uu____0, deserialized_pk, (size_t)3U * sizeof( - libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_PortableVector)); + libcrux_ml_kem_polynomial_PolynomialRingElement__libcrux_ml_kem_vector_portable_vector_type_PortableVector)); uint8_t public_key_serialized[1184U]; - libcrux_ml_kem_ind_cpa_serialize_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( + libcrux_ml_kem_ind_cpa_serialize_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( uu____0, Eurydice_array_to_subslice_from((size_t)1184U, public_key, (size_t)1152U, uint8_t, size_t, Eurydice_slice), @@ -5035,7 +5200,7 @@ libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_Porta static inline bool libcrux_ml_kem_ind_cca_instantiations_portable_validate_public_key___3size_t_1152size_t_1184size_t( uint8_t *public_key) { - return libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_PortableVector_3size_t_1152size_t_1184size_t( + return libcrux_ml_kem_ind_cca_validate_public_key__libcrux_ml_kem_vector_portable_vector_type_PortableVector_3size_t_1152size_t_1184size_t( public_key); } @@ -5057,17 +5222,19 @@ libcrux_ml_kem_mlkem768_portable_validate_public_key( return uu____0; } -static inline libcrux_ml_kem_vector_portable_PortableVector -libcrux_ml_kem_vector_portable___core__clone__Clone_for_libcrux_ml_kem__vector__portable__PortableVector___clone( - libcrux_ml_kem_vector_portable_PortableVector *self) { +static inline libcrux_ml_kem_vector_portable_vector_type_PortableVector +libcrux_ml_kem_vector_portable_vector_type___core__clone__Clone_for_libcrux_ml_kem__vector__portable__vector_type__PortableVector___clone( + libcrux_ml_kem_vector_portable_vector_type_PortableVector *self) { return self[0U]; } -typedef int16_t libcrux_ml_kem_vector_MontgomeryFieldElement; +typedef int16_t libcrux_ml_kem_vector_portable_vector_type_FieldElement; -typedef int16_t libcrux_ml_kem_vector_FieldElementTimesMontgomeryR; +typedef int16_t + libcrux_ml_kem_vector_portable_arithmetic_MontgomeryFieldElement; -typedef int16_t libcrux_ml_kem_vector_FieldElement; +typedef int16_t + libcrux_ml_kem_vector_portable_arithmetic_FieldElementTimesMontgomeryR; #if defined(__cplusplus) } diff --git a/libcrux-ml-kem/cg/libcrux_sha3_avx2.h b/libcrux-ml-kem/cg/libcrux_sha3_avx2.h index 2bc4d84e..1e8f134e 100644 --- a/libcrux-ml-kem/cg/libcrux_sha3_avx2.h +++ b/libcrux-ml-kem/cg/libcrux_sha3_avx2.h @@ -1,8 +1,8 @@ /* This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml - ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 42a43169 + -funroll-loops 0 ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: + KaRaMeL version: 42a43169 */ #ifndef __libcrux_sha3_avx2_H @@ -1286,14 +1286,17 @@ libcrux_sha3_generic_keccak_chi__core_core_arch_x86___m256i_4size_t( *s) { core_core_arch_x86___m256i old[5U][5U]; memcpy(old, s->st, (size_t)5U * sizeof(core_core_arch_x86___m256i[5U])); - KRML_MAYBE_FOR5( - i0, (size_t)0U, (size_t)5U, (size_t)1U, size_t i1 = i0; KRML_MAYBE_FOR5( - i, (size_t)0U, (size_t)5U, (size_t)1U, size_t j = i; - core_core_arch_x86___m256i uu____0 = - libcrux_sha3_simd_avx2___libcrux_sha3__traits__internal__KeccakItem_4__usize__for_core__core_arch__x86____m256i___and_not_xor( - s->st[i1][j], old[i1][(j + (size_t)2U) % (size_t)5U], - old[i1][(j + (size_t)1U) % (size_t)5U]); - s->st[i1][j] = uu____0;);); + for (size_t i0 = (size_t)0U; i0 < (size_t)5U; i0++) { + size_t i1 = i0; + for (size_t i = (size_t)0U; i < (size_t)5U; i++) { + size_t j = i; + core_core_arch_x86___m256i uu____0 = + libcrux_sha3_simd_avx2___libcrux_sha3__traits__internal__KeccakItem_4__usize__for_core__core_arch__x86____m256i___and_not_xor( + s->st[i1][j], old[i1][(j + (size_t)2U) % (size_t)5U], + old[i1][(j + (size_t)1U) % (size_t)5U]); + s->st[i1][j] = uu____0; + } + } } __attribute__((target("avx2"))) @@ -1370,18 +1373,19 @@ libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_136 Eurydice_slice last[4U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[4U][200U] = {{0U}}; - KRML_MAYBE_FOR4( - i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i0], - (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, - .end = last_len}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, - void *); - blocks[i0][last_len] = 31U; size_t uu____1 = i0; - size_t uu____2 = (size_t)136U - (size_t)1U; - blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U;); + for (size_t i = (size_t)0U; i < (size_t)4U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)200U, blocks[i0], + (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, + .end = last_len}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, void *); + blocks[i0][last_len] = 31U; + size_t uu____1 = i0; + size_t uu____2 = (size_t)136U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; + } core_core_arch_x86___m256i(*uu____3)[5U] = s->st; uint8_t uu____4[4U][200U]; memcpy(uu____4, blocks, (size_t)4U * sizeof(uint8_t[200U])); @@ -1636,17 +1640,20 @@ libcrux_sha3_generic_keccak_squeeze_first_and_last__core_core_arch_x86___m256i_4 uint8_t b[4U][200U]; libcrux_sha3_simd_avx2___libcrux_sha3__traits__internal__KeccakItem_4__usize__for_core__core_arch__x86____m256i___store_block_full___136size_t( s->st, b); - KRML_MAYBE_FOR4( - i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; - core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); - core_slice___Slice_T___copy_from_slice( - uu____0, - Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, - core_ops_range_Range__size_t, - Eurydice_slice), - uint8_t, void *);); + for (size_t i = (size_t)0U; i < (size_t)4U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; + core_ops_range_Range__size_t lit; + lit.start = (size_t)0U; + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); + core_slice___Slice_T___copy_from_slice( + uu____0, + Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, + core_ops_range_Range__size_t, + Eurydice_slice), + uint8_t, void *); + } } __attribute__((target("avx2"))) @@ -1689,17 +1696,20 @@ libcrux_sha3_generic_keccak_squeeze_last__core_core_arch_x86___m256i_4size_t_136 uint8_t b[4U][200U]; libcrux_sha3_simd_avx2___libcrux_sha3__traits__internal__KeccakItem_4__usize__for_core__core_arch__x86____m256i___store_block_full___136size_t( s.st, b); - KRML_MAYBE_FOR4( - i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = out[i0]; uint8_t *uu____1 = b[i0]; - core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); - core_slice___Slice_T___copy_from_slice( - uu____0, - Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, - core_ops_range_Range__size_t, - Eurydice_slice), - uint8_t, void *);); + for (size_t i = (size_t)0U; i < (size_t)4U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; + core_ops_range_Range__size_t lit; + lit.start = (size_t)0U; + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); + core_slice___Slice_T___copy_from_slice( + uu____0, + Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, + core_ops_range_Range__size_t, + Eurydice_slice), + uint8_t, void *); + } } __attribute__((target("avx2"))) @@ -2042,18 +2052,19 @@ libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168 Eurydice_slice last[4U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[4U][200U] = {{0U}}; - KRML_MAYBE_FOR4( - i, (size_t)0U, (size_t)4U, (size_t)1U, size_t i0 = i; - Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i0], - (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, - .end = last_len}), - uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, - void *); - blocks[i0][last_len] = 31U; size_t uu____1 = i0; - size_t uu____2 = (size_t)168U - (size_t)1U; - blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U;); + for (size_t i = (size_t)0U; i < (size_t)4U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = Eurydice_array_to_subslice( + (size_t)200U, blocks[i0], + (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, + .end = last_len}), + uint8_t, core_ops_range_Range__size_t, Eurydice_slice); + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, void *); + blocks[i0][last_len] = 31U; + size_t uu____1 = i0; + size_t uu____2 = (size_t)168U - (size_t)1U; + blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; + } core_core_arch_x86___m256i(*uu____3)[5U] = s->st; uint8_t uu____4[4U][200U]; memcpy(uu____4, blocks, (size_t)4U * sizeof(uint8_t[200U])); diff --git a/libcrux-ml-kem/cg/libcrux_sha3_portable.h b/libcrux-ml-kem/cg/libcrux_sha3_portable.h index 431ba627..53df0e9b 100644 --- a/libcrux-ml-kem/cg/libcrux_sha3_portable.h +++ b/libcrux-ml-kem/cg/libcrux_sha3_portable.h @@ -1,8 +1,8 @@ /* This file was generated by KaRaMeL KaRaMeL invocation: /home/franziskus/eurydice//eurydice --config ../cg.yaml - ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: - KaRaMeL version: 42a43169 + -funroll-loops 0 ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc F* version: + KaRaMeL version: 42a43169 */ #ifndef __libcrux_sha3_portable_H @@ -848,14 +848,17 @@ static inline void libcrux_sha3_generic_keccak_chi__uint64_t_1size_t( libcrux_sha3_generic_keccak_KeccakState__uint64_t__1size_t *s) { uint64_t old[5U][5U]; memcpy(old, s->st, (size_t)5U * sizeof(uint64_t[5U])); - KRML_MAYBE_FOR5( - i0, (size_t)0U, (size_t)5U, (size_t)1U, size_t i1 = i0; KRML_MAYBE_FOR5( - i, (size_t)0U, (size_t)5U, (size_t)1U, size_t j = i; - uint64_t uu____0 = - libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___and_not_xor( - s->st[i1][j], old[i1][(j + (size_t)2U) % (size_t)5U], - old[i1][(j + (size_t)1U) % (size_t)5U]); - s->st[i1][j] = uu____0;);); + for (size_t i0 = (size_t)0U; i0 < (size_t)5U; i0++) { + size_t i1 = i0; + for (size_t i = (size_t)0U; i < (size_t)5U; i++) { + size_t j = i; + uint64_t uu____0 = + libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___and_not_xor( + s->st[i1][j], old[i1][(j + (size_t)2U) % (size_t)5U], + old[i1][(j + (size_t)1U) % (size_t)5U]); + s->st[i1][j] = uu____0; + } + } } static inline void libcrux_sha3_generic_keccak_iota__uint64_t_1size_t( @@ -911,16 +914,16 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_72size_t_6uint8_t( Eurydice_slice last[1U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[1U][200U] = {{0U}}; - { - size_t i = (size_t)0U; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i], + (size_t)200U, blocks[i0], (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = last_len}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); - blocks[i][last_len] = 6U; - size_t uu____1 = i; + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, void *); + blocks[i0][last_len] = 6U; + size_t uu____1 = i0; size_t uu____2 = (size_t)72U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } @@ -976,13 +979,13 @@ libcrux_sha3_generic_keccak_squeeze_first_and_last__uint64_t_1size_t_72size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___72size_t( s->st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, @@ -1023,13 +1026,13 @@ libcrux_sha3_generic_keccak_squeeze_last__uint64_t_1size_t_72size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___72size_t( s.st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, @@ -1195,16 +1198,16 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_136size_t_6uint8_t( Eurydice_slice last[1U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[1U][200U] = {{0U}}; - { - size_t i = (size_t)0U; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i], + (size_t)200U, blocks[i0], (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = last_len}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); - blocks[i][last_len] = 6U; - size_t uu____1 = i; + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, void *); + blocks[i0][last_len] = 6U; + size_t uu____1 = i0; size_t uu____2 = (size_t)136U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } @@ -1260,13 +1263,13 @@ libcrux_sha3_generic_keccak_squeeze_first_and_last__uint64_t_1size_t_136size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___136size_t( s->st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, @@ -1307,13 +1310,13 @@ libcrux_sha3_generic_keccak_squeeze_last__uint64_t_1size_t_136size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___136size_t( s.st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, @@ -1419,16 +1422,16 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_136size_t_31uint8_t( Eurydice_slice last[1U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[1U][200U] = {{0U}}; - { - size_t i = (size_t)0U; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i], + (size_t)200U, blocks[i0], (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = last_len}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); - blocks[i][last_len] = 31U; - size_t uu____1 = i; + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, void *); + blocks[i0][last_len] = 31U; + size_t uu____1 = i0; size_t uu____2 = (size_t)136U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } @@ -1642,16 +1645,16 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_168size_t_31uint8_t( Eurydice_slice last[1U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[1U][200U] = {{0U}}; - { - size_t i = (size_t)0U; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i], + (size_t)200U, blocks[i0], (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = last_len}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); - blocks[i][last_len] = 31U; - size_t uu____1 = i; + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, void *); + blocks[i0][last_len] = 31U; + size_t uu____1 = i0; size_t uu____2 = (size_t)168U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } @@ -1857,16 +1860,16 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_144size_t_6uint8_t( Eurydice_slice last[1U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[1U][200U] = {{0U}}; - { - size_t i = (size_t)0U; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i], + (size_t)200U, blocks[i0], (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = last_len}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); - blocks[i][last_len] = 6U; - size_t uu____1 = i; + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, void *); + blocks[i0][last_len] = 6U; + size_t uu____1 = i0; size_t uu____2 = (size_t)144U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } @@ -1922,13 +1925,13 @@ libcrux_sha3_generic_keccak_squeeze_first_and_last__uint64_t_1size_t_144size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___144size_t( s->st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, @@ -1969,13 +1972,13 @@ libcrux_sha3_generic_keccak_squeeze_last__uint64_t_1size_t_144size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___144size_t( s.st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, @@ -2141,16 +2144,16 @@ libcrux_sha3_generic_keccak_absorb_final__uint64_t_1size_t_104size_t_6uint8_t( Eurydice_slice last[1U]) { size_t last_len = core_slice___Slice_T___len(last[0U], uint8_t, size_t); uint8_t blocks[1U][200U] = {{0U}}; - { - size_t i = (size_t)0U; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; Eurydice_slice uu____0 = Eurydice_array_to_subslice( - (size_t)200U, blocks[i], + (size_t)200U, blocks[i0], (CLITERAL(core_ops_range_Range__size_t){.start = (size_t)0U, .end = last_len}), uint8_t, core_ops_range_Range__size_t, Eurydice_slice); - core_slice___Slice_T___copy_from_slice(uu____0, last[i], uint8_t, void *); - blocks[i][last_len] = 6U; - size_t uu____1 = i; + core_slice___Slice_T___copy_from_slice(uu____0, last[i0], uint8_t, void *); + blocks[i0][last_len] = 6U; + size_t uu____1 = i0; size_t uu____2 = (size_t)104U - (size_t)1U; blocks[uu____1][uu____2] = (uint32_t)blocks[uu____1][uu____2] | 128U; } @@ -2206,13 +2209,13 @@ libcrux_sha3_generic_keccak_squeeze_first_and_last__uint64_t_1size_t_104size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___104size_t( s->st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, @@ -2253,13 +2256,13 @@ libcrux_sha3_generic_keccak_squeeze_last__uint64_t_1size_t_104size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___104size_t( s.st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, @@ -2454,13 +2457,13 @@ libcrux_sha3_generic_keccak_squeeze_first_and_last__uint64_t_1size_t_168size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___168size_t( s->st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t, @@ -2478,13 +2481,13 @@ libcrux_sha3_generic_keccak_squeeze_last__uint64_t_1size_t_168size_t( uint8_t b[1U][200U]; libcrux_sha3_portable_keccak___libcrux_sha3__traits__internal__KeccakItem_1__usize__for_u64___store_block_full___168size_t( s.st, b); - { - size_t i = (size_t)0U; - Eurydice_slice uu____0 = out[i]; - uint8_t *uu____1 = b[i]; + for (size_t i = (size_t)0U; i < (size_t)1U; i++) { + size_t i0 = i; + Eurydice_slice uu____0 = out[i0]; + uint8_t *uu____1 = b[i0]; core_ops_range_Range__size_t lit; lit.start = (size_t)0U; - lit.end = core_slice___Slice_T___len(out[i], uint8_t, size_t); + lit.end = core_slice___Slice_T___len(out[i0], uint8_t, size_t); core_slice___Slice_T___copy_from_slice( uu____0, Eurydice_array_to_subslice((size_t)200U, uu____1, lit, uint8_t,