From: Mark Wooding Date: Wed, 25 Sep 2019 10:44:59 +0000 (+0100) Subject: Update crypto code from Catacomb 2.3.0.1-45-g9c14. X-Git-Url: https://git.distorted.org.uk/~mdw/secnet/commitdiff_plain/8a7654a695e8ecdc8c14dced445839a7a7e6a8ca Update crypto code from Catacomb 2.3.0.1-45-g9c14. * Imported new `test-import/f25519-tests.in', from upstream `math/t/f25519'. * Imported new `test-import/f25519.c', from upstream `math/f25519.c'. * Imported new `test-import/f25519.h', from upstream `math/f25519.h'. * Imported new `test-import/fgoldi-tests.in', from upstream `math/t/fgoldi'. * Imported new `test-import/fgoldi.c', from upstream `math/fgoldi.c'. * Imported new `test-import/fgoldi.h', from upstream `math/fgoldi.h'. * Imported new `test-import/montladder.h', from upstream `math/montladder.h'. * Imported new `test-import/qfarith.h', from upstream `math/qfarith.h'. * Imported new `test-import/x25519-tests.in', from upstream `pub/t/x25519'. * Imported new `test-import/x25519.c', from upstream `pub/x25519.c'. * Imported new `test-import/x25519.h', from upstream `pub/x25519.h'. * Imported new `test-import/x448-tests.in', from upstream `pub/t/x448'. * Imported new `test-import/x448.c', from upstream `pub/x448.c'. * Imported new `test-import/x448.h', from upstream `pub/x448.h'. Upstream-Revision: 9c1437f372e62f0b3b3a7162aabee73bdc96ce4b --- diff --git a/f25519-tests.in b/f25519-tests.in new file mode 100644 index 0000000..09ef4c7 --- /dev/null +++ b/f25519-tests.in @@ -0,0 +1,1537 @@ +### Test cases for arithmetic mod 2^255 - 19. -*-conf-*- +### Extracted from Catacomb. + +###-------------------------------------------------------------------------- +test add + +## Some load and store tests. +x 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 +y 0000000000000000000000000000000000000000000000000000000000000000 +z 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 + +x ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +y 0000000000000000000000000000000000000000000000000000000000000000 +z ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f + +x edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +y 00000000000000000000000000000000000000000000000000000000000000 +z 00 + +## Random tests. +x bb8cd45b6185ee8ca34c4d7560425fd5c2fc22871113c6427198e8f9439a8523 +y 98f16cc5e44b7228b7f3b6ed91930d68bba5071157d19259c48034d2817e30d5 +z 667e412146d160b55a400463f2d56c3d7ea22a9868e4589c35191dccc518b678 + +x 8ef938a7b07a668c234c2c5bb65115b8e2e22a3703cda51c70e7a56a075d4f34 +y 1f3cd4bf4f768058c4de1aa5aeb90e227338e308c7a0a199050ca1c38d1e034c +z c0350d6700f1e6e4e72a4700650b24da551b0e40ca6d47b675f3462e957b5200 + +x 8b2c4678fd4f8b7254eea925e4da8d472db7f97d349d1b2134ced884b747ea7d +y 58dca7954f843b7e4dc56b048903e7728df66ef6824f29932b2f568c995ddf2c +z f608ee0d4dd4c6f0a1b3152a6dde74babaad6874b7ec44b45ffd2e1151a5c92a + +x 9cd64f0cf439bccd224f7a789396b9f888998d1ba9759c93a5d6a27f45db0e67 +y 12f724a127052612081e27e3915db9a540de9b64c566edc313914ad94424464e +z c1cd74ad1b3fe2df2a6da15b25f4729ec97729806edc8957b967ed588aff5435 + +x 82e59fa9703b2557303665fe24e3d46259da974d78155f05c6b8891f92fc808d +y 98a073ec62baf1354b681a3c78d62df1698ed5077dbe2bd68ba4a6e0233e3447 +z 2d861396d3f5168d7b9e7f3a9db90254c3686d55f5d38adb515d3000b63ab554 + +x 686ceca221d0f4c6d98287e97c506085064e7b172672b88ee555dd0308bfd309 +y 60adc3675be5e6c2921a74b5b8b24b0a26341a19567dae713a720786bc72df16 +z c819b00a7db5db896c9dfb9e3503ac8f2c8295307cef660020c8e489c431b320 + +x a50a5b82d2451ed9a5844585712202a6dc0e0230501d57b8c00f4bd4771aed9e +y 98d71b8b140aea02ad47d9b19e47d2a03257adc1d5c47611adc667652b78c87c +z 63e2760de74f08dc52cc1e37106ad4460f66aff125e2cdc96dd6b239a392b51b + +x 1637e3eb4c5d173b8cba29bdb13b930f48ae0599e354819f8ae0cf70f0f7b61b +y ffeef1767df70de7a4a75864c03935d7934c6cf5228b9c3000813ed0e55447e2 +z 2826d562ca542522316282217275c8e6dbfa718e06e01dd08a610e41d64cfe7d + +x 9e8bf571c45bc5f37c9126e70498698978903b94d9c6712baef91894ab924fda +y 480f68f8ee644bfb64e3fa514eaf16aea6368da6813802c4c3e6ce8f6540dfa3 +z 0c9b5d6ab3c010efe1742139534780371fc7c83a5bff73ef71e0e72311d32e7e + +x df9bdbd478bd1ec1ff078cdc76f2a5fcdc52f0198ba412e0b5a10e664b175dad +y 080bc47bd2fb2ba3be6a07a02162f76020479f2cc6469c6766df23acf9517896 +z 0da79f504bb94a64be72937c98549d5dfd998f4651ebae471c8132124569d543 + +x b6dd223f5d8a3dc5dd6f7a0679173ff656303017a17f17f4086fd4ecd3a23020 +y 560d827aad23c26fddbfd16c3514a9b518a4586d6e3c5739860743662b14f4b4 +z 1feba4b90aaeff34bb2f4c73ae2be8ab6fd488840fbc6e2d8f761753ffb62455 + +x 1d59691a670c40143ca7f7e693389ab64a911b17a2fe4368fba9097b40864162 +y cb42d3ba12a8b90ef1622ea09241d3157c515043040914356d6d99b95089fa07 +z e89b3cd579b4f9222d0a2687267a6dccc6e26b5aa607589d6817a334910f3c6a + +x 82b48877e9c8c18edb52db3e1417d894e572a8edd84335d93c642158f2a926e0 +y 93c6a39c1ef97f318c3b13bf8e77bea653b2eb130bdf43b00a0e0e40a362e819 +z 287b2c1408c241c0678eeefda28e963b39259401e422798947722f98950c0f7a + +x a6137481c5b9b8bcb3c87f3868c5f812da71aeb21c5ce18a508773120ea4f659 +y 812eacdc5a8eb2e8fde0c23a19c2e33466d754ab3109d28ff48fb41dab8066e2 +z 4d42205e20486ba5b1a942738187dc474049035e4e65b31a45172830b9245d3c + +x 598fb4096a7054e317e66bc9633d56dfcaeabc31a7bbc9da13074b242edeca09 +y 929b1bddd55c99b06b99a3ffbac5adc1d28823cb8354adcfea60b7a87fe32039 +z eb2ad0e63fcded93837f0fc91e0304a19d73e0fc2a1077aafe6702cdadc1eb42 + +x c42183d915267e655409326b1b77a042d8918feefd75dd3d18551f398ef426e7 +y e3729a6110686ffa57d1c69284a60fb36173148a89b1810d04614f03c8f90084 +z cd941d3b268eed5facdaf8fd9f1db0f53905a47887275f4b1cb66e3c56ee276b + +x 67b8b7ea7e7f9f52d686f906589c919b293bff6d3127e7ac581dc1630af7bcc1 +y 99d18d2190ef0da148b843c014fea3efea59f9adbb28fa38407191fcc24e029c +z 268a450c0f6fadf31e3f3dc76c9a358b1495f81bed4fe1e5988e5260cd45bf5d + +x bc3422b79e01234fefd3637a19bfb2dd0a83bf2071b27bf5389918a50e579294 +y b665dffe064aceffaabba94697cf27054d016427ebaf68858c5250cc5c1b770f +z 859a01b6a54bf14e9a8f0dc1b08edae2578423485c62e47ac5eb68716b720924 + +x d419cbfd5514d9cffa1765b9f273fd7492000a3d110586ed0b8137760a2e808e +y bcb52f423917c074464b2078d1c3f883fb793b02411b8b13c08266d17658a499 +z b6cffa3f8f2b994441638531c437f6f88d7a453f52201101cc039e4781862428 + +x 2f7eb8051d16a52b797e2618881bd0857eb205bf97e581e09680f86308f7e082 +y 9ceda63b29c3bfedbb6f3f0be2f3f2bd285bb9d21620c3edde69629b00b1c3cd +z f16b5f4146d9641935ee65236a0fc343a70dbf91ae0545ce75ea5aff08a8a450 + +###-------------------------------------------------------------------------- +test sub + +x dfb53b4ff67c742728c564d50ae20e3e3617804478a95e511d37ff4dcf04fa3f +y 9bc2006bb07dcf7bf0b461e7599e3c3cbfcdf6b6f41fc1db2219767ce9c43bcd +z 1ef33ae445ffa4ab371003eeb043d2017749898d83899d75fa1d89d1e53fbe72 + +x 432ec65076c94af41e054a43f64fe4eecb23f50a303fd38e0172e4e846e67394 +y 3642c84c5f5fcd5a0f3f2e37114beb8e7b614c39d354f1b32fe7e9cc918da5c8 +z faebfd03176a7d990fc61b0ce504f95f50c2a8d15ceae1dad18afa1bb558ce4b + +x 1725a986c03d9d53346ab2064545ba90ab38191e19ded9ecc2f44d422ab04150 +y 11a20caef0239e4ffb5ab2f7d3576633a0d4a08c78a02f35765fafff5398c48b +z f3829cd8cf19ff03390f000f71ed535d0b647891a03daab74c959e42d6177d44 + +x ec5d5cdfc8183f9aa3d47634d16427c3a399e2166bfa4ddfecbc911e5f33ceba +y 649f8e29c483765c4232c369fd0e50a0026eac306eb4bd6924e7b4d7d3f73e26 +z 9bbecdb50495c83d61a2b3cad355d722a12b36e6fc459075c8d5dc468b3b8f14 + +x cc9927c331884612d8fab9a2262ad0db38f55e0cc587e45b972ea8b1f504450d +y 30c5c9f8d5491a350051bbc6bb78e568d98061b43cb1797cd3d7454e8a7aa1bf +z 76d45dca5b3e2cddd7a9fedb6ab1ea725f74fd5788d66adfc35662636b8aa34d + +x 662bc96da214e50f13e07a15b8e0b78f512c744a66975b2170ba28079ca7d03b +y 84b072295dca0abef806ec5c1e594179dc5e9eb172c178af1902a42ea7a3728e +z cf7a5644454ada511ad98eb89987761675cdd598f3d5e27156b884d8f4035e2d + +x ed6f947157492eccc5fb1d0542593d58a47e2d87355dc0378e65376163fcf457 +y cb27e06c5ebf42a61caadd4fb222799772aaef31487bf61ac84c15f58af265d3 +z 0f48b404f989eb25a95140b58f36c4c031d43d55ede1c91cc618226cd8098f04 + +x 33c2fc57d8ffc29e6d670cfc4e25b695320055cf443ade53f49f6c23c452f644 +y 3814860ccbb4391894c107961170d3af1594988a7972b97d0fb2169631b216fa +z d5ad764b0d4b8986d9a504663db5e2e51c6cbc44cbc724d6e4ed558d92a0df4a + +x d0fd0d5e73be5c534aa37645aecc49b202fadb30733f16d0de719a70bec2c751 +y 910c7b4d317397cff70c91e5bf8ec42ba1700b0866adbbfe99b7fbb2c46c7093 +z 2cf19210424bc5835296e55fee3d85866189d0280d925ad144ba9ebdf955573e + +x e0f8130d6b0125e824b254ed57edc59455a8a4704a3f14a4ae8dbf8721595468 +y 4e4f69af6f85742068ad70225e8850c85aef3d3fb3ba3b52c2be979db4eb979d +z 7fa9aa5dfb7bb0c7bc04e4caf96475ccfab866319784d851ecce27ea6c6dbc4a + +x 204d5f69ebab4597d2aa9295ecc2959480a2ab0b225674cc8a147cf7c1e59717 +y 3abdd29c94819ec7507673bd5cc4fb267fcb17c1509abd5e462b46b012f815a8 +z c08f8ccc562aa7cf81341fd88ffe996d01d7934ad1bbb66d44e93547afed816f + +x e2d75c74060aee615b6cfc815c8618f826b07c4987e10f20d27ff74eab3ac7d0 +y 7a06b32d284b5faedb91dac8e94cb7f76c678bad81ed78ac4e75eb9edd8d11e9 +z 55d1a946debe8eb37fda21b972396100ba48f19b05f49673830a0cb0cdacb567 + +x 8d50b0573b0bb945bf128e1a9a37c151e991581673cf6295db5a6223d428ac9d +y 47ca477794fdf378f3486355b5348960ee957470b8c74d62199ac48b4478c4ca +z 338668e0a60dc5cccbc92ac5e40238f1fafbe3a5ba071533c2c09d978fb0e752 + +x b66b49190a99456aaac5c33beaec423a3fa79a84df0f00122aed29151185ceef +y 13c06f7941743bfa261845d99772fd0d5f1a8258aeda53b161505ed8bdca1bc8 +z a3abd99fc8240a7083ad7e62527a452ce08c182c3135ac60c89ccb3c53bab227 + +x 44ac89bb8d4de1a8756b00401236ea4e316a2fe637f6e5f052576da70c29c4ea +y 05dd39ac32768d899b80ed10279aa10d6316d60ab2d061e877dc5f21ce8e1140 +z 52cf4f0f5bd7531fdaea122feb9b4841ce5359db85258408db7a0d863e9ab22a + +x ef0f6c7f56ff22260c66d583f79c7f581181d3a0f3167c93786bb6c89de4372c +y be934afeffaf5e6755a92e6606ffd054627dbe1b18ad6ae543363a01da605512 +z 317c2181564fc4beb6bca61df19dae03af031585db6911ae34357cc7c383e219 + +x 773e0db8f86c5182b5f51d10376f42cde275dac6a646ab1cab065760e045107e +y 3f92ddafdfe67d357b4f9b61807bcb8b0f1f6c2dacba27902f48fc15a31db606 +z 38ac2f081986d34c3aa682aeb6f37641d3566e99fa8b838c7bbe5a4a3d285a77 + +x 34860a848d0afb20e43f4a36b3c8941f5821864216da9cb3ce1a11f056565a3d +y 9dfed86048acd45ec0009c1ba3b20a1ba645ec141070fd8ae41d25e159bbce9f +z 84873123455e26c2233fae1a10168a04b2db992d066a9f28eafceb0efd9a8b1d + +x 854ba91672ae1b8f6c29395dcfa4f3514ed97dc2c9e1e419f926825619fac55b +y 7a700653ad355caf17f89045ecfb3ee821194b54048e55d8eed41fea2b0a22ab +z f8daa2c3c478bfdf5431a817e3a8b4692cc0326ec5538f410a52626cedefa330 + +x 0c66b3d8c3916940b70d381d232ba8aecfe27e3ae63fa6cbb287216708f224f0 +y 477186656245c4083dff93a95c6e5deb707916e52cd74abbd522743c24c53088 +z c5f42c73614ca5377a0ea473c6bc4ac35e696855b9685b10dd64ad2ae42cf467 + +###-------------------------------------------------------------------------- +test neg + +x 0000000000000000000000000000000000000000000000000000000000000000 +z 0000000000000000000000000000000000000000000000000000000000000000 + +x 23d767107e23d5ce14189cce939c4b5334d6736da3da40a715236b9d8319efc1 +z b72898ef81dc2a31ebe763316c63b4accb298c925c25bf58eadc94627ce6103e + +x 9bb944cfb58b186cc551e0a0eca74528c7618ff47485bf6a723f43d990f69f6e +z 5246bb304a74e7933aae1f5f1358bad7389e700b8b7a40958dc0bc266f096011 + +x bff36d2aa923d5a9af5398e2cfcba4acdf3c3181a8ff00b8a1099cd97a4e8542 +z 2e0c92d556dc2a5650ac671d30345b5320c3ce7e5700ff475ef6632685b17a3d + +x 1b65a51746eabb7c0d8d9844dda03bde7128407e94661db2d5fd9c0f3790d120 +z d29a5ae8b9154483f27267bb225fc4218ed7bf816b99e24d2a0263f0c86f2e5f + +x 88f4cf29a610c4465f63a272fde2f19a4874a70a0829885014379b637ab0e82d +z 650b30d659ef3bb9a09c5d8d021d0e65b78b58f5f7d677afebc8649c854f1752 + +x 94ca4d567efcf088e6bf1cb3698f6b8bf2164db4f523e28781aebfcbb501ec63 +z 5935b2a981030f771940e34c967094740de9b24b0adc1d787e5140344afe131c + +x 3f8d7ae4f1698921524e49ccb2ce4459e4c048f76f04c5e60179f5417d2d52db +z 9b72851b0e9676deadb1b6334d31bba61b3fb70890fb3a19fe860abe82d2ad24 + +x 1eaa0c45af0d8f85d865cc66ff3d0dc3355f1ac36821cdd95a6b9232a27f9044 +z cf55f3ba50f2707a279a339900c2f23ccaa0e53c97de3226a5946dcd5d806f3b + +x 33e142c78ee87a7980ade6c796e7ff949cee6d3af0415bf5b6901f84c2db910a +z ba1ebd38711785867f5219386918006b631192c50fbea40a496fe07b3d246e75 + +x 24a0c185c47787caf1a666a62002a503f2a3e591e5f2946e148a47b9b114a884 +z b65f3e7a3b8878350e599959dffd5afc0d5c1a6e1a0d6b91eb75b8464eeb577b + +x a8bd0c1c3f219a97de87b22e8cb3eb5daea33b5646589b6925ec4ec83ca37455 +z 4542f3e3c0de656821784dd1734c14a2515cc4a9b9a76496da13b137c35c8b2a + +x 1a340d2679ca205f6b198cff4bffadcde1afeeed124ef0c574655dbe8732b681 +z c0cbf2d98635dfa094e67300b40052321e501112edb10f3a8b9aa24178cd497e + +x da43c139a1f92ba1b5fc996befe5218368eac3c46b42e98a9cca8b8f6f1540f5 +z 00bc3ec65e06d45e4a036694101ade7c97153c3b94bd16756335747090eabf0a + +x 81aad864a31e5f4afa32c29eb97f22c103dfe5b1323db05fc9b1545312aa6c0d +z 6c55279b5ce1a0b505cd3d614680dd3efc201a4ecdc24fa0364eabaced559372 + +x 28231ad38d214f1421df7005eddb4f4c12e522b10d1cbcd10ee26dfcc222a62c +z c5dce52c72deb0ebde208ffa1224b0b3ed1add4ef2e3432ef11d92033ddd5953 + +x c1facefef35c1ed00db767ed0281ebfad1f3c915c6649f5e1c26a6f3f9478b43 +z 2c0531010ca3e12ff2489812fd7e14052e0c36ea399b60a1e3d9590c06b8743c + +x c2e4046e7200386ca2afea8ecc9c98c105fbf6e31b598e21e482796a69956040 +z 2b1bfb918dffc7935d5015713363673efa04091ce4a671de1b7d8695966a9f3f + +x a42fedea4eac90580a0bbcb0491a7e8cc82de7a99aa74ed35f705c536afa0236 +z 49d01215b1536fa7f5f4434fb6e5817337d218566558b12ca08fa3ac9505fd49 + +x d1ab8c50d54279ceac870d0ce4a2af56bf8c03e87482dcb7775183a4908ac739 +z 1c5473af2abd86315378f2f31b5d50a94073fc178b7d234888ae7c5b6f753846 + +x 1ffd85fa5ead53ff509756fc28051ef65eca040303b65f7b5b7e1d1a8508e030 +z ce027a05a152ac00af68a903d7fae109a135fbfcfc49a084a481e2e57af71f4f + +###-------------------------------------------------------------------------- +test condneg + +x 5330763b29dff20501a1d6c64025c36279083473721f5cacf89168189ff9810d +m 0x00000000 +z 5330763b29dff20501a1d6c64025c36279083473721f5cacf89168189ff9810d + +x 9d9c36e2126d911a503e1cc1a8489ee74949ae2a8408dc7d72ed0d75e4350545 +m 0x00000000 +z 9d9c36e2126d911a503e1cc1a8489ee74949ae2a8408dc7d72ed0d75e4350545 + +x 47da10abec2cb54c5890e5945999deb1d89ffd268bbbe2eafc86f1acc8bf5f7e +m 0x00000000 +z 47da10abec2cb54c5890e5945999deb1d89ffd268bbbe2eafc86f1acc8bf5f7e + +x 3e6ec07de86be6ffab2dfa1deb9ed67844645be92bdbb22b7ba91379babcdfed +m 0x00000000 +z 516ec07de86be6ffab2dfa1deb9ed67844645be92bdbb22b7ba91379babcdf6d + +x 5f5c0730649586b5c0b60a14d3b669b3649eb6725d71d834e78ff2aa0e5450e5 +m 0xffffffff +z 7ba3f8cf9b6a794a3f49f5eb2c49964c9b61498da28e27cb18700d55f1abaf1a + +x c357befcc6836d89387915e368e5e6162252b433eb58d94eb3cc4b783e98c226 +m 0xffffffff +z 2aa84103397c9276c786ea1c971a19e9ddad4bcc14a726b14c33b487c1673d59 + +x 713ad0f656a8fcd75fdee2c4ac248ee7ad09a5f357c565daa94ae46d8590d2c8 +m 0x00000000 +z 843ad0f656a8fcd75fdee2c4ac248ee7ad09a5f357c565daa94ae46d8590d248 + +x 909d669185e98b4a88a6531b830193b23035d64665929e34e86d53c4a9eef30a +m 0xffffffff +z 5d62996e7a1674b57759ace47cfe6c4dcfca29b99a6d61cb1792ac3b56110c75 + +x 8f23ec139f93258e6d57fa278339f1cb5da193c5d1ad7183fb2b151111262285 +m 0x00000000 +z a223ec139f93258e6d57fa278339f1cb5da193c5d1ad7183fb2b151111262205 + +x a9a5480c72157f389be80ae7ad63502434c380ccd1cef813dc9bd2e9a85e2f22 +m 0xffffffff +z 445ab7f38dea80c76417f518529cafdbcb3c7f332e3107ec23642d1657a1d05d + +x 316f98b6697e7daa8775d3aa91dee8fbbae4e935a2f62cd2975e2d552f0c9846 +m 0xffffffff +z bc90674996818255788a2c556e211704451b16ca5d09d32d68a1d2aad0f36739 + +x 70128d6dd5fb42f287fba3533c71cb5dc2361b6d91c3d9626c58849e27f7d349 +m 0xffffffff +z 7ded72922a04bd0d78045cacc38e34a23dc9e4926e3c269d93a77b61d8082c36 + +x 66a6f3dc6274e4122dc401ef23529175d71d96b660a52cdcd64556073b5430b2 +m 0x00000000 +z 79a6f3dc6274e4122dc401ef23529175d71d96b660a52cdcd64556073b543032 + +x 3909505812b228e6ca5cc6c0b17824ef765923eded6105e6eb0f176781624c5a +m 0xffffffff +z b4f6afa7ed4dd71935a3393f4e87db1089a6dc12129efa1914f0e8987e9db325 + +x b7febd7d63efae3bcc60c1c344f2f6166b272eed785a9e541d3ff4f12e82a5f3 +m 0xffffffff +z 230142829c1051c4339f3e3cbb0d09e994d8d11287a561abe2c00b0ed17d5a0c + +x d1cacc1db40de13351224046975319d7546ae9e88e1909c2a8f46792a140d279 +m 0xffffffff +z 1c3533e24bf21eccaeddbfb968ace628ab95161771e6f63d570b986d5ebf2d06 + +x 4c449a50fc1e145be1463e4c171b3c51c9683c41c45005d8aeca607911c9b3be +m 0xffffffff +z 8ebb65af03e1eba41eb9c1b3e8e4c3ae3697c3be3baffa2751359f86ee364c41 + +x c929c50eedbad6ceacdefb00bd58a32820c874c906741e9d93cd0f668819edcc +m 0x00000000 +z dc29c50eedbad6ceacdefb00bd58a32820c874c906741e9d93cd0f668819ed4c + +x 1c57449dcfc7e8f9fab77d226d4b50d7dee06c29d08d3d4f4ae7c8ad238a0a82 +m 0xffffffff +z bea8bb6230381706054882dd92b4af28211f93d62f72c2b0b5183752dc75f57d + +x 396a2ddc48f158e73c95dc289da3f0d3b2128875e20c401cb50fd6cc7a28dd18 +m 0xffffffff +z b495d223b70ea718c36a23d7625c0f2c4ded778a1df3bfe34af0293385d72267 + +###-------------------------------------------------------------------------- +test pick2 + +x e6f52222f35081896f3d9ecc0ffb27fa3e75c8ad1c98e161878d2c3cffd72c78 +y a24cd71f7acb653466b7d67bb41efb5a29503d2627d2ce28fe19680ccd939be5 +i 0x00000000 +z b54cd71f7acb653466b7d67bb41efb5a29503d2627d2ce28fe19680ccd939b65 + +x 4e51fe2dac96a664d0675962116b7af4e605194a1c9fb774c621a3107994c9ed +y 508934be10ce5e11e6940d56e84b148e20f48369e748536846763c80bab9af49 +i 0x00000000 +z 508934be10ce5e11e6940d56e84b148e20f48369e748536846763c80bab9af49 + +x 530175217081c3fb3ecd17702ad334ad48f05affd5ab3754ef10be5b0eb5375d +y 8aebc7e01e2bb2829f21311462175948d85cd3e65d676eec893e3df13f639d07 +i 0xffffffff +z 530175217081c3fb3ecd17702ad334ad48f05affd5ab3754ef10be5b0eb5375d + +x 0e53c5141d72c8c81d80b1a1283b0267b278f98e28ce08ccac7b010022e5adae +y 2215cc15e950d6abfffa26113f269628f50f9ac37ad3260ae9189958d75080b6 +i 0xffffffff +z 2153c5141d72c8c81d80b1a1283b0267b278f98e28ce08ccac7b010022e5ad2e + +x 3dc16434679d30686d5023fda4cc574563841caf1d588e965fe1ec1c4ba54398 +y 4ca50330751d33ebba981277926a3fb801d216474cb183f90947680f5ea383a2 +i 0xffffffff +z 50c16434679d30686d5023fda4cc574563841caf1d588e965fe1ec1c4ba54318 + +x 09e68cb66b5ae2f3160a71738d1e9a042b9b76335eddc4b9466d0c6b8100eeb6 +y 270eb833ae635bed17df9218a53a91b7afeb74f0df3bfffb8334c04773cf716d +i 0xffffffff +z 1ce68cb66b5ae2f3160a71738d1e9a042b9b76335eddc4b9466d0c6b8100ee36 + +x 831b8a99e3b44bf21cdd4f3c06da7c16a95e98f3dc42cf2ac282edec67d9b2ca +y 482840e31c7620de6d290d747afc63ca199c60169f8eb62d28ca1142c5336990 +i 0xffffffff +z 961b8a99e3b44bf21cdd4f3c06da7c16a95e98f3dc42cf2ac282edec67d9b24a + +x a022ace6772d82d30832328c7cbfedb622b710d1fe9313a77dc4cc5ca577a7bb +y 39c86c57bf581c16d8c03b4ef0fe813815b5da1281f03bb3f2cdb0ddf19868d0 +i 0xffffffff +z b322ace6772d82d30832328c7cbfedb622b710d1fe9313a77dc4cc5ca577a73b + +x 719d3f13c38b915873bcb14308bfd9bb6f4a6cfd249a745bceb55787ce480caa +y c72de6e206ed24555d091763644d4405f2ee5dbd846a036d6a21442a6c40e0c6 +i 0x00000000 +z da2de6e206ed24555d091763644d4405f2ee5dbd846a036d6a21442a6c40e046 + +x 07cdd3cd677a3c1783bcf7855bf1dbb453809b66c66c7bbbb67690cea33ca581 +y c9d889281ac117390875739e4b62df6dc3cca6c65439c46bb907c81d3a961fa3 +i 0x00000000 +z dcd889281ac117390875739e4b62df6dc3cca6c65439c46bb907c81d3a961f23 + +x a69a728035cc69d5d3f96dd4a8081864333e53e434820dd569deb9e58393d4b7 +y 3f4ef71dfa1eccd817d3192dbe2e08466e4a66b4d836b0892b3636dc523098ed +i 0x00000000 +z 524ef71dfa1eccd817d3192dbe2e08466e4a66b4d836b0892b3636dc5230986d + +x d249414415ac4960e934d29e08c75ff1b18431a6e18f7404e638293d3d8e81d5 +y 33cd02e07762f74976834d1b6dd3b8eb7e2ad7a5d04ba90bbe747476071f10cb +i 0x00000000 +z 46cd02e07762f74976834d1b6dd3b8eb7e2ad7a5d04ba90bbe747476071f104b + +x efb782aba4dca351a5c9279b370073840b977b2458c6c84c9c9046dc92cc5507 +y 6d9f50eb56b84989aab77c54987f05c715b74185417863f2c275635d2d6f2eeb +i 0x00000000 +z 809f50eb56b84989aab77c54987f05c715b74185417863f2c275635d2d6f2e6b + +x 10c4381ed467e27d756ff7a260a6ffd282ad757b10c9956c518a43117699ee91 +y 9b9a70c67be3296ef9d65fdd8014c4b263c28fd31f3299f4461c688c469ff704 +i 0x00000000 +z 9b9a70c67be3296ef9d65fdd8014c4b263c28fd31f3299f4461c688c469ff704 + +x 5a30428bee407ee673ec7d2cb4854efd80b9761df5dec906463f888f60be7152 +y fc2e139be53203eb73041e9335253534c420208164682c2e02f31f084f5582f0 +i 0xffffffff +z 5a30428bee407ee673ec7d2cb4854efd80b9761df5dec906463f888f60be7152 + +x 43c7cd903c7dd7cdab85c6b5585955163e0da7dd0c5b5882ac620246619af342 +y 0eb52162c69425ad75b778c39746014789f7929119d4e122d4b98bf64784fcde +i 0xffffffff +z 43c7cd903c7dd7cdab85c6b5585955163e0da7dd0c5b5882ac620246619af342 + +x f37f3707e4609d389096c1fea551b572a6b4644fd6af2e9e7a0fa93a91ae38e5 +y d10dd4d911346a5952e3123d4f156a7e40807d142c4afb4bc314ac6f9346dfa8 +i 0xffffffff +z 06803707e4609d389096c1fea551b572a6b4644fd6af2e9e7a0fa93a91ae3865 + +x a4f4c203cb892691a6d6e9dff8a10ac1a8d9470b13ba24e1bddac05d6d7f9c0e +y b88145fabdeaa9fa108bb04a4d283ac034b4c8d8ffe1b2174de9a80254762c54 +i 0xffffffff +z a4f4c203cb892691a6d6e9dff8a10ac1a8d9470b13ba24e1bddac05d6d7f9c0e + +x 649d8ce64f623228553de99b823c5f5c5ef37f00e2ddf658fc9bc2405afde715 +y 0f24ace92223d2db75e2d82e8a5bc8b0e7981478216b999d2bdde9c72732d58f +i 0xffffffff +z 649d8ce64f623228553de99b823c5f5c5ef37f00e2ddf658fc9bc2405afde715 + +x 3f466e24ed4169ca3df624d747f054f97422d5eee3fade2fa3c4eba488694a6c +y 37e3171c9aa56d07ffcde4f1fd0fdcc41e2086ecf93c9e53f3f6a4c3e4db587c +i 0xffffffff +z 3f466e24ed4169ca3df624d747f054f97422d5eee3fade2fa3c4eba488694a6c + +###-------------------------------------------------------------------------- +test pickn + +v[0] 91aaaaf3ff9e58f299c0f6d0a4a3851d100423e4b7380d5a32a86cde6cb19562 +v[1] e586b4ab140cd20bfc70aa5ae1c389941a8c631ce033f54793d77c91b5e3d50b +v[2] 911122291921aced748e1346261ce8dc0e50704bf59495c3d7c1a9806ae58b5e +v[3] dac7c42fc0253029c78310ea1508b2464db2c44689fa7d485fb5863b7c136f15 +i 0 +z 91aaaaf3ff9e58f299c0f6d0a4a3851d100423e4b7380d5a32a86cde6cb19562 + +v[0] e8864778a3aecd6f35f8afa097072e94c4e50680baf91a6036f4f24fb0dcf111 +v[1] 5dec44933a517f5a8bf6d858920e1200c74e65132baf0d08ca033e36e15a1c46 +v[2] 4fca88e6d122c0a460b5dd502281d80616edd30bede891226b4b3c4b3eb9eea0 +v[3] 5fbf4e034d45326d89ffe92bf4738a7120c63ea42568c25acacf4dd7915b9e8f +v[4] 343001277d416dd31dc770232fc47c7d02884fef3fc10eaddf6f8b42fbb00b26 +i 1 +z 5dec44933a517f5a8bf6d858920e1200c74e65132baf0d08ca033e36e15a1c46 + +v[0] f0cfc16fe0cb8910c26f6f46e69954dd34277d171044140c2dc448b6f63e053c +v[1] d54feccab8d55297eb24f622818aaa2ac5b7fcafee5efe872bb600cbdce85a3a +v[2] 5f1cb6c6b4e8eedb566150a99a7c92228e7f737efa1810b9d40f9a4ea020e56d +v[3] c762a32a3f3a6f8cd956412eacdaa75ee56b347b952a7c18dd19c0ee2e50b8fc +v[4] b6e76d1d2cdf04692036f26515ca6b92d57b1bba625f07553d2d4adf89de9611 +v[5] 874c9e94d425fe9590aa1cde396ec56531342207a0e3b42ef0ae710bc9b68418 +v[6] 872ebc0bbd45d07727887aa8116a5743880093c73b3048c3b46920c04e0f64e2 +v[7] 9cde037629d20a4481ba7050546eca2dfd293b0953aa708764531bd8d0fba387 +v[8] e9f7cb8ed4af14ac61722de66406e97ee9a87d9362dfa87e489a9c98f8b891b6 +v[9] 6c5bb4410d83505ad34d10409d02fc005a47ef802b5d9130f3b5d385ff78957e +v[10] ff40983b47e7263665a03e4396421fc34209afaf52d7d69012833b4a228e6c40 +v[11] 4588ed141f6401c460ff6ad4888172c9d19f15f214d96bedd59f818d7c03b720 +v[12] 99ede977304bc4e8f5edc44463b48fc13c001f5c584f2b100c791ae472fdddba +v[13] 8ba76d6aa98a062e1091ca60e05ecf21208657bf287f20c6cacaaeff41a537ff +v[14] a18760b118187f5b392637dd5c5f97ccce583b5b84b69f8e37d8caf77c616db0 +v[15] 7e921cc5caa3b3884358cb0ffd2d9d160ed54256049fa1540d861dbb6dd1631d +v[16] aa8102188fbba89c45259c52080b3969c234d070411bc4b91870a8b482eedfbf +v[17] d98da58b248507edf310beb9fb522dd23d88bc0412ef3b5bd7a13b7a15070647 +v[18] 0626183221836da09c9bb5a1dd07df570883af17a9a8fed1c4bc7e8770e348fe +v[19] 16b01a5593b3eaf0902d0ade7e00da7b7a57556c2e7169e8b6ba5df5c5fb02a5 +v[20] e40715b07034e109d79a95a8b031eebc6c59dd0bb77de6cb960fe65a6d1be59e +i 20 +z f70715b07034e109d79a95a8b031eebc6c59dd0bb77de6cb960fe65a6d1be51e + +v[0] e30f85631b4ea4aadb9487c76cbec40ab63101a482e5aa2e3ee329fc21071bf4 +v[1] 8bc9fdd41fe1ecf5c2cc2075c72e4ceab370b099ddc672ee16bbd7a7de19dbb4 +v[2] ede086a76fedddb463d9f0fb44b39ac7fb64665061eb96015d4ed39eb33cd772 +v[3] a7cd74dc0c94aa8bfa480a88396b7f293f1ac329e4ce79e04507be4edbf4fef1 +v[4] 45f5c114a46bf0b2c8be1ecb8fc7c81e7fef668a2e4e9769f2f2dfecf405af92 +v[5] 123d101a02348f81088beeb6fafb7f720b49631736829d2f19e95b8d833684a3 +v[6] ba936ae1b5555b05601c2e59bf9585846ac01b5b7f6fe4bbd45e0653e961deaf +v[7] 51c0c307d99e34a617ead92dd37e1a0f36ebe2e45ef5b3690fd114099d483dc6 +v[8] af94cee7979c057995680c3a5adfe26e7dea759e2640b0b09aff383fa355d289 +v[9] 6ddb6908532c513f463473e449747f88d47766460ad316734c2cca87963b3060 +v[10] 88192953b60710667d47633be71d87214d2dc8be882ceb6928daf311499d2e83 +v[11] 37da1b76c2c16025f0644b6451027c8bc9768379c3aa7ab8410d34d8c8222706 +v[12] 1a46c0531cc13f546e001a67721931f4f6bf8eeeadaaab667ee651db0b272509 +i 7 +z 64c0c307d99e34a617ead92dd37e1a0f36ebe2e45ef5b3690fd114099d483d46 + +v[0] 9929839bce983fe53c4f8f9d07a462f82e8eebabba2c0daee1378abf585bb53d +v[1] 4e47d3997d6562c7b0347acc96925bd1907bf3a9c57d51b099c4a574d7bf8fc7 +v[2] a0de02656ba18dd1cfdb2938fbb864f9f59001110391ee1818f5c1dfee64f61a +v[3] 9c4153154f5b827bb847edfa04ce754e442f2e96ea001fc27f6d94ea8b06fc00 +v[4] 7ba90562980966abd857be3a84c1bffeabbb589415e722e51225f8317e829777 +v[5] ac4657b264ccfad4f5ba3f7a470458101d5c6025c45d00191ddd4bf85ca48705 +v[6] 8b11cfc6ceb02c5d4b3e19c19f1ae745fd0cdfd9da1a80e9df1be8f7bb99ace3 +v[7] 1202bae1f86d05ed8fca09965bb1cfa3fb696a3f2b7089ee10589394639da2bd +v[8] 143f799fc9ebec77aa444eb5ec95f64029cf61b875a2f94e228323844cb8eff9 +v[9] dcf99568b397db79bd2e8ae49778e1e49865e91525f932a1813d1c395420a43c +v[10] 84fdfee8137558f0b9f2441c375fce466e3212c0d0de3179919fb130e61b711a +v[11] 602454ffaf59610f76863a7456146f866539740d6dae63a3628d408e34db8e76 +v[12] 86ae4475d41ea312a97c821ac78b815e459dc6bb4d52c236a39e5e53ff17f5fb +v[13] 0fd56e878b74a2daebc2acc30c31c279f3dab146d748e7aa9b17eda7ac039c8f +v[14] e559e8bbd51113f84ebbe35ab16bfd46cf610a5c61307b986111ddbee3037f7a +v[15] bac90f3afdf4f4828368090958aef5e49aa83d25fc5dc15d9b8a354a30961e75 +v[16] 253eee8f614306e59a31d9fab5423ea269b67babd54c52243b86b8af1372f3ab +v[17] 69828b787af1831f772a3bb9a410dac8bc47909ac6bddc94a5c600a3167ce780 +v[18] 1903e9ca239847045875b0bd4e1575a724d9f729e3cbfc377de17ad29839a121 +v[19] 57bc65c0fd8495014f31e3be740967f3fd1884bee743b20b947339923530d63d +v[20] cf7427ebf6088e6f3385275f993b5c06ee14f738b59d49ecc327521ddced2a4a +v[21] 74c2a4122225e97b646d6a38584626a6ed811506ee7cd00b48ba563b7a776380 +v[22] 604f163d7d7f4987c8aaf2e7a946cec1597ebeb59aaeaad0dbd0737527b9350a +v[23] 30e7ae69cd5fb42ec00ca840988a59bf5688aa0b810bb2e9ea24fb5b322891a0 +v[24] 68caff542deb61b055bf65127a94d8ab107f5d2496764f97351dbbfbf34928e4 +v[25] c0d307ece7f18150d958bd88bf11912dc818fac7cae06ca9ec3fafd15d452af8 +v[26] 731b9ae286f29660fd0814568351bd6da114f3ee8b87c217cfe531746faa8c90 +i 8 +z 273f799fc9ebec77aa444eb5ec95f64029cf61b875a2f94e228323844cb8ef79 + +v[0] 85b3448d0292edc0b14cfae9225989a16a61ee8441166d5b97faf876b0ab6c7d +v[1] 88b0f7c78f8390b6cc1de0afda111326dbb41e7603b82033902eb56ea542c2dc +v[2] daf45d38b24294648a7b203758ff0654d42507e958bbd98c72229aae0a9e5757 +v[3] 98b44fbbf6e45c81c2473b626307506881a9fa609c546741b3637b731ff62adb +v[4] c0779c0f0a35658998ee9cb6b0cb6b7e089b7f288ea171c18bd2664ca5c3fc1d +v[5] 8da42494a2c1e2034d2009fd486cc230085fcc8af171e2bc2cf428bbf9b4bc86 +v[6] 6dfb99cec539941c9e7d26e5640641e4ef2c3f1a732f9c85759858a95c346ea1 +v[7] 471a369f8d1d3341ac707f1c41e5f0655cae51d8a170037ee349b3c14e01be2d +v[8] c1b75b02941ae0c2e398a2c8871955c8306f6ab88cdc6d751e11b35605d10829 +v[9] ea508e41e33ca0b03b5d93a54ec359e01a5a00a98a80f7e6d998641a6cb7ef58 +v[10] bb009a72b5d5be344a3ba9509b6e8eafbafdab4b0ec9202c8d29983935c6937a +v[11] fdce2ff0df8548fd7df3b8a087aa30c819af0eff3b8931e5ddedfdb0f4450919 +v[12] eea3990f7f4045a3b6cdae27e4dc8a8062049ac4423ce46108ab464d866b80f3 +v[13] a18000f37c8c4a30195e71864b14f170a3f5c427f4769c736fbdc18b3fe68887 +v[14] ba9aa19e99a69b34f357f92d95a6c409f1bb331d1d27b693164cd0dbb552c771 +v[15] b5863e0215351b2f9b6f661ab94c833016bdef73a34b100b6db79ea8d4b22ec3 +v[16] 983eb31be6cd1cd4cb53e489e4535683e21c00e6c52f685e84bd3cfc98f9ab2b +v[17] c31c18c6c12feb3be4e51a1671fa6001c1dfadc0ebb35349766d9d07d5a70025 +v[18] 6f81695294071c711947499c2c3d96969a70948c29ea9506ff675d25052f0950 +v[19] 3b42ffd7fb054072e7fb93bfa63d24511e6c93455cdd5b9be3c8382a3cdbfba4 +v[20] 6d7463ce0227e29a2706b8ad6be0d6cefa173c261697520b23edb87a189d31eb +v[21] f6cea0722a490515f48632f42f167a911ba00fd9883604e52d713210f3d9475c +v[22] 6281bf17cc14876c75e9620d8bb9bfd6e4dceae1ad3cb675769f94623ab3a955 +v[23] 2c943465a6d4484c71b2c5ae26e1d738059667093450cff54e6b45f12a7588f4 +v[24] 3d9ba6aad36754c5c767a0f288b6dbfcd2f1e21bd14094f4ddfb7c4bb79ef882 +v[25] 052e95ca0672218808e36c18e1fdee412a945ad735ea883abd527dfe8343a51d +v[26] 3f8ec0ccd82005e01ffd1fd7413a2a1dce1a177cf53474904cc46abdffd22a22 +v[27] 2030168387fa230e7a77eae5f051b4e0f1cbc53a78a5df640479c9fc373b9d78 +v[28] 3abd6a4fb5a585bb1b4609cebbbd1035392c7565654331a173092c098e1583a2 +v[29] 6bceb64086f3874854b4c89d31d20d8772b2f48be6a5fa1fe572be9927345103 +i 2 +z daf45d38b24294648a7b203758ff0654d42507e958bbd98c72229aae0a9e5757 + +v[0] 8a9e76766b2eeda9b4de923344005a825bd2475bc4d529b033de3510cd405b73 +v[1] 5206880a0e1c282a10e03253c787e005bc9a18613b6e238f1eb72c604844a2ab +v[2] acd4fe99d1df199ca20c743238a2bf9562ea4de7b82061d1a6861d77146bdfb8 +v[3] 6dccfdff241fd837508913d7e0b1ca3e7a426be578c2e82612f7d2b2491f08f1 +v[4] 76aa8f5fb4b3592ff58785ea27d287fa5f250fb84fc9838fad8d6a2cfc223dad +v[5] 71019d81508491afb6a33d8c99aba13d59c63bb88a2ba1182c144f171ed5a815 +v[6] f6ab8f0b95fcaad29def12e05f348a9a35449c7ef5e2859748e69c517f4f3f65 +v[7] 237b33cbba9ebcae93f8a4fd863f62a03651be2e936ddb5a62dd3b6a68734b2a +v[8] 4bbe3113be34a9f7fa26dd96258d1776797b8ea454a2f596ae076bdc0f5d0ff0 +v[9] 19ae0acbd7ba59869b51caa13e1041bcffed633235a858f39d0d583575a64123 +v[10] cc5e18fdfedf9a416727f81b24a227c0c0771565fff69fc3e19399a254d8c9c5 +v[11] 50765357fa421d9153c1f02adcc98f188d2aac6a39fc8d522c5e81fbb775bdbe +v[12] 10e3e53b7605240cadc28c4d3aeb1afe40b7d1d547f4ad60c8d03006b42fb499 +v[13] aec6bfd729a6e2898890c9ee15338aec209c94141dad7b7884f7be481a2f0d6d +v[14] 8f9620a5b985a3a1dc4825f1f4c683457a98f799118691bc57b17ab42713b593 +v[15] 92c24c6920edb4f37e73dd795ac9bbfcd8035dba28421fce290109c222bfbc86 +v[16] 45bdcd99b590e64aeb5173c7538e77a7cd10a9d786338c43e3a0946b33a9c822 +v[17] e0b86e6b4752ea2cae053b1bd897c6d749c7fa46308be876b8006c3ffa2d6479 +v[18] 6cb53b7769f0da52c697c8640c029099d84afb55c20c9ac84b959ff36c339e92 +v[19] a21436f9a4c876375d16c41bd3780f024b867f6fe6394c5c64b4ea5a6f306c7e +v[20] 93b40e751d291e90ec3adf902935285a5746781bfc1c594d520dc5828ba53d3f +v[21] 6dc080d82251557b9804deeaae90bb1a45d9895c5067f3b04dbfcbb5ab0be3e2 +v[22] 22783694c9ab9d652dc216306ea4fc09734e90bd08625e688b9bc1b8c73e3366 +v[23] 078b0d30cc5fbb248a5e84a416a3d849772ef6eadf20f73eeb82125f68a216e6 +v[24] 83dd79bd150e5f7bf7a357236ed41ca06b8c40bcce840e118f6cf457ff151654 +v[25] 72169420815aa9a38719072be9c824d68a0cc5d6b4251ff9180938def3dcb0ac +v[26] 63f1febc1579b537b71e1fd12687ec49885dbcf93db68f44660bca4780ca9aa8 +v[27] dc337f8a3699ff549dfa26c1a5ddab43cdac7062d90fc2a779ff528c414035f7 +i 16 +z 45bdcd99b590e64aeb5173c7538e77a7cd10a9d786338c43e3a0946b33a9c822 + +v[0] aa199ae7d7c298e11aa74e5bcff2f206fe6b53962f3bb39767ad6df19c58d93d +v[1] 4b95d1e296609760e06e7e476af7182db41712d73be94a3533b7332a7dbb780d +v[2] b72f91cbf1117db1982b035f0e76e51bf4cd8e968b932606450bdae0d588906b +v[3] a1de9fc4d0e579aad319de0280fb45b5fed6c9d38dab5216ff8401376fce0230 +v[4] fc216489a815b0c98969118c9ada3f7152c4eb07217abe54fae4fd4d63e96811 +v[5] b660cb7ac499821dc872c3400fb2590527659ecd72df16c7ec5376075fca7d7e +v[6] 3bbbd9dbbc9263d289de49b1648fd64751d8b0e6d5d506a356fee0ed6452ce89 +v[7] d17efdc8cff826d28ab55b51211209a27054f2d33f108f34ce7bdc5c71b918e1 +v[8] 21da90e37be817920404ff5015346dd05ef32e018632e09b7cea35d42eb1de1d +v[9] 66da40ef6fae8df49b5aca9a2400ea4fba527a9513c821e00985625615e71416 +v[10] 61e5b60766ca457b36aeca26a62e6f4831691ef79bdc72158c2a2b85fe3b5cb2 +v[11] 9a0917795f936a5384c4a504b2ba3d7056906ea4e34474c310b873f88890bd37 +v[12] af65ade7e8f0022420932d50d0a8587c43ac4436bc511248358886e2c7072c1f +v[13] fadd2a9fa72f438f147964180ffba490beaa55baf6275d8ca347ce5f5f94fd05 +v[14] debd9beec2527f284790a9ca8fbc074ec359f4a89974c2ff49780fcb21c5ea91 +v[15] f6a57794ba1265d9974e52f856acd3dddd0f6a50844172466c82f0d49eef676d +v[16] 97cbe03e723431b6c14bf1681e845d530e083ddaa26f055d3e162615f57c113f +v[17] b89054ac8b7135c1e6d215e4e5dcf679298fdcf6ef35301002be560389f8cd08 +v[18] 8ba6a9d5ee4bf15d87170e7c050699e858c6316bc92d5f4e19eeb3ed82e012b0 +v[19] bf0f272aabf63cd98397f4da2fd3c5742373529c91ab455fdf394fb6d0b8272d +v[20] 7a2a4980dec077abbd6a06f8b90219b818d4990b8f62b9dfc50bc4feec31eaf6 +v[21] f1d55b4e207cf5b7bdff5f59a63b55fbce6704b5ace5c5183f6be8e4770c567c +v[22] d55b23bebc2f16fc9adddf06ece363add71c4cfd73ab228461cfb926addee0cd +v[23] 76ac92ee62c2bb928bb5ec11673b51c2f1fec44ca27741a647cadfe55733eb41 +v[24] 1544a9b6c6cf77fec3e83bb08056bf18f3eb440611249f60cc97b58b5a93d364 +v[25] 702a0023d8ff6a108a2eadb777569f54df2c3b85634bb872611ccd8cf74e2807 +v[26] 8dc8889dae004e88a94f3c3beb4d39da7c074a038ff8899c5798f7a26fd17ec9 +i 19 +z bf0f272aabf63cd98397f4da2fd3c5742373529c91ab455fdf394fb6d0b8272d + +v[0] 63eca008f74f57babb34dde1fbaa5264656007f7479d8df3ba5cccadbe83925f +v[1] 001a67bf61d077528bf9b386694a99d7293d6b49f368ad54767a2829643621b0 +v[2] 4c124850c332a4e2a6a335e5f5676f803ede7958719b083f648137cfccb82f50 +v[3] 39f293fdd5b28c882b824d1cfef38a327334776139bc2d814834a86d6b2d93bf +v[4] 114df0c93aebb6a764740e43a67c6b582b49f6d0c393a23db42611023c044d9a +v[5] cd9e11bd49d7ee82e52f89d7100fd64c4474695054cd22442ed2bf17991cebe8 +v[6] 56931f05328bd38dea431af6537fe4a4f1e419a24c5181974e61b64367a65a5b +v[7] 2bec95a108b7a500937b5a3f3c54ae9b2cc7b11629ac581f7d8663b9c910af96 +v[8] 380777fd3ab97d140a142d3d37c7786264ea00b63083219652376d7fd56ea846 +v[9] f0fb2846d9cb0b88751db963f9360ff2bda25052eba9edd2ec561807c1f0fc27 +v[10] 34294c58ff5ff91f1472dc3d7b3099c81ef434126c58de3751c788a71f2a78de +v[11] 05c5a1c0bf29c1bef5da9298450b8ce6c5856b3f7e2037133734a03959573927 +v[12] 7fd9db5b2418267e94db49ea0534ec8d397f32f90981448c944a4ff3cb6d9c3f +v[13] 7015d096ddd557e669fcedd9b3b2624b910505f756e8ea160c5436bab604669b +v[14] 46858fe7612b43ba805a6c7999a3be02b1e635963792d228f1414fbdf13e175b +v[15] 70422706d36540ece562d1c36bfc5b178d1cf47c1ed87bea38be5a9f95010521 +v[16] 250e48d385aefbc10776582e71e4139148c99d6f9ea8c46a8e57194986eb2ef8 +v[17] 44accaac045de3183f7a45f89d4bdb5534594c90296ea664061f3f8a142f2d7e +i 9 +z f0fb2846d9cb0b88751db963f9360ff2bda25052eba9edd2ec561807c1f0fc27 + +v[0] 3fca772e14531611cf82782ecff97358f710763698b73e84479056a97d7d352f +i 0 +z 3fca772e14531611cf82782ecff97358f710763698b73e84479056a97d7d352f + +v[0] fd8d6560ef50712fb5f0707c342f618cbbe5697d261d249ad4887dc5ebac4f07 +v[1] 89c98bc89a81402e218e377257bd1532d524dd33a3b8c0458b2e5211d4d7b305 +v[2] e48938f9271a8861d46fa6063563b92c0a6fd59634151b075316faad9c87008e +v[3] 332fb871bf280cb18dc5d444a565ab1e505d274e52c231808af7d52cc28990de +v[4] 9073abe824ac2d30ec9562a5a67836af5cf9c038aee85ae1f7d387da64f558d5 +v[5] 04c3ffe8e6ed014162fbe6f3b8467114afdb6d5d51ad878c4462d8a926d9966a +v[6] 5864d08abd45dd3d4b6e59762a8feb76cdbcbab01a66e512d40bc070e2754ce9 +v[7] 0a780e6ecd9b4ed16cb4fd1b4b060c74d97a4268733855102b036f89cb4d5bac +v[8] 34bddd4d2ac8a920864e6b9cff04ab70f9978a16d0ceb06aee33aaa78e49328e +v[9] b65e8424be6a9247ad08f01a28e887bca33b3f5c28ef3adebf37798972eb99fc +v[10] ebd2aa397fc49104dc1c3f82f275bf625984c8c84a6f699e801b736c667a8cb8 +v[11] 8a704e508538e1d8a64c4c9052f46a07151c79dcf95e6359a8e5f41370ba40e2 +i 4 +z a373abe824ac2d30ec9562a5a67836af5cf9c038aee85ae1f7d387da64f55855 + +v[0] fb1b4c61b9b2fbe2faa5c0e3227e3c2fd4c8277aa629fc88fc18a4a29df3d6f0 +v[1] 3431d240f65ae76dcca41df165a4eb4c5af155027844d80a0c7f0d07ca4b5761 +v[2] 67e879347f3adcd41cac36e8c80a0f4c2ea80eb08ae9ee2b21e528769eb4c7bb +v[3] ce843b0190451928f2e637449b5ed95580645a0e0440ab017026631c619d2bcb +v[4] cc85641974b86dfa780e3edeafc0d6730da6f579826ba8f9bb8ab065b1e149b7 +v[5] 2f0c812e2c9114bef4810a01d108ff001fe328d575cff750e30133b464e2648b +v[6] 407a5a8964f840ca90aa4cf79a18f5760f7a8ff23bd6bf2d6dfc88c980728aaf +v[7] 26c2b3f4075ede77023b2de230edf8ce5e75a0cb9f1d81a0d154ba5d79de83f6 +v[8] cd98878185983eebc6f188559d9bbf8dc422eca6598a7df35449d0b39106c706 +v[9] 42aea74be96565c44c08df95a6aa58603085152d4f7fcf38375283859d17a46c +v[10] 31383c1609e8be3dc7279916eb5bb5d3e95e745a96f55ed3d69f296bfda19a28 +v[11] dc140f380ac16ab63124f9f7a02aa458ceeffbed4a9b8e31f45c67ce6ce1c394 +v[12] 81bb67da90b02b5b19ce9863902f12f33a85795994d7d22b914f0e82a44a4f11 +v[13] fd76e39b1d68f07e538353c0ffeb0c1225f5de64166ccd419c10134329f954de +v[14] e9f40437c324cacfc6974bee082cdb82c432a86d8465a0229a1e05fb19dec82d +i 0 +z 0e1c4c61b9b2fbe2faa5c0e3227e3c2fd4c8277aa629fc88fc18a4a29df3d670 + +v[0] c2b1fe3853bbed5be05536475b2f1bb818eb5ed0111f3be6c6b3bb8ede2d0beb +v[1] a692dee2a40878814b9ded7ba7ba47a391585ac93af04a0addec3904ed912ec6 +v[2] 015e98f69b98f157f559f8282bfbd20e07cc4a9e2929feab5a8c246011d1098f +v[3] 76761cf13e45886da2b747f0de3a238be8aaf5868eca88c4de6b614ff3902e12 +v[4] b6b06a046fa5f2e43e698fc96818cc7bf888d5c4f4f2f0bda86cc35c1b48679c +v[5] d7ecabc614122bb6908ebabcf7bcfa9a4fae88bb8450d559297c778dd35279f8 +v[6] cdd96bbd24cc00b4fa5c8b20efa66a3db1d62e76f001dbd87800fc59f4a29a1d +v[7] 9c16ca817b43101672fd1cb3583a6b44bfe2ab5956794280a3a32bd2aa651656 +v[8] 4d7ba5f8240527b3c9de386b00dafc163314b3f1311bc30b8434993b50e08d67 +v[9] c4ab9766eee58337a92412440f12083a0205c39ba27e0877613b4288dfce9899 +v[10] 71ca275f3f7df242b5770d37c92425bde86184ab23c06c6b6bec799c47651433 +v[11] 49da5429ec1ade01eba828ad21d230cced84c8a28f239a69194cc0b5de9a0f20 +v[12] fc17ee1656b6f0de36158fe2db82ad3f63c196c54002728bde4c5e27e6c0d7db +v[13] ece944bcc82f520e8171aefe728863b99a9772cc48b714d82426224b302b7be2 +v[14] d2ea262ae062bc1167e79a7bd8abc2b6c7cbbdc03622495d1ff3a56e23c03f72 +v[15] 9be5176e8e873f9c320cff256e7b8801cdc1cee0b32ddd715d71abeaf909e0bd +v[16] 0e666632a0ea9c9c5cc3fa519a42c34313ed2f64057106e38dddec87d68146b0 +v[17] dc48385d46bcedbdf17f43e7b2de274556b411a0ac4b7e89a2f5f71a1d1ea5ba +v[18] 76919d83ecc757cfcd916e23e5cadbdda21793a322c0fadad4e581819ebc0b18 +v[19] 84830e7a1b4b50e6ba90fd5f8b1198aa60b0c8987c962e9eb12adc2cc389ee1d +i 11 +z 49da5429ec1ade01eba828ad21d230cced84c8a28f239a69194cc0b5de9a0f20 + +v[0] 99f065bb53134babd50f3f46adb63c64f7600acb39487718bc0a39fd3a5f4ebd +v[1] f70702612b9b45f7833232a7267492299c23caeffdc4f8a494653cde777861ab +v[2] 16c9b6b125cb9cbb201cd0a558fd58cc29f2d197b9b160a0cff88ac890b9e429 +v[3] ff87c5e3356c8fb8dbeb739aaedd0df3da2ec3072e5a806569a5847fcbcb4267 +v[4] 01d23260fa58bc7c077e05cac9e1359a9f4f2c9f2bc8312e0832376e3c3cc554 +v[5] b7b5071166d68c704410d4e9123a261631822060c336b8cf0f5685a7df6ae6ea +v[6] 621633e25b1ba392baaa31fc2d6a57e8286f6bf6e5edd5a0268a895af91d61c8 +v[7] a29ab1d52fde5e7026124c3cec2be1fa674d37692165f46d1d91bb9f41156a55 +v[8] 26d8eb53078f2e515bdee3adc377a16b54ae575343888c27c6d72e07dd7ded04 +v[9] ba5d57dae01659afb41b3b4712f0ccfa3b6b2a0d8a99fa5f1078203925897618 +v[10] 8cf51cab05199e2154a5bf655e6a9e9498c20cd08b564936b164b0a7f49a1e30 +v[11] c5b3977228539a7f573c88800633f1da39a3f1bff9e1018af48f94f211a812b3 +v[12] 149a93a1ded07e398fe248962a7656f9b0f15ce62c4aa0bba4a3c6f00cc362f7 +v[13] 234974b4054622b0672626f111ea5b44afd81dcb15f29974585c9b77476d9290 +v[14] 4be4b2338d92909e6a138d4d2e53e72707a4af62acc8cf2a121c8105ec4ebf32 +v[15] 1e6192c030263e3847898afaf5003000552b9ccba7caf6361c1f34fa0890b086 +v[16] ba698e634085f7dd38da012c8c97efb97a9b3c08c829d660e72e46d12eba79ea +v[17] 712198efd6734fb564278f1bd0dde082482078548dcf4681e65e6dce39328c1e +v[18] 8cff8caee2ed08e384331fc0509c1ab44b291d840d19ee991c9978bb7642b4c7 +v[19] 98a539cf588938c8ee31d80ff0254e13460f50d7907885f2debf7b68be91edf0 +v[20] f0cc67c038324ed37948dfd94ab50dc6fd07ea8b441009ea2c4e185f0d800b85 +v[21] 09ae723e872da1687e02c883a254e033e8c67e784ed33e3a28eb8cc92be37d32 +i 6 +z 751633e25b1ba392baaa31fc2d6a57e8286f6bf6e5edd5a0268a895af91d6148 + +v[0] 97379391993ac07a0b019c4b6d2d08d4555e5761b4faa7bea8eac269844c6106 +v[1] a2aff4f6141eedf254a8f7122ee37a1403b97fddc2805ce4ad010829aee1575e +v[2] a54665a1ac19c8ab83dad06bb5ce855b45246a9ad338516c5d67948f86eb1aa7 +v[3] b8fa1fa064f6bd0af94d427686a09472b6a841576754500464ac3310cc147d40 +v[4] dbb4cd734b211f5ad48452a193489fa25b0c82a594105a96ad627c5cd5328596 +v[5] 5396b8de36ade038e4424344fb2083226410f771c8ec979e916f37710b56cffe +v[6] 039b59e759c9a380200b129e08d77ef53d703689b60ba5f117111ddd27f1674a +v[7] b3456d7bfa566b925ef014c6538c89251b7c0fa9fea89fd1806f97bcbfc3cdb7 +v[8] 4ab7a386cbc720b5676de0e76d584d6fa538a0015debe30c37e1839165763d5c +v[9] f7f55c12c67c1ca28b3947fb7bd7c4ed9a5240f962425b9b4810191d448af7c5 +v[10] 8dc0a95877c2ea17052b55c9f93440319ec38bbf80b375177e84ad14bab558dd +v[11] 246d97123750b41e5bf2d96f10b3c9e66e92759373999bd94191a65f25a864f3 +v[12] 5bfa2905cb0b0aef125fb39deb2cd392b3cfe3f3ec58f8361e8cd5f12bd2db98 +v[13] 192413efd53bb958417f65a818d48d6bbf94dcc77210d9623adbca15633bd7ad +v[14] ee95faf7a7f31c7afd13d393ff2ff4e448799c87c62092e9e646efa4c635d1f4 +v[15] 77c00984400bbdcc81aeb42085c44be70137db5a0464f6081aa9c8e646e96e1c +v[16] 743cd93d6f6a48161881d2224b7d7c0ce96d56d54adff0b719955cde417b35a6 +v[17] 92b99335dcf6b33de126d05329d8884802cc3afd0f93e9dea7db5f6dbdc6c623 +v[18] 584ccd19fe7395f9f2dc53f2a9da292e0cccfabe82bc46aa64c29581fc570deb +v[19] f9321c751abb9df278fbc2054e3fa368734cc852589891b49580332a52b6bf72 +v[20] debc2bf3cedb7c897924936aac0b485bc05eb89530c886299e8d1ccad277355a +v[21] 472d49f8ccc249b8271fd0630ab575721852e98015ea27732915ed06775b444e +v[22] 7b29b054a2347baeda4dbd1b739072e6d144aae3547adc8287c3af84285057d1 +v[23] d7a79b1f1ca757e17729436fe744ea7d99a64d13bf85737b6a71d41ab13343e4 +v[24] a957b6345193173a231d9db8acb3a6c09bb411d210e0e52c94e75a4d68602aba +v[25] 6277d818cbecae95f1aea85481ee631ff1e7c77c6693e6349d1804db784238f2 +v[26] 27e1d5a11dd9025508168d9d11cce0b8f0768b6846105161eca53abfa4aeeff6 +v[27] 1823372e2c7cb9fdcdc97ca64ffa06564907b09015472cfa73bf0a45d7c90bec +v[28] 08cfef24b9eb875598779315de4fcfc918931e05f49b374113c25cb5b23a4944 +v[29] 3a5d9db56bac2f413a3d33b6d7a2f54053aa3a641d6554d6f008779939f2682f +v[30] 22d0256cb1a53aaefd5d2fde14b63e5adce607ee5a22e8498f29982f88088938 +i 18 +z 6b4ccd19fe7395f9f2dc53f2a9da292e0cccfabe82bc46aa64c29581fc570d6b + +v[0] 91a76b64122a404fbf873d65089a7613bd3d93c4227a4b05817223640ec20ee9 +v[1] ab46f7649122de1d73278608e02d44a1367f4f5a7c01d1c17f2a50fb3148dfcf +i 0 +z a4a76b64122a404fbf873d65089a7613bd3d93c4227a4b05817223640ec20e69 + +v[0] 1c12d157172079be7ecc31716fac8946f5517a3da6612bf4a0db65707e72764b +v[1] 9d9ec126bd404e82448a16c187152307ab6319fdd5d4280f070275cedf1cced2 +v[2] 25be86a2abbf7619f7b92855cc50572af4fcf6ee071078d24baa24d623ebe4e5 +v[3] 9b3a13dd1b67a284a9ed869de2663d82035342bc0cad65484da1c7b60b82a55b +v[4] fb82840bfd348ccaa0d3d362c1123096a5103a09f979e2f4acdf7aa600e55a84 +v[5] c64642a4946ed50924eb1a4c6ab73b53942c5a17cc868f8c6c5ef92ce5986830 +v[6] 8e7aaf58bc15be92a31af4f0b092969a250222e7ccbdb638aa846f8253c33d50 +v[7] 375bb009118659c831591bd6861e9c9eaec85c0fd9a1facd5f2767ff27e3d36f +v[8] f5b4b72840ef438fb8f7fd1419aa5248dc38126cfc29099cffe68aa94b215b31 +v[9] 3b0cf55a0dc7856788375bfa1390fe4c628c271c99ea76ac78517ad5f36f61ac +v[10] 82cf74084903490f30152c730970f8b622de5414e1a60e1efafc6aa57ff2fba3 +v[11] 9d476226e3c4f844f392e7efea7726b02bea64c9aa1e78513efb28a000cf9624 +i 11 +z 9d476226e3c4f844f392e7efea7726b02bea64c9aa1e78513efb28a000cf9624 + +v[0] 4f8b3919461d4408a4d4375688f8985332745cb5253671dd7fea3c58b8e33e5b +v[1] ecd4f6bf71be54fa88e51fd9d98f60c009fa1b4f15ccacdfa7b26a5ba52b1794 +v[2] b0bc276ac01ed6b25fb569ec8c614f4a9299faadcb93bdee4dc637c888381d29 +v[3] 2fbc1564ecd906f5d56838c9ceb3ba5b5f13925cadd653008f1ee9f54c18ea37 +v[4] 66e9f3ed35f45675f9601181ddcff688229371c6428c1d9dc67699821e3130b6 +v[5] 6b08a213ca51403db7e08bf6945b23ccb62465f582248661b901b6e550345516 +v[6] abdb83672459dad5b11c3cf9e4d21235ff92c01ab00b2d44aa6f10bfe9b274d0 +v[7] f609191b4efb288359af7170acd0904c57d45c7c658c0d670e0fb22f9ebc0044 +v[8] e4056ab4b8afad5e6951c8168477f15ee3e11fe3f236a1d19ea201f78b8898a5 +v[9] f3b253fd18515ee3dcfd4a14409838a3d993a5274bd77a1e5a7088d20ba6c592 +v[10] 710b8819a202ab80bcf308aa94d3305944dc739e33648df045bba215160f8ee9 +v[11] 1b63314e9fbd605ac063546ee4249bf9f37da0b6b78d99848f487c6880f70c3e +v[12] fb04f3e49a44c4eea104c213446b0e6b81da047a0862604f488e0c6128238d3c +v[13] 43b1624809a253f46b12d97aa08dc3f16b25613022483b8044cb01b6d23cfb28 +v[14] 0796291d8916b0b70ebdab0f42b8cc55c14734cf7a398d48f94b48d9871ff0c2 +v[15] c55cc772bb71392f13258339eaa1d8b01c402e8f6c9b6061f0e1c564feb98234 +v[16] 882ad3994d999ac7243ebe9955468a52b2242564a295a9740af8980043f9ef0a +v[17] 201f86fc5826d74580c3bd3fe04cda2a823c2a4d1ace3e862a9bf6873ba25055 +v[18] 5c39347c213f6e1b5ded1de9f92ed21d99721c4e4216d5abe207321caa426971 +v[19] 38ba53a577809f2d2c3cc33016e6141f4a87b6f57b75be70b9cd3d287f07ab00 +v[20] 7b9e12c5293fd99ed3fb50a2eac4587bca4aa8bb97c147626dcb9688593ad2e9 +v[21] 4852c30283c1ffa109aade1353d11e9712d8c4e6d416926f231a2b89b78fbdbd +v[22] 80d25270ef8002232cd0e35433ecefc135cbcaa06511ba3ac14484b6e41c953a +v[23] 6159366a1aee4692a9986a12234728c685cf766ad3e2c4cc842f1142c0fb856e +v[24] 95d34152d18b9942bb13c6bec8e533c259adfd69dbeb06da63c351997463cee9 +v[25] dd5890be52cd0207fecd0f93dbd3a6819aa2c5a592ca0975a419104e7ff4c284 +v[26] d9c3f02b7644b3580d190f03bfc9accc8abf9546463a2171d9cb19b3783e0c92 +v[27] e59449e7a9d07631450d85d108f3cfec2d67d63ad65a7311b310bb10137fcdbc +i 27 +z f89449e7a9d07631450d85d108f3cfec2d67d63ad65a7311b310bb10137fcd3c + +v[0] e5d98efcc2879f32793efa8f96dda9c87b70834fc9d468dc464b0940a7dc160b +v[1] 04d4bc5cd4690a0c6561feae82c6be57195c7553276f12aa16fb930ac47e315f +i 0 +z e5d98efcc2879f32793efa8f96dda9c87b70834fc9d468dc464b0940a7dc160b + +v[0] bfbed3f0a31b886bd96a817e0b65be1b1e374fddb237514e89fee7ce34a08c45 +v[1] eedd85cd817fc74938e60c366445e6bd5383dedd290db3633d5ed2ff320139a2 +v[2] 006b1e62b3aa1830de71c0ae063fbf090e536304d601e6c851800ff1d501d249 +v[3] a4a63dcc680646b69c8e651dd9c3e043bad07eb9bd6b55bc5bc854d82bbc6b00 +v[4] ffa2e97c95ef5efb87b78e89f35e95f89c1c1b2591673fd2166fcc9765abb4b8 +v[5] 030984d84d3d9667e436996578a3ae58853d44e111990221cd15795167475426 +v[6] da8350e83ac6d67029c24a8d386c6352a27bd22fd6a207474a952742790e4be9 +v[7] 0618b6f82b936b5eca87e9ab8dcd9a2e3744586bae01a75cfabb23b1b64f7aab +v[8] 5a3e077d0d0d28ba3b6d6fefecc6c2f7ca530fa63bf414976ac8b26ed6596a3b +v[9] 381e56750672340b18b60612bd462ade52d3b0d5b487f1af8438140740df484a +v[10] 65275cc865fc4b5d94023fdcb929dd27dcd64870773c79f015d4a5f30751ef2f +v[11] 724f96fe61888b5a885713d0c52e759726b877031b3f4f80ad24bcf417a3dbba +v[12] 17f55299b7cd1d851091052401612078978bf2b09fca8c9e2189474e9d24b81f +v[13] 14b82eebd7325586c1ed8be9353fe5ad9375290a92e76d13947c6405febb2f52 +v[14] eb5a5c7771ccf698a2e803a3a4e6db056ceb0da4d808db5758f2cb28ccc44bee +v[15] 96db7bfd64b7d41430ca6fd0714487926d02dc71571161f8deea0f6a3b52ba80 +i 6 +z ed8350e83ac6d67029c24a8d386c6352a27bd22fd6a207474a952742790e4b69 + +###-------------------------------------------------------------------------- +test condswap + +x 14e55571df646a69a8280bf8dbf8e9afc15bf5558bb8b8236ebcaa19a96053bd +y 8bef5021598a8175565e1f2b522ed1c4306fef4e0e973b50d3a03db1fcf11a43 +m 0xffffffff +xx 8bef5021598a8175565e1f2b522ed1c4306fef4e0e973b50d3a03db1fcf11a43 +yy 27e55571df646a69a8280bf8dbf8e9afc15bf5558bb8b8236ebcaa19a960533d + +x 53d8c54864e18f8fc742b2cb996f1d7595122ca9c90de9f49485cf5a5ef05058 +y 9aa95be655b6704a3dd482e8424f82d17443ae26ab41092fad95df9cac678787 +m 0x00000000 +xx 53d8c54864e18f8fc742b2cb996f1d7595122ca9c90de9f49485cf5a5ef05058 +yy ada95be655b6704a3dd482e8424f82d17443ae26ab41092fad95df9cac678707 + +x 8c7b4ffbf50edf7edcf8d69b67796de38b56a5d4e3a9fb2201354cca0b1b7c57 +y 856e707988c37e59fc6689d024b98bc01b71034484ba194ec7f45106267cb7f6 +m 0xffffffff +xx 986e707988c37e59fc6689d024b98bc01b71034484ba194ec7f45106267cb776 +yy 8c7b4ffbf50edf7edcf8d69b67796de38b56a5d4e3a9fb2201354cca0b1b7c57 + +x c8cb24a636f6d8f2c045c8441b21314884a71d55c73d4ef7ad65620ac0d86616 +y 02b47be53df7c8521d57589256e69b8bbeb1e838d84c090287c04a25d5c08e1a +m 0x00000000 +xx c8cb24a636f6d8f2c045c8441b21314884a71d55c73d4ef7ad65620ac0d86616 +yy 02b47be53df7c8521d57589256e69b8bbeb1e838d84c090287c04a25d5c08e1a + +x 7d96f47612fb7135edfa71dd4526d8b4c944d74ddf004e1653d3af52485168b4 +y a4e83162602d20cf71a279c1071038ecf94f38be11ad1191927b3f480d393e1d +m 0x00000000 +xx 9096f47612fb7135edfa71dd4526d8b4c944d74ddf004e1653d3af5248516834 +yy a4e83162602d20cf71a279c1071038ecf94f38be11ad1191927b3f480d393e1d + +x c3a3d4462091b36bd6fd494e70c3166478be0a65bca7f7361246c52dda402981 +y 62d0ae1abbe5cb909328f59e71330269e4f2b1d3c664e7f1f0780e0a4774c262 +m 0xffffffff +xx 62d0ae1abbe5cb909328f59e71330269e4f2b1d3c664e7f1f0780e0a4774c262 +yy d6a3d4462091b36bd6fd494e70c3166478be0a65bca7f7361246c52dda402901 + +x 38c9b0d92be50270e29cc3181952e745cbf21c8d145ae0c0a6e59f25394ea59c +y caf4896a2d3666200741d817ee1dac661652b9a1741ea966d5ed7cbc4c76217a +m 0x00000000 +xx 4bc9b0d92be50270e29cc3181952e745cbf21c8d145ae0c0a6e59f25394ea51c +yy caf4896a2d3666200741d817ee1dac661652b9a1741ea966d5ed7cbc4c76217a + +x d637a72affa4112bbccd2878208ce34fae442e97175e1b39f43c00b14d312a2b +y 76209f8b1f152ba7e1e6294f707831021eb2ac03872ed3774ab8fc5e6a0e864f +m 0x00000000 +xx d637a72affa4112bbccd2878208ce34fae442e97175e1b39f43c00b14d312a2b +yy 76209f8b1f152ba7e1e6294f707831021eb2ac03872ed3774ab8fc5e6a0e864f + +x 12f3bd417fb3860b2a4fd04eb1c51c558a4c5a3dcc1ac457654a45a3cd45b0d4 +y 46f802836c7bde099775f3fb4f5f6345364a7e158bae9e16c4c99aee0cfa5e42 +m 0xffffffff +xx 46f802836c7bde099775f3fb4f5f6345364a7e158bae9e16c4c99aee0cfa5e42 +yy 25f3bd417fb3860b2a4fd04eb1c51c558a4c5a3dcc1ac457654a45a3cd45b054 + +x bf1809201f83a34cb07aa2e2372516631ba0513e600956e6702903e9084770c4 +y 414bbc77d13d7b4e706acc07406e8d624f2485463f9948d81b72268c1e086a14 +m 0xffffffff +xx 414bbc77d13d7b4e706acc07406e8d624f2485463f9948d81b72268c1e086a14 +yy d21809201f83a34cb07aa2e2372516631ba0513e600956e6702903e908477044 + +x bb8703f2ddaaaaa6ad19219684b1bde576b38bbe9065178b24c1bc55563fe525 +y 1cb3ca7846a3c584b1bc05b25ee91d4779ab9ac64ecef0fcbaea8d311b55d618 +m 0xffffffff +xx 1cb3ca7846a3c584b1bc05b25ee91d4779ab9ac64ecef0fcbaea8d311b55d618 +yy bb8703f2ddaaaaa6ad19219684b1bde576b38bbe9065178b24c1bc55563fe525 + +x a07c7110c32e362864a42cd2f371ff420bfd442d291cc15ec079d642b5c85bdf +y 497fa7867fcd0617c4cd765aa6f46b89390744b5b57d11ab732153e075fcb607 +m 0xffffffff +xx 497fa7867fcd0617c4cd765aa6f46b89390744b5b57d11ab732153e075fcb607 +yy b37c7110c32e362864a42cd2f371ff420bfd442d291cc15ec079d642b5c85b5f + +x 10fddb7f48015b394512257da026938b67f65dd0a84dace51417d68da003a913 +y ebd6706b7cd2ee2d97848ee1adaa990d8ddbfad48e43f51d7ef843fa7597410c +m 0xffffffff +xx ebd6706b7cd2ee2d97848ee1adaa990d8ddbfad48e43f51d7ef843fa7597410c +yy 10fddb7f48015b394512257da026938b67f65dd0a84dace51417d68da003a913 + +x 1dd835e2173b936a91da37b3aa11e848e4497964a9a78ea929a19105eb981a24 +y 3e6f1ab7d5c460dfb7ad1926c60b64a8dd48ed0115b0655a6d8619666b8c8dde +m 0xffffffff +xx 516f1ab7d5c460dfb7ad1926c60b64a8dd48ed0115b0655a6d8619666b8c8d5e +yy 1dd835e2173b936a91da37b3aa11e848e4497964a9a78ea929a19105eb981a24 + +x c4541b1380e796a333d88affdccb4d2bc68bc5a1b3890ef2fc1a2c38dbcac725 +y 6f6338ad8dc0562bc02e307743b81013ffff6c135fdf8603f9956b7f94eb55fa +m 0xffffffff +xx 826338ad8dc0562bc02e307743b81013ffff6c135fdf8603f9956b7f94eb557a +yy c4541b1380e796a333d88affdccb4d2bc68bc5a1b3890ef2fc1a2c38dbcac725 + +x d71f16494f041d1547e5dd9ed539e6b9c1506cebb66f6424e6c7aaf6d0ace080 +y 78c1e6cc0b6f64e161def3b2ede7465f21f6afe61299e9a3c52b1a7a080b9b26 +m 0x00000000 +xx ea1f16494f041d1547e5dd9ed539e6b9c1506cebb66f6424e6c7aaf6d0ace000 +yy 78c1e6cc0b6f64e161def3b2ede7465f21f6afe61299e9a3c52b1a7a080b9b26 + +x 4d90838ab9cc0a79f4e2aa6a860bf8cfbce5f834aab428d4a06f8ef4a2da582a +y 53124b302e7675ea5784e2e7d9fdecb38d9c8be158312dd81c51757bafb79b42 +m 0x00000000 +xx 4d90838ab9cc0a79f4e2aa6a860bf8cfbce5f834aab428d4a06f8ef4a2da582a +yy 53124b302e7675ea5784e2e7d9fdecb38d9c8be158312dd81c51757bafb79b42 + +x c8e764092ea695b0dd8f0ecbca5a4e02096c821b0f5cd57de8e3e50d8b2a40db +y db7fb38dfede5259a584dbcc697f259ce380110636e301acb308bf687449110e +m 0x00000000 +xx dbe764092ea695b0dd8f0ecbca5a4e02096c821b0f5cd57de8e3e50d8b2a405b +yy db7fb38dfede5259a584dbcc697f259ce380110636e301acb308bf687449110e + +x 34cf8e55b3d2494362a87a24907fbdab61cb4f452ef5a889a1aa40a22be6d976 +y 679c6d6f6dca1b71bb098e3854c63ffb8ddb76f1a1cb246ce956fd71d6477c20 +m 0x00000000 +xx 34cf8e55b3d2494362a87a24907fbdab61cb4f452ef5a889a1aa40a22be6d976 +yy 679c6d6f6dca1b71bb098e3854c63ffb8ddb76f1a1cb246ce956fd71d6477c20 + +x 9638ab322ced065068f98597cc61fc2bd846b5849dc39a881209b8efcbc95eec +y 32922ff2b62e968417225b765f2787387c8a42fcab1dbec3815298f53813a8cd +m 0xffffffff +xx 45922ff2b62e968417225b765f2787387c8a42fcab1dbec3815298f53813a84d +yy a938ab322ced065068f98597cc61fc2bd846b5849dc39a881209b8efcbc95e6c + +###-------------------------------------------------------------------------- +test mulconst + +x 8d517a8804d934ae93388e1d59748c3c22866d7be6cec58a357ec43f6dd029db +a -319312 +z 3f2fea85c9195f2246f4f6fd2e8d5de95c5065edbea45a174bc0d1ef3db4aa54 + +x 1b5d6a6c9cdd0dabd126e5f5ee2513f3d27c56dd3aad89c882fe9fd2d38a93b9 +a 499342 +z dd310555966ebe7f409dcce2933f91af8e14c8909f78e4f113606789dd7f504b + +x 9e03b44e93743e0cf5768f65bd3c0f255e001de330d5e1a863d6e4dbb11748a9 +a -284189 +z 6e8c7f8d0f1476cf2603f5702fe8e8bba5c01e86b6e008ac72987fdd6721183c + +x 9cc65e302736aab9bf02dd451c216ac3dd2066af299d7f6bb361eb3b36777f74 +a -15738 +z 8c067e5dccdafaf56301050be17b8895c07e7f13572bbc5ce1af8b5be043d91b + +x 7f36ff91ed165c6ee44aca261dc09e3e124c2ed8167064c20d9b84fa226e2555 +a 423857 +z dc7415db1ab5e5a5658d089ced49bf97718bccc55e2f15b83a28157cbe47e559 + +x e8852c80db69c7e55d476ed00ca7c0735052f7f72f81198a57236feb89a5903c +a -140934 +z 4923ee40bb01314c2fe9f2f87d0743823311b2d9265219eb7a6de5fdfd09a308 + +x 505ef65d294b77e260757bc867199c4b0922b5022dfd6a1fe7478ea27ec102c5 +a -307893 +z b14d72c991a0bfc22b1b95934bbe589b6a4a1f9c76a89d7012f8cb03379a8844 + +x e410c260dc8c1838f3e9658ae586425039b373ee2ab88c750a51853b012af0af +a 471420 +z 42ae337a920ee1b83768cbf0750f524cf1f9e98b99f195e869785f90a2356756 + +x e2d181914b54175190462d11402717f42efa37967b2fe0bc4433fd4c862fd646 +a 492178 +z 4c6e1ba6896d2d661fbf99b77f63e3095d3341f04bf258dc3e4f51e39c68f576 + +x 9cdda0d7da106ef5cfb34774f48308b64953e92869dab0ba804927080509d8a2 +a -312149 +z 4e75e56793563268480efaf6232ad702bc5aef6246bd44e3499ff437810b523b + +x 9dac4442858b8dcc324464911e6f23ed046e42612e8105dc3aa2b9eccea15dc8 +a -88818 +z ce52a0897600a05383df0a0b99a451f0d5568146b4323392fc164153715ecb0a + +x c9f92ceffa7027ffa71e64b714c36b28a6a18c3608f8170d11d51acbee3c62ba +a -259755 +z 89582517069925572219b2eec2a25029e8e1c78772ca8c50bf23220d02740763 + +x 8f8bcf28f4920465680c8e15befba4ebd23c1e27b71c224c98461f69caf76eb1 +a -430350 +z e96b93f0aab6ca70f7d2c1121110efc320aff34e1ec693d7bf17bce1a756d622 + +x 6f4d413a27388fe84a2585e809927bd470ba1b0dc749ae6e2dfa100617a5a7db +a 11486 +z 1cf1f5bd0770d949ee36df858e5842805d121722de30d2ef6bc2b82d021fc14b + +x e1d05a072d1ab70d895969271f44b7c9d1654171836cf234724d2f90434c04e6 +a 8057 +z e32b3c792cd3b6a770eaa2627ff8de8895873d73d734b961646fbce0643a443d + +x d8564ee3ff02c80f0bf3e9cdfce42cd8ac1012ad8ea74f8c0f5754b5775a8de5 +a -304373 +z 884266ea43a6a9b72d113b437dae63c664ef53884c893212fd864412f4e5e457 + +x bf66769ee0cf873764524e760ee654e8d5090aa774f2e96144d945f8da37af19 +a -159091 +z d7438999b3bdb99a46e2f3dc8492cbaf52b0a19c651cc382c384940861bccb6b + +x 72b7d02b1fe23adea87696864c0a9f0466db85e39db397f0eb428a50e277aa2a +a -521654 +z a611bd153336e178a7f3d912adc2fb39b342132458faeedbdb0a35973efae23e + +x ff5c39d4b7fff86810a7a3b14a58bc01e6ecf062116adaa78dac0d1bd3f6039b +a -140759 +z eb9e32bf7d027cda198048da50aa79a11bc99f3b37a219a2104c78f4affb584f + +x a6f1f7f30e3f9e5467f180f92d2c94165fd9427d0c7d383b9077ca9a7e50dac5 +a -317637 +z 56a32847c50bc9609db9796e1650fbe97524aacea746d3cf285f0f2fced01a49 + +###-------------------------------------------------------------------------- +test mul + +## Easy multiplication. +x 0500000c00003800006000004000000009000006000048000090000040000000 +y 070000180000200000e00000800200000400000c000030000090000080020000 +z de200094610090df0020fe0180270700650d00dc2a00f84100e0340040570000 + +## Random tests. +x adcc6f10734dae2273304a6aa493ee8f96e05f2402341c0d997dce58ea57ff6f +y df3c8d5bb6380fa278d4ff2994c7865bcc146596d3c3126242f0dc3509b57449 +z 5ee2615b75a40367ced4ed4bf1578d13e7afa4d415f38f802b7e7b374365b627 + +x 054bc4d5e9b78b068fd20645eeb1f03aef2e89a1f56cb50e5f1170a86529526a +y f976ffa1d1b4a33d0fd866528897cea3eaffdc75e31aa65450a62ff765fe7985 +z 0210280745f6c29a04433f07f880bfd2eddd758d82996e79c65de817c30e7309 + +x e361c6fedbbe081b7cd683d23a2bf0ac889806be7230b56d9398959713a300ec +y c8121e53d78c2e9ba2ba7f51b7cb15cec970a63b4a642ac470aa1f2145f07bd0 +z b48bb1c7ddd26cd9e5a2cb73bb3885dbe4a47e03886d4dfd59e5729d544d566a + +x 463158a2077f931567d45e19deb4454a2ae77045db70a2c078e160ebdb74fd94 +y 3f311e3f8d225016448fbce3fbfbe84002736e3b0d5a90f57d705ede8706008f +z 44cd97e25c20ae2fe2ef4f2630981a1fe54c79ebd904bc40e39d9fa615ffa76c + +x 1c73fca52556e01204d4b957a01d1049f2247c8666d90c1d3703cff16a38c8bf +y e9afa0cc85577ec7eb1ac66d87260d5f3659936ff88cde8bd1c3fa1d499e8bcb +z 0979a8baf734c86a4f57ae400b7790c4985fba3088cb1b265dfc7a66c794121b + +x 6e2bab74e427b1a44f0cb181f9dedd6fed43cfd395d3708c4ae8fd2137215eb6 +y ef400834f2dad8763a1a5a58a37d1b36a78873860e4dac808d3166f13724942c +z 0d481adbce7bd82ebc5a3e5ed7a492e78a032ebf211a5bd2371c528c77954936 + +x cb3575b41d9521da5c85c6438af14903a8d6d9c3857aa8e101e5295fb277de7b +y 9f76715d2ae3c8ca182406553d3481fc36d67727ca2d51f5db37940aa3208d8d +z 0b2fa619265bd424b9e20d38bf4552ad63de8ab552166080d099edea5fbadf7f + +x abd66cf3b20dc4c5a866f1a3b965f794a726f96dd00f576d16ead66eea3a1177 +y 97f70fc92e0cda0e010f2a9d7608c33db954af18bc18ad55bf66e7d91ae31abd +z dcbb2cf34274971ef030827865b093a00761de3da90e46f00e18d0fd934a2b7f + +x 3b3c96ff9be8e17e0a0d3979ea5e5623fff5fa18914151abf79fe66639beef06 +y 1d29c361677805f1dd2b839e025e56208a10c0b8d9f2a8c490b0a892c0e27080 +z 0050873016bc67023d0c479fffa56a5a70512f9864d00b0a3e951f1e85c8b412 + +x b263d4a71b6d963e0a972819e5e5805b9522f142d3c0ff2738c51cce31e9f0d5 +y 64f3fbcff2195c297292df3e1cf900aae457e09864c5a6248ea21ef8efd557d9 +z 7e6f6f511cbf2743c0fc1c6431243908606cb257d20f8a8a0885e6ecd000e811 + +x 0df0497e1e01dbcc4a48d4865127d9cc31a9a0a56e90cc31619e65c1521b2369 +y 9277f0c6a5bcd7c7ed8dcf7182795f67a12e856b126d09966689834c43aada47 +z 798d270ae34aa2452694b4ff74049a6a5169d71c85bd1a9ac59625e9298cdf1b + +x 1dc64bef2189eb5349f5a8983c1854a40141a5390ea4bf8535a15aa71d0289b7 +y fb59dc9b08f9163881b10020ce040da296ed8c1a9a935c27ca0047a4d7f6342b +z 9fc23104cefd3014a469e6d3a0631338eaf91e24994ecd50bfc0b4547317317e + +x 975b108909e87803af98af9425d2a982865b6cc9c144985b32fe5bb842702e24 +y a69e9130dc40be50e827dc50dac05bf900946cf67ec35f1bb1705001314e4fcb +z 12d042e50d0cff7b43a5ede61ce827a99619bf84995d488fe9eb56a8de769164 + +x 39c0db5a4b161c368b0f71c7e8ef97dddc444e4a33181e0743519f2a879ae04f +y d3cc45ff509ed45998bd5f218408ad51f7457b35e8ad69d5431f174047d7c6e5 +z 96b877604f52782ff2a5b1a12d7db642371ca993b648c4971cbf593213503219 + +x f8c6715e4a327cbbdbb08d74121619abc73dc421d7267029e39b50c1510d2045 +y 63870a83cad4c1c64195ae7b92f3b19c830f35f1a3186815565d846c787c7ffc +z 286a0b8c6681a7b79a5f85426fb60819b7bd349e93c1e11943c41c8dfd57d00f + +x 49c9bcaf5434b8205a348df290a96da27df084f34047efbf91cf544057a50bde +y 54269f8b23c05b94c9c1cd74eae88d9227af12a6fb337548eb93c2a88a75a8a5 +z 1e3dcab5d7361f00e70198b52e8fb6d1fba74abd79d99480527f6711b21b833b + +x c7212b43ff0d10fc52d3a2a7e15bb9cf53856f7ce33b79df89e1d13f95a94511 +y 5213ec20bd054491a5485f665075835da609ad4f3dc005744f061480862ee602 +z e136339fa01067c6c0823a7ebe2f84d917600e244a9883191900bb95a3b59764 + +x a15d62c6308448f1f70602f43be1825696d228eb170bed55322a21d2b1afa915 +y 58afe65bc8adbe22807026aa1b0d68af330bca268fdc054406aa41c820960e71 +z 996c597e0a024c2ff0ffe289d8c7270e4ea1d38e294d7210eddeb2c0725a1305 + +x ea233ae033ca93034bc8fd8ea3c0625bbb15b00265264fdd61f62cc808b505fe +y 09e12ef9b3426991f7119c2e8349278342ed0072317c4ec7ab24561b61396b39 +z 1fd72191fe9f00b0cca6a635d14904bd0c1e0ccd1275e84ad0b7bde134866e2a + +x fe1fd3da05524af4ccd538f1d2ede09582101fc2a47c2e63758a546bed6cc5ec +y 523346406ef3df6ac9a455d0d2e7f732ad01c88245b07a888cc21c40fce11a76 +z de6cac8fdc878d9c4eda6b78f8b629ecf776980e49fed56bab936fc03924f44e + +###-------------------------------------------------------------------------- +test sqr + +x 4dc87ad85abe8938634492ce2ea10bf48dc4aa2fa37a6a0fde3e5a01e90dde2b +z 346297c756d77b8ea312ddc455223f4577aea2a2e8d944cb24adb487de143b46 + +x a33aed91165d7fd13a543760d3915c1b5d411a21895cde81b2f3640b87550cc9 +z f923e49da9d5f45e23a782f911fac1a6c2e67cbbc7b03ee4675a0c5fbec03641 + +x a1406e453db6c92ef808295d1919c5bb2491c0ce6d5326d276c57e57943e0acc +z 18425bbd92149991c4545e65495af0e6372289e9a32649c127122243204bdd73 + +x 70a56b8484234ed002a68c8d535a4e527a61c360f7d4ee5b4970c8ace1e12de0 +z bed1c435139f151d0650577e03c32428f63cdb7bc1920110b5fdbb27f08cb200 + +x 86c3236a6194f1585b4dbeb09d0247fb7d3ae08063ccf9fc4fde70fc23735710 +z 9b6509acadd5d31c4c843e91cec78be00aec4fdf7d86132965bd6f62f078f711 + +x 0e5e83c51a8c091673425c38785e0aa1d74c7261a035a891bf734cca8c8a3db3 +z 4efe5029e99438835a8a45d0180b8de357eac82ba9dd8e127baac0d758dfca1d + +x 31c39a5afc33f8a8d3c570b9dc5389bea6fdaaeeb44cd7524f6c445b9583a34c +z 359b7c8791cc87aa8b3c799c9d4d7e1f4062a4f64436d8c01071597e8c262127 + +x 5a06203c15d6c1db6ea0fcf468a1e3f09d68c4a0f64c3d7e30e70290545e708e +z 07f8b435ea322bedf613458b1eb420f1d6bc96741d69695899bd40f7eca6f72a + +x b1973433646474167b791b326827641260fb33d6a2c96d4e963a6b091f824505 +z 52a62396dbbceead62912f8adfed2707fc25edb51aac19b2a274c246f1209f26 + +x 96b157d71e107168fac206dd63007f10f4ae1225b0761c470ee18ecdb4fff20b +z 84ba2a84b156437cdcc39ecc8b1ad01bba934d8dfb7d504b9f2442db0ad01167 + +x 6167d77675e19785960c28df551b458e41dfd0dfe5e56e785b7367997d5eb0a6 +z 79a558436af4310d3eaee93f9a7cab72bd817fdf59d267e2c530ba8d667a005c + +x fb4b2ab08db932ce10dd62639aabbb266f9ce775fb5a5e0875864f18a3ee506c +z a6013661f2f0ab875739836039bff6bff4c993aefdda43dccecf4c404b9a612a + +x ea26bcf0bfc3e15d4df7ddbcac8b5b9e9a7215d74196d77c9e0524e861c6aeb4 +z 113e06861e3d338618695f4713464cea536c8019da77ff0dd9946f3b860df062 + +x b67b1ffffec757ef147e86cf60898c5dac515f080f43f4e120017caab4eee5ee +z 7d9748a1ff6ca9cdebeb3dd6668522767afb9ebf1c680fe7fb3f5848f7222036 + +x c122016f17f12e53f9ac031719fe428c826217b2b757ae44f2f33d1b8b1bb553 +z dc068d032b97c98eea6dd6c8bc42e9a0a6250c81a36a8f64615489e191287c72 + +x 1266ff0654c08e6183cd6c3cc760cc5c88d1f49b918f2f8f587b3edd4adea513 +z f07f17fadb2e2dbd282d296fe5a15cc5c2baf6b45f5fd5dc4692f252039bc862 + +x 4c4dd9c6e46fb2c096388583f2a0c969245452b23f16ea43e15064c45357ccef +z 5127fd4415a84115997b8b3ebe88a590efde9f8b53a43e86b1a4d60782c91025 + +x 095d149c2616212e5f770f133e719d285a8bc888414271296684e732feb5473f +z d8038bee551cac14d1c610bbc0960d943b01526072c589bc913ab51fd47bc848 + +x ad55f9f916d62bb13ceb1461b99e82d76b860c084ca408dd4a18f154b907754a +z e5c86ee6350c9ab736229f3f53e2ab852641bb8a62fdda609444df377e9ca04a + +x 2e4976f45acc671e38add93aa6a89669cdc9874975879b3134dd37c633c9eb14 +z c6513f1a11346d33b05ad65eca13f11125cf70bdcdd6e666a8a7b9c5b6098429 + +###-------------------------------------------------------------------------- +test inv + +x 344ff33a2bc801f861bd13575797da35352c8164808d27f51ea7ca46931b2b1f +z 07f678dfeef071b038d692bf825cb4e75bc1934bd3a6e3dfea99e78bdaeecf3a + +x 670097e2fbbecf6516e949d98f6d722d3f732c33bfb4e62512f9d28d94546b64 +z b2f5cbcd7d8c996ed33a813b1aa39c36f5826b436867bd89b4ce43a156c1e96b + +x 234f3bd8760cdc8ae7fac9457da418cd082e42906ffe59a13e52185a7845e61c +z 7488ff9231e4819684148e16ebc25440732ffe7d211eb3d3263db1af9f1d0513 + +x 22a39a35b1cabc6dfecd1b898593070f0c81bbd04b4b20f43a9c7c14b5dfe967 +z 892024fdbc8937b9b3aef794f57b8ed8517510b6de3f6088987b1310c1dc7932 + +x d850c118c69198268826d05650958c6bed55b181090cf1c96493ecc4635a913f +z 7aeae1b0dc5211f374872e78da8f225325f3f33f9c42bfdeff25d425dff7710f + +x 33ccdc0e39f7cd0a61782c87ac089eb7bbcabce4dd222f05088d3d6332efe959 +z 668f87e23239e965c80740d4daa9c913609388f291c11f950684f45e689a061d + +x 7c06f93b2f66001c74073b8ba7536049738e89b0a0d859a8a73710de3fadcf79 +z 52df0aa24bb4a7474e6ed9852ba542c1f4c5219372a7b5d60988890e2955491e + +x 9a0ce9ff4026bd58abcf8a128dbc55a19c446005834a143634452821d5f9f0ee +z 79eaa93b6287705c0ba564c31bab1854c7f4354845be065c4bf94d38a7a8b421 + +x a13a127490bd3443fdba99baf61d113f3aadd6966c9732cd16348f9fbed32e0e +z 67290b25e6bd7328dd804309a6203c02a75657f593c7e66e48c9192524e5b87b + +x 35f7ac3eaa36c4ed338388fe7eda61cf237eff6ddc0847cb0c95255bbaef8ddc +z 4950601d2cfe75eb9c4524e2f40f404fe82d0014c916dc43d9416cd2e274992d + +x 8a058593035986da3a19e63dacaf40fb3db4cf382205fc4e4802e0ff0c61c8d6 +z 6a23b743dc2fa4a4132780cf6edfed4c219760f3b31343b08710ea18d2c0fc43 + +x a10d03234e700ec92270b6105fdb787d8edd3f960fdd78ea2e169f49dc708d45 +z 101dad1720604d0b093831baaa97fd0701ce773b9c1be1db0403533ad4376c0a + +x 52d3b9e030a5ed574f7f9489c47e73f78ef88a39b570045f9ef73c9a3e65f425 +z 83da3e088dbc9a3cbe06496c5a52edc8d7abcbb8a0f839361762137b119d961a + +x 9928b5f14ec80a036479d7b08c128e601db880daebef36adde6fbd1f50f82629 +z 8dcaa9a2439b77cbe44928ac2877e09755c505f58df4d0ffb9b23fc256b12779 + +x 5a956523956f8ace6166ea6cb3c7421f8d1142d26084a81d615f00d578e03448 +z 658a3ee24ec5b5f1d2d12614e535247c9f2f259131b00f654e09b4517c63ea09 + +x 157492cd38a07802351ca0d1a5615d5c5f254692acce930fb6be351e9a52f088 +z 32fec1eab85ddf8d27a437876e7f5a07f012b02e7971869811c3c31230204164 + +x 2d07c109c332847567621ef4338e149b99c5bc3bf6e50943695da7fed5d8141e +z a81472d28a8235bff43ad5cc012d52e95ece3dbc5ba2962dc54cf9e7f81bee04 + +x 7e172f6c03415e83d4671e0191151d49e5257651ba73848254e68fad0a095c50 +z 1a8efdc57ae9d39ffa64afbc5d2dc1f25a29d365ac3dee0d8529977c14aa4415 + +x 1934546e37b0bac80319fa7f2f86c18e83de8da830b9d0b5019c26768974eda4 +z ffe55479771f20518d8fc6491055368b5dcce9b4e193d19897f1e116b9cdf946 + +x 90324ccfe0e34e9b08db1862be3bc17798a8581ee097be76545e3bf9d586a2e6 +z 0f5ccf4920d617c9b4f7fe6e2c9e95e89b5516555d5e3f5f9900485451d7425f + +###-------------------------------------------------------------------------- +test quosqrt + +x 18798551568191dbfe6bcacf95bf4bf00290de4c773a1d4233d1eae272b3085b +y 2ee52110807ab6e31e0ed7b4de818d6474b514c63c99206e58a6df38e149123f +z0 3819accb91d97a3f4dbca732f19723fc772a19b3eb4d307acad706cc7c7e1c1f +z1 b5e653346e2685c0b24358cd0e68dc0388d5e64c14b2cf853528f9338381e360 + +x 8671a0ecb7344f2e44fc9066aeb42661e848417e8c51b353680573830857d90f +y 9c4cfb1aa650924ceaf3e23b260d02b7d8b7dd4445360cad0bd4270428f55292 +z0 +z1 + +x bb0d27e1743f444e2f612c2ff575c6c6663f01869eaa8666774b8baa59b2a714 +y 2fecb156c393d27d7b9a5e4cc2b57cb5524d5b945e92c5b4bdccdd6d00e684c6 +z0 +z1 + +x 59af963f7245901807a46a59d4e49bab5b1fdf3001f63ef4e600ef8150d0e13a +y b5ac3372ca5435577c416ba46a57879b0ca1df29057c540cac4edacc507b5e23 +z0 +z1 + +x a7b8659775a53e1fa315066be6a37a3f645d782cb69ec6b4f27fcf4daed3d82e +y 4550c4697a5d29d1a97b50ea65e98ec839567a3fc556ec3790b016c24b867d89 +z0 a190875f536f94ae2af8aae90bf0afabed437b36cf640d85529b150155eed53e +z1 4c6f78a0ac906b51d5075516f40f505412bc84c9309bf27aad64eafeaa112a41 + +x 7163512100699c32d5fadbe3583f2f6f314c347f1e66c434b15ac06a5733f3ed +y 2806d76598a43c24820daaf87afa5a9a4d414e5d8f51993f1b01166bb5479c27 +z0 01d5d023a6c5f7ec1d5df3179bb240e3003a9e3be8ad4e154c6e8f7cb7af6536 +z1 ec2a2fdc593a0813e2a20ce8644dbf1cffc561c41752b1eab391708348509a49 + +x e950533666a4a1edc3dae30637d6b005e34b614fe75555be0e1759def06a2aee +y ac5a603347a585ca19eba141b1dd1b8833855e9807776627e8c9f92001a4b9b0 +z0 +z1 + +x d3c5ccb02442548901b3ffa2ed5564735b0b041386fd38e6c40844dc9183006e +y 5e6f23ccef94660e569bc42093d2b862ca605b81d64bb3589331d015082b4996 +z0 d7d578a72f1ea2dcacd0a96be285e9635230dc297fa7f6e1f2b9754e2d29190c +z1 162a8758d0e15d23532f56941d7a169cadcf23d68058091e0d468ab1d2d6e673 + +x 37cad075017c111f99135be6a0f553535d56153cef8839eee1e70614d65df1c2 +y e5f9944a377be3ab64daccfc9e711f4aa522c68a80efd0a70c72cdd4507014b7 +z0 +z1 + +x 85dedba748f478537d016f20b9871e830e513514fbd27141aa54ca77b2a673be +y 950bc6fb51f6d8c36b7ddc8cb28d9efd498690a46c57888b279de0e549e84c52 +z0 fb7871031556b171a25dfd0483f0e2ed8d24a8acc2d9fc201f42f0b892fd541a +z1 f2868efceaa94e8e5da202fb7c0f1d1272db57533d2603dfe0bd0f476d02ab65 + +x d70f399a983c6ad48acca796d9106c5e7681f34bdf34248f6dc54620282bb327 +y cad23bcd1fb96331bc8139f2a8f21d24492e56a7b80e343a7002acc96a739454 +z0 ff70c5bffe08911fb5522b21beecfd80fb018f0afef24fe85cfb7e4a5024960a +z1 ee8e3a4001f76ee04aadd4de4113027f04fe70f5010db017a30481b5afdb6975 + +x 71ee96ced0b50bc560f2477a88ea2447573490f71850f084ae0b318cafd8a75f +y 15c61eefd2c05d72fb07e44a006dfe314d8797f978bab1fe9f9276bcc82b542a +z0 +z1 + +x c27a9f169b8096308f313ab5a521886084f03ec6d9e8b30e4773d0a3ab1a7c67 +y a7ca0e7fc5566dfc3790a3de164ef26d6452715db428994d438e79f65034d174 +z0 129427bd4c2195fac5a0da4c52ff634c697f18c3b02d0e7aad45a64d03b6e922 +z1 db6bd842b3de6a053a5f25b3ad009cb39680e73c4fd2f18552ba59b2fc49165d + +x dd73476aeab865af0775723ebd2128ca71621b1d95231813c3d3cb32b805f418 +y dc6621f2ba82deb8272243baa5d2e177a60b1b780daa3ba081040e05b1d1b2f9 +z0 32ae54f7a7dfa101bad00f723898d29a7307454f86cd1197c44b07d1b997fa1f +z1 bb51ab0858205efe452ff08dc7672d658cf8bab07932ee683bb4f82e46680560 + +x 3a3ee482bf7075fa38780616603133ecea7b56acab59d96ebf7192e21c49a806 +y b7e6d647792961137dadce55ce69634379338bbda45fbef9d56be52620738d06 +z0 122b696683c2d1f3feedaf6166037ddbd7281e0c4c875724177f240b54e0dc22 +z1 dbd496997c3d2e0c0112509e99fc822428d7e1f3b378a8dbe880dbf4ab1f235d + +x 71f31797a8a36123e4a0b173ee4bc5a04d7799d1eba246df51cf943aeba0270c +y 7340069440d6c72b4536018eec373f50a1142c9e79de8a5396f994e53c64ab18 +z0 +z1 + +x 0d2a6a9de4d52289cc724840670abcc5a4ee04f1197bd1d230689431b01afce0 +y 21457f6784da81822df90f09b44782bd50a12c4fb378091cd33b177c734e0728 +z0 2b272304b3cca59e26431d91118a95c965bd542191c7cef760b085673e96a432 +z1 c2d8dcfb4c335a61d9bce26eee756a369a42abde6e3831089f4f7a98c1695b4d + +x 288b09090258a71747c1a08a51b0894a0c096f5b88ee38ea56a3aaefc1afa0f5 +y a7f6391e06b8972b18e899753bf3853270cae7971774041fa9bf09a55349f950 +z0 +z1 + +x e912e39e2199c3980c5fe3cac6d8bed394367f28213524f006a9b2c0cce4a6dc +y e6b4a592e37fb5d3af73c486cc211a57d4077c093a161276dcb6eb44303d3ec6 +z0 +z1 + +x ec6785be59b890e07176c09195430b7f5daee0b0898ee744e578ac25873012b6 +y b3cd2df2c2531beeca882607d73f38403d8ff384f99be1ce582536bc3d4bfcd1 +z0 +z1 + +###-------------------------------------------------------------------------- +test sub-mulc-add-sub-mul + +## A very basic smoke-test. +u 03 +v 01 +a 5 +w 01 +x 07 +y 02 +z 37 + +## Stress the bounds. +u 000000feffff030000f0ffffdfffff7f000000ffffff03000008ffff1f000040 +v 00 +a 0xfffff +w 000000feffff030000f0ffffdfffff7f000000ffffff03000008ffff1f000040 +x 000000feffff030000f0ffffdfffff7f000000ffffff03000008ffff1f000040 +y 00 +z 00000cf2ffdf4400a09a000079fdffea040098edffa73b024072ffbfe0feff65 + +## Random tests. +u 6f0dc2547ad77f7b3da324876e63c724c1f69cb2bc70ff960f1594f90202e17f +v 23a2d45c26880166516e6831ab5070dd2247992418ad7cc41155a9362744f763 +a 4783 +w e145b5f91b683918d1efe6193de27909bf9051b0157acfa458bc3f63e5272de5 +x e694fc475a442bd72cbbf11206474e3169fa74ad453aec3034c1dcc1f1dfbce0 +y f9b4f1ac9369241a302f874305cd2d2fba362b5735d36d3e072c7198d7dd4005 +z 08518c9f52236272202869bf7cb549c667f6a27d1c4f18ab58605d63821a6c61 + +u f1b3d663fb9458ba8e4521e8e2c976fafc8936433b62e316c6dcff794b1ac8d0 +v 2185dd6948ef2339c9a43518dd02eac6518852d1c35858dbdf5c1acf1d995884 +a -128133 +w d7a628aa59d409b755a1ff0d76f37ae8e4a73d47375940c61351074f3c42ad2a +x 4a353e9e7e9a0700ab2c043cc05f9795cc267e001b64799ca1849f024a42dfd7 +y dbef6513fba5ca19c545b162718eeba960b0930b8ce99c3edac5facf5fddf4f2 +z 9dbfe69897a273171ab4a697f88a0d4b420a3ada7a7f9e67d0ba871e2097026d + +u e8624dbe04a1b19102019d7fd9e06fe502764afb92330d03693279e872e84f81 +v 8da8b04024ff708a8b5fa31a6a654fc31d3748f74a897898aa42c2bb65494586 +a -118148 +w 83f63df59ce4b3161427b932ecbd7796bd162b553b70bbfef8a990ba6f20c23e +x 9d896d69ec478456fb6cad67774c6e3e0e313aadc0564d759380981fb12dc3b8 +y 0e8799aa8de1b1ac4aeae4d1e8cd5936c66b8a0a60c8d17ec23bc9c9f94421ea +z 2221a87687c127b352e077bf7e975c83c667c8ce603e9d9fa5e02b195c7ad873 + +u 2527a8ab98898038e9e132a1bc8349a33e2c2f6ec8b6c15b06410177297d30fb +v 71cdbe058a0357295dd5134fb95a630055f39d9bd8fa0c759b1b70fbef6147d0 +a -14780 +w 0fe111e19ddf5d11d40b584a31888aea4a388540b86d14b962a1a7135114d5b3 +x a6386eeff2764007a570ba7e82a214667c2949a793fa0a52b7665c09285c6661 +y a7557aaa000c8840e08163b7eec08bf24ba275a35d85bfd7813aaafcc22715c8 +z 867491333fc048b229ddb4740b1fe6dca1feebf1d40660814feeb1fce97fca12 + +u fe07ffcd6b14f75efd74ff983e8e5c20f379b0c78907f0e453753b457fb53159 +v 617f2f7c1153eaea3ccae7dfb07fbe804b2cb5c8205d657c3106b5a60100cafc +a -128312 +w a0af624a3f54278e2f7cc77f5d0f10750179bb18e07da059feb0bc98fb1d688f +x ce432859e6d7e691ba9b44d467e8a5f1a97979facd2d3c7deec46e121193133b +y d60050fad0f5c4b2e042141e4f7a418d3e8a8a308acc96651728f363ee793628 +z b9e4e8873e006d41104b1cd6a32282fa2b94ade000dd57dee6dd506cceb34c34 + +u b46e84be433f9e4f43ffa2f1f5200013953d820d292e3af978c54401a252111c +v cb7cec0c48efa4e0e54f05ac18574d5f67bf1a1193d6d58f42183abc9f5bdd49 +a -3288 +w 18603c0562c4d893a699fa6258e2de57e1cafd3e8ad756806d09db0c1ac9f86c +x 0854368c6b459ba6fcaa95db92605c9d791bf4dcc57bfda2ef318b48f7521d73 +y 0c83d0b2d331ccc62bbcd2d2771b18bc0b909a3bbebcdcb99020952672f050d4 +z d54073b190601f1cc36c25109a5b44f04b6c2240c268bc71cb983d3dfb25cd64 + +u 1f490365c3b82416fd3866a42a03f3bd643844e0d0cbebb66af54aa35de3efa4 +v dc805758c7e714a2acbc1e467520ecc3b9d23ce5133fe79e377e6d4520cd5196 +a -129141 +w 1a53a3728ef3587085d0b530be8ae95e367927f9ac3b7126445d32b46f3abfad +x 0af6ce5107ca06fdfe732d11161b197830a963ec667065c5293bbdf843e23672 +y 5bbfb655a175dcf7a4f4fc886a03e3d99cddbd34524c3cd2fb13b793bb2132be +z 7e5576020e7bac35c7f5b3dc6b60b2c1cca55f6c98141682efb4737963d0307e + +u 09e03f5d67a92cf076740e4261833f244b60da6d02cb42278e2ed9183b6eba3a +v 5a8b665434e91158559cfecf1d43d562c307518a3ce889165b406b1aae38a674 +a -13299 +w 16e0d405bc40f2075f5dd901769def19f15759faef9a5fb6356b94c5c48be3e0 +x 101da726c0dfd102c8eb2178640054248225a6fcfac1bab28a09b59cf38703d6 +y f268d102402d31a33e52a941a06c64a30a721ed55184edfcfcd85db6fe3db676 +z 24fc9112ce6d3d70e8c245f9e2c883290384462065a5a1ab5821b9cf9d61953b + +u f86ba345a367c676d99450d4893ef4033201c8ddbb631c4658e4ed24ece98749 +v a3c51a17107327742f44cc2e265482522cf39b6bcbff919bcf99fc033d76348f +a -88039 +w 5dcbe0be5f9f80b46d2e651504b10a3e481257a4bfacf40d8ccacea9d73dc2ea +x 2ac88350fbffcbc743d36fe45c80a70a8cbe88be36759943c8e124163e432dec +y f54685e704df0e499e495b3b77e64aa0ec0c9fc0bb18ed456a412ac6079fe9d2 +z 3e7c00ea9ee49825f5fbb9b704dc720b062d8e08ee8dd410f3d34d255602b56b + +u 1cd810875f48ef4c71ecb0997acfa31249ebcc9280e7c2f741038a0529f653d3 +v ba2e564cae8cdc2bea40d64b5598493ac2b11902d91b5aec7a0e4a8649aa7ab2 +a -77488 +w ca4929fb0fed99fd9dca7a21275dbd97185900d4eb362eb09bcb5ce7098aaaa2 +x 89b395b440fab27d3b32e0740caac3ce38affbd80b2f8f7b6709294d6770873e +y d2cd5ac1ea7b0e1f45bd3cc64b651518dcdf9f25078de7cc4970bf54976a0c8d +z 06ea5e15853bb29db5cfccd62db2e64067c90a97eab43039cacf4ee639ffe979 + +u 9960c3131e513fba3241b1f9bdf44fdbe06c43d9cda9e05fdb451eda3e8df394 +v 4c5f72392dddd1b8e84db5bfc2db04985fe3d1226a470c851a489f98d954e6ec +a -33449 +w 04eacb794c87c19087b793a0e2d187cc7e0b07d265fd6cc46946780d2ab83810 +x 414db559bd22f12717b431310c1063534de5e627e983f4967b2fb38f2c5f87b0 +y 599bee129778596ba77c27a896020fa55123b8635ff3d9efd56fe406de878146 +z 26c7d591e0028dd611d6e84969da716eb740207e49f5ea02f17a3224612def12 + +u 2cfc4c9cb8ca259bd4ffcbbd498510f8a65cca584303a28ed475584bd1eed111 +v 3223cab1344be86c0af9995a769276cddbf70eaf55caee24dd4ec0d06c2f4309 +a -53728 +w 3a48f8bd8a229fa9f5b9d7c4135ef6c3a251b0ce451f482471f017e963839405 +x bec0e71a657e85e024d91c41b3a2f75f478528d8ae1afb70bdc5da255d20de06 +y 53dc48614937bd5ea1bce51b166bc9947e248a98cd0fac55f632cded216e9cfd +z 2999f607e716f0c769e9fdeff636568674f3601166d6b7f566a369b5d4e2797a + +u c37946f39bde051e4a6f91a18fda21ec2bfcc375b703bbb81fdcc7ff15cfedf4 +v f37e2f1bb6b71763263e742cfd1ce8a9e004a5e06faf0afc52cf49ea89ad9244 +a -69223 +w 0592777a8c77c1713a72b2ce18fa318fa93e9c6e6b870e54723a43408b502b74 +x cf575224b26f636b4b4f28c90995b87d900f6ca5ec9de6c24e65b747d303d221 +y 8ab7d691dd76d7cd63d3456c677987a9e53904a4895f053e3de08786d564c837 +z 1d667ed7c9b93f2972de23f4d633bcb5f2e56e446cba103c3cf2cf0931687b13 + +u 2afb15ae6438b8eef9d07f2491e43e32a2b9287381c7bf036dce2a1b0a3542e5 +v 18c9bb7c91d5e5ed96e6effc6609fe40e72c5634cac2cf6fb55b083c3339f40a +a -33255 +w c0c870e0ee2116aa1182b2b4ee4bfde446f721fa6f1bba3a2ed4fb703855c673 +x 91fd148ae6d53a419983999020d845503cc923e012e6869201615fbb8e460360 +y 5d02294b16e04ca4a7fa4fa5dc9f12c7156e2a68c02495ea171a8cf13d35af99 +z f1f90c61c85c137e2e9d5ca7a6b388afd954f6c93548e5fc3b82e02fe875923e + +u a7a7193315006fd85c97226f44708d61ecddad2e184d69b0db62f9fb2bc678bb +v 87a64ef3c67f464441927c08fd1b57d17bd644a422b96f151aa2d7920989e4ac +a 67151 +w 6b31a270025004a878f214f100a764165033e170ea5e4c52832673cf88f9f0b3 +x 0c0af67c56e0b2336ba06f447ea4f9cbf052147e35f16216b306ef1211ce4142 +y 54fec5270095dfc21f44805ba17565386bc50d45bd1f797ebfa04da5040ad08c +z 92fdbcabd91ab43baa827594672dede4f0c71d8302b4cc8cd79270aa0c96d915 + +u 5d72825031c526d9e1efe34fcbbbd81b91460112f9f950e78e12c777a2994a59 +v 4334ab5246765e241435c6faac0a00add3a5adcdafe017121d03b9561d0d3516 +a -66199 +w ef3211bb4e1bac43430e48594577d1d271f76b46ea7e44542c23524b3d6236bc +x 1bfb4fb8d8429f0dd7a6cbc23dc2357ce9c1c72be3acf0a49abc331ac751e68a +y 7cf2ea00463d76152e230cb5465ab55d30f09afbd007d2b55393cfe8e348cf9a +z c0a66f24e5800bec2b9ff65207afd4b29326525b910381d233bd91d51530d046 + +u 01a66900161a4ad98f028a8da8f10142b4855712a7eb8ffbd699b13b7cc1a471 +v c6f8a0b42c3f2a1109201c7a97e3307f6cb56a1a27f13e4567456d9eac2a2f4e +a -71473 +w e2eef0e19682ebb44cfdf84c71cb556311432fd948951a661d4240e16bc68d1c +x f69b44aaff31db04fa4e8f14f51051d353e50110b1562b27d4493ac5e44a5b07 +y 29039f65da48a24be024cf8f1af95ea9b09a08a54eec810e97018add81eec1df +z a827fcc698403d01f8c2597a582ac8ddd612e5c2a520b0a2428e8dd35c58002d + +u bc607923665e36ea0f8206b358fb3a327ef9a70ddcadb2edc49660891e932726 +v 33e905cd1b262eba320c61428704c1d7c354361043ea7233c69f1f691f7c7175 +a -101999 +w e1b804b366c155d0f1a09fdbede434c669bf7f188daa96b8542dcbc9bbe66b6b +x 413d410937fbf0575bf34c0b70ee6cd5737e17b6058e774f889104b2f6cacc7b +y 0784aeb89be679694477cf399b605473c2c48887b687a980d7d333632e060e6c +z 16edc745e1596492fadffd303c31ce5827c3971c591c68f9e2b4f62c967aaa6f + +u 904e1b99ee3f860409a2db3aa4e539b2b50cebc57359f23fca21b5bb1306dc50 +v 133d76a1f768d77a6801d73a570b35f6dbbd98aabfa4258445684143cd30a39f +a -50858 +w 547270fdf41f753a4189d2a9630ab17b4c6034829770a40fd8346e75e92610cf +x 076c4e34375857b9e6289287e03c744fd60d76c377a772f6edef3ad30e4afafb +y f2e8a830fe203901f5f34ae6e606aa8f6cffb504b166cba4cdd84d011b783b90 +z 659233daf8ebd47c77b9d46ac65237e1bfdeebbcc552c7db5cf8dd2d4bd1aa2d + +u a6f4bce9adbe5a68585c205d20b05c6662748f5f1dd2458defbc126792837a63 +v 8f1110929626587241fd403c8332b2ebbc398d4dd7042b993fc24a18b53e3847 +a 81985 +w 012aaf1e00a521e8e0639ed116e15476f0f8f1c6dff47d860ed60e0bb7c156f7 +x 13aaf4f9f20d64110beef21bde5c7262c4bff80a85a08db1e098d45ec3d69457 +y eb3230fdacce04518359bfa7cff0c9d6d015966545e40e1c1da18b760031b2aa +z 607f7b77fc8d3ca15cdf6e2abba71853fa74739f83589a4458854ae2db0a4727 diff --git a/f25519.c b/f25519.c new file mode 100644 index 0000000..d16943c --- /dev/null +++ b/f25519.c @@ -0,0 +1,876 @@ +/* -*-c-*- + * + * Arithmetic modulo 2^255 - 19 + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "f25519.h" + +/*----- Basic setup -------------------------------------------------------*/ + +/* Elements x of GF(2^255 - 19) are represented by ten signed integers x_i: x + * = SUM_{0<=i<10} x_i 2^ceil(51i/2), mostly following Bernstein's original + * paper. + */ + +typedef int32 piece; typedef int64 dblpiece; +typedef uint32 upiece; typedef uint64 udblpiece; +#define P p26 +#define PIECEWD(i) ((i)%2 ? 25 : 26) +#define NPIECE 10 + +#define M26 0x03ffffffu +#define M25 0x01ffffffu +#define B26 0x04000000u +#define B25 0x02000000u +#define B24 0x01000000u + +#define PIECES(v) v##0, v##1, v##2, v##3, v##4, v##5, v##6, v##7, v##8, v##9 +#define FETCH(v, w) do { \ + v##0 = (w)->P[0]; v##1 = (w)->P[1]; \ + v##2 = (w)->P[2]; v##3 = (w)->P[3]; \ + v##4 = (w)->P[4]; v##5 = (w)->P[5]; \ + v##6 = (w)->P[6]; v##7 = (w)->P[7]; \ + v##8 = (w)->P[8]; v##9 = (w)->P[9]; \ +} while (0) +#define STASH(w, v) do { \ + (w)->P[0] = v##0; (w)->P[1] = v##1; \ + (w)->P[2] = v##2; (w)->P[3] = v##3; \ + (w)->P[4] = v##4; (w)->P[5] = v##5; \ + (w)->P[6] = v##6; (w)->P[7] = v##7; \ + (w)->P[8] = v##8; (w)->P[9] = v##9; \ +} while (0) + +/*----- Debugging machinery -----------------------------------------------*/ + +#if defined(F25519_DEBUG) + +#include + +#include "mp.h" +#include "mptext.h" + +static mp *get_2p255m91(void) +{ + mpw w19 = 19; + mp *p = MP_NEW, m19; + + p = mp_setbit(p, MP_ZERO, 255); + mp_build(&m19, &w19, &w19 + 1); + p = mp_sub(p, p, &m19); + return (p); +} + +DEF_FDUMP(fdump, piece, PIECEWD, NPIECE, 32, get_2p255m91()) + +#endif + +/*----- Loading and storing -----------------------------------------------*/ + +/* --- @f25519_load@ --- * + * + * Arguments: @f25519 *z@ = where to store the result + * @const octet xv[32]@ = source to read + * + * Returns: --- + * + * Use: Reads an element of %$\gf{2^{255} - 19}$% in external + * representation from @xv@ and stores it in @z@. + * + * External representation is little-endian base-256. Some + * elements have multiple encodings, which are not produced by + * correct software; use of noncanonical encodings is not an + * error, and toleration of them is considered a performance + * feature. + */ + +void f25519_load(f25519 *z, const octet xv[32]) +{ + + uint32 xw0 = LOAD32_L(xv + 0), xw1 = LOAD32_L(xv + 4), + xw2 = LOAD32_L(xv + 8), xw3 = LOAD32_L(xv + 12), + xw4 = LOAD32_L(xv + 16), xw5 = LOAD32_L(xv + 20), + xw6 = LOAD32_L(xv + 24), xw7 = LOAD32_L(xv + 28); + piece PIECES(x), b, c; + + /* First, split the 32-bit words into the irregularly-sized pieces we need + * for the field representation. These pieces are all positive. We'll do + * the sign correction afterwards. + * + * It may be that the top bit of the input is set. Avoid trouble by + * folding that back round into the bottom piece of the representation. + * + * Here, we briefly have 0 <= x_0 < 2^26 + 19, but will resolve this later. + * Otherwise, we have 0 <= x_{2i} < 2^26, and 0 <= x_{2i+1} < 2^25. + */ + x0 = ((xw0 << 0)&0x03ffffff) + 19*((xw7 >> 31)&0x00000001); + x1 = ((xw1 << 6)&0x01ffffc0) | ((xw0 >> 26)&0x0000003f); + x2 = ((xw2 << 13)&0x03ffe000) | ((xw1 >> 19)&0x00001fff); + x3 = ((xw3 << 19)&0x01f80000) | ((xw2 >> 13)&0x0007ffff); + x4 = ((xw3 >> 6)&0x03ffffff); + x5 = (xw4 << 0)&0x01ffffff; + x6 = ((xw5 << 7)&0x03ffff80) | ((xw4 >> 25)&0x0000007f); + x7 = ((xw6 << 13)&0x01ffe000) | ((xw5 >> 19)&0x00001fff); + x8 = ((xw7 << 20)&0x03f00000) | ((xw6 >> 12)&0x000fffff); + x9 = ((xw7 >> 6)&0x01ffffff); + + /* Next, we convert these pieces into a roughly balanced signed + * representation. For each piece, check to see if its top bit is set. If + * it is, then lend a bit to the next piece over. For x_9, this needs to + * be carried around, which is a little fiddly. In particular, we delay + * the carry until after all of the pieces have been balanced. If we don't + * do this, then we have to do a more expensive test for nonzeroness to + * decide whether to lend a bit leftwards rather than just testing a single + * bit. + * + * This fixes up the anomalous size of x_0: the loan of a bit becomes an + * actual carry if x_0 >= 2^26. By the end, then, we have: + * + * { 2^25 if i even + * |x_i| <= { + * { 2^24 if i odd + * + * Note that we don't try for a canonical representation here: both upper + * and lower bounds are achievable. + * + * All of the x_i at this point are positive, so we don't need to do + * anything wierd when masking them. + */ + b = x9&B24; c = 19&((b >> 19) - (b >> 24)); x9 -= b << 1; + b = x8&B25; x9 += b >> 25; x8 -= b << 1; + b = x7&B24; x8 += b >> 24; x7 -= b << 1; + b = x6&B25; x7 += b >> 25; x6 -= b << 1; + b = x5&B24; x6 += b >> 24; x5 -= b << 1; + b = x4&B25; x5 += b >> 25; x4 -= b << 1; + b = x3&B24; x4 += b >> 24; x3 -= b << 1; + b = x2&B25; x3 += b >> 25; x2 -= b << 1; + b = x1&B24; x2 += b >> 24; x1 -= b << 1; + b = x0&B25; x1 += (b >> 25) + (x0 >> 26); x0 = (x0&M26) - (b << 1); + x0 += c; + + /* And with that, we're done. */ + STASH(z, x); +} + +/* --- @f25519_store@ --- * + * + * Arguments: @octet zv[32]@ = where to write the result + * @const f25519 *x@ = the field element to write + * + * Returns: --- + * + * Use: Stores a field element in the given octet vector in external + * representation. A canonical encoding is always stored, so, + * in particular, the top bit of @xv[31]@ is always left clear. + */ + +void f25519_store(octet zv[32], const f25519 *x) +{ + + piece PIECES(x), PIECES(y), c, d; + uint32 zw0, zw1, zw2, zw3, zw4, zw5, zw6, zw7; + mask32 m; + + FETCH(x, x); + + /* First, propagate the carries throughout the pieces. By the end of this, + * we'll have all of the pieces canonically sized and positive, and maybe + * there'll be (signed) carry out. The carry c is in { -1, 0, +1 }, and + * the remaining value will be in the half-open interval [0, 2^255). The + * whole represented value is then x + 2^255 c. + * + * It's worth paying careful attention to the bounds. We assume that we + * start out with |x_i| <= 2^30. We start by cutting off and reducing the + * carry c_9 from the topmost piece, x_9. This leaves 0 <= x_9 < 2^25; and + * we'll have |c_9| <= 2^5. We multiply this by 19 and we'll add it onto + * x_0 and propagate the carries: but what bounds can we calculate on x + * before this? + * + * Let o_i = floor(51 i/2). We have X_i = SUM_{0<=j= 2^255 - 19, then we should subtract 2^255 - 19 from the whole + * value; if c = -1 then we should add 2^255 - 19; and otherwise we should + * do nothing. + * + * But conditional behaviour is bad, m'kay. So here's what we do instead. + * + * The first job is to sort out what we wanted to do. If c = -1 then we + * want to (a) invert the constant addend and (b) feed in a carry-in; + * otherwise, we don't. + */ + m = SIGN(c); + d = m&1; + + /* Now do the addition/subtraction. Remember that all of the x_i are + * nonnegative, so shifting and masking are safe and easy. + */ + d += x0 + (19 ^ (M26&m)); y0 = d&M26; d >>= 26; + d += x1 + (M25&m); y1 = d&M25; d >>= 25; + d += x2 + (M26&m); y2 = d&M26; d >>= 26; + d += x3 + (M25&m); y3 = d&M25; d >>= 25; + d += x4 + (M26&m); y4 = d&M26; d >>= 26; + d += x5 + (M25&m); y5 = d&M25; d >>= 25; + d += x6 + (M26&m); y6 = d&M26; d >>= 26; + d += x7 + (M25&m); y7 = d&M25; d >>= 25; + d += x8 + (M26&m); y8 = d&M26; d >>= 26; + d += x9 + (M25&m); y9 = d&M25; d >>= 25; + + /* The final carry-out is in d; since we only did addition, and the x_i are + * nonnegative, then d is in { 0, 1 }. We want to keep y, rather than x, + * if (a) c /= 0 (in which case we know that the old value was + * unsatisfactory), or (b) if d = 1 (in which case, if c = 0, we know that + * the subtraction didn't cause a borrow, so we must be in the case where + * 2^255 - 19 <= x < 2^255). + */ + m = NONZEROP(c) | ~NONZEROP(d - 1); + x0 = (y0&m) | (x0&~m); x1 = (y1&m) | (x1&~m); + x2 = (y2&m) | (x2&~m); x3 = (y3&m) | (x3&~m); + x4 = (y4&m) | (x4&~m); x5 = (y5&m) | (x5&~m); + x6 = (y6&m) | (x6&~m); x7 = (y7&m) | (x7&~m); + x8 = (y8&m) | (x8&~m); x9 = (y9&m) | (x9&~m); + + /* Extract 32-bit words from the value. */ + zw0 = ((x0 >> 0)&0x03ffffff) | (((uint32)x1 << 26)&0xfc000000); + zw1 = ((x1 >> 6)&0x0007ffff) | (((uint32)x2 << 19)&0xfff80000); + zw2 = ((x2 >> 13)&0x00001fff) | (((uint32)x3 << 13)&0xffffe000); + zw3 = ((x3 >> 19)&0x0000003f) | (((uint32)x4 << 6)&0xffffffc0); + zw4 = ((x5 >> 0)&0x01ffffff) | (((uint32)x6 << 25)&0xfe000000); + zw5 = ((x6 >> 7)&0x0007ffff) | (((uint32)x7 << 19)&0xfff80000); + zw6 = ((x7 >> 13)&0x00000fff) | (((uint32)x8 << 12)&0xfffff000); + zw7 = ((x8 >> 20)&0x0000003f) | (((uint32)x9 << 6)&0x7fffffc0); + + /* Store the result as an octet string. */ + STORE32_L(zv + 0, zw0); STORE32_L(zv + 4, zw1); + STORE32_L(zv + 8, zw2); STORE32_L(zv + 12, zw3); + STORE32_L(zv + 16, zw4); STORE32_L(zv + 20, zw5); + STORE32_L(zv + 24, zw6); STORE32_L(zv + 28, zw7); +} + +/* --- @f25519_set@ --- * + * + * Arguments: @f25519 *z@ = where to write the result + * @int a@ = a small-ish constant + * + * Returns: --- + * + * Use: Sets @z@ to equal @a@. + */ + +void f25519_set(f25519 *x, int a) +{ + unsigned i; + + x->P[0] = a; + for (i = 1; i < NPIECE; i++) x->P[i] = 0; +} + +/*----- Basic arithmetic --------------------------------------------------*/ + +/* --- @f25519_add@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the sum %$x + y$%. + */ + +void f25519_add(f25519 *z, const f25519 *x, const f25519 *y) +{ + z->P[0] = x->P[0] + y->P[0]; z->P[1] = x->P[1] + y->P[1]; + z->P[2] = x->P[2] + y->P[2]; z->P[3] = x->P[3] + y->P[3]; + z->P[4] = x->P[4] + y->P[4]; z->P[5] = x->P[5] + y->P[5]; + z->P[6] = x->P[6] + y->P[6]; z->P[7] = x->P[7] + y->P[7]; + z->P[8] = x->P[8] + y->P[8]; z->P[9] = x->P[9] + y->P[9]; +} + +/* --- @f25519_sub@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the difference %$x - y$%. + */ + +void f25519_sub(f25519 *z, const f25519 *x, const f25519 *y) +{ + z->P[0] = x->P[0] - y->P[0]; z->P[1] = x->P[1] - y->P[1]; + z->P[2] = x->P[2] - y->P[2]; z->P[3] = x->P[3] - y->P[3]; + z->P[4] = x->P[4] - y->P[4]; z->P[5] = x->P[5] - y->P[5]; + z->P[6] = x->P[6] - y->P[6]; z->P[7] = x->P[7] - y->P[7]; + z->P[8] = x->P[8] - y->P[8]; z->P[9] = x->P[9] - y->P[9]; +} + +/* --- @f25519_neg@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@) + * @const f25519 *x@ = an operand + * + * Returns: --- + * + * Use: Set @z = -x@. + */ + +void f25519_neg(f25519 *z, const f25519 *x) +{ + z->P[0] = -x->P[0]; z->P[1] = -x->P[1]; + z->P[2] = -x->P[2]; z->P[3] = -x->P[3]; + z->P[4] = -x->P[4]; z->P[5] = -x->P[5]; + z->P[6] = -x->P[6]; z->P[7] = -x->P[7]; + z->P[8] = -x->P[8]; z->P[9] = -x->P[9]; +} + +/*----- Constant-time utilities -------------------------------------------*/ + +/* --- @f25519_pick2@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * @uint32 m@ = a mask + * + * Returns: --- + * + * Use: If @m@ is zero, set @z = y@; if @m@ is all-bits-set, then set + * @z = x@. If @m@ has some other value, then scramble @z@ in + * an unhelpful way. + */ + +void f25519_pick2(f25519 *z, const f25519 *x, const f25519 *y, uint32 m) +{ + mask32 mm = FIX_MASK32(m); + + z->P[0] = PICK2(x->P[0], y->P[0], mm); + z->P[1] = PICK2(x->P[1], y->P[1], mm); + z->P[2] = PICK2(x->P[2], y->P[2], mm); + z->P[3] = PICK2(x->P[3], y->P[3], mm); + z->P[4] = PICK2(x->P[4], y->P[4], mm); + z->P[5] = PICK2(x->P[5], y->P[5], mm); + z->P[6] = PICK2(x->P[6], y->P[6], mm); + z->P[7] = PICK2(x->P[7], y->P[7], mm); + z->P[8] = PICK2(x->P[8], y->P[8], mm); + z->P[9] = PICK2(x->P[9], y->P[9], mm); +} + +/* --- @f25519_pickn@ --- * + * + * Arguments: @f25519 *z@ = where to put the result + * @const f25519 *v@ = a table of entries + * @size_t n@ = the number of entries in @v@ + * @size_t i@ = an index + * + * Returns: --- + * + * Use: If @0 <= i < n < 32@ then set @z = v[i]@. If @n >= 32@ then + * do something unhelpful; otherwise, if @i >= n@ then set @z@ + * to zero. + */ + +void f25519_pickn(f25519 *z, const f25519 *v, size_t n, size_t i) +{ + uint32 b = (uint32)1 << (31 - i); + mask32 m; + + z->P[0] = z->P[1] = z->P[2] = z->P[3] = z->P[4] = + z->P[5] = z->P[6] = z->P[7] = z->P[8] = z->P[9] = 0; + while (n--) { + m = SIGN(b); + CONDPICK(z->P[0], v->P[0], m); + CONDPICK(z->P[1], v->P[1], m); + CONDPICK(z->P[2], v->P[2], m); + CONDPICK(z->P[3], v->P[3], m); + CONDPICK(z->P[4], v->P[4], m); + CONDPICK(z->P[5], v->P[5], m); + CONDPICK(z->P[6], v->P[6], m); + CONDPICK(z->P[7], v->P[7], m); + CONDPICK(z->P[8], v->P[8], m); + CONDPICK(z->P[9], v->P[9], m); + v++; b <<= 1; + } +} + +/* --- @f25519_condswap@ --- * + * + * Arguments: @f25519 *x, *y@ = two operands + * @uint32 m@ = a mask + * + * Returns: --- + * + * Use: If @m@ is zero, do nothing; if @m@ is all-bits-set, then + * exchange @x@ and @y@. If @m@ has some other value, then + * scramble @x@ and @y@ in an unhelpful way. + */ + +void f25519_condswap(f25519 *x, f25519 *y, uint32 m) +{ + mask32 mm = FIX_MASK32(m); + + CONDSWAP(x->P[0], y->P[0], mm); + CONDSWAP(x->P[1], y->P[1], mm); + CONDSWAP(x->P[2], y->P[2], mm); + CONDSWAP(x->P[3], y->P[3], mm); + CONDSWAP(x->P[4], y->P[4], mm); + CONDSWAP(x->P[5], y->P[5], mm); + CONDSWAP(x->P[6], y->P[6], mm); + CONDSWAP(x->P[7], y->P[7], mm); + CONDSWAP(x->P[8], y->P[8], mm); + CONDSWAP(x->P[9], y->P[9], mm); +} + +/* --- @f25519_condneg@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@) + * @const f25519 *x@ = an operand + * @uint32 m@ = a mask + * + * Returns: --- + * + * Use: If @m@ is zero, set @z = x@; if @m@ is all-bits-set, then set + * @z = -x@. If @m@ has some other value then scramble @z@ in + * an unhelpful way. + */ + +void f25519_condneg(f25519 *z, const f25519 *x, uint32 m) +{ + mask32 m_xor = FIX_MASK32(m); + piece m_add = m&1; +# define CONDNEG(x) (((x) ^ m_xor) + m_add) + + z->P[0] = CONDNEG(x->P[0]); + z->P[1] = CONDNEG(x->P[1]); + z->P[2] = CONDNEG(x->P[2]); + z->P[3] = CONDNEG(x->P[3]); + z->P[4] = CONDNEG(x->P[4]); + z->P[5] = CONDNEG(x->P[5]); + z->P[6] = CONDNEG(x->P[6]); + z->P[7] = CONDNEG(x->P[7]); + z->P[8] = CONDNEG(x->P[8]); + z->P[9] = CONDNEG(x->P[9]); + +#undef CONDNEG +} + +/*----- Multiplication ----------------------------------------------------*/ + +/* Let B = 2^63 - 1 be the largest value such that +B and -B can be + * represented in a double-precision piece. On entry, it must be the case + * that |X_i| <= M <= B - 2^25 for some M. If this is the case, then, on + * exit, we will have |Z_i| <= 2^25 + 19 M/2^25. + */ +#define CARRYSTEP(z, x, m, b, f, xx, n) do { \ + (z) = (dblpiece)((udblpiece)(x)&(m)) - (b) + \ + (f)*ASR(dblpiece, (xx), (n)); \ +} while (0) +#define CARRY_REDUCE(z, x) do { \ + dblpiece PIECES(_t); \ + \ + /* Bias the input pieces. This keeps the carries and so on centred \ + * around zero rather than biased positive. \ + */ \ + _t0 = (x##0) + B25; _t1 = (x##1) + B24; \ + _t2 = (x##2) + B25; _t3 = (x##3) + B24; \ + _t4 = (x##4) + B25; _t5 = (x##5) + B24; \ + _t6 = (x##6) + B25; _t7 = (x##7) + B24; \ + _t8 = (x##8) + B25; _t9 = (x##9) + B24; \ + \ + /* Calculate the reduced pieces. Careful with the bithacking. */ \ + CARRYSTEP(z##0, _t0, M26, B25, 19, _t9, 25); \ + CARRYSTEP(z##1, _t1, M25, B24, 1, _t0, 26); \ + CARRYSTEP(z##2, _t2, M26, B25, 1, _t1, 25); \ + CARRYSTEP(z##3, _t3, M25, B24, 1, _t2, 26); \ + CARRYSTEP(z##4, _t4, M26, B25, 1, _t3, 25); \ + CARRYSTEP(z##5, _t5, M25, B24, 1, _t4, 26); \ + CARRYSTEP(z##6, _t6, M26, B25, 1, _t5, 25); \ + CARRYSTEP(z##7, _t7, M25, B24, 1, _t6, 26); \ + CARRYSTEP(z##8, _t8, M26, B25, 1, _t7, 25); \ + CARRYSTEP(z##9, _t9, M25, B24, 1, _t8, 26); \ +} while (0) + +/* --- @f25519_mulconst@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@) + * @const f25519 *x@ = an operand + * @long a@ = a small-ish constant; %$|a| < 2^{20}$%. + * + * Returns: --- + * + * Use: Set @z@ to the product %$a x$%. + */ + +void f25519_mulconst(f25519 *z, const f25519 *x, long a) +{ + + piece PIECES(x); + dblpiece PIECES(z), aa = a; + + FETCH(x, x); + + /* Suppose that |x_i| <= 2^27, and |a| <= 2^23. Then we'll have + * |z_i| <= 2^50. + */ + z0 = aa*x0; z1 = aa*x1; z2 = aa*x2; z3 = aa*x3; z4 = aa*x4; + z5 = aa*x5; z6 = aa*x6; z7 = aa*x7; z8 = aa*x8; z9 = aa*x9; + + /* Following `CARRY_REDUCE', we'll have |z_i| <= 2^26. */ + CARRY_REDUCE(z, z); + STASH(z, z); +} + +/* --- @f25519_mul@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the product %$x y$%. + */ + +void f25519_mul(f25519 *z, const f25519 *x, const f25519 *y) +{ + + piece PIECES(x), PIECES(y); + dblpiece PIECES(z); + unsigned i; + + FETCH(x, x); FETCH(y, y); + + /* Suppose that |x_i|, |y_i| <= 2^27. Then we'll have + * + * |z_0| <= 267*2^54 + * |z_1| <= 154*2^54 + * |z_2| <= 213*2^54 + * |z_3| <= 118*2^54 + * |z_4| <= 159*2^54 + * |z_5| <= 82*2^54 + * |z_6| <= 105*2^54 + * |z_7| <= 46*2^54 + * |z_8| <= 51*2^54 + * |z_9| <= 10*2^54 + * + * all of which are less than 2^63 - 2^25. + */ + +#define M(a, b) ((dblpiece)(a)*(b)) + z0 = M(x0, y0) + + 19*(M(x2, y8) + M(x4, y6) + M(x6, y4) + M(x8, y2)) + + 38*(M(x1, y9) + M(x3, y7) + M(x5, y5) + M(x7, y3) + M(x9, y1)); + z1 = M(x0, y1) + M(x1, y0) + + 19*(M(x2, y9) + M(x3, y8) + M(x4, y7) + M(x5, y6) + + M(x6, y5) + M(x7, y4) + M(x8, y3) + M(x9, y2)); + z2 = M(x0, y2) + M(x2, y0) + + 2* M(x1, y1) + + 19*(M(x4, y8) + M(x6, y6) + M(x8, y4)) + + 38*(M(x3, y9) + M(x5, y7) + M(x7, y5) + M(x9, y3)); + z3 = M(x0, y3) + M(x1, y2) + M(x2, y1) + M(x3, y0) + + 19*(M(x4, y9) + M(x5, y8) + M(x6, y7) + + M(x7, y6) + M(x8, y5) + M(x9, y4)); + z4 = M(x0, y4) + M(x2, y2) + M(x4, y0) + + 2*(M(x1, y3) + M(x3, y1)) + + 19*(M(x6, y8) + M(x8, y6)) + + 38*(M(x5, y9) + M(x7, y7) + M(x9, y5)); + z5 = M(x0, y5) + M(x1, y4) + M(x2, y3) + + M(x3, y2) + M(x4, y1) + M(x5, y0) + + 19*(M(x6, y9) + M(x7, y8) + M(x8, y7) + M(x9, y6)); + z6 = M(x0, y6) + M(x2, y4) + M(x4, y2) + M(x6, y0) + + 2*(M(x1, y5) + M(x3, y3) + M(x5, y1)) + + 19* M(x8, y8) + + 38*(M(x7, y9) + M(x9, y7)); + z7 = M(x0, y7) + M(x1, y6) + M(x2, y5) + M(x3, y4) + + M(x4, y3) + M(x5, y2) + M(x6, y1) + M(x7, y0) + + 19*(M(x8, y9) + M(x9, y8)); + z8 = M(x0, y8) + M(x2, y6) + M(x4, y4) + M(x6, y2) + M(x8, y0) + + 2*(M(x1, y7) + M(x3, y5) + M(x5, y3) + M(x7, y1)) + + 38* M(x9, y9); + z9 = M(x0, y9) + M(x1, y8) + M(x2, y7) + M(x3, y6) + M(x4, y5) + + M(x5, y4) + M(x6, y3) + M(x7, y2) + M(x8, y1) + M(x9, y0); +#undef M + + /* From above, we have |z_i| <= 2^63 - 2^25. A pass of `CARRY_REDUCE' will + * leave |z_i| <= 2^38 + 2^25; and a second pass will leave |z_i| <= 2^25 + + * 2^13, which is comfortable for an addition prior to the next + * multiplication. + */ + for (i = 0; i < 2; i++) CARRY_REDUCE(z, z); + STASH(z, z); +} + +/* --- @f25519_sqr@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x@ = an operand + * + * Returns: --- + * + * Use: Set @z@ to the square %$x^2$%. + */ + +void f25519_sqr(f25519 *z, const f25519 *x) +{ + + piece PIECES(x); + dblpiece PIECES(z); + unsigned i; + + FETCH(x, x); + + /* See `f25519_mul' for bounds. */ + +#define M(a, b) ((dblpiece)(a)*(b)) + z0 = M(x0, x0) + + 38*(M(x2, x8) + M(x4, x6) + M(x5, x5)) + + 76*(M(x1, x9) + M(x3, x7)); + z1 = 2* M(x0, x1) + + 38*(M(x2, x9) + M(x3, x8) + M(x4, x7) + M(x5, x6)); + z2 = 2*(M(x0, x2) + M(x1, x1)) + + 19* M(x6, x6) + + 38* M(x4, x8) + + 76*(M(x3, x9) + M(x5, x7)); + z3 = 2*(M(x0, x3) + M(x1, x2)) + + 38*(M(x4, x9) + M(x5, x8) + M(x6, x7)); + z4 = M(x2, x2) + + 2* M(x0, x4) + + 4* M(x1, x3) + + 38*(M(x6, x8) + M(x7, x7)) + + 76* M(x5, x9); + z5 = 2*(M(x0, x5) + M(x1, x4) + M(x2, x3)) + + 38*(M(x6, x9) + M(x7, x8)); + z6 = 2*(M(x0, x6) + M(x2, x4) + M(x3, x3)) + + 4* M(x1, x5) + + 19* M(x8, x8) + + 76* M(x7, x9); + z7 = 2*(M(x0, x7) + M(x1, x6) + M(x2, x5) + M(x3, x4)) + + 38* M(x8, x9); + z8 = M(x4, x4) + + 2*(M(x0, x8) + M(x2, x6)) + + 4*(M(x1, x7) + M(x3, x5)) + + 38* M(x9, x9); + z9 = 2*(M(x0, x9) + M(x1, x8) + M(x2, x7) + M(x3, x6) + M(x4, x5)); +#undef M + + /* See `f25519_mul' for details. */ + for (i = 0; i < 2; i++) CARRY_REDUCE(z, z); + STASH(z, z); +} + +/*----- More complicated things -------------------------------------------*/ + +/* --- @f25519_inv@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@) + * @const f25519 *x@ = an operand + * + * Returns: --- + * + * Use: Stores in @z@ the multiplicative inverse %$x^{-1}$%. If + * %$x = 0$% then @z@ is set to zero. This is considered a + * feature. + */ + +void f25519_inv(f25519 *z, const f25519 *x) +{ + f25519 t, u, t2, t11, t2p10m1, t2p50m1; + unsigned i; + +#define SQRN(z, x, n) do { \ + f25519_sqr((z), (x)); \ + for (i = 1; i < (n); i++) f25519_sqr((z), (z)); \ +} while (0) + + /* Calculate x^-1 = x^(p - 2) = x^(2^255 - 21), which also handles x = 0 as + * intended. The addition chain here is from Bernstein's implementation; I + * couldn't find a better one. + */ /* step | value */ + f25519_sqr(&t2, x); /* 1 | 2 */ + SQRN(&u, &t2, 2); /* 3 | 8 */ + f25519_mul(&t, &u, x); /* 4 | 9 */ + f25519_mul(&t11, &t, &t2); /* 5 | 11 = 2^5 - 21 */ + f25519_sqr(&u, &t11); /* 6 | 22 */ + f25519_mul(&t, &t, &u); /* 7 | 31 = 2^5 - 1 */ + SQRN(&u, &t, 5); /* 12 | 2^10 - 2^5 */ + f25519_mul(&t2p10m1, &t, &u); /* 13 | 2^10 - 1 */ + SQRN(&u, &t2p10m1, 10); /* 23 | 2^20 - 2^10 */ + f25519_mul(&t, &t2p10m1, &u); /* 24 | 2^20 - 1 */ + SQRN(&u, &t, 20); /* 44 | 2^40 - 2^20 */ + f25519_mul(&t, &t, &u); /* 45 | 2^40 - 1 */ + SQRN(&u, &t, 10); /* 55 | 2^50 - 2^10 */ + f25519_mul(&t2p50m1, &t2p10m1, &u); /* 56 | 2^50 - 1 */ + SQRN(&u, &t2p50m1, 50); /* 106 | 2^100 - 2^50 */ + f25519_mul(&t, &t2p50m1, &u); /* 107 | 2^100 - 1 */ + SQRN(&u, &t, 100); /* 207 | 2^200 - 2^100 */ + f25519_mul(&t, &t, &u); /* 208 | 2^200 - 1 */ + SQRN(&u, &t, 50); /* 258 | 2^250 - 2^50 */ + f25519_mul(&t, &t2p50m1, &u); /* 259 | 2^250 - 1 */ + SQRN(&u, &t, 5); /* 264 | 2^255 - 2^5 */ + f25519_mul(z, &u, &t11); /* 265 | 2^255 - 21 */ + +#undef SQRN +} + +/* --- @f25519_quosqrt@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * + * Returns: Zero if successful, @-1@ if %$x/y$% is not a square. + * + * Use: Stores in @z@ the one of the square roots %$\pm\sqrt{x/y}$%. + * If %$x = y = 0% then the result is zero; if %$y = 0$% but %$x + * \ne 0$% then the operation fails. If you wanted a specific + * square root then you'll have to pick it yourself. + */ + +static const piece sqrtm1_pieces[NPIECE] = { + -32595792, -7943725, 9377950, 3500415, 12389472, + -272473, -25146209, -2005654, 326686, 11406482 +}; +#define SQRTM1 ((const f25519 *)sqrtm1_pieces) + +int f25519_quosqrt(f25519 *z, const f25519 *x, const f25519 *y) +{ + f25519 t, u, w, beta, xy3, t2p50m1; + octet xb[32], b0[32], b1[32]; + int32 rc = -1; + mask32 m; + unsigned i; + +#define SQRN(z, x, n) do { \ + f25519_sqr((z), (x)); \ + for (i = 1; i < (n); i++) f25519_sqr((z), (z)); \ +} while (0) + + /* This is a bit tricky; the algorithm is from Bernstein, Duif, Lange, + * Schwabe, and Yang, `High-speed high-security signatures', 2011-09-26, + * https://ed25519.cr.yp.to/ed25519-20110926.pdf. + * + * First of all, a complicated exponentation. The addition chain here is + * mine. We start with some preliminary values. + */ /* step | value */ + SQRN(&u, y, 1); /* 1 | 0, 2 */ + f25519_mul(&t, &u, y); /* 2 | 0, 3 */ + f25519_mul(&xy3, &t, x); /* 3 | 1, 3 */ + SQRN(&u, &u, 1); /* 4 | 0, 4 */ + f25519_mul(&w, &u, &xy3); /* 5 | 1, 7 */ + + /* And now we calculate w^((p - 5)/8) = w^(252 - 3). */ + SQRN(&u, &w, 1); /* 6 | 2 */ + f25519_mul(&t, &w, &u); /* 7 | 3 */ + SQRN(&u, &t, 1); /* 8 | 6 */ + f25519_mul(&t, &u, &w); /* 9 | 7 */ + SQRN(&u, &t, 3); /* 12 | 56 */ + f25519_mul(&t, &t, &u); /* 13 | 63 = 2^6 - 1 */ + SQRN(&u, &t, 6); /* 19 | 2^12 - 2^6 */ + f25519_mul(&t, &t, &u); /* 20 | 2^12 - 1 */ + SQRN(&u, &t, 12); /* 32 | 2^24 - 2^12 */ + f25519_mul(&t, &t, &u); /* 33 | 2^24 - 1 */ + SQRN(&u, &t, 1); /* 34 | 2^25 - 2 */ + f25519_mul(&t, &u, &w); /* 35 | 2^25 - 1 */ + SQRN(&u, &t, 25); /* 60 | 2^50 - 2^25 */ + f25519_mul(&t2p50m1, &t, &u); /* 61 | 2^50 - 1 */ + SQRN(&u, &t2p50m1, 50); /* 111 | 2^100 - 2^50 */ + f25519_mul(&t, &t2p50m1, &u); /* 112 | 2^100 - 1 */ + SQRN(&u, &t, 100); /* 212 | 2^200 - 2^100 */ + f25519_mul(&t, &t, &u); /* 213 | 2^200 - 1 */ + SQRN(&u, &t, 50); /* 263 | 2^250 - 2^50 */ + f25519_mul(&t, &t2p50m1, &u); /* 264 | 2^250 - 1 */ + SQRN(&u, &t, 2); /* 266 | 2^252 - 4 */ + f25519_mul(&t, &u, &w); /* 267 | 2^252 - 3 */ + + /* And finally... */ + f25519_mul(&beta, &t, &xy3); /* 268 | ... */ + + /* Now we have beta = (x y^3) (x y^7)^((p - 5)/8) = (x/y)^((p + 3)/8), and + * we're ready to finish the computation. Suppose that alpha^2 = u/w. + * Then beta^4 = (x/y)^((p + 3)/2) = alpha^(p + 3) = alpha^4 = (x/y)^2, so + * we have beta^2 = ±x/y. If y beta^2 = x then beta is the one we wanted; + * if -y beta^2 = x, then we want beta sqrt(-1), which we already know. Of + * course, it might not match either, in which case we fail. + * + * The easiest way to compare is to encode. This isn't as wasteful as it + * sounds: the hard part is normalizing the representations, which we have + * to do anyway. + */ + f25519_sqr(&t, &beta); + f25519_mul(&t, &t, y); + f25519_neg(&u, &t); + f25519_store(xb, x); + f25519_store(b0, &t); + f25519_store(b1, &u); + f25519_mul(&u, &beta, SQRTM1); + + m = -consttime_memeq(b0, xb, 32); + rc = PICK2(0, rc, m); + f25519_pick2(z, &beta, &u, m); + m = -consttime_memeq(b1, xb, 32); + rc = PICK2(0, rc, m); + + /* And we're done. */ + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/f25519.h b/f25519.h new file mode 100644 index 0000000..d097c0d --- /dev/null +++ b/f25519.h @@ -0,0 +1,295 @@ +/* -*-c-*- + * + * Arithmetic modulo 2^255 - 19 + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_F25519_H +#define CATACOMB_F25519_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include "fake-mLib-bits.h" + +#ifndef CATACOMB_QFARITH_H +# include "qfarith.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef union { + int32 p26[10]; +} f25519; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @f25519_set@ --- * + * + * Arguments: @f25519 *z@ = where to write the result + * @int a@ = a small-ish constant + * + * Returns: --- + * + * Use: Sets @z@ to equal @a@. + */ + +extern void f25519_set(f25519 */*x*/, int /*a*/); + +/* --- @f25519_load@ --- * + * + * Arguments: @f25519 *z@ = where to store the result + * @const octet xv[32]@ = source to read + * + * Returns: --- + * + * Use: Reads an element of %$\gf{2^{255} - 19}$% in external + * representation from @xv@ and stores it in @z@. + * + * External representation is little-endian base-256. Elements + * have multiple encodings, which are not produced by correct + * software; use of noncanonical encodings is not an error, and + * toleration of them is considered a performance feature. + * + * Some specifications, e.g., RFC7748, require the topmost bit + * (i.e., bit 7 of @wv[31]@) to be ignored. Callers + * implementing such specifications should clear the bit + * explicitly. (It's much easier for a caller who wants the bit + * to be ignored to clear it than for a caller who wants the bit + * to be significant to apply the necessary change by hand.) + */ + +extern void f25519_load(f25519 */*z*/, const octet /*xv*/[32]); + +/* --- @f25519_store@ --- * + * + * Arguments: @octet zv[32]@ = where to write the result + * @const f25519 *x@ = the field element to write + * + * Returns: --- + * + * Use: Stores a field element in the given octet vector in external + * representation. A canonical encoding is always stored, so, + * in particular, the top bit of @xv[31]@ is always left clear. + */ + +extern void f25519_store(octet /*zv*/[32], const f25519 */*x*/); + +/* --- @f25519_pick2@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * @uint32 m@ = a mask + * + * Returns: --- + * + * Use: If @m@ is zero, set @z = y@; if @m@ is all-bits-set, then set + * @z = x@. If @m@ has some other value, then scramble @z@ in + * an unhelpful way. + */ + +extern void f25519_pick2(f25519 */*z*/, const f25519 */*x*/, + const f25519 */*y*/, uint32 /*m*/); + +/* --- @f25519_pickn@ --- * + * + * Arguments: @f25519 *z@ = where to put the result + * @const f25519 *v@ = a table of entries + * @size_t n@ = the number of entries in @v@ + * @size_t i@ = an index + * + * Returns: --- + * + * Use: If @0 <= i < n < 32@ then set @z = v[i]@. If @n >= 32@ then + * do something unhelpful; otherwise, if @i >= n@ then set @z@ + * to zero. + */ + +extern void f25519_pickn(f25519 */*z*/, const f25519 */*v*/, size_t /*n*/, + size_t /*i*/); + +/* --- @f25519_condswap@ --- * + * + * Arguments: @f25519 *x, *y@ = two operands + * @uint32 m@ = a mask + * + * Returns: --- + * + * Use: If @m@ is zero, do nothing; if @m@ is all-bits-set, then + * exchange @x@ and @y@. If @m@ has some other value, then + * scramble @x@ and @y@ in an unhelpful way. + */ + +extern void f25519_condswap(f25519 */*x*/, f25519 */*y*/, uint32 /*m*/); + +/* --- @f25519_add@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the sum %$x + y$%. + */ + +extern void f25519_add(f25519 */*z*/, + const f25519 */*x*/, const f25519 */*y*/); + +/* --- @f25519_sub@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the difference %$x - y$%. + */ + +extern void f25519_sub(f25519 */*z*/, + const f25519 */*x*/, const f25519 */*y*/); + +/* --- @f25519_neg@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@) + * @const f25519 *x@ = an operand + * + * Returns: --- + * + * Use: Set @z = -x@. + */ + +extern void f25519_neg(f25519 */*z*/, const f25519 */*x*/); + +/* --- @f25519_condneg@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@) + * @const f25519 *x@ = an operand + * @uint32 m@ = a mask + * + * Returns: --- + * + * Use: If @m@ is zero, set @z = x@; if @m@ is all-bits-set, then set + * @z = -x@. If @m@ has some other value then scramble @z@ in + * an unhelpful way. + */ + +extern void f25519_condneg(f25519 */*z*/, const f25519 */*x*/, uint32 /*m*/); + +/* --- @f25519_mulconst@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@) + * @const f25519 *x@ = an operand + * @long a@ = a small-ish constant; %$|a| < 2^{20}$%. + * + * Returns: --- + * + * Use: Set @z@ to the product %$a x$%. + */ + +extern void f25519_mulconst(f25519 */*z*/, const f25519 */*x*/, long /*a*/); + +/* --- @f25519_mul@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the product %$x y$%. + */ + +extern void f25519_mul(f25519 */*z*/, + const f25519 */*x*/, const f25519 */*y*/); + +/* --- @f25519_sqr@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x@ = an operand + * + * Returns: --- + * + * Use: Set @z@ to the square %$x^2$%. + */ + +extern void f25519_sqr(f25519 */*z*/, const f25519 */*x*/); + +/* --- @f25519_inv@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@) + * @const f25519 *x@ = an operand + * + * Returns: --- + * + * Use: Stores in @z@ the multiplicative inverse %$x^{-1}$%. If + * %$x = 0$% then @z@ is set to zero. This is considered a + * feature. + */ + +extern void f25519_inv(f25519 */*z*/, const f25519 */*x*/); + +/* --- @f25519_quosqrt@ --- * + * + * Arguments: @f25519 *z@ = where to put the result (may alias @x@ or @y@) + * @const f25519 *x, *y@ = two operands + * + * Returns: Zero if successful, @-1@ if %$x/y$% is not a square. + * + * Use: Stores in @z@ the one of the square roots %$\pm\sqrt{x/y}$%. + * If %$x = y = 0% then the result is zero; if %$y = 0$% but %$x + * \ne 0$% then the operation fails. If you wanted a specific + * square root then you'll have to pick it yourself. + */ + +extern int f25519_quosqrt(f25519 */*z*/, + const f25519 */*x*/, const f25519 */*y*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/fgoldi-tests.in b/fgoldi-tests.in new file mode 100644 index 0000000..c574fc6 --- /dev/null +++ b/fgoldi-tests.in @@ -0,0 +1,782 @@ +### Test cases for arithmetic mod 2^448 - 2^224 - 1. -*-conf-*- +### Extracted from Catacomb. + +###-------------------------------------------------------------------------- +test add + +## Some easy ones. +x ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff +y 00 +z ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff + +x fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff +y 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +z fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff + +x fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff +y 01 +z 00 + +## Random tests. +x 6b3944398448a0a5f6c4e1be9abfcbb082b8f68f1c831d51ef2244f6e1a4c4baaf0ada769c1261b8e14b4856de381d69961078ea1949d39c +y 62e933c5f93e57e042d66b89d3c72ee85441b1207732d888b3d6bc35f3bcef91a6f4564cb085fd3239191c2fe427dcdb0e81164d30ca8145 +z cd2278fe7d87f785399b4d486e87fa98d7f9a7b093b5f5d9a2f9002cd561b44c56ff30c34c985eeb1a656485c260f944a5918e374a1355e2 + +x 34938a406030a285024e9ff0a45987b53accc9d5d59828de8b8e07ba693b64d1dd2c7a190e708253a9ae57572e44fa458c8f8ac87cd96037 +y 9d05863131328886c7203fe70924761e56244d40a04d4b5592f1c6a457b9d94fe950fb8a865f9091ba9223479f3e46680fb78ccddc776bf2 +z d298107291622a0cca6eded7ae7dfdd390f0161676e673331e80ce5ec2f43d21c77d75a494cf12e563417b9ecd8240ae9b4617965951cc29 + +x 4e9cb6823482233daf59662d00212f2afe42183f8ce949b2e0ca5473e32ab647fe9bc1c472b2288715c0d5b118043fbc9aec782654363cdd +y 6c62329ec8eb576b6866cb6af702b891dd2cd72d21c354ada34221141381acca066fb46a8fbce28df44f0ac8062e38847067b8639be867f8 +z bbfee820fd6d7ba817c03198f723e7bbdb6fef6cadac9e5f840d7687f7ab6212050b762f026f0b150a10e0791f3277400b54318aef1ea4d5 + +x b46d33f24a69c2288bed34eb054d1fcd6244606cffca7d53ff4e68f113174655a9a72898ad2699fe49d069a0a84e077bf48205008dee04aa +y 9abc68911a75a6a376837cc6fc0e18c63cfb81747a59ba1314412f032f8b2a2fc5dde29176d141e71dbc11aeb2ecb9a336c8467882a175ea +z 4f2a9c8365de68cc0171b1b1025c37939f3fe2e079243867139097f443a270846e850b2a24f8dae5678c7b4e5b3bc11e2b4b4c780f907a94 + +x 1195eae69f2bad43b7b8330395e41c811bae2f753f0a6727b9decd2e553dce743dbb568b45140c3a464c8646db12b3af18df328a95640706 +y 8fc020ba693b4014fbf4e9c64223a8c3234e1361b8e2a745e3897f582537e20417831c159c107451fec49b88c4cde774330d8986430b39e0 +z a0550ba10967ed57b2ad1dcad707c5443ffc42d6f7ec0e6d9c684d877a74b079543e73a0e124808b441122cf9fe09a244cecbb10d96f40e6 + +x 4b25a323cba12b5d042369a065a3696c7613898205f7defd3ab15ec351ec9fe1ba453c8b9abf254ff793c92b1f77d5f23f7629c04ec5c70d +y b12ee8f930b029e2e4b79b808566b88b8087a510e5f80751ffc8f5426709bc2b40608e3e769dbd97d37dfe8a36fd25fbc1efb2cd9eda09f2 +z fc538b1dfc51553fe9da0421eb0922f8f69a2e93eaefe64e3a7a5406b9f55b0dfba5cac9105de3e6ca11c8b65574fbed0166dc8ded9fd1ff + +x c441e6cebc634bd7de7de356e855528d52f4affae7cdd585352d94218ca171929b17b8f49ea294f5151a277c116519de5ff92ce4e2f6ce0a +y 809617d4e40d53223f01887bfab5a7d2dc1eb4f680ae59981b33e11fe71345b3155f567cc867cd9e48c8b534870c7df49dff883c0900d8cd +z 44d8fda2a1719ef91d7f6bd2e20bfa5f2f1364f1687c2f1e5160754173b5b645b1760e71670a62945ee2dcb0987196d2fdf8b520ecf6a6d8 + +x a92361d9c458605877a6d9229128b1a52f7bab378d0d389568aae10d09d419b0e6436684b438abcaa3e1710efee5ecec1af06cf0c82b339d +y 74bc6cd43025234b1a6e15fe2d4fab520c874af6f896b82ecb096b0ec3cf73ecf04ef1d13ca612ef0981b8aca0a769ae60202eca36410b0e +z 1de0cdadf57d83a39114ef20bf775cf83b02f62d86a4f0c333b44c1ccca38d9cd7925756f1debdb9ad622abb9e8d569b7b109bbaff6c3eab + +x f0ed25db758767b83b1d5ab6f8bdbe8e263b18341ea296b2a5d27c0d928004d6c48695ac88af863ed12be6629d8a1b58ca83ddb4ff9c778b +y 44998d5a87e29ace239af04334451efca0d8bb88b441140caab3e79da9c73f1354df0c4e2a8148141bb44c33eb63f1c0025ec2b289390e06 +z 3487b335fd6902875fb74afa2c03dd8ac713d4bcd2e3aabe4f8664ab3b4844e91866a2fab230cf52ecdf329688ee0c19cde19f6789d68591 + +x 64429139cb6dd44a64984ac73cdf306354a32772da0724c647164d89218906de465c0c47f2841564fc69933d140088a02584bbeb7a138e7a +y 391d7bf04dd8082b6b196651c251737ba319720b66075f2e65a06023e1dc9697ee4c540b6fae20bdc333c9a95e69266b5ebeccf0b2aea18d +z 9e5f0c2a1946dd75cfb1b018ff30a4def7bc997d400f83f4acb6adac03669d7535a9605261333621c09d5ce77269ae0b844288dc2dc22f08 + +x 0bb7ca441d108e3d7a4c43025798eb1f1036e2d2200e2457aa93a631c068bf9e99805e8c69344d6f5fc063865f2e94bb954c20645f8b7003 +y 3f47bc6701604867acc3cf534d62c9847617954d860c34ac2bcacbfb1c24c99a7442a6170ea6539df0c98afaf6fc8f45dcaa77afebcc8290 +z 4afe86ac1e70d6a426101356a4fab4a4864d7720a71a5803d65d722ddd8c88390ec304a477daa00c508aee80562b240172f797134b58f393 + +x 93205ac6e814337d0d12f8e55f0b62a32ba948cbc6df03293d51e67a7aa7e1457d201991f3392f1cc4a4a9b6b2ed27407ac4e24a5b0e2664 +y c2d648607a99e6dccb9f9940ffed57de39928d9c3fcbabd79876ecf1a5476ff5a637d0052f04d82a2794bf0e31268fd6ff640b4aa1ac921f +z 55f7a22663ae195ad9b191265ff9b981653bd66706abaf00d6c7d26c20ef503b2458e996223e0747eb3869c5e313b7167a29ee94fcbab883 + +x 42bb562d81bac7f606d2157697f29f1799b3e5172f003f44785b80006fb56681b832ff6e7875d6a146b09a9a95f9f3cfb210f5b9aa545e0c +y e7cc109d2ea008a1c938c66e296911c0d7503b1a961f23edce9532c718e53518729dcc6f7e921f831c56d1d8ee7c5b4919f4030ce6703e68 +z 298867caaf5ad097d00adce4c05bb1d770042132c51f623147f1b2c7879a9c992ad0cbdef607f62463066c7384764f19cc04f9c590c59c74 + +x 4cfc133cf2b3e22f569340c3a59299087f9caf8b36562d418f2e18494769278c16a22641e4de8f675e9540d6fc0f8c210a64dd63c8d01453 +y f33b0a3beaad1fb12ba48d69ef999bb7a5af3bd2b977aaf518bc65a13caaa9d61cacbb7c5ce6173a282d341cf83c86a458c8d2d10a1c1ac2 +z 40381e77dc6102e18137ce2c952c35c0244ceb5df0cdd736a8ea7dea8413d162334ee2bd40c5a7a186c274f2f44c12c6622cb035d3ec2e15 + +x fc64ef657d34477c17b0674b697cc5a4bc8e665ba1dee02e5afd0d2f57e0a64abb2bc428215d9e8ece95c5283e4233d483201c286e4997cb +y ed4af51625762548e95f32e7042f07bb260f734fb9ba43301daddff9a863990d79791d5db1bbbdbad75c09ce313d93638c219c989702c5ed +z eaafe47ca2aa6cc400109a326eabcc5fe39dd9aa5a99245f77aaed280144405834a5e185d2185c49a6f2cef66f7fc6371042b8c0054c5cb9 + +x 2fa4cdcae0b01f3f3aa28d4ff311054c73683c09749eb312cd4ff7cf018fa647a66b44477459cab757b9149623ecf9064dba16d5601eafb7 +y b378045a6652eea3cc9a8530dea6361daa86866f038e579670f2d50e072417342f1887827335a0a041d1411b24a68d8f190edd8a251ac3c7 +z e31cd22447030ee3063d1380d1b83b691defc278772c0ba93d42cdde09b3bd7bd583cbc9e78e6a58998a56b14792879666c8f35f8638727f + +x 5107c636bcd6bc59ec9c7fcf04efbf90fdde936bff7e221be660d542f74fcccb8b49220b93744203bdb7b026f1bb9fd9a64c0187fd3d99a7 +y ee48bc6d5c231bd7be253ed69171d2525157d0d8fe12fdafa6e7a3285f0d966fd4c570928f61850138489fca5cb540444c24b602d9025899 +z 405082a418fad730abc2bda5966092e34e366444fe911fcb8c48796b575d623b600f939d22d6c704f5ff4ff14d71e01df370b789d640f140 + +x 475e593758fa8506baa94e1b6070aeaff278d905af67f9e5a5273ae0737825d220c02ae7a89f39998f98895c83e51e7bd0cc0c9126273792 +y 3f724d7bbb27bf8b2f4e328bd865e412ed6207802703def28b9b64567b15f7648c1f96ca5092400e32427f9880c95fa0a83f7fbdd6b2d2b7 +z 87d0a6b213224592e9f780a638d692c2dfdbe085d66ad7d831c39e36f08d1c37addfc0b1f9317aa7c1da08f503af7e1b790c8c4efdd9094a + +x fb7923d1a8666b372b41792749ae312903e1b1a8198970a5da6d85dc19a4326bcde206ee841a2bf106c95e99b42fa7eb3fa559b4b88d31c2 +y 45e467dafaee144bbd614028c0ea4d3a37b4ef99ded5c9e44b7526916218202401233364bffadac9424143bac99b4c2d89ceea71c3fd0ea4 +z 415e8baba3558082e8a2b94f09997f633a95a142f85e3a8a26e3ab6d7dbc528fce053a52441506bb490aa2537ecbf318c97344267c8b4066 + +x 2212850af1b191227fc4875e981ee15968832cb6898243af481b62d91ae5cb26fdcd72e45a54cbbbd9efc5e1739f8683d8ab318586b51e7c +y 6b7b3294bfd31a11644924c988b0b19cfc1db66d8e674040ee21537b54aed4e1e217f0b3427d7d4d9dc7d9dcbcda8c2c47c5348b9eaa7ddb +z 8e8db79eb085ac33e30dac2721cf92f664a1e22318ea83ef363db5547093a008e0e562989dd1480977b79fbe307a13b01f71661025609c57 + +###-------------------------------------------------------------------------- +test sub + +x 890e734c6f4af5b1c62cf6fdd0facf76af535bdc9781396c59a6cd8c37cc96aac97fa61bef07c60c69dfb633049014868473d28481385ba1 +y 0a06a622804bfe9041259a435be8c40aa56d1be10dd3c4261157c16c0d0d99d11b0f5dce0b164a2e6d4c53813242954830a39f2c894fb315 +z 7f08cd29effef62085075cba75120b6c0ae63ffb89ae7445484f0c202abffdd8ad70494de3f17bdefb9263b2d14d7f3d54d03258f8e8a78b + +x 17935b9768cf9ecdc3b3a4c3c87ee20f766bca820f620c1852a48d680f445f1a28ee6a9a18fbdcdb9f35846bc6f0bbb1687b227bcadd4c3a +y 9f913b62023a48e577ac9aaa6d06bb5cf46ea3acc2946a80f66fba02859837491a31b6740a5ed1178c8b6faf4198ac836419deb8aa439c0d +z 78012035669556e84b070a195b7827b381fc26d64ccda1975b34d3658aab27d10dbdb4250e9d0bc413aa14bc84580f2e046244c21f9ab02c + +x b1689e72355c7305d5cab07e2d672e7b92872c115f03f9b45fe7c9d3354ea0d3702f4f915900085ec44e816dcd731086c999c0e97ce52b40 +y a85e9b5cbe9f628049f91b9adcc1db63f19e8f7c37b92e43015d0f76f188c1cfe89c86910afb82c2c6f1f7197562b919380a1b32b2439006 +z 090a031677bc10858bd194e450a55217a1e89c94274aca715e8aba5d44c5de038892c8ff4e05859bfd5c89535811576c918fa5b7caa19b39 + +x 8f952f2233cdba45ccaafcb8e6d17b38529a44ff49e8ac8dc6378710d5e5af052c460e2758e3ee28f5866e71737c9b6e7731c03d11d21cd6 +y 5bc41fd436b58032dd4f50cd0c57bda1127a3033c2183d8133cb9c40760ea41bb42f48f36b6a2f3bcd0dbc60b5bef5e4b712308ca0f2b443 +z 34d10f4efc173a13ef5aacebd97abe963f2014cc87cf6f0c936ceacf5ed70bea7716c633ec78bfed2779b210bebda589bf1e90b170df6792 + +x 708939d3a13fe996dd90b1128231b7da3593c12d9ab880a4da9febe7f12bfefe72aab1608145911fdfa1e3f1f59b426a06dee253d4d3eeb6 +y 008929e61e53becf9bc6dcbf6414f3a71e9f134fcab293cd42e096fef3d87a472a79ed1ce623708aee31e12f5bef9bc6d0aa470ce2a52f80 +z 700010ed82ec2ac741cad4521d1dc43217f4addecf05edd697bf54e9fd5283b74831c4439b212195f06f02c29aaca6a335339b47f22dbf36 + +x a7996b0ae1d8ad5856ae5cf3abc8fc61c4b3579d951b632b9af67dce957365759fb5a6f54965a86b1dcccc9439eebdeb04f616c3fb4db382 +y 2df8e6cf52e985d0e20f4f5e9bbaf1b8bd7d7b982da05568b7ea82fd2a5c0302d0ce9feec5e135eca886fd30827905eae204a51e498a173d +z 7aa1843a8eef2788739e0d95100e0ba90636dc04687b0dc3e20bfbd06a176273cfe606078483727f7445cf63b774b80122f171a4b2c39b45 + +x 74179531aaf2ee4e7a309350982fc9ce501ad18c650f0adacce5da9b520ce27c04ca69dca0e719713d4d10db532401bee26b7ff9819bf532 +y 6a3554898f2951ed005bc4ac74dfd0ef124cffbb52301109d8414719473dc17a602a3b530195c383efa22dd6da87414395886e4b9dd5b5f3 +z 09e240a81ac99d6179d5cea32350f8de3dced1d012dff8d0f4a393820acf2002a49f2e899f5256ed4daae204799cbf7a4de310aee4c53f3f + +x e7c145e38ca66fd86991538ab11231abb60af8b0ab7460e047f7b5b69bbe4a3a56c28c14131c35621f4014d541ffabd642c774bc1a5c66c7 +y 9ca047c2251cc6012bd734198e4b2c6ca0d50a85db601659b8380510fc6c1d08a27fa5fb8eb3c9e5622185f83fba6ed128d153cc9563e1d6 +z 4a21fe20678aa9d63eba1e7123c7043f1635ed2bd0134a878fbeb0a69e512d32b442e71884686b7cbc1e8fdc01453d051af620f084f884f0 + +x 8f01ab3bbedf7ac443423793a422910a54dd73f121ce6f52270d7953386bf2b0eb228b2560b7103aa94f3190e80038505f2b21a9f138c414 +y 44a6b845b4b3b6d9c55478664fa2134df50e7ff4c5184aa57bcc8d01da42cdbb78da3898fd92287b604b6a369c06d695241c48605b57808f +z 4a5bf2f5092cc4ea7dedbe2c55807dbd5ecef4fc5bb525adab40eb515d2825f57248528d6224e8be4804c7594cfa61ba3a0fd94896e14385 + +x 1b6f84c1ad9ec3d008f345a19305aa35e5b55efeb535024b0fc9aee4be1c031bb070655fc5e672ea75b5db98cff0dcfb5427e21e5ffc4fa9 +y ad5d4e308c69186e87ac97551e9ec34f2d1746d5f6712b126c3415346ac2271450aca96fc6b9e82ef7e2f3fad60df4f184e34dff8fb53b02 +z 6e1136912135ab628146ae4b7567e6e5b79e1829bfc3d638a39499b0545adb0660c4bbeffe2c8abb7ed2e79df8e2e809d043941fcf4614a7 + +x 25ce194230be078d7f35b85d68706d768fec7994654fcd3f63f3d32eaf59f17bc87a617d41f76b7d0c78b63377a203e43194f0b056d26b0b +y 76266bea72a15cdc355867a490e775c909b7b6cfc833107e7c6b7dbaed2c8491c6d000b2d7d2beb72d72937285aa1bceff18aa35d0c52158 +z aea7ae57bd1cabb049dd50b9d788f7ac8535c3c49c1bbdc1e6875674c02c6dea01aa60cb6924adc5de0523c1f1f7e715327b467b860c4ab3 + +x c010bfa3d130f868f2b975318139c2a847c69014b76164192b437fd7e26b892a5a2425670fe3e8fd9efdfa250f57579d1af2d24f8eb6ce92 +y bfe65616e278b6ce46b295600131bf5ea092451a87f6bc3adf1c86f2fe717351b073062ced1394a14051bb33f3874cca569aae8ba97605f9 +z 002a688defb7419aab07e0d07f08034aa7334bfa2f6ba7de4b26f9e4e2f915d9a9b01e3b22cf545c5eac3ff21bcf0ad3c35724c4e43fc999 + +x b2f21992b1f2155b7afc3a1d731b52c03cf14208e634b7da123888d652afcd919e9f5f0bea8b9986c71a7ba08fefe58ee0402d9a23b95f2c +y ae241fa6292c63f3c09301255a866825b39c9645512ea123486f9a873cacab567cd169c463fb1cf0417633a7055d831d23fd1d58dd42e726 +z 04cefaeb87c6b267b96839f81895e99a8954acc2940616b7cac8ed4e1603223b22cef54686907c9685a447f989926271bd430f4246767805 + +x b714b60b2614ab6ce63bf8eae621357f2e921f79de94982fcd5f524015db3faa52b15ff042733958fa202786f61bfed0b9fb5d5873619aec +y 0c99e1da4c747ad1a625321cf9359b1d823544d1eacfddc38e4bfd729ed2f9fb37760242340f7986843fb8fa0435bcb5cffdf11453caebcf +z ab7bd430d99f309b3f16c6ceedeb9961ac5cdba7f3c4ba6b3e1455cd760846ae1a3b5dae0e64c0d175e16e8bf1e6411beafd6b432097ae1c + +x c5425daf8f7089def2ff910e256d9496fc109d2698cf15dec1ce3f8116231969c5ed327626362b0658c60e74023a3cae5ef128fb5d27cad7 +y bc4e49fbf095f73894c4d623a210475cb7ba78ebbcbee8ab55a851162f789fb21e72de95afe4ddd45b90289f94f6d02b5f5a4b90c603ea31 +z 09f413b49eda91a55e3bbbea825c4d3a4556243bdb102d326c26ee6ae7aa79b6a67b54e076514d31fc35e6d46d436b82ff96dd6a9723e0a5 + +x 9aa20b4259efd3a701a63347181fa63f56f42a97ef836bf3aab88d30bbf28a91bbf713a0170024e6057e2281ac113f9b58cb13d63e850ea7 +y 09e7104367d8c0441d811ecc619af04def9236752c2d47bc508b0de3c3b29c74533d8eb9fee13279aed8d58247e4010206c697d9b72bab43 +z 91bbfafef1161363e424157bb684b5f16661f421c35624375a2d804df73fee1c68ba85e6181ef16c57a54cfe642d3d9952057cfc86596363 + +x e8ead9316aeb8f56d43418cd3bb1a71234c9e20b4a6dc1604ffdfdbcaacebe73b71d18c2c167544304d895d67e2daa2538a4ad0708cd9acf +y ff3603f0960bb7a92f2b7fbfe242b467164e0ca72e89bcab6c467b5391166d05c601b38de40643f04d5b50ff8ec62b18c69e9df74f01babe +z e9b3d641d3dfd8aca409990d596ef3aa1d7bd6641be404b5e2b6826919b8516ef11b6534dd601153b67c45d7ef667e0d72051010b8cbe010 + +x f37b41d9950036d560f02b8befd6f5c73096b8995850b9fc563291fba59fd994916744fbd4c1dd5d17a9e5ecd4ec4a658dfdae1ba7024bc6 +y eeda58ba400f16a946381fb11f0ac0db895957236bcc629ce9d1ea425eef8412ea73af488b97f1afa950736f26c3cace887417b699cc3410 +z 05a1e81e55f11f2c1ab80cdacfcc35eca63c6176ed8356606d60a6b847b05482a7f394b2492aecad6d58727dae298096048997650d3616b6 + +x 2bdb71a053047c4173718ce104e5b8671fbd61c59bfe8b20b890ceda15a69d24eec3775f4ce8a9c16d36e50626bc334e0fc1be492d800c06 +y b1ccd0dac33ac46b2709f9626ed70136f98dfbc705ad93ea8f1b325d644daf2c0180cb83bfdbb7398d3f58c0f6600056a174850b9db91ed4 +z 790ea1c58fc9b7d54b68937e960db731262f66fd9551f83528759c7db058eef7ec43acdb8c0cf287e0f68c462f5b33f86d4c393e90c6ed31 + +x 8f3fd6346c7f2dacf0d7cdb88a5bca3b222a895a07b169d0bcd0af0a9aa634876ae1a939262dd75bd12b5a97127155a015e00acac7d5cbc8 +y 0e9c03c5a06accdddd0d8613e41a00f2b586e297e366987e02e7536e0ca1b4c2c75fed619655acddffe8585c7a828432d90575731a4c8519 +z 81a3d26fcb1461ce12ca47a5a640ca496ca3a6c2234ad151bae95b9c8d0580c4a281bcd78fd72a7ed142013b98eed06d3cda9556ad8946af + +###-------------------------------------------------------------------------- +test condswap + +x db0be3ccfda1e2f8492bffb5d3344f1856ff1896b6a067d2fa064423ac5b05b669db1c9b51899c44a7f470be4173856d9aa3d1cd10cb8c9b +y 3005560f89232a97cebf6808e7493dd0f17e572556b53723b57faee51d8a0a45c7fb51aeb916f59c74ea6041494483b2fdce72189d1bd031 +m 0xffffffff +xx 3005560f89232a97cebf6808e7493dd0f17e572556b53723b57faee51d8a0a45c7fb51aeb916f59c74ea6041494483b2fdce72189d1bd031 +yy db0be3ccfda1e2f8492bffb5d3344f1856ff1896b6a067d2fa064423ac5b05b669db1c9b51899c44a7f470be4173856d9aa3d1cd10cb8c9b + +x ea009751f6a7045ec7d6d46b16cbe663f5a78fca3835626c79864bec4030443bb9349654d52b2edab92b8f4aa876a97e868aa6267a54e6b1 +y 8c6f864ef7f664f4985ed8c1ea0c63bd7ab355b5321c2712791b610a2dadddc90a65ca8d5c25ff199b011193796b08f96420934615103b7b +m 0x00000000 +xx ea009751f6a7045ec7d6d46b16cbe663f5a78fca3835626c79864bec4030443bb9349654d52b2edab92b8f4aa876a97e868aa6267a54e6b1 +yy 8c6f864ef7f664f4985ed8c1ea0c63bd7ab355b5321c2712791b610a2dadddc90a65ca8d5c25ff199b011193796b08f96420934615103b7b + +x dc3aa7d363058993cbdc54e95f3c972a2cea17cdf9370fccdfedfa1ba939ca35f762c5c6283f84348282fd56d83539804427eabe3bd6170d +y 8c47a0990eccf7300986232dbc8ee26e8996c3bb4b73663ec5525312bea8975221c9f49039840c181d042654a8c1806bb86702ac7d0b80f4 +m 0x00000000 +xx dc3aa7d363058993cbdc54e95f3c972a2cea17cdf9370fccdfedfa1ba939ca35f762c5c6283f84348282fd56d83539804427eabe3bd6170d +yy 8c47a0990eccf7300986232dbc8ee26e8996c3bb4b73663ec5525312bea8975221c9f49039840c181d042654a8c1806bb86702ac7d0b80f4 + +x 69b45538513af2148e0a2903539bc5e20fca4da447278bf5967091d2e781121080c14a41989f9ee5218c444d3a42989ba890c7be7faae5d3 +y 935eadbde0c571c29deb4d8404dd39a8cca177ced36c359abfa7a6cafe6075422e1d79cba8d81cdbdfa4a5144faf37b19ca22b2b40fe1a0b +m 0x00000000 +xx 69b45538513af2148e0a2903539bc5e20fca4da447278bf5967091d2e781121080c14a41989f9ee5218c444d3a42989ba890c7be7faae5d3 +yy 935eadbde0c571c29deb4d8404dd39a8cca177ced36c359abfa7a6cafe6075422e1d79cba8d81cdbdfa4a5144faf37b19ca22b2b40fe1a0b + +x de30072f175127ad4200a08099f4d0df0edfa40eb02e21a03c5628dcb2f70da8bce9ebbb1ebed2aca391e73a4114c06bcdbf762bf28777cf +y 5eaf3aecf1f7d1fd3b43be8fa450163c79f162b0c6eaa4b1ad39baaf3a4c36564e001c935fdce38e90789151beff0f3cc4fdfc2d86dcb587 +m 0x00000000 +xx de30072f175127ad4200a08099f4d0df0edfa40eb02e21a03c5628dcb2f70da8bce9ebbb1ebed2aca391e73a4114c06bcdbf762bf28777cf +yy 5eaf3aecf1f7d1fd3b43be8fa450163c79f162b0c6eaa4b1ad39baaf3a4c36564e001c935fdce38e90789151beff0f3cc4fdfc2d86dcb587 + +x 1bb20a5a05b190737ad6b2bc5bc2b9259fa7e36eac8f3032a7c56ed59c1510baaea32bba898b329b0c64fadbe454095b9f82b366bfae3d8b +y cf0a87c8befed020caf82f37b4c5f17d2aa9ff8ab75baa156cfe2716ac1eaabf9bc760c2ddcd66a9d02a8384ad1db9e8f857b151d126e0ef +m 0x00000000 +xx 1bb20a5a05b190737ad6b2bc5bc2b9259fa7e36eac8f3032a7c56ed59c1510baaea32bba898b329b0c64fadbe454095b9f82b366bfae3d8b +yy cf0a87c8befed020caf82f37b4c5f17d2aa9ff8ab75baa156cfe2716ac1eaabf9bc760c2ddcd66a9d02a8384ad1db9e8f857b151d126e0ef + +x c186531a219344dc485cd5dad6500616ac8e0653693168573cb9be590b02dfb1ddc5d87d27f2d9fa46ffeda955a6285b7ef2b9bf84825d06 +y 91f3be7eb2e0be38d92974d81be5126ef40d358f242d23aa4863fb16ba3e8844e02edc87c0206e211587886ed532da0ab148cfcf64e9b58d +m 0x00000000 +xx c186531a219344dc485cd5dad6500616ac8e0653693168573cb9be590b02dfb1ddc5d87d27f2d9fa46ffeda955a6285b7ef2b9bf84825d06 +yy 91f3be7eb2e0be38d92974d81be5126ef40d358f242d23aa4863fb16ba3e8844e02edc87c0206e211587886ed532da0ab148cfcf64e9b58d + +x 9f2476d6db424d19ee0cba4ed091da5b44ca63caf2f711eaeb7edcc75f49e0d0c367c1f2817b6bb39460f897432901064cabed7f6a03b1f0 +y 66e7dcd34d76a19e3285685112b7619f9a3557764a918922faf1370bb97c2b2fa845dd34662cfe7299ab702c68fd43b5f6f15a0af6625f2e +m 0xffffffff +xx 66e7dcd34d76a19e3285685112b7619f9a3557764a918922faf1370bb97c2b2fa845dd34662cfe7299ab702c68fd43b5f6f15a0af6625f2e +yy 9f2476d6db424d19ee0cba4ed091da5b44ca63caf2f711eaeb7edcc75f49e0d0c367c1f2817b6bb39460f897432901064cabed7f6a03b1f0 + +x f124ac31d304a29cdd94bdc0611c61064a7c5f09cf6847bccd52fc7a7b77ede73b42b1ef75f000de4361028e0fb63896f4ef5ad3bc1b9c90 +y 6629084a230c793086e469b9a01e052ad7a5680d6955667e0dfb19a250f447d9e238695400dc4ecaeefcebed44d374e57ec4e414f5629e63 +m 0x00000000 +xx f124ac31d304a29cdd94bdc0611c61064a7c5f09cf6847bccd52fc7a7b77ede73b42b1ef75f000de4361028e0fb63896f4ef5ad3bc1b9c90 +yy 6629084a230c793086e469b9a01e052ad7a5680d6955667e0dfb19a250f447d9e238695400dc4ecaeefcebed44d374e57ec4e414f5629e63 + +x b64f2952510827bef3d32ef6347251274c7241d9913268a7a6a5c360a4b29e7ed04d09a9ee5aa83235eaf8c0582b076b21d78b7062952773 +y 77897028a9a81fd54362a6085aa2c2fd6fdd44589f447c7310b9b3b5a29b54ed15c57e2c9fbff16f20129a4dbd43640a0d1037e277ca5c93 +m 0xffffffff +xx 77897028a9a81fd54362a6085aa2c2fd6fdd44589f447c7310b9b3b5a29b54ed15c57e2c9fbff16f20129a4dbd43640a0d1037e277ca5c93 +yy b64f2952510827bef3d32ef6347251274c7241d9913268a7a6a5c360a4b29e7ed04d09a9ee5aa83235eaf8c0582b076b21d78b7062952773 + +x 4d75efd204a66aed323456e6f55cb891ee7a31d739ae89726e0ea84532f9c740d1b647b117094fb85da2c62da04f3b9cb13db6b840046b7c +y 0afd07bb073a150e7b82711e1f42f7b0789af8192ea6b4e1b24a3d48de7f8b802875aca5a02a9d24deca0b58c895992a449d01026495b96c +m 0x00000000 +xx 4d75efd204a66aed323456e6f55cb891ee7a31d739ae89726e0ea84532f9c740d1b647b117094fb85da2c62da04f3b9cb13db6b840046b7c +yy 0afd07bb073a150e7b82711e1f42f7b0789af8192ea6b4e1b24a3d48de7f8b802875aca5a02a9d24deca0b58c895992a449d01026495b96c + +x 1ff4eb5f0280744f0c909cede8be29cccb8ae43e4626018a9a1d352a97d987678863ba34bdeb183bb5e9347e96760665f5881570778a2e19 +y 49cd390a9edc7fad6c84c2e44ce09e490161094d2dc6cad30759fbef10aa30e5aa6474bc46571188418f3e4a2b19ecfc379a1f94e3a44e48 +m 0x00000000 +xx 1ff4eb5f0280744f0c909cede8be29cccb8ae43e4626018a9a1d352a97d987678863ba34bdeb183bb5e9347e96760665f5881570778a2e19 +yy 49cd390a9edc7fad6c84c2e44ce09e490161094d2dc6cad30759fbef10aa30e5aa6474bc46571188418f3e4a2b19ecfc379a1f94e3a44e48 + +x e96c0316baf01c25ef8a41c02e99aa84c82f8eecd3249be268834afb5f7e95f0ad10bfad4160bb335c30ffd6a1090c91c57eb6ac7a7a5e66 +y 115e6f115bc4e19af60710f3dd821fb58cb680a32d6973eae9ea3e48f1928dc1d9f684a8c8de80affc59bc0fb342bb040f89d2d46b8ff8fc +m 0x00000000 +xx e96c0316baf01c25ef8a41c02e99aa84c82f8eecd3249be268834afb5f7e95f0ad10bfad4160bb335c30ffd6a1090c91c57eb6ac7a7a5e66 +yy 115e6f115bc4e19af60710f3dd821fb58cb680a32d6973eae9ea3e48f1928dc1d9f684a8c8de80affc59bc0fb342bb040f89d2d46b8ff8fc + +x 71bd8f5036da4c33f6940348ea448c2f9bccb152dab40b410bd695923a9e255b33aaf361055be4bb9a570e201dce784cc1ccb0f89faca85f +y 971b2f6569ddd9099a87ec4086d8218abcfbe81579f25f03634e471170a5088f48a6cfd09ed9e389ca37b780165c00b206304229135b6044 +m 0xffffffff +xx 971b2f6569ddd9099a87ec4086d8218abcfbe81579f25f03634e471170a5088f48a6cfd09ed9e389ca37b780165c00b206304229135b6044 +yy 71bd8f5036da4c33f6940348ea448c2f9bccb152dab40b410bd695923a9e255b33aaf361055be4bb9a570e201dce784cc1ccb0f89faca85f + +x 0f1165e19968f3e6159e9f7f843c1b849e5c3917af4e2798869112c6efca9993ed339c8495eec8c54b286820bf7befdc8ae344e4d309c077 +y 7ce5a2ae66b9bddd30c98d9aa9fcdd6ef90d244d10115d15cf5d81e9e389f6852b153a42c642447043fcfd278166b92c624508973449b0e8 +m 0xffffffff +xx 7ce5a2ae66b9bddd30c98d9aa9fcdd6ef90d244d10115d15cf5d81e9e389f6852b153a42c642447043fcfd278166b92c624508973449b0e8 +yy 0f1165e19968f3e6159e9f7f843c1b849e5c3917af4e2798869112c6efca9993ed339c8495eec8c54b286820bf7befdc8ae344e4d309c077 + +x 6dd07b4891d8f45ad1ee64da38383ec50d6f29634767607eca19a547cadc3c157ebe7d86a28d4d2fa2d40f2c5402d8b338cfd8d30aeadb6a +y 63da9a5a0cd51e58168ddb305c0e70a2f898279dae6394e1b3e1ef3a0763847d5d2f15be493114360204d037d7d3c3a9e746d27dcb544ded +m 0xffffffff +xx 63da9a5a0cd51e58168ddb305c0e70a2f898279dae6394e1b3e1ef3a0763847d5d2f15be493114360204d037d7d3c3a9e746d27dcb544ded +yy 6dd07b4891d8f45ad1ee64da38383ec50d6f29634767607eca19a547cadc3c157ebe7d86a28d4d2fa2d40f2c5402d8b338cfd8d30aeadb6a + +x d91228b648f75350d775432af35be9aa283e9729fcd3b689f0c7ee02ea67efd33493980ae5eec92ad6ab42ccd253a7aab5a62c26be275278 +y 07c5d1b4f9b8db88cd4187b1ae5e175bf703af12b26d066c1d55dd367569d3e23e3d0470f3c47e6761746ce7de39cf563500d026a6791980 +m 0xffffffff +xx 07c5d1b4f9b8db88cd4187b1ae5e175bf703af12b26d066c1d55dd367569d3e23e3d0470f3c47e6761746ce7de39cf563500d026a6791980 +yy d91228b648f75350d775432af35be9aa283e9729fcd3b689f0c7ee02ea67efd33493980ae5eec92ad6ab42ccd253a7aab5a62c26be275278 + +x f9e764e20657319802b53ee29df43b0d83d994d9049b9820fc0c31b631265c49f6613923a042eadce5902fb81753784ff5a9c0de2c4f6b12 +y 6ab2f8279e82aa65e8326e5c60bfa067e4967b3ea67d0369853282e5429736529a43eeee3fdf24ebbe5ca85b59647994fc99c90da83c6229 +m 0xffffffff +xx 6ab2f8279e82aa65e8326e5c60bfa067e4967b3ea67d0369853282e5429736529a43eeee3fdf24ebbe5ca85b59647994fc99c90da83c6229 +yy f9e764e20657319802b53ee29df43b0d83d994d9049b9820fc0c31b631265c49f6613923a042eadce5902fb81753784ff5a9c0de2c4f6b12 + +x 772289865ac905fac203e4654b258890ddb91cac71c6d2af3826e3acfebfa222c937b40069ce3a757e2ffd960b5821ed1ad54e4ad2e3c6fd +y 58dbf838ab81a754533c7f80fea48cbc981f724e4c150ddbb0afb5c711a8e21079446f77c427f7eb1892c096fa3eae5e2b070413611cd184 +m 0xffffffff +xx 58dbf838ab81a754533c7f80fea48cbc981f724e4c150ddbb0afb5c711a8e21079446f77c427f7eb1892c096fa3eae5e2b070413611cd184 +yy 772289865ac905fac203e4654b258890ddb91cac71c6d2af3826e3acfebfa222c937b40069ce3a757e2ffd960b5821ed1ad54e4ad2e3c6fd + +x 0bd6656d68c41bfc5389db274367f69191754919435ba58d2256017b5bc595d102c6f4f745b3ceb0c32bd0a6cdadded3a3dc925ef2b5c73c +y 1d903009c74d3d135a192bd42466cd28303f482626a7d10832f1f6eae72c3b051b0373e62300a71226011475034f0bfc6c9a65601bb83993 +m 0xffffffff +xx 1d903009c74d3d135a192bd42466cd28303f482626a7d10832f1f6eae72c3b051b0373e62300a71226011475034f0bfc6c9a65601bb83993 +yy 0bd6656d68c41bfc5389db274367f69191754919435ba58d2256017b5bc595d102c6f4f745b3ceb0c32bd0a6cdadded3a3dc925ef2b5c73c + +###-------------------------------------------------------------------------- +test mulconst + +x cb908747a1af81f52715ef8440aed06aaacbcd7903c99cdecef5ec54e7845bedaad6475028b0cbdb0d53b6eeb71843f900fefd398a083d5a +a -417895 +z e95e64fd1b2e2e79d1bfef5c96942eaf7ca5d40b1af774ed9c4ea2351c8ae81013f896bafd1f0b0e3a3c2ca3347c6cf88f988877af5e009b + +x 46b23d83c0848e79af947191cb76b087483beec6224af749e59c0c5ae27ff8abada31da895f8132aae0457f5ddc30d18a8d52046fbe6ef55 +a 384370 +z 31c9bf2f3bdfd3c1dc115db96d7a1c15e2a9ae67dfebccddc9408a0dcd147d9aa62ce4a55a2d6ad54542317756a08d6be3b959bf132624e2 + +x 53e19751de62909506bebf74411d359014ec4b6afbb8ce14eeed8a3938013f0fee6897e3cc3adcbc90d7df321c4caa1941d0e5909551335d +a -49682 +z 82fb902a8992ec1032a6837cec56189c45d1c1fdc47748e17dd9ecabc807a52eb537d6411f99f4d3b328e7ca76475924f90506a8adeb908e + +x 7ff3b9b3d8ee248a48d0c8d308d8c3658374acc92303143061a46656ae2b35094ed7b5b27d23366c0e42ee0a9471a4355d81cda0e4390348 +a 131908 +z adbb3dd21e634dfe2c41593c65249f03a048338037d4a107892df36f10e3ff68402d6f48e74bc7a7858f2c3650fd2a10acdfd4213850529e + +x f532f4f5ab5447b083ee4225246aaa4448696e4fc8bcf5b0ec1b52df88354e5327d7a3cf6e15db9945205968c275755ea3906a27437d29ed +a 383911 +z 1f42b3585a2553ab19b14639c3e3aca636d88053c70fb758962713783bcd824b729fb4d01dd56a344d991bf2d32a2967acf470b39bee88a6 + +x ef0e2a829097e50575eae6b1ad3fa10b8e417b0363654e0cb07a563a905c02e367c6f1ad7be1469b9f5295e3db0726853adffb820715f7d1 +a -226220 +z a7c5387af1b9f61f09d628feac1a050173021386775c9f534557b8841b812155325e3632eee7a2302ef8af0b4746575d6c2bcf3b29f674b0 + +x 3b4655b1c22542ca413f76bc24751a01cdab6b385b50301d67fd62ba31ad132150e38e12a849405112c4742e93b92849bd8b872c29edb2f9 +a -89924 +z b51c0dfa2407a89435fedbcfd7835b6e0849d8626995fd00974f44c49d794d3c5dc16028e9fdee45bbcd269035e8bdba695a6653028d4d59 + +x 48bdc2073bff25ae9bf7fcc368d65602a71e48c343bc7181c361331f108867d56c588f698aa5b91222f5dbbc859bce656f2607b053222fc7 +a 66432 +z e845dfe65d563884074ffeecaa325706df4a129b73b056cab6ad999588216d72525222ce00ce4d2ffb09fcf6f010a6eeb2eb753fefd44b47 + +x 98a26f23f83673a480076b2fc7ccfef07fbbe70c4160d5af638c345f7d17b00931efff543fd47b7b8b362a70657a458566ada4aefd1c5eaf +a 492192 +z 0ef483482255b5ca0f8338317f6eaf9c4fbf8bde8b8b04e26d2cdc0632186f1e62a9c3a1be23e8dc444ce50783135aeca614c884bdb77a30 + +x 6ebf7c4e06837120cc852a077945656046e64c2d88ce440bdfc8d38736a4d510a722bc8b0d225f11df0e704e4b04c48bf481da68fd1e150e +a -7098 +z 8d4e2cd12323b5744442fe4e4fc21748b344d7f94794398ec187f0f986ee743cd733a7a16bd4495818ab033103f020c794c988c5d2c1628a + +x 94e49f2bb473a7273abed94363c4dc3d13db159e3c3698a62ce5f321252aa03c7f63dd6eff9529c985f43abc7283d11140cb44ff6fd0f3d3 +a -392951 +z 58a606cdc1bf1d5646fc08c7a6b3336fbe532c823c70242ea7536cc6dcdde7c4f492306e39ac0fb88367e41d63a8305d69fab57a52c8c284 + +x cd262298ce3b73294bfb523c30206fc3771144890a0ebcef19e02e5085973a6aeefabdf8cb7186d57be38ee84b114b9a7a22556c0cf88df1 +a -237681 +z 7553420c53b255fb909d6e9008f043e7af25a2a9c29b177b830ff1ae6f6fdcb6aefb8386465f24634fb04c6078322ac691586f91cf7928bd + +x cc9bd2e72ce15dd50877f95812b65c65cf09b14e2817784a5b296c123e498c532362180a932a455b2ddb75e26335dbcb21eb94a90ebb6940 +a 246794 +z 8838e720b6e497d9cde9fbddc2333c13cb5bdbbbe5afe41ffd61f5035c8c4987fddb8036c25b0505765bf1a5aa369c6bf7723c65278584a8 + +x d8ab6b8f3523e98f49140e051c0b744bb0068d20f499c0763aa28ec1d1dd7e86356f357149c317376be96cd520b3ae04a2c4d468d74745e8 +a -360296 +z 4c0bc5f6fc52c6302b74c790d57ccc8fae59f2aeebb59c3393c56e70060f4d170ea41354f5040804a6e8dcb4a7c585ee71a6d90454e701de + +x 6036fbfb9fcc223a1776ec67c9424788aabe553a7d6a0472159edc747ebaf97e99f7263ece635ef0b702a3610aef32e17f59fae503e18d74 +a -5433 +z f6fa9a49b55077330fcda976a19ba7cfd98e44fa54044840df0ae9e19710193e684703f7fadbcbbc534e7be3adec0cae0d95ea414494f368 + +x a3433dfc89ec4d6d858bb5b018e2d474b7de7604ed4491957fe16453d3793740ef88136814f59b19ed3610252e74cbc3a36571d02e57913b +a 237641 +z 7a01a802b7a5aca44675887d9cf94d04d4893e2dc5d7474090cb32798fa370690255f57d18dce2a57126bb5883672b5a74a1c780f48f7bd8 + +x c17ecc6099e9630a4ec20f4199abe1c10d414f6d734014ada1e6f097090a2bb4e638fb52d9bf56080d77c2b535f52cb091cbaad3c65072e8 +a 517226 +z 708adeac4ff99cac4c3eb649d55276f58a7d21a0507af176a53893c567050d352af501a9c242baf53121e8b56f5679b175dc01538350b644 + +x 134263fd765e5f1da64900df5643c5241d4fa8a9e96ee59f01667b64f9122e85e995b90d4bf5d5fe9f68825dfa6edd19d8ce009270ae2984 +a 390674 +z 2ffbda7ccbeecd8dc4600965679146753c496d35bfa546e13edbbaa259065b024c8aaa3a17a3384f4f14d5ee01371ac55fb50a153b4ac1c0 + +x 54326fffef9f0fe1207a07c8ac063d64b3fe81528e005f857319a74da2c3423a552b05f8c465908b028a2dcf15cb7158c99a1d2bdfd890da +a -255467 +z e554e875e480c68c4fd780425ff8fb50f18bbafd0536a09489bc7cf197fdcb80dd4c7e31447a1a862066b6761ea39ea3b8c3002039c86b40 + +x 5c30f73ec3addb2d27e0e79579063f2d30fa9fb47c2b6a3a32553120a047cad83abc901e5a5b4a65f8e51144f7eb0abec9a4d105236b2618 +a -466309 +z 5ec894f6abe2d88971da11b982c3322d1f533a326057816f6273585bfa186a7f569ddf93c27e8e74719ddb515689d5935c56e6b86936f22b + +###-------------------------------------------------------------------------- +test mul + +## Easy tests. +x 03 +y 02 +z 06 + +x f7ffffdfffffff00000050000000000000a0ffffff03000090fffffffbffffafffffff00000020000000fdffff9ffffffff9ffff7fffffff +y ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff +z bfffff6f02000083ffff5f010000a1ffff9ffcffffc0ffff6ffdffffc4ffffff02000082ffff8f03000089ffff6ffaffff7cffffff000000 + +x f8ff7ffeff5f00001000000800000300000100a0ffffafffff130000fbffff0100000000e0ffffebffffffff7ffffffffeff1f0000080000 +y f7ff7f0200e0ffffefffff070000faff7ffefffffefffffffff7ffff040080ffff1fffff8ffffff7ffff0500800200000000f0fffffbffff +z 0a0100240020f5ff7ffdff4fffff4100003a00201400400300a8feff030180e6fffff9ff8f02003001002c0000f0ff9f0600d0f8ff670200 + +## Random tests. +x 94aa99eaba90c5eb2efd7101c8efeffc1e44c8fcd84ccb8ef27b9792ae12534c0a250e5400407177bd655e51c343f776a3fd26474da4dc74 +y 284a0f7df2d7d7c760cc57b1606625884c1643020230a9eecca7de6098f5338ddf9297daecae8a07e199494cb6db91c2c683566bf79545d2 +z 213a31ed7e494f470736ded872f2c4f3675562a7b42bf01ea246be0ecaae2a61ae500690df9f99ea9fa8e5e1b9ccf3614bc34148b7693c91 + +x a434abefb0de3c7f5e33f9230ead871bb3f06888c0d568b9a74fa32b676dc600fed2d54a042e1b97340852c4d6ef796a18561884d760d4ad +y 99d4c85f047d3dd8e530c50ae7d80815a30ec6ba820316f5da922cfa7a51ab45290ac2ab8a53082716a6d7f77ac5a285fac298eca4fd9c52 +z 97b2991fcc858d5667d3674484db9435ba71ab0c836c534efb823c123f9e94d0d3445257c55c73e8bd62f1d7acf1d75fea5eea669bfb9912 + +x fe9911abbe57f1ddd61acd062d59637b129a1571af65fb70169db0d8b12b498a66d1eefcf9c8cbea01179f113afef0ae192550828885689c +y e371e9a11f662e38caff28cf4cf5ca8cdfe4a8b99fa12a33765a22ae25506874fdcd85388ed406a955d293320e01957f119027ec4803c2a9 +z 171b49441f9891d927d2f6436eee1dc59e7872730be496638017b42151cdf00e9abb212bafc47c05a4e185bf7cf21ccd97b0c8ea426e4381 + +x 1c300df44d28406d070b10c1920e01ea8b9056d9e1d6f9704dbda3f6328c26a28e9e4aa07dc79e03c09c5639cf8b8c783c8b430b9d8c21a8 +y c565b0357a1e8aff3b3a6164ff34c9598a1c15a1551224fb38d25dfa3b0627c9d992dbd215910236aeeed23f4efd99640054b6648946346c +z f7871e06efb6f737cb4e04f708827092e94e3c70faee57f70096b9d674d0ac5b228824924bb705de49de9f9c0e834462093a9a5551fc7d5d + +x 9014dd22854f1f21fa1475d74eba669101c871c2a21ffd5d10f0792e3cc5d34f15b4735759575dda169e2dd868a5ae64dbeaa2a654cfde5c +y c6f59ecf6add5ff92813cd6f37de9c6f8d3ae9cd33e4f3236ff43127f463f297c3067493868adf7823bc285a3d609a57d9b0b841a9b628a1 +z cbebe67e30ed82acb0de699a5d874121257b78c2b0642583713b58fdcd089a6277a5c5e571538e4af9025dfc63cd78931be51780055dfb2f + +x c8fc23a431d744e45e8bcd2dd2ca612db40b26287970aa878a5cf6283c51b2bd4edb76f705f29bc3911a9aee8fb7272009520f3590ac4c4a +y c1015900ea58d6305b8b558c992bff50a8614843cd3d11274830dff6e1db405f8b268100fbc5e44c477cc2a9e83f825c7840e560fc2b2920 +z 6ecf49d92efb60a15a9de38ff37d3b23b339d889ad8b11cb332df260b9c49fd28b287a559fa5a5edf732b3bd1014711fb7d088a37cf6ef72 + +x daaea5c9549776d866be36a032027a65eb8325b1684d3c37cba068e69aad7d4f104ff47c14f669883cdef5dae9a0c7840379631ef97e6bc3 +y f8dc00891a9c55481a224309a8024ea257850b2bc62ab10bb5ea5b836776cd46994900d6656b7f7e0d9092fd824b16d20ea14528a0de7729 +z 83d3eb62429c2ece396cd7069dfa2985630da2fb0949b52f1df9231c82f32022543d4a2302241d0146b4db97f44ec5342b6444f463ad056f + +x 786f4ebb20161c96f93ffe3ee2b0cae50fc454d910b3fae4fbd8454b8ab7975c6cab8f6a1b593996b24b22603137a52ee732f9d19f9a6e43 +y d78d3df4f455c8f5d98baaa17200d4c94056e21768c4ca783188bf15c28dc86c581fd9c150f923f905becba19361ca94f7434d8a74744669 +z e857a2020e1877b50151772bcf06763285c1d8b2b5ffdb63e13ef4985ccc3b965fdb053305f16feea4a3ac0edad21423c80ef847181bdff7 + +x 6b48bf18ec4557e745cad3e106511bd5a9bbe136c77cf639745f891f54bb16c11e19770eb5112df8bb6755b97cb1e23c9c7efe589693764e +y 95c2a38f889c451f792c3d5d8b3237eed3f99e2b4857bfc48f75d7c0de3f293d2cfa7f97d65d75e0e3df633d84931973ac542ce07ba974b1 +z 2fdfb1146b569ac98b0811e600e2d8e578023024ed704f97c7f7d56a2b4a33ac6ec68d14f0789441a904d175fbf8b91603c532ecdffd27e4 + +x 1fbba059c333843e3cf0cff19bec99bd0cfc89c3b390200165680b742fe540b32042959022e7393c9e13ef7fa3f1dd5ac46595803210c536 +y c723bb3649b1d95647636abffd325e363931782f02002ad6d75d2082c980a7a2c5e1d51045880b36d4f62c16250faffcb2acb824d8d3d5d4 +z 97041eef8892ecaaa97c4effb8c69160b3878fd302bc5f0862bfe4894bf23193738d8dd95c9eee9539e23fff67243372b97f02c3a3934555 + +x 26f5bc0c2c49899690fa423478ab1cf7000be27609bf683896a6ce3f619510b061ca04debb6c64540e724d113cd4b8ff3485337851367700 +y b8540188b9ca77a82899c7fd26412dcbd6a3c9b45be595f63bce7426d7c16eb20c3a2dc86afe9064edc19840f75f05de828c276e98451ee5 +z d973580e88abb6c83defc009607082ffbdcae6ce9d577218580459711682f8708a15de9c62e3ca3b50e91a7bf5781deee152ac801a64fe81 + +x 6c044d6556abb8efdf5b180695293464a8bc4b9cab201822053c7295973ea0a8866425629cfff1d372a48f51dbc6a7f828691194c32c2c5c +y da28b84dfd48f206972fe282449991597bc7f0734916b6f7a253897fca2ccd6b80aa477cfd08549b6d25bd18932128e59889e2dcfaf76157 +z a599fabf997468487b9376500b58a51e0e00c86d9eac6f50157aa1017d99ac8b95e7842b36071a192784ef72433c06a1dd042990b71ffe8f + +x 50378c6ac56816962d428ea523a0cf87121fb3c53b37bac6d3a05fcbdfb8a5fb20aa014f1e1b01a3963534d403baeb7c436f72cf3cc5db58 +y 78901fa015c6f0d3e1072aa87d865579fa405615691a3f27945f9b1431ee8bce8ac9965a1f9b0f42ff10bc77c43cc93566eee9a9b79866ed +z 00127644003ed4b518f04abbd058a46015fb328883b92070bc5cf0fd98d7307dfabbc65f3e8551c622792efabe55f03953e498e360410790 + +x 5db2f6db35af2e1c84ab6832b967bf987cd03adea7113fb8806ce8fb3ffa426dc10997e13afcd39cf5cd65f65f8a09e650fad8e5f6ef2648 +y b063695bc97a18d6ccb0785ee4588951dcbee420ce8e37b25cce325352968015c94f9bb784f3a2bfa34c6a1edf710b63f139fff6d4f7b2f3 +z 999284a309482f67ab6460e73ad1ad267052b59fe50cd58a245e22079e2b50b119e312ff60a65037cf9faeaa259d22f689eaedd7924f1093 + +x d5baefaae7fc9000e0d55f287f740dfb1899ba6e9e36338959a16ac5e5f45442a37086b5519a0b439f38b129328aebf468dec4b59c89a249 +y 4febc8666dcf2b150faec9902a5f57e97275e7b122724c2b77d9b78655b455d424db93f859b8de6b09c4bad6d5ba68349c65c41caca67f8b +z 19e6ed86dc819e6b4368d196679328710f63bf1fcba6652265508b509ecd0e3e8b8bf17f8f1eeb361af107ef684a729a3635cb55de3f8605 + +x 9974be322a0f471cfe0855456104219d8037ca1cb5aacb9ff5da86a047ce159430cfd92f67e764244996668ac44d8d9787dc1b5754d215c1 +y 78c00f878fb41fdb0cd22c026881d5022fc470755e6261945b9bfcc3868f591f08288e4d64a65c9f3d0b05d3ab7f27d801aef29e5e98caf8 +z fd51b84f21b06377054dc879b8a176a7799951d5669486b210e4528b9f52bd60f88c2a068f722d85fa12761a4caf2f05bcdeecb7ed62646e + +x f4048d4a1602eeec43cdf20c3ac9f7b359935bae3648070276faf07a5c58fdf79771ba6c077ddeae47617971e2145f4960587637e7028822 +y 32635c7425108f5d19e35e4d91a4bdf3310bc884c9061d0697556ae25e17cd611e090c1179ca9a68225b283c8ab98a7b1e97508592c60c66 +z 8d6a91d016aaa7a0da03b06f5876ce8e8a71d1e5e5eb430d6c5ae16e1d6d9b61e77179b4f6fe43ce37cae27689983d41923f3b30e9d9f930 + +x 9023c019bf7ef6df45e0e44111903c622220bd3dde046679540302451d001e47a153b0ac7dcfb9831e2d262d8e27002197d9640900e4c1cc +y 1f5e2ca612ec6f14df4b528cc35001e763b9414a81381a1a3c7008c0cc525bdb00aea94ce2348f380dda43b5edf4fec7c8cf5ea2f5fec4b8 +z bf2c241efc180988232b83cda91e12dd0aec0d22ab68353c9841c4ea0547fd1b377fbca125f8cf92c426f8eb859f85a3853516ec104d9b6e + +x bbdecfafa9284e3067081b7d1bd7ce0e488829859628a8f6a38bc1a3ca6ec3130dbc1345b69abb7224b047fd3f2dadcf9cc11a8ec46a6436 +y 49a956ee69cdfecf29440d60fde9db1edd94619af97f625d45dc83c64994fe6c1ac858150cb526ca3c58a9fdc09d409ee3ed0b0cbcdb711c +z 7abfd47fdfcceb278c917afd059e335110bec63fea48dedf7f8275da8922201ea06be39e3d1bccea2d38f5eb7d7aa5ef4e6fe6792a9f0ce0 + +x a9483d4f0c94eac273adc392c3f425be610206683cbb6806dca47be3b54ad142fa2c54a7a473675556bcc8cfd50649af3c58d7a91e84b428 +y b986365aa08f088fe04aaaf2e00468af3fb41cda961b56ece5bedfd83cf9a0fb959ae70c23d9b27cd1eaf8b611d9e578aa0b9d899b81d5f1 +z 4af529627637ad3f3f1269319f4fd426d31e276287ee525d0c64974e55fca1cd58694eadf47e44dc3e843e01c36b22f9717067a907840ca1 + +###-------------------------------------------------------------------------- +test sqr + +## Easy tests. +x 03 +z 09 + +x f7ffffdfffffff00000050000000000000a0ffffff03000090fffffffbffffafffffff00000020000000fdffff9ffffffff9ffff7fffffff +z 8c000040010000f3ffffff040000f4000040120000ff0000800a000099000060060000030000000a0000e7010000180000290200800b0000 + +## Random tests. +x 776cf7ee39df23538f76e6be87ecbb1ed78477b858e3520f24b2b36f09a7dd61daf7bd5990af13c11b1419d8215eb69c30efc3917097797b +z 870001f8ff173e02ce682526a513ff99c6e9688cbec13839ecbf0fbc11d8f84f6cf53041b5bdcbc624f9787db9babe61cd477cb9395590d1 + +x 1e5ef8dd68207b3c3d3c670acee7ecb277ee6bc10be9fa3f3d800e1414bf402298ca443de6fd57ca899188c884a93d4b9c9d1b00a7c9ce44 +z 4a6d6da8002b6a0f3f5c3a9631254ccc62cf66c93279c4b77dda55d32514c8b388b543002f8055321c7195ce1fd26f51f48732e664cdc62f + +x e02eba6cd5ec1cc39ab92db439896520e50a5f9e9ed6d31ad37d00ebb2a54cb68f1c0ae537006ec2ffb14aaad2de16ff06194929b702b95a +z 95632fd74045a49782f6f9d0c86d554cf6efd07f9eef57d669828c77537d4c3a69138d755855640064f5e9bc8fbe0eca96fb04053f565431 + +x bad2a1348fc0b54791f9f2875009c8be2d30f14526fbbc22c439c1ae2b865436cd74f428766e4e676b795fe9333312f6334d4e4ec2378e26 +z d87a8f7ca45620b4646fad2c22792538bd16f37879dbc4d87c21cafa60c282f6415fde2fb6293a8b8a6e5b3901f88d75f9243023b68f41d3 + +x d6d221f2bf71eba62e49db570e13ca69f4a8a33543298619cda7c8d2524c9446b11ae7b7d301579f047565b7044b5286c2478896800ad992 +z fdb163312b884bc6d74c4c269011311388ead9c069884f48487f9ac0d62b39aa175e81976fb599716aaa68db4c02985a6f0ffe522b0fb21b + +x 20cc05120202e684981bce1db74af493d218ed8e0f5e76fad46bfeb98c69e504113b0eb91771c602cb422ae09846fbfef7c47afd09689277 +z b07d84ff34dc5f0cbcc60037400ee04ba09f34d1d7a0c6a80672a3f6c1da630681d4207ce1325d301b36f0acaafd7579a108646f5a26b755 + +x 72c4c3e4fcfd36389f558e0d4016f3f088145be47b2de85ee7ab963fcd8c7adf449d5b7c37ad8a32cf97ea9bde5c220fc896cf1b91633e19 +z 1e8f68736c3b259b661c0c1ec065a642e717f9e4d86003411b8e15ff89537d8e129c116d2f8a9e7e1b46879deedd66fa6ce2b60ab680cfb0 + +x 8c524f059e7ebcf3af3072dbd2f76ebc530adba6d26240c8675b5451d5558db648e7a61fefb1369cf2939ba1fadcf8e40385db5d57cacace +z a19188e6821f5cc2c53b7e59ae6f70e95fb929c0f282627ccfa2c6d9cb59dc871e9dcf3e2a8d6d66b7a6907d4d36c9de03c3d74325d8c1f1 + +x dd47eb6f4f68cd3a9abd6af401bd6f3c795d89474dd41a89025b24c8349a0de417c3676bb6ee36002d7c8ff6b4fb4491e693cfa617e079f8 +z 871f46c93dea48a0d937b3f1f724f66615daa9200f0b48cee01c3b20e4a05dd6ce01bd7b2713e096cc2bd1c5ce7ca0c075aed0fc1ef6fa51 + +x 577870fdb83454eed0711eb51d7bd91f9843769737566823e41d0668fad45c82fe069347769244af7230e6fbc40f5a71151279ae65e9893a +z efabd464218df4a490b9870d541c45e9b7ab29bae25d9e976539a553995ded0edc5610916883642a032eae4e96eb9e4e1443f747dec98135 + +x 8ba84194db2aad7b46005423b1251555ea931b933e0083fee76b9863fb528927f27a4a0617b8d75de306103b592a0fbd51b72bfbb051ee2d +z 3a29e940174d846df65d51070295f535a03e988fc401ef62f5dd2456cf52668390e61e7b6912186d6d5260f6d6977004003bb106abbdaf02 + +x 9f17e0943b4e39051abfd8f4512ef177fd5c368ebdf4b0af49df2e1d89e30c4e68ec474d81203964bfe9c1fecc1279e5e4f598ac97b48cb0 +z d794adb47cff3f7666dd0a934896015e59f278d9b1d6dc7a06328da96d6e6520670598129b7e1b26f9537216364199cf5c0010f23692ec90 + +x a6b51625066e4cccb7d45dff5b182e2a6bf4b1cce7090a187d38dd39f08afad6f868c0277bf70d5fb88b6e67432526e4feb39ae707e34990 +z 67315efb85e16a1e97130092cc351759d9c18261845329f63eba1e77d91ad2c7df51ffa50b655de81bc807ea2b3e137214a2b08b400f2b7a + +x 28a0fe53cf73a0419fdb4cb493c6425be8aa812c3693411816c90621097a9d5687feb16ebf874a30ec849297742b7aab5921427d7b474190 +z 69300770a5bc2c9c599431e5f879ef3f3ec065e3a2cfe82e3499018add58acada581e9e81d40799fc74674b9721da018a64138519abdb108 + +x fad58259395fd5bbcfca35b095253a3a121b62f1694e14cd9e2f85bd08e8a15d1dff98e3b81eeec678821a1ee9d6192c8351bde45ce0581f +z bee7e0d6d4de419981ba2aa3964adfc7545e21b72b65c774b2029c22e06f251cebf04cdffd23e2051b57f986cbf7e56f047050714a275e72 + +x 91e548171a8136d2d26e6bea02cb16ec9591e9cd5b913184b22b43d1029bdb214ef737f6e45f473f7d95b8fde075645c3b0c2dd2bd224278 +z abe2936ecf2ac3012455dcac906f691f2d96490539c9621658fd7f66790bbfe0d2df07165ea80e0c3282642d45b63b7db476b53e4f94f1c5 + +x a52c855daa9ede16ea8de7c681436d5d31eda6ca5b441f972e5cf5639a1c56f689fcb411965271853de2893f22b81d7d0facafdb49292e39 +z 382480e92d44199fe5f7c357ad2e5a7277beab1a3055d48e679516151ca85ee3cb498b172087d588738daac2ec1da9638552d76be97626ad + +x c65888cdc1a575fc9a06dce8800607f56fe88839948b7e4e2713aae44b0ae6b7c6b68786b11b430d22766e9e4d76af118a972729c67c06b7 +z 31311e4ff9600089b533cdac6c05de3ddfe6a450ee7fc90cde1bb297e2deb750336ac3ed2f6fa9b88ece846be6f6aeb392f6753eb6fa475e + +x a61c81d621df61ece4b7274f63ae4e9f2e2df1d603fc9303ee361962b2d70bd783ff1b5d8f3ed27f17e7773b2b1c85af7fbd70387bdef5d3 +z a014ef20adc291c0238be3759ceb9f9645524b961761c8a991ce67efbddda568359fe36e762980d75a58a7ba10b803c9f883fe4d2239a08b + +x 96ced952366c324c5fccd48ac5d475cc1944e7e455dc093f0d9680d6d6abf1e45c76a286ac46acb4de061b9eb673a2d3124e6c3b921ad71f +z 6debaeff6a7d2bb2c1389cb3338fc87b2a32e651ecb8d43fc012efc9b9c59c79487b742f0b30d0b64ac283af0d3b877102c6a7ff0f606eb9 + +###-------------------------------------------------------------------------- +test inv + +x d665678f17043846f953fb09c88295d7fd0a53bc70ec7d396aff56e7dfa376f3a338f0da0af9e07b66d3ff7443e3829b541bd667201999d4 +z 6839ab730bf666c6ca987d254d83bf32b981b466c147f04b823981da75e12c9ded469a0a462861a987c13f05739f47596401fec25a5eee5c + +x bb8d567f6163a92603a388405121bd58abfcf05c596bf0624bf65b6a8fe03e6940648382fe01e5ab58e37ce235f4acbfb9e02624001c49da +z 3f60d0fa0036da2db915e232bd841d09f006d4ba018c1d268af86d36990579d669ee63393b95c202645dcb1225fe9e64d14270905e63eb79 + +x d456692d8e00bf9cd86d22a9f4ad9e9879e6298274854ae82729ebbdb0cc46877caeb381506dbb097b10c180d615661189da65d431e3003b +z 6e0f5a173fb60be882a2b570200515dc7ad473e2192470ba89e6dda6cfdd6ff77026a1d76acdded7b5881a54d68605140a4ffceae70906d5 + +x 359ab073b7465de1358a5772aef79db09118541c062421cb30a972525a351f16b5545daed5f9ce8e91a283818df6cdbf443831fbe5f3e848 +z 2b0ea74e6f4533498eb3f34247a9674f3a2cf2ab0e4fde65ff11b0d1e756430bc5452ca4b85bd3a1f10f6e4e3b1874df8d19f390a9021757 + +x 3509fb8b7688f354738d4a8ca4091f66c880db794aacec6115e675090394ca77e1c83b955aaf4d8e75c6e4e9200be1ce5693532a561d970d +z cafa18317193054cff7884bada249422ba889c19693d66610fb774fb4bdfeac0e67a5ba6f84ace126c125c46b4cfd627ee777e231a6ffc1f + +x 42e2babc095d88b61caa8883e91fd045106db9c4eeb4d945703c1dee3229c58869e21f73909ae2f3c4437d301a2a3724d67f6ad310f63835 +z 28c43a594b6471412f504dc10fd79d2c04ec029a7723cfa0a90aef036991f1b56cf156e2cbc7533671086edb54036e9f4ddc9bfe2e3ffcda + +x 9c01d006213bcfda413517ec815e8cebc06707f5649398a9d14a5d64754375c1ded8aaefd838e8eba84746de07a0f9b32caa2325c4c8e540 +z 0a3b64374ac2149d602a9f0ee4fcf6d814c476f451531a086b04b0dd598287b1758f77780b7de08573326a9767e816309d871fb1962bb1a4 + +x 7bbd8a2de4bd2ffee4e93d0dd2fa9c5d4abcf9ab86c097921fe7d603b7ffdd07006c7d79d1a10267edce9b3069b134bed727c8f0ed1aca13 +z c909ffafbcc09a96723b9afba8ec0d00d5ce0c9d85de3c1e4de24cf44fb934bd0d2397b380885b7419cbbeac339fc85e2161f08c2f3515d7 + +x 6a64650ccf103604c3b030415f7114c88c7094fbd0fd2f2b6b907a27fe104ef4e0684c17ff9f26f15eee5e7442e679ecad3e49a0629cb5c3 +z 9db77e47433997640b4c0916c5123e8a4d9c7c0bcd12b2dafccbababd6c9dbc3f4ec7991ea68b3ad4ffc6f0be4920764c65d98bdeba8a811 + +x c3823c71f6c0f3679cb9c776e437e718f856c8fde038418942d062423113352aeb60ab84138f2bf73f268386cab0f2a1419660e966c24187 +z 558bff4fffa85d6f67ad44938f5b4473d250a87a120af9ff645a7db37a43808abe30c19c90bac94adb190840078214518e189d6c9fc5bef2 + +x 44bd920b0eaf47695f93d063cd85c43c58470c23796f4a106b298d5f2b091210d103e9575c369bb0be66b2323d89cc29602a8071697931c6 +z 67464f2dab3a95c9ac7c783017105df7d561d7ae499ad89c4698da2c0710a1654c89966a7bd30d2d5c0511ed9f020309cde84cecd66be8d0 + +x a6b12fc35e62532ea7c1fd49dd834bb7957da914ec3daf2e4f446b54916d016054cb59ffd4e3d9eecd4a18b08033ee8d9ff84db072cc4f86 +z cc70960f0bb743da1b23d11eb87530a820484a861abd68d2ed7079b487d88481d915b1b34c29d9938b5fa54d05c75cb1aebf0b722a6770b6 + +x 1773dc978cd9f94186b83fd5e10a456b48058acd9e3bbacbecee2cfd0f8303c64721ca64c2913d57764336ea055700c2fcafc60d9f4b817e +z 49e443096eb28c167ee62c63bfe4079418fa8e7f9e58757e13327680890b02ce7c9e5bbbc51366e0b3f5315edc456b6f65a09ea1b1a24438 + +x 552158406db36accc32edde2f0ce46e23a1d406f60e54ca6a789386df36a57434c826c9586c4b371df3179f675e5956fe7dc3022f785d9e0 +z e0025a1007d3dff5e44947a0292bee8db5abbd1a0fca1d3ab0a64a37925396cd96c21af54d36656eb0b60c63fd5651622ec5487d53f976e4 + +x 6b006d36f60750bb5c59f6eb31e2efe6098ab67de7a7a8a27201652380a295c408ec78351c2a799d62227dffd4731b7605e5c462dce2c1e8 +z 21785aae5f73da711f6144894728627824b685fac3d95068a9d0c4e0ee058301a8953322a5ee5be75452164a55477f1a987103a718bf98ca + +x 700cb76911e718ce8829f8d767c53e333dd2f7f20d2c020d1da3cc9ce96b9f6c7aad67450d5aab8f8c60e8ad77d4b5fdb86fae92a0ac30fe +z 257f202b457f19f27ceed047e6778204c2b71646fcc96e19c6f07518780bb5b1c456fd6e93ce2f1cb0aea1a225137511dc71e446c1fe22c3 + +x 0c909e0326649d4d375452c5b233a86e90b0fa88b20aa54e02685edd02b70aa022ed8af31e994b70b20101a5cfd8e16ba53c702840b4a16b +z 98c41073ea843b4b5ad6b0589699f48a1576e3d834f8e595b8859069b71bf5e16126aa93b20259ff0a03976ff6d7f78239ec1059f8cf1193 + +x 4529761361781e67037eae69c5ca9977b1e21468834eb83cd369471e5092249015cd263563bff9348a0f51e4a8517e27236ed1ecfe30a780 +z e20d5896be18bb273bb0ba84f6c070de45378bac6d793685e654764e5aa847d48403a68560b48dcb12573ac737366ae701072300615b4659 + +x 6fae83f7eadeaca22b6781f400b01f9de186b12e31fdf56e0ebe98a8420baacf5069ffdf26d0215c16b64027dd69ff29709a64cfe8f52dcb +z daa266a02c4500d989670eb63ab78219892d9c1ca2e17f4b5200cf1d920cfece5e80050be77f81a616de840bf19c23835ed17d57aeeea0f5 + +x 23ca16e8b4c15f8f2b216441d851368d185a7f8587f398b0cf775875678241094538708da0cb2260c5e056b59c003c30c8f84f5088d0c99c +z 9de1360b4718fc762e6ffab46827c5e4672a77d797aa608b31c132d1ad8138e7a64ba1f4278a07a6088f8cec9a01ea9bc1427c55241433c5 + +###-------------------------------------------------------------------------- +test sub-mulc-add-sub-mul + +u 07ebfe324f64b54e938951a1e437bab4d35c2bbf5f210c5d78ca2b4eb7ef9c3dab61724be4fa7c2e43086b58db7e961f62a44b029f9901d5 +v d44920bba642b8162d1c3e956e060bbe6f15484298c2ec55575ee378556b0e8826f627bebda963b7d4d9f1c768a49cd408957105d3c6008a +a -41997 +w e3647583d41ee4e813045d4f7a8b53af084c1dfeab8db93472810e8c54d253a2c100a6fc341bd92223341150d363f00f1c2bbb9ff9f8e7ca +x d61c770618adfc42ef3ac4272dfae86a674f8ae4c273d26ad7b9a29943c4740e0c9535812b9ef0d17fb4bfcc77bf60646aa96a11c29035a3 +y 76c496c2c798e23c657eb80c44940229ba88f21bcacb21cb6b4cdc8b93d10832f3c4d31819fbeacb6c5a516c7889f0e639abc29ec4d7b604 +z 5a94d8487539381061d764a3806e31e1b2add772d2f9cb9c4fb96336f7b36534a9a0f7caf30b7e086c875670a0d568f895502983b1dec2ef + +u e1792f9e9c7b70293e041a9059df95bcac07b4112f25d35375ade1794660a0a10c520adf06fd477c79a170ab88108e4b74bc47ede8ddc0a4 +v 6cffa5fd3f07f203fcf08c399690b793a152e65aa99c6f9b465d39861c3c46691b635cd02c9e77083ecdee73a54aa1aab5ce6044cb2cb8d8 +a 23228 +w 31cd1c1937619b8fe711d22912104fd03fcfa3f14f81f3bc7ec9839c5440836d7c9b92158c818933aa614f9a085f9a1c18d71dd11d09a6db +x 2386136ccd81814300b5f3fa148c4025e6d7a2d9da344e56b42811deaa3d4ecbd5365f91d941d7bab20b305ac6dd0457a4b81cc611bb5f11 +y 16bf2b1e10c77597990088a8df91150a6e7b6c3008e6584909b2f7184358abf6b59674e210aeec3219a5202440139aecde4a4b6e0f46dbaa +z dd373d5908b408e51e3c6f8da1c439f845d40467057a34a96cd53680661b329f073d0bfe6af98543d5d38c3d0476c19d20c54226e7bf8d7c + +u fe6d00268bafd5878e0a4ddebad8dff25399a1d18e69f94b471029058e9712b98263d88b4dea5d08d8fe70b3a62ba2d136c2c2713ca809ea +v 12be184341bbd7ab5a668f3c3e4b13a60c70cd4e1f229f90901be24a285f3ff0b7391aee82529076c14232f61a11b6a8edffd56af603a25b +a -252008 +w 178e5309ab3a578b8b09149da9539d93309c5214b61e3c045034847354f59d58fee27e31dfcf5d5daa24b5a605686b468a3db727583709d4 +x 8da5b2f4c39e442c729a09cf04405136c55cf7b76fbe949ec3b34fb17b2edabcac44f4b4a19afb58c9d86eb87a0c58cff2cf196e6cac7da2 +y 3b0be5158a7c13a6c71455025ea5b4466eaa321956fa785f9b74872532e3767d796da94ac47e6d25a368ea1ac79c44fda8d2e13edae5c219 +z 7ad75999f1bd89b130fa03274247b36b2c2684163097d46deb852083b5fab0e8755d2150dcd2ee563757f05eb1d132df284ccf818cd56b9c + +u e4ef0519fc7af554a4a348cfcea95c6c18752f4a35a946b7d2ad1e6aa77d64ec4012eea4faead2d91c66b0d57198b19317a79e136a98caf9 +v 008c72ff456f0f941781020ce6387d8065772af7c68955668a7cb05b53f00960f15fc463029a2e2a353a2fd3bc43790a847ea35c75d6cd26 +a 287411 +w 5ee722a21955b3bec9ed5f151686af9da9d3f5e6491e3d9a8d82237b1e3dddb58b827264ab5a1aca3eb8c1de7922b59744567e0467a4357f +x 9381ebf793f7b3f523f4621e934217ba463f96279ce2e7d165fc00ea037b20254948132dd2f0481ad9816e1f66da64d081e4d24866094af9 +y 62e4648d4716c6e0f99357c8c099c4988cfec4fa21873b7928350f174679f59629a54d78bc8d239800709a585d4890fb2b634f68ec13cd78 +z 850e54cf9388bdaf3de63c3e73823c0f39f0b9bf15a9f0262f24c828d2fc8cd7d1ac939193804fac3d92467e26ba5e57d1dc4f8664a270af + +u 5f3811d6b8277fd93a197bf4f3dec4bf4dd5fc6a0ac92ee3d0e64ae48fa9e1373cfd63da945db924bbac41a2b78f6819ccdf2820b1a3c4ff +v ee669edf4430678ff1190be8e39c06dd00cd9982ab5b625e5a6814ec456f68f9467f1f38519f4bcb392772479ba553060391752ab4fc70aa +a -254559 +w 3d11820f867d39b2b1169030c24a9307eb387f44ee0fc8d53a946e56065e8cf9af6069c9c8099de1565f3d491c33248965ebf941987ade48 +x 9582a93732bb52eba39d81c161dd0a996b50dadb13b4eb54085ecb9e86117ed25cb7c78d1a5cc3807a97d740710c2fbf65f97e8de3591163 +y 501c2ca79204d22e6c52d32d405310853e7e29da884c0f14782e9029929751821f81a9493c8dd76e582bb48465ce5b40d7c5e398322ceada +z dcdc428d085f7548c99d963af7b8af997c1503307d75e298efbfc042d425d385a6b7321d86d5af13809ed3ec6bc5d96afcd026d08caeaa30 + +u d17c198598d3b5188e5807c445976b769d458ca952a7b99da4b19ffa3b35b6100bd3605136143912640e402a7cb91675e61527244844409b +v 9cac226e58f5ffbc41bb82b769ed12d061eef4d2d0369eb12724bcd4db6a1ff85f22d6b25003cbea0308a1b7dcce1450283d4e96ac8d4b8c +a 516083 +w 9f92e7a68af5c7737f3f3e959d2b55230ca11e0dd467bd52a20b91816ce61ac7fa7059934c7a952e43058ff4f277170ec5ecc4cab51baef5 +x d4fb3628a45e2290c7fd201ca434ef83911ac2687218605782b3cdca577e692a389756e6b9a0891311727d623fe8ea601fb13efe238adee0 +y ce572b3cdd011749634a577c727aa4516d00c4236cdf3b4664c2be35d3efe7e0b140b5ef2d4a0339a8a29eb26025e60e7d166913251966be +z 790d7ef8990c44fd271d5a41c55a6d552f60fd8980c1c3b91919fdd5e291c75b0a0cbc4224dfd2ce93de2eef53249f3d9d0955f05b4cefaa + +u 396fe89631a66fcf4368600d3a8cbfa6fc903cc8d157f13ac0e4a569436c3230c0a9319a55ebb7e61d428e74b8ce740e973ee5d2b0a99a61 +v f644b35fe8d9bd57a0e6837ef03d889df2248a06a0e52a9cdc80307cf68c496f34aa82f246b8d6e040d166ffa1920b7d921938bb33f8e8a0 +a -339102 +w 716c673c21cd0d92d86f8060beba37c65b7d9eb8b1d4f8aa5665478278ea5c3a2a2c4f606aa179bc8b38f4f37b3e077959ac7c8c81a5fba2 +x 6379d7843800b16ad06ff70511c7ff656fc93ff95a05617b4adf7e2b6810cf2cf81dfd6b0c7d478d52f2f4989a13a3ccbc3a4e30f85a3279 +y 5b982eda7d33ef68c0d94400610744b91572443614a128bc90011a953bc9422910640047809049a513c413b4390a09395da3de6958c44b64 +z 91cf825bde194c05cadbb9dcee5f08f152d2bacabc144b4ee498b82ddf4074846ccc75d366184ee29bd322deaf99d6ae81563cc2e7b2e98d + +u b8bb334fbe75e81a417ef59e14b52898e34dcc8bca4bb2caa987dc31950a9afa4dd356735dd163eba9073056a2e7f259f1485ef37acf8c24 +v 0e872ffa891f664be01868170c452c25cbd41dd0e4df0a66c0ed67dfd3d007c25c50e4b0615450906c69788080546b9a4ad425402c422580 +a 287059 +w 52356b0443301992c676f6cfa7eeca79d586324bbb5f8aa71163b89d863ffc7879e55c363ce260fd6ab160e18ef0921d81a4d634799fe816 +x 35be6d14d3dc696bb20c90de43c7e08b2427ffc9c63a5c37767ee6756894b6d94c748e9d2c4d8519cbdc2efaa215874bb1923cf7aa5a826c +y 8db5fd04e45f9f93c7a2a2e238c7f001fd7c059d02fce693340c106ebb98d7f6f3029d3e820e2e3e912901c33c3dfce56d68a7c42a2f2e0a +z 29ff4f6533b4292d0e8f2a7abbd1269d1455d8ec34cadca9df875d544ba10395c36d1e750fb66ff0a9d97a92538a63ab48db8583fa6ebd5f + +u 74dfa3166dee585d6d4c5f310259a6f9a407e5c520559f22a3f290733d2f0ba8a276d46820bc73f9231fe25dcc8e9c2e2542eda5024180ed +v 50881f8d2fac3278cadb483b7db6e179306b6e967f8fbdb53f70f443ba9f1b1073921a0a1f46c8833856e6a0ead7ab6f445abf833d2550f7 +a -430161 +w 10b16716f590c13b435ce912fd4adb5dcb4982d8e0302dfccff5f9d388efaae716e8d9e2915de30d365a04468f4bec0f4489d81c0e159bd0 +x b4e67998a7579734cf8f0fc281bb29e1c3dd4dd4d9c1434e830d4d093ea2b908137dad647ab349c5858d1b3ce20f7378546033114dc0fa68 +y 76a10a58f6136ec6b73d96ed1d506b758ddf6f54326f7b2a12d28dec9ed880dac2d16f2f57004c7df846ffb4c5c7de814a0245668df0e804 +z 33216663bc217e49c81d64e3957f3a16452193b677c68f3df80315c7496995a752c7f42807d22e6a23ad2f5568ada163ba168cd1ff3631c0 + +u c047f2b5077afcb0c246abb9104309be15f2c2da8e703e74459d34281992fbbfb95b1012067415c5b17650d10f5d2d12b84c3c825068b881 +v 831adf8c6481178176f11f1d7010fa4b51c6e30ae8a9aec3a748a47bad643ff69cc8e1ba47bf9d33183de1c1220e989c58d6b23e8a602ddd +a -445266 +w db32546436b5d585cd4fefcdf8affd7c467c31699787dedd133f205641fcf74ee246a5f62dee25eefb54091b5dd0cb4dc7cfad9cc68bb9cb +x 9ea3da4650bbc07d7cefbff97a9bebe5aa932772ce0e47a4bdfaab1be5457f652f9882d8e4ca286b7bce092a4fe93b1c0473a2d5d33d92d3 +y a8eeaf02c9e281f2522def4792beff7382ae509316b80ca3e70b36c080706f9cc8589518dd9b27e61c3f3e28c8608524bc201076d6ae2fcb +z 463c925f11987399440da6a502b87ee798b2dfc37f012951af57dda87651de7bb96c2c30890e6b65771e70ee08bf41e2bde696dfcb177e83 + +u 63428356e8b4c5147870a0e653866093d5ca20a691524e3adba1c95af70fc706fdb420391c230dcb70cbad21f028b03e7554efac7bc8bed6 +v e99ca8f8dfe11c545b49031f68a605229adac19568b5cfb9b02b9721416c225179968b5583d0588ead12790c5df7c13bae466f934e997b4e +a -445574 +w 7ace55b2ba3365a01a872ef5882a8d47518fec37bd816d809d4716301a7b6811926eb5aa593fb2c852ae2455fa42e92be1038d96ebf31966 +x db9244d18540fb524ec9455f493b570aba16ee4f4491247fa18efe63a43c70e533ad6660f64e836675bd788113993836c43a3c5868efe068 +y 8cc4affd9631c4ff75313f43588d977f24b58a0ef1c3275b7c142e6113f20d72fe974f11c9f7cf3dc176e1799dcb4230d5bb138ddee2eb34 +z 179440042f537fcd021678f32a1346547ac1a4aa5dc3e5bed329c543ec35058efa16af2ca066ffb7087a3daf68345aa3a0a21c6133fd3a59 + +u 993bb02c2ae6974f6988293ce6eae32f520758329e80ae242801f45937baed48cb9bbc111731aea52883ca30286b7593746e6522fc3ccd54 +v 2bbbb81c8e51356355a1e49ebc1c6e160119eca0df8c07d171783665c9d96af7164e6bd7384002ed5c19f531bda705b90e06130bfcb2ad17 +a -159409 +w 6b3eb1b9dac2b8f6d86a0d983bd2b36a98c760ecf5f4aa30e22726e8048cc2e633a7a7bdc862d6bb02fcb0d9e854ac9dce8cb9982645ba44 +x fba6ac4753539d9dea1190d160994937af74be3f73856e56dd7ef4fffd1f6e2d99f1466fff7ec4bacd115f4e1f8708adb8c9afa7b17ee887 +y 7f28c3d4526328a9f03cbfb3a0b04fc2aac564effcdbcedfd61a160d0499c83742255e86764c344887a93f7f1851903372e40d7034b16f03 +z 2bec5989a2f2fc934dc0e673f07f0ea7ebade4d4bdf7bf472f7e779a716dbc4aa01771bd1dcc634780b0da41389c108a76fc67235e028142 + +u 96ab5a1f5b6cffe08fbe3118d7bf2d09e6da8dfdb0ce69cae1c2d3fe71864db59befd7e252410d04a858ef680a754b2d42f7f4ab7cd38e0d +v 673d469ae9193bb79aace5d641041c94b81f6f9a9d12e5a05db86674899ed5650b8d4d30bb00f2b51b0261245dd3a2e18a10f8109cae1535 +a 197264 +w 83f7aaef3c944d9d6ef3c329224067a204f738f3625488ba01845e31fa07dda26e08a4e395687b322f594fed860bf1597ab33536c5f24c53 +x 9bdc4e2e4e412b65af636a24480a40ab73df53fb209619044317f90df9bba10e5892aa502ee86e1039a8547a4e119caa359e8095ef0f5827 +y 659ea4924522edb2aa50430f9bf5ba3112c60af504dd290215a52c8bc275fa8fe0042348811a7cacd0d8bbf95255a547ae9b82db70326b25 +z a28bd6727521f46a3ab3ac32a3452c03b7ceca3c06c4e5f260c1868935269b8cbeb3d303cc6df3faee2595788af6f24a52ef8237763793a1 + +u a0de95d94e3506ed563b974d07454fd347f7b37aa1e9453e0145d23e1867f2aea78434ace37877022343cad84d9100c7683b33c115014903 +v ceeac84a960af7e749645352ddbd4a9f7fd77e96268ed8548e4247b6084e13a193233ba02c49da24c89f2a62ed50029ab38eb6566167aaab +a -5830 +w 8568f4c8837fbef756a3c03ee6a59f7ce0b5ffe370afb5c18545e4fe88eae49c65c642494e1cba91c4eb8b2fa94df6ca22b21d3e7b717f3a +x 70170f374d567a159bd8e354eceee6aacbedfcf9a2be6b530808152a96e93a301518f0042baecaf90170bdc4cc8c2e1003bfe737cd258929 +y cfa4cd159f5793a1833bfdb97261c204d3a80a01e1488ce8c628e68225bbcffa785093267eb3f75702e70b6abef59bc0a223ecfa09aac356 +z 7302a30f89bf3163baf814605772b0ca175aec6a030e53a2677c49351d88f1c095a1974e1dabcf5859c206f4bd3e932f7973766e81e0c278 + +u c297bf2bf6e64d4446a2e5d1c6448f5881c5973ccf6e75730dcf2bb74096e603a354461e02e818a94ace1f47053d23710719135cdd366d92 +v 8966ea0a08b7f43706340232c68a264c54b4e609ad8c901d0c0768c2aa5660434e5d4ce7510883238b17a8c92f8013d2488730d3a28ca291 +a -266784 +w c52a9e11dce1938ffb862357a9a696ee72c9fe18f7163d29052c949b4ac0fa151052dffa3546cdefdef598c28ebcc620d064783e8ee20413 +x 04f0bdf761a2cfebb822a12bb44b2def0906ae99cf84e7bff6d033e4082c2fed1961942288b0e2beb11a0e96db8a5037fa61631cd89896e4 +y add0f3d532987482db8148a8ef3724e27ad497bdcd804686114acb3a86e4e561001a7af6420bbeef57b77bf8444c4b978e5cd136083d9118 +z efda70e401d9e5beea539fb3ce7a145bfc90422e049387f222db53edae81078046fb1e2db538ebd7ba36ff5509691c83ef9c51f3581edc2e + +u 06768f69843008554828e6665685231b32e60fa878cdc11536819fb04874df4c6f9023b356f1cfb03a1706d04f472f1f1cba2148e161f936 +v 61d686b96bd02a99efe67123f3962e318ce9836b1ed0b7a39ae98483f38efa78a89063badbf97325b4743b2342647ed8a44a164e76328781 +a -301528 +w f8987e1314d3a3fa7ed1784fd04e4b381e9bbee6a785400e51d66402bd95c13de03e4a8213fbcbcec493f0ab8f3aef54794d8baeb9579b57 +x dee30a4b1359ae1459b790e8bedbce16eef2e299082dd2a07e46063c79af11524e438740af78d161afbd5b410888ab9f64eb4129dd1caadf +y cc52f548a25b964b2556be59c5243b63a323701d696d8d3f866be512554227b8aa3567960aec684ba50701be5528f188a9bcba490517949f +z bf88a0bbfcf8d048525ba4b7f64988bb8db5ab4abe40c20530b512f130dd54ed8f0bf9c36f51c20735415e25905d4047d896bf6eef7325ec + +u b2fd5cba9d6d5487c5257954d1d170a99cd27c2e990aa7b20006d8615b929f9024c5b3a0b063dc9c364a668cde34b4a26ec4e374d38d2a32 +v e4796d1ed6d6cd3443a095e6f91e80db3ea043b1f9026e4015a4abff5b2ecde79848dd0b856db0f47a6f29e1759fbaeb2ac82d2d8a939d89 +a -338517 +w 65c169eec5df306b2d17d58f7c1f833bea184fadbbc8924803cc0ff2804d24531e69004059169f29423b5692d54c92fec7936933eac92317 +x ab7c743547424e08a733876339fc4434d1c0ede96dbcfc7a92acbb6ec4e1f6e330d13cee90e4378863022bb49b57b6b4617b37fb5e6f7d0a +y 5fb79ffb10f7c3bc4cc98025f7c7f71bdb4041a5161e7fdee2a701692d16ae77d23680becc76f14e66a7e961d8841adad5485043e13b7694 +z 365da4af25fe7f21edf0706495f44475b2d3a9b157b3008dd745cb8e756e3da662108d6c05d573aedfbaa0fd0c8420b6b7ab8d418d273be2 + +u 0b1fe73972fe3400b1a9563b759cc65dc7f685031405e14ecbf1ab977c7c9afceafa91f51d1127f09058b637c9cdc39fa665be7c2a4d55d6 +v 349cebcab0d98aea0beb0d38dde902e4f6caa23cbb066e68ef8d384613b4ecf6d21780ae1844c4b3eb9598cfd62fc001505d3ce4e66746ae +a -242599 +w 7c7018b38125bf7415723b398f888458a647f4a2f2ff0b7dcbd6eb7ae873c44068429efde0be1f2f28ae1c8e01db9f812442fabaf51ffadb +x c125c39bcf8ae742747cc2f711e470b8386403e275a14e5651f1dae89231cb3ee186a3d2c1b1a74002ac70e1fc1a5adc89a17734aa231650 +y feb78a43f6e633e7b92ffb2789f6486cc7597ce0ce9ce2486828af900d97c9ee8fcd0f52d43d01e141f9987ad194dfaa8a31b9d649e487ac +z 32318ade75655d7aacba10759063893db2482b2083a924915afefc63891f9951b58bf5525f5b330f16422c65bdf77a5508f1830849c2a941 + +u 080f596d6be6f4554477689f6ac45ff60a880924f6e609701bd6d1fe32eb4f1be13edf39399eb170fa5b5b9801e38301e7ed768383cab6cf +v f14535e25853aa97a8bc8128610eaab77977d07d3a89608a837b16fb2c2878f8edf11a2276f3c42ee21ba275dd4e6059574f887abcf6480f +a 273443 +w f273139e62664cb2b5f9c268c37abfcddc054c0f30ed8f0fd643017a989512cf115467ca704b3442b1c92496e378f4df6434b27e9c9fbacb +x 8af391a0b26881d67fa19196d5dded3e00cc3dc60247781ec1d000e635b6f39f7186e948bbb5b03894f0a000b27838dbda844836c5c29d99 +y 56513a9d50e48e2464df2069404f09c21d4bf112d2223ea316e78cb4ebbca403327ab344af7e15b17b9865ea8d801cc7d4f6f7283687c3bd +z 9c3043751d7889855a337637b51e1fb9c7bb47d75ef529e4e8545822cbb2f535ef1579b9c660813438e2e9f16bb35f4a7843d3e7820e1406 + +u a5d6bc11f9251ec7d03e87c267b2eb05d51fdbeb24970e2c87a7d8923f7adbf4bff904e5ae498f5984072d7a21c703ba6765bc3292e43bfe +v 2be24a92df5b92545f72e710d4a5c71f881d544305e891dc9fcf2b39a24a5e80fe44f856411fc886566f428b5443af8140543e549d092170 +a -140922 +w 629534899a55d04d6e0c879ea02b9eb05675cf6074ce400d8caa25b2adc59eedcd88f203f9440db9fb06c5bfcd65512324d01f871b485650 +x 867e9ed2dbef2b0d485a7d5dc71266eae2b6053c2f1e09dfba6192f015419e06868aaaefefdc3b03cb26e50cc4861f38eac76ac69e5ab1fd +y 61d009f31c5be4eaca1f44ab6800f0116dadb7923e427db6e525f03c17b380eaa6d0c8f06440674c80f0040c272b8b956366a82ca28dccbf +z a7628d76da5a4a8dcabfcd28252b9fb1f780e2d32f72a0f1f8da7ff7d354c6d35a72efb2b75e87c332f93557c1a5e1bd51813e18ee1fe241 diff --git a/fgoldi.c b/fgoldi.c new file mode 100644 index 0000000..14b98ed --- /dev/null +++ b/fgoldi.c @@ -0,0 +1,589 @@ +/* -*-c-*- + * + * Arithmetic in the Goldilocks field GF(2^448 - 2^224 - 1) + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "fgoldi.h" + +/*----- Basic setup -------------------------------------------------------* + * + * Let φ = 2^224; then p = φ^2 - φ - 1, and, in GF(p), we have φ^2 = φ + 1 + * (hence the name). + */ + +/* We represent an element of GF(p) as 16 28-bit signed integer pieces x_i: + * x = SUM_{0<=i<16} x_i 2^(28i). + */ + +typedef int32 piece; typedef int64 dblpiece; +typedef uint32 upiece; typedef uint64 udblpiece; +#define PIECEWD(i) 28 +#define NPIECE 16 +#define P p28 + +#define B28 0x10000000u +#define B27 0x08000000u +#define M28 0x0fffffffu +#define M27 0x07ffffffu +#define M32 0xffffffffu + +/*----- Debugging machinery -----------------------------------------------*/ + +#if defined(FGOLDI_DEBUG) + +#include + +#include "mp.h" +#include "mptext.h" + +static mp *get_pgoldi(void) +{ + mp *p = MP_NEW, *t = MP_NEW; + + p = mp_setbit(p, MP_ZERO, 448); + t = mp_setbit(t, MP_ZERO, 224); + p = mp_sub(p, p, t); + p = mp_sub(p, p, MP_ONE); + mp_drop(t); + return (p); +} + +DEF_FDUMP(fdump, piece, PIECEWD, NPIECE, 56, get_pgoldi()) + +#endif + +/*----- Loading and storing -----------------------------------------------*/ + +/* --- @fgoldi_load@ --- * + * + * Arguments: @fgoldi *z@ = where to store the result + * @const octet xv[56]@ = source to read + * + * Returns: --- + * + * Use: Reads an element of %$\gf{2^{448} - 2^{224} - 19}$% in + * external representation from @xv@ and stores it in @z@. + * + * External representation is little-endian base-256. Some + * elements have multiple encodings, which are not produced by + * correct software; use of noncanonical encodings is not an + * error, and toleration of them is considered a performance + * feature. + */ + +void fgoldi_load(fgoldi *z, const octet xv[56]) +{ + + unsigned i; + uint32 xw[14]; + piece b, c; + + /* First, read the input value as words. */ + for (i = 0; i < 14; i++) xw[i] = LOAD32_L(xv + 4*i); + + /* Extract unsigned 28-bit pieces from the words. */ + z->P[ 0] = (xw[ 0] >> 0)&M28; + z->P[ 7] = (xw[ 6] >> 4)&M28; + z->P[ 8] = (xw[ 7] >> 0)&M28; + z->P[15] = (xw[13] >> 4)&M28; + for (i = 1; i < 7; i++) { + z->P[i + 0] = ((xw[i + 0] << (4*i)) | (xw[i - 1] >> (32 - 4*i)))&M28; + z->P[i + 8] = ((xw[i + 7] << (4*i)) | (xw[i + 6] >> (32 - 4*i)))&M28; + } + + /* Convert the nonnegative pieces into a balanced signed representation, so + * each piece ends up in the interval |z_i| <= 2^27. For each piece, if + * its top bit is set, lend a bit leftwards; in the case of z_15, reduce + * this bit by adding it onto z_0 and z_8, since this is the φ^2 bit, and + * φ^2 = φ + 1. We delay this carry until after all of the pieces have + * been balanced. If we don't do this, then we have to do a more expensive + * test for nonzeroness to decide whether to lend a bit leftwards rather + * than just testing a single bit. + * + * Note that we don't try for a canonical representation here: both upper + * and lower bounds are achievable. + */ + b = z->P[15]&B27; z->P[15] -= b << 1; c = b >> 27; + for (i = NPIECE - 1; i--; ) + { b = z->P[i]&B27; z->P[i] -= b << 1; z->P[i + 1] += b >> 27; } + z->P[0] += c; z->P[8] += c; +} + +/* --- @fgoldi_store@ --- * + * + * Arguments: @octet zv[56]@ = where to write the result + * @const fgoldi *x@ = the field element to write + * + * Returns: --- + * + * Use: Stores a field element in the given octet vector in external + * representation. A canonical encoding is always stored. + */ + +void fgoldi_store(octet zv[56], const fgoldi *x) +{ + + piece y[NPIECE], yy[NPIECE], c, d; + uint32 u, v; + mask32 m; + unsigned i; + + for (i = 0; i < NPIECE; i++) y[i] = x->P[i]; + + /* First, propagate the carries. By the end of this, we'll have all of the + * the pieces canonically sized and positive, and maybe there'll be + * (signed) carry out. The carry c is in { -1, 0, +1 }, and the remaining + * value will be in the half-open interval [0, φ^2). The whole represented + * value is then y + φ^2 c. + * + * Assume that we start out with |y_i| <= 2^30. We start off by cutting + * off and reducing the carry c_15 from the topmost piece, y_15. This + * leaves 0 <= y_15 < 2^28; and we'll have |c_15| <= 4. We'll add this + * onto y_0 and y_8, and propagate the carries. It's very clear that we'll + * end up with |y + (φ + 1) c_15 - φ^2/2| << φ^2. + * + * Here, the y_i are signed, so we must be cautious about bithacking them. + */ + c = ASR(piece, y[15], 28); y[15] = (upiece)y[15]&M28; y[8] += c; + for (i = 0; i < NPIECE; i++) + { y[i] += c; c = ASR(piece, y[i], 28); y[i] = (upiece)y[i]&M28; } + + /* Now we have a slightly fiddly job to do. If c = +1, or if c = 0 and + * y >= p, then we should subtract p from the whole value; if c = -1 then + * we should add p; and otherwise we should do nothing. + * + * But conditional behaviour is bad, m'kay. So here's what we do instead. + * + * The first job is to sort out what we wanted to do. If c = -1 then we + * want to (a) invert the constant addend and (b) feed in a carry-in; + * otherwise, we don't. + */ + m = SIGN(c)&M28; + d = m&1; + + /* Now do the addition/subtraction. Remember that all of the y_i are + * nonnegative, so shifting and masking are safe and easy. + */ + d += y[0] + (1 ^ m); yy[0] = d&M28; d >>= 28; + for (i = 1; i < 8; i++) + { d += y[i] + m; yy[i] = d&M28; d >>= 28; } + d += y[8] + (1 ^ m); yy[8] = d&M28; d >>= 28; + for (i = 9; i < 16; i++) + { d += y[i] + m; yy[i] = d&M28; d >>= 28; } + + /* The final carry-out is in d; since we only did addition, and the y_i are + * nonnegative, then d is in { 0, 1 }. We want to keep y', rather than y, + * if (a) c /= 0 (in which case we know that the old value was + * unsatisfactory), or (b) if d = 1 (in which case, if c = 0, we know that + * the subtraction didn't cause a borrow, so we must be in the case where + * p <= y < φ^2. + */ + m = NONZEROP(c) | ~NONZEROP(d - 1); + for (i = 0; i < NPIECE; i++) y[i] = (yy[i]&m) | (y[i]&~m); + + /* Extract 32-bit words from the value. */ + for (i = 0; i < 7; i++) { + u = ((y[i + 0] >> (4*i)) | ((uint32)y[i + 1] << (28 - 4*i)))&M32; + v = ((y[i + 8] >> (4*i)) | ((uint32)y[i + 9] << (28 - 4*i)))&M32; + STORE32_L(zv + 4*i, u); + STORE32_L(zv + 4*i + 28, v); + } +} + +/* --- @fgoldi_set@ --- * + * + * Arguments: @fgoldi *z@ = where to write the result + * @int a@ = a small-ish constant + * + * Returns: --- + * + * Use: Sets @z@ to equal @a@. + */ + +void fgoldi_set(fgoldi *x, int a) +{ + unsigned i; + + x->P[0] = a; + for (i = 1; i < NPIECE; i++) x->P[i] = 0; +} + +/*----- Basic arithmetic --------------------------------------------------*/ + +/* --- @fgoldi_add@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@ or @y@) + * @const fgoldi *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the sum %$x + y$%. + */ + +void fgoldi_add(fgoldi *z, const fgoldi *x, const fgoldi *y) +{ + unsigned i; + for (i = 0; i < NPIECE; i++) z->P[i] = x->P[i] + y->P[i]; +} + +/* --- @fgoldi_sub@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@ or @y@) + * @const fgoldi *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the difference %$x - y$%. + */ + +void fgoldi_sub(fgoldi *z, const fgoldi *x, const fgoldi *y) +{ + unsigned i; + for (i = 0; i < NPIECE; i++) z->P[i] = x->P[i] - y->P[i]; +} + +/*----- Constant-time utilities -------------------------------------------*/ + +/* --- @fgoldi_condswap@ --- * + * + * Arguments: @fgoldi *x, *y@ = two operands + * @uint32 m@ = a mask + * + * Returns: --- + * + * Use: If @m@ is zero, do nothing; if @m@ is all-bits-set, then + * exchange @x@ and @y@. If @m@ has some other value, then + * scramble @x@ and @y@ in an unhelpful way. + */ + +void fgoldi_condswap(fgoldi *x, fgoldi *y, uint32 m) +{ + unsigned i; + mask32 mm = FIX_MASK32(m); + + for (i = 0; i < NPIECE; i++) CONDSWAP(x->P[i], y->P[i], mm); +} + +/*----- Multiplication ----------------------------------------------------*/ + +/* Let B = 2^63 - 1 be the largest value such that +B and -B can be + * represented in a double-precision piece. On entry, it must be the case + * that |X_i| <= M <= B - 2^27 for some M. If this is the case, then, on + * exit, we will have |Z_i| <= 2^27 + M/2^27. + */ +#define CARRY_REDUCE(z, x) do { \ + dblpiece _t[NPIECE], _c; \ + unsigned _i; \ + \ + /* Bias the input pieces. This keeps the carries and so on centred \ + * around zero rather than biased positive. \ + */ \ + for (_i = 0; _i < NPIECE; _i++) _t[_i] = (x)[_i] + B27; \ + \ + /* Calculate the reduced pieces. Careful with the bithacking. */ \ + _c = ASR(dblpiece, _t[15], 28); \ + (z)[0] = (dblpiece)((udblpiece)_t[0]&M28) - B27 + _c; \ + for (_i = 1; _i < NPIECE; _i++) { \ + (z)[_i] = (dblpiece)((udblpiece)_t[_i]&M28) - B27 + \ + ASR(dblpiece, _t[_i - 1], 28); \ + } \ + (z)[8] += _c; \ +} while (0) + +/* --- @fgoldi_mulconst@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@) + * @const fgoldi *x@ = an operand + * @long a@ = a small-ish constant; %$|a| < 2^{20}$%. + * + * Returns: --- + * + * Use: Set @z@ to the product %$a x$%. + */ + +void fgoldi_mulconst(fgoldi *z, const fgoldi *x, long a) +{ + unsigned i; + dblpiece zz[NPIECE], aa = a; + + for (i = 0; i < NPIECE; i++) zz[i] = aa*x->P[i]; + CARRY_REDUCE(z->P, zz); +} + +/* --- @fgoldi_mul@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@ or @y@) + * @const fgoldi *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the product %$x y$%. + */ + +void fgoldi_mul(fgoldi *z, const fgoldi *x, const fgoldi *y) +{ + dblpiece zz[NPIECE], u[NPIECE]; + piece ab[NPIECE/2], cd[NPIECE/2]; + const piece + *a = x->P + NPIECE/2, *b = x->P, + *c = y->P + NPIECE/2, *d = y->P; + unsigned i, j; + +# define M(x,i, y,j) ((dblpiece)(x)[i]*(y)[j]) + + /* Behold the magic. + * + * Write x = a φ + b, and y = c φ + d. Then x y = a c φ^2 + + * (a d + b c) φ + b d. Karatsuba and Ofman observed that a d + b c = + * (a + b) (c + d) - a c - b d, saving a multiplication, and Hamburg chose + * the prime p so that φ^2 = φ + 1. So + * + * x y = ((a + b) (c + d) - b d) φ + a c + b d + */ + + for (i = 0; i < NPIECE; i++) zz[i] = 0; + + /* Our first job will be to calculate (1 - φ) b d, and write the result + * into z. As we do this, an interesting thing will happen. Write + * b d = u φ + v; then (1 - φ) b d = u φ + v - u φ^2 - v φ = (1 - φ) v - u. + * So, what we do is to write the product end-swapped and negated, and then + * we'll subtract the (negated, remember) high half from the low half. + */ + for (i = 0; i < NPIECE/2; i++) { + for (j = 0; j < NPIECE/2 - i; j++) + zz[i + j + NPIECE/2] -= M(b,i, d,j); + for (; j < NPIECE/2; j++) + zz[i + j - NPIECE/2] -= M(b,i, d,j); + } + for (i = 0; i < NPIECE/2; i++) + zz[i] -= zz[i + NPIECE/2]; + + /* Next, we add on a c. There are no surprises here. */ + for (i = 0; i < NPIECE/2; i++) + for (j = 0; j < NPIECE/2; j++) + zz[i + j] += M(a,i, c,j); + + /* Now, calculate a + b and c + d. */ + for (i = 0; i < NPIECE/2; i++) + { ab[i] = a[i] + b[i]; cd[i] = c[i] + d[i]; } + + /* Finally (for the multiplication) we must add on (a + b) (c + d) φ. + * Write (a + b) (c + d) as u φ + v; then we actually want u φ^2 + v φ = + * v φ + (1 + φ) u. We'll store u in a temporary place and add it on + * twice. + */ + for (i = 0; i < NPIECE; i++) u[i] = 0; + for (i = 0; i < NPIECE/2; i++) { + for (j = 0; j < NPIECE/2 - i; j++) + zz[i + j + NPIECE/2] += M(ab,i, cd,j); + for (; j < NPIECE/2; j++) + u[i + j - NPIECE/2] += M(ab,i, cd,j); + } + for (i = 0; i < NPIECE/2; i++) + { zz[i] += u[i]; zz[i + NPIECE/2] += u[i]; } + +#undef M + + /* That wraps it up for the multiplication. Let's figure out some bounds. + * Fortunately, Karatsuba is a polynomial identity, so all of the pieces + * end up the way they'd be if we'd done the thing the easy way, which + * simplifies the analysis. Suppose we started with |x_i|, |y_i| <= 9/5 + * 2^28. The overheads in the result are given by the coefficients of + * + * ((u^16 - 1)/(u - 1))^2 mod u^16 - u^8 - 1 + * + * the greatest of which is 38. So |z_i| <= 38*81/25*2^56 < 2^63. + * + * Anyway, a round of `CARRY_REDUCE' will leave us with |z_i| < 2^27 + + * 2^36; and a second round will leave us with |z_i| < 2^27 + 512. + */ + for (i = 0; i < 2; i++) CARRY_REDUCE(zz, zz); + for (i = 0; i < NPIECE; i++) z->P[i] = zz[i]; +} + +/* --- @fgoldi_sqr@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@ or @y@) + * @const fgoldi *x@ = an operand + * + * Returns: --- + * + * Use: Set @z@ to the square %$x^2$%. + */ + +void fgoldi_sqr(fgoldi *z, const fgoldi *x) +{ + + dblpiece zz[NPIECE], u[NPIECE]; + piece ab[NPIECE]; + const piece *a = x->P + NPIECE/2, *b = x->P; + unsigned i, j; + +# define M(x,i, y,j) ((dblpiece)(x)[i]*(y)[j]) + + /* The magic is basically the same as `fgoldi_mul' above. We write + * x = a φ + b and use Karatsuba and the special prime shape. This time, + * we have + * + * x^2 = ((a + b)^2 - b^2) φ + a^2 + b^2 + */ + + for (i = 0; i < NPIECE; i++) zz[i] = 0; + + /* Our first job will be to calculate (1 - φ) b^2, and write the result + * into z. Again, this interacts pleasantly with the prime shape. + */ + for (i = 0; i < NPIECE/4; i++) { + zz[2*i + NPIECE/2] -= M(b,i, b,i); + for (j = i + 1; j < NPIECE/2 - i; j++) + zz[i + j + NPIECE/2] -= 2*M(b,i, b,j); + for (; j < NPIECE/2; j++) + zz[i + j - NPIECE/2] -= 2*M(b,i, b,j); + } + for (; i < NPIECE/2; i++) { + zz[2*i - NPIECE/2] -= M(b,i, b,i); + for (j = i + 1; j < NPIECE/2; j++) + zz[i + j - NPIECE/2] -= 2*M(b,i, b,j); + } + for (i = 0; i < NPIECE/2; i++) + zz[i] -= zz[i + NPIECE/2]; + + /* Next, we add on a^2. There are no surprises here. */ + for (i = 0; i < NPIECE/2; i++) { + zz[2*i] += M(a,i, a,i); + for (j = i + 1; j < NPIECE/2; j++) + zz[i + j] += 2*M(a,i, a,j); + } + + /* Now, calculate a + b. */ + for (i = 0; i < NPIECE/2; i++) + ab[i] = a[i] + b[i]; + + /* Finally (for the multiplication) we must add on (a + b)^2 φ. + * Write (a + b)^2 as u φ + v; then we actually want (u + v) φ + u. We'll + * store u in a temporary place and add it on twice. + */ + for (i = 0; i < NPIECE; i++) u[i] = 0; + for (i = 0; i < NPIECE/4; i++) { + zz[2*i + NPIECE/2] += M(ab,i, ab,i); + for (j = i + 1; j < NPIECE/2 - i; j++) + zz[i + j + NPIECE/2] += 2*M(ab,i, ab,j); + for (; j < NPIECE/2; j++) + u[i + j - NPIECE/2] += 2*M(ab,i, ab,j); + } + for (; i < NPIECE/2; i++) { + u[2*i - NPIECE/2] += M(ab,i, ab,i); + for (j = i + 1; j < NPIECE/2; j++) + u[i + j - NPIECE/2] += 2*M(ab,i, ab,j); + } + for (i = 0; i < NPIECE/2; i++) + { zz[i] += u[i]; zz[i + NPIECE/2] += u[i]; } + +#undef M + + /* Finally, carrying. */ + for (i = 0; i < 2; i++) CARRY_REDUCE(zz, zz); + for (i = 0; i < NPIECE; i++) z->P[i] = zz[i]; +} + +/*----- More advanced operations ------------------------------------------*/ + +/* --- @fgoldi_inv@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@) + * @const fgoldi *x@ = an operand + * + * Returns: --- + * + * Use: Stores in @z@ the multiplicative inverse %$x^{-1}$%. If + * %$x = 0$% then @z@ is set to zero. This is considered a + * feature. + */ + +void fgoldi_inv(fgoldi *z, const fgoldi *x) +{ + fgoldi t, u; + unsigned i; + +#define SQRN(z, x, n) do { \ + fgoldi_sqr((z), (x)); \ + for (i = 1; i < (n); i++) fgoldi_sqr((z), (z)); \ +} while (0) + + /* Calculate x^-1 = x^(p - 2) = x^(2^448 - 2^224 - 3), which also handles + * x = 0 as intended. The addition chain is home-made. + */ /* step | value */ + fgoldi_sqr(&u, x); /* 1 | 2 */ + fgoldi_mul(&t, &u, x); /* 2 | 3 */ + SQRN(&u, &t, 2); /* 4 | 12 */ + fgoldi_mul(&t, &u, &t); /* 5 | 15 */ + SQRN(&u, &t, 4); /* 9 | 240 */ + fgoldi_mul(&u, &u, &t); /* 10 | 255 = 2^8 - 1 */ + SQRN(&u, &u, 4); /* 14 | 2^12 - 16 */ + fgoldi_mul(&t, &u, &t); /* 15 | 2^12 - 1 */ + SQRN(&u, &t, 12); /* 27 | 2^24 - 2^12 */ + fgoldi_mul(&u, &u, &t); /* 28 | 2^24 - 1 */ + SQRN(&u, &u, 12); /* 40 | 2^36 - 2^12 */ + fgoldi_mul(&t, &u, &t); /* 41 | 2^36 - 1 */ + fgoldi_sqr(&t, &t); /* 42 | 2^37 - 2 */ + fgoldi_mul(&t, &t, x); /* 43 | 2^37 - 1 */ + SQRN(&u, &t, 37); /* 80 | 2^74 - 2^37 */ + fgoldi_mul(&u, &u, &t); /* 81 | 2^74 - 1 */ + SQRN(&u, &u, 37); /* 118 | 2^111 - 2^37 */ + fgoldi_mul(&t, &u, &t); /* 119 | 2^111 - 1 */ + SQRN(&u, &t, 111); /* 230 | 2^222 - 2^111 */ + fgoldi_mul(&t, &u, &t); /* 231 | 2^222 - 1 */ + fgoldi_sqr(&u, &t); /* 232 | 2^223 - 2 */ + fgoldi_mul(&u, &u, x); /* 233 | 2^223 - 1 */ + SQRN(&u, &u, 223); /* 456 | 2^446 - 2^223 */ + fgoldi_mul(&t, &u, &t); /* 457 | 2^446 - 2^222 - 1 */ + SQRN(&t, &t, 2); /* 459 | 2^448 - 2^224 - 4 */ + fgoldi_mul(z, &t, x); /* 460 | 2^448 - 2^224 - 3 */ + +#undef SQRN +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/fgoldi.h b/fgoldi.h new file mode 100644 index 0000000..cac2ff1 --- /dev/null +++ b/fgoldi.h @@ -0,0 +1,212 @@ +/* -*-c-*- + * + * Arithmetic in the Goldilocks field GF(2^448 - 2^224 - 1) + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_FGOLDI_H +#define CATACOMB_FGOLDI_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include "fake-mLib-bits.h" + +#ifndef CATACOMB_QFARITH_H +# include "qfarith.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +typedef union { + int32 p28[16]; +} fgoldi; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @fgoldi_load@ --- * + * + * Arguments: @fgoldi *z@ = where to store the result + * @const octet xv[56]@ = source to read + * + * Returns: --- + * + * Use: Reads an element of %$\gf{2^{448} - 2^{224} - 19}$% in + * external representation from @xv@ and stores it in @z@. + * + * External representation is little-endian base-256. Some + * elements have multiple encodings, which are not produced by + * correct software; use of noncanonical encodings is not an + * error, and toleration of them is considered a performance + * feature. + */ + +extern void fgoldi_load(fgoldi */*z*/, const octet /*xv*/[56]); + +/* --- @fgoldi_store@ --- * + * + * Arguments: @octet zv[56]@ = where to write the result + * @const fgoldi *x@ = the field element to write + * + * Returns: --- + * + * Use: Stores a field element in the given octet vector in external + * representation. A canonical encoding is always stored. + */ + +extern void fgoldi_store(octet /*zv*/[56], const fgoldi */*x*/); + +/* --- @fgoldi_set@ --- * + * + * Arguments: @fgoldi *z@ = where to write the result + * @int a@ = a small-ish constant + * + * Returns: --- + * + * Use: Sets @z@ to equal @a@. + */ + +extern void fgoldi_set(fgoldi */*x*/, int /*a*/); + +/* --- @fgoldi_add@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@ or @y@) + * @const fgoldi *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the sum %$x + y$%. + */ + +extern void fgoldi_add(fgoldi */*z*/, + const fgoldi */*x*/, const fgoldi */*y*/); + +/* --- @fgoldi_sub@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@ or @y@) + * @const fgoldi *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the difference %$x - y$%. + */ + +extern void fgoldi_sub(fgoldi */*z*/, + const fgoldi */*x*/, const fgoldi */*y*/); + +/* --- @fgoldi_condswap@ --- * + * + * Arguments: @fgoldi *x, *y@ = two operands + * @uint32 m@ = a mask + * + * Returns: --- + * + * Use: If @m@ is zero, do nothing; if @m@ is all-bits-set, then + * exchange @x@ and @y@. If @m@ has some other value, then + * scramble @x@ and @y@ in an unhelpful way. + */ + +extern void fgoldi_condswap(fgoldi */*x*/, fgoldi */*y*/, uint32 /*m*/); + +/* --- @fgoldi_mulconst@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@) + * @const fgoldi *x@ = an operand + * @long a@ = a small-ish constant; %$|a| < 2^{20}$%. + * + * Returns: --- + * + * Use: Set @z@ to the product %$a x$%. + */ + +extern void fgoldi_mulconst(fgoldi */*z*/, const fgoldi */*x*/, long /*a*/); + +/* --- @fgoldi_mul@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@ or @y@) + * @const fgoldi *x, *y@ = two operands + * + * Returns: --- + * + * Use: Set @z@ to the product %$x y$%. + */ + +extern void fgoldi_mul(fgoldi */*z*/, + const fgoldi */*x*/, const fgoldi */*y*/); + +/* --- @fgoldi_sqr@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@ or @y@) + * @const fgoldi *x@ = an operand + * + * Returns: --- + * + * Use: Set @z@ to the square %$x^2$%. + */ + +extern void fgoldi_sqr(fgoldi */*z*/, const fgoldi */*x*/); + +/* --- @fgoldi_inv@ --- * + * + * Arguments: @fgoldi *z@ = where to put the result (may alias @x@) + * @const fgoldi *x@ = an operand + * + * Returns: --- + * + * Use: Stores in @z@ the multiplicative inverse %$x^{-1}$%. If + * %$x = 0$% then @z@ is set to zero. This is considered a + * feature. + */ + +extern void fgoldi_inv(fgoldi */*z*/, const fgoldi */*x*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/montladder.h b/montladder.h new file mode 100644 index 0000000..bcd3539 --- /dev/null +++ b/montladder.h @@ -0,0 +1,162 @@ +/* -*-c-*- + * + * Definitions for Montgomery's ladder + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_MONTLADDER_H +#define CATACOMB_MONTLADDER_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Notes on the Montgomery ladder ------------------------------------* + * + * The algorithm here is Montgomery's famous binary ladder for calculating + * x-coordinates of scalar products on a particular shape of elliptic curve, + * as elucidated by Daniel Bernstein. + * + * Let Q = (x_1, y_1) be the base point, for some unknown y_1 (which will + * turn out to be unimportant). Define x_n, z_n by x(n Q) = (x_n : z_n). + * Given x_n, z_n, x_{n+1}, z_{n+1}, Montgomery's differential addition + * formulae calculate x_{2i}, z_{2i}, x_{2i+1}, z_{2i+1}. Furthermore, + * calculating x_{2i}, z_{2i} requires only x_n, z_n, and the calculation of + * x_{2i+1}, z_{2i+1} is symmetrical. + */ + +/*----- Functions provided ------------------------------------------------*/ + +/* F designates a field, both naming the type of its elements and acting as a + * prefix for the standard field operations `F_add', `F_sub', `F_mul', + * `F_sqr', and `F_inv' (the last of which should return zero its own + * inverse); and the constant-time utility `F_condswap'. + * + * The macro calculates the x-coordinate of the product k Q, where Q is a + * point on the elliptic curve B y^2 = x^3 + A x^2 + x or its quadratic + * twist, for some irrelevant B. The x-coordinate of Q is given as X1 (a + * pointer to a field element). The scalar k is given as a vector of NK + * unsigned integers KW, each containing NBITS significant bits, with the + * least-significant element first. The result is written to the field + * element pointed to by Z. + * + * The curve coefficient A is given indirectly, as the name of a macro MULA0 + * such that + * + * MULA0(z, x) + * + * will store in z the value (A - 2)/4 x. + */ +#define MONT_LADDER(f, mula0, kw, nk, nbits, z, x1) do { \ + f _x, _z, _u, _w; \ + f _t0, _t1, _t2, _t3, _t4; \ + uint32 _m = 0, _mm = 0, _k; \ + unsigned _i, _j; \ + \ + /* Initialize the main variables. We'll have, (x, z) and (u, w) \ + * holding (x_n, z_n) and (x_{n+1}, z_{n+1}) in some order, but \ + * there's some weirdness: if m = 0 then (x, z) = (x_n, z_n) and \ + * (u, v) = (x_{n+1}, z_{n+1}); if m /= 0, then the pairs are \ + * swapped over. \ + * \ + * Initially, we have (x_0, z_0) = (1, 0), representing the identity \ + * at projective-infinity, which works fine; and we have z_1 = 1. \ + */ \ + _u = *(x1); f##_set(&_w, 1); f##_set(&_x, 1); f##_set(&_z, 0); \ + \ + /* The main ladder loop. Work through each bit of the clamped key. */ \ + for (_i = (nk); _i--; ) { \ + _k = (kw)[_i]; \ + for (_j = 0; _j < (nbits); _j++) { \ + /* We're at bit i of the scalar key (represented by 32 (7 - i) + \ + * (31 - j) in our loop variables -- don't worry about that). \ + * Let k = 2^i k_i + k'_i, with 0 <= k'_i < 2^i. In particular, \ + * then, k_0 = k. Write Q(i) = (x_i, z_i). \ + * \ + * We currently have, in (x, z) and (u, w), Q(k_i) and Q(k_i + \ + * 1), in some order. The ladder step will double the point in \ + * (x, z), and leave the sum of (x : z) and (u : w) in (u, w). \ + */ \ + \ + _mm = -((_k >> ((nbits) - 1))&1u); _k <<= 1; \ + f##_condswap(&_x, &_u, _m ^ _mm); \ + f##_condswap(&_z, &_w, _m ^ _mm); \ + _m = _mm; \ + \ + f##_add(&_t0, &_x, &_z); /* x + z */ \ + f##_sub(&_t1, &_x, &_z); /* x - z */ \ + f##_add(&_t2, &_u, &_w); /* u + w */ \ + f##_sub(&_t3, &_u, &_w); /* u - w */ \ + f##_mul(&_t2, &_t2, &_t1); /* (x - z) (u + w) */ \ + f##_mul(&_t3, &_t3, &_t0); /* (x + z) (u - w) */ \ + f##_sqr(&_t0, &_t0); /* (x + z)^2 */ \ + f##_sqr(&_t1, &_t1); /* (x - z)^2 */ \ + f##_mul(&_x, &_t0, &_t1); /* (x + z)^2 (x - z)^2 */ \ + f##_sub(&_t1, &_t0, &_t1); /* (x + z)^2 - (x - z)^2 */ \ + mula0(&_t4, &_t1); /* A_0 ((x + z)^2 - (x - z)^2) */ \ + f##_add(&_t0, &_t0, &_t4); /* A_0 ... + (x + z)^2 */ \ + f##_mul(&_z, &_t0, &_t1); /* (...^2 - ...^2) (A_0 ... + ...) */ \ + f##_add(&_t0, &_t2, &_t3); /* (x - z) (u + w) + (x + z) (u - w) */ \ + f##_sub(&_t1, &_t2, &_t3); /* (x - z) (u + w) - (x + z) (u - w) */ \ + f##_sqr(&_u, &_t0); /* (... + ...)^2 */ \ + f##_sqr(&_t1, &_t1); /* (... - ...)^2 */ \ + f##_mul(&_w, &_t1, (x1)); /* x_1 (... - ...)^2 */ \ + } \ + } \ + \ + /* Almost done. Undo the swap, if any. */ \ + f##_condswap(&_x, &_u, _m); \ + f##_condswap(&_z, &_w, _m); \ + \ + /* And convert to affine. */ \ + f##_inv(&_t0, &_z); \ + f##_mul((z), &_x, &_t0); \ +} while (0) + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/qfarith.h b/qfarith.h new file mode 100644 index 0000000..f41aa95 --- /dev/null +++ b/qfarith.h @@ -0,0 +1,187 @@ +/* -*-c-*- + * + * Utilities for quick field arithmetic + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_QFARITH_H +#define CATACOMB_QFARITH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "fake-mLib-bits.h" +/*----- Signed integer types ----------------------------------------------*/ + +typedef int32_t int32; +typedef int64_t int64; +#define HAVE_INT64 1 + +/*----- General bit-hacking utilities -------------------------------------*/ + +/* Individual bits, and masks for low bits. */ +#define BIT(n) (1ul << (n)) +#define MASK(n) (BIT(n) - 1) + +/* Arithmetic right shift. If X is a value of type TY, and N is a + * nonnegative integer, then return the value of X shifted right by N bits; + * alternatively, this is floor(X/2^N). + * + * GCC manages to compile this into a simple shift operation if one is + * available, but it's correct for all C targets. + */ +#define ASR(ty, x, n) (((x) - (ty)((u##ty)(x)&MASK(n)))/(ty)BIT(n)) + +/*----- Constant-time utilities -------------------------------------------*/ + +/* The following have better implementations on a two's complement target. */ + +/* If we have two's complement arithmetic then masks are signed; this + * avoids a switch to unsigned representation, with the consequent problem + * of overflow when we convert back. + */ +typedef int32 mask32; + +/* Convert an unsigned mask M into a `mask32'. This is a hairy-looking + * no-op on many targets, but, given that we have two's complement + * integers, it is free of arithmetic overflow. + */ +#define FIX_MASK32(m) \ + ((mask32)((m)&0x7fffffffu) + (-(mask32)0x7fffffff - 1)*(((m) >> 31)&1u)) + +/* If Z is zero and M has its low 32 bits set, then copy (at least) the low + * 32 bits of X to Z; if M is zero, do nothing. Otherwise, scramble Z + * unhelpfully. + */ +#define CONDPICK(z, x, m) do { (z) |= (x)&(m); } while (0) + +/* If M has its low 32 bits set, then return (at least) the low 32 bits of + * X in Z; if M is zero, then return (at least) the low 32 bits of Y in Z. + * Otherwise, return an unhelful result. + */ +#define PICK2(x, y, m) (((x)&(m)) | ((y)&~(m))) + +/* If M has its low 32 bits set then swap (at least) the low 32 bits of X + * and Y; if M is zero, then do nothing. Otherwise, scramble X and Y + * unhelpfully. + */ +#define CONDSWAP(x, y, m) \ + do { mask32 t_ = ((x) ^ (y))&(m); (x) ^= t_; (y) ^= t_; } while (0) + +/* Return zero if bit 31 of X is clear, or a mask with (at least) the low 32 + * bits set if bit 31 of X is set. + */ +#define SIGN(x) (-(mask32)(((uint32)(x) >> 31)&1)) + +/* Return zero if X is zero, or a mask with (at least) the low 32 bits set if + * X is nonzero. + */ +#define NONZEROP(x) SIGN((U32(x) >> 1) - U32(x)) + +/*----- Debugging utilities -----------------------------------------------*/ + +/* Define a debugging function DUMPFN, which will dump an integer represented + * modulo M. The integer is represented as a vector of NPIECE pieces of type + * PIECETY. The pieces are assembled at possibly irregular offsets: piece i + * logically has width PIECEWD(i), but may overhang the next piece. The + * pieces may be signed. GETMOD is an expression which calculates and + * returns the value of M, as an `mp *'. + * + * The generated function writes the value of such an integer X to the stream + * FP, labelled with the string WHAT. + * + * The definition assumes that , , and + * have been included. + */ +#define DEF_FDUMP(dumpfn, piecety, piecewd, npiece, noctet, getmod) \ + static void dumpfn(FILE *fp, const char *what, const piecety *x) \ + { \ + mpw w; \ + mp m, *y = MP_ZERO, *t = MP_NEW, *p; \ + octet b[noctet]; \ + unsigned i, o; \ + \ + p = getmod; \ + mp_build(&m, &w, &w + 1); \ + for (i = o = 0; i < npiece; i++) { \ + if (x[i] >= 0) { w = x[i]; m.f &= ~MP_NEG; } \ + else { w = -x[i]; m.f |= MP_NEG; } \ + t = mp_lsl(t, &m, o); \ + y = mp_add(y, y, t); \ + o += piecewd(i); \ + } \ + \ + fprintf(fp, "%s = <", what); \ + for (i = 0; i < npiece; i++) { \ + if (i) fputs(", ", fp); \ + fprintf(fp, "%ld", (long)x[i]); \ + } \ + fputs(">\n\t= ", fp); \ + mp_writefile(y, fp, 10); \ + fputs("\n\t== ", fp); \ + mp_div(0, &y, y, p); \ + mp_writefile(y, fp, 10); \ + fputs("\n\t= 0x", fp); \ + mp_writefile(y, fp, 16); \ + fputs(" (mod 2^255 - 19)\n\t= [", fp); \ + mp_storel(y, b, sizeof(b)); \ + for (i = 0; i < 32; i++) { \ + if (i && !(i%4)) fputc(':', fp); \ + fprintf(fp, "%02x", b[i]); \ + } \ + fputs("]\n", fp); \ + mp_drop(y); mp_drop(p); mp_drop(t); \ + } + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/x25519-tests.in b/x25519-tests.in new file mode 100644 index 0000000..a2d6263 --- /dev/null +++ b/x25519-tests.in @@ -0,0 +1,56 @@ +### Tests for X25519. -*-conf-*- +### Extracted from Catacomb. + +###-------------------------------------------------------------------------- +test x25519 + +## These are from Daniel J. Bernstein, `Cryptography in NaCl', 2009-03-10, +## https://cr.yp.to/highspeed/naclcrypto-20090310.pdf +## Make Alice's public key. +x 77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a +Y 0900000000000000000000000000000000000000000000000000000000000000 +Z 8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a + +## Make Bob's public key. +x 5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb +Y 0900000000000000000000000000000000000000000000000000000000000000 +Z de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f + +## Make the shared secret using Alice's private key. +x 77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a +Y de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f +Z 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742 + +## Make the (same) shared secret using Bob's private key. +x 5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb +Y 8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a +Z 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742 + +## These tests are from RFC7748. I've clamped the public values because +## RFC7748 wants the top bits ignored. +x a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4 +Y e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c +Z c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552 + +x 4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d +Y e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a413 +Z 95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957 + +###-------------------------------------------------------------------------- +test x25519-mct + +## These tests are from RFC7748. +x 0900000000000000000000000000000000000000000000000000000000000000 +Y 0900000000000000000000000000000000000000000000000000000000000000 +n 1 +Z 422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079 + +x 0900000000000000000000000000000000000000000000000000000000000000 +Y 0900000000000000000000000000000000000000000000000000000000000000 +n 1000 +Z 684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51 + +## This one takes aaaaages. +## 0900000000000000000000000000000000000000000000000000000000000000 +## 0900000000000000000000000000000000000000000000000000000000000000 +## 1000000 7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424; diff --git a/x25519.c b/x25519.c new file mode 100644 index 0000000..85c1187 --- /dev/null +++ b/x25519.c @@ -0,0 +1,108 @@ +/* -*-c-*- + * + * The X25519 key-agreement algorithm + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "fake-mLib-bits.h" + +#include "montladder.h" +#include "f25519.h" +#include "x25519.h" + +/*----- Important constants -----------------------------------------------*/ + +const octet x25519_base[32] = { 9, 0, /* ... */ }; + +#define A0 121665 + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @x25519@ --- * + * + * Arguments: @octet zz[X25519_OUTSZ]@ = where to put the result + * @const octet k[X25519_KEYSZ]@ = pointer to private key + * @const octet qx[X25519_PUBSZ]@ = pointer to public value + * + * Returns: --- + * + * Use: Calculates X25519 of @k@ and @qx@. + * + * Note that there is disagreement over whether the most + * significant bit of @qx@ (i.e., the value @qx[31]&0x80@) + * should be ignored or counted towards the represented value. + * Historically implementations respected the bit; later + * convention seems to be to ignore it. This implementation + * honours the bit: a caller who wants to ignore the bit can + * easily clear it, while caller who wants to respect it has a + * difficult job if this function ignores it. + */ + +void x25519(octet zz[X25519_OUTSZ], + const octet k[X25519_KEYSZ], + const octet qx[X25519_PUBSZ]) +{ + uint32 kw[8]; + f25519 x1; + + /* Load and clamp the key. The low bits are cleared to kill the small + * subgroups on the curve and its twist, and a high bit is set to guard + * against careless implementations, though this isn't one of those. + */ + kw[0] = LOAD32_L(k + 0); kw[1] = LOAD32_L(k + 4); + kw[2] = LOAD32_L(k + 8); kw[3] = LOAD32_L(k + 12); + kw[4] = LOAD32_L(k + 16); kw[5] = LOAD32_L(k + 20); + kw[6] = LOAD32_L(k + 24); kw[7] = LOAD32_L(k + 28); + kw[0] &= 0xfffffff8; kw[7] = (kw[7]&0x3fffffff) | 0x40000000; + + /* And run the ladder. */ + f25519_load(&x1, qx); +#define MULA0(z, x) do { f25519_mulconst((z), (x), A0); } while (0) + MONT_LADDER(f25519, MULA0, kw, 8, 32, &x1, &x1); +#undef MULA0 + f25519_store(zz, &x1); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/x25519.h b/x25519.h new file mode 100644 index 0000000..422d161 --- /dev/null +++ b/x25519.h @@ -0,0 +1,109 @@ +/* -*-c-*- + * + * The X25519 key-agreement algorithm + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_X25519_H +#define CATACOMB_X25519_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Notes on the X25519 key-agreement algorithm -----------------------* + * + * This is X25519, as described in Daniel J. Bernstein, `Curve25519: new + * Diffie--Hellman speed records', PKC 2006, + * https://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * Since then, the name `Curve25519' has shifted somewhat, to refer to the + * specific elliptic curve used, and the x-coordinate Diffie--Hellman + * operation is now named `X25519'. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "fake-mLib-bits.h" + +/*----- Important constants -----------------------------------------------*/ + +#define X25519_KEYSZ 32u +#define X25519_PUBSZ 32u +#define X25519_OUTSZ 32u + +extern const octet x25519_base[32]; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @x25519@ --- * + * + * Arguments: @octet zz[X25519_OUTSZ]@ = where to put the result + * @const octet k[X25519_KEYSZ]@ = pointer to private key + * @const octet qx[X25519_PUBSZ]@ = pointer to public value + * + * Returns: --- + * + * Use: Calculates X25519 of @k@ and @qx@. + * + * Note that there is disagreement over whether the most + * significant bit of @qx@ (i.e., the value @qx[31]&0x80@) + * should be ignored or counted towards the represented value. + * Historically implementations respected the bit; later + * convention seems to be to ignore it. This implementation + * honours the bit: a caller who wants to ignore the bit can + * easily clear it, while caller who wants to respect it has a + * difficult job if this function ignores it. + */ + +extern void x25519(octet /*zz*/[X25519_OUTSZ], + const octet /*k*/[X25519_KEYSZ], + const octet /*qx*/[X25519_PUBSZ]); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/x448-tests.in b/x448-tests.in new file mode 100644 index 0000000..f6efcee --- /dev/null +++ b/x448-tests.in @@ -0,0 +1,49 @@ +### Tests for X448. -*-conf-*- +### Extracted from Catacomb. + +###-------------------------------------------------------------------------- +test x448 + +## These are taken from RFC7748. +x 3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3 +Y 06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086 +Z ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f + +x 203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f +Y 0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db +Z 884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d + +x 9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b +Y 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Z 9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0 + +x 1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d +Y 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Z 3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609 + +x 9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b +Y 3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609 +Z 07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d + +x 1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d +Y 9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0 +Z 07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d + +###-------------------------------------------------------------------------- +test x448-mct + +## These are taken from RFC7748. +x 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Y 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +n 1 +Z 3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113 + +x 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Y 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +n 1000 +Z aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38 + +## This one takes aaaaages. +## 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +## 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +## 1000000 077f453681caca3693198420bbe515cae0002472519b3e67661a7e89cab94695c8f4bcd66e61b9b9c946da8d524de3d69bd9d9d66b997e37; diff --git a/x448.c b/x448.c new file mode 100644 index 0000000..332ff7b --- /dev/null +++ b/x448.c @@ -0,0 +1,97 @@ +/* -*-c-*- + * + * The X448 key-agreement algorithm + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "fake-mLib-bits.h" + +#include "montladder.h" +#include "fgoldi.h" +#include "x448.h" + +/*----- Important constants -----------------------------------------------*/ + +const octet x448_base[56] = { 5, 0, /* ... */ }; + +#define A0 39081 + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @x448@ --- * + * + * Arguments: @octet zz[X448_OUTSZ]@ = where to put the result + * @const octet k[X448_KEYSZ]@ = pointer to private key + * @const octet qx[X448_PUBSZ]@ = pointer to public value + * + * Returns: --- + * + * Use: Calculates X448 of @k@ and @qx@. + */ + +void x448(octet zz[X448_OUTSZ], + const octet k[X448_KEYSZ], + const octet qx[X448_PUBSZ]) +{ + uint32 kw[14]; + fgoldi x1; + unsigned i; + + /* Load and clamp the key. The low bits are cleared to kill the small + * subgroups on the curve and its twist, and a high bit is set to guard + * against careless implementations, though this isn't one of those. + */ + for (i = 0; i < 14; i++) kw[i] = LOAD32_L(k + 4*i); + kw[0] &= 0xfffffffc; kw[13] |= 0x80000000; + + /* And run the ladder. */ + fgoldi_load(&x1, qx); +#define MULA0(z, x) do { fgoldi_mulconst((z), (x), A0); } while (0) + MONT_LADDER(fgoldi, MULA0, kw, 14, 32, &x1, &x1); +#undef MULA0 + fgoldi_store(zz, &x1); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/x448.h b/x448.h new file mode 100644 index 0000000..401f4e2 --- /dev/null +++ b/x448.h @@ -0,0 +1,101 @@ +/* -*-c-*- + * + * The X448 key-agreement algorithm + * + * (c) 2017 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + * + * This file was originally part of Catacomb, but has been automatically + * modified for incorporation into secnet: see `import-catacomb-crypto' + * for details. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_X448_H +#define CATACOMB_X448_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Notes on the X448 key-agreement algorithm -------------------------* + * + * This is X448, as described in RFC7748, based on the elliptic curve defined + * in Mike Hamburg, `Ed448-Goldilocks, a new elliptic curve', EUROCRYPT 2016, + * https://eprint.iacr.org/2015/625/. + * + * The RFC-specified operation is simpler than the Diffie--Hellman function + * described in Hamburg's paper, since it doesn't involve the `Decaf' + * cofactor elimination procedure. Indeed, it looks very much like X25519 + * with Hamburg's curve slotted in in place of Bernstein's. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "fake-mLib-bits.h" + +/*----- Important constants -----------------------------------------------*/ + +#define X448_KEYSZ 56 +#define X448_PUBSZ 56 +#define X448_OUTSZ 56 + +extern const octet x448_base[56]; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @x448@ --- * + * + * Arguments: @octet zz[X448_OUTSZ]@ = where to put the result + * @const octet k[X448_KEYSZ]@ = pointer to private key + * @const octet qx[X448_PUBSZ]@ = pointer to public value + * + * Returns: --- + * + * Use: Calculates X448 of @k@ and @qx@. + */ + +extern void x448(octet /*zz*/[X448_OUTSZ], + const octet /*k*/[X448_KEYSZ], + const octet /*qx*/[X448_PUBSZ]); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif