Hack on the newly imported X25519 and X448 code.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 29 Apr 2017 12:55:40 +0000 (13:55 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 25 Sep 2019 12:46:59 +0000 (13:46 +0100)
I've tried to touch the code as little as possible to integrate it with
the rest of Secnet.  I've limited myself to:

  * adding Secnet notices and GPL-mandated notices;

  * removing definitions which obviously won't work;

  * removing code which is unnecessary given Secnet's less ambitious
    portability objectives; and

  * providing substitutes for some of the support types and macros
    assumed by the original implementation, in particular a fake version
    of <mLib/bits.h>.

I've also written a new test driver for the field and curve arithmetic,
and reformatted the test vectors, though the data remains the same.

The code builds and passes the tests.

Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
17 files changed:
Makefile.in
f25519-tests.in [deleted file]
f25519.c
f25519.h
fake-mLib-bits.h [new file with mode: 0644]
fgoldi-tests.in [deleted file]
fgoldi.c
fgoldi.h
montladder.h
qfarith.h
x25519-tests.in
x25519.c
x25519.h
x448-tests.in
x448.c
x448.h
xdh-test.c [new file with mode: 0644]

index 6bc02ef..d31d44e 100644 (file)
@@ -62,13 +62,14 @@ OBJECTS:=secnet.o util.o conffile.yy.o conffile.tab.o conffile.o modules.o \
        resolver.o random.o udp.o site.o transform-cbcmac.o transform-eax.o \
        comm-common.o polypath.o \
        netlink.o rsa.o dh.o serpent.o serpentbe.o \
+       f25519.o x25519.o fgoldi.o x448.o \
        md5.o sha512.o tun.o slip.o sha1.o ipaddr.o log.o \
        process.o @LIBOBJS@ \
        hackypar.o
 # version.o is handled specially below and in the link rule for secnet.
 
 TEST_OBJECTS:=eax-aes-test.o eax-serpent-test.o eax-serpentbe-test.o \
-               eax-test.o aes.o
+               eax-test.o aes.o x25519-test.o x448-test.o
 
 ifeq (version.o,$(MAKECMDGOALS))
 OBJECTS:=version.o
@@ -145,7 +146,7 @@ endif
 
 check: eax-aes-test.confirm eax-serpent-test.confirm \
        eax-serpentbe-test.confirm check-ipaddrset \
-       msgcode-test.confirm
+       msgcode-test.confirm x25519-test.confirm x448-test.confirm
 
 version.c: Makefile
        echo "#include \"secnet.h\"" >$@.new
@@ -172,6 +173,24 @@ msgcode-test.confirm: msgcode-test
        ./msgcode-test
        touch $@
 
+XDH_FUNCS = x25519 x448
+x25519_FIELD = f25519
+x448_FIELD = fgoldi
+
+$(addsuffix -test, $(XDH_FUNCS)): %-test: %-test.o %.o
+       $(CC) $(LDFLAGS) $(ALL_CFLAGS) -o $@ $^
+x25519-test: f25519.o
+x448-test: fgoldi.o
+
+$(addsuffix -test.o, $(XDH_FUNCS)): %-test.o: xdh-test.c
+       $(CC) $(CPPFLAGS) $(ALL_CFLAGS) -c \
+               -DXDH=$* -DFIELD=$($*_FIELD) \
+               $< -o $@
+
+$(addsuffix -test.confirm, $(XDH_FUNCS)): %-test.confirm: %-test %-tests.in
+       ./$*-test <$(srcdir)/$*-tests.in
+       touch $@
+
 check-ipaddrset: ipaddrset-test.py ipaddrset.py ipaddrset-test.expected
        $(srcdir)/ipaddrset-test.py >ipaddrset-test.new
        diff -u $(srcdir)/ipaddrset-test.expected ipaddrset-test.new
@@ -207,6 +226,8 @@ clean:
        $(RM) -f *.o *.yy.[ch] *.tab.[ch] $(TARGETS) core version.c
        $(RM) -f *.d *.pyc *~ eax-*-test.confirm eax-*-test
        $(RM) -f msgcode-test.confirm msgcode-test
+       $(RM) -f $(addsuffix -test, $(XDH_FUNCS))
+       $(RM) -f $(addsuffix -test.confirm, $(XDH_FUNCS))
 
 realclean:     clean
        $(RM) -f *~ Makefile config.h  *.d \
diff --git a/f25519-tests.in b/f25519-tests.in
deleted file mode 100644 (file)
index 96d4ac7..0000000
+++ /dev/null
@@ -1,1235 +0,0 @@
-### Test cases for arithmetic mod 2^255 - 19.
-
-add {
-  ## Some load and store tests.
-  0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
-    0000000000000000000000000000000000000000000000000000000000000000
-    0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20;
-  ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
-    0000000000000000000000000000000000000000000000000000000000000000
-    ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f;
-  edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
-    00000000000000000000000000000000000000000000000000000000000000
-    00;
-
-  ## Random tests.
-  bb8cd45b6185ee8ca34c4d7560425fd5c2fc22871113c6427198e8f9439a8523
-    98f16cc5e44b7228b7f3b6ed91930d68bba5071157d19259c48034d2817e30d5
-    667e412146d160b55a400463f2d56c3d7ea22a9868e4589c35191dccc518b678;
-  8ef938a7b07a668c234c2c5bb65115b8e2e22a3703cda51c70e7a56a075d4f34
-    1f3cd4bf4f768058c4de1aa5aeb90e227338e308c7a0a199050ca1c38d1e034c
-    c0350d6700f1e6e4e72a4700650b24da551b0e40ca6d47b675f3462e957b5200;
-  8b2c4678fd4f8b7254eea925e4da8d472db7f97d349d1b2134ced884b747ea7d
-    58dca7954f843b7e4dc56b048903e7728df66ef6824f29932b2f568c995ddf2c
-    f608ee0d4dd4c6f0a1b3152a6dde74babaad6874b7ec44b45ffd2e1151a5c92a;
-  9cd64f0cf439bccd224f7a789396b9f888998d1ba9759c93a5d6a27f45db0e67
-    12f724a127052612081e27e3915db9a540de9b64c566edc313914ad94424464e
-    c1cd74ad1b3fe2df2a6da15b25f4729ec97729806edc8957b967ed588aff5435;
-  82e59fa9703b2557303665fe24e3d46259da974d78155f05c6b8891f92fc808d
-    98a073ec62baf1354b681a3c78d62df1698ed5077dbe2bd68ba4a6e0233e3447
-    2d861396d3f5168d7b9e7f3a9db90254c3686d55f5d38adb515d3000b63ab554;
-  686ceca221d0f4c6d98287e97c506085064e7b172672b88ee555dd0308bfd309
-    60adc3675be5e6c2921a74b5b8b24b0a26341a19567dae713a720786bc72df16
-    c819b00a7db5db896c9dfb9e3503ac8f2c8295307cef660020c8e489c431b320;
-  a50a5b82d2451ed9a5844585712202a6dc0e0230501d57b8c00f4bd4771aed9e
-    98d71b8b140aea02ad47d9b19e47d2a03257adc1d5c47611adc667652b78c87c
-    63e2760de74f08dc52cc1e37106ad4460f66aff125e2cdc96dd6b239a392b51b;
-  1637e3eb4c5d173b8cba29bdb13b930f48ae0599e354819f8ae0cf70f0f7b61b
-    ffeef1767df70de7a4a75864c03935d7934c6cf5228b9c3000813ed0e55447e2
-    2826d562ca542522316282217275c8e6dbfa718e06e01dd08a610e41d64cfe7d;
-  9e8bf571c45bc5f37c9126e70498698978903b94d9c6712baef91894ab924fda
-    480f68f8ee644bfb64e3fa514eaf16aea6368da6813802c4c3e6ce8f6540dfa3
-    0c9b5d6ab3c010efe1742139534780371fc7c83a5bff73ef71e0e72311d32e7e;
-  df9bdbd478bd1ec1ff078cdc76f2a5fcdc52f0198ba412e0b5a10e664b175dad
-    080bc47bd2fb2ba3be6a07a02162f76020479f2cc6469c6766df23acf9517896
-    0da79f504bb94a64be72937c98549d5dfd998f4651ebae471c8132124569d543;
-  b6dd223f5d8a3dc5dd6f7a0679173ff656303017a17f17f4086fd4ecd3a23020
-    560d827aad23c26fddbfd16c3514a9b518a4586d6e3c5739860743662b14f4b4
-    1feba4b90aaeff34bb2f4c73ae2be8ab6fd488840fbc6e2d8f761753ffb62455;
-  1d59691a670c40143ca7f7e693389ab64a911b17a2fe4368fba9097b40864162
-    cb42d3ba12a8b90ef1622ea09241d3157c515043040914356d6d99b95089fa07
-    e89b3cd579b4f9222d0a2687267a6dccc6e26b5aa607589d6817a334910f3c6a;
-  82b48877e9c8c18edb52db3e1417d894e572a8edd84335d93c642158f2a926e0
-    93c6a39c1ef97f318c3b13bf8e77bea653b2eb130bdf43b00a0e0e40a362e819
-    287b2c1408c241c0678eeefda28e963b39259401e422798947722f98950c0f7a;
-  a6137481c5b9b8bcb3c87f3868c5f812da71aeb21c5ce18a508773120ea4f659
-    812eacdc5a8eb2e8fde0c23a19c2e33466d754ab3109d28ff48fb41dab8066e2
-    4d42205e20486ba5b1a942738187dc474049035e4e65b31a45172830b9245d3c;
-  598fb4096a7054e317e66bc9633d56dfcaeabc31a7bbc9da13074b242edeca09
-    929b1bddd55c99b06b99a3ffbac5adc1d28823cb8354adcfea60b7a87fe32039
-    eb2ad0e63fcded93837f0fc91e0304a19d73e0fc2a1077aafe6702cdadc1eb42;
-  c42183d915267e655409326b1b77a042d8918feefd75dd3d18551f398ef426e7
-    e3729a6110686ffa57d1c69284a60fb36173148a89b1810d04614f03c8f90084
-    cd941d3b268eed5facdaf8fd9f1db0f53905a47887275f4b1cb66e3c56ee276b;
-  67b8b7ea7e7f9f52d686f906589c919b293bff6d3127e7ac581dc1630af7bcc1
-    99d18d2190ef0da148b843c014fea3efea59f9adbb28fa38407191fcc24e029c
-    268a450c0f6fadf31e3f3dc76c9a358b1495f81bed4fe1e5988e5260cd45bf5d;
-  bc3422b79e01234fefd3637a19bfb2dd0a83bf2071b27bf5389918a50e579294
-    b665dffe064aceffaabba94697cf27054d016427ebaf68858c5250cc5c1b770f
-    859a01b6a54bf14e9a8f0dc1b08edae2578423485c62e47ac5eb68716b720924;
-  d419cbfd5514d9cffa1765b9f273fd7492000a3d110586ed0b8137760a2e808e
-    bcb52f423917c074464b2078d1c3f883fb793b02411b8b13c08266d17658a499
-    b6cffa3f8f2b994441638531c437f6f88d7a453f52201101cc039e4781862428;
-  2f7eb8051d16a52b797e2618881bd0857eb205bf97e581e09680f86308f7e082
-    9ceda63b29c3bfedbb6f3f0be2f3f2bd285bb9d21620c3edde69629b00b1c3cd
-    f16b5f4146d9641935ee65236a0fc343a70dbf91ae0545ce75ea5aff08a8a450;
-}
-
-sub {
-  dfb53b4ff67c742728c564d50ae20e3e3617804478a95e511d37ff4dcf04fa3f
-    9bc2006bb07dcf7bf0b461e7599e3c3cbfcdf6b6f41fc1db2219767ce9c43bcd
-    1ef33ae445ffa4ab371003eeb043d2017749898d83899d75fa1d89d1e53fbe72;
-  432ec65076c94af41e054a43f64fe4eecb23f50a303fd38e0172e4e846e67394
-    3642c84c5f5fcd5a0f3f2e37114beb8e7b614c39d354f1b32fe7e9cc918da5c8
-    faebfd03176a7d990fc61b0ce504f95f50c2a8d15ceae1dad18afa1bb558ce4b;
-  1725a986c03d9d53346ab2064545ba90ab38191e19ded9ecc2f44d422ab04150
-    11a20caef0239e4ffb5ab2f7d3576633a0d4a08c78a02f35765fafff5398c48b
-    f3829cd8cf19ff03390f000f71ed535d0b647891a03daab74c959e42d6177d44;
-  ec5d5cdfc8183f9aa3d47634d16427c3a399e2166bfa4ddfecbc911e5f33ceba
-    649f8e29c483765c4232c369fd0e50a0026eac306eb4bd6924e7b4d7d3f73e26
-    9bbecdb50495c83d61a2b3cad355d722a12b36e6fc459075c8d5dc468b3b8f14;
-  cc9927c331884612d8fab9a2262ad0db38f55e0cc587e45b972ea8b1f504450d
-    30c5c9f8d5491a350051bbc6bb78e568d98061b43cb1797cd3d7454e8a7aa1bf
-    76d45dca5b3e2cddd7a9fedb6ab1ea725f74fd5788d66adfc35662636b8aa34d;
-  662bc96da214e50f13e07a15b8e0b78f512c744a66975b2170ba28079ca7d03b
-    84b072295dca0abef806ec5c1e594179dc5e9eb172c178af1902a42ea7a3728e
-    cf7a5644454ada511ad98eb89987761675cdd598f3d5e27156b884d8f4035e2d;
-  ed6f947157492eccc5fb1d0542593d58a47e2d87355dc0378e65376163fcf457
-    cb27e06c5ebf42a61caadd4fb222799772aaef31487bf61ac84c15f58af265d3
-    0f48b404f989eb25a95140b58f36c4c031d43d55ede1c91cc618226cd8098f04;
-  33c2fc57d8ffc29e6d670cfc4e25b695320055cf443ade53f49f6c23c452f644
-    3814860ccbb4391894c107961170d3af1594988a7972b97d0fb2169631b216fa
-    d5ad764b0d4b8986d9a504663db5e2e51c6cbc44cbc724d6e4ed558d92a0df4a;
-  d0fd0d5e73be5c534aa37645aecc49b202fadb30733f16d0de719a70bec2c751
-    910c7b4d317397cff70c91e5bf8ec42ba1700b0866adbbfe99b7fbb2c46c7093
-    2cf19210424bc5835296e55fee3d85866189d0280d925ad144ba9ebdf955573e;
-  e0f8130d6b0125e824b254ed57edc59455a8a4704a3f14a4ae8dbf8721595468
-    4e4f69af6f85742068ad70225e8850c85aef3d3fb3ba3b52c2be979db4eb979d
-    7fa9aa5dfb7bb0c7bc04e4caf96475ccfab866319784d851ecce27ea6c6dbc4a;
-  204d5f69ebab4597d2aa9295ecc2959480a2ab0b225674cc8a147cf7c1e59717
-    3abdd29c94819ec7507673bd5cc4fb267fcb17c1509abd5e462b46b012f815a8
-    c08f8ccc562aa7cf81341fd88ffe996d01d7934ad1bbb66d44e93547afed816f;
-  e2d75c74060aee615b6cfc815c8618f826b07c4987e10f20d27ff74eab3ac7d0
-    7a06b32d284b5faedb91dac8e94cb7f76c678bad81ed78ac4e75eb9edd8d11e9
-    55d1a946debe8eb37fda21b972396100ba48f19b05f49673830a0cb0cdacb567;
-  8d50b0573b0bb945bf128e1a9a37c151e991581673cf6295db5a6223d428ac9d
-    47ca477794fdf378f3486355b5348960ee957470b8c74d62199ac48b4478c4ca
-    338668e0a60dc5cccbc92ac5e40238f1fafbe3a5ba071533c2c09d978fb0e752;
-  b66b49190a99456aaac5c33beaec423a3fa79a84df0f00122aed29151185ceef
-    13c06f7941743bfa261845d99772fd0d5f1a8258aeda53b161505ed8bdca1bc8
-    a3abd99fc8240a7083ad7e62527a452ce08c182c3135ac60c89ccb3c53bab227;
-  44ac89bb8d4de1a8756b00401236ea4e316a2fe637f6e5f052576da70c29c4ea
-    05dd39ac32768d899b80ed10279aa10d6316d60ab2d061e877dc5f21ce8e1140
-    52cf4f0f5bd7531fdaea122feb9b4841ce5359db85258408db7a0d863e9ab22a;
-  ef0f6c7f56ff22260c66d583f79c7f581181d3a0f3167c93786bb6c89de4372c
-    be934afeffaf5e6755a92e6606ffd054627dbe1b18ad6ae543363a01da605512
-    317c2181564fc4beb6bca61df19dae03af031585db6911ae34357cc7c383e219;
-  773e0db8f86c5182b5f51d10376f42cde275dac6a646ab1cab065760e045107e
-    3f92ddafdfe67d357b4f9b61807bcb8b0f1f6c2dacba27902f48fc15a31db606
-    38ac2f081986d34c3aa682aeb6f37641d3566e99fa8b838c7bbe5a4a3d285a77;
-  34860a848d0afb20e43f4a36b3c8941f5821864216da9cb3ce1a11f056565a3d
-    9dfed86048acd45ec0009c1ba3b20a1ba645ec141070fd8ae41d25e159bbce9f
-    84873123455e26c2233fae1a10168a04b2db992d066a9f28eafceb0efd9a8b1d;
-  854ba91672ae1b8f6c29395dcfa4f3514ed97dc2c9e1e419f926825619fac55b
-    7a700653ad355caf17f89045ecfb3ee821194b54048e55d8eed41fea2b0a22ab
-    f8daa2c3c478bfdf5431a817e3a8b4692cc0326ec5538f410a52626cedefa330;
-  0c66b3d8c3916940b70d381d232ba8aecfe27e3ae63fa6cbb287216708f224f0
-    477186656245c4083dff93a95c6e5deb707916e52cd74abbd522743c24c53088
-    c5f42c73614ca5377a0ea473c6bc4ac35e696855b9685b10dd64ad2ae42cf467;
-}
-
-neg {
-  0000000000000000000000000000000000000000000000000000000000000000
-    0000000000000000000000000000000000000000000000000000000000000000;
-  23d767107e23d5ce14189cce939c4b5334d6736da3da40a715236b9d8319efc1
-    b72898ef81dc2a31ebe763316c63b4accb298c925c25bf58eadc94627ce6103e;
-  9bb944cfb58b186cc551e0a0eca74528c7618ff47485bf6a723f43d990f69f6e
-    5246bb304a74e7933aae1f5f1358bad7389e700b8b7a40958dc0bc266f096011;
-  bff36d2aa923d5a9af5398e2cfcba4acdf3c3181a8ff00b8a1099cd97a4e8542
-    2e0c92d556dc2a5650ac671d30345b5320c3ce7e5700ff475ef6632685b17a3d;
-  1b65a51746eabb7c0d8d9844dda03bde7128407e94661db2d5fd9c0f3790d120
-    d29a5ae8b9154483f27267bb225fc4218ed7bf816b99e24d2a0263f0c86f2e5f;
-  88f4cf29a610c4465f63a272fde2f19a4874a70a0829885014379b637ab0e82d
-    650b30d659ef3bb9a09c5d8d021d0e65b78b58f5f7d677afebc8649c854f1752;
-  94ca4d567efcf088e6bf1cb3698f6b8bf2164db4f523e28781aebfcbb501ec63
-    5935b2a981030f771940e34c967094740de9b24b0adc1d787e5140344afe131c;
-  3f8d7ae4f1698921524e49ccb2ce4459e4c048f76f04c5e60179f5417d2d52db
-    9b72851b0e9676deadb1b6334d31bba61b3fb70890fb3a19fe860abe82d2ad24;
-  1eaa0c45af0d8f85d865cc66ff3d0dc3355f1ac36821cdd95a6b9232a27f9044
-    cf55f3ba50f2707a279a339900c2f23ccaa0e53c97de3226a5946dcd5d806f3b;
-  33e142c78ee87a7980ade6c796e7ff949cee6d3af0415bf5b6901f84c2db910a
-    ba1ebd38711785867f5219386918006b631192c50fbea40a496fe07b3d246e75;
-  24a0c185c47787caf1a666a62002a503f2a3e591e5f2946e148a47b9b114a884
-    b65f3e7a3b8878350e599959dffd5afc0d5c1a6e1a0d6b91eb75b8464eeb577b;
-  a8bd0c1c3f219a97de87b22e8cb3eb5daea33b5646589b6925ec4ec83ca37455
-    4542f3e3c0de656821784dd1734c14a2515cc4a9b9a76496da13b137c35c8b2a;
-  1a340d2679ca205f6b198cff4bffadcde1afeeed124ef0c574655dbe8732b681
-    c0cbf2d98635dfa094e67300b40052321e501112edb10f3a8b9aa24178cd497e;
-  da43c139a1f92ba1b5fc996befe5218368eac3c46b42e98a9cca8b8f6f1540f5
-    00bc3ec65e06d45e4a036694101ade7c97153c3b94bd16756335747090eabf0a;
-  81aad864a31e5f4afa32c29eb97f22c103dfe5b1323db05fc9b1545312aa6c0d
-    6c55279b5ce1a0b505cd3d614680dd3efc201a4ecdc24fa0364eabaced559372;
-  28231ad38d214f1421df7005eddb4f4c12e522b10d1cbcd10ee26dfcc222a62c
-    c5dce52c72deb0ebde208ffa1224b0b3ed1add4ef2e3432ef11d92033ddd5953;
-  c1facefef35c1ed00db767ed0281ebfad1f3c915c6649f5e1c26a6f3f9478b43
-    2c0531010ca3e12ff2489812fd7e14052e0c36ea399b60a1e3d9590c06b8743c;
-  c2e4046e7200386ca2afea8ecc9c98c105fbf6e31b598e21e482796a69956040
-    2b1bfb918dffc7935d5015713363673efa04091ce4a671de1b7d8695966a9f3f;
-  a42fedea4eac90580a0bbcb0491a7e8cc82de7a99aa74ed35f705c536afa0236
-    49d01215b1536fa7f5f4434fb6e5817337d218566558b12ca08fa3ac9505fd49;
-  d1ab8c50d54279ceac870d0ce4a2af56bf8c03e87482dcb7775183a4908ac739
-    1c5473af2abd86315378f2f31b5d50a94073fc178b7d234888ae7c5b6f753846;
-  1ffd85fa5ead53ff509756fc28051ef65eca040303b65f7b5b7e1d1a8508e030
-    ce027a05a152ac00af68a903d7fae109a135fbfcfc49a084a481e2e57af71f4f;
-}
-
-condneg {
-  5330763b29dff20501a1d6c64025c36279083473721f5cacf89168189ff9810d
-    0x00000000
-    5330763b29dff20501a1d6c64025c36279083473721f5cacf89168189ff9810d;
-  9d9c36e2126d911a503e1cc1a8489ee74949ae2a8408dc7d72ed0d75e4350545
-    0x00000000
-    9d9c36e2126d911a503e1cc1a8489ee74949ae2a8408dc7d72ed0d75e4350545;
-  47da10abec2cb54c5890e5945999deb1d89ffd268bbbe2eafc86f1acc8bf5f7e
-    0x00000000
-    47da10abec2cb54c5890e5945999deb1d89ffd268bbbe2eafc86f1acc8bf5f7e;
-  3e6ec07de86be6ffab2dfa1deb9ed67844645be92bdbb22b7ba91379babcdfed
-    0x00000000
-    516ec07de86be6ffab2dfa1deb9ed67844645be92bdbb22b7ba91379babcdf6d;
-  5f5c0730649586b5c0b60a14d3b669b3649eb6725d71d834e78ff2aa0e5450e5
-    0xffffffff
-    7ba3f8cf9b6a794a3f49f5eb2c49964c9b61498da28e27cb18700d55f1abaf1a;
-  c357befcc6836d89387915e368e5e6162252b433eb58d94eb3cc4b783e98c226
-    0xffffffff
-    2aa84103397c9276c786ea1c971a19e9ddad4bcc14a726b14c33b487c1673d59;
-  713ad0f656a8fcd75fdee2c4ac248ee7ad09a5f357c565daa94ae46d8590d2c8
-    0x00000000
-    843ad0f656a8fcd75fdee2c4ac248ee7ad09a5f357c565daa94ae46d8590d248;
-  909d669185e98b4a88a6531b830193b23035d64665929e34e86d53c4a9eef30a
-    0xffffffff
-    5d62996e7a1674b57759ace47cfe6c4dcfca29b99a6d61cb1792ac3b56110c75;
-  8f23ec139f93258e6d57fa278339f1cb5da193c5d1ad7183fb2b151111262285
-    0x00000000
-    a223ec139f93258e6d57fa278339f1cb5da193c5d1ad7183fb2b151111262205;
-  a9a5480c72157f389be80ae7ad63502434c380ccd1cef813dc9bd2e9a85e2f22
-    0xffffffff
-    445ab7f38dea80c76417f518529cafdbcb3c7f332e3107ec23642d1657a1d05d;
-  316f98b6697e7daa8775d3aa91dee8fbbae4e935a2f62cd2975e2d552f0c9846
-    0xffffffff
-    bc90674996818255788a2c556e211704451b16ca5d09d32d68a1d2aad0f36739;
-  70128d6dd5fb42f287fba3533c71cb5dc2361b6d91c3d9626c58849e27f7d349
-    0xffffffff
-    7ded72922a04bd0d78045cacc38e34a23dc9e4926e3c269d93a77b61d8082c36;
-  66a6f3dc6274e4122dc401ef23529175d71d96b660a52cdcd64556073b5430b2
-    0x00000000
-    79a6f3dc6274e4122dc401ef23529175d71d96b660a52cdcd64556073b543032;
-  3909505812b228e6ca5cc6c0b17824ef765923eded6105e6eb0f176781624c5a
-    0xffffffff
-    b4f6afa7ed4dd71935a3393f4e87db1089a6dc12129efa1914f0e8987e9db325;
-  b7febd7d63efae3bcc60c1c344f2f6166b272eed785a9e541d3ff4f12e82a5f3
-    0xffffffff
-    230142829c1051c4339f3e3cbb0d09e994d8d11287a561abe2c00b0ed17d5a0c;
-  d1cacc1db40de13351224046975319d7546ae9e88e1909c2a8f46792a140d279
-    0xffffffff
-    1c3533e24bf21eccaeddbfb968ace628ab95161771e6f63d570b986d5ebf2d06;
-  4c449a50fc1e145be1463e4c171b3c51c9683c41c45005d8aeca607911c9b3be
-    0xffffffff
-    8ebb65af03e1eba41eb9c1b3e8e4c3ae3697c3be3baffa2751359f86ee364c41;
-  c929c50eedbad6ceacdefb00bd58a32820c874c906741e9d93cd0f668819edcc
-    0x00000000
-    dc29c50eedbad6ceacdefb00bd58a32820c874c906741e9d93cd0f668819ed4c;
-  1c57449dcfc7e8f9fab77d226d4b50d7dee06c29d08d3d4f4ae7c8ad238a0a82
-    0xffffffff
-    bea8bb6230381706054882dd92b4af28211f93d62f72c2b0b5183752dc75f57d;
-  396a2ddc48f158e73c95dc289da3f0d3b2128875e20c401cb50fd6cc7a28dd18
-    0xffffffff
-    b495d223b70ea718c36a23d7625c0f2c4ded778a1df3bfe34af0293385d72267;
-}
-
-pick2 {
-  e6f52222f35081896f3d9ecc0ffb27fa3e75c8ad1c98e161878d2c3cffd72c78
-    a24cd71f7acb653466b7d67bb41efb5a29503d2627d2ce28fe19680ccd939be5
-    0x00000000
-    b54cd71f7acb653466b7d67bb41efb5a29503d2627d2ce28fe19680ccd939b65;
-  4e51fe2dac96a664d0675962116b7af4e605194a1c9fb774c621a3107994c9ed
-    508934be10ce5e11e6940d56e84b148e20f48369e748536846763c80bab9af49
-    0x00000000
-    508934be10ce5e11e6940d56e84b148e20f48369e748536846763c80bab9af49;
-  530175217081c3fb3ecd17702ad334ad48f05affd5ab3754ef10be5b0eb5375d
-    8aebc7e01e2bb2829f21311462175948d85cd3e65d676eec893e3df13f639d07
-    0xffffffff
-    530175217081c3fb3ecd17702ad334ad48f05affd5ab3754ef10be5b0eb5375d;
-  0e53c5141d72c8c81d80b1a1283b0267b278f98e28ce08ccac7b010022e5adae
-    2215cc15e950d6abfffa26113f269628f50f9ac37ad3260ae9189958d75080b6
-    0xffffffff
-    2153c5141d72c8c81d80b1a1283b0267b278f98e28ce08ccac7b010022e5ad2e;
-  3dc16434679d30686d5023fda4cc574563841caf1d588e965fe1ec1c4ba54398
-    4ca50330751d33ebba981277926a3fb801d216474cb183f90947680f5ea383a2
-    0xffffffff
-    50c16434679d30686d5023fda4cc574563841caf1d588e965fe1ec1c4ba54318;
-  09e68cb66b5ae2f3160a71738d1e9a042b9b76335eddc4b9466d0c6b8100eeb6
-    270eb833ae635bed17df9218a53a91b7afeb74f0df3bfffb8334c04773cf716d
-    0xffffffff
-    1ce68cb66b5ae2f3160a71738d1e9a042b9b76335eddc4b9466d0c6b8100ee36;
-  831b8a99e3b44bf21cdd4f3c06da7c16a95e98f3dc42cf2ac282edec67d9b2ca
-    482840e31c7620de6d290d747afc63ca199c60169f8eb62d28ca1142c5336990
-    0xffffffff
-    961b8a99e3b44bf21cdd4f3c06da7c16a95e98f3dc42cf2ac282edec67d9b24a;
-  a022ace6772d82d30832328c7cbfedb622b710d1fe9313a77dc4cc5ca577a7bb
-    39c86c57bf581c16d8c03b4ef0fe813815b5da1281f03bb3f2cdb0ddf19868d0
-    0xffffffff
-    b322ace6772d82d30832328c7cbfedb622b710d1fe9313a77dc4cc5ca577a73b;
-  719d3f13c38b915873bcb14308bfd9bb6f4a6cfd249a745bceb55787ce480caa
-    c72de6e206ed24555d091763644d4405f2ee5dbd846a036d6a21442a6c40e0c6
-    0x00000000
-    da2de6e206ed24555d091763644d4405f2ee5dbd846a036d6a21442a6c40e046;
-  07cdd3cd677a3c1783bcf7855bf1dbb453809b66c66c7bbbb67690cea33ca581
-    c9d889281ac117390875739e4b62df6dc3cca6c65439c46bb907c81d3a961fa3
-    0x00000000
-    dcd889281ac117390875739e4b62df6dc3cca6c65439c46bb907c81d3a961f23;
-  a69a728035cc69d5d3f96dd4a8081864333e53e434820dd569deb9e58393d4b7
-    3f4ef71dfa1eccd817d3192dbe2e08466e4a66b4d836b0892b3636dc523098ed
-    0x00000000
-    524ef71dfa1eccd817d3192dbe2e08466e4a66b4d836b0892b3636dc5230986d;
-  d249414415ac4960e934d29e08c75ff1b18431a6e18f7404e638293d3d8e81d5
-    33cd02e07762f74976834d1b6dd3b8eb7e2ad7a5d04ba90bbe747476071f10cb
-    0x00000000
-    46cd02e07762f74976834d1b6dd3b8eb7e2ad7a5d04ba90bbe747476071f104b;
-  efb782aba4dca351a5c9279b370073840b977b2458c6c84c9c9046dc92cc5507
-    6d9f50eb56b84989aab77c54987f05c715b74185417863f2c275635d2d6f2eeb
-    0x00000000
-    809f50eb56b84989aab77c54987f05c715b74185417863f2c275635d2d6f2e6b;
-  10c4381ed467e27d756ff7a260a6ffd282ad757b10c9956c518a43117699ee91
-    9b9a70c67be3296ef9d65fdd8014c4b263c28fd31f3299f4461c688c469ff704
-    0x00000000
-    9b9a70c67be3296ef9d65fdd8014c4b263c28fd31f3299f4461c688c469ff704;
-  5a30428bee407ee673ec7d2cb4854efd80b9761df5dec906463f888f60be7152
-    fc2e139be53203eb73041e9335253534c420208164682c2e02f31f084f5582f0
-    0xffffffff
-    5a30428bee407ee673ec7d2cb4854efd80b9761df5dec906463f888f60be7152;
-  43c7cd903c7dd7cdab85c6b5585955163e0da7dd0c5b5882ac620246619af342
-    0eb52162c69425ad75b778c39746014789f7929119d4e122d4b98bf64784fcde
-    0xffffffff
-    43c7cd903c7dd7cdab85c6b5585955163e0da7dd0c5b5882ac620246619af342;
-  f37f3707e4609d389096c1fea551b572a6b4644fd6af2e9e7a0fa93a91ae38e5
-    d10dd4d911346a5952e3123d4f156a7e40807d142c4afb4bc314ac6f9346dfa8
-    0xffffffff
-    06803707e4609d389096c1fea551b572a6b4644fd6af2e9e7a0fa93a91ae3865;
-  a4f4c203cb892691a6d6e9dff8a10ac1a8d9470b13ba24e1bddac05d6d7f9c0e
-    b88145fabdeaa9fa108bb04a4d283ac034b4c8d8ffe1b2174de9a80254762c54
-    0xffffffff
-    a4f4c203cb892691a6d6e9dff8a10ac1a8d9470b13ba24e1bddac05d6d7f9c0e;
-  649d8ce64f623228553de99b823c5f5c5ef37f00e2ddf658fc9bc2405afde715
-    0f24ace92223d2db75e2d82e8a5bc8b0e7981478216b999d2bdde9c72732d58f
-    0xffffffff
-    649d8ce64f623228553de99b823c5f5c5ef37f00e2ddf658fc9bc2405afde715;
-  3f466e24ed4169ca3df624d747f054f97422d5eee3fade2fa3c4eba488694a6c
-    37e3171c9aa56d07ffcde4f1fd0fdcc41e2086ecf93c9e53f3f6a4c3e4db587c
-    0xffffffff
-    3f466e24ed4169ca3df624d747f054f97422d5eee3fade2fa3c4eba488694a6c;
-}
-
-pickn {
-  "91aaaaf3ff9e58f299c0f6d0a4a3851d100423e4b7380d5a32a86cde6cb19562
-   e586b4ab140cd20bfc70aa5ae1c389941a8c631ce033f54793d77c91b5e3d50b
-   911122291921aced748e1346261ce8dc0e50704bf59495c3d7c1a9806ae58b5e
-   dac7c42fc0253029c78310ea1508b2464db2c44689fa7d485fb5863b7c136f15"
-    0
-    91aaaaf3ff9e58f299c0f6d0a4a3851d100423e4b7380d5a32a86cde6cb19562;
-  "e8864778a3aecd6f35f8afa097072e94c4e50680baf91a6036f4f24fb0dcf111
-   5dec44933a517f5a8bf6d858920e1200c74e65132baf0d08ca033e36e15a1c46
-   4fca88e6d122c0a460b5dd502281d80616edd30bede891226b4b3c4b3eb9eea0
-   5fbf4e034d45326d89ffe92bf4738a7120c63ea42568c25acacf4dd7915b9e8f
-   343001277d416dd31dc770232fc47c7d02884fef3fc10eaddf6f8b42fbb00b26"
-    1
-    5dec44933a517f5a8bf6d858920e1200c74e65132baf0d08ca033e36e15a1c46;
-  "f0cfc16fe0cb8910c26f6f46e69954dd34277d171044140c2dc448b6f63e053c
-   d54feccab8d55297eb24f622818aaa2ac5b7fcafee5efe872bb600cbdce85a3a
-   5f1cb6c6b4e8eedb566150a99a7c92228e7f737efa1810b9d40f9a4ea020e56d
-   c762a32a3f3a6f8cd956412eacdaa75ee56b347b952a7c18dd19c0ee2e50b8fc
-   b6e76d1d2cdf04692036f26515ca6b92d57b1bba625f07553d2d4adf89de9611
-   874c9e94d425fe9590aa1cde396ec56531342207a0e3b42ef0ae710bc9b68418
-   872ebc0bbd45d07727887aa8116a5743880093c73b3048c3b46920c04e0f64e2
-   9cde037629d20a4481ba7050546eca2dfd293b0953aa708764531bd8d0fba387
-   e9f7cb8ed4af14ac61722de66406e97ee9a87d9362dfa87e489a9c98f8b891b6
-   6c5bb4410d83505ad34d10409d02fc005a47ef802b5d9130f3b5d385ff78957e
-   ff40983b47e7263665a03e4396421fc34209afaf52d7d69012833b4a228e6c40
-   4588ed141f6401c460ff6ad4888172c9d19f15f214d96bedd59f818d7c03b720
-   99ede977304bc4e8f5edc44463b48fc13c001f5c584f2b100c791ae472fdddba
-   8ba76d6aa98a062e1091ca60e05ecf21208657bf287f20c6cacaaeff41a537ff
-   a18760b118187f5b392637dd5c5f97ccce583b5b84b69f8e37d8caf77c616db0
-   7e921cc5caa3b3884358cb0ffd2d9d160ed54256049fa1540d861dbb6dd1631d
-   aa8102188fbba89c45259c52080b3969c234d070411bc4b91870a8b482eedfbf
-   d98da58b248507edf310beb9fb522dd23d88bc0412ef3b5bd7a13b7a15070647
-   0626183221836da09c9bb5a1dd07df570883af17a9a8fed1c4bc7e8770e348fe
-   16b01a5593b3eaf0902d0ade7e00da7b7a57556c2e7169e8b6ba5df5c5fb02a5
-   e40715b07034e109d79a95a8b031eebc6c59dd0bb77de6cb960fe65a6d1be59e"
-    20
-    f70715b07034e109d79a95a8b031eebc6c59dd0bb77de6cb960fe65a6d1be51e;
-  "e30f85631b4ea4aadb9487c76cbec40ab63101a482e5aa2e3ee329fc21071bf4
-   8bc9fdd41fe1ecf5c2cc2075c72e4ceab370b099ddc672ee16bbd7a7de19dbb4
-   ede086a76fedddb463d9f0fb44b39ac7fb64665061eb96015d4ed39eb33cd772
-   a7cd74dc0c94aa8bfa480a88396b7f293f1ac329e4ce79e04507be4edbf4fef1
-   45f5c114a46bf0b2c8be1ecb8fc7c81e7fef668a2e4e9769f2f2dfecf405af92
-   123d101a02348f81088beeb6fafb7f720b49631736829d2f19e95b8d833684a3
-   ba936ae1b5555b05601c2e59bf9585846ac01b5b7f6fe4bbd45e0653e961deaf
-   51c0c307d99e34a617ead92dd37e1a0f36ebe2e45ef5b3690fd114099d483dc6
-   af94cee7979c057995680c3a5adfe26e7dea759e2640b0b09aff383fa355d289
-   6ddb6908532c513f463473e449747f88d47766460ad316734c2cca87963b3060
-   88192953b60710667d47633be71d87214d2dc8be882ceb6928daf311499d2e83
-   37da1b76c2c16025f0644b6451027c8bc9768379c3aa7ab8410d34d8c8222706
-   1a46c0531cc13f546e001a67721931f4f6bf8eeeadaaab667ee651db0b272509"
-    7
-    64c0c307d99e34a617ead92dd37e1a0f36ebe2e45ef5b3690fd114099d483d46;
-  "9929839bce983fe53c4f8f9d07a462f82e8eebabba2c0daee1378abf585bb53d
-   4e47d3997d6562c7b0347acc96925bd1907bf3a9c57d51b099c4a574d7bf8fc7
-   a0de02656ba18dd1cfdb2938fbb864f9f59001110391ee1818f5c1dfee64f61a
-   9c4153154f5b827bb847edfa04ce754e442f2e96ea001fc27f6d94ea8b06fc00
-   7ba90562980966abd857be3a84c1bffeabbb589415e722e51225f8317e829777
-   ac4657b264ccfad4f5ba3f7a470458101d5c6025c45d00191ddd4bf85ca48705
-   8b11cfc6ceb02c5d4b3e19c19f1ae745fd0cdfd9da1a80e9df1be8f7bb99ace3
-   1202bae1f86d05ed8fca09965bb1cfa3fb696a3f2b7089ee10589394639da2bd
-   143f799fc9ebec77aa444eb5ec95f64029cf61b875a2f94e228323844cb8eff9
-   dcf99568b397db79bd2e8ae49778e1e49865e91525f932a1813d1c395420a43c
-   84fdfee8137558f0b9f2441c375fce466e3212c0d0de3179919fb130e61b711a
-   602454ffaf59610f76863a7456146f866539740d6dae63a3628d408e34db8e76
-   86ae4475d41ea312a97c821ac78b815e459dc6bb4d52c236a39e5e53ff17f5fb
-   0fd56e878b74a2daebc2acc30c31c279f3dab146d748e7aa9b17eda7ac039c8f
-   e559e8bbd51113f84ebbe35ab16bfd46cf610a5c61307b986111ddbee3037f7a
-   bac90f3afdf4f4828368090958aef5e49aa83d25fc5dc15d9b8a354a30961e75
-   253eee8f614306e59a31d9fab5423ea269b67babd54c52243b86b8af1372f3ab
-   69828b787af1831f772a3bb9a410dac8bc47909ac6bddc94a5c600a3167ce780
-   1903e9ca239847045875b0bd4e1575a724d9f729e3cbfc377de17ad29839a121
-   57bc65c0fd8495014f31e3be740967f3fd1884bee743b20b947339923530d63d
-   cf7427ebf6088e6f3385275f993b5c06ee14f738b59d49ecc327521ddced2a4a
-   74c2a4122225e97b646d6a38584626a6ed811506ee7cd00b48ba563b7a776380
-   604f163d7d7f4987c8aaf2e7a946cec1597ebeb59aaeaad0dbd0737527b9350a
-   30e7ae69cd5fb42ec00ca840988a59bf5688aa0b810bb2e9ea24fb5b322891a0
-   68caff542deb61b055bf65127a94d8ab107f5d2496764f97351dbbfbf34928e4
-   c0d307ece7f18150d958bd88bf11912dc818fac7cae06ca9ec3fafd15d452af8
-   731b9ae286f29660fd0814568351bd6da114f3ee8b87c217cfe531746faa8c90"
-    8
-    273f799fc9ebec77aa444eb5ec95f64029cf61b875a2f94e228323844cb8ef79;
-  "85b3448d0292edc0b14cfae9225989a16a61ee8441166d5b97faf876b0ab6c7d
-   88b0f7c78f8390b6cc1de0afda111326dbb41e7603b82033902eb56ea542c2dc
-   daf45d38b24294648a7b203758ff0654d42507e958bbd98c72229aae0a9e5757
-   98b44fbbf6e45c81c2473b626307506881a9fa609c546741b3637b731ff62adb
-   c0779c0f0a35658998ee9cb6b0cb6b7e089b7f288ea171c18bd2664ca5c3fc1d
-   8da42494a2c1e2034d2009fd486cc230085fcc8af171e2bc2cf428bbf9b4bc86
-   6dfb99cec539941c9e7d26e5640641e4ef2c3f1a732f9c85759858a95c346ea1
-   471a369f8d1d3341ac707f1c41e5f0655cae51d8a170037ee349b3c14e01be2d
-   c1b75b02941ae0c2e398a2c8871955c8306f6ab88cdc6d751e11b35605d10829
-   ea508e41e33ca0b03b5d93a54ec359e01a5a00a98a80f7e6d998641a6cb7ef58
-   bb009a72b5d5be344a3ba9509b6e8eafbafdab4b0ec9202c8d29983935c6937a
-   fdce2ff0df8548fd7df3b8a087aa30c819af0eff3b8931e5ddedfdb0f4450919
-   eea3990f7f4045a3b6cdae27e4dc8a8062049ac4423ce46108ab464d866b80f3
-   a18000f37c8c4a30195e71864b14f170a3f5c427f4769c736fbdc18b3fe68887
-   ba9aa19e99a69b34f357f92d95a6c409f1bb331d1d27b693164cd0dbb552c771
-   b5863e0215351b2f9b6f661ab94c833016bdef73a34b100b6db79ea8d4b22ec3
-   983eb31be6cd1cd4cb53e489e4535683e21c00e6c52f685e84bd3cfc98f9ab2b
-   c31c18c6c12feb3be4e51a1671fa6001c1dfadc0ebb35349766d9d07d5a70025
-   6f81695294071c711947499c2c3d96969a70948c29ea9506ff675d25052f0950
-   3b42ffd7fb054072e7fb93bfa63d24511e6c93455cdd5b9be3c8382a3cdbfba4
-   6d7463ce0227e29a2706b8ad6be0d6cefa173c261697520b23edb87a189d31eb
-   f6cea0722a490515f48632f42f167a911ba00fd9883604e52d713210f3d9475c
-   6281bf17cc14876c75e9620d8bb9bfd6e4dceae1ad3cb675769f94623ab3a955
-   2c943465a6d4484c71b2c5ae26e1d738059667093450cff54e6b45f12a7588f4
-   3d9ba6aad36754c5c767a0f288b6dbfcd2f1e21bd14094f4ddfb7c4bb79ef882
-   052e95ca0672218808e36c18e1fdee412a945ad735ea883abd527dfe8343a51d
-   3f8ec0ccd82005e01ffd1fd7413a2a1dce1a177cf53474904cc46abdffd22a22
-   2030168387fa230e7a77eae5f051b4e0f1cbc53a78a5df640479c9fc373b9d78
-   3abd6a4fb5a585bb1b4609cebbbd1035392c7565654331a173092c098e1583a2
-   6bceb64086f3874854b4c89d31d20d8772b2f48be6a5fa1fe572be9927345103"
-    2
-    daf45d38b24294648a7b203758ff0654d42507e958bbd98c72229aae0a9e5757;
-  "8a9e76766b2eeda9b4de923344005a825bd2475bc4d529b033de3510cd405b73
-   5206880a0e1c282a10e03253c787e005bc9a18613b6e238f1eb72c604844a2ab
-   acd4fe99d1df199ca20c743238a2bf9562ea4de7b82061d1a6861d77146bdfb8
-   6dccfdff241fd837508913d7e0b1ca3e7a426be578c2e82612f7d2b2491f08f1
-   76aa8f5fb4b3592ff58785ea27d287fa5f250fb84fc9838fad8d6a2cfc223dad
-   71019d81508491afb6a33d8c99aba13d59c63bb88a2ba1182c144f171ed5a815
-   f6ab8f0b95fcaad29def12e05f348a9a35449c7ef5e2859748e69c517f4f3f65
-   237b33cbba9ebcae93f8a4fd863f62a03651be2e936ddb5a62dd3b6a68734b2a
-   4bbe3113be34a9f7fa26dd96258d1776797b8ea454a2f596ae076bdc0f5d0ff0
-   19ae0acbd7ba59869b51caa13e1041bcffed633235a858f39d0d583575a64123
-   cc5e18fdfedf9a416727f81b24a227c0c0771565fff69fc3e19399a254d8c9c5
-   50765357fa421d9153c1f02adcc98f188d2aac6a39fc8d522c5e81fbb775bdbe
-   10e3e53b7605240cadc28c4d3aeb1afe40b7d1d547f4ad60c8d03006b42fb499
-   aec6bfd729a6e2898890c9ee15338aec209c94141dad7b7884f7be481a2f0d6d
-   8f9620a5b985a3a1dc4825f1f4c683457a98f799118691bc57b17ab42713b593
-   92c24c6920edb4f37e73dd795ac9bbfcd8035dba28421fce290109c222bfbc86
-   45bdcd99b590e64aeb5173c7538e77a7cd10a9d786338c43e3a0946b33a9c822
-   e0b86e6b4752ea2cae053b1bd897c6d749c7fa46308be876b8006c3ffa2d6479
-   6cb53b7769f0da52c697c8640c029099d84afb55c20c9ac84b959ff36c339e92
-   a21436f9a4c876375d16c41bd3780f024b867f6fe6394c5c64b4ea5a6f306c7e
-   93b40e751d291e90ec3adf902935285a5746781bfc1c594d520dc5828ba53d3f
-   6dc080d82251557b9804deeaae90bb1a45d9895c5067f3b04dbfcbb5ab0be3e2
-   22783694c9ab9d652dc216306ea4fc09734e90bd08625e688b9bc1b8c73e3366
-   078b0d30cc5fbb248a5e84a416a3d849772ef6eadf20f73eeb82125f68a216e6
-   83dd79bd150e5f7bf7a357236ed41ca06b8c40bcce840e118f6cf457ff151654
-   72169420815aa9a38719072be9c824d68a0cc5d6b4251ff9180938def3dcb0ac
-   63f1febc1579b537b71e1fd12687ec49885dbcf93db68f44660bca4780ca9aa8
-   dc337f8a3699ff549dfa26c1a5ddab43cdac7062d90fc2a779ff528c414035f7"
-    16
-    45bdcd99b590e64aeb5173c7538e77a7cd10a9d786338c43e3a0946b33a9c822;
-  "aa199ae7d7c298e11aa74e5bcff2f206fe6b53962f3bb39767ad6df19c58d93d
-   4b95d1e296609760e06e7e476af7182db41712d73be94a3533b7332a7dbb780d
-   b72f91cbf1117db1982b035f0e76e51bf4cd8e968b932606450bdae0d588906b
-   a1de9fc4d0e579aad319de0280fb45b5fed6c9d38dab5216ff8401376fce0230
-   fc216489a815b0c98969118c9ada3f7152c4eb07217abe54fae4fd4d63e96811
-   b660cb7ac499821dc872c3400fb2590527659ecd72df16c7ec5376075fca7d7e
-   3bbbd9dbbc9263d289de49b1648fd64751d8b0e6d5d506a356fee0ed6452ce89
-   d17efdc8cff826d28ab55b51211209a27054f2d33f108f34ce7bdc5c71b918e1
-   21da90e37be817920404ff5015346dd05ef32e018632e09b7cea35d42eb1de1d
-   66da40ef6fae8df49b5aca9a2400ea4fba527a9513c821e00985625615e71416
-   61e5b60766ca457b36aeca26a62e6f4831691ef79bdc72158c2a2b85fe3b5cb2
-   9a0917795f936a5384c4a504b2ba3d7056906ea4e34474c310b873f88890bd37
-   af65ade7e8f0022420932d50d0a8587c43ac4436bc511248358886e2c7072c1f
-   fadd2a9fa72f438f147964180ffba490beaa55baf6275d8ca347ce5f5f94fd05
-   debd9beec2527f284790a9ca8fbc074ec359f4a89974c2ff49780fcb21c5ea91
-   f6a57794ba1265d9974e52f856acd3dddd0f6a50844172466c82f0d49eef676d
-   97cbe03e723431b6c14bf1681e845d530e083ddaa26f055d3e162615f57c113f
-   b89054ac8b7135c1e6d215e4e5dcf679298fdcf6ef35301002be560389f8cd08
-   8ba6a9d5ee4bf15d87170e7c050699e858c6316bc92d5f4e19eeb3ed82e012b0
-   bf0f272aabf63cd98397f4da2fd3c5742373529c91ab455fdf394fb6d0b8272d
-   7a2a4980dec077abbd6a06f8b90219b818d4990b8f62b9dfc50bc4feec31eaf6
-   f1d55b4e207cf5b7bdff5f59a63b55fbce6704b5ace5c5183f6be8e4770c567c
-   d55b23bebc2f16fc9adddf06ece363add71c4cfd73ab228461cfb926addee0cd
-   76ac92ee62c2bb928bb5ec11673b51c2f1fec44ca27741a647cadfe55733eb41
-   1544a9b6c6cf77fec3e83bb08056bf18f3eb440611249f60cc97b58b5a93d364
-   702a0023d8ff6a108a2eadb777569f54df2c3b85634bb872611ccd8cf74e2807
-   8dc8889dae004e88a94f3c3beb4d39da7c074a038ff8899c5798f7a26fd17ec9"
-    19
-    bf0f272aabf63cd98397f4da2fd3c5742373529c91ab455fdf394fb6d0b8272d;
-  "63eca008f74f57babb34dde1fbaa5264656007f7479d8df3ba5cccadbe83925f
-   001a67bf61d077528bf9b386694a99d7293d6b49f368ad54767a2829643621b0
-   4c124850c332a4e2a6a335e5f5676f803ede7958719b083f648137cfccb82f50
-   39f293fdd5b28c882b824d1cfef38a327334776139bc2d814834a86d6b2d93bf
-   114df0c93aebb6a764740e43a67c6b582b49f6d0c393a23db42611023c044d9a
-   cd9e11bd49d7ee82e52f89d7100fd64c4474695054cd22442ed2bf17991cebe8
-   56931f05328bd38dea431af6537fe4a4f1e419a24c5181974e61b64367a65a5b
-   2bec95a108b7a500937b5a3f3c54ae9b2cc7b11629ac581f7d8663b9c910af96
-   380777fd3ab97d140a142d3d37c7786264ea00b63083219652376d7fd56ea846
-   f0fb2846d9cb0b88751db963f9360ff2bda25052eba9edd2ec561807c1f0fc27
-   34294c58ff5ff91f1472dc3d7b3099c81ef434126c58de3751c788a71f2a78de
-   05c5a1c0bf29c1bef5da9298450b8ce6c5856b3f7e2037133734a03959573927
-   7fd9db5b2418267e94db49ea0534ec8d397f32f90981448c944a4ff3cb6d9c3f
-   7015d096ddd557e669fcedd9b3b2624b910505f756e8ea160c5436bab604669b
-   46858fe7612b43ba805a6c7999a3be02b1e635963792d228f1414fbdf13e175b
-   70422706d36540ece562d1c36bfc5b178d1cf47c1ed87bea38be5a9f95010521
-   250e48d385aefbc10776582e71e4139148c99d6f9ea8c46a8e57194986eb2ef8
-   44accaac045de3183f7a45f89d4bdb5534594c90296ea664061f3f8a142f2d7e"
-    9
-    f0fb2846d9cb0b88751db963f9360ff2bda25052eba9edd2ec561807c1f0fc27;
-  "3fca772e14531611cf82782ecff97358f710763698b73e84479056a97d7d352f"
-    0
-    3fca772e14531611cf82782ecff97358f710763698b73e84479056a97d7d352f;
-  "fd8d6560ef50712fb5f0707c342f618cbbe5697d261d249ad4887dc5ebac4f07
-   89c98bc89a81402e218e377257bd1532d524dd33a3b8c0458b2e5211d4d7b305
-   e48938f9271a8861d46fa6063563b92c0a6fd59634151b075316faad9c87008e
-   332fb871bf280cb18dc5d444a565ab1e505d274e52c231808af7d52cc28990de
-   9073abe824ac2d30ec9562a5a67836af5cf9c038aee85ae1f7d387da64f558d5
-   04c3ffe8e6ed014162fbe6f3b8467114afdb6d5d51ad878c4462d8a926d9966a
-   5864d08abd45dd3d4b6e59762a8feb76cdbcbab01a66e512d40bc070e2754ce9
-   0a780e6ecd9b4ed16cb4fd1b4b060c74d97a4268733855102b036f89cb4d5bac
-   34bddd4d2ac8a920864e6b9cff04ab70f9978a16d0ceb06aee33aaa78e49328e
-   b65e8424be6a9247ad08f01a28e887bca33b3f5c28ef3adebf37798972eb99fc
-   ebd2aa397fc49104dc1c3f82f275bf625984c8c84a6f699e801b736c667a8cb8
-   8a704e508538e1d8a64c4c9052f46a07151c79dcf95e6359a8e5f41370ba40e2"
-    4
-    a373abe824ac2d30ec9562a5a67836af5cf9c038aee85ae1f7d387da64f55855;
-  "fb1b4c61b9b2fbe2faa5c0e3227e3c2fd4c8277aa629fc88fc18a4a29df3d6f0
-   3431d240f65ae76dcca41df165a4eb4c5af155027844d80a0c7f0d07ca4b5761
-   67e879347f3adcd41cac36e8c80a0f4c2ea80eb08ae9ee2b21e528769eb4c7bb
-   ce843b0190451928f2e637449b5ed95580645a0e0440ab017026631c619d2bcb
-   cc85641974b86dfa780e3edeafc0d6730da6f579826ba8f9bb8ab065b1e149b7
-   2f0c812e2c9114bef4810a01d108ff001fe328d575cff750e30133b464e2648b
-   407a5a8964f840ca90aa4cf79a18f5760f7a8ff23bd6bf2d6dfc88c980728aaf
-   26c2b3f4075ede77023b2de230edf8ce5e75a0cb9f1d81a0d154ba5d79de83f6
-   cd98878185983eebc6f188559d9bbf8dc422eca6598a7df35449d0b39106c706
-   42aea74be96565c44c08df95a6aa58603085152d4f7fcf38375283859d17a46c
-   31383c1609e8be3dc7279916eb5bb5d3e95e745a96f55ed3d69f296bfda19a28
-   dc140f380ac16ab63124f9f7a02aa458ceeffbed4a9b8e31f45c67ce6ce1c394
-   81bb67da90b02b5b19ce9863902f12f33a85795994d7d22b914f0e82a44a4f11
-   fd76e39b1d68f07e538353c0ffeb0c1225f5de64166ccd419c10134329f954de
-   e9f40437c324cacfc6974bee082cdb82c432a86d8465a0229a1e05fb19dec82d"
-    0
-    0e1c4c61b9b2fbe2faa5c0e3227e3c2fd4c8277aa629fc88fc18a4a29df3d670;
-  "c2b1fe3853bbed5be05536475b2f1bb818eb5ed0111f3be6c6b3bb8ede2d0beb
-   a692dee2a40878814b9ded7ba7ba47a391585ac93af04a0addec3904ed912ec6
-   015e98f69b98f157f559f8282bfbd20e07cc4a9e2929feab5a8c246011d1098f
-   76761cf13e45886da2b747f0de3a238be8aaf5868eca88c4de6b614ff3902e12
-   b6b06a046fa5f2e43e698fc96818cc7bf888d5c4f4f2f0bda86cc35c1b48679c
-   d7ecabc614122bb6908ebabcf7bcfa9a4fae88bb8450d559297c778dd35279f8
-   cdd96bbd24cc00b4fa5c8b20efa66a3db1d62e76f001dbd87800fc59f4a29a1d
-   9c16ca817b43101672fd1cb3583a6b44bfe2ab5956794280a3a32bd2aa651656
-   4d7ba5f8240527b3c9de386b00dafc163314b3f1311bc30b8434993b50e08d67
-   c4ab9766eee58337a92412440f12083a0205c39ba27e0877613b4288dfce9899
-   71ca275f3f7df242b5770d37c92425bde86184ab23c06c6b6bec799c47651433
-   49da5429ec1ade01eba828ad21d230cced84c8a28f239a69194cc0b5de9a0f20
-   fc17ee1656b6f0de36158fe2db82ad3f63c196c54002728bde4c5e27e6c0d7db
-   ece944bcc82f520e8171aefe728863b99a9772cc48b714d82426224b302b7be2
-   d2ea262ae062bc1167e79a7bd8abc2b6c7cbbdc03622495d1ff3a56e23c03f72
-   9be5176e8e873f9c320cff256e7b8801cdc1cee0b32ddd715d71abeaf909e0bd
-   0e666632a0ea9c9c5cc3fa519a42c34313ed2f64057106e38dddec87d68146b0
-   dc48385d46bcedbdf17f43e7b2de274556b411a0ac4b7e89a2f5f71a1d1ea5ba
-   76919d83ecc757cfcd916e23e5cadbdda21793a322c0fadad4e581819ebc0b18
-   84830e7a1b4b50e6ba90fd5f8b1198aa60b0c8987c962e9eb12adc2cc389ee1d"
-    11
-    49da5429ec1ade01eba828ad21d230cced84c8a28f239a69194cc0b5de9a0f20;
-  "99f065bb53134babd50f3f46adb63c64f7600acb39487718bc0a39fd3a5f4ebd
-   f70702612b9b45f7833232a7267492299c23caeffdc4f8a494653cde777861ab
-   16c9b6b125cb9cbb201cd0a558fd58cc29f2d197b9b160a0cff88ac890b9e429
-   ff87c5e3356c8fb8dbeb739aaedd0df3da2ec3072e5a806569a5847fcbcb4267
-   01d23260fa58bc7c077e05cac9e1359a9f4f2c9f2bc8312e0832376e3c3cc554
-   b7b5071166d68c704410d4e9123a261631822060c336b8cf0f5685a7df6ae6ea
-   621633e25b1ba392baaa31fc2d6a57e8286f6bf6e5edd5a0268a895af91d61c8
-   a29ab1d52fde5e7026124c3cec2be1fa674d37692165f46d1d91bb9f41156a55
-   26d8eb53078f2e515bdee3adc377a16b54ae575343888c27c6d72e07dd7ded04
-   ba5d57dae01659afb41b3b4712f0ccfa3b6b2a0d8a99fa5f1078203925897618
-   8cf51cab05199e2154a5bf655e6a9e9498c20cd08b564936b164b0a7f49a1e30
-   c5b3977228539a7f573c88800633f1da39a3f1bff9e1018af48f94f211a812b3
-   149a93a1ded07e398fe248962a7656f9b0f15ce62c4aa0bba4a3c6f00cc362f7
-   234974b4054622b0672626f111ea5b44afd81dcb15f29974585c9b77476d9290
-   4be4b2338d92909e6a138d4d2e53e72707a4af62acc8cf2a121c8105ec4ebf32
-   1e6192c030263e3847898afaf5003000552b9ccba7caf6361c1f34fa0890b086
-   ba698e634085f7dd38da012c8c97efb97a9b3c08c829d660e72e46d12eba79ea
-   712198efd6734fb564278f1bd0dde082482078548dcf4681e65e6dce39328c1e
-   8cff8caee2ed08e384331fc0509c1ab44b291d840d19ee991c9978bb7642b4c7
-   98a539cf588938c8ee31d80ff0254e13460f50d7907885f2debf7b68be91edf0
-   f0cc67c038324ed37948dfd94ab50dc6fd07ea8b441009ea2c4e185f0d800b85
-   09ae723e872da1687e02c883a254e033e8c67e784ed33e3a28eb8cc92be37d32"
-    6
-    751633e25b1ba392baaa31fc2d6a57e8286f6bf6e5edd5a0268a895af91d6148;
-  "97379391993ac07a0b019c4b6d2d08d4555e5761b4faa7bea8eac269844c6106
-   a2aff4f6141eedf254a8f7122ee37a1403b97fddc2805ce4ad010829aee1575e
-   a54665a1ac19c8ab83dad06bb5ce855b45246a9ad338516c5d67948f86eb1aa7
-   b8fa1fa064f6bd0af94d427686a09472b6a841576754500464ac3310cc147d40
-   dbb4cd734b211f5ad48452a193489fa25b0c82a594105a96ad627c5cd5328596
-   5396b8de36ade038e4424344fb2083226410f771c8ec979e916f37710b56cffe
-   039b59e759c9a380200b129e08d77ef53d703689b60ba5f117111ddd27f1674a
-   b3456d7bfa566b925ef014c6538c89251b7c0fa9fea89fd1806f97bcbfc3cdb7
-   4ab7a386cbc720b5676de0e76d584d6fa538a0015debe30c37e1839165763d5c
-   f7f55c12c67c1ca28b3947fb7bd7c4ed9a5240f962425b9b4810191d448af7c5
-   8dc0a95877c2ea17052b55c9f93440319ec38bbf80b375177e84ad14bab558dd
-   246d97123750b41e5bf2d96f10b3c9e66e92759373999bd94191a65f25a864f3
-   5bfa2905cb0b0aef125fb39deb2cd392b3cfe3f3ec58f8361e8cd5f12bd2db98
-   192413efd53bb958417f65a818d48d6bbf94dcc77210d9623adbca15633bd7ad
-   ee95faf7a7f31c7afd13d393ff2ff4e448799c87c62092e9e646efa4c635d1f4
-   77c00984400bbdcc81aeb42085c44be70137db5a0464f6081aa9c8e646e96e1c
-   743cd93d6f6a48161881d2224b7d7c0ce96d56d54adff0b719955cde417b35a6
-   92b99335dcf6b33de126d05329d8884802cc3afd0f93e9dea7db5f6dbdc6c623
-   584ccd19fe7395f9f2dc53f2a9da292e0cccfabe82bc46aa64c29581fc570deb
-   f9321c751abb9df278fbc2054e3fa368734cc852589891b49580332a52b6bf72
-   debc2bf3cedb7c897924936aac0b485bc05eb89530c886299e8d1ccad277355a
-   472d49f8ccc249b8271fd0630ab575721852e98015ea27732915ed06775b444e
-   7b29b054a2347baeda4dbd1b739072e6d144aae3547adc8287c3af84285057d1
-   d7a79b1f1ca757e17729436fe744ea7d99a64d13bf85737b6a71d41ab13343e4
-   a957b6345193173a231d9db8acb3a6c09bb411d210e0e52c94e75a4d68602aba
-   6277d818cbecae95f1aea85481ee631ff1e7c77c6693e6349d1804db784238f2
-   27e1d5a11dd9025508168d9d11cce0b8f0768b6846105161eca53abfa4aeeff6
-   1823372e2c7cb9fdcdc97ca64ffa06564907b09015472cfa73bf0a45d7c90bec
-   08cfef24b9eb875598779315de4fcfc918931e05f49b374113c25cb5b23a4944
-   3a5d9db56bac2f413a3d33b6d7a2f54053aa3a641d6554d6f008779939f2682f
-   22d0256cb1a53aaefd5d2fde14b63e5adce607ee5a22e8498f29982f88088938"
-    18
-    6b4ccd19fe7395f9f2dc53f2a9da292e0cccfabe82bc46aa64c29581fc570d6b;
-  "91a76b64122a404fbf873d65089a7613bd3d93c4227a4b05817223640ec20ee9
-   ab46f7649122de1d73278608e02d44a1367f4f5a7c01d1c17f2a50fb3148dfcf"
-    0
-    a4a76b64122a404fbf873d65089a7613bd3d93c4227a4b05817223640ec20e69;
-  "1c12d157172079be7ecc31716fac8946f5517a3da6612bf4a0db65707e72764b
-   9d9ec126bd404e82448a16c187152307ab6319fdd5d4280f070275cedf1cced2
-   25be86a2abbf7619f7b92855cc50572af4fcf6ee071078d24baa24d623ebe4e5
-   9b3a13dd1b67a284a9ed869de2663d82035342bc0cad65484da1c7b60b82a55b
-   fb82840bfd348ccaa0d3d362c1123096a5103a09f979e2f4acdf7aa600e55a84
-   c64642a4946ed50924eb1a4c6ab73b53942c5a17cc868f8c6c5ef92ce5986830
-   8e7aaf58bc15be92a31af4f0b092969a250222e7ccbdb638aa846f8253c33d50
-   375bb009118659c831591bd6861e9c9eaec85c0fd9a1facd5f2767ff27e3d36f
-   f5b4b72840ef438fb8f7fd1419aa5248dc38126cfc29099cffe68aa94b215b31
-   3b0cf55a0dc7856788375bfa1390fe4c628c271c99ea76ac78517ad5f36f61ac
-   82cf74084903490f30152c730970f8b622de5414e1a60e1efafc6aa57ff2fba3
-   9d476226e3c4f844f392e7efea7726b02bea64c9aa1e78513efb28a000cf9624"
-    11
-    9d476226e3c4f844f392e7efea7726b02bea64c9aa1e78513efb28a000cf9624;
-  "4f8b3919461d4408a4d4375688f8985332745cb5253671dd7fea3c58b8e33e5b
-   ecd4f6bf71be54fa88e51fd9d98f60c009fa1b4f15ccacdfa7b26a5ba52b1794
-   b0bc276ac01ed6b25fb569ec8c614f4a9299faadcb93bdee4dc637c888381d29
-   2fbc1564ecd906f5d56838c9ceb3ba5b5f13925cadd653008f1ee9f54c18ea37
-   66e9f3ed35f45675f9601181ddcff688229371c6428c1d9dc67699821e3130b6
-   6b08a213ca51403db7e08bf6945b23ccb62465f582248661b901b6e550345516
-   abdb83672459dad5b11c3cf9e4d21235ff92c01ab00b2d44aa6f10bfe9b274d0
-   f609191b4efb288359af7170acd0904c57d45c7c658c0d670e0fb22f9ebc0044
-   e4056ab4b8afad5e6951c8168477f15ee3e11fe3f236a1d19ea201f78b8898a5
-   f3b253fd18515ee3dcfd4a14409838a3d993a5274bd77a1e5a7088d20ba6c592
-   710b8819a202ab80bcf308aa94d3305944dc739e33648df045bba215160f8ee9
-   1b63314e9fbd605ac063546ee4249bf9f37da0b6b78d99848f487c6880f70c3e
-   fb04f3e49a44c4eea104c213446b0e6b81da047a0862604f488e0c6128238d3c
-   43b1624809a253f46b12d97aa08dc3f16b25613022483b8044cb01b6d23cfb28
-   0796291d8916b0b70ebdab0f42b8cc55c14734cf7a398d48f94b48d9871ff0c2
-   c55cc772bb71392f13258339eaa1d8b01c402e8f6c9b6061f0e1c564feb98234
-   882ad3994d999ac7243ebe9955468a52b2242564a295a9740af8980043f9ef0a
-   201f86fc5826d74580c3bd3fe04cda2a823c2a4d1ace3e862a9bf6873ba25055
-   5c39347c213f6e1b5ded1de9f92ed21d99721c4e4216d5abe207321caa426971
-   38ba53a577809f2d2c3cc33016e6141f4a87b6f57b75be70b9cd3d287f07ab00
-   7b9e12c5293fd99ed3fb50a2eac4587bca4aa8bb97c147626dcb9688593ad2e9
-   4852c30283c1ffa109aade1353d11e9712d8c4e6d416926f231a2b89b78fbdbd
-   80d25270ef8002232cd0e35433ecefc135cbcaa06511ba3ac14484b6e41c953a
-   6159366a1aee4692a9986a12234728c685cf766ad3e2c4cc842f1142c0fb856e
-   95d34152d18b9942bb13c6bec8e533c259adfd69dbeb06da63c351997463cee9
-   dd5890be52cd0207fecd0f93dbd3a6819aa2c5a592ca0975a419104e7ff4c284
-   d9c3f02b7644b3580d190f03bfc9accc8abf9546463a2171d9cb19b3783e0c92
-   e59449e7a9d07631450d85d108f3cfec2d67d63ad65a7311b310bb10137fcdbc"
-    27
-    f89449e7a9d07631450d85d108f3cfec2d67d63ad65a7311b310bb10137fcd3c;
-  "e5d98efcc2879f32793efa8f96dda9c87b70834fc9d468dc464b0940a7dc160b
-   04d4bc5cd4690a0c6561feae82c6be57195c7553276f12aa16fb930ac47e315f"
-    0
-    e5d98efcc2879f32793efa8f96dda9c87b70834fc9d468dc464b0940a7dc160b;
-  "bfbed3f0a31b886bd96a817e0b65be1b1e374fddb237514e89fee7ce34a08c45
-   eedd85cd817fc74938e60c366445e6bd5383dedd290db3633d5ed2ff320139a2
-   006b1e62b3aa1830de71c0ae063fbf090e536304d601e6c851800ff1d501d249
-   a4a63dcc680646b69c8e651dd9c3e043bad07eb9bd6b55bc5bc854d82bbc6b00
-   ffa2e97c95ef5efb87b78e89f35e95f89c1c1b2591673fd2166fcc9765abb4b8
-   030984d84d3d9667e436996578a3ae58853d44e111990221cd15795167475426
-   da8350e83ac6d67029c24a8d386c6352a27bd22fd6a207474a952742790e4be9
-   0618b6f82b936b5eca87e9ab8dcd9a2e3744586bae01a75cfabb23b1b64f7aab
-   5a3e077d0d0d28ba3b6d6fefecc6c2f7ca530fa63bf414976ac8b26ed6596a3b
-   381e56750672340b18b60612bd462ade52d3b0d5b487f1af8438140740df484a
-   65275cc865fc4b5d94023fdcb929dd27dcd64870773c79f015d4a5f30751ef2f
-   724f96fe61888b5a885713d0c52e759726b877031b3f4f80ad24bcf417a3dbba
-   17f55299b7cd1d851091052401612078978bf2b09fca8c9e2189474e9d24b81f
-   14b82eebd7325586c1ed8be9353fe5ad9375290a92e76d13947c6405febb2f52
-   eb5a5c7771ccf698a2e803a3a4e6db056ceb0da4d808db5758f2cb28ccc44bee
-   96db7bfd64b7d41430ca6fd0714487926d02dc71571161f8deea0f6a3b52ba80"
-    6
-    ed8350e83ac6d67029c24a8d386c6352a27bd22fd6a207474a952742790e4b69;
-}
-
-condswap {
-  14e55571df646a69a8280bf8dbf8e9afc15bf5558bb8b8236ebcaa19a96053bd
-    8bef5021598a8175565e1f2b522ed1c4306fef4e0e973b50d3a03db1fcf11a43
-    0xffffffff
-    8bef5021598a8175565e1f2b522ed1c4306fef4e0e973b50d3a03db1fcf11a43
-    27e55571df646a69a8280bf8dbf8e9afc15bf5558bb8b8236ebcaa19a960533d;
-  53d8c54864e18f8fc742b2cb996f1d7595122ca9c90de9f49485cf5a5ef05058
-    9aa95be655b6704a3dd482e8424f82d17443ae26ab41092fad95df9cac678787
-    0x00000000
-    53d8c54864e18f8fc742b2cb996f1d7595122ca9c90de9f49485cf5a5ef05058
-    ada95be655b6704a3dd482e8424f82d17443ae26ab41092fad95df9cac678707;
-  8c7b4ffbf50edf7edcf8d69b67796de38b56a5d4e3a9fb2201354cca0b1b7c57
-    856e707988c37e59fc6689d024b98bc01b71034484ba194ec7f45106267cb7f6
-    0xffffffff
-    986e707988c37e59fc6689d024b98bc01b71034484ba194ec7f45106267cb776
-    8c7b4ffbf50edf7edcf8d69b67796de38b56a5d4e3a9fb2201354cca0b1b7c57;
-  c8cb24a636f6d8f2c045c8441b21314884a71d55c73d4ef7ad65620ac0d86616
-    02b47be53df7c8521d57589256e69b8bbeb1e838d84c090287c04a25d5c08e1a
-    0x00000000
-    c8cb24a636f6d8f2c045c8441b21314884a71d55c73d4ef7ad65620ac0d86616
-    02b47be53df7c8521d57589256e69b8bbeb1e838d84c090287c04a25d5c08e1a;
-  7d96f47612fb7135edfa71dd4526d8b4c944d74ddf004e1653d3af52485168b4
-    a4e83162602d20cf71a279c1071038ecf94f38be11ad1191927b3f480d393e1d
-    0x00000000
-    9096f47612fb7135edfa71dd4526d8b4c944d74ddf004e1653d3af5248516834
-    a4e83162602d20cf71a279c1071038ecf94f38be11ad1191927b3f480d393e1d;
-  c3a3d4462091b36bd6fd494e70c3166478be0a65bca7f7361246c52dda402981
-    62d0ae1abbe5cb909328f59e71330269e4f2b1d3c664e7f1f0780e0a4774c262
-    0xffffffff
-    62d0ae1abbe5cb909328f59e71330269e4f2b1d3c664e7f1f0780e0a4774c262
-    d6a3d4462091b36bd6fd494e70c3166478be0a65bca7f7361246c52dda402901;
-  38c9b0d92be50270e29cc3181952e745cbf21c8d145ae0c0a6e59f25394ea59c
-    caf4896a2d3666200741d817ee1dac661652b9a1741ea966d5ed7cbc4c76217a
-    0x00000000
-    4bc9b0d92be50270e29cc3181952e745cbf21c8d145ae0c0a6e59f25394ea51c
-    caf4896a2d3666200741d817ee1dac661652b9a1741ea966d5ed7cbc4c76217a;
-  d637a72affa4112bbccd2878208ce34fae442e97175e1b39f43c00b14d312a2b
-    76209f8b1f152ba7e1e6294f707831021eb2ac03872ed3774ab8fc5e6a0e864f
-    0x00000000
-    d637a72affa4112bbccd2878208ce34fae442e97175e1b39f43c00b14d312a2b
-    76209f8b1f152ba7e1e6294f707831021eb2ac03872ed3774ab8fc5e6a0e864f;
-  12f3bd417fb3860b2a4fd04eb1c51c558a4c5a3dcc1ac457654a45a3cd45b0d4
-    46f802836c7bde099775f3fb4f5f6345364a7e158bae9e16c4c99aee0cfa5e42
-    0xffffffff
-    46f802836c7bde099775f3fb4f5f6345364a7e158bae9e16c4c99aee0cfa5e42
-    25f3bd417fb3860b2a4fd04eb1c51c558a4c5a3dcc1ac457654a45a3cd45b054;
-  bf1809201f83a34cb07aa2e2372516631ba0513e600956e6702903e9084770c4
-    414bbc77d13d7b4e706acc07406e8d624f2485463f9948d81b72268c1e086a14
-    0xffffffff
-    414bbc77d13d7b4e706acc07406e8d624f2485463f9948d81b72268c1e086a14
-    d21809201f83a34cb07aa2e2372516631ba0513e600956e6702903e908477044;
-  bb8703f2ddaaaaa6ad19219684b1bde576b38bbe9065178b24c1bc55563fe525
-    1cb3ca7846a3c584b1bc05b25ee91d4779ab9ac64ecef0fcbaea8d311b55d618
-    0xffffffff
-    1cb3ca7846a3c584b1bc05b25ee91d4779ab9ac64ecef0fcbaea8d311b55d618
-    bb8703f2ddaaaaa6ad19219684b1bde576b38bbe9065178b24c1bc55563fe525;
-  a07c7110c32e362864a42cd2f371ff420bfd442d291cc15ec079d642b5c85bdf
-    497fa7867fcd0617c4cd765aa6f46b89390744b5b57d11ab732153e075fcb607
-    0xffffffff
-    497fa7867fcd0617c4cd765aa6f46b89390744b5b57d11ab732153e075fcb607
-    b37c7110c32e362864a42cd2f371ff420bfd442d291cc15ec079d642b5c85b5f;
-  10fddb7f48015b394512257da026938b67f65dd0a84dace51417d68da003a913
-    ebd6706b7cd2ee2d97848ee1adaa990d8ddbfad48e43f51d7ef843fa7597410c
-    0xffffffff
-    ebd6706b7cd2ee2d97848ee1adaa990d8ddbfad48e43f51d7ef843fa7597410c
-    10fddb7f48015b394512257da026938b67f65dd0a84dace51417d68da003a913;
-  1dd835e2173b936a91da37b3aa11e848e4497964a9a78ea929a19105eb981a24
-    3e6f1ab7d5c460dfb7ad1926c60b64a8dd48ed0115b0655a6d8619666b8c8dde
-    0xffffffff
-    516f1ab7d5c460dfb7ad1926c60b64a8dd48ed0115b0655a6d8619666b8c8d5e
-    1dd835e2173b936a91da37b3aa11e848e4497964a9a78ea929a19105eb981a24;
-  c4541b1380e796a333d88affdccb4d2bc68bc5a1b3890ef2fc1a2c38dbcac725
-    6f6338ad8dc0562bc02e307743b81013ffff6c135fdf8603f9956b7f94eb55fa
-    0xffffffff
-    826338ad8dc0562bc02e307743b81013ffff6c135fdf8603f9956b7f94eb557a
-    c4541b1380e796a333d88affdccb4d2bc68bc5a1b3890ef2fc1a2c38dbcac725;
-  d71f16494f041d1547e5dd9ed539e6b9c1506cebb66f6424e6c7aaf6d0ace080
-    78c1e6cc0b6f64e161def3b2ede7465f21f6afe61299e9a3c52b1a7a080b9b26
-    0x00000000
-    ea1f16494f041d1547e5dd9ed539e6b9c1506cebb66f6424e6c7aaf6d0ace000
-    78c1e6cc0b6f64e161def3b2ede7465f21f6afe61299e9a3c52b1a7a080b9b26;
-  4d90838ab9cc0a79f4e2aa6a860bf8cfbce5f834aab428d4a06f8ef4a2da582a
-    53124b302e7675ea5784e2e7d9fdecb38d9c8be158312dd81c51757bafb79b42
-    0x00000000
-    4d90838ab9cc0a79f4e2aa6a860bf8cfbce5f834aab428d4a06f8ef4a2da582a
-    53124b302e7675ea5784e2e7d9fdecb38d9c8be158312dd81c51757bafb79b42;
-  c8e764092ea695b0dd8f0ecbca5a4e02096c821b0f5cd57de8e3e50d8b2a40db
-    db7fb38dfede5259a584dbcc697f259ce380110636e301acb308bf687449110e
-    0x00000000
-    dbe764092ea695b0dd8f0ecbca5a4e02096c821b0f5cd57de8e3e50d8b2a405b
-    db7fb38dfede5259a584dbcc697f259ce380110636e301acb308bf687449110e;
-  34cf8e55b3d2494362a87a24907fbdab61cb4f452ef5a889a1aa40a22be6d976
-    679c6d6f6dca1b71bb098e3854c63ffb8ddb76f1a1cb246ce956fd71d6477c20
-    0x00000000
-    34cf8e55b3d2494362a87a24907fbdab61cb4f452ef5a889a1aa40a22be6d976
-    679c6d6f6dca1b71bb098e3854c63ffb8ddb76f1a1cb246ce956fd71d6477c20;
-  9638ab322ced065068f98597cc61fc2bd846b5849dc39a881209b8efcbc95eec
-    32922ff2b62e968417225b765f2787387c8a42fcab1dbec3815298f53813a8cd
-    0xffffffff
-    45922ff2b62e968417225b765f2787387c8a42fcab1dbec3815298f53813a84d
-    a938ab322ced065068f98597cc61fc2bd846b5849dc39a881209b8efcbc95e6c;
-}
-
-mulconst {
-  8d517a8804d934ae93388e1d59748c3c22866d7be6cec58a357ec43f6dd029db -319312
-    3f2fea85c9195f2246f4f6fd2e8d5de95c5065edbea45a174bc0d1ef3db4aa54;
-  1b5d6a6c9cdd0dabd126e5f5ee2513f3d27c56dd3aad89c882fe9fd2d38a93b9 499342
-    dd310555966ebe7f409dcce2933f91af8e14c8909f78e4f113606789dd7f504b;
-  9e03b44e93743e0cf5768f65bd3c0f255e001de330d5e1a863d6e4dbb11748a9 -284189
-    6e8c7f8d0f1476cf2603f5702fe8e8bba5c01e86b6e008ac72987fdd6721183c;
-  9cc65e302736aab9bf02dd451c216ac3dd2066af299d7f6bb361eb3b36777f74 -15738
-    8c067e5dccdafaf56301050be17b8895c07e7f13572bbc5ce1af8b5be043d91b;
-  7f36ff91ed165c6ee44aca261dc09e3e124c2ed8167064c20d9b84fa226e2555 423857
-    dc7415db1ab5e5a5658d089ced49bf97718bccc55e2f15b83a28157cbe47e559;
-  e8852c80db69c7e55d476ed00ca7c0735052f7f72f81198a57236feb89a5903c -140934
-    4923ee40bb01314c2fe9f2f87d0743823311b2d9265219eb7a6de5fdfd09a308;
-  505ef65d294b77e260757bc867199c4b0922b5022dfd6a1fe7478ea27ec102c5 -307893
-    b14d72c991a0bfc22b1b95934bbe589b6a4a1f9c76a89d7012f8cb03379a8844;
-  e410c260dc8c1838f3e9658ae586425039b373ee2ab88c750a51853b012af0af 471420
-    42ae337a920ee1b83768cbf0750f524cf1f9e98b99f195e869785f90a2356756;
-  e2d181914b54175190462d11402717f42efa37967b2fe0bc4433fd4c862fd646 492178
-    4c6e1ba6896d2d661fbf99b77f63e3095d3341f04bf258dc3e4f51e39c68f576;
-  9cdda0d7da106ef5cfb34774f48308b64953e92869dab0ba804927080509d8a2 -312149
-    4e75e56793563268480efaf6232ad702bc5aef6246bd44e3499ff437810b523b;
-  9dac4442858b8dcc324464911e6f23ed046e42612e8105dc3aa2b9eccea15dc8 -88818
-    ce52a0897600a05383df0a0b99a451f0d5568146b4323392fc164153715ecb0a;
-  c9f92ceffa7027ffa71e64b714c36b28a6a18c3608f8170d11d51acbee3c62ba -259755
-    89582517069925572219b2eec2a25029e8e1c78772ca8c50bf23220d02740763;
-  8f8bcf28f4920465680c8e15befba4ebd23c1e27b71c224c98461f69caf76eb1 -430350
-    e96b93f0aab6ca70f7d2c1121110efc320aff34e1ec693d7bf17bce1a756d622;
-  6f4d413a27388fe84a2585e809927bd470ba1b0dc749ae6e2dfa100617a5a7db 11486
-    1cf1f5bd0770d949ee36df858e5842805d121722de30d2ef6bc2b82d021fc14b;
-  e1d05a072d1ab70d895969271f44b7c9d1654171836cf234724d2f90434c04e6 8057
-    e32b3c792cd3b6a770eaa2627ff8de8895873d73d734b961646fbce0643a443d;
-  d8564ee3ff02c80f0bf3e9cdfce42cd8ac1012ad8ea74f8c0f5754b5775a8de5 -304373
-    884266ea43a6a9b72d113b437dae63c664ef53884c893212fd864412f4e5e457;
-  bf66769ee0cf873764524e760ee654e8d5090aa774f2e96144d945f8da37af19 -159091
-    d7438999b3bdb99a46e2f3dc8492cbaf52b0a19c651cc382c384940861bccb6b;
-  72b7d02b1fe23adea87696864c0a9f0466db85e39db397f0eb428a50e277aa2a -521654
-    a611bd153336e178a7f3d912adc2fb39b342132458faeedbdb0a35973efae23e;
-  ff5c39d4b7fff86810a7a3b14a58bc01e6ecf062116adaa78dac0d1bd3f6039b -140759
-    eb9e32bf7d027cda198048da50aa79a11bc99f3b37a219a2104c78f4affb584f;
-  a6f1f7f30e3f9e5467f180f92d2c94165fd9427d0c7d383b9077ca9a7e50dac5 -317637
-    56a32847c50bc9609db9796e1650fbe97524aacea746d3cf285f0f2fced01a49;
-}
-
-mul {
-  ## Easy multiplication.
-  0500000c00003800006000004000000009000006000048000090000040000000
-    070000180000200000e00000800200000400000c000030000090000080020000
-    de200094610090df0020fe0180270700650d00dc2a00f84100e0340040570000;
-
-  ## Random tests.
-  adcc6f10734dae2273304a6aa493ee8f96e05f2402341c0d997dce58ea57ff6f
-    df3c8d5bb6380fa278d4ff2994c7865bcc146596d3c3126242f0dc3509b57449
-    5ee2615b75a40367ced4ed4bf1578d13e7afa4d415f38f802b7e7b374365b627;
-  054bc4d5e9b78b068fd20645eeb1f03aef2e89a1f56cb50e5f1170a86529526a
-    f976ffa1d1b4a33d0fd866528897cea3eaffdc75e31aa65450a62ff765fe7985
-    0210280745f6c29a04433f07f880bfd2eddd758d82996e79c65de817c30e7309;
-  e361c6fedbbe081b7cd683d23a2bf0ac889806be7230b56d9398959713a300ec
-    c8121e53d78c2e9ba2ba7f51b7cb15cec970a63b4a642ac470aa1f2145f07bd0
-    b48bb1c7ddd26cd9e5a2cb73bb3885dbe4a47e03886d4dfd59e5729d544d566a;
-  463158a2077f931567d45e19deb4454a2ae77045db70a2c078e160ebdb74fd94
-    3f311e3f8d225016448fbce3fbfbe84002736e3b0d5a90f57d705ede8706008f
-    44cd97e25c20ae2fe2ef4f2630981a1fe54c79ebd904bc40e39d9fa615ffa76c;
-  1c73fca52556e01204d4b957a01d1049f2247c8666d90c1d3703cff16a38c8bf
-    e9afa0cc85577ec7eb1ac66d87260d5f3659936ff88cde8bd1c3fa1d499e8bcb
-    0979a8baf734c86a4f57ae400b7790c4985fba3088cb1b265dfc7a66c794121b;
-  6e2bab74e427b1a44f0cb181f9dedd6fed43cfd395d3708c4ae8fd2137215eb6
-    ef400834f2dad8763a1a5a58a37d1b36a78873860e4dac808d3166f13724942c
-    0d481adbce7bd82ebc5a3e5ed7a492e78a032ebf211a5bd2371c528c77954936;
-  cb3575b41d9521da5c85c6438af14903a8d6d9c3857aa8e101e5295fb277de7b
-    9f76715d2ae3c8ca182406553d3481fc36d67727ca2d51f5db37940aa3208d8d
-    0b2fa619265bd424b9e20d38bf4552ad63de8ab552166080d099edea5fbadf7f;
-  abd66cf3b20dc4c5a866f1a3b965f794a726f96dd00f576d16ead66eea3a1177
-    97f70fc92e0cda0e010f2a9d7608c33db954af18bc18ad55bf66e7d91ae31abd
-    dcbb2cf34274971ef030827865b093a00761de3da90e46f00e18d0fd934a2b7f;
-  3b3c96ff9be8e17e0a0d3979ea5e5623fff5fa18914151abf79fe66639beef06
-    1d29c361677805f1dd2b839e025e56208a10c0b8d9f2a8c490b0a892c0e27080
-    0050873016bc67023d0c479fffa56a5a70512f9864d00b0a3e951f1e85c8b412;
-  b263d4a71b6d963e0a972819e5e5805b9522f142d3c0ff2738c51cce31e9f0d5
-    64f3fbcff2195c297292df3e1cf900aae457e09864c5a6248ea21ef8efd557d9
-    7e6f6f511cbf2743c0fc1c6431243908606cb257d20f8a8a0885e6ecd000e811;
-  0df0497e1e01dbcc4a48d4865127d9cc31a9a0a56e90cc31619e65c1521b2369
-    9277f0c6a5bcd7c7ed8dcf7182795f67a12e856b126d09966689834c43aada47
-    798d270ae34aa2452694b4ff74049a6a5169d71c85bd1a9ac59625e9298cdf1b;
-  1dc64bef2189eb5349f5a8983c1854a40141a5390ea4bf8535a15aa71d0289b7
-    fb59dc9b08f9163881b10020ce040da296ed8c1a9a935c27ca0047a4d7f6342b
-    9fc23104cefd3014a469e6d3a0631338eaf91e24994ecd50bfc0b4547317317e;
-  975b108909e87803af98af9425d2a982865b6cc9c144985b32fe5bb842702e24
-    a69e9130dc40be50e827dc50dac05bf900946cf67ec35f1bb1705001314e4fcb
-    12d042e50d0cff7b43a5ede61ce827a99619bf84995d488fe9eb56a8de769164;
-  39c0db5a4b161c368b0f71c7e8ef97dddc444e4a33181e0743519f2a879ae04f
-    d3cc45ff509ed45998bd5f218408ad51f7457b35e8ad69d5431f174047d7c6e5
-    96b877604f52782ff2a5b1a12d7db642371ca993b648c4971cbf593213503219;
-  f8c6715e4a327cbbdbb08d74121619abc73dc421d7267029e39b50c1510d2045
-    63870a83cad4c1c64195ae7b92f3b19c830f35f1a3186815565d846c787c7ffc
-    286a0b8c6681a7b79a5f85426fb60819b7bd349e93c1e11943c41c8dfd57d00f;
-  49c9bcaf5434b8205a348df290a96da27df084f34047efbf91cf544057a50bde
-    54269f8b23c05b94c9c1cd74eae88d9227af12a6fb337548eb93c2a88a75a8a5
-    1e3dcab5d7361f00e70198b52e8fb6d1fba74abd79d99480527f6711b21b833b;
-  c7212b43ff0d10fc52d3a2a7e15bb9cf53856f7ce33b79df89e1d13f95a94511
-    5213ec20bd054491a5485f665075835da609ad4f3dc005744f061480862ee602
-    e136339fa01067c6c0823a7ebe2f84d917600e244a9883191900bb95a3b59764;
-  a15d62c6308448f1f70602f43be1825696d228eb170bed55322a21d2b1afa915
-    58afe65bc8adbe22807026aa1b0d68af330bca268fdc054406aa41c820960e71
-    996c597e0a024c2ff0ffe289d8c7270e4ea1d38e294d7210eddeb2c0725a1305;
-  ea233ae033ca93034bc8fd8ea3c0625bbb15b00265264fdd61f62cc808b505fe
-    09e12ef9b3426991f7119c2e8349278342ed0072317c4ec7ab24561b61396b39
-    1fd72191fe9f00b0cca6a635d14904bd0c1e0ccd1275e84ad0b7bde134866e2a;
-  fe1fd3da05524af4ccd538f1d2ede09582101fc2a47c2e63758a546bed6cc5ec
-    523346406ef3df6ac9a455d0d2e7f732ad01c88245b07a888cc21c40fce11a76
-    de6cac8fdc878d9c4eda6b78f8b629ecf776980e49fed56bab936fc03924f44e;
-}
-
-sqr {
-  4dc87ad85abe8938634492ce2ea10bf48dc4aa2fa37a6a0fde3e5a01e90dde2b
-    346297c756d77b8ea312ddc455223f4577aea2a2e8d944cb24adb487de143b46;
-  a33aed91165d7fd13a543760d3915c1b5d411a21895cde81b2f3640b87550cc9
-    f923e49da9d5f45e23a782f911fac1a6c2e67cbbc7b03ee4675a0c5fbec03641;
-  a1406e453db6c92ef808295d1919c5bb2491c0ce6d5326d276c57e57943e0acc
-    18425bbd92149991c4545e65495af0e6372289e9a32649c127122243204bdd73;
-  70a56b8484234ed002a68c8d535a4e527a61c360f7d4ee5b4970c8ace1e12de0
-    bed1c435139f151d0650577e03c32428f63cdb7bc1920110b5fdbb27f08cb200;
-  86c3236a6194f1585b4dbeb09d0247fb7d3ae08063ccf9fc4fde70fc23735710
-    9b6509acadd5d31c4c843e91cec78be00aec4fdf7d86132965bd6f62f078f711;
-  0e5e83c51a8c091673425c38785e0aa1d74c7261a035a891bf734cca8c8a3db3
-    4efe5029e99438835a8a45d0180b8de357eac82ba9dd8e127baac0d758dfca1d;
-  31c39a5afc33f8a8d3c570b9dc5389bea6fdaaeeb44cd7524f6c445b9583a34c
-    359b7c8791cc87aa8b3c799c9d4d7e1f4062a4f64436d8c01071597e8c262127;
-  5a06203c15d6c1db6ea0fcf468a1e3f09d68c4a0f64c3d7e30e70290545e708e
-    07f8b435ea322bedf613458b1eb420f1d6bc96741d69695899bd40f7eca6f72a;
-  b1973433646474167b791b326827641260fb33d6a2c96d4e963a6b091f824505
-    52a62396dbbceead62912f8adfed2707fc25edb51aac19b2a274c246f1209f26;
-  96b157d71e107168fac206dd63007f10f4ae1225b0761c470ee18ecdb4fff20b
-    84ba2a84b156437cdcc39ecc8b1ad01bba934d8dfb7d504b9f2442db0ad01167;
-  6167d77675e19785960c28df551b458e41dfd0dfe5e56e785b7367997d5eb0a6
-    79a558436af4310d3eaee93f9a7cab72bd817fdf59d267e2c530ba8d667a005c;
-  fb4b2ab08db932ce10dd62639aabbb266f9ce775fb5a5e0875864f18a3ee506c
-    a6013661f2f0ab875739836039bff6bff4c993aefdda43dccecf4c404b9a612a;
-  ea26bcf0bfc3e15d4df7ddbcac8b5b9e9a7215d74196d77c9e0524e861c6aeb4
-    113e06861e3d338618695f4713464cea536c8019da77ff0dd9946f3b860df062;
-  b67b1ffffec757ef147e86cf60898c5dac515f080f43f4e120017caab4eee5ee
-    7d9748a1ff6ca9cdebeb3dd6668522767afb9ebf1c680fe7fb3f5848f7222036;
-  c122016f17f12e53f9ac031719fe428c826217b2b757ae44f2f33d1b8b1bb553
-    dc068d032b97c98eea6dd6c8bc42e9a0a6250c81a36a8f64615489e191287c72;
-  1266ff0654c08e6183cd6c3cc760cc5c88d1f49b918f2f8f587b3edd4adea513
-    f07f17fadb2e2dbd282d296fe5a15cc5c2baf6b45f5fd5dc4692f252039bc862;
-  4c4dd9c6e46fb2c096388583f2a0c969245452b23f16ea43e15064c45357ccef
-    5127fd4415a84115997b8b3ebe88a590efde9f8b53a43e86b1a4d60782c91025;
-  095d149c2616212e5f770f133e719d285a8bc888414271296684e732feb5473f
-    d8038bee551cac14d1c610bbc0960d943b01526072c589bc913ab51fd47bc848;
-  ad55f9f916d62bb13ceb1461b99e82d76b860c084ca408dd4a18f154b907754a
-    e5c86ee6350c9ab736229f3f53e2ab852641bb8a62fdda609444df377e9ca04a;
-  2e4976f45acc671e38add93aa6a89669cdc9874975879b3134dd37c633c9eb14
-    c6513f1a11346d33b05ad65eca13f11125cf70bdcdd6e666a8a7b9c5b6098429;
-}
-
-inv {
-  344ff33a2bc801f861bd13575797da35352c8164808d27f51ea7ca46931b2b1f
-    07f678dfeef071b038d692bf825cb4e75bc1934bd3a6e3dfea99e78bdaeecf3a;
-  670097e2fbbecf6516e949d98f6d722d3f732c33bfb4e62512f9d28d94546b64
-    b2f5cbcd7d8c996ed33a813b1aa39c36f5826b436867bd89b4ce43a156c1e96b;
-  234f3bd8760cdc8ae7fac9457da418cd082e42906ffe59a13e52185a7845e61c
-    7488ff9231e4819684148e16ebc25440732ffe7d211eb3d3263db1af9f1d0513;
-  22a39a35b1cabc6dfecd1b898593070f0c81bbd04b4b20f43a9c7c14b5dfe967
-    892024fdbc8937b9b3aef794f57b8ed8517510b6de3f6088987b1310c1dc7932;
-  d850c118c69198268826d05650958c6bed55b181090cf1c96493ecc4635a913f
-    7aeae1b0dc5211f374872e78da8f225325f3f33f9c42bfdeff25d425dff7710f;
-  33ccdc0e39f7cd0a61782c87ac089eb7bbcabce4dd222f05088d3d6332efe959
-    668f87e23239e965c80740d4daa9c913609388f291c11f950684f45e689a061d;
-  7c06f93b2f66001c74073b8ba7536049738e89b0a0d859a8a73710de3fadcf79
-    52df0aa24bb4a7474e6ed9852ba542c1f4c5219372a7b5d60988890e2955491e;
-  9a0ce9ff4026bd58abcf8a128dbc55a19c446005834a143634452821d5f9f0ee
-    79eaa93b6287705c0ba564c31bab1854c7f4354845be065c4bf94d38a7a8b421;
-  a13a127490bd3443fdba99baf61d113f3aadd6966c9732cd16348f9fbed32e0e
-    67290b25e6bd7328dd804309a6203c02a75657f593c7e66e48c9192524e5b87b;
-  35f7ac3eaa36c4ed338388fe7eda61cf237eff6ddc0847cb0c95255bbaef8ddc
-    4950601d2cfe75eb9c4524e2f40f404fe82d0014c916dc43d9416cd2e274992d;
-  8a058593035986da3a19e63dacaf40fb3db4cf382205fc4e4802e0ff0c61c8d6
-    6a23b743dc2fa4a4132780cf6edfed4c219760f3b31343b08710ea18d2c0fc43;
-  a10d03234e700ec92270b6105fdb787d8edd3f960fdd78ea2e169f49dc708d45
-    101dad1720604d0b093831baaa97fd0701ce773b9c1be1db0403533ad4376c0a;
-  52d3b9e030a5ed574f7f9489c47e73f78ef88a39b570045f9ef73c9a3e65f425
-    83da3e088dbc9a3cbe06496c5a52edc8d7abcbb8a0f839361762137b119d961a;
-  9928b5f14ec80a036479d7b08c128e601db880daebef36adde6fbd1f50f82629
-    8dcaa9a2439b77cbe44928ac2877e09755c505f58df4d0ffb9b23fc256b12779;
-  5a956523956f8ace6166ea6cb3c7421f8d1142d26084a81d615f00d578e03448
-    658a3ee24ec5b5f1d2d12614e535247c9f2f259131b00f654e09b4517c63ea09;
-  157492cd38a07802351ca0d1a5615d5c5f254692acce930fb6be351e9a52f088
-    32fec1eab85ddf8d27a437876e7f5a07f012b02e7971869811c3c31230204164;
-  2d07c109c332847567621ef4338e149b99c5bc3bf6e50943695da7fed5d8141e
-    a81472d28a8235bff43ad5cc012d52e95ece3dbc5ba2962dc54cf9e7f81bee04;
-  7e172f6c03415e83d4671e0191151d49e5257651ba73848254e68fad0a095c50
-    1a8efdc57ae9d39ffa64afbc5d2dc1f25a29d365ac3dee0d8529977c14aa4415;
-  1934546e37b0bac80319fa7f2f86c18e83de8da830b9d0b5019c26768974eda4
-    ffe55479771f20518d8fc6491055368b5dcce9b4e193d19897f1e116b9cdf946;
-  90324ccfe0e34e9b08db1862be3bc17798a8581ee097be76545e3bf9d586a2e6
-    0f5ccf4920d617c9b4f7fe6e2c9e95e89b5516555d5e3f5f9900485451d7425f;
-}
-
-quosqrt {
-  18798551568191dbfe6bcacf95bf4bf00290de4c773a1d4233d1eae272b3085b
-    2ee52110807ab6e31e0ed7b4de818d6474b514c63c99206e58a6df38e149123f
-    3819accb91d97a3f4dbca732f19723fc772a19b3eb4d307acad706cc7c7e1c1f
-    b5e653346e2685c0b24358cd0e68dc0388d5e64c14b2cf853528f9338381e360;
-  8671a0ecb7344f2e44fc9066aeb42661e848417e8c51b353680573830857d90f
-    9c4cfb1aa650924ceaf3e23b260d02b7d8b7dd4445360cad0bd4270428f55292
-    "" "";
-  bb0d27e1743f444e2f612c2ff575c6c6663f01869eaa8666774b8baa59b2a714
-    2fecb156c393d27d7b9a5e4cc2b57cb5524d5b945e92c5b4bdccdd6d00e684c6
-    "" "";
-  59af963f7245901807a46a59d4e49bab5b1fdf3001f63ef4e600ef8150d0e13a
-    b5ac3372ca5435577c416ba46a57879b0ca1df29057c540cac4edacc507b5e23
-    "" "";
-  a7b8659775a53e1fa315066be6a37a3f645d782cb69ec6b4f27fcf4daed3d82e
-    4550c4697a5d29d1a97b50ea65e98ec839567a3fc556ec3790b016c24b867d89
-    a190875f536f94ae2af8aae90bf0afabed437b36cf640d85529b150155eed53e
-    4c6f78a0ac906b51d5075516f40f505412bc84c9309bf27aad64eafeaa112a41;
-  7163512100699c32d5fadbe3583f2f6f314c347f1e66c434b15ac06a5733f3ed
-    2806d76598a43c24820daaf87afa5a9a4d414e5d8f51993f1b01166bb5479c27
-    01d5d023a6c5f7ec1d5df3179bb240e3003a9e3be8ad4e154c6e8f7cb7af6536
-    ec2a2fdc593a0813e2a20ce8644dbf1cffc561c41752b1eab391708348509a49;
-  e950533666a4a1edc3dae30637d6b005e34b614fe75555be0e1759def06a2aee
-    ac5a603347a585ca19eba141b1dd1b8833855e9807776627e8c9f92001a4b9b0
-    "" "";
-  d3c5ccb02442548901b3ffa2ed5564735b0b041386fd38e6c40844dc9183006e
-    5e6f23ccef94660e569bc42093d2b862ca605b81d64bb3589331d015082b4996
-    d7d578a72f1ea2dcacd0a96be285e9635230dc297fa7f6e1f2b9754e2d29190c
-    162a8758d0e15d23532f56941d7a169cadcf23d68058091e0d468ab1d2d6e673;
-  37cad075017c111f99135be6a0f553535d56153cef8839eee1e70614d65df1c2
-    e5f9944a377be3ab64daccfc9e711f4aa522c68a80efd0a70c72cdd4507014b7
-    "" "";
-  85dedba748f478537d016f20b9871e830e513514fbd27141aa54ca77b2a673be
-    950bc6fb51f6d8c36b7ddc8cb28d9efd498690a46c57888b279de0e549e84c52
-    fb7871031556b171a25dfd0483f0e2ed8d24a8acc2d9fc201f42f0b892fd541a
-    f2868efceaa94e8e5da202fb7c0f1d1272db57533d2603dfe0bd0f476d02ab65;
-  d70f399a983c6ad48acca796d9106c5e7681f34bdf34248f6dc54620282bb327
-    cad23bcd1fb96331bc8139f2a8f21d24492e56a7b80e343a7002acc96a739454
-    ff70c5bffe08911fb5522b21beecfd80fb018f0afef24fe85cfb7e4a5024960a
-    ee8e3a4001f76ee04aadd4de4113027f04fe70f5010db017a30481b5afdb6975;
-  71ee96ced0b50bc560f2477a88ea2447573490f71850f084ae0b318cafd8a75f
-    15c61eefd2c05d72fb07e44a006dfe314d8797f978bab1fe9f9276bcc82b542a
-    "" "";
-  c27a9f169b8096308f313ab5a521886084f03ec6d9e8b30e4773d0a3ab1a7c67
-    a7ca0e7fc5566dfc3790a3de164ef26d6452715db428994d438e79f65034d174
-    129427bd4c2195fac5a0da4c52ff634c697f18c3b02d0e7aad45a64d03b6e922
-    db6bd842b3de6a053a5f25b3ad009cb39680e73c4fd2f18552ba59b2fc49165d;
-  dd73476aeab865af0775723ebd2128ca71621b1d95231813c3d3cb32b805f418
-    dc6621f2ba82deb8272243baa5d2e177a60b1b780daa3ba081040e05b1d1b2f9
-    32ae54f7a7dfa101bad00f723898d29a7307454f86cd1197c44b07d1b997fa1f
-    bb51ab0858205efe452ff08dc7672d658cf8bab07932ee683bb4f82e46680560;
-  3a3ee482bf7075fa38780616603133ecea7b56acab59d96ebf7192e21c49a806
-    b7e6d647792961137dadce55ce69634379338bbda45fbef9d56be52620738d06
-    122b696683c2d1f3feedaf6166037ddbd7281e0c4c875724177f240b54e0dc22
-    dbd496997c3d2e0c0112509e99fc822428d7e1f3b378a8dbe880dbf4ab1f235d;
-  71f31797a8a36123e4a0b173ee4bc5a04d7799d1eba246df51cf943aeba0270c
-    7340069440d6c72b4536018eec373f50a1142c9e79de8a5396f994e53c64ab18
-    "" "";
-  0d2a6a9de4d52289cc724840670abcc5a4ee04f1197bd1d230689431b01afce0
-    21457f6784da81822df90f09b44782bd50a12c4fb378091cd33b177c734e0728
-    2b272304b3cca59e26431d91118a95c965bd542191c7cef760b085673e96a432
-    c2d8dcfb4c335a61d9bce26eee756a369a42abde6e3831089f4f7a98c1695b4d;
-  288b09090258a71747c1a08a51b0894a0c096f5b88ee38ea56a3aaefc1afa0f5
-    a7f6391e06b8972b18e899753bf3853270cae7971774041fa9bf09a55349f950
-    "" "";
-  e912e39e2199c3980c5fe3cac6d8bed394367f28213524f006a9b2c0cce4a6dc
-    e6b4a592e37fb5d3af73c486cc211a57d4077c093a161276dcb6eb44303d3ec6
-    "" "";
-  ec6785be59b890e07176c09195430b7f5daee0b0898ee744e578ac25873012b6
-    b3cd2df2c2531beeca882607d73f38403d8ff384f99be1ce582536bc3d4bfcd1
-    "" "";
-}
-
-sub-mulc-add-sub-mul {
-  ## A very basic smoke-test.
-  03 01 5 01 07 02 37;
-
-  ## Stress the bounds.
-  000000feffff030000f0ffffdfffff7f000000ffffff03000008ffff1f000040 00
-    0xfffff
-    000000feffff030000f0ffffdfffff7f000000ffffff03000008ffff1f000040
-    000000feffff030000f0ffffdfffff7f000000ffffff03000008ffff1f000040 00
-    00000cf2ffdf4400a09a000079fdffea040098edffa73b024072ffbfe0feff65;
-
-  ## Random tests.
-  6f0dc2547ad77f7b3da324876e63c724c1f69cb2bc70ff960f1594f90202e17f
-    23a2d45c26880166516e6831ab5070dd2247992418ad7cc41155a9362744f763
-    4783
-    e145b5f91b683918d1efe6193de27909bf9051b0157acfa458bc3f63e5272de5
-    e694fc475a442bd72cbbf11206474e3169fa74ad453aec3034c1dcc1f1dfbce0
-    f9b4f1ac9369241a302f874305cd2d2fba362b5735d36d3e072c7198d7dd4005
-    08518c9f52236272202869bf7cb549c667f6a27d1c4f18ab58605d63821a6c61;
-  f1b3d663fb9458ba8e4521e8e2c976fafc8936433b62e316c6dcff794b1ac8d0
-    2185dd6948ef2339c9a43518dd02eac6518852d1c35858dbdf5c1acf1d995884
-    -128133
-    d7a628aa59d409b755a1ff0d76f37ae8e4a73d47375940c61351074f3c42ad2a
-    4a353e9e7e9a0700ab2c043cc05f9795cc267e001b64799ca1849f024a42dfd7
-    dbef6513fba5ca19c545b162718eeba960b0930b8ce99c3edac5facf5fddf4f2
-    9dbfe69897a273171ab4a697f88a0d4b420a3ada7a7f9e67d0ba871e2097026d;
-  e8624dbe04a1b19102019d7fd9e06fe502764afb92330d03693279e872e84f81
-    8da8b04024ff708a8b5fa31a6a654fc31d3748f74a897898aa42c2bb65494586
-    -118148
-    83f63df59ce4b3161427b932ecbd7796bd162b553b70bbfef8a990ba6f20c23e
-    9d896d69ec478456fb6cad67774c6e3e0e313aadc0564d759380981fb12dc3b8
-    0e8799aa8de1b1ac4aeae4d1e8cd5936c66b8a0a60c8d17ec23bc9c9f94421ea
-    2221a87687c127b352e077bf7e975c83c667c8ce603e9d9fa5e02b195c7ad873;
-  2527a8ab98898038e9e132a1bc8349a33e2c2f6ec8b6c15b06410177297d30fb
-    71cdbe058a0357295dd5134fb95a630055f39d9bd8fa0c759b1b70fbef6147d0
-    -14780
-    0fe111e19ddf5d11d40b584a31888aea4a388540b86d14b962a1a7135114d5b3
-    a6386eeff2764007a570ba7e82a214667c2949a793fa0a52b7665c09285c6661
-    a7557aaa000c8840e08163b7eec08bf24ba275a35d85bfd7813aaafcc22715c8
-    867491333fc048b229ddb4740b1fe6dca1feebf1d40660814feeb1fce97fca12;
-  fe07ffcd6b14f75efd74ff983e8e5c20f379b0c78907f0e453753b457fb53159
-    617f2f7c1153eaea3ccae7dfb07fbe804b2cb5c8205d657c3106b5a60100cafc
-    -128312
-    a0af624a3f54278e2f7cc77f5d0f10750179bb18e07da059feb0bc98fb1d688f
-    ce432859e6d7e691ba9b44d467e8a5f1a97979facd2d3c7deec46e121193133b
-    d60050fad0f5c4b2e042141e4f7a418d3e8a8a308acc96651728f363ee793628
-    b9e4e8873e006d41104b1cd6a32282fa2b94ade000dd57dee6dd506cceb34c34;
-  b46e84be433f9e4f43ffa2f1f5200013953d820d292e3af978c54401a252111c
-    cb7cec0c48efa4e0e54f05ac18574d5f67bf1a1193d6d58f42183abc9f5bdd49
-    -3288
-    18603c0562c4d893a699fa6258e2de57e1cafd3e8ad756806d09db0c1ac9f86c
-    0854368c6b459ba6fcaa95db92605c9d791bf4dcc57bfda2ef318b48f7521d73
-    0c83d0b2d331ccc62bbcd2d2771b18bc0b909a3bbebcdcb99020952672f050d4
-    d54073b190601f1cc36c25109a5b44f04b6c2240c268bc71cb983d3dfb25cd64;
-  1f490365c3b82416fd3866a42a03f3bd643844e0d0cbebb66af54aa35de3efa4
-    dc805758c7e714a2acbc1e467520ecc3b9d23ce5133fe79e377e6d4520cd5196
-    -129141
-    1a53a3728ef3587085d0b530be8ae95e367927f9ac3b7126445d32b46f3abfad
-    0af6ce5107ca06fdfe732d11161b197830a963ec667065c5293bbdf843e23672
-    5bbfb655a175dcf7a4f4fc886a03e3d99cddbd34524c3cd2fb13b793bb2132be
-    7e5576020e7bac35c7f5b3dc6b60b2c1cca55f6c98141682efb4737963d0307e;
-  09e03f5d67a92cf076740e4261833f244b60da6d02cb42278e2ed9183b6eba3a
-    5a8b665434e91158559cfecf1d43d562c307518a3ce889165b406b1aae38a674
-    -13299
-    16e0d405bc40f2075f5dd901769def19f15759faef9a5fb6356b94c5c48be3e0
-    101da726c0dfd102c8eb2178640054248225a6fcfac1bab28a09b59cf38703d6
-    f268d102402d31a33e52a941a06c64a30a721ed55184edfcfcd85db6fe3db676
-    24fc9112ce6d3d70e8c245f9e2c883290384462065a5a1ab5821b9cf9d61953b;
-  f86ba345a367c676d99450d4893ef4033201c8ddbb631c4658e4ed24ece98749
-    a3c51a17107327742f44cc2e265482522cf39b6bcbff919bcf99fc033d76348f
-    -88039
-    5dcbe0be5f9f80b46d2e651504b10a3e481257a4bfacf40d8ccacea9d73dc2ea
-    2ac88350fbffcbc743d36fe45c80a70a8cbe88be36759943c8e124163e432dec
-    f54685e704df0e499e495b3b77e64aa0ec0c9fc0bb18ed456a412ac6079fe9d2
-    3e7c00ea9ee49825f5fbb9b704dc720b062d8e08ee8dd410f3d34d255602b56b;
-  1cd810875f48ef4c71ecb0997acfa31249ebcc9280e7c2f741038a0529f653d3
-    ba2e564cae8cdc2bea40d64b5598493ac2b11902d91b5aec7a0e4a8649aa7ab2
-    -77488
-    ca4929fb0fed99fd9dca7a21275dbd97185900d4eb362eb09bcb5ce7098aaaa2
-    89b395b440fab27d3b32e0740caac3ce38affbd80b2f8f7b6709294d6770873e
-    d2cd5ac1ea7b0e1f45bd3cc64b651518dcdf9f25078de7cc4970bf54976a0c8d
-    06ea5e15853bb29db5cfccd62db2e64067c90a97eab43039cacf4ee639ffe979;
-  9960c3131e513fba3241b1f9bdf44fdbe06c43d9cda9e05fdb451eda3e8df394
-    4c5f72392dddd1b8e84db5bfc2db04985fe3d1226a470c851a489f98d954e6ec
-    -33449
-    04eacb794c87c19087b793a0e2d187cc7e0b07d265fd6cc46946780d2ab83810
-    414db559bd22f12717b431310c1063534de5e627e983f4967b2fb38f2c5f87b0
-    599bee129778596ba77c27a896020fa55123b8635ff3d9efd56fe406de878146
-    26c7d591e0028dd611d6e84969da716eb740207e49f5ea02f17a3224612def12;
-  2cfc4c9cb8ca259bd4ffcbbd498510f8a65cca584303a28ed475584bd1eed111
-    3223cab1344be86c0af9995a769276cddbf70eaf55caee24dd4ec0d06c2f4309
-    -53728
-    3a48f8bd8a229fa9f5b9d7c4135ef6c3a251b0ce451f482471f017e963839405
-    bec0e71a657e85e024d91c41b3a2f75f478528d8ae1afb70bdc5da255d20de06
-    53dc48614937bd5ea1bce51b166bc9947e248a98cd0fac55f632cded216e9cfd
-    2999f607e716f0c769e9fdeff636568674f3601166d6b7f566a369b5d4e2797a;
-  c37946f39bde051e4a6f91a18fda21ec2bfcc375b703bbb81fdcc7ff15cfedf4
-    f37e2f1bb6b71763263e742cfd1ce8a9e004a5e06faf0afc52cf49ea89ad9244
-    -69223
-    0592777a8c77c1713a72b2ce18fa318fa93e9c6e6b870e54723a43408b502b74
-    cf575224b26f636b4b4f28c90995b87d900f6ca5ec9de6c24e65b747d303d221
-    8ab7d691dd76d7cd63d3456c677987a9e53904a4895f053e3de08786d564c837
-    1d667ed7c9b93f2972de23f4d633bcb5f2e56e446cba103c3cf2cf0931687b13;
-  2afb15ae6438b8eef9d07f2491e43e32a2b9287381c7bf036dce2a1b0a3542e5
-    18c9bb7c91d5e5ed96e6effc6609fe40e72c5634cac2cf6fb55b083c3339f40a
-    -33255
-    c0c870e0ee2116aa1182b2b4ee4bfde446f721fa6f1bba3a2ed4fb703855c673
-    91fd148ae6d53a419983999020d845503cc923e012e6869201615fbb8e460360
-    5d02294b16e04ca4a7fa4fa5dc9f12c7156e2a68c02495ea171a8cf13d35af99
-    f1f90c61c85c137e2e9d5ca7a6b388afd954f6c93548e5fc3b82e02fe875923e;
-  a7a7193315006fd85c97226f44708d61ecddad2e184d69b0db62f9fb2bc678bb
-    87a64ef3c67f464441927c08fd1b57d17bd644a422b96f151aa2d7920989e4ac
-    67151
-    6b31a270025004a878f214f100a764165033e170ea5e4c52832673cf88f9f0b3
-    0c0af67c56e0b2336ba06f447ea4f9cbf052147e35f16216b306ef1211ce4142
-    54fec5270095dfc21f44805ba17565386bc50d45bd1f797ebfa04da5040ad08c
-    92fdbcabd91ab43baa827594672dede4f0c71d8302b4cc8cd79270aa0c96d915;
-  5d72825031c526d9e1efe34fcbbbd81b91460112f9f950e78e12c777a2994a59
-    4334ab5246765e241435c6faac0a00add3a5adcdafe017121d03b9561d0d3516
-    -66199
-    ef3211bb4e1bac43430e48594577d1d271f76b46ea7e44542c23524b3d6236bc
-    1bfb4fb8d8429f0dd7a6cbc23dc2357ce9c1c72be3acf0a49abc331ac751e68a
-    7cf2ea00463d76152e230cb5465ab55d30f09afbd007d2b55393cfe8e348cf9a
-    c0a66f24e5800bec2b9ff65207afd4b29326525b910381d233bd91d51530d046;
-  01a66900161a4ad98f028a8da8f10142b4855712a7eb8ffbd699b13b7cc1a471
-    c6f8a0b42c3f2a1109201c7a97e3307f6cb56a1a27f13e4567456d9eac2a2f4e
-    -71473
-    e2eef0e19682ebb44cfdf84c71cb556311432fd948951a661d4240e16bc68d1c
-    f69b44aaff31db04fa4e8f14f51051d353e50110b1562b27d4493ac5e44a5b07
-    29039f65da48a24be024cf8f1af95ea9b09a08a54eec810e97018add81eec1df
-    a827fcc698403d01f8c2597a582ac8ddd612e5c2a520b0a2428e8dd35c58002d;
-  bc607923665e36ea0f8206b358fb3a327ef9a70ddcadb2edc49660891e932726
-    33e905cd1b262eba320c61428704c1d7c354361043ea7233c69f1f691f7c7175
-    -101999
-    e1b804b366c155d0f1a09fdbede434c669bf7f188daa96b8542dcbc9bbe66b6b
-    413d410937fbf0575bf34c0b70ee6cd5737e17b6058e774f889104b2f6cacc7b
-    0784aeb89be679694477cf399b605473c2c48887b687a980d7d333632e060e6c
-    16edc745e1596492fadffd303c31ce5827c3971c591c68f9e2b4f62c967aaa6f;
-  904e1b99ee3f860409a2db3aa4e539b2b50cebc57359f23fca21b5bb1306dc50
-    133d76a1f768d77a6801d73a570b35f6dbbd98aabfa4258445684143cd30a39f
-    -50858
-    547270fdf41f753a4189d2a9630ab17b4c6034829770a40fd8346e75e92610cf
-    076c4e34375857b9e6289287e03c744fd60d76c377a772f6edef3ad30e4afafb
-    f2e8a830fe203901f5f34ae6e606aa8f6cffb504b166cba4cdd84d011b783b90
-    659233daf8ebd47c77b9d46ac65237e1bfdeebbcc552c7db5cf8dd2d4bd1aa2d;
-  a6f4bce9adbe5a68585c205d20b05c6662748f5f1dd2458defbc126792837a63
-    8f1110929626587241fd403c8332b2ebbc398d4dd7042b993fc24a18b53e3847
-    81985
-    012aaf1e00a521e8e0639ed116e15476f0f8f1c6dff47d860ed60e0bb7c156f7
-    13aaf4f9f20d64110beef21bde5c7262c4bff80a85a08db1e098d45ec3d69457
-    eb3230fdacce04518359bfa7cff0c9d6d015966545e40e1c1da18b760031b2aa
-    607f7b77fc8d3ca15cdf6e2abba71853fa74739f83589a4458854ae2db0a4727;
-}
index 6dfc511..4e0d1cc 100644 (file)
--- a/f25519.c
+++ b/f25519.c
@@ -1,3 +1,44 @@
+/*
+ * f25519.c: arithmetic modulo 2^255 - 19
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb, and modified for Secnet (2017-04-30):
+ *
+ *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
+ *
+ *   * Remove the 16/32-bit implementation, since C99 always has 64-bit
+ *     arithmetic.
+ *
+ *   * Remove the test rig code: a replacement is in a separate source file.
+ *
+ *   * Disable some of the operations which aren't needed for X25519.
+ *     (They're used for Ed25519, which we don't need.)
+ *
+ * The file's original comment headers are preserved below.
+ */
 /* -*-c-*-
  *
  * Arithmetic modulo 2^255 - 19
 
 /*----- Header files ------------------------------------------------------*/
 
-#include "config.h"
-
-#include "ct.h"
 #include "f25519.h"
 
 /*----- Basic setup -------------------------------------------------------*/
 
-#if F25519_IMPL == 26
 /* 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.
@@ -68,30 +105,9 @@ typedef uint32 upiece;  typedef uint64 udblpiece;
   (w)->P[8] = v##8; (w)->P[9] = v##9;                                  \
 } while (0)
 
-#elif F25519_IMPL == 10
-/* Elements x of GF(2^255 - 19) are represented by 26 signed integers x_i: x
- * = SUM_{0<=i<26} x_i 2^ceil(255i/26); i.e., most pieces are 10 bits wide,
- * except for pieces 5, 10, 15, 20, and 25 which have 9 bits.
- */
-
-typedef  int16  piece;  typedef  int32  dblpiece;
-typedef uint16 upiece;  typedef uint32 udblpiece;
-#define P p10
-#define PIECEWD(i)                                                     \
-    ((i) == 5 || (i) == 10 || (i) == 15 || (i) == 20 || (i) == 25 ? 9 : 10)
-#define NPIECE 26
-
-#define B10 0x0400
-#define B9 0x200
-#define B8 0x100
-#define M10 0x3ff
-#define M9 0x1ff
-
-#endif
-
 /*----- Debugging machinery -----------------------------------------------*/
 
-#if defined(F25519_DEBUG) || defined(TEST_RIG)
+#if defined(F25519_DEBUG)
 
 #include <stdio.h>
 
@@ -134,8 +150,6 @@ DEF_FDUMP(fdump, piece, PIECEWD, NPIECE, 32, get_2p255m91())
 
 void f25519_load(f25519 *z, const octet xv[32])
 {
-#if F25519_IMPL == 26
-
   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),
@@ -199,50 +213,6 @@ void f25519_load(f25519 *z, const octet xv[32])
 
   /* And with that, we're done. */
   STASH(z, x);
-
-#elif F25519_IMPL == 10
-
-  piece x[NPIECE];
-  unsigned i, j, n, wd;
-  uint32 a;
-  int b, c;
-
-  /* First, just get the content out of the buffer. */
-  for (i = j = a = n = 0, wd = 10; j < NPIECE; i++) {
-    a |= (uint32)xv[i] << n; n += 8;
-    if (n >= wd) {
-      x[j++] = a&MASK(wd);
-      a >>= wd; n -= wd;
-      wd = PIECEWD(j);
-    }
-  }
-
-  /* There's a little bit left over from the top byte.  Carry it into the low
-   * piece.
-   */
-  x[0] += 19*(int)(a&MASK(n));
-
-  /* Next, convert the pieces into a roughly balanced signed representation.
-   * If a piece's top bit is set, lend a bit to the next piece over.  For
-   * x_25, this needs to be carried around, which is a bit fiddly.
-   */
-  b = x[NPIECE - 1]&B8;
-  c = 19&((b >> 3) - (b >> 8));
-  x[NPIECE - 1] -= b << 1;
-  for (i = NPIECE - 2; i > 0; i--) {
-    wd = PIECEWD(i) - 1;
-    b = x[i]&BIT(wd);
-    x[i + 1] += b >> wd;
-    x[i] -= b << 1;
-  }
-  b = x[0]&B9;
-  x[1] += (b >> 9) + (x[0] >> 10);
-  x[0] = (x[0]&M10) - (b << 1) + c;
-
-  /* And we're done. */
-  for (i = 0; i < NPIECE; i++) z->P[i] = x[i];
-
-#endif
 }
 
 /* --- @f25519_store@ --- *
@@ -259,8 +229,6 @@ void f25519_load(f25519 *z, const octet xv[32])
 
 void f25519_store(octet zv[32], const f25519 *x)
 {
-#if F25519_IMPL == 26
-
   piece PIECES(x), PIECES(y), c, d;
   uint32 zw0, zw1, zw2, zw3, zw4, zw5, zw6, zw7;
   mask32 m;
@@ -359,76 +327,6 @@ void f25519_store(octet zv[32], const f25519 *x)
   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);
-
-#elif F25519_IMPL == 10
-
-  piece y[NPIECE], yy[NPIECE], c, d;
-  unsigned i, j, n, wd;
-  uint32 m, a;
-
-  /* Before we do anything, copy the input so we can hack on it. */
-  for (i = 0; i < NPIECE; i++) y[i] = x->P[i];
-
-  /* First, propagate the carries throughout the pieces.
-   *
-   * It's worth paying careful attention to the bounds.  We assume that we
-   * start out with |y_i| <= 2^14.  We start by cutting off and reducing the
-   * carry c_25 from the topmost piece, y_25.  This leaves 0 <= y_25 < 2^9;
-   * and we'll have |c_25| <= 2^5.  We multiply this by 19 and we'll ad it
-   * onto y_0 and propagte the carries: but what bounds can we calculate on
-   * y before this?
-   *
-   * Let o_i = floor(255 i/26).  We have Y_i = SUM_{0<=j<i} y_j 2^{o_i}, so
-   * y = Y_26.  We see, inductively, that |Y_i| < 2^{31+o_{i-1}}: Y_0 = 0;
-   * |y_i| <= 2^14; and |Y_{i+1}| = |Y_i + y_i 2^{o_i}| <= |Y_i| + 2^{14+o_i}
-   * < 2^{15+o_i}.  Then x = Y_25 + 2^246 y_25, and we have better bounds for
-   * y_25, so
-   *
-   *   -2^251 < y + 19 c_25 < 2^255 + 2^251
-   *
-   * Here, the y_i are signed, so we must be cautious about bithacking them.
-   *
-   * (Rather closer than the 10-piece case above, but still doable in one
-   * pass.)
-   */
-  c = 19*ASR(piece, y[NPIECE - 1], 9);
-  y[NPIECE - 1] = (upiece)y[NPIECE - 1]&M9;
-  for (i = 0; i < NPIECE; i++) {
-    wd = PIECEWD(i);
-    y[i] += c;
-    c = ASR(piece, y[i], wd);
-    y[i] = (upiece)y[i]&MASK(wd);
-  }
-
-  /* Now the addition or subtraction. */
-  m = SIGN(c);
-  d = m&1;
-
-  d += y[0] + (19 ^ (M10&m));
-  yy[0] = d&M10;
-  d >>= 10;
-  for (i = 1; i < NPIECE; i++) {
-    wd = PIECEWD(i);
-    d += y[i] + (MASK(wd)&m);
-    yy[i] = d&MASK(wd);
-    d >>= wd;
-  }
-
-  /* Choose which value to keep. */
-  m = NONZEROP(c) | ~NONZEROP(d - 1);
-  for (i = 0; i < NPIECE; i++) y[i] = (yy[i]&m) | (y[i]&~m);
-
-  /* Store the result as an octet string. */
-  for (i = j = a = n = 0; i < NPIECE; i++) {
-    a |= (upiece)y[i] << n; n += PIECEWD(i);
-    while (n >= 8) {
-      zv[j++] = a&0xff;
-      a >>= 8; n -= 8;
-    }
-  }
-  zv[j++] = a;
-
-#endif
 }
 
 /* --- @f25519_set@ --- *
@@ -463,16 +361,11 @@ void f25519_set(f25519 *x, int a)
 
 void f25519_add(f25519 *z, const f25519 *x, const f25519 *y)
 {
-#if F25519_IMPL == 26
   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];
-#elif F25519_IMPL == 10
-  unsigned i;
-  for (i = 0; i < NPIECE; i++) z->P[i] = x->P[i] + y->P[i];
-#endif
 }
 
 /* --- @f25519_sub@ --- *
@@ -487,18 +380,15 @@ void f25519_add(f25519 *z, const f25519 *x, const f25519 *y)
 
 void f25519_sub(f25519 *z, const f25519 *x, const f25519 *y)
 {
-#if F25519_IMPL == 26
   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];
-#elif F25519_IMPL == 10
-  unsigned i;
-  for (i = 0; i < NPIECE; i++) z->P[i] = x->P[i] - y->P[i];
-#endif
 }
 
+#ifndef F25519_TRIM_X25519
+
 /* --- @f25519_neg@ --- *
  *
  * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
@@ -511,20 +401,19 @@ void f25519_sub(f25519 *z, const f25519 *x, const f25519 *y)
 
 void f25519_neg(f25519 *z, const f25519 *x)
 {
-#if F25519_IMPL == 26
   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];
-#elif F25519_IMPL == 10
-  unsigned i;
-  for (i = 0; i < NPIECE; i++) z->P[i] = -x->P[i];
-#endif
 }
 
+#endif
+
 /*----- Constant-time utilities -------------------------------------------*/
 
+#ifndef F25519_TRIM_X25519
+
 /* --- @f25519_pick2@ --- *
  *
  * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
@@ -542,7 +431,6 @@ void f25519_pick2(f25519 *z, const f25519 *x, const f25519 *y, uint32 m)
 {
   mask32 mm = FIX_MASK32(m);
 
-#if F25519_IMPL == 26
   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);
@@ -553,10 +441,6 @@ void f25519_pick2(f25519 *z, const f25519 *x, const f25519 *y, uint32 m)
   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);
-#elif F25519_IMPL == 10
-  unsigned i;
-  for (i = 0; i < NPIECE; i++) z->P[i] = PICK2(x->P[i], y->P[i], mm);
-#endif
 }
 
 /* --- @f25519_pickn@ --- *
@@ -578,7 +462,6 @@ void f25519_pickn(f25519 *z, const f25519 *v, size_t n, size_t i)
   uint32 b = (uint32)1 << (31 - i);
   mask32 m;
 
-#if F25519_IMPL == 26
   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--) {
@@ -595,17 +478,9 @@ void f25519_pickn(f25519 *z, const f25519 *v, size_t n, size_t i)
     CONDPICK(z->P[9], v->P[9], m);
     v++; b <<= 1;
   }
-#elif F25519_IMPL == 10
-  unsigned j;
+}
 
-  for (j = 0; j < NPIECE; j++) z->P[j] = 0;
-  while (n--) {
-    m = SIGN(b);
-    for (j = 0; j < NPIECE; j++) CONDPICK(z->P[j], v->P[j], m);
-    v++; b <<= 1;
-  }
 #endif
-}
 
 /* --- @f25519_condswap@ --- *
  *
@@ -623,7 +498,6 @@ void f25519_condswap(f25519 *x, f25519 *y, uint32 m)
 {
   mask32 mm = FIX_MASK32(m);
 
-#if F25519_IMPL == 26
   CONDSWAP(x->P[0], y->P[0], mm);
   CONDSWAP(x->P[1], y->P[1], mm);
   CONDSWAP(x->P[2], y->P[2], mm);
@@ -634,12 +508,10 @@ void f25519_condswap(f25519 *x, f25519 *y, uint32 m)
   CONDSWAP(x->P[7], y->P[7], mm);
   CONDSWAP(x->P[8], y->P[8], mm);
   CONDSWAP(x->P[9], y->P[9], mm);
-#elif F25519_IMPL == 10
-  unsigned i;
-  for (i = 0; i < NPIECE; i++) CONDSWAP(x->P[i], y->P[i], mm);
-#endif
 }
 
+#ifndef F25519_TRIM_X25519
+
 /* --- @f25519_condneg@ --- *
  *
  * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
@@ -655,16 +527,10 @@ void f25519_condswap(f25519 *x, f25519 *y, uint32 m)
 
 void f25519_condneg(f25519 *z, const f25519 *x, uint32 m)
 {
-#ifdef NEG_TWOC
   mask32 m_xor = FIX_MASK32(m);
   piece m_add = m&1;
 # define CONDNEG(x) (((x) ^ m_xor) + m_add)
-#else
-  int s = PICK2(-1, +1, m);
-# define CONDNEG(x) (s*(x))
-#endif
 
-#if F25519_IMPL == 26
   z->P[0] = CONDNEG(x->P[0]);
   z->P[1] = CONDNEG(x->P[1]);
   z->P[2] = CONDNEG(x->P[2]);
@@ -675,17 +541,13 @@ void f25519_condneg(f25519 *z, const f25519 *x, uint32 m)
   z->P[7] = CONDNEG(x->P[7]);
   z->P[8] = CONDNEG(x->P[8]);
   z->P[9] = CONDNEG(x->P[9]);
-#elif F25519_IMPL == 10
-  unsigned i;
-  for (i = 0; i < NPIECE; i++) z->P[i] = CONDNEG(x->P[i]);
-#endif
 
 #undef CONDNEG
 }
 
-/*----- Multiplication ----------------------------------------------------*/
+#endif
 
-#if F25519_IMPL == 26
+/*----- 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
@@ -721,67 +583,6 @@ void f25519_condneg(f25519 *z, const f25519 *x, uint32 m)
   CARRYSTEP(z##9, _t9, M25, B24,  1, _t8, 26);                         \
 } while (0)
 
-#elif F25519_IMPL == 10
-
-/* Perform carry propagation on X. */
-static void carry_reduce(dblpiece x[NPIECE])
-{
-  /* Initial bounds: we assume |x_i| < 2^31 - 2^27. */
-
-  unsigned i, j;
-  dblpiece c;
-
-  /* The result is nearly canonical, because we do sequential carry
-   * propagation, because smaller processors are more likely to prefer the
-   * smaller working set than the instruction-level parallelism.
-   *
-   * Start at x_23; truncate it to 10 bits, and propagate the carry to x_24.
-   * Truncate x_24 to 10 bits, and add the carry onto x_25.  Truncate x_25 to
-   * 9 bits, and add 19 times the carry onto x_0.  And so on.
-   *
-   * Let c_i be the portion of x_i to be carried onto x_{i+1}.  I claim that
-   * |c_i| <= 2^22.  Then the carry /into/ any x_i has magnitude at most
-   * 19*2^22 < 2^27 (allowing for the reduction as we carry from x_25 to
-   * x_0), and x_i after carry is bounded above by 2^31.  Hence, the carry
-   * out is at most 2^22, as claimed.
-   *
-   * Once we reach x_23 for the second time, we start with |x_23| <= 2^9.
-   * The carry into x_23 is at most 2^27 as calculated above; so the carry
-   * out into x_24 has magnitude at most 2^17.  In turn, |x_24| <= 2^9 before
-   * the carry, so is now no more than 2^18 in magnitude, and the carry out
-   * into x_25 is at most 2^8.  This leaves |x_25| < 2^9 after carry
-   * propagation.
-   *
-   * Be careful with the bit hacking because the quantities involved are
-   * signed.
-   */
-
-  /*For each piece, we bias it so that floor division (as done by an
-   * arithmetic right shift) and modulus (as done by bitwise-AND) does the
-   * right thing.
-   */
-#define CARRY(i, wd, b, m) do {                                                \
-  x[i] += (b);                                                         \
-  c = ASR(dblpiece, x[i], (wd));                                       \
-  x[i] = (dblpiece)((udblpiece)x[i]&(m)) - (b);                                \
-} while (0)
-
-                            {                CARRY(23, 10, B9, M10);      }
-                            { x[24] +=    c; CARRY(24, 10, B9, M10);      }
-                            { x[25] +=    c; CARRY(25,  9, B8,  M9);      }
-                            {  x[0] += 19*c; CARRY( 0, 10, B9, M10);      }
-  for (i = 1; i < 21; ) {
-    for (j = i + 4; i < j; ) {  x[i] +=    c; CARRY( i, 10, B9, M10); i++; }
-                            {  x[i] +=    c; CARRY( i,  9, B8,  M9); i++; }
-  }
-  while (i < 25)            {  x[i] +=    c; CARRY( i, 10, B9, M10); i++; }
-  x[25] += c;
-
-#undef CARRY
-}
-
-#endif
-
 /* --- @f25519_mulconst@ --- *
  *
  * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
@@ -795,8 +596,6 @@ static void carry_reduce(dblpiece x[NPIECE])
 
 void f25519_mulconst(f25519 *z, const f25519 *x, long a)
 {
-#if F25519_IMPL == 26
-
   piece PIECES(x);
   dblpiece PIECES(z), aa = a;
 
@@ -811,17 +610,6 @@ void f25519_mulconst(f25519 *z, const f25519 *x, long a)
   /* Following `CARRY_REDUCE', we'll have |z_i| <= 2^26. */
   CARRY_REDUCE(z, z);
   STASH(z, z);
-
-#elif F25519_IMPL == 10
-
-  dblpiece y[NPIECE];
-  unsigned i;
-
-  for (i = 0; i < NPIECE; i++) y[i] = a*x->P[i];
-  carry_reduce(y);
-  for (i = 0; i < NPIECE; i++) z->P[i] = y[i];
-
-#endif
 }
 
 /* --- @f25519_mul@ --- *
@@ -836,8 +624,6 @@ void f25519_mulconst(f25519 *z, const f25519 *x, long a)
 
 void f25519_mul(f25519 *z, const f25519 *x, const f25519 *y)
 {
-#if F25519_IMPL == 26
-
   piece PIECES(x), PIECES(y);
   dblpiece PIECES(z);
   unsigned i;
@@ -902,48 +688,6 @@ void f25519_mul(f25519 *z, const f25519 *x, const f25519 *y)
    */
   for (i = 0; i < 2; i++) CARRY_REDUCE(z, z);
   STASH(z, z);
-
-#elif F25519_IMPL == 10
-
-  dblpiece u[NPIECE], t, tt, p;
-  unsigned i, j, k;
-
-  /* This is unpleasant.  Honestly, this table seems to be the best way of
-   * doing it.
-   */
-  static const unsigned short off[NPIECE] = {
-      0,  10,  20,  30,  40,  50,  59,  69,  79,  89,  99, 108, 118,
-    128, 138, 148, 157, 167, 177, 187, 197, 206, 216, 226, 236, 246
-  };
-
-  /* First pass: things we must multiply by 19 or 38. */
-  for (i = 0; i < NPIECE - 1; i++) {
-    t = tt = 0;
-    for (j = i + 1; j < NPIECE; j++) {
-      k = NPIECE + i - j; p = (dblpiece)x->P[j]*y->P[k];
-      if (off[i] < off[j] + off[k] - 255) tt += p;
-      else t += p;
-    }
-    u[i] = 19*(t + 2*tt);
-  }
-  u[NPIECE - 1] = 0;
-
-  /* Second pass: things we must multiply by 1 or 2. */
-  for (i = 0; i < NPIECE; i++) {
-    t = tt = 0;
-    for (j = 0; j <= i; j++) {
-      k = i - j; p = (dblpiece)x->P[j]*y->P[k];
-      if (off[i] < off[j] + off[k]) tt += p;
-      else t += p;
-    }
-    u[i] += t + 2*tt;
-  }
-
-  /* And we're done. */
-  carry_reduce(u);
-  for (i = 0; i < NPIECE; i++) z->P[i] = u[i];
-
-#endif
 }
 
 /* --- @f25519_sqr@ --- *
@@ -958,8 +702,6 @@ void f25519_mul(f25519 *z, const f25519 *x, const f25519 *y)
 
 void f25519_sqr(f25519 *z, const f25519 *x)
 {
-#if F25519_IMPL == 26
-
   piece PIECES(x);
   dblpiece PIECES(z);
   unsigned i;
@@ -1003,10 +745,6 @@ void f25519_sqr(f25519 *z, const f25519 *x)
   /* See `f25519_mul' for details. */
   for (i = 0; i < 2; i++) CARRY_REDUCE(z, z);
   STASH(z, z);
-
-#elif F25519_IMPL == 10
-  f25519_mul(z, x, x);
-#endif
 }
 
 /*----- More complicated things -------------------------------------------*/
@@ -1063,6 +801,8 @@ void f25519_inv(f25519 *z, const f25519 *x)
 #undef SQRN
 }
 
+#ifndef F25519_TRIM_X25519
+
 /* --- @f25519_quosqrt@ --- *
  *
  * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
@@ -1170,318 +910,6 @@ int f25519_quosqrt(f25519 *z, const f25519 *x, const f25519 *y)
   return (rc);
 }
 
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/report.h>
-#include <mLib/str.h>
-#include <mLib/testrig.h>
-
-static void fixdstr(dstr *d)
-{
-  if (d->len > 32)
-    die(1, "invalid length for f25519");
-  else if (d->len < 32) {
-    dstr_ensure(d, 32);
-    memset(d->buf + d->len, 0, 32 - d->len);
-    d->len = 32;
-  }
-}
-
-static void cvt_f25519(const char *buf, dstr *d)
-{
-  dstr dd = DSTR_INIT;
-
-  type_hex.cvt(buf, &dd); fixdstr(&dd);
-  dstr_ensure(d, sizeof(f25519)); d->len = sizeof(f25519);
-  f25519_load((f25519 *)d->buf, (const octet *)dd.buf);
-  dstr_destroy(&dd);
-}
-
-static void dump_f25519(dstr *d, FILE *fp)
-  { fdump(stderr, "???", (const piece *)d->buf); }
-
-static void cvt_f25519_ref(const char *buf, dstr *d)
-  { type_hex.cvt(buf, d); fixdstr(d); }
-
-static void dump_f25519_ref(dstr *d, FILE *fp)
-{
-  f25519 x;
-
-  f25519_load(&x, (const octet *)d->buf);
-  fdump(stderr, "???", x.P);
-}
-
-static int eq(const f25519 *x, dstr *d)
-  { octet b[32]; f25519_store(b, x); return (memcmp(b, d->buf, 32) == 0); }
-
-static const test_type
-  type_f25519 = { cvt_f25519, dump_f25519 },
-  type_f25519_ref = { cvt_f25519_ref, dump_f25519_ref };
-
-#define TEST_UNOP(op)                                                  \
-  static int vrf_##op(dstr dv[])                                       \
-  {                                                                    \
-    f25519 *x = (f25519 *)dv[0].buf;                                   \
-    f25519 z, zz;                                                      \
-    int ok = 1;                                                                \
-                                                                       \
-    f25519_##op(&z, x);                                                        \
-    if (!eq(&z, &dv[1])) {                                             \
-      ok = 0;                                                          \
-      fprintf(stderr, "failed!\n");                                    \
-      fdump(stderr, "x", x->P);                                                \
-      fdump(stderr, "calc", z.P);                                      \
-      f25519_load(&zz, (const octet *)dv[1].buf);                      \
-      fdump(stderr, "z", zz.P);                                                \
-    }                                                                  \
-                                                                       \
-    return (ok);                                                       \
-  }
-
-TEST_UNOP(neg)
-TEST_UNOP(sqr)
-TEST_UNOP(inv)
-
-#define TEST_BINOP(op)                                                 \
-  static int vrf_##op(dstr dv[])                                       \
-  {                                                                    \
-    f25519 *x = (f25519 *)dv[0].buf, *y = (f25519 *)dv[1].buf;         \
-    f25519 z, zz;                                                      \
-    int ok = 1;                                                                \
-                                                                       \
-    f25519_##op(&z, x, y);                                             \
-    if (!eq(&z, &dv[2])) {                                             \
-      ok = 0;                                                          \
-      fprintf(stderr, "failed!\n");                                    \
-      fdump(stderr, "x", x->P);                                                \
-      fdump(stderr, "y", y->P);                                                \
-      fdump(stderr, "calc", z.P);                                      \
-      f25519_load(&zz, (const octet *)dv[2].buf);                      \
-      fdump(stderr, "z", zz.P);                                                \
-    }                                                                  \
-                                                                       \
-    return (ok);                                                       \
-  }
-
-TEST_BINOP(add)
-TEST_BINOP(sub)
-TEST_BINOP(mul)
-
-static int vrf_mulc(dstr dv[])
-{
-  f25519 *x = (f25519 *)dv[0].buf;
-  long a = *(const long *)dv[1].buf;
-  f25519 z, zz;
-  int ok = 1;
-
-  f25519_mulconst(&z, x, a);
-  if (!eq(&z, &dv[2])) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    fdump(stderr, "x", x->P);
-    fprintf(stderr, "a = %ld\n", a);
-    fdump(stderr, "calc", z.P);
-    f25519_load(&zz, (const octet *)dv[2].buf);
-    fdump(stderr, "z", zz.P);
-  }
-
-  return (ok);
-}
-
-static int vrf_condneg(dstr dv[])
-{
-  f25519 *x = (f25519 *)dv[0].buf;
-  uint32 m = *(uint32 *)dv[1].buf;
-  f25519 z;
-  int ok = 1;
-
-  f25519_condneg(&z, x, m);
-  if (!eq(&z, &dv[2])) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    fdump(stderr, "x", x->P);
-    fprintf(stderr, "m = 0x%08lx\n", (unsigned long)m);
-    fdump(stderr, "calc z", z.P);
-    f25519_load(&z, (const octet *)dv[1].buf);
-    fdump(stderr, "want z", z.P);
-  }
-
-  return (ok);
-}
-
-static int vrf_pick2(dstr dv[])
-{
-  f25519 *x = (f25519 *)dv[0].buf, *y = (f25519 *)dv[1].buf;
-  uint32 m = *(uint32 *)dv[2].buf;
-  f25519 z;
-  int ok = 1;
-
-  f25519_pick2(&z, x, y, m);
-  if (!eq(&z, &dv[3])) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    fdump(stderr, "x", x->P);
-    fdump(stderr, "y", y->P);
-    fprintf(stderr, "m = 0x%08lx\n", (unsigned long)m);
-    fdump(stderr, "calc z", z.P);
-    f25519_load(&z, (const octet *)dv[3].buf);
-    fdump(stderr, "want z", z.P);
-  }
-
-  return (ok);
-}
-
-static int vrf_pickn(dstr dv[])
-{
-  dstr d = DSTR_INIT;
-  f25519 v[32], z;
-  size_t i = *(uint32 *)dv[1].buf, j, n;
-  const char *p;
-  char *q;
-  int ok = 1;
-
-  for (q = dv[0].buf, n = 0; (p = str_qword(&q, 0)) != 0; n++)
-    { cvt_f25519(p, &d); v[n] = *(f25519 *)d.buf; }
-
-  f25519_pickn(&z, v, n, i);
-  if (!eq(&z, &dv[2])) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    for (j = 0; j < n; j++) {
-      fprintf(stderr, "v[%2u]", (unsigned)j);
-      fdump(stderr, "", v[j].P);
-    }
-    fprintf(stderr, "i = %u\n", (unsigned)i);
-    fdump(stderr, "calc z", z.P);
-    f25519_load(&z, (const octet *)dv[2].buf);
-    fdump(stderr, "want z", z.P);
-  }
-
-  dstr_destroy(&d);
-  return (ok);
-}
-
-static int vrf_condswap(dstr dv[])
-{
-  f25519 *x = (f25519 *)dv[0].buf, *y = (f25519 *)dv[1].buf;
-  f25519 xx = *x, yy = *y;
-  uint32 m = *(uint32 *)dv[2].buf;
-  int ok = 1;
-
-  f25519_condswap(&xx, &yy, m);
-  if (!eq(&xx, &dv[3]) || !eq(&yy, &dv[4])) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    fdump(stderr, "x", x->P);
-    fdump(stderr, "y", y->P);
-    fprintf(stderr, "m = 0x%08lx\n", (unsigned long)m);
-    fdump(stderr, "calc xx", xx.P);
-    fdump(stderr, "calc yy", yy.P);
-    f25519_load(&xx, (const octet *)dv[3].buf);
-    f25519_load(&yy, (const octet *)dv[4].buf);
-    fdump(stderr, "want xx", xx.P);
-    fdump(stderr, "want yy", yy.P);
-  }
-
-  return (ok);
-}
-
-static int vrf_quosqrt(dstr dv[])
-{
-  f25519 *x = (f25519 *)dv[0].buf, *y = (f25519 *)dv[1].buf;
-  f25519 z, zz;
-  int rc;
-  int ok = 1;
-
-  if (dv[2].len) { fixdstr(&dv[2]); fixdstr(&dv[3]); }
-  rc = f25519_quosqrt(&z, x, y);
-  if (!dv[2].len ? !rc : (rc || (!eq(&z, &dv[2]) && !eq(&z, &dv[3])))) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    fdump(stderr, "x", x->P);
-    fdump(stderr, "y", y->P);
-    if (rc) fprintf(stderr, "calc: FAIL\n");
-    else fdump(stderr, "calc", z.P);
-    if (!dv[2].len)
-      fprintf(stderr, "exp: FAIL\n");
-    else {
-      f25519_load(&zz, (const octet *)dv[2].buf);
-      fdump(stderr, "z", zz.P);
-      f25519_load(&zz, (const octet *)dv[3].buf);
-      fdump(stderr, "z'", zz.P);
-    }
-  }
-
-  return (ok);
-}
-
-static int vrf_sub_mulc_add_sub_mul(dstr dv[])
-{
-  f25519 *u = (f25519 *)dv[0].buf, *v = (f25519 *)dv[1].buf,
-    *w = (f25519 *)dv[3].buf, *x = (f25519 *)dv[4].buf,
-    *y = (f25519 *)dv[5].buf;
-  long a = *(const long *)dv[2].buf;
-  f25519 umv, aumv, wpaumv, xmy, z, zz;
-  int ok = 1;
-
-  f25519_sub(&umv, u, v);
-  f25519_mulconst(&aumv, &umv, a);
-  f25519_add(&wpaumv, w, &aumv);
-  f25519_sub(&xmy, x, y);
-  f25519_mul(&z, &wpaumv, &xmy);
-
-  if (!eq(&z, &dv[6])) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    fdump(stderr, "u", u->P);
-    fdump(stderr, "v", v->P);
-    fdump(stderr, "u - v", umv.P);
-    fprintf(stderr, "a = %ld\n", a);
-    fdump(stderr, "a (u - v)", aumv.P);
-    fdump(stderr, "w + a (u - v)", wpaumv.P);
-    fdump(stderr, "x", x->P);
-    fdump(stderr, "y", y->P);
-    fdump(stderr, "x - y", xmy.P);
-    fdump(stderr, "(x - y) (w + a (u - v))", z.P);
-    f25519_load(&zz, (const octet *)dv[6].buf); fdump(stderr, "z", zz.P);
-  }
-
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "add", vrf_add, { &type_f25519, &type_f25519, &type_f25519_ref } },
-  { "sub", vrf_sub, { &type_f25519, &type_f25519, &type_f25519_ref } },
-  { "neg", vrf_neg, { &type_f25519, &type_f25519_ref } },
-  { "condneg", vrf_condneg,
-    { &type_f25519, &type_uint32, &type_f25519_ref } },
-  { "mul", vrf_mul, { &type_f25519, &type_f25519, &type_f25519_ref } },
-  { "mulconst", vrf_mulc, { &type_f25519, &type_long, &type_f25519_ref } },
-  { "pick2", vrf_pick2,
-    { &type_f25519, &type_f25519, &type_uint32, &type_f25519_ref } },
-  { "pickn", vrf_pickn,
-    { &type_string, &type_uint32, &type_f25519_ref } },
-  { "condswap", vrf_condswap,
-    { &type_f25519, &type_f25519, &type_uint32,
-      &type_f25519_ref, &type_f25519_ref } },
-  { "sqr", vrf_sqr, { &type_f25519, &type_f25519_ref } },
-  { "inv", vrf_inv, { &type_f25519, &type_f25519_ref } },
-  { "quosqrt", vrf_quosqrt,
-    { &type_f25519, &type_f25519, &type_hex, &type_hex } },
-  { "sub-mulc-add-sub-mul", vrf_sub_mulc_add_sub_mul,
-    { &type_f25519, &type_f25519, &type_long, &type_f25519,
-      &type_f25519, &type_f25519, &type_f25519_ref } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, tests, SRCDIR "/t/f25519");
-  return (0);
-}
-
 #endif
 
 /*----- That's all, folks -------------------------------------------------*/
index fc75546..8450748 100644 (file)
--- a/f25519.h
+++ b/f25519.h
@@ -1,3 +1,42 @@
+/*
+ * f25519.h: arithmetic modulo 2^255 - 19
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb, and lightly modified for Secnet (2017-04-30):
+ *
+ *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
+ *
+ *   * Remove the 16/32-bit implementation, since C99 always has 64-bit
+ *     arithmetic.
+ *
+ *   * Disable some of the operations which aren't needed for X25519.
+ *     (They're used for Ed25519, which we don't need.)
+ *
+ * The file's original comment headers are preserved below.
+ */
 /* -*-c-*-
  *
  * Arithmetic modulo 2^255 - 19
@@ -34,7 +73,7 @@
 
 /*----- Header files ------------------------------------------------------*/
 
-#include <mLib/bits.h>
+#include "fake-mLib-bits.h"
 
 #ifndef CATACOMB_QFARITH_H
 #  include "qfarith.h"
 
 typedef union {
   int32 p26[10];
-  int16 p10[26];
 } f25519;
 
-#if !defined(F25519_IMPL) && defined(HAVE_INT64)
-#  define F25519_IMPL 26
-#endif
-
-#ifndef F25519_IMPL
-#  define F25519_IMPL 10
-#endif
-
 /*----- Functions provided ------------------------------------------------*/
 
+#define F25519_TRIM_X25519
+
 /* --- @f25519_set@ --- *
  *
  * Arguments:  @f25519 *z@ = where to write the result
@@ -108,6 +140,8 @@ extern void f25519_load(f25519 */*z*/, const octet /*xv*/[32]);
 
 extern void f25519_store(octet /*zv*/[32], const f25519 */*x*/);
 
+#ifndef F25519_TRIM_X25519
+
 /* --- @f25519_pick2@ --- *
  *
  * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
@@ -141,6 +175,8 @@ extern void f25519_pick2(f25519 */*z*/, const f25519 */*x*/,
 extern void f25519_pickn(f25519 */*z*/, const f25519 */*v*/, size_t /*n*/,
                         size_t /*i*/);
 
+#endif
+
 /* --- @f25519_condswap@ --- *
  *
  * Arguments:  @f25519 *x, *y@ = two operands
@@ -181,6 +217,8 @@ extern void f25519_add(f25519 */*z*/,
 extern void f25519_sub(f25519 */*z*/,
                       const f25519 */*x*/, const f25519 */*y*/);
 
+#ifndef F25519_TRIM_X25519
+
 /* --- @f25519_neg@ --- *
  *
  * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
@@ -208,6 +246,8 @@ extern void f25519_neg(f25519 */*z*/, const f25519 */*x*/);
 
 extern void f25519_condneg(f25519 */*z*/, const f25519 */*x*/, uint32 /*m*/);
 
+#endif
+
 /* --- @f25519_mulconst@ --- *
  *
  * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
@@ -260,6 +300,8 @@ extern void f25519_sqr(f25519 */*z*/, const f25519 */*x*/);
 
 extern void f25519_inv(f25519 */*z*/, const f25519 */*x*/);
 
+#ifndef F25519_TRIM_X25519
+
 /* --- @f25519_quosqrt@ --- *
  *
  * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
@@ -276,6 +318,8 @@ extern void f25519_inv(f25519 */*z*/, const f25519 */*x*/);
 extern int f25519_quosqrt(f25519 */*z*/,
                          const f25519 */*x*/, const f25519 */*y*/);
 
+#endif
+
 /*----- That's all, folks -------------------------------------------------*/
 
 #ifdef __cplusplus
diff --git a/fake-mLib-bits.h b/fake-mLib-bits.h
new file mode 100644 (file)
index 0000000..3fa7ecb
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef fake_mLib_bits_h
+#define fake_mLib_bits_h
+
+/* The <mLib/bits.h> header defines a large number of types and macros for
+ * various kinds of bithacking.  Notably, it has machinery for autodetecting
+ * suitable types holding (at least) various numbers of bits -- a service
+ * which C99 provides through other means.
+ *
+ * This file provides a small portion of the <mLib/bits.h> interface, just
+ * enough to make the pieces of code lifted from Catacomb feel at home.
+ */
+
+#include <stdint.h>
+#include "unaligned.h"
+
+typedef uint8_t octet;
+typedef uint_fast32_t uint32;
+typedef uint_fast64_t uint64;
+#define HAVE_UINT64 1
+
+#define LOAD32_L(p) (get_uint32_le(p))
+#define STORE32_L(p, x) put_uint32_le((p), (x))
+
+#define U32(x) ((uint32)(x) & 0xffffffffu)
+
+#define NEG_TWOC 1                     /* assume two's complement */
+
+#endif /* fake_mLib_bits_h */
diff --git a/fgoldi-tests.in b/fgoldi-tests.in
deleted file mode 100644 (file)
index 1f635c7..0000000
+++ /dev/null
@@ -1,572 +0,0 @@
-### Test cases for arithmetic mod 2^448 - 2^224 - 1.
-
-add {
-  ## Some easy ones.
-  ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff
-    00
-    ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff;
-  fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
-    0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-    fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff;
-  fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
-    01 00;
-
-  ## Random tests.
-  6b3944398448a0a5f6c4e1be9abfcbb082b8f68f1c831d51ef2244f6e1a4c4baaf0ada769c1261b8e14b4856de381d69961078ea1949d39c
-    62e933c5f93e57e042d66b89d3c72ee85441b1207732d888b3d6bc35f3bcef91a6f4564cb085fd3239191c2fe427dcdb0e81164d30ca8145
-    cd2278fe7d87f785399b4d486e87fa98d7f9a7b093b5f5d9a2f9002cd561b44c56ff30c34c985eeb1a656485c260f944a5918e374a1355e2;
-  34938a406030a285024e9ff0a45987b53accc9d5d59828de8b8e07ba693b64d1dd2c7a190e708253a9ae57572e44fa458c8f8ac87cd96037
-    9d05863131328886c7203fe70924761e56244d40a04d4b5592f1c6a457b9d94fe950fb8a865f9091ba9223479f3e46680fb78ccddc776bf2
-    d298107291622a0cca6eded7ae7dfdd390f0161676e673331e80ce5ec2f43d21c77d75a494cf12e563417b9ecd8240ae9b4617965951cc29;
-  4e9cb6823482233daf59662d00212f2afe42183f8ce949b2e0ca5473e32ab647fe9bc1c472b2288715c0d5b118043fbc9aec782654363cdd
-    6c62329ec8eb576b6866cb6af702b891dd2cd72d21c354ada34221141381acca066fb46a8fbce28df44f0ac8062e38847067b8639be867f8
-    bbfee820fd6d7ba817c03198f723e7bbdb6fef6cadac9e5f840d7687f7ab6212050b762f026f0b150a10e0791f3277400b54318aef1ea4d5;
-  b46d33f24a69c2288bed34eb054d1fcd6244606cffca7d53ff4e68f113174655a9a72898ad2699fe49d069a0a84e077bf48205008dee04aa
-    9abc68911a75a6a376837cc6fc0e18c63cfb81747a59ba1314412f032f8b2a2fc5dde29176d141e71dbc11aeb2ecb9a336c8467882a175ea
-    4f2a9c8365de68cc0171b1b1025c37939f3fe2e079243867139097f443a270846e850b2a24f8dae5678c7b4e5b3bc11e2b4b4c780f907a94;
-  1195eae69f2bad43b7b8330395e41c811bae2f753f0a6727b9decd2e553dce743dbb568b45140c3a464c8646db12b3af18df328a95640706
-    8fc020ba693b4014fbf4e9c64223a8c3234e1361b8e2a745e3897f582537e20417831c159c107451fec49b88c4cde774330d8986430b39e0
-    a0550ba10967ed57b2ad1dcad707c5443ffc42d6f7ec0e6d9c684d877a74b079543e73a0e124808b441122cf9fe09a244cecbb10d96f40e6;
-  4b25a323cba12b5d042369a065a3696c7613898205f7defd3ab15ec351ec9fe1ba453c8b9abf254ff793c92b1f77d5f23f7629c04ec5c70d
-    b12ee8f930b029e2e4b79b808566b88b8087a510e5f80751ffc8f5426709bc2b40608e3e769dbd97d37dfe8a36fd25fbc1efb2cd9eda09f2
-    fc538b1dfc51553fe9da0421eb0922f8f69a2e93eaefe64e3a7a5406b9f55b0dfba5cac9105de3e6ca11c8b65574fbed0166dc8ded9fd1ff;
-  c441e6cebc634bd7de7de356e855528d52f4affae7cdd585352d94218ca171929b17b8f49ea294f5151a277c116519de5ff92ce4e2f6ce0a
-    809617d4e40d53223f01887bfab5a7d2dc1eb4f680ae59981b33e11fe71345b3155f567cc867cd9e48c8b534870c7df49dff883c0900d8cd
-    44d8fda2a1719ef91d7f6bd2e20bfa5f2f1364f1687c2f1e5160754173b5b645b1760e71670a62945ee2dcb0987196d2fdf8b520ecf6a6d8;
-  a92361d9c458605877a6d9229128b1a52f7bab378d0d389568aae10d09d419b0e6436684b438abcaa3e1710efee5ecec1af06cf0c82b339d
-    74bc6cd43025234b1a6e15fe2d4fab520c874af6f896b82ecb096b0ec3cf73ecf04ef1d13ca612ef0981b8aca0a769ae60202eca36410b0e
-    1de0cdadf57d83a39114ef20bf775cf83b02f62d86a4f0c333b44c1ccca38d9cd7925756f1debdb9ad622abb9e8d569b7b109bbaff6c3eab;
-  f0ed25db758767b83b1d5ab6f8bdbe8e263b18341ea296b2a5d27c0d928004d6c48695ac88af863ed12be6629d8a1b58ca83ddb4ff9c778b
-    44998d5a87e29ace239af04334451efca0d8bb88b441140caab3e79da9c73f1354df0c4e2a8148141bb44c33eb63f1c0025ec2b289390e06
-    3487b335fd6902875fb74afa2c03dd8ac713d4bcd2e3aabe4f8664ab3b4844e91866a2fab230cf52ecdf329688ee0c19cde19f6789d68591;
-  64429139cb6dd44a64984ac73cdf306354a32772da0724c647164d89218906de465c0c47f2841564fc69933d140088a02584bbeb7a138e7a
-    391d7bf04dd8082b6b196651c251737ba319720b66075f2e65a06023e1dc9697ee4c540b6fae20bdc333c9a95e69266b5ebeccf0b2aea18d
-    9e5f0c2a1946dd75cfb1b018ff30a4def7bc997d400f83f4acb6adac03669d7535a9605261333621c09d5ce77269ae0b844288dc2dc22f08;
-  0bb7ca441d108e3d7a4c43025798eb1f1036e2d2200e2457aa93a631c068bf9e99805e8c69344d6f5fc063865f2e94bb954c20645f8b7003
-    3f47bc6701604867acc3cf534d62c9847617954d860c34ac2bcacbfb1c24c99a7442a6170ea6539df0c98afaf6fc8f45dcaa77afebcc8290
-    4afe86ac1e70d6a426101356a4fab4a4864d7720a71a5803d65d722ddd8c88390ec304a477daa00c508aee80562b240172f797134b58f393;
-  93205ac6e814337d0d12f8e55f0b62a32ba948cbc6df03293d51e67a7aa7e1457d201991f3392f1cc4a4a9b6b2ed27407ac4e24a5b0e2664
-    c2d648607a99e6dccb9f9940ffed57de39928d9c3fcbabd79876ecf1a5476ff5a637d0052f04d82a2794bf0e31268fd6ff640b4aa1ac921f
-    55f7a22663ae195ad9b191265ff9b981653bd66706abaf00d6c7d26c20ef503b2458e996223e0747eb3869c5e313b7167a29ee94fcbab883;
-  42bb562d81bac7f606d2157697f29f1799b3e5172f003f44785b80006fb56681b832ff6e7875d6a146b09a9a95f9f3cfb210f5b9aa545e0c
-    e7cc109d2ea008a1c938c66e296911c0d7503b1a961f23edce9532c718e53518729dcc6f7e921f831c56d1d8ee7c5b4919f4030ce6703e68
-    298867caaf5ad097d00adce4c05bb1d770042132c51f623147f1b2c7879a9c992ad0cbdef607f62463066c7384764f19cc04f9c590c59c74;
-  4cfc133cf2b3e22f569340c3a59299087f9caf8b36562d418f2e18494769278c16a22641e4de8f675e9540d6fc0f8c210a64dd63c8d01453
-    f33b0a3beaad1fb12ba48d69ef999bb7a5af3bd2b977aaf518bc65a13caaa9d61cacbb7c5ce6173a282d341cf83c86a458c8d2d10a1c1ac2
-    40381e77dc6102e18137ce2c952c35c0244ceb5df0cdd736a8ea7dea8413d162334ee2bd40c5a7a186c274f2f44c12c6622cb035d3ec2e15;
-  fc64ef657d34477c17b0674b697cc5a4bc8e665ba1dee02e5afd0d2f57e0a64abb2bc428215d9e8ece95c5283e4233d483201c286e4997cb
-    ed4af51625762548e95f32e7042f07bb260f734fb9ba43301daddff9a863990d79791d5db1bbbdbad75c09ce313d93638c219c989702c5ed
-    eaafe47ca2aa6cc400109a326eabcc5fe39dd9aa5a99245f77aaed280144405834a5e185d2185c49a6f2cef66f7fc6371042b8c0054c5cb9;
-  2fa4cdcae0b01f3f3aa28d4ff311054c73683c09749eb312cd4ff7cf018fa647a66b44477459cab757b9149623ecf9064dba16d5601eafb7
-    b378045a6652eea3cc9a8530dea6361daa86866f038e579670f2d50e072417342f1887827335a0a041d1411b24a68d8f190edd8a251ac3c7
-    e31cd22447030ee3063d1380d1b83b691defc278772c0ba93d42cdde09b3bd7bd583cbc9e78e6a58998a56b14792879666c8f35f8638727f;
-  5107c636bcd6bc59ec9c7fcf04efbf90fdde936bff7e221be660d542f74fcccb8b49220b93744203bdb7b026f1bb9fd9a64c0187fd3d99a7
-    ee48bc6d5c231bd7be253ed69171d2525157d0d8fe12fdafa6e7a3285f0d966fd4c570928f61850138489fca5cb540444c24b602d9025899
-    405082a418fad730abc2bda5966092e34e366444fe911fcb8c48796b575d623b600f939d22d6c704f5ff4ff14d71e01df370b789d640f140;
-  475e593758fa8506baa94e1b6070aeaff278d905af67f9e5a5273ae0737825d220c02ae7a89f39998f98895c83e51e7bd0cc0c9126273792
-    3f724d7bbb27bf8b2f4e328bd865e412ed6207802703def28b9b64567b15f7648c1f96ca5092400e32427f9880c95fa0a83f7fbdd6b2d2b7
-    87d0a6b213224592e9f780a638d692c2dfdbe085d66ad7d831c39e36f08d1c37addfc0b1f9317aa7c1da08f503af7e1b790c8c4efdd9094a;
-  fb7923d1a8666b372b41792749ae312903e1b1a8198970a5da6d85dc19a4326bcde206ee841a2bf106c95e99b42fa7eb3fa559b4b88d31c2
-    45e467dafaee144bbd614028c0ea4d3a37b4ef99ded5c9e44b7526916218202401233364bffadac9424143bac99b4c2d89ceea71c3fd0ea4
-    415e8baba3558082e8a2b94f09997f633a95a142f85e3a8a26e3ab6d7dbc528fce053a52441506bb490aa2537ecbf318c97344267c8b4066;
-  2212850af1b191227fc4875e981ee15968832cb6898243af481b62d91ae5cb26fdcd72e45a54cbbbd9efc5e1739f8683d8ab318586b51e7c
-    6b7b3294bfd31a11644924c988b0b19cfc1db66d8e674040ee21537b54aed4e1e217f0b3427d7d4d9dc7d9dcbcda8c2c47c5348b9eaa7ddb
-    8e8db79eb085ac33e30dac2721cf92f664a1e22318ea83ef363db5547093a008e0e562989dd1480977b79fbe307a13b01f71661025609c57;
-}
-
-sub {
-  890e734c6f4af5b1c62cf6fdd0facf76af535bdc9781396c59a6cd8c37cc96aac97fa61bef07c60c69dfb633049014868473d28481385ba1
-    0a06a622804bfe9041259a435be8c40aa56d1be10dd3c4261157c16c0d0d99d11b0f5dce0b164a2e6d4c53813242954830a39f2c894fb315
-    7f08cd29effef62085075cba75120b6c0ae63ffb89ae7445484f0c202abffdd8ad70494de3f17bdefb9263b2d14d7f3d54d03258f8e8a78b;
-  17935b9768cf9ecdc3b3a4c3c87ee20f766bca820f620c1852a48d680f445f1a28ee6a9a18fbdcdb9f35846bc6f0bbb1687b227bcadd4c3a
-    9f913b62023a48e577ac9aaa6d06bb5cf46ea3acc2946a80f66fba02859837491a31b6740a5ed1178c8b6faf4198ac836419deb8aa439c0d
-    78012035669556e84b070a195b7827b381fc26d64ccda1975b34d3658aab27d10dbdb4250e9d0bc413aa14bc84580f2e046244c21f9ab02c;
-  b1689e72355c7305d5cab07e2d672e7b92872c115f03f9b45fe7c9d3354ea0d3702f4f915900085ec44e816dcd731086c999c0e97ce52b40
-    a85e9b5cbe9f628049f91b9adcc1db63f19e8f7c37b92e43015d0f76f188c1cfe89c86910afb82c2c6f1f7197562b919380a1b32b2439006
-    090a031677bc10858bd194e450a55217a1e89c94274aca715e8aba5d44c5de038892c8ff4e05859bfd5c89535811576c918fa5b7caa19b39;
-  8f952f2233cdba45ccaafcb8e6d17b38529a44ff49e8ac8dc6378710d5e5af052c460e2758e3ee28f5866e71737c9b6e7731c03d11d21cd6
-    5bc41fd436b58032dd4f50cd0c57bda1127a3033c2183d8133cb9c40760ea41bb42f48f36b6a2f3bcd0dbc60b5bef5e4b712308ca0f2b443
-    34d10f4efc173a13ef5aacebd97abe963f2014cc87cf6f0c936ceacf5ed70bea7716c633ec78bfed2779b210bebda589bf1e90b170df6792;
-  708939d3a13fe996dd90b1128231b7da3593c12d9ab880a4da9febe7f12bfefe72aab1608145911fdfa1e3f1f59b426a06dee253d4d3eeb6
-    008929e61e53becf9bc6dcbf6414f3a71e9f134fcab293cd42e096fef3d87a472a79ed1ce623708aee31e12f5bef9bc6d0aa470ce2a52f80
-    700010ed82ec2ac741cad4521d1dc43217f4addecf05edd697bf54e9fd5283b74831c4439b212195f06f02c29aaca6a335339b47f22dbf36;
-  a7996b0ae1d8ad5856ae5cf3abc8fc61c4b3579d951b632b9af67dce957365759fb5a6f54965a86b1dcccc9439eebdeb04f616c3fb4db382
-    2df8e6cf52e985d0e20f4f5e9bbaf1b8bd7d7b982da05568b7ea82fd2a5c0302d0ce9feec5e135eca886fd30827905eae204a51e498a173d
-    7aa1843a8eef2788739e0d95100e0ba90636dc04687b0dc3e20bfbd06a176273cfe606078483727f7445cf63b774b80122f171a4b2c39b45;
-  74179531aaf2ee4e7a309350982fc9ce501ad18c650f0adacce5da9b520ce27c04ca69dca0e719713d4d10db532401bee26b7ff9819bf532
-    6a3554898f2951ed005bc4ac74dfd0ef124cffbb52301109d8414719473dc17a602a3b530195c383efa22dd6da87414395886e4b9dd5b5f3
-    09e240a81ac99d6179d5cea32350f8de3dced1d012dff8d0f4a393820acf2002a49f2e899f5256ed4daae204799cbf7a4de310aee4c53f3f;
-  e7c145e38ca66fd86991538ab11231abb60af8b0ab7460e047f7b5b69bbe4a3a56c28c14131c35621f4014d541ffabd642c774bc1a5c66c7
-    9ca047c2251cc6012bd734198e4b2c6ca0d50a85db601659b8380510fc6c1d08a27fa5fb8eb3c9e5622185f83fba6ed128d153cc9563e1d6
-    4a21fe20678aa9d63eba1e7123c7043f1635ed2bd0134a878fbeb0a69e512d32b442e71884686b7cbc1e8fdc01453d051af620f084f884f0;
-  8f01ab3bbedf7ac443423793a422910a54dd73f121ce6f52270d7953386bf2b0eb228b2560b7103aa94f3190e80038505f2b21a9f138c414
-    44a6b845b4b3b6d9c55478664fa2134df50e7ff4c5184aa57bcc8d01da42cdbb78da3898fd92287b604b6a369c06d695241c48605b57808f
-    4a5bf2f5092cc4ea7dedbe2c55807dbd5ecef4fc5bb525adab40eb515d2825f57248528d6224e8be4804c7594cfa61ba3a0fd94896e14385;
-  1b6f84c1ad9ec3d008f345a19305aa35e5b55efeb535024b0fc9aee4be1c031bb070655fc5e672ea75b5db98cff0dcfb5427e21e5ffc4fa9
-    ad5d4e308c69186e87ac97551e9ec34f2d1746d5f6712b126c3415346ac2271450aca96fc6b9e82ef7e2f3fad60df4f184e34dff8fb53b02
-    6e1136912135ab628146ae4b7567e6e5b79e1829bfc3d638a39499b0545adb0660c4bbeffe2c8abb7ed2e79df8e2e809d043941fcf4614a7;
-  25ce194230be078d7f35b85d68706d768fec7994654fcd3f63f3d32eaf59f17bc87a617d41f76b7d0c78b63377a203e43194f0b056d26b0b
-    76266bea72a15cdc355867a490e775c909b7b6cfc833107e7c6b7dbaed2c8491c6d000b2d7d2beb72d72937285aa1bceff18aa35d0c52158
-    aea7ae57bd1cabb049dd50b9d788f7ac8535c3c49c1bbdc1e6875674c02c6dea01aa60cb6924adc5de0523c1f1f7e715327b467b860c4ab3;
-  c010bfa3d130f868f2b975318139c2a847c69014b76164192b437fd7e26b892a5a2425670fe3e8fd9efdfa250f57579d1af2d24f8eb6ce92
-    bfe65616e278b6ce46b295600131bf5ea092451a87f6bc3adf1c86f2fe717351b073062ced1394a14051bb33f3874cca569aae8ba97605f9
-    002a688defb7419aab07e0d07f08034aa7334bfa2f6ba7de4b26f9e4e2f915d9a9b01e3b22cf545c5eac3ff21bcf0ad3c35724c4e43fc999;
-  b2f21992b1f2155b7afc3a1d731b52c03cf14208e634b7da123888d652afcd919e9f5f0bea8b9986c71a7ba08fefe58ee0402d9a23b95f2c
-    ae241fa6292c63f3c09301255a866825b39c9645512ea123486f9a873cacab567cd169c463fb1cf0417633a7055d831d23fd1d58dd42e726
-    04cefaeb87c6b267b96839f81895e99a8954acc2940616b7cac8ed4e1603223b22cef54686907c9685a447f989926271bd430f4246767805;
-  b714b60b2614ab6ce63bf8eae621357f2e921f79de94982fcd5f524015db3faa52b15ff042733958fa202786f61bfed0b9fb5d5873619aec
-    0c99e1da4c747ad1a625321cf9359b1d823544d1eacfddc38e4bfd729ed2f9fb37760242340f7986843fb8fa0435bcb5cffdf11453caebcf
-    ab7bd430d99f309b3f16c6ceedeb9961ac5cdba7f3c4ba6b3e1455cd760846ae1a3b5dae0e64c0d175e16e8bf1e6411beafd6b432097ae1c;
-  c5425daf8f7089def2ff910e256d9496fc109d2698cf15dec1ce3f8116231969c5ed327626362b0658c60e74023a3cae5ef128fb5d27cad7
-    bc4e49fbf095f73894c4d623a210475cb7ba78ebbcbee8ab55a851162f789fb21e72de95afe4ddd45b90289f94f6d02b5f5a4b90c603ea31
-    09f413b49eda91a55e3bbbea825c4d3a4556243bdb102d326c26ee6ae7aa79b6a67b54e076514d31fc35e6d46d436b82ff96dd6a9723e0a5;
-  9aa20b4259efd3a701a63347181fa63f56f42a97ef836bf3aab88d30bbf28a91bbf713a0170024e6057e2281ac113f9b58cb13d63e850ea7
-    09e7104367d8c0441d811ecc619af04def9236752c2d47bc508b0de3c3b29c74533d8eb9fee13279aed8d58247e4010206c697d9b72bab43
-    91bbfafef1161363e424157bb684b5f16661f421c35624375a2d804df73fee1c68ba85e6181ef16c57a54cfe642d3d9952057cfc86596363;
-  e8ead9316aeb8f56d43418cd3bb1a71234c9e20b4a6dc1604ffdfdbcaacebe73b71d18c2c167544304d895d67e2daa2538a4ad0708cd9acf
-    ff3603f0960bb7a92f2b7fbfe242b467164e0ca72e89bcab6c467b5391166d05c601b38de40643f04d5b50ff8ec62b18c69e9df74f01babe
-    e9b3d641d3dfd8aca409990d596ef3aa1d7bd6641be404b5e2b6826919b8516ef11b6534dd601153b67c45d7ef667e0d72051010b8cbe010;
-  f37b41d9950036d560f02b8befd6f5c73096b8995850b9fc563291fba59fd994916744fbd4c1dd5d17a9e5ecd4ec4a658dfdae1ba7024bc6
-    eeda58ba400f16a946381fb11f0ac0db895957236bcc629ce9d1ea425eef8412ea73af488b97f1afa950736f26c3cace887417b699cc3410
-    05a1e81e55f11f2c1ab80cdacfcc35eca63c6176ed8356606d60a6b847b05482a7f394b2492aecad6d58727dae298096048997650d3616b6;
-  2bdb71a053047c4173718ce104e5b8671fbd61c59bfe8b20b890ceda15a69d24eec3775f4ce8a9c16d36e50626bc334e0fc1be492d800c06
-    b1ccd0dac33ac46b2709f9626ed70136f98dfbc705ad93ea8f1b325d644daf2c0180cb83bfdbb7398d3f58c0f6600056a174850b9db91ed4
-    790ea1c58fc9b7d54b68937e960db731262f66fd9551f83528759c7db058eef7ec43acdb8c0cf287e0f68c462f5b33f86d4c393e90c6ed31;
-  8f3fd6346c7f2dacf0d7cdb88a5bca3b222a895a07b169d0bcd0af0a9aa634876ae1a939262dd75bd12b5a97127155a015e00acac7d5cbc8
-    0e9c03c5a06accdddd0d8613e41a00f2b586e297e366987e02e7536e0ca1b4c2c75fed619655acddffe8585c7a828432d90575731a4c8519
-    81a3d26fcb1461ce12ca47a5a640ca496ca3a6c2234ad151bae95b9c8d0580c4a281bcd78fd72a7ed142013b98eed06d3cda9556ad8946af;
-}
-
-condswap {
-  db0be3ccfda1e2f8492bffb5d3344f1856ff1896b6a067d2fa064423ac5b05b669db1c9b51899c44a7f470be4173856d9aa3d1cd10cb8c9b
-    3005560f89232a97cebf6808e7493dd0f17e572556b53723b57faee51d8a0a45c7fb51aeb916f59c74ea6041494483b2fdce72189d1bd031
-    0xffffffff
-    3005560f89232a97cebf6808e7493dd0f17e572556b53723b57faee51d8a0a45c7fb51aeb916f59c74ea6041494483b2fdce72189d1bd031
-    db0be3ccfda1e2f8492bffb5d3344f1856ff1896b6a067d2fa064423ac5b05b669db1c9b51899c44a7f470be4173856d9aa3d1cd10cb8c9b;
-  ea009751f6a7045ec7d6d46b16cbe663f5a78fca3835626c79864bec4030443bb9349654d52b2edab92b8f4aa876a97e868aa6267a54e6b1
-    8c6f864ef7f664f4985ed8c1ea0c63bd7ab355b5321c2712791b610a2dadddc90a65ca8d5c25ff199b011193796b08f96420934615103b7b
-    0x00000000
-    ea009751f6a7045ec7d6d46b16cbe663f5a78fca3835626c79864bec4030443bb9349654d52b2edab92b8f4aa876a97e868aa6267a54e6b1
-    8c6f864ef7f664f4985ed8c1ea0c63bd7ab355b5321c2712791b610a2dadddc90a65ca8d5c25ff199b011193796b08f96420934615103b7b;
-  dc3aa7d363058993cbdc54e95f3c972a2cea17cdf9370fccdfedfa1ba939ca35f762c5c6283f84348282fd56d83539804427eabe3bd6170d
-    8c47a0990eccf7300986232dbc8ee26e8996c3bb4b73663ec5525312bea8975221c9f49039840c181d042654a8c1806bb86702ac7d0b80f4
-    0x00000000
-    dc3aa7d363058993cbdc54e95f3c972a2cea17cdf9370fccdfedfa1ba939ca35f762c5c6283f84348282fd56d83539804427eabe3bd6170d
-    8c47a0990eccf7300986232dbc8ee26e8996c3bb4b73663ec5525312bea8975221c9f49039840c181d042654a8c1806bb86702ac7d0b80f4;
-  69b45538513af2148e0a2903539bc5e20fca4da447278bf5967091d2e781121080c14a41989f9ee5218c444d3a42989ba890c7be7faae5d3
-    935eadbde0c571c29deb4d8404dd39a8cca177ced36c359abfa7a6cafe6075422e1d79cba8d81cdbdfa4a5144faf37b19ca22b2b40fe1a0b
-    0x00000000
-    69b45538513af2148e0a2903539bc5e20fca4da447278bf5967091d2e781121080c14a41989f9ee5218c444d3a42989ba890c7be7faae5d3
-    935eadbde0c571c29deb4d8404dd39a8cca177ced36c359abfa7a6cafe6075422e1d79cba8d81cdbdfa4a5144faf37b19ca22b2b40fe1a0b;
-  de30072f175127ad4200a08099f4d0df0edfa40eb02e21a03c5628dcb2f70da8bce9ebbb1ebed2aca391e73a4114c06bcdbf762bf28777cf
-    5eaf3aecf1f7d1fd3b43be8fa450163c79f162b0c6eaa4b1ad39baaf3a4c36564e001c935fdce38e90789151beff0f3cc4fdfc2d86dcb587
-    0x00000000
-    de30072f175127ad4200a08099f4d0df0edfa40eb02e21a03c5628dcb2f70da8bce9ebbb1ebed2aca391e73a4114c06bcdbf762bf28777cf
-    5eaf3aecf1f7d1fd3b43be8fa450163c79f162b0c6eaa4b1ad39baaf3a4c36564e001c935fdce38e90789151beff0f3cc4fdfc2d86dcb587;
-  1bb20a5a05b190737ad6b2bc5bc2b9259fa7e36eac8f3032a7c56ed59c1510baaea32bba898b329b0c64fadbe454095b9f82b366bfae3d8b
-    cf0a87c8befed020caf82f37b4c5f17d2aa9ff8ab75baa156cfe2716ac1eaabf9bc760c2ddcd66a9d02a8384ad1db9e8f857b151d126e0ef
-    0x00000000
-    1bb20a5a05b190737ad6b2bc5bc2b9259fa7e36eac8f3032a7c56ed59c1510baaea32bba898b329b0c64fadbe454095b9f82b366bfae3d8b
-    cf0a87c8befed020caf82f37b4c5f17d2aa9ff8ab75baa156cfe2716ac1eaabf9bc760c2ddcd66a9d02a8384ad1db9e8f857b151d126e0ef;
-  c186531a219344dc485cd5dad6500616ac8e0653693168573cb9be590b02dfb1ddc5d87d27f2d9fa46ffeda955a6285b7ef2b9bf84825d06
-    91f3be7eb2e0be38d92974d81be5126ef40d358f242d23aa4863fb16ba3e8844e02edc87c0206e211587886ed532da0ab148cfcf64e9b58d
-    0x00000000
-    c186531a219344dc485cd5dad6500616ac8e0653693168573cb9be590b02dfb1ddc5d87d27f2d9fa46ffeda955a6285b7ef2b9bf84825d06
-    91f3be7eb2e0be38d92974d81be5126ef40d358f242d23aa4863fb16ba3e8844e02edc87c0206e211587886ed532da0ab148cfcf64e9b58d;
-  9f2476d6db424d19ee0cba4ed091da5b44ca63caf2f711eaeb7edcc75f49e0d0c367c1f2817b6bb39460f897432901064cabed7f6a03b1f0
-    66e7dcd34d76a19e3285685112b7619f9a3557764a918922faf1370bb97c2b2fa845dd34662cfe7299ab702c68fd43b5f6f15a0af6625f2e
-    0xffffffff
-    66e7dcd34d76a19e3285685112b7619f9a3557764a918922faf1370bb97c2b2fa845dd34662cfe7299ab702c68fd43b5f6f15a0af6625f2e
-    9f2476d6db424d19ee0cba4ed091da5b44ca63caf2f711eaeb7edcc75f49e0d0c367c1f2817b6bb39460f897432901064cabed7f6a03b1f0;
-  f124ac31d304a29cdd94bdc0611c61064a7c5f09cf6847bccd52fc7a7b77ede73b42b1ef75f000de4361028e0fb63896f4ef5ad3bc1b9c90
-    6629084a230c793086e469b9a01e052ad7a5680d6955667e0dfb19a250f447d9e238695400dc4ecaeefcebed44d374e57ec4e414f5629e63
-    0x00000000
-    f124ac31d304a29cdd94bdc0611c61064a7c5f09cf6847bccd52fc7a7b77ede73b42b1ef75f000de4361028e0fb63896f4ef5ad3bc1b9c90
-    6629084a230c793086e469b9a01e052ad7a5680d6955667e0dfb19a250f447d9e238695400dc4ecaeefcebed44d374e57ec4e414f5629e63;
-  b64f2952510827bef3d32ef6347251274c7241d9913268a7a6a5c360a4b29e7ed04d09a9ee5aa83235eaf8c0582b076b21d78b7062952773
-    77897028a9a81fd54362a6085aa2c2fd6fdd44589f447c7310b9b3b5a29b54ed15c57e2c9fbff16f20129a4dbd43640a0d1037e277ca5c93
-    0xffffffff
-    77897028a9a81fd54362a6085aa2c2fd6fdd44589f447c7310b9b3b5a29b54ed15c57e2c9fbff16f20129a4dbd43640a0d1037e277ca5c93
-    b64f2952510827bef3d32ef6347251274c7241d9913268a7a6a5c360a4b29e7ed04d09a9ee5aa83235eaf8c0582b076b21d78b7062952773;
-  4d75efd204a66aed323456e6f55cb891ee7a31d739ae89726e0ea84532f9c740d1b647b117094fb85da2c62da04f3b9cb13db6b840046b7c
-    0afd07bb073a150e7b82711e1f42f7b0789af8192ea6b4e1b24a3d48de7f8b802875aca5a02a9d24deca0b58c895992a449d01026495b96c
-    0x00000000
-    4d75efd204a66aed323456e6f55cb891ee7a31d739ae89726e0ea84532f9c740d1b647b117094fb85da2c62da04f3b9cb13db6b840046b7c
-    0afd07bb073a150e7b82711e1f42f7b0789af8192ea6b4e1b24a3d48de7f8b802875aca5a02a9d24deca0b58c895992a449d01026495b96c;
-  1ff4eb5f0280744f0c909cede8be29cccb8ae43e4626018a9a1d352a97d987678863ba34bdeb183bb5e9347e96760665f5881570778a2e19
-    49cd390a9edc7fad6c84c2e44ce09e490161094d2dc6cad30759fbef10aa30e5aa6474bc46571188418f3e4a2b19ecfc379a1f94e3a44e48
-    0x00000000
-    1ff4eb5f0280744f0c909cede8be29cccb8ae43e4626018a9a1d352a97d987678863ba34bdeb183bb5e9347e96760665f5881570778a2e19
-    49cd390a9edc7fad6c84c2e44ce09e490161094d2dc6cad30759fbef10aa30e5aa6474bc46571188418f3e4a2b19ecfc379a1f94e3a44e48;
-  e96c0316baf01c25ef8a41c02e99aa84c82f8eecd3249be268834afb5f7e95f0ad10bfad4160bb335c30ffd6a1090c91c57eb6ac7a7a5e66
-    115e6f115bc4e19af60710f3dd821fb58cb680a32d6973eae9ea3e48f1928dc1d9f684a8c8de80affc59bc0fb342bb040f89d2d46b8ff8fc
-    0x00000000
-    e96c0316baf01c25ef8a41c02e99aa84c82f8eecd3249be268834afb5f7e95f0ad10bfad4160bb335c30ffd6a1090c91c57eb6ac7a7a5e66
-    115e6f115bc4e19af60710f3dd821fb58cb680a32d6973eae9ea3e48f1928dc1d9f684a8c8de80affc59bc0fb342bb040f89d2d46b8ff8fc;
-  71bd8f5036da4c33f6940348ea448c2f9bccb152dab40b410bd695923a9e255b33aaf361055be4bb9a570e201dce784cc1ccb0f89faca85f
-    971b2f6569ddd9099a87ec4086d8218abcfbe81579f25f03634e471170a5088f48a6cfd09ed9e389ca37b780165c00b206304229135b6044
-    0xffffffff
-    971b2f6569ddd9099a87ec4086d8218abcfbe81579f25f03634e471170a5088f48a6cfd09ed9e389ca37b780165c00b206304229135b6044
-    71bd8f5036da4c33f6940348ea448c2f9bccb152dab40b410bd695923a9e255b33aaf361055be4bb9a570e201dce784cc1ccb0f89faca85f;
-  0f1165e19968f3e6159e9f7f843c1b849e5c3917af4e2798869112c6efca9993ed339c8495eec8c54b286820bf7befdc8ae344e4d309c077
-    7ce5a2ae66b9bddd30c98d9aa9fcdd6ef90d244d10115d15cf5d81e9e389f6852b153a42c642447043fcfd278166b92c624508973449b0e8
-    0xffffffff
-    7ce5a2ae66b9bddd30c98d9aa9fcdd6ef90d244d10115d15cf5d81e9e389f6852b153a42c642447043fcfd278166b92c624508973449b0e8
-    0f1165e19968f3e6159e9f7f843c1b849e5c3917af4e2798869112c6efca9993ed339c8495eec8c54b286820bf7befdc8ae344e4d309c077;
-  6dd07b4891d8f45ad1ee64da38383ec50d6f29634767607eca19a547cadc3c157ebe7d86a28d4d2fa2d40f2c5402d8b338cfd8d30aeadb6a
-    63da9a5a0cd51e58168ddb305c0e70a2f898279dae6394e1b3e1ef3a0763847d5d2f15be493114360204d037d7d3c3a9e746d27dcb544ded
-    0xffffffff
-    63da9a5a0cd51e58168ddb305c0e70a2f898279dae6394e1b3e1ef3a0763847d5d2f15be493114360204d037d7d3c3a9e746d27dcb544ded
-    6dd07b4891d8f45ad1ee64da38383ec50d6f29634767607eca19a547cadc3c157ebe7d86a28d4d2fa2d40f2c5402d8b338cfd8d30aeadb6a;
-  d91228b648f75350d775432af35be9aa283e9729fcd3b689f0c7ee02ea67efd33493980ae5eec92ad6ab42ccd253a7aab5a62c26be275278
-    07c5d1b4f9b8db88cd4187b1ae5e175bf703af12b26d066c1d55dd367569d3e23e3d0470f3c47e6761746ce7de39cf563500d026a6791980
-    0xffffffff
-    07c5d1b4f9b8db88cd4187b1ae5e175bf703af12b26d066c1d55dd367569d3e23e3d0470f3c47e6761746ce7de39cf563500d026a6791980
-    d91228b648f75350d775432af35be9aa283e9729fcd3b689f0c7ee02ea67efd33493980ae5eec92ad6ab42ccd253a7aab5a62c26be275278;
-  f9e764e20657319802b53ee29df43b0d83d994d9049b9820fc0c31b631265c49f6613923a042eadce5902fb81753784ff5a9c0de2c4f6b12
-    6ab2f8279e82aa65e8326e5c60bfa067e4967b3ea67d0369853282e5429736529a43eeee3fdf24ebbe5ca85b59647994fc99c90da83c6229
-    0xffffffff
-    6ab2f8279e82aa65e8326e5c60bfa067e4967b3ea67d0369853282e5429736529a43eeee3fdf24ebbe5ca85b59647994fc99c90da83c6229
-    f9e764e20657319802b53ee29df43b0d83d994d9049b9820fc0c31b631265c49f6613923a042eadce5902fb81753784ff5a9c0de2c4f6b12;
-  772289865ac905fac203e4654b258890ddb91cac71c6d2af3826e3acfebfa222c937b40069ce3a757e2ffd960b5821ed1ad54e4ad2e3c6fd
-    58dbf838ab81a754533c7f80fea48cbc981f724e4c150ddbb0afb5c711a8e21079446f77c427f7eb1892c096fa3eae5e2b070413611cd184
-    0xffffffff
-    58dbf838ab81a754533c7f80fea48cbc981f724e4c150ddbb0afb5c711a8e21079446f77c427f7eb1892c096fa3eae5e2b070413611cd184
-    772289865ac905fac203e4654b258890ddb91cac71c6d2af3826e3acfebfa222c937b40069ce3a757e2ffd960b5821ed1ad54e4ad2e3c6fd;
-  0bd6656d68c41bfc5389db274367f69191754919435ba58d2256017b5bc595d102c6f4f745b3ceb0c32bd0a6cdadded3a3dc925ef2b5c73c
-    1d903009c74d3d135a192bd42466cd28303f482626a7d10832f1f6eae72c3b051b0373e62300a71226011475034f0bfc6c9a65601bb83993
-    0xffffffff
-    1d903009c74d3d135a192bd42466cd28303f482626a7d10832f1f6eae72c3b051b0373e62300a71226011475034f0bfc6c9a65601bb83993
-    0bd6656d68c41bfc5389db274367f69191754919435ba58d2256017b5bc595d102c6f4f745b3ceb0c32bd0a6cdadded3a3dc925ef2b5c73c;
-}
-
-mulconst {
-  cb908747a1af81f52715ef8440aed06aaacbcd7903c99cdecef5ec54e7845bedaad6475028b0cbdb0d53b6eeb71843f900fefd398a083d5a -417895
-    e95e64fd1b2e2e79d1bfef5c96942eaf7ca5d40b1af774ed9c4ea2351c8ae81013f896bafd1f0b0e3a3c2ca3347c6cf88f988877af5e009b;
-  46b23d83c0848e79af947191cb76b087483beec6224af749e59c0c5ae27ff8abada31da895f8132aae0457f5ddc30d18a8d52046fbe6ef55 384370
-    31c9bf2f3bdfd3c1dc115db96d7a1c15e2a9ae67dfebccddc9408a0dcd147d9aa62ce4a55a2d6ad54542317756a08d6be3b959bf132624e2;
-  53e19751de62909506bebf74411d359014ec4b6afbb8ce14eeed8a3938013f0fee6897e3cc3adcbc90d7df321c4caa1941d0e5909551335d -49682
-    82fb902a8992ec1032a6837cec56189c45d1c1fdc47748e17dd9ecabc807a52eb537d6411f99f4d3b328e7ca76475924f90506a8adeb908e;
-  7ff3b9b3d8ee248a48d0c8d308d8c3658374acc92303143061a46656ae2b35094ed7b5b27d23366c0e42ee0a9471a4355d81cda0e4390348 131908
-    adbb3dd21e634dfe2c41593c65249f03a048338037d4a107892df36f10e3ff68402d6f48e74bc7a7858f2c3650fd2a10acdfd4213850529e;
-  f532f4f5ab5447b083ee4225246aaa4448696e4fc8bcf5b0ec1b52df88354e5327d7a3cf6e15db9945205968c275755ea3906a27437d29ed 383911
-    1f42b3585a2553ab19b14639c3e3aca636d88053c70fb758962713783bcd824b729fb4d01dd56a344d991bf2d32a2967acf470b39bee88a6;
-  ef0e2a829097e50575eae6b1ad3fa10b8e417b0363654e0cb07a563a905c02e367c6f1ad7be1469b9f5295e3db0726853adffb820715f7d1 -226220
-    a7c5387af1b9f61f09d628feac1a050173021386775c9f534557b8841b812155325e3632eee7a2302ef8af0b4746575d6c2bcf3b29f674b0;
-  3b4655b1c22542ca413f76bc24751a01cdab6b385b50301d67fd62ba31ad132150e38e12a849405112c4742e93b92849bd8b872c29edb2f9 -89924
-    b51c0dfa2407a89435fedbcfd7835b6e0849d8626995fd00974f44c49d794d3c5dc16028e9fdee45bbcd269035e8bdba695a6653028d4d59;
-  48bdc2073bff25ae9bf7fcc368d65602a71e48c343bc7181c361331f108867d56c588f698aa5b91222f5dbbc859bce656f2607b053222fc7 66432
-    e845dfe65d563884074ffeecaa325706df4a129b73b056cab6ad999588216d72525222ce00ce4d2ffb09fcf6f010a6eeb2eb753fefd44b47;
-  98a26f23f83673a480076b2fc7ccfef07fbbe70c4160d5af638c345f7d17b00931efff543fd47b7b8b362a70657a458566ada4aefd1c5eaf 492192
-    0ef483482255b5ca0f8338317f6eaf9c4fbf8bde8b8b04e26d2cdc0632186f1e62a9c3a1be23e8dc444ce50783135aeca614c884bdb77a30;
-  6ebf7c4e06837120cc852a077945656046e64c2d88ce440bdfc8d38736a4d510a722bc8b0d225f11df0e704e4b04c48bf481da68fd1e150e -7098
-    8d4e2cd12323b5744442fe4e4fc21748b344d7f94794398ec187f0f986ee743cd733a7a16bd4495818ab033103f020c794c988c5d2c1628a;
-  94e49f2bb473a7273abed94363c4dc3d13db159e3c3698a62ce5f321252aa03c7f63dd6eff9529c985f43abc7283d11140cb44ff6fd0f3d3 -392951
-    58a606cdc1bf1d5646fc08c7a6b3336fbe532c823c70242ea7536cc6dcdde7c4f492306e39ac0fb88367e41d63a8305d69fab57a52c8c284;
-  cd262298ce3b73294bfb523c30206fc3771144890a0ebcef19e02e5085973a6aeefabdf8cb7186d57be38ee84b114b9a7a22556c0cf88df1 -237681
-    7553420c53b255fb909d6e9008f043e7af25a2a9c29b177b830ff1ae6f6fdcb6aefb8386465f24634fb04c6078322ac691586f91cf7928bd;
-  cc9bd2e72ce15dd50877f95812b65c65cf09b14e2817784a5b296c123e498c532362180a932a455b2ddb75e26335dbcb21eb94a90ebb6940 246794
-    8838e720b6e497d9cde9fbddc2333c13cb5bdbbbe5afe41ffd61f5035c8c4987fddb8036c25b0505765bf1a5aa369c6bf7723c65278584a8;
-  d8ab6b8f3523e98f49140e051c0b744bb0068d20f499c0763aa28ec1d1dd7e86356f357149c317376be96cd520b3ae04a2c4d468d74745e8 -360296
-    4c0bc5f6fc52c6302b74c790d57ccc8fae59f2aeebb59c3393c56e70060f4d170ea41354f5040804a6e8dcb4a7c585ee71a6d90454e701de;
-  6036fbfb9fcc223a1776ec67c9424788aabe553a7d6a0472159edc747ebaf97e99f7263ece635ef0b702a3610aef32e17f59fae503e18d74 -5433
-    f6fa9a49b55077330fcda976a19ba7cfd98e44fa54044840df0ae9e19710193e684703f7fadbcbbc534e7be3adec0cae0d95ea414494f368;
-  a3433dfc89ec4d6d858bb5b018e2d474b7de7604ed4491957fe16453d3793740ef88136814f59b19ed3610252e74cbc3a36571d02e57913b 237641
-    7a01a802b7a5aca44675887d9cf94d04d4893e2dc5d7474090cb32798fa370690255f57d18dce2a57126bb5883672b5a74a1c780f48f7bd8;
-  c17ecc6099e9630a4ec20f4199abe1c10d414f6d734014ada1e6f097090a2bb4e638fb52d9bf56080d77c2b535f52cb091cbaad3c65072e8 517226
-    708adeac4ff99cac4c3eb649d55276f58a7d21a0507af176a53893c567050d352af501a9c242baf53121e8b56f5679b175dc01538350b644;
-  134263fd765e5f1da64900df5643c5241d4fa8a9e96ee59f01667b64f9122e85e995b90d4bf5d5fe9f68825dfa6edd19d8ce009270ae2984 390674
-    2ffbda7ccbeecd8dc4600965679146753c496d35bfa546e13edbbaa259065b024c8aaa3a17a3384f4f14d5ee01371ac55fb50a153b4ac1c0;
-  54326fffef9f0fe1207a07c8ac063d64b3fe81528e005f857319a74da2c3423a552b05f8c465908b028a2dcf15cb7158c99a1d2bdfd890da -255467
-    e554e875e480c68c4fd780425ff8fb50f18bbafd0536a09489bc7cf197fdcb80dd4c7e31447a1a862066b6761ea39ea3b8c3002039c86b40;
-  5c30f73ec3addb2d27e0e79579063f2d30fa9fb47c2b6a3a32553120a047cad83abc901e5a5b4a65f8e51144f7eb0abec9a4d105236b2618 -466309
-    5ec894f6abe2d88971da11b982c3322d1f533a326057816f6273585bfa186a7f569ddf93c27e8e74719ddb515689d5935c56e6b86936f22b;
-}
-
-mul {
-  ## Easy tests.
-  03 02 06;
-  f7ffffdfffffff00000050000000000000a0ffffff03000090fffffffbffffafffffff00000020000000fdffff9ffffffff9ffff7fffffff
-    ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff
-    bfffff6f02000083ffff5f010000a1ffff9ffcffffc0ffff6ffdffffc4ffffff02000082ffff8f03000089ffff6ffaffff7cffffff000000;
-  f8ff7ffeff5f00001000000800000300000100a0ffffafffff130000fbffff0100000000e0ffffebffffffff7ffffffffeff1f0000080000
-    f7ff7f0200e0ffffefffff070000faff7ffefffffefffffffff7ffff040080ffff1fffff8ffffff7ffff0500800200000000f0fffffbffff
-    0a0100240020f5ff7ffdff4fffff4100003a00201400400300a8feff030180e6fffff9ff8f02003001002c0000f0ff9f0600d0f8ff670200;
-
-  ## Random tests.
-  94aa99eaba90c5eb2efd7101c8efeffc1e44c8fcd84ccb8ef27b9792ae12534c0a250e5400407177bd655e51c343f776a3fd26474da4dc74
-    284a0f7df2d7d7c760cc57b1606625884c1643020230a9eecca7de6098f5338ddf9297daecae8a07e199494cb6db91c2c683566bf79545d2
-    213a31ed7e494f470736ded872f2c4f3675562a7b42bf01ea246be0ecaae2a61ae500690df9f99ea9fa8e5e1b9ccf3614bc34148b7693c91;
-  a434abefb0de3c7f5e33f9230ead871bb3f06888c0d568b9a74fa32b676dc600fed2d54a042e1b97340852c4d6ef796a18561884d760d4ad
-    99d4c85f047d3dd8e530c50ae7d80815a30ec6ba820316f5da922cfa7a51ab45290ac2ab8a53082716a6d7f77ac5a285fac298eca4fd9c52
-    97b2991fcc858d5667d3674484db9435ba71ab0c836c534efb823c123f9e94d0d3445257c55c73e8bd62f1d7acf1d75fea5eea669bfb9912;
-  fe9911abbe57f1ddd61acd062d59637b129a1571af65fb70169db0d8b12b498a66d1eefcf9c8cbea01179f113afef0ae192550828885689c
-    e371e9a11f662e38caff28cf4cf5ca8cdfe4a8b99fa12a33765a22ae25506874fdcd85388ed406a955d293320e01957f119027ec4803c2a9
-    171b49441f9891d927d2f6436eee1dc59e7872730be496638017b42151cdf00e9abb212bafc47c05a4e185bf7cf21ccd97b0c8ea426e4381;
-  1c300df44d28406d070b10c1920e01ea8b9056d9e1d6f9704dbda3f6328c26a28e9e4aa07dc79e03c09c5639cf8b8c783c8b430b9d8c21a8
-    c565b0357a1e8aff3b3a6164ff34c9598a1c15a1551224fb38d25dfa3b0627c9d992dbd215910236aeeed23f4efd99640054b6648946346c
-    f7871e06efb6f737cb4e04f708827092e94e3c70faee57f70096b9d674d0ac5b228824924bb705de49de9f9c0e834462093a9a5551fc7d5d;
-  9014dd22854f1f21fa1475d74eba669101c871c2a21ffd5d10f0792e3cc5d34f15b4735759575dda169e2dd868a5ae64dbeaa2a654cfde5c
-    c6f59ecf6add5ff92813cd6f37de9c6f8d3ae9cd33e4f3236ff43127f463f297c3067493868adf7823bc285a3d609a57d9b0b841a9b628a1
-    cbebe67e30ed82acb0de699a5d874121257b78c2b0642583713b58fdcd089a6277a5c5e571538e4af9025dfc63cd78931be51780055dfb2f;
-  c8fc23a431d744e45e8bcd2dd2ca612db40b26287970aa878a5cf6283c51b2bd4edb76f705f29bc3911a9aee8fb7272009520f3590ac4c4a
-    c1015900ea58d6305b8b558c992bff50a8614843cd3d11274830dff6e1db405f8b268100fbc5e44c477cc2a9e83f825c7840e560fc2b2920
-    6ecf49d92efb60a15a9de38ff37d3b23b339d889ad8b11cb332df260b9c49fd28b287a559fa5a5edf732b3bd1014711fb7d088a37cf6ef72;
-  daaea5c9549776d866be36a032027a65eb8325b1684d3c37cba068e69aad7d4f104ff47c14f669883cdef5dae9a0c7840379631ef97e6bc3
-    f8dc00891a9c55481a224309a8024ea257850b2bc62ab10bb5ea5b836776cd46994900d6656b7f7e0d9092fd824b16d20ea14528a0de7729
-    83d3eb62429c2ece396cd7069dfa2985630da2fb0949b52f1df9231c82f32022543d4a2302241d0146b4db97f44ec5342b6444f463ad056f;
-  786f4ebb20161c96f93ffe3ee2b0cae50fc454d910b3fae4fbd8454b8ab7975c6cab8f6a1b593996b24b22603137a52ee732f9d19f9a6e43
-    d78d3df4f455c8f5d98baaa17200d4c94056e21768c4ca783188bf15c28dc86c581fd9c150f923f905becba19361ca94f7434d8a74744669
-    e857a2020e1877b50151772bcf06763285c1d8b2b5ffdb63e13ef4985ccc3b965fdb053305f16feea4a3ac0edad21423c80ef847181bdff7;
-  6b48bf18ec4557e745cad3e106511bd5a9bbe136c77cf639745f891f54bb16c11e19770eb5112df8bb6755b97cb1e23c9c7efe589693764e
-    95c2a38f889c451f792c3d5d8b3237eed3f99e2b4857bfc48f75d7c0de3f293d2cfa7f97d65d75e0e3df633d84931973ac542ce07ba974b1
-    2fdfb1146b569ac98b0811e600e2d8e578023024ed704f97c7f7d56a2b4a33ac6ec68d14f0789441a904d175fbf8b91603c532ecdffd27e4;
-  1fbba059c333843e3cf0cff19bec99bd0cfc89c3b390200165680b742fe540b32042959022e7393c9e13ef7fa3f1dd5ac46595803210c536
-    c723bb3649b1d95647636abffd325e363931782f02002ad6d75d2082c980a7a2c5e1d51045880b36d4f62c16250faffcb2acb824d8d3d5d4
-    97041eef8892ecaaa97c4effb8c69160b3878fd302bc5f0862bfe4894bf23193738d8dd95c9eee9539e23fff67243372b97f02c3a3934555;
-  26f5bc0c2c49899690fa423478ab1cf7000be27609bf683896a6ce3f619510b061ca04debb6c64540e724d113cd4b8ff3485337851367700
-    b8540188b9ca77a82899c7fd26412dcbd6a3c9b45be595f63bce7426d7c16eb20c3a2dc86afe9064edc19840f75f05de828c276e98451ee5
-    d973580e88abb6c83defc009607082ffbdcae6ce9d577218580459711682f8708a15de9c62e3ca3b50e91a7bf5781deee152ac801a64fe81;
-  6c044d6556abb8efdf5b180695293464a8bc4b9cab201822053c7295973ea0a8866425629cfff1d372a48f51dbc6a7f828691194c32c2c5c
-    da28b84dfd48f206972fe282449991597bc7f0734916b6f7a253897fca2ccd6b80aa477cfd08549b6d25bd18932128e59889e2dcfaf76157
-    a599fabf997468487b9376500b58a51e0e00c86d9eac6f50157aa1017d99ac8b95e7842b36071a192784ef72433c06a1dd042990b71ffe8f;
-  50378c6ac56816962d428ea523a0cf87121fb3c53b37bac6d3a05fcbdfb8a5fb20aa014f1e1b01a3963534d403baeb7c436f72cf3cc5db58
-    78901fa015c6f0d3e1072aa87d865579fa405615691a3f27945f9b1431ee8bce8ac9965a1f9b0f42ff10bc77c43cc93566eee9a9b79866ed
-    00127644003ed4b518f04abbd058a46015fb328883b92070bc5cf0fd98d7307dfabbc65f3e8551c622792efabe55f03953e498e360410790;
-  5db2f6db35af2e1c84ab6832b967bf987cd03adea7113fb8806ce8fb3ffa426dc10997e13afcd39cf5cd65f65f8a09e650fad8e5f6ef2648
-    b063695bc97a18d6ccb0785ee4588951dcbee420ce8e37b25cce325352968015c94f9bb784f3a2bfa34c6a1edf710b63f139fff6d4f7b2f3
-    999284a309482f67ab6460e73ad1ad267052b59fe50cd58a245e22079e2b50b119e312ff60a65037cf9faeaa259d22f689eaedd7924f1093;
-  d5baefaae7fc9000e0d55f287f740dfb1899ba6e9e36338959a16ac5e5f45442a37086b5519a0b439f38b129328aebf468dec4b59c89a249
-    4febc8666dcf2b150faec9902a5f57e97275e7b122724c2b77d9b78655b455d424db93f859b8de6b09c4bad6d5ba68349c65c41caca67f8b
-    19e6ed86dc819e6b4368d196679328710f63bf1fcba6652265508b509ecd0e3e8b8bf17f8f1eeb361af107ef684a729a3635cb55de3f8605;
-  9974be322a0f471cfe0855456104219d8037ca1cb5aacb9ff5da86a047ce159430cfd92f67e764244996668ac44d8d9787dc1b5754d215c1
-    78c00f878fb41fdb0cd22c026881d5022fc470755e6261945b9bfcc3868f591f08288e4d64a65c9f3d0b05d3ab7f27d801aef29e5e98caf8
-    fd51b84f21b06377054dc879b8a176a7799951d5669486b210e4528b9f52bd60f88c2a068f722d85fa12761a4caf2f05bcdeecb7ed62646e;
-  f4048d4a1602eeec43cdf20c3ac9f7b359935bae3648070276faf07a5c58fdf79771ba6c077ddeae47617971e2145f4960587637e7028822
-    32635c7425108f5d19e35e4d91a4bdf3310bc884c9061d0697556ae25e17cd611e090c1179ca9a68225b283c8ab98a7b1e97508592c60c66
-    8d6a91d016aaa7a0da03b06f5876ce8e8a71d1e5e5eb430d6c5ae16e1d6d9b61e77179b4f6fe43ce37cae27689983d41923f3b30e9d9f930;
-  9023c019bf7ef6df45e0e44111903c622220bd3dde046679540302451d001e47a153b0ac7dcfb9831e2d262d8e27002197d9640900e4c1cc
-    1f5e2ca612ec6f14df4b528cc35001e763b9414a81381a1a3c7008c0cc525bdb00aea94ce2348f380dda43b5edf4fec7c8cf5ea2f5fec4b8
-    bf2c241efc180988232b83cda91e12dd0aec0d22ab68353c9841c4ea0547fd1b377fbca125f8cf92c426f8eb859f85a3853516ec104d9b6e;
-  bbdecfafa9284e3067081b7d1bd7ce0e488829859628a8f6a38bc1a3ca6ec3130dbc1345b69abb7224b047fd3f2dadcf9cc11a8ec46a6436
-    49a956ee69cdfecf29440d60fde9db1edd94619af97f625d45dc83c64994fe6c1ac858150cb526ca3c58a9fdc09d409ee3ed0b0cbcdb711c
-    7abfd47fdfcceb278c917afd059e335110bec63fea48dedf7f8275da8922201ea06be39e3d1bccea2d38f5eb7d7aa5ef4e6fe6792a9f0ce0;
-  a9483d4f0c94eac273adc392c3f425be610206683cbb6806dca47be3b54ad142fa2c54a7a473675556bcc8cfd50649af3c58d7a91e84b428
-    b986365aa08f088fe04aaaf2e00468af3fb41cda961b56ece5bedfd83cf9a0fb959ae70c23d9b27cd1eaf8b611d9e578aa0b9d899b81d5f1
-    4af529627637ad3f3f1269319f4fd426d31e276287ee525d0c64974e55fca1cd58694eadf47e44dc3e843e01c36b22f9717067a907840ca1;
-}
-
-sqr {
-  ## Easy tests.
-  03 09;
-  f7ffffdfffffff00000050000000000000a0ffffff03000090fffffffbffffafffffff00000020000000fdffff9ffffffff9ffff7fffffff
-    8c000040010000f3ffffff040000f4000040120000ff0000800a000099000060060000030000000a0000e7010000180000290200800b0000;
-
-  ## Random tests.
-  776cf7ee39df23538f76e6be87ecbb1ed78477b858e3520f24b2b36f09a7dd61daf7bd5990af13c11b1419d8215eb69c30efc3917097797b
-    870001f8ff173e02ce682526a513ff99c6e9688cbec13839ecbf0fbc11d8f84f6cf53041b5bdcbc624f9787db9babe61cd477cb9395590d1;
-  1e5ef8dd68207b3c3d3c670acee7ecb277ee6bc10be9fa3f3d800e1414bf402298ca443de6fd57ca899188c884a93d4b9c9d1b00a7c9ce44
-    4a6d6da8002b6a0f3f5c3a9631254ccc62cf66c93279c4b77dda55d32514c8b388b543002f8055321c7195ce1fd26f51f48732e664cdc62f;
-  e02eba6cd5ec1cc39ab92db439896520e50a5f9e9ed6d31ad37d00ebb2a54cb68f1c0ae537006ec2ffb14aaad2de16ff06194929b702b95a
-    95632fd74045a49782f6f9d0c86d554cf6efd07f9eef57d669828c77537d4c3a69138d755855640064f5e9bc8fbe0eca96fb04053f565431;
-  bad2a1348fc0b54791f9f2875009c8be2d30f14526fbbc22c439c1ae2b865436cd74f428766e4e676b795fe9333312f6334d4e4ec2378e26
-    d87a8f7ca45620b4646fad2c22792538bd16f37879dbc4d87c21cafa60c282f6415fde2fb6293a8b8a6e5b3901f88d75f9243023b68f41d3;
-  d6d221f2bf71eba62e49db570e13ca69f4a8a33543298619cda7c8d2524c9446b11ae7b7d301579f047565b7044b5286c2478896800ad992
-    fdb163312b884bc6d74c4c269011311388ead9c069884f48487f9ac0d62b39aa175e81976fb599716aaa68db4c02985a6f0ffe522b0fb21b;
-  20cc05120202e684981bce1db74af493d218ed8e0f5e76fad46bfeb98c69e504113b0eb91771c602cb422ae09846fbfef7c47afd09689277
-    b07d84ff34dc5f0cbcc60037400ee04ba09f34d1d7a0c6a80672a3f6c1da630681d4207ce1325d301b36f0acaafd7579a108646f5a26b755;
-  72c4c3e4fcfd36389f558e0d4016f3f088145be47b2de85ee7ab963fcd8c7adf449d5b7c37ad8a32cf97ea9bde5c220fc896cf1b91633e19
-    1e8f68736c3b259b661c0c1ec065a642e717f9e4d86003411b8e15ff89537d8e129c116d2f8a9e7e1b46879deedd66fa6ce2b60ab680cfb0;
-  8c524f059e7ebcf3af3072dbd2f76ebc530adba6d26240c8675b5451d5558db648e7a61fefb1369cf2939ba1fadcf8e40385db5d57cacace
-    a19188e6821f5cc2c53b7e59ae6f70e95fb929c0f282627ccfa2c6d9cb59dc871e9dcf3e2a8d6d66b7a6907d4d36c9de03c3d74325d8c1f1;
-  dd47eb6f4f68cd3a9abd6af401bd6f3c795d89474dd41a89025b24c8349a0de417c3676bb6ee36002d7c8ff6b4fb4491e693cfa617e079f8
-    871f46c93dea48a0d937b3f1f724f66615daa9200f0b48cee01c3b20e4a05dd6ce01bd7b2713e096cc2bd1c5ce7ca0c075aed0fc1ef6fa51;
-  577870fdb83454eed0711eb51d7bd91f9843769737566823e41d0668fad45c82fe069347769244af7230e6fbc40f5a71151279ae65e9893a
-    efabd464218df4a490b9870d541c45e9b7ab29bae25d9e976539a553995ded0edc5610916883642a032eae4e96eb9e4e1443f747dec98135;
-  8ba84194db2aad7b46005423b1251555ea931b933e0083fee76b9863fb528927f27a4a0617b8d75de306103b592a0fbd51b72bfbb051ee2d
-    3a29e940174d846df65d51070295f535a03e988fc401ef62f5dd2456cf52668390e61e7b6912186d6d5260f6d6977004003bb106abbdaf02;
-  9f17e0943b4e39051abfd8f4512ef177fd5c368ebdf4b0af49df2e1d89e30c4e68ec474d81203964bfe9c1fecc1279e5e4f598ac97b48cb0
-    d794adb47cff3f7666dd0a934896015e59f278d9b1d6dc7a06328da96d6e6520670598129b7e1b26f9537216364199cf5c0010f23692ec90;
-  a6b51625066e4cccb7d45dff5b182e2a6bf4b1cce7090a187d38dd39f08afad6f868c0277bf70d5fb88b6e67432526e4feb39ae707e34990
-    67315efb85e16a1e97130092cc351759d9c18261845329f63eba1e77d91ad2c7df51ffa50b655de81bc807ea2b3e137214a2b08b400f2b7a;
-  28a0fe53cf73a0419fdb4cb493c6425be8aa812c3693411816c90621097a9d5687feb16ebf874a30ec849297742b7aab5921427d7b474190
-    69300770a5bc2c9c599431e5f879ef3f3ec065e3a2cfe82e3499018add58acada581e9e81d40799fc74674b9721da018a64138519abdb108;
-  fad58259395fd5bbcfca35b095253a3a121b62f1694e14cd9e2f85bd08e8a15d1dff98e3b81eeec678821a1ee9d6192c8351bde45ce0581f
-    bee7e0d6d4de419981ba2aa3964adfc7545e21b72b65c774b2029c22e06f251cebf04cdffd23e2051b57f986cbf7e56f047050714a275e72;
-  91e548171a8136d2d26e6bea02cb16ec9591e9cd5b913184b22b43d1029bdb214ef737f6e45f473f7d95b8fde075645c3b0c2dd2bd224278
-    abe2936ecf2ac3012455dcac906f691f2d96490539c9621658fd7f66790bbfe0d2df07165ea80e0c3282642d45b63b7db476b53e4f94f1c5;
-  a52c855daa9ede16ea8de7c681436d5d31eda6ca5b441f972e5cf5639a1c56f689fcb411965271853de2893f22b81d7d0facafdb49292e39
-    382480e92d44199fe5f7c357ad2e5a7277beab1a3055d48e679516151ca85ee3cb498b172087d588738daac2ec1da9638552d76be97626ad;
-  c65888cdc1a575fc9a06dce8800607f56fe88839948b7e4e2713aae44b0ae6b7c6b68786b11b430d22766e9e4d76af118a972729c67c06b7
-    31311e4ff9600089b533cdac6c05de3ddfe6a450ee7fc90cde1bb297e2deb750336ac3ed2f6fa9b88ece846be6f6aeb392f6753eb6fa475e;
-  a61c81d621df61ece4b7274f63ae4e9f2e2df1d603fc9303ee361962b2d70bd783ff1b5d8f3ed27f17e7773b2b1c85af7fbd70387bdef5d3
-    a014ef20adc291c0238be3759ceb9f9645524b961761c8a991ce67efbddda568359fe36e762980d75a58a7ba10b803c9f883fe4d2239a08b;
-  96ced952366c324c5fccd48ac5d475cc1944e7e455dc093f0d9680d6d6abf1e45c76a286ac46acb4de061b9eb673a2d3124e6c3b921ad71f
-    6debaeff6a7d2bb2c1389cb3338fc87b2a32e651ecb8d43fc012efc9b9c59c79487b742f0b30d0b64ac283af0d3b877102c6a7ff0f606eb9;
-}
-
-inv {
-  d665678f17043846f953fb09c88295d7fd0a53bc70ec7d396aff56e7dfa376f3a338f0da0af9e07b66d3ff7443e3829b541bd667201999d4
-    6839ab730bf666c6ca987d254d83bf32b981b466c147f04b823981da75e12c9ded469a0a462861a987c13f05739f47596401fec25a5eee5c;
-  bb8d567f6163a92603a388405121bd58abfcf05c596bf0624bf65b6a8fe03e6940648382fe01e5ab58e37ce235f4acbfb9e02624001c49da
-    3f60d0fa0036da2db915e232bd841d09f006d4ba018c1d268af86d36990579d669ee63393b95c202645dcb1225fe9e64d14270905e63eb79;
-  d456692d8e00bf9cd86d22a9f4ad9e9879e6298274854ae82729ebbdb0cc46877caeb381506dbb097b10c180d615661189da65d431e3003b
-    6e0f5a173fb60be882a2b570200515dc7ad473e2192470ba89e6dda6cfdd6ff77026a1d76acdded7b5881a54d68605140a4ffceae70906d5;
-  359ab073b7465de1358a5772aef79db09118541c062421cb30a972525a351f16b5545daed5f9ce8e91a283818df6cdbf443831fbe5f3e848
-    2b0ea74e6f4533498eb3f34247a9674f3a2cf2ab0e4fde65ff11b0d1e756430bc5452ca4b85bd3a1f10f6e4e3b1874df8d19f390a9021757;
-  3509fb8b7688f354738d4a8ca4091f66c880db794aacec6115e675090394ca77e1c83b955aaf4d8e75c6e4e9200be1ce5693532a561d970d
-    cafa18317193054cff7884bada249422ba889c19693d66610fb774fb4bdfeac0e67a5ba6f84ace126c125c46b4cfd627ee777e231a6ffc1f;
-  42e2babc095d88b61caa8883e91fd045106db9c4eeb4d945703c1dee3229c58869e21f73909ae2f3c4437d301a2a3724d67f6ad310f63835
-    28c43a594b6471412f504dc10fd79d2c04ec029a7723cfa0a90aef036991f1b56cf156e2cbc7533671086edb54036e9f4ddc9bfe2e3ffcda;
-  9c01d006213bcfda413517ec815e8cebc06707f5649398a9d14a5d64754375c1ded8aaefd838e8eba84746de07a0f9b32caa2325c4c8e540
-    0a3b64374ac2149d602a9f0ee4fcf6d814c476f451531a086b04b0dd598287b1758f77780b7de08573326a9767e816309d871fb1962bb1a4;
-  7bbd8a2de4bd2ffee4e93d0dd2fa9c5d4abcf9ab86c097921fe7d603b7ffdd07006c7d79d1a10267edce9b3069b134bed727c8f0ed1aca13
-    c909ffafbcc09a96723b9afba8ec0d00d5ce0c9d85de3c1e4de24cf44fb934bd0d2397b380885b7419cbbeac339fc85e2161f08c2f3515d7;
-  6a64650ccf103604c3b030415f7114c88c7094fbd0fd2f2b6b907a27fe104ef4e0684c17ff9f26f15eee5e7442e679ecad3e49a0629cb5c3
-    9db77e47433997640b4c0916c5123e8a4d9c7c0bcd12b2dafccbababd6c9dbc3f4ec7991ea68b3ad4ffc6f0be4920764c65d98bdeba8a811;
-  c3823c71f6c0f3679cb9c776e437e718f856c8fde038418942d062423113352aeb60ab84138f2bf73f268386cab0f2a1419660e966c24187
-    558bff4fffa85d6f67ad44938f5b4473d250a87a120af9ff645a7db37a43808abe30c19c90bac94adb190840078214518e189d6c9fc5bef2;
-  44bd920b0eaf47695f93d063cd85c43c58470c23796f4a106b298d5f2b091210d103e9575c369bb0be66b2323d89cc29602a8071697931c6
-    67464f2dab3a95c9ac7c783017105df7d561d7ae499ad89c4698da2c0710a1654c89966a7bd30d2d5c0511ed9f020309cde84cecd66be8d0;
-  a6b12fc35e62532ea7c1fd49dd834bb7957da914ec3daf2e4f446b54916d016054cb59ffd4e3d9eecd4a18b08033ee8d9ff84db072cc4f86
-    cc70960f0bb743da1b23d11eb87530a820484a861abd68d2ed7079b487d88481d915b1b34c29d9938b5fa54d05c75cb1aebf0b722a6770b6;
-  1773dc978cd9f94186b83fd5e10a456b48058acd9e3bbacbecee2cfd0f8303c64721ca64c2913d57764336ea055700c2fcafc60d9f4b817e
-    49e443096eb28c167ee62c63bfe4079418fa8e7f9e58757e13327680890b02ce7c9e5bbbc51366e0b3f5315edc456b6f65a09ea1b1a24438;
-  552158406db36accc32edde2f0ce46e23a1d406f60e54ca6a789386df36a57434c826c9586c4b371df3179f675e5956fe7dc3022f785d9e0
-    e0025a1007d3dff5e44947a0292bee8db5abbd1a0fca1d3ab0a64a37925396cd96c21af54d36656eb0b60c63fd5651622ec5487d53f976e4;
-  6b006d36f60750bb5c59f6eb31e2efe6098ab67de7a7a8a27201652380a295c408ec78351c2a799d62227dffd4731b7605e5c462dce2c1e8
-    21785aae5f73da711f6144894728627824b685fac3d95068a9d0c4e0ee058301a8953322a5ee5be75452164a55477f1a987103a718bf98ca;
-  700cb76911e718ce8829f8d767c53e333dd2f7f20d2c020d1da3cc9ce96b9f6c7aad67450d5aab8f8c60e8ad77d4b5fdb86fae92a0ac30fe
-    257f202b457f19f27ceed047e6778204c2b71646fcc96e19c6f07518780bb5b1c456fd6e93ce2f1cb0aea1a225137511dc71e446c1fe22c3;
-  0c909e0326649d4d375452c5b233a86e90b0fa88b20aa54e02685edd02b70aa022ed8af31e994b70b20101a5cfd8e16ba53c702840b4a16b
-    98c41073ea843b4b5ad6b0589699f48a1576e3d834f8e595b8859069b71bf5e16126aa93b20259ff0a03976ff6d7f78239ec1059f8cf1193;
-  4529761361781e67037eae69c5ca9977b1e21468834eb83cd369471e5092249015cd263563bff9348a0f51e4a8517e27236ed1ecfe30a780
-    e20d5896be18bb273bb0ba84f6c070de45378bac6d793685e654764e5aa847d48403a68560b48dcb12573ac737366ae701072300615b4659;
-  6fae83f7eadeaca22b6781f400b01f9de186b12e31fdf56e0ebe98a8420baacf5069ffdf26d0215c16b64027dd69ff29709a64cfe8f52dcb
-    daa266a02c4500d989670eb63ab78219892d9c1ca2e17f4b5200cf1d920cfece5e80050be77f81a616de840bf19c23835ed17d57aeeea0f5;
-  23ca16e8b4c15f8f2b216441d851368d185a7f8587f398b0cf775875678241094538708da0cb2260c5e056b59c003c30c8f84f5088d0c99c
-    9de1360b4718fc762e6ffab46827c5e4672a77d797aa608b31c132d1ad8138e7a64ba1f4278a07a6088f8cec9a01ea9bc1427c55241433c5;
-}
-
-sub-mulc-add-sub-mul {
-  07ebfe324f64b54e938951a1e437bab4d35c2bbf5f210c5d78ca2b4eb7ef9c3dab61724be4fa7c2e43086b58db7e961f62a44b029f9901d5
-    d44920bba642b8162d1c3e956e060bbe6f15484298c2ec55575ee378556b0e8826f627bebda963b7d4d9f1c768a49cd408957105d3c6008a -41997
-    e3647583d41ee4e813045d4f7a8b53af084c1dfeab8db93472810e8c54d253a2c100a6fc341bd92223341150d363f00f1c2bbb9ff9f8e7ca
-    d61c770618adfc42ef3ac4272dfae86a674f8ae4c273d26ad7b9a29943c4740e0c9535812b9ef0d17fb4bfcc77bf60646aa96a11c29035a3
-    76c496c2c798e23c657eb80c44940229ba88f21bcacb21cb6b4cdc8b93d10832f3c4d31819fbeacb6c5a516c7889f0e639abc29ec4d7b604
-    5a94d8487539381061d764a3806e31e1b2add772d2f9cb9c4fb96336f7b36534a9a0f7caf30b7e086c875670a0d568f895502983b1dec2ef;
-  e1792f9e9c7b70293e041a9059df95bcac07b4112f25d35375ade1794660a0a10c520adf06fd477c79a170ab88108e4b74bc47ede8ddc0a4
-    6cffa5fd3f07f203fcf08c399690b793a152e65aa99c6f9b465d39861c3c46691b635cd02c9e77083ecdee73a54aa1aab5ce6044cb2cb8d8 23228
-    31cd1c1937619b8fe711d22912104fd03fcfa3f14f81f3bc7ec9839c5440836d7c9b92158c818933aa614f9a085f9a1c18d71dd11d09a6db
-    2386136ccd81814300b5f3fa148c4025e6d7a2d9da344e56b42811deaa3d4ecbd5365f91d941d7bab20b305ac6dd0457a4b81cc611bb5f11
-    16bf2b1e10c77597990088a8df91150a6e7b6c3008e6584909b2f7184358abf6b59674e210aeec3219a5202440139aecde4a4b6e0f46dbaa
-    dd373d5908b408e51e3c6f8da1c439f845d40467057a34a96cd53680661b329f073d0bfe6af98543d5d38c3d0476c19d20c54226e7bf8d7c;
-  fe6d00268bafd5878e0a4ddebad8dff25399a1d18e69f94b471029058e9712b98263d88b4dea5d08d8fe70b3a62ba2d136c2c2713ca809ea
-    12be184341bbd7ab5a668f3c3e4b13a60c70cd4e1f229f90901be24a285f3ff0b7391aee82529076c14232f61a11b6a8edffd56af603a25b -252008
-    178e5309ab3a578b8b09149da9539d93309c5214b61e3c045034847354f59d58fee27e31dfcf5d5daa24b5a605686b468a3db727583709d4
-    8da5b2f4c39e442c729a09cf04405136c55cf7b76fbe949ec3b34fb17b2edabcac44f4b4a19afb58c9d86eb87a0c58cff2cf196e6cac7da2
-    3b0be5158a7c13a6c71455025ea5b4466eaa321956fa785f9b74872532e3767d796da94ac47e6d25a368ea1ac79c44fda8d2e13edae5c219
-    7ad75999f1bd89b130fa03274247b36b2c2684163097d46deb852083b5fab0e8755d2150dcd2ee563757f05eb1d132df284ccf818cd56b9c;
-  e4ef0519fc7af554a4a348cfcea95c6c18752f4a35a946b7d2ad1e6aa77d64ec4012eea4faead2d91c66b0d57198b19317a79e136a98caf9
-    008c72ff456f0f941781020ce6387d8065772af7c68955668a7cb05b53f00960f15fc463029a2e2a353a2fd3bc43790a847ea35c75d6cd26 287411
-    5ee722a21955b3bec9ed5f151686af9da9d3f5e6491e3d9a8d82237b1e3dddb58b827264ab5a1aca3eb8c1de7922b59744567e0467a4357f
-    9381ebf793f7b3f523f4621e934217ba463f96279ce2e7d165fc00ea037b20254948132dd2f0481ad9816e1f66da64d081e4d24866094af9
-    62e4648d4716c6e0f99357c8c099c4988cfec4fa21873b7928350f174679f59629a54d78bc8d239800709a585d4890fb2b634f68ec13cd78
-    850e54cf9388bdaf3de63c3e73823c0f39f0b9bf15a9f0262f24c828d2fc8cd7d1ac939193804fac3d92467e26ba5e57d1dc4f8664a270af;
-  5f3811d6b8277fd93a197bf4f3dec4bf4dd5fc6a0ac92ee3d0e64ae48fa9e1373cfd63da945db924bbac41a2b78f6819ccdf2820b1a3c4ff
-    ee669edf4430678ff1190be8e39c06dd00cd9982ab5b625e5a6814ec456f68f9467f1f38519f4bcb392772479ba553060391752ab4fc70aa -254559
-    3d11820f867d39b2b1169030c24a9307eb387f44ee0fc8d53a946e56065e8cf9af6069c9c8099de1565f3d491c33248965ebf941987ade48
-    9582a93732bb52eba39d81c161dd0a996b50dadb13b4eb54085ecb9e86117ed25cb7c78d1a5cc3807a97d740710c2fbf65f97e8de3591163
-    501c2ca79204d22e6c52d32d405310853e7e29da884c0f14782e9029929751821f81a9493c8dd76e582bb48465ce5b40d7c5e398322ceada
-    dcdc428d085f7548c99d963af7b8af997c1503307d75e298efbfc042d425d385a6b7321d86d5af13809ed3ec6bc5d96afcd026d08caeaa30;
-  d17c198598d3b5188e5807c445976b769d458ca952a7b99da4b19ffa3b35b6100bd3605136143912640e402a7cb91675e61527244844409b
-    9cac226e58f5ffbc41bb82b769ed12d061eef4d2d0369eb12724bcd4db6a1ff85f22d6b25003cbea0308a1b7dcce1450283d4e96ac8d4b8c 516083
-    9f92e7a68af5c7737f3f3e959d2b55230ca11e0dd467bd52a20b91816ce61ac7fa7059934c7a952e43058ff4f277170ec5ecc4cab51baef5
-    d4fb3628a45e2290c7fd201ca434ef83911ac2687218605782b3cdca577e692a389756e6b9a0891311727d623fe8ea601fb13efe238adee0
-    ce572b3cdd011749634a577c727aa4516d00c4236cdf3b4664c2be35d3efe7e0b140b5ef2d4a0339a8a29eb26025e60e7d166913251966be
-    790d7ef8990c44fd271d5a41c55a6d552f60fd8980c1c3b91919fdd5e291c75b0a0cbc4224dfd2ce93de2eef53249f3d9d0955f05b4cefaa;
-  396fe89631a66fcf4368600d3a8cbfa6fc903cc8d157f13ac0e4a569436c3230c0a9319a55ebb7e61d428e74b8ce740e973ee5d2b0a99a61
-    f644b35fe8d9bd57a0e6837ef03d889df2248a06a0e52a9cdc80307cf68c496f34aa82f246b8d6e040d166ffa1920b7d921938bb33f8e8a0 -339102
-    716c673c21cd0d92d86f8060beba37c65b7d9eb8b1d4f8aa5665478278ea5c3a2a2c4f606aa179bc8b38f4f37b3e077959ac7c8c81a5fba2
-    6379d7843800b16ad06ff70511c7ff656fc93ff95a05617b4adf7e2b6810cf2cf81dfd6b0c7d478d52f2f4989a13a3ccbc3a4e30f85a3279
-    5b982eda7d33ef68c0d94400610744b91572443614a128bc90011a953bc9422910640047809049a513c413b4390a09395da3de6958c44b64
-    91cf825bde194c05cadbb9dcee5f08f152d2bacabc144b4ee498b82ddf4074846ccc75d366184ee29bd322deaf99d6ae81563cc2e7b2e98d;
-  b8bb334fbe75e81a417ef59e14b52898e34dcc8bca4bb2caa987dc31950a9afa4dd356735dd163eba9073056a2e7f259f1485ef37acf8c24
-    0e872ffa891f664be01868170c452c25cbd41dd0e4df0a66c0ed67dfd3d007c25c50e4b0615450906c69788080546b9a4ad425402c422580 287059
-    52356b0443301992c676f6cfa7eeca79d586324bbb5f8aa71163b89d863ffc7879e55c363ce260fd6ab160e18ef0921d81a4d634799fe816
-    35be6d14d3dc696bb20c90de43c7e08b2427ffc9c63a5c37767ee6756894b6d94c748e9d2c4d8519cbdc2efaa215874bb1923cf7aa5a826c
-    8db5fd04e45f9f93c7a2a2e238c7f001fd7c059d02fce693340c106ebb98d7f6f3029d3e820e2e3e912901c33c3dfce56d68a7c42a2f2e0a
-    29ff4f6533b4292d0e8f2a7abbd1269d1455d8ec34cadca9df875d544ba10395c36d1e750fb66ff0a9d97a92538a63ab48db8583fa6ebd5f;
-  74dfa3166dee585d6d4c5f310259a6f9a407e5c520559f22a3f290733d2f0ba8a276d46820bc73f9231fe25dcc8e9c2e2542eda5024180ed
-    50881f8d2fac3278cadb483b7db6e179306b6e967f8fbdb53f70f443ba9f1b1073921a0a1f46c8833856e6a0ead7ab6f445abf833d2550f7 -430161
-    10b16716f590c13b435ce912fd4adb5dcb4982d8e0302dfccff5f9d388efaae716e8d9e2915de30d365a04468f4bec0f4489d81c0e159bd0
-    b4e67998a7579734cf8f0fc281bb29e1c3dd4dd4d9c1434e830d4d093ea2b908137dad647ab349c5858d1b3ce20f7378546033114dc0fa68
-    76a10a58f6136ec6b73d96ed1d506b758ddf6f54326f7b2a12d28dec9ed880dac2d16f2f57004c7df846ffb4c5c7de814a0245668df0e804
-    33216663bc217e49c81d64e3957f3a16452193b677c68f3df80315c7496995a752c7f42807d22e6a23ad2f5568ada163ba168cd1ff3631c0;
-  c047f2b5077afcb0c246abb9104309be15f2c2da8e703e74459d34281992fbbfb95b1012067415c5b17650d10f5d2d12b84c3c825068b881
-    831adf8c6481178176f11f1d7010fa4b51c6e30ae8a9aec3a748a47bad643ff69cc8e1ba47bf9d33183de1c1220e989c58d6b23e8a602ddd -445266
-    db32546436b5d585cd4fefcdf8affd7c467c31699787dedd133f205641fcf74ee246a5f62dee25eefb54091b5dd0cb4dc7cfad9cc68bb9cb
-    9ea3da4650bbc07d7cefbff97a9bebe5aa932772ce0e47a4bdfaab1be5457f652f9882d8e4ca286b7bce092a4fe93b1c0473a2d5d33d92d3
-    a8eeaf02c9e281f2522def4792beff7382ae509316b80ca3e70b36c080706f9cc8589518dd9b27e61c3f3e28c8608524bc201076d6ae2fcb
-    463c925f11987399440da6a502b87ee798b2dfc37f012951af57dda87651de7bb96c2c30890e6b65771e70ee08bf41e2bde696dfcb177e83;
-  63428356e8b4c5147870a0e653866093d5ca20a691524e3adba1c95af70fc706fdb420391c230dcb70cbad21f028b03e7554efac7bc8bed6
-    e99ca8f8dfe11c545b49031f68a605229adac19568b5cfb9b02b9721416c225179968b5583d0588ead12790c5df7c13bae466f934e997b4e -445574
-    7ace55b2ba3365a01a872ef5882a8d47518fec37bd816d809d4716301a7b6811926eb5aa593fb2c852ae2455fa42e92be1038d96ebf31966
-    db9244d18540fb524ec9455f493b570aba16ee4f4491247fa18efe63a43c70e533ad6660f64e836675bd788113993836c43a3c5868efe068
-    8cc4affd9631c4ff75313f43588d977f24b58a0ef1c3275b7c142e6113f20d72fe974f11c9f7cf3dc176e1799dcb4230d5bb138ddee2eb34
-    179440042f537fcd021678f32a1346547ac1a4aa5dc3e5bed329c543ec35058efa16af2ca066ffb7087a3daf68345aa3a0a21c6133fd3a59;
-  993bb02c2ae6974f6988293ce6eae32f520758329e80ae242801f45937baed48cb9bbc111731aea52883ca30286b7593746e6522fc3ccd54
-    2bbbb81c8e51356355a1e49ebc1c6e160119eca0df8c07d171783665c9d96af7164e6bd7384002ed5c19f531bda705b90e06130bfcb2ad17 -159409
-    6b3eb1b9dac2b8f6d86a0d983bd2b36a98c760ecf5f4aa30e22726e8048cc2e633a7a7bdc862d6bb02fcb0d9e854ac9dce8cb9982645ba44
-    fba6ac4753539d9dea1190d160994937af74be3f73856e56dd7ef4fffd1f6e2d99f1466fff7ec4bacd115f4e1f8708adb8c9afa7b17ee887
-    7f28c3d4526328a9f03cbfb3a0b04fc2aac564effcdbcedfd61a160d0499c83742255e86764c344887a93f7f1851903372e40d7034b16f03
-    2bec5989a2f2fc934dc0e673f07f0ea7ebade4d4bdf7bf472f7e779a716dbc4aa01771bd1dcc634780b0da41389c108a76fc67235e028142;
-  96ab5a1f5b6cffe08fbe3118d7bf2d09e6da8dfdb0ce69cae1c2d3fe71864db59befd7e252410d04a858ef680a754b2d42f7f4ab7cd38e0d
-    673d469ae9193bb79aace5d641041c94b81f6f9a9d12e5a05db86674899ed5650b8d4d30bb00f2b51b0261245dd3a2e18a10f8109cae1535 197264
-    83f7aaef3c944d9d6ef3c329224067a204f738f3625488ba01845e31fa07dda26e08a4e395687b322f594fed860bf1597ab33536c5f24c53
-    9bdc4e2e4e412b65af636a24480a40ab73df53fb209619044317f90df9bba10e5892aa502ee86e1039a8547a4e119caa359e8095ef0f5827
-    659ea4924522edb2aa50430f9bf5ba3112c60af504dd290215a52c8bc275fa8fe0042348811a7cacd0d8bbf95255a547ae9b82db70326b25
-    a28bd6727521f46a3ab3ac32a3452c03b7ceca3c06c4e5f260c1868935269b8cbeb3d303cc6df3faee2595788af6f24a52ef8237763793a1;
-  a0de95d94e3506ed563b974d07454fd347f7b37aa1e9453e0145d23e1867f2aea78434ace37877022343cad84d9100c7683b33c115014903
-    ceeac84a960af7e749645352ddbd4a9f7fd77e96268ed8548e4247b6084e13a193233ba02c49da24c89f2a62ed50029ab38eb6566167aaab -5830
-    8568f4c8837fbef756a3c03ee6a59f7ce0b5ffe370afb5c18545e4fe88eae49c65c642494e1cba91c4eb8b2fa94df6ca22b21d3e7b717f3a
-    70170f374d567a159bd8e354eceee6aacbedfcf9a2be6b530808152a96e93a301518f0042baecaf90170bdc4cc8c2e1003bfe737cd258929
-    cfa4cd159f5793a1833bfdb97261c204d3a80a01e1488ce8c628e68225bbcffa785093267eb3f75702e70b6abef59bc0a223ecfa09aac356
-    7302a30f89bf3163baf814605772b0ca175aec6a030e53a2677c49351d88f1c095a1974e1dabcf5859c206f4bd3e932f7973766e81e0c278;
-  c297bf2bf6e64d4446a2e5d1c6448f5881c5973ccf6e75730dcf2bb74096e603a354461e02e818a94ace1f47053d23710719135cdd366d92
-    8966ea0a08b7f43706340232c68a264c54b4e609ad8c901d0c0768c2aa5660434e5d4ce7510883238b17a8c92f8013d2488730d3a28ca291 -266784
-    c52a9e11dce1938ffb862357a9a696ee72c9fe18f7163d29052c949b4ac0fa151052dffa3546cdefdef598c28ebcc620d064783e8ee20413
-    04f0bdf761a2cfebb822a12bb44b2def0906ae99cf84e7bff6d033e4082c2fed1961942288b0e2beb11a0e96db8a5037fa61631cd89896e4
-    add0f3d532987482db8148a8ef3724e27ad497bdcd804686114acb3a86e4e561001a7af6420bbeef57b77bf8444c4b978e5cd136083d9118
-    efda70e401d9e5beea539fb3ce7a145bfc90422e049387f222db53edae81078046fb1e2db538ebd7ba36ff5509691c83ef9c51f3581edc2e;
-  06768f69843008554828e6665685231b32e60fa878cdc11536819fb04874df4c6f9023b356f1cfb03a1706d04f472f1f1cba2148e161f936
-    61d686b96bd02a99efe67123f3962e318ce9836b1ed0b7a39ae98483f38efa78a89063badbf97325b4743b2342647ed8a44a164e76328781 -301528
-    f8987e1314d3a3fa7ed1784fd04e4b381e9bbee6a785400e51d66402bd95c13de03e4a8213fbcbcec493f0ab8f3aef54794d8baeb9579b57
-    dee30a4b1359ae1459b790e8bedbce16eef2e299082dd2a07e46063c79af11524e438740af78d161afbd5b410888ab9f64eb4129dd1caadf
-    cc52f548a25b964b2556be59c5243b63a323701d696d8d3f866be512554227b8aa3567960aec684ba50701be5528f188a9bcba490517949f
-    bf88a0bbfcf8d048525ba4b7f64988bb8db5ab4abe40c20530b512f130dd54ed8f0bf9c36f51c20735415e25905d4047d896bf6eef7325ec;
-  b2fd5cba9d6d5487c5257954d1d170a99cd27c2e990aa7b20006d8615b929f9024c5b3a0b063dc9c364a668cde34b4a26ec4e374d38d2a32
-    e4796d1ed6d6cd3443a095e6f91e80db3ea043b1f9026e4015a4abff5b2ecde79848dd0b856db0f47a6f29e1759fbaeb2ac82d2d8a939d89 -338517
-    65c169eec5df306b2d17d58f7c1f833bea184fadbbc8924803cc0ff2804d24531e69004059169f29423b5692d54c92fec7936933eac92317
-    ab7c743547424e08a733876339fc4434d1c0ede96dbcfc7a92acbb6ec4e1f6e330d13cee90e4378863022bb49b57b6b4617b37fb5e6f7d0a
-    5fb79ffb10f7c3bc4cc98025f7c7f71bdb4041a5161e7fdee2a701692d16ae77d23680becc76f14e66a7e961d8841adad5485043e13b7694
-    365da4af25fe7f21edf0706495f44475b2d3a9b157b3008dd745cb8e756e3da662108d6c05d573aedfbaa0fd0c8420b6b7ab8d418d273be2;
-  0b1fe73972fe3400b1a9563b759cc65dc7f685031405e14ecbf1ab977c7c9afceafa91f51d1127f09058b637c9cdc39fa665be7c2a4d55d6
-    349cebcab0d98aea0beb0d38dde902e4f6caa23cbb066e68ef8d384613b4ecf6d21780ae1844c4b3eb9598cfd62fc001505d3ce4e66746ae -242599
-    7c7018b38125bf7415723b398f888458a647f4a2f2ff0b7dcbd6eb7ae873c44068429efde0be1f2f28ae1c8e01db9f812442fabaf51ffadb
-    c125c39bcf8ae742747cc2f711e470b8386403e275a14e5651f1dae89231cb3ee186a3d2c1b1a74002ac70e1fc1a5adc89a17734aa231650
-    feb78a43f6e633e7b92ffb2789f6486cc7597ce0ce9ce2486828af900d97c9ee8fcd0f52d43d01e141f9987ad194dfaa8a31b9d649e487ac
-    32318ade75655d7aacba10759063893db2482b2083a924915afefc63891f9951b58bf5525f5b330f16422c65bdf77a5508f1830849c2a941;
-  080f596d6be6f4554477689f6ac45ff60a880924f6e609701bd6d1fe32eb4f1be13edf39399eb170fa5b5b9801e38301e7ed768383cab6cf
-    f14535e25853aa97a8bc8128610eaab77977d07d3a89608a837b16fb2c2878f8edf11a2276f3c42ee21ba275dd4e6059574f887abcf6480f 273443
-    f273139e62664cb2b5f9c268c37abfcddc054c0f30ed8f0fd643017a989512cf115467ca704b3442b1c92496e378f4df6434b27e9c9fbacb
-    8af391a0b26881d67fa19196d5dded3e00cc3dc60247781ec1d000e635b6f39f7186e948bbb5b03894f0a000b27838dbda844836c5c29d99
-    56513a9d50e48e2464df2069404f09c21d4bf112d2223ea316e78cb4ebbca403327ab344af7e15b17b9865ea8d801cc7d4f6f7283687c3bd
-    9c3043751d7889855a337637b51e1fb9c7bb47d75ef529e4e8545822cbb2f535ef1579b9c660813438e2e9f16bb35f4a7843d3e7820e1406;
-  a5d6bc11f9251ec7d03e87c267b2eb05d51fdbeb24970e2c87a7d8923f7adbf4bff904e5ae498f5984072d7a21c703ba6765bc3292e43bfe
-    2be24a92df5b92545f72e710d4a5c71f881d544305e891dc9fcf2b39a24a5e80fe44f856411fc886566f428b5443af8140543e549d092170 -140922
-    629534899a55d04d6e0c879ea02b9eb05675cf6074ce400d8caa25b2adc59eedcd88f203f9440db9fb06c5bfcd65512324d01f871b485650
-    867e9ed2dbef2b0d485a7d5dc71266eae2b6053c2f1e09dfba6192f015419e06868aaaefefdc3b03cb26e50cc4861f38eac76ac69e5ab1fd
-    61d009f31c5be4eaca1f44ab6800f0116dadb7923e427db6e525f03c17b380eaa6d0c8f06440674c80f0040c272b8b956366a82ca28dccbf
-    a7628d76da5a4a8dcabfcd28252b9fb1f780e2d32f72a0f1f8da7ff7d354c6d35a72efb2b75e87c332f93557c1a5e1bd51813e18ee1fe241;
-}
index 5b2889f..6a8d35b 100644 (file)
--- a/fgoldi.c
+++ b/fgoldi.c
@@ -1,3 +1,41 @@
+/*
+ * fgoldi.c: arithmetic modulo 2^448 - 2^224 - 1
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb, and modified for Secnet (2017-04-30):
+ *
+ *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
+ *
+ *   * Remove the 16/32-bit implementation, since C99 always has 64-bit
+ *     arithmetic.
+ *
+ *   * Remove the test rig code: a replacement is in a separate source file.
+ *
+ * The file's original comment headers are preserved below.
+ */
 /* -*-c-*-
  *
  * Arithmetic in the Goldilocks field GF(2^448 - 2^224 - 1)
@@ -27,8 +65,6 @@
 
 /*----- Header files ------------------------------------------------------*/
 
-#include "config.h"
-
 #include "fgoldi.h"
 
 /*----- Basic setup -------------------------------------------------------*
@@ -37,7 +73,6 @@
  * (hence the name).
  */
 
-#if FGOLDI_IMPL == 28
 /* 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).
  */
@@ -54,32 +89,9 @@ typedef uint32 upiece; typedef uint64 udblpiece;
 #define M27 0x07ffffffu
 #define M32 0xffffffffu
 
-#elif FGOLDI_IMPL == 12
-/* We represent an element of GF(p) as 40 signed integer pieces x_i: x =
- * SUM_{0<=i<40} x_i 2^ceil(224i/20).  Pieces i with i == 0 (mod 5) are 12
- * bits wide; the others are 11 bits wide, so they form eight groups of 56
- * bits.
- */
-
-typedef  int16  piece; typedef  int32  dblpiece;
-typedef uint16 upiece; typedef uint32 udblpiece;
-#define PIECEWD(i) ((i)%5 ? 11 : 12)
-#define NPIECE 40
-#define P p12
-
-#define B12 0x1000u
-#define B11 0x0800u
-#define B10 0x0400u
-#define M12 0xfffu
-#define M11 0x7ffu
-#define M10 0x3ffu
-#define M8 0xffu
-
-#endif
-
 /*----- Debugging machinery -----------------------------------------------*/
 
-#if defined(FGOLDI_DEBUG) || defined(TEST_RIG)
+#if defined(FGOLDI_DEBUG)
 
 #include <stdio.h>
 
@@ -123,8 +135,6 @@ DEF_FDUMP(fdump, piece, PIECEWD, NPIECE, 56, get_pgoldi())
 
 void fgoldi_load(fgoldi *z, const octet xv[56])
 {
-#if FGOLDI_IMPL == 28
-
   unsigned i;
   uint32 xw[14];
   piece b, c;
@@ -158,35 +168,6 @@ void fgoldi_load(fgoldi *z, const octet xv[56])
   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;
-
-#elif FGOLDI_IMPL == 12
-
-  unsigned i, j, n, w, b;
-  uint32 a;
-  int c;
-
-  /* First, convert the bytes into nonnegative pieces. */
-  for (i = j = a = n = 0, w = PIECEWD(0); i < 56; i++) {
-    a |= (uint32)xv[i] << n; n += 8;
-    if (n >= w) {
-      z->P[j++] = a&MASK(w);
-      a >>= w; n -= w; w = PIECEWD(j);
-    }
-  }
-
-  /* Convert the nonnegative pieces into a balanced signed representation, so
-   * each piece ends up in the interval |z_i| <= 2^11 + 1.
-   */
-  b = z->P[39]&B10; z->P[39] -= b << 1; c = b >> 10;
-  for (i = NPIECE - 1; i--; ) {
-    w = PIECEWD(i) - 1;
-    b = z->P[i]&BIT(w);
-    z->P[i] -= b << 1;
-    z->P[i + 1] += b >> w;
-  }
-  z->P[0] += c; z->P[20] += c;
-
-#endif
 }
 
 /* --- @fgoldi_store@ --- *
@@ -202,8 +183,6 @@ void fgoldi_load(fgoldi *z, const octet xv[56])
 
 void fgoldi_store(octet zv[56], const fgoldi *x)
 {
-#if FGOLDI_IMPL == 28
-
   piece y[NPIECE], yy[NPIECE], c, d;
   uint32 u, v;
   mask32 m;
@@ -269,80 +248,6 @@ void fgoldi_store(octet zv[56], const fgoldi *x)
     STORE32_L(zv + 4*i,             u);
     STORE32_L(zv + 4*i + 28, v);
   }
-
-#elif FGOLDI_IMPL == 12
-
-  piece y[NPIECE], yy[NPIECE], c, d;
-  uint32 a;
-  mask32 m, mm;
-  unsigned i, j, n, w;
-
-  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^14.  We start off by cutting
-   * off and reducing the carry c_39 from the topmost piece, y_39.  This
-   * leaves 0 <= y_39 < 2^11; and we'll have |c_39| <= 16.  We'll add this
-   * onto y_0 and y_20, and propagate the carries.  It's very clear that
-   * we'll end up with |y + (φ + 1) c_39 - Ï†^2/2| << Ï†^2.
-   *
-   * Here, the y_i are signed, so we must be cautious about bithacking them.
-   */
-  c = ASR(piece, y[39], 11); y[39] = (piece)y[39]&M11; y[20] += c;
-  for (i = 0; i < NPIECE; i++) {
-    w = PIECEWD(i); m = (1 << w) - 1;
-    y[i] += c; c = ASR(piece, y[i], w); y[i] = (upiece)y[i]&m;
-  }
-
-  /* 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.
-   */
-  mm = SIGN(c);
-  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 ^ (mm&M12)); yy[ 0] = d&M12; d >>= 12;
-  for (i = 1; i < 20; i++) {
-    w = PIECEWD(i); m = MASK(w);
-    d += y[ i] +      (mm&m);    yy[ i] = d&m;   d >>= w;
-  }
-    d += y[20] + (1 ^ (mm&M12)); yy[20] = d&M12; d >>= 12;
-  for (i = 21; i < 40; i++) {
-    w = PIECEWD(i); m = MASK(w);
-    d += y[ i] +      (mm&m);    yy[ i] = d&m;   d >>= w;
-  }
-
-  /* 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);
-
-  /* Convert that back into octets. */
-  for (i = j = a = n = 0; i < NPIECE; i++) {
-    a |= (uint32)y[i] << n; n += PIECEWD(i);
-    while (n >= 8) { zv[j++] = a&M8; a >>= 8; n -= 8; }
-  }
-
-#endif
 }
 
 /* --- @fgoldi_set@ --- *
@@ -421,8 +326,6 @@ void fgoldi_condswap(fgoldi *x, fgoldi *y, uint32 m)
 
 /*----- Multiplication ----------------------------------------------------*/
 
-#if FGOLDI_IMPL == 28
-
 /* 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
@@ -447,58 +350,6 @@ void fgoldi_condswap(fgoldi *x, fgoldi *y, uint32 m)
   (z)[8] += _c;                                                                \
 } while (0)
 
-#elif FGOLDI_IMPL == 12
-
-static void carry_reduce(dblpiece x[NPIECE])
-{
-  /* Initial bounds: we assume |x_i| < 2^31 - 2^27. */
-
-  unsigned i, j;
-  dblpiece c;
-
-  /* The result is nearly canonical, because we do sequential carry
-   * propagation, because smaller processors are more likely to prefer the
-   * smaller working set than the instruction-level parallelism.
-   *
-   * Start at x_37; truncate it to 10 bits, and propagate the carry to x_38.
-   * Truncate x_38 to 10 bits, and add the carry onto x_39.  Truncate x_39 to
-   * 10 bits, and add the carry onto x_0 and x_20.  And so on.
-   *
-   * Once we reach x_37 for the second time, we start with |x_37| <= 2^10.
-   * The carry into x_37 is at most 2^21; so the carry out into x_38 has
-   * magnitude at most 2^10.  In turn, |x_38| <= 2^10 before the carry, so is
-   * now no more than 2^11 in magnitude, and the carry out into x_39 is at
-   * most 1.  This leaves |x_39| <= 2^10 + 1 after carry propagation.
-   *
-   * Be careful with the bit hacking because the quantities involved are
-   * signed.
-   */
-
-  /* For each piece, we bias it so that floor division (as done by an
-   * arithmetic right shift) and modulus (as done by bitwise-AND) does the
-   * right thing.
-   */
-#define CARRY(i, wd, b, m) do {                                                \
-  x[i] += (b);                                                         \
-  c = ASR(dblpiece, x[i], (wd));                                       \
-  x[i] = (dblpiece)((udblpiece)x[i]&(m)) - (b);                                \
-} while (0)
-
-                            {             CARRY(37, 11, B10, M11);      }
-                            { x[38] += c; CARRY(38, 11, B10, M11);      }
-                            { x[39] += c; CARRY(39, 11, B10, M11);      }
-                              x[20] += c;
-  for (i = 0; i < 35; ) {
-                            {  x[i] += c; CARRY( i, 12, B11, M12); i++; }
-    for (j = i + 4; i < j; ) {  x[i] += c; CARRY( i, 11, B10, M11); i++; }
-  }
-                            {  x[i] += c; CARRY( i, 12, B11, M12); i++; }
-  while (i < 39)            {  x[i] += c; CARRY( i, 11, B10, M11); i++; }
-  x[39] += c;
-}
-
-#endif
-
 /* --- @fgoldi_mulconst@ --- *
  *
  * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@)
@@ -516,12 +367,7 @@ void fgoldi_mulconst(fgoldi *z, const fgoldi *x, long a)
   dblpiece zz[NPIECE], aa = a;
 
   for (i = 0; i < NPIECE; i++) zz[i] = aa*x->P[i];
-#if FGOLDI_IMPL == 28
   CARRY_REDUCE(z->P, zz);
-#elif FGOLDI_IMPL == 12
-  carry_reduce(zz);
-  for (i = 0; i < NPIECE; i++) z->P[i] = zz[i];
-#endif
 }
 
 /* --- @fgoldi_mul@ --- *
@@ -543,24 +389,8 @@ void fgoldi_mul(fgoldi *z, const fgoldi *x, const fgoldi *y)
     *c = y->P + NPIECE/2, *d = y->P;
   unsigned i, j;
 
-#if FGOLDI_IMPL == 28
-
 #  define M(x,i, y,j) ((dblpiece)(x)[i]*(y)[j])
 
-#elif FGOLDI_IMPL == 12
-
-  static const unsigned short off[39] = {
-      0,  12,  23,  34,  45,  56,  68,  79,  90, 101,
-    112, 124, 135, 146, 157, 168, 180, 191, 202, 213,
-    224, 236, 247, 258, 269, 280, 292, 303, 314, 325,
-    336, 348, 359, 370, 381, 392, 404, 415, 426
-  };
-
-#define M(x,i, y,j)                                                    \
-  (((dblpiece)(x)[i]*(y)[j]) << (off[i] + off[j] - off[(i) + (j)]))
-
-#endif
-
   /* Behold the magic.
    *
    * Write x = a Ï† + b, and y = c Ï† + d.  Then x y = a c Ï†^2 +
@@ -614,7 +444,6 @@ void fgoldi_mul(fgoldi *z, const fgoldi *x, const fgoldi *y)
 
 #undef M
 
-#if FGOLDI_IMPL == 28
   /* 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
@@ -630,10 +459,6 @@ void fgoldi_mul(fgoldi *z, const fgoldi *x, const fgoldi *y)
    */
   for (i = 0; i < 2; i++) CARRY_REDUCE(zz, zz);
   for (i = 0; i < NPIECE; i++) z->P[i] = zz[i];
-#elif FGOLDI_IMPL == 12
-  carry_reduce(zz);
-  for (i = 0; i < NPIECE; i++) z->P[i] = zz[i];
-#endif
 }
 
 /* --- @fgoldi_sqr@ --- *
@@ -648,8 +473,6 @@ void fgoldi_mul(fgoldi *z, const fgoldi *x, const fgoldi *y)
 
 void fgoldi_sqr(fgoldi *z, const fgoldi *x)
 {
-#if FGOLDI_IMPL == 28
-
   dblpiece zz[NPIECE], u[NPIECE];
   piece ab[NPIECE];
   const piece *a = x->P + NPIECE/2, *b = x->P;
@@ -721,9 +544,6 @@ void fgoldi_sqr(fgoldi *z, const fgoldi *x)
   for (i = 0; i < 2; i++) CARRY_REDUCE(zz, zz);
   for (i = 0; i < NPIECE; i++) z->P[i] = zz[i];
 
-#elif FGOLDI_IMPL == 12
-  fgoldi_mul(z, x, x);
-#endif
 }
 
 /*----- More advanced operations ------------------------------------------*/
@@ -783,206 +603,4 @@ void fgoldi_inv(fgoldi *z, const fgoldi *x)
 #undef SQRN
 }
 
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/report.h>
-#include <mLib/str.h>
-#include <mLib/testrig.h>
-
-static void fixdstr(dstr *d)
-{
-  if (d->len > 56)
-    die(1, "invalid length for fgoldi");
-  else if (d->len < 56) {
-    dstr_ensure(d, 56);
-    memset(d->buf + d->len, 0, 56 - d->len);
-    d->len = 56;
-  }
-}
-
-static void cvt_fgoldi(const char *buf, dstr *d)
-{
-  dstr dd = DSTR_INIT;
-
-  type_hex.cvt(buf, &dd); fixdstr(&dd);
-  dstr_ensure(d, sizeof(fgoldi)); d->len = sizeof(fgoldi);
-  fgoldi_load((fgoldi *)d->buf, (const octet *)dd.buf);
-  dstr_destroy(&dd);
-}
-
-static void dump_fgoldi(dstr *d, FILE *fp)
-  { fdump(stderr, "???", (const piece *)d->buf); }
-
-static void cvt_fgoldi_ref(const char *buf, dstr *d)
-  { type_hex.cvt(buf, d); fixdstr(d); }
-
-static void dump_fgoldi_ref(dstr *d, FILE *fp)
-{
-  fgoldi x;
-
-  fgoldi_load(&x, (const octet *)d->buf);
-  fdump(stderr, "???", x.P);
-}
-
-static int eq(const fgoldi *x, dstr *d)
-  { octet b[56]; fgoldi_store(b, x); return (memcmp(b, d->buf, 56) == 0); }
-
-static const test_type
-  type_fgoldi = { cvt_fgoldi, dump_fgoldi },
-  type_fgoldi_ref = { cvt_fgoldi_ref, dump_fgoldi_ref };
-
-#define TEST_UNOP(op)                                                  \
-  static int vrf_##op(dstr dv[])                                       \
-  {                                                                    \
-    fgoldi *x = (fgoldi *)dv[0].buf;                                   \
-    fgoldi z, zz;                                                      \
-    int ok = 1;                                                                \
-                                                                       \
-    fgoldi_##op(&z, x);                                                        \
-    if (!eq(&z, &dv[1])) {                                             \
-      ok = 0;                                                          \
-      fprintf(stderr, "failed!\n");                                    \
-      fdump(stderr, "x", x->P);                                                \
-      fdump(stderr, "calc", z.P);                                      \
-      fgoldi_load(&zz, (const octet *)dv[1].buf);                      \
-      fdump(stderr, "z", zz.P);                                                \
-    }                                                                  \
-                                                                       \
-    return (ok);                                                       \
-  }
-
-TEST_UNOP(sqr)
-TEST_UNOP(inv)
-
-#define TEST_BINOP(op)                                                 \
-  static int vrf_##op(dstr dv[])                                       \
-  {                                                                    \
-    fgoldi *x = (fgoldi *)dv[0].buf, *y = (fgoldi *)dv[1].buf;         \
-    fgoldi z, zz;                                                      \
-    int ok = 1;                                                                \
-                                                                       \
-    fgoldi_##op(&z, x, y);                                             \
-    if (!eq(&z, &dv[2])) {                                             \
-      ok = 0;                                                          \
-      fprintf(stderr, "failed!\n");                                    \
-      fdump(stderr, "x", x->P);                                                \
-      fdump(stderr, "y", y->P);                                                \
-      fdump(stderr, "calc", z.P);                                      \
-      fgoldi_load(&zz, (const octet *)dv[2].buf);                      \
-      fdump(stderr, "z", zz.P);                                                \
-    }                                                                  \
-                                                                       \
-    return (ok);                                                       \
-  }
-
-TEST_BINOP(add)
-TEST_BINOP(sub)
-TEST_BINOP(mul)
-
-static int vrf_mulc(dstr dv[])
-{
-  fgoldi *x = (fgoldi *)dv[0].buf;
-  long a = *(const long *)dv[1].buf;
-  fgoldi z, zz;
-  int ok = 1;
-
-  fgoldi_mulconst(&z, x, a);
-  if (!eq(&z, &dv[2])) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    fdump(stderr, "x", x->P);
-    fprintf(stderr, "a = %ld\n", a);
-    fdump(stderr, "calc", z.P);
-    fgoldi_load(&zz, (const octet *)dv[2].buf);
-    fdump(stderr, "z", zz.P);
-  }
-
-  return (ok);
-}
-
-static int vrf_condswap(dstr dv[])
-{
-  fgoldi *x = (fgoldi *)dv[0].buf, *y = (fgoldi *)dv[1].buf;
-  fgoldi xx = *x, yy = *y;
-  uint32 m = *(uint32 *)dv[2].buf;
-  int ok = 1;
-
-  fgoldi_condswap(&xx, &yy, m);
-  if (!eq(&xx, &dv[3]) || !eq(&yy, &dv[4])) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    fdump(stderr, "x", x->P);
-    fdump(stderr, "y", y->P);
-    fprintf(stderr, "m = 0x%08lx\n", (unsigned long)m);
-    fdump(stderr, "calc xx", xx.P);
-    fdump(stderr, "calc yy", yy.P);
-    fgoldi_load(&xx, (const octet *)dv[3].buf);
-    fgoldi_load(&yy, (const octet *)dv[4].buf);
-    fdump(stderr, "want xx", xx.P);
-    fdump(stderr, "want yy", yy.P);
-  }
-
-  return (ok);
-}
-
-static int vrf_sub_mulc_add_sub_mul(dstr dv[])
-{
-  fgoldi *u = (fgoldi *)dv[0].buf, *v = (fgoldi *)dv[1].buf,
-    *w = (fgoldi *)dv[3].buf, *x = (fgoldi *)dv[4].buf,
-    *y = (fgoldi *)dv[5].buf;
-  long a = *(const long *)dv[2].buf;
-  fgoldi umv, aumv, wpaumv, xmy, z, zz;
-  int ok = 1;
-
-  fgoldi_sub(&umv, u, v);
-  fgoldi_mulconst(&aumv, &umv, a);
-  fgoldi_add(&wpaumv, w, &aumv);
-  fgoldi_sub(&xmy, x, y);
-  fgoldi_mul(&z, &wpaumv, &xmy);
-
-  if (!eq(&z, &dv[6])) {
-    ok = 0;
-    fprintf(stderr, "failed!\n");
-    fdump(stderr, "u", u->P);
-    fdump(stderr, "v", v->P);
-    fdump(stderr, "u - v", umv.P);
-    fprintf(stderr, "a = %ld\n", a);
-    fdump(stderr, "a (u - v)", aumv.P);
-    fdump(stderr, "w + a (u - v)", wpaumv.P);
-    fdump(stderr, "x", x->P);
-    fdump(stderr, "y", y->P);
-    fdump(stderr, "x - y", xmy.P);
-    fdump(stderr, "(x - y) (w + a (u - v))", z.P);
-    fgoldi_load(&zz, (const octet *)dv[6].buf); fdump(stderr, "z", zz.P);
-  }
-
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "add", vrf_add, { &type_fgoldi, &type_fgoldi, &type_fgoldi_ref } },
-  { "sub", vrf_sub, { &type_fgoldi, &type_fgoldi, &type_fgoldi_ref } },
-  { "mul", vrf_mul, { &type_fgoldi, &type_fgoldi, &type_fgoldi_ref } },
-  { "mulconst", vrf_mulc, { &type_fgoldi, &type_long, &type_fgoldi_ref } },
-  { "condswap", vrf_condswap,
-    { &type_fgoldi, &type_fgoldi, &type_uint32,
-      &type_fgoldi_ref, &type_fgoldi_ref } },
-  { "sqr", vrf_sqr, { &type_fgoldi, &type_fgoldi_ref } },
-  { "inv", vrf_inv, { &type_fgoldi, &type_fgoldi_ref } },
-  { "sub-mulc-add-sub-mul", vrf_sub_mulc_add_sub_mul,
-    { &type_fgoldi, &type_fgoldi, &type_long, &type_fgoldi,
-      &type_fgoldi, &type_fgoldi, &type_fgoldi_ref } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, tests, SRCDIR "/t/fgoldi");
-  return (0);
-}
-
-#endif
-
 /*----- That's all, folks -------------------------------------------------*/
index b05fd77..1857008 100644 (file)
--- a/fgoldi.h
+++ b/fgoldi.h
@@ -1,3 +1,39 @@
+/*
+ * fgoldi.h: arithmetic modulo 2^448 - 2^224 - 1
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb, and lightly modified for Secnet (2017-04-30):
+ *
+ *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
+ *
+ *   * Remove the 16/32-bit implementation, since C99 always has 64-bit
+ *     arithmetic.
+ *
+ * The file's original comment headers are preserved below.
+ */
 /* -*-c-*-
  *
  * Arithmetic in the Goldilocks field GF(2^448 - 2^224 - 1)
@@ -34,7 +70,7 @@
 
 /*----- Header files ------------------------------------------------------*/
 
-#include <mLib/bits.h>
+#include "fake-mLib-bits.h"
 
 #ifndef CATACOMB_QFARITH_H
 #  include "qfarith.h"
@@ -44,7 +80,6 @@
 
 typedef union {
   int32 p28[16];
-  int16 p12[40];
 } fgoldi;
 
 #if !defined(FGOLDI_IMPL) && defined(HAVE_INT64)
index 02d2961..4292158 100644 (file)
@@ -1,3 +1,33 @@
+/*
+ * montladder.h: Montgomery's ladder
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb (2017-04-30).  The file's original comment headers
+ * are preserved below.
+ */
 /* -*-c-*-
  *
  * Definitions for Montgomery's ladder
index abcd293..fcedf3e 100644 (file)
--- a/qfarith.h
+++ b/qfarith.h
@@ -1,3 +1,40 @@
+/*
+ * qfarith.h: utilities for quick field arithmetic
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb, and modified for Secnet (2017-04-30):
+ *
+ *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
+ *
+ *   * Use C99 signed integer types instead of our own local probing.
+ *
+ *   * Remove the support for non-two's-complement targets.
+ *
+ * The file's original comment headers are preserved below.
+ */
 /* -*-c-*-
  *
  * Utilities for quick field arithmetic
 /*----- Header files ------------------------------------------------------*/
 
 #include <limits.h>
+#include <stdint.h>
 
-#include <mLib/bits.h>
+#include "fake-mLib-bits.h"
 
 /*----- Signed integer types ----------------------------------------------*/
 
-/* See if we can find a suitable 64-bit or wider type.  Don't bother if we
- * don't have a corresponding unsigned type, because we really need both.
- */
-#ifdef HAVE_UINT64
-#  if INT_MAX >> 31 == 0xffffffff
-#    define HAVE_INT64
-     typedef int int64;
-#  elif LONG_MAX >> 31 == 0xffffffff
-#    define HAVE_INT64
-     typedef long int64;
-#  elif defined(LLONG_MAX)
-#    define HAVE_INT64
-     MLIB_BITS_EXTENSION typedef long long int64;
-#  endif
-#endif
-
-/* Choose suitable 32- and 16-bit types. */
-#if INT_MAX >= 0x7fffffff
-   typedef int int32;
-#else
-   typedef long int32;
-#endif
-
-typedef short int16;
+typedef int_fast32_t int32;
+typedef int_fast64_t int64;
+#define HAVE_INT64 1
 
 /*----- General bit-hacking utilities -------------------------------------*/
 
@@ -117,42 +134,7 @@ typedef short int16;
 # define CONDSWAP(x, y, m)                                             \
     do { mask32 t_ = ((x) ^ (y))&(m); (x) ^= t_; (y) ^= t_; } while (0)
 #else
-
-  /* We don't have two's complement arithmetic.  We can't use bithacking at
-   * all: if we try to hack on the bits of signed numbers we'll come unstuck
-   * when we hit the other representation of zero; and if we switch to
-   * unsigned arithmetic then we'll have overflow when we try to convert a
-   * negative number back.  So fall back to simple arithmetic.
-   */
-  typedef uint32 mask32;
-
-  /* Convert an unsigned mask M into a `mask32'.  Our masks are unsigned, so
-   * this does nothing.
-   */
-# define FIX_MASK32(m) ((mask32)(m))
-
-  /* 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)*(int)((unsigned)(m)&1u); } 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)*(int)((unsigned)(m)&1u) + (y)*(int)(1 - ((unsigned)(m)&1u)))
-
-  /* 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 {                                                \
-    int32 x_ = PICK2((y), (x), (m)), y_ = PICK2((x), (y), (m));                \
-    (x) = x_; (y) = y_;                                                        \
-  } while (0)
+#  error "Targets without two's complement arithmetic aren't supported"
 #endif
 
 /* Return zero if bit 31 of X is clear, or a mask with (at least) the low 32
index b80521d..875b0a3 100644 (file)
-### Tests for X25519.
-
-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.
-  77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
-    0900000000000000000000000000000000000000000000000000000000000000
-    8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a;
-
-  ## Make Bob's public key.
-  5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
-    0900000000000000000000000000000000000000000000000000000000000000
-    de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f;
-
-  ## Make the shared secret using Alice's private key.
-  77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
-    de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
-    4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742;
-
-  ## Make the (same) shared secret using Bob's private key.
-  5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
-    8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
-    4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742;
-
-  ## These tests are from RFC7748.  I've clamped the public values because
-  ## RFC7748 wants the top bits ignored.
-  a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4
-    e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c
-    c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552;
-  4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d
-    e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a413
-    95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957;
-}
-
-x25519-mct {
-  ## These tests are from RFC7748.
-
-  0900000000000000000000000000000000000000000000000000000000000000
-    0900000000000000000000000000000000000000000000000000000000000000
-    1 422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079;
-  0900000000000000000000000000000000000000000000000000000000000000
-    0900000000000000000000000000000000000000000000000000000000000000
-    1000 684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51;
-
-  ## This one takes aaaaages.
-  ##0900000000000000000000000000000000000000000000000000000000000000
-  ##  0900000000000000000000000000000000000000000000000000000000000000
-  ##  1000000 7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424;
-}
+### Test cases for arithmetic mod 2^255 - 19.                  -*-conf-*-
+
+###--------------------------------------------------------------------------
+test add
+
+## Some easy things, mostly to test loading and storing.
+x 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+y 0000000000000000000000000000000000000000000000000000000000000000
+z 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+
+x ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
+y 0000000000000000000000000000000000000000000000000000000000000000
+z ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
+
+x edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
+y 0000000000000000000000000000000000000000000000000000000000000000
+z 0000000000000000000000000000000000000000000000000000000000000000
+
+## 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 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 xdh
+
+## These are from Daniel J. Bernstein, `Cryptography in NaCl', 2009-03-10,
+## https://cr.yp.to/highspeed/naclcrypto-20090310.pdf
+
+k 77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
+X 0900000000000000000000000000000000000000000000000000000000000000
+Z 8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
+
+k 5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
+X 0900000000000000000000000000000000000000000000000000000000000000
+Z de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
+
+k 77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
+X de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
+Z 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742
+
+k 5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
+X 8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
+Z 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742
+
+## These tests are from RFC7748.
+
+k a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4
+X e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c
+Z c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552
+
+k 4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d
+X e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493
+Z 95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957
+
+###--------------------------------------------------------------------------
+test xdh-mct
+
+## These tests are from RFC7748.
+
+k 0900000000000000000000000000000000000000000000000000000000000000
+X 0900000000000000000000000000000000000000000000000000000000000000
+n 1
+Z 422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079
+
+k 0900000000000000000000000000000000000000000000000000000000000000
+X 0900000000000000000000000000000000000000000000000000000000000000
+n 1000
+Z 684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51
+
+## This one takes aaaaages.
+##k 0900000000000000000000000000000000000000000000000000000000000000
+##X 0900000000000000000000000000000000000000000000000000000000000000
+##n 1000000
+##Z 7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424
index 8e9649e..19f3518 100644 (file)
--- a/x25519.c
+++ b/x25519.c
@@ -1,3 +1,43 @@
+/*
+ * x25519.c: Bernstein's X25519 key-exchange function
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb, and modified for Secnet (2017-04-30):
+ *
+ *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
+ *
+ *   * Remove the test rig code: a replacement is in a separate source file.
+ *
+ *   * Ignore the top bit of the input public key: in Secnet, conformance
+ *     with RFC7748 is more valuable than flexibility.
+ *
+ *   * Strip out the key-management definitions.
+ *
+ * The file's original comment headers are preserved below.
+ */
 /* -*-c-*-
  *
  * The X25519 key-agreement algorithm
@@ -27,7 +67,7 @@
 
 /*----- Header files ------------------------------------------------------*/
 
-#include <mLib/bits.h>
+#include "fake-mLib-bits.h"
 
 #include "montladder.h"
 #include "f25519.h"
@@ -39,24 +79,6 @@ const octet x25519_base[32] = { 9, 0, /* ... */ };
 
 #define A0 121665
 
-/*----- Key fetching ------------------------------------------------------*/
-
-const key_fetchdef x25519_pubfetch[] = {
-  { "pub",     offsetof(x25519_pub, pub),      KENC_BINARY,    0 },
-  { 0,         0,                              0,              0 }
-};
-
-static const key_fetchdef priv[] = {
-  { "priv",    offsetof(x25519_priv, priv),    KENC_BINARY,    0 },
-  { 0,         0,                              0,              0 }
-};
-
-const key_fetchdef x25519_privfetch[] = {
-  { "pub",     offsetof(x25519_priv, pub),     KENC_BINARY,    0 },
-  { "private", 0,                              KENC_STRUCT,    priv },
-  { 0,         0,                              0,              0 }
-};
-
 /*----- Main code ---------------------------------------------------------*/
 
 /* --- @x25519@ --- *
@@ -84,6 +106,7 @@ void x25519(octet zz[X25519_OUTSZ],
            const octet qx[X25519_PUBSZ])
 {
   uint32 kw[8];
+  uint8_t b[X25519_PUBSZ];
   f25519 x1;
 
   /* Load and clamp the key.  The low bits are cleared to kill the small
@@ -96,8 +119,11 @@ void x25519(octet zz[X25519_OUTSZ],
   kw[6] = LOAD32_L(k + 24); kw[7] = LOAD32_L(k + 28);
   kw[0] &= 0xfffffff8; kw[7] = (kw[7]&0x3fffffff) | 0x40000000;
 
+  /* Copy the input point and clamp the top bit. */
+  memcpy(b, qx, sizeof(b)); b[31] &= 0x7f;
+  f25519_load(&x1, b);
+
   /* 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
index 56008df..b7b03e6 100644 (file)
--- a/x25519.h
+++ b/x25519.h
@@ -1,3 +1,38 @@
+/*
+ * x25519.h: Bernstein's X25519 key-exchange function
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb, and modified for Secnet (2017-04-30):
+ *
+ *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
+ *
+ *   * Strip out the key-management definitions.
+ *
+ * The file's original comment headers are preserved below.
+ */
 /* -*-c-*-
  *
  * The X25519 key-agreement algorithm
 
 /*----- Header files ------------------------------------------------------*/
 
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_KEY_H
-#  include "key.h"
-#endif
+#include "fake-mLib-bits.h"
 
 /*----- Important constants -----------------------------------------------*/
 
 
 extern const octet x25519_base[32];
 
-/*----- Key fetching ------------------------------------------------------*/
-
-typedef struct x25519_priv { key_bin priv, pub; } x25519_priv;
-typedef struct x25519_pub { key_bin pub; } x25519_pub;
-
-extern const key_fetchdef x25519_pubfetch[], x25519_privfetch[];
-#define X25519_PUBFETCHSZ 3
-#define X25519_PRIVFETCHSZ 6
-
 /*----- Functions provided ------------------------------------------------*/
 
 /* --- @x25519@ --- *
index 0320af3..753ac8d 100644 (file)
-### Tests for X448.
-
-x448 {
-  ## These are taken from RFC7748.
-
-  3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3
-    06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086
-    ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f;
-  203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f
-    0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db
-    884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d;
-
-  9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b
-    0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-    9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0;
-  1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d
-    0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-    3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609;
-  9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b
-    3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609
-    07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d;
-  1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d
-    9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0
-    07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d;
-}
-
-x448-mct {
-  ## These are taken from RFC7748.
-
-  0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-    0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-    1 3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113;
-  0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-    0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-    1000 aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38;
-
-  ## This one takes aaaaages.
-  0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-    0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-    1000000 077f453681caca3693198420bbe515cae0002472519b3e67661a7e89cab94695c8f4bcd66e61b9b9c946da8d524de3d69bd9d9d66b997e37;
-}
+### Test cases for arithmetic mod 2^448 - 2^224 - 1.           -*-conf-*-
+
+###--------------------------------------------------------------------------
+test add
+
+## Some easy ones.
+x ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff
+y 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+z ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff
+
+x fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
+y 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+z fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
+
+x fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
+y 0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+z 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+
+## 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 0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+y 0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+z 0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+
+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 0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+z 0900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+
+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 xdh
+
+## These are taken from RFC7748.
+
+k 3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3
+X 06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086
+Z ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f
+
+k 203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f
+X 0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db
+Z 884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d
+
+
+k 9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b
+X 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Z 9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0
+
+k 1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d
+X 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Z 3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609
+
+k 9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b
+X 3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609
+Z 07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d
+
+k 1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d
+X 9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0
+Z 07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d
+
+###--------------------------------------------------------------------------
+test xdh-mct
+
+## These are taken from RFC7748.
+
+k 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+X 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+n 1
+Z 3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113
+
+k 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+X 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+n 1000
+Z aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38
+
+## This one takes aaaaages.
+##k 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+##X 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+##n 1000000
+##Z 077f453681caca3693198420bbe515cae0002472519b3e67661a7e89cab94695c8f4bcd66e61b9b9c946da8d524de3d69bd9d9d66b997e37
diff --git a/x448.c b/x448.c
index d766e5c..c58335a 100644 (file)
--- a/x448.c
+++ b/x448.c
@@ -1,3 +1,40 @@
+/*
+ * x448.c: Hamburg's X448 key-exchange function
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb, and modified for Secnet (2017-04-30):
+ *
+ *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
+ *
+ *   * Remove the test rig code: a replacement is in a separate source file.
+ *
+ *   * Strip out the key-management definitions.
+ *
+ * The file's original comment headers are preserved below.
+ */
 /* -*-c-*-
  *
  * The X448 key-agreement algorithm
@@ -27,7 +64,7 @@
 
 /*----- Header files ------------------------------------------------------*/
 
-#include <mLib/bits.h>
+#include "fake-mLib-bits.h"
 
 #include "montladder.h"
 #include "fgoldi.h"
@@ -39,24 +76,6 @@ const octet x448_base[56] = { 5, 0, /* ... */ };
 
 #define A0 39081
 
-/*----- Key fetching ------------------------------------------------------*/
-
-const key_fetchdef x448_pubfetch[] = {
-  { "pub",     offsetof(x448_pub, pub),        KENC_BINARY,    0 },
-  { 0,         0,                              0,              0 }
-};
-
-static const key_fetchdef priv[] = {
-  { "priv",    offsetof(x448_priv, priv),      KENC_BINARY,    0 },
-  { 0,         0,                              0,              0 }
-};
-
-const key_fetchdef x448_privfetch[] = {
-  { "pub",     offsetof(x448_priv, pub),       KENC_BINARY,    0 },
-  { "private", 0,                              KENC_STRUCT,    priv },
-  { 0,         0,                              0,              0 }
-};
-
 /*----- Main code ---------------------------------------------------------*/
 
 /* --- @x448@ --- *
diff --git a/x448.h b/x448.h
index f1b0f2c..ae1672f 100644 (file)
--- a/x448.h
+++ b/x448.h
@@ -1,3 +1,38 @@
+/*
+ * x448.h: Hamburg's X448 key-exchange function
+ */
+/*
+ * This file is Free Software.  It has been modified to as part of its
+ * incorporation into secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the permissive licence shown below.
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This program 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
+ * along with this program; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+/*
+ * Imported from Catacomb, and modified for Secnet (2017-04-30):
+ *
+ *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
+ *
+ *   * Strip out the key-management definitions.
+ *
+ * The file's original comment headers are preserved below.
+ */
 /* -*-c-*-
  *
  * The X448 key-agreement algorithm
 
 /*----- Header files ------------------------------------------------------*/
 
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_KEY_H
-#  include "key.h"
-#endif
-
-/*----- Key fetching ------------------------------------------------------*/
-
-typedef struct x448_priv { key_bin priv, pub; } x448_priv;
-typedef struct x448_pub { key_bin pub; } x448_pub;
-
-extern const key_fetchdef x448_pubfetch[], x448_privfetch[];
-#define X448_PUBFETCHSZ 3
-#define X448_PRIVFETCHSZ 6
+#include "fake-mLib-bits.h"
 
 /*----- Important constants -----------------------------------------------*/
 
diff --git a/xdh-test.c b/xdh-test.c
new file mode 100644 (file)
index 0000000..016c8d2
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * xdh-test.c: test harness elliptic-curve Diffie--Hellman
+ *
+ * (The implementations originally came with different test arrangements,
+ * with complicated external dependencies.  This file replicates the original
+ * tests, but without the dependencies.)
+ */
+/*
+ * This file is Free Software.  It was originally written for secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This software 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
+ * along with this software; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "secnet.h"
+
+#include "f25519.h"
+#include "fgoldi.h"
+
+#include "x25519.h"
+#include "x448.h"
+
+#define GLUE(x, y) GLUE_(x, y)
+#define GLUE_(x, y) x##y
+#define FIELDOP(op) GLUE(FIELD, _##op)
+
+#define f25519_FESZ 32u
+#define fgoldi_FESZ 56u
+
+/* Define some global variables we shouldn't need.
+ *
+ * Annoyingly, `secnet.h' declares static pointers and initializes them to
+ * point to some external variables.  At `-O0', GCC doesn't optimize these
+ * away, so there's a link-time dependency on these variables.  Define them
+ * here, so that `f25519.c' and `f448.c' can find them.
+ *
+ * (Later GCC has `-Og', which optimizes without making debugging a
+ * nightmare, but I'm not running that version here.  Note that `serpent.c'
+ * doesn't have this problem because it defines its own word load and store
+ * operations to cope with its endian weirdness, whereas the field arithmetic
+ * uses `unaligned.h' which manages to include `secnet.h'.)
+ */
+uint64_t now_global;
+struct timeval tv_now_global;
+
+union reg {
+    long i;
+    unsigned long u;
+    uint8_t fe[FIELDOP(FESZ)];
+};
+
+struct regty {
+    void (*parse)(union reg *r, char *p);
+    void (*dump)(FILE *fp, const union reg *r);
+    int (*eq)(const union reg *r, const union reg *rr);
+};
+
+struct regdef {
+    const char *name;
+    const struct regty *ty;
+    int r;
+};
+
+struct test {
+    const char *name;
+    void (*fn)(union reg *out, const union reg *in);
+    const struct regdef *regs;
+};
+
+static int lno;
+
+static void bail(const char *msg, ...)
+{
+    va_list ap;
+    va_start(ap, msg);
+    fprintf(stderr, "unexpected error (line %d): ", lno);
+    vfprintf(stderr, msg, ap);
+    va_end(ap);
+    fputc('\n', stderr);
+    exit(3);
+}
+
+static void parse_hex(uint8_t *b, size_t sz, char *p)
+{
+    size_t n = strlen(p);
+    unsigned i;
+    char bb[3];
+
+    if (n%2) bail("bad hex (odd number of nibbles)");
+    else if (n/2 != sz) bail("bad hex (want %zu bytes, found %zu", sz, n/2);
+    while (sz) {
+       for (i = 0; i < 2; i++) {
+           if (!isxdigit((unsigned char)p[i]))
+               bail("bad hex digit `%c'", p[i]);
+           bb[i] = p[i];
+       }
+       bb[2] = 0;
+       p += 2;
+       *b++ = strtoul(bb, 0, 16); sz--;
+    }
+}
+
+static void dump_hex(FILE *fp, const uint8_t *b, size_t sz)
+    { while (sz--) fprintf(fp, "%02x", *b++); fputc('\n', fp); }
+
+static void parse_int(union reg *r, char *p)
+{
+    char *q;
+
+    errno = 0;
+    r->i = strtol(p, &q, 0);
+    if (*q || errno) bail("bad integer `%s'", p);
+}
+
+static void dump_int(FILE *fp, const union reg *r)
+    { fprintf(fp, "%ld\n", r->i); }
+
+static int eq_int(const union reg *r, const union reg *rr)
+    { return (r->i == rr->i); }
+
+static const struct regty regty_int = { parse_int, dump_int, eq_int };
+
+static void parse_uint(union reg *r, char *p)
+{
+    char *q;
+
+    errno = 0;
+    r->u = strtoul(p, &q, 0);
+    if (*q || errno) bail("bad integer `%s'", p);
+}
+
+static void dump_uint(FILE *fp, const union reg *r)
+    { fprintf(fp, "%lu\n", r->u); }
+
+static int eq_uint(const union reg *r, const union reg *rr)
+    { return (r->u == rr->u); }
+
+static const struct regty regty_uint = { parse_uint, dump_uint, eq_uint };
+
+static void parse_fe(union reg *r, char *p)
+    { parse_hex(r->fe, sizeof(r->fe), p); }
+
+static void dump_fe(FILE *fp, const union reg *r)
+    { dump_hex(fp, r->fe, sizeof(r->fe)); }
+
+static int eq_fe(const union reg *r, const union reg *rr)
+    { return (memcmp(r->fe, rr->fe, sizeof(r->fe)) == 0); }
+
+static const struct regty regty_fe = { parse_fe, dump_fe, eq_fe };
+
+enum {
+    RZ, RXX = RZ, RYY, NROUT,
+    RX = NROUT, RY, RA = RY, RK = RY, RM, RN = RM, NREG
+};
+
+#define BINOP(op)                                                      \
+    static void test_##op(union reg *out, const union reg *in)         \
+    {                                                                  \
+       FIELD x, y, z;                                                  \
+                                                                       \
+       FIELDOP(load)(&x, in[RX].fe);                                   \
+       FIELDOP(load)(&y, in[RY].fe);                                   \
+       FIELDOP(op)(&z, &x, &y);                                        \
+       FIELDOP(store)(out[RZ].fe, &z);                                 \
+    }
+
+#define UNOP(op)                                                       \
+    static void test_##op(union reg *out, const union reg *in)         \
+    {                                                                  \
+       FIELD x, z;                                                     \
+                                                                       \
+       FIELDOP(load)(&x, in[RX].fe);                                   \
+       FIELDOP(op)(&z, &x);                                            \
+       FIELDOP(store)(out[RZ].fe, &z);                                 \
+    }
+
+BINOP(add)
+BINOP(sub)
+BINOP(mul)
+UNOP(sqr)
+UNOP(inv)
+
+static void test_mulconst(union reg *out, const union reg *in)
+{
+    FIELD x, z;
+
+    FIELDOP(load)(&x, in[RX].fe);
+    FIELDOP(mulconst)(&z, &x, in[RA].i);
+    FIELDOP(store)(out[RZ].fe, &z);
+}
+
+static void test_condswap(union reg *out, const union reg *in)
+{
+    FIELD x, y;
+
+    FIELDOP(load)(&x, in[RX].fe);
+    FIELDOP(load)(&y, in[RY].fe);
+    FIELDOP(condswap)(&x, &y, in[RM].u);
+    FIELDOP(store)(out[RXX].fe, &x);
+    FIELDOP(store)(out[RYY].fe, &y);
+}
+
+static void test_xdh(union reg *out, const union reg *in)
+    { XDH(out[RZ].fe, in[RK].fe, in[RX].fe); }
+
+static void test_xdhmct(union reg *out, const union reg *in)
+{
+    uint8_t b0[FIELDOP(FESZ)], b1[FIELDOP(FESZ)], *k = b0, *x = b1, *t;
+    unsigned long i, n;
+
+    memcpy(b0, in[RK].fe, sizeof(b0));
+    memcpy(b1, in[RX].fe, sizeof(b1));
+    n = in[RM].u;
+    for (i = 0; i < n; i++) {
+       XDH(x, k, x);
+       t = x; x = k; k = t;
+    }
+    memcpy(out[RZ].fe, k, sizeof(b0));
+}
+
+#define REG_X { "x", &regty_fe, RX }
+#define REG_Y { "y", &regty_fe, RY }
+#define REG_A { "a", &regty_int, RA }
+#define REG_M { "m", &regty_uint, RM }
+#define REG_XX { "xx", &regty_fe, RXX }
+#define REG_YY { "yy", &regty_fe, RYY }
+#define REG_Z { "z", &regty_fe, RZ }
+#define REG_BIGX { "X", &regty_fe, RX }
+#define REG_BIGZ { "Z", &regty_fe, RZ }
+#define REG_K { "k", &regty_fe, RK }
+#define REG_N { "n", &regty_uint, RN }
+#define REGLIST_END { 0 }
+static const struct regdef
+    unop_regs[] = { REG_X, REG_Z, REGLIST_END },
+    binop_regs[] = { REG_X, REG_Y, REG_Z, REGLIST_END },
+    mulconst_regs[] = { REG_X, REG_A, REG_Z, REGLIST_END },
+    condswap_regs[] = { REG_X, REG_Y, REG_M, REG_XX, REG_YY, REGLIST_END },
+    xdh_regs[] = { REG_K, REG_BIGX, REG_BIGZ, REGLIST_END },
+    xdhmct_regs[] = { REG_K, REG_BIGX, REG_N, REG_BIGZ, REGLIST_END };
+
+static const struct test tests[] = {
+    { "add", test_add, binop_regs },
+    { "sub", test_sub, binop_regs },
+    { "condswap", test_condswap, condswap_regs },
+    { "mulconst", test_mulconst, mulconst_regs },
+    { "mul", test_mul, binop_regs },
+    { "sqr", test_sqr, unop_regs },
+    { "inv", test_inv, unop_regs },
+    { "xdh", test_xdh, xdh_regs },
+    { "xdh-mct", test_xdhmct, xdhmct_regs },
+    { 0 }
+};
+
+static int check(const struct test *test, unsigned iat,
+                 union reg *out, const union reg *in)
+{
+    const struct regdef *rdef;
+    int ok = 1;
+
+    if (!iat) return (0);
+    assert(test);
+    for (rdef = test->regs; rdef->name; rdef++)
+       if (!(iat & (1 << rdef->r)))
+           bail("register `%s' not set", rdef->name);
+    test->fn(out, in);
+    for (rdef = test->regs; rdef->name; rdef++) {
+       if (rdef->r >= NROUT) continue;
+       if (!rdef->ty->eq(&in[rdef->r], &out[rdef->r])) ok = 0;
+    }
+    if (ok) return (0);
+
+    fprintf(stderr, "failed `%s'\n", test->name);
+    for (rdef = test->regs; rdef->name; rdef++) {
+       if (rdef->r >= NROUT) {
+           fprintf(stderr, "\tinput `%s' = ", rdef->name);
+           rdef->ty->dump(stderr, &in[rdef->r]);
+       } else {
+           fprintf(stderr, "\texpected `%s' = ", rdef->name);
+           rdef->ty->dump(stderr, &in[rdef->r]);
+           fprintf(stderr, "\tcomputed `%s' = ", rdef->name);
+           rdef->ty->dump(stderr, &out[rdef->r]);
+       }
+    }
+    return (-1);
+}
+
+int main(void)
+{
+    char linebuf[256];
+    char *p;
+    const char *q;
+    size_t n;
+    unsigned iat = 0, rbit;
+    const struct test *test = 0;
+    union reg in[NREG], out[NROUT];
+    const struct regdef *rdef;
+    int rc = 0;
+
+    lno = 0;
+    while (fgets(linebuf, sizeof(linebuf), stdin)) {
+       lno++;
+       n = strlen(linebuf); assert(n);
+       if (linebuf[n - 1] != '\n') bail("line too long");
+       linebuf[n - 1] = 0;
+       p = linebuf;
+       while (isspace((unsigned char)*p)) p++;
+       if (*p == '#') continue;
+       if (!*p) {
+           if (check(test, iat, out, in)) rc = 2;
+           iat = 0;
+           continue;
+       }
+       q = p;
+       while (*p && !isspace((unsigned char)*p)) p++;
+       if (!*p) bail("missing argument");
+       *p++ = 0;
+       while (isspace((unsigned char)*p)) p++;
+       if (strcmp(q, "test") == 0) {
+           if (check(test, iat, out, in)) rc = 2;
+           iat = 0;
+           for (test = tests; test->name; test++)
+               if (strcmp(p, test->name) == 0) goto found_test;
+           bail("unknown test `%s'", p);
+       found_test:
+           continue;
+       }
+       if (!test) bail("no test defined yet");
+       for (rdef = test->regs; rdef->name; rdef++)
+           if (strcmp(q, rdef->name) == 0) goto found_reg;
+       bail("unknown register `%s'", q);
+    found_reg:
+       rbit = 1 << rdef->r;
+       if (iat & rbit)
+           bail("register `%s' already set", rdef->name);
+       rdef->ty->parse(&in[rdef->r], p);
+       iat |= rbit;
+    }
+    if (check(test, iat, out, in)) rc = 2;
+    return (rc);
+}